UNPKG

3.07 kBJavaScriptView Raw
1var opcodes = require('./opcodes.json')
2var varuint = require('varuint-bitcoin')
3
4function pushDataSize (i) {
5 return i < opcodes.OP_PUSHDATA1 ? 1
6 : i <= 0xff ? 2
7 : i <= 0xffff ? 3
8 : 5
9}
10
11function readPushDataInt (buffer, offset) {
12 var opcode = buffer.readUInt8(offset)
13 var number, size
14
15 // ~6 bit
16 if (opcode < opcodes.OP_PUSHDATA1) {
17 number = opcode
18 size = 1
19
20 // 8 bit
21 } else if (opcode === opcodes.OP_PUSHDATA1) {
22 if (offset + 2 > buffer.length) return null
23 number = buffer.readUInt8(offset + 1)
24 size = 2
25
26 // 16 bit
27 } else if (opcode === opcodes.OP_PUSHDATA2) {
28 if (offset + 3 > buffer.length) return null
29 number = buffer.readUInt16LE(offset + 1)
30 size = 3
31
32 // 32 bit
33 } else {
34 if (offset + 5 > buffer.length) return null
35 if (opcode !== opcodes.OP_PUSHDATA4) throw new Error('Unexpected opcode')
36
37 number = buffer.readUInt32LE(offset + 1)
38 size = 5
39 }
40
41 return {
42 opcode: opcode,
43 number: number,
44 size: size
45 }
46}
47
48// https://github.com/feross/buffer/blob/master/index.js#L1127
49function verifuint (value, max) {
50 if (typeof value !== 'number') throw new Error('cannot write a non-number as a number')
51 if (value < 0) throw new Error('specified a negative value for writing an unsigned value')
52 if (value > max) throw new Error('RangeError: value out of range')
53 if (Math.floor(value) !== value) throw new Error('value has a fractional component')
54}
55
56function readUInt64LE (buffer, offset) {
57 var a = buffer.readUInt32LE(offset)
58 var b = buffer.readUInt32LE(offset + 4)
59 b *= 0x100000000
60
61 verifuint(b + a, 0x001fffffffffffff)
62
63 return b + a
64}
65
66function writePushDataInt (buffer, number, offset) {
67 var size = pushDataSize(number)
68
69 // ~6 bit
70 if (size === 1) {
71 buffer.writeUInt8(number, offset)
72
73 // 8 bit
74 } else if (size === 2) {
75 buffer.writeUInt8(opcodes.OP_PUSHDATA1, offset)
76 buffer.writeUInt8(number, offset + 1)
77
78 // 16 bit
79 } else if (size === 3) {
80 buffer.writeUInt8(opcodes.OP_PUSHDATA2, offset)
81 buffer.writeUInt16LE(number, offset + 1)
82
83 // 32 bit
84 } else {
85 buffer.writeUInt8(opcodes.OP_PUSHDATA4, offset)
86 buffer.writeUInt32LE(number, offset + 1)
87 }
88
89 return size
90}
91
92function writeUInt64LE (buffer, value, offset) {
93 verifuint(value, 0x001fffffffffffff)
94
95 buffer.writeInt32LE(value & -1, offset)
96 buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4)
97 return offset + 8
98}
99
100// TODO: remove in 4.0.0?
101function readVarInt (buffer, offset) {
102 var result = varuint.decode(buffer, offset)
103
104 return {
105 number: result,
106 size: varuint.decode.bytes
107 }
108}
109
110// TODO: remove in 4.0.0?
111function writeVarInt (buffer, number, offset) {
112 varuint.encode(number, buffer, offset)
113 return varuint.encode.bytes
114}
115
116module.exports = {
117 pushDataSize: pushDataSize,
118 readPushDataInt: readPushDataInt,
119 readUInt64LE: readUInt64LE,
120 readVarInt: readVarInt,
121 varIntBuffer: varuint.encode,
122 varIntSize: varuint.encodingLength,
123 writePushDataInt: writePushDataInt,
124 writeUInt64LE: writeUInt64LE,
125 writeVarInt: writeVarInt
126}