Skip to content
This repository was archived by the owner on Jan 25, 2024. It is now read-only.

Commit fe8d6c6

Browse files
refactor(bufferutils): backport BufferReader
The upstream PR that introduced BufferWriter has had some significant changes: bitcoinjs/bitcoinjs-lib#1533 In particular, we now also have BufferReader. Also we can and should use both classes in many more places. Subclass BufferReader with `ZcashBufferReader` and implement `readInt64()` there. Replace fixtures for `readInt64()` with `test/forks/zcash/bufferutils.js`. Issue: BG-16466
1 parent cb79b8d commit fe8d6c6

File tree

9 files changed

+683
-461
lines changed

9 files changed

+683
-461
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"scripts": {
2020
"coverage-report": "nyc report --reporter=lcov",
2121
"coverage-html": "nyc report --reporter=html",
22-
"coverage": "BITGO_UTXO_LIB_TEST_EXPECTED_COUNT=3436 nyc --check-coverage --branches 90 --functions 90 mocha --recursive",
22+
"coverage": "BITGO_UTXO_LIB_TEST_EXPECTED_COUNT=3442 nyc --check-coverage --branches 90 --functions 90 mocha --recursive",
2323
"integration": "mocha test/integration/",
2424
"standard": "standard",
2525
"test": "npm run standard && npm run coverage",

src/buffer_writer.js

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/bufferutils.js

Lines changed: 135 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,141 @@
1+
/* eslint-disable */
2+
const types = require('./types');
3+
const typeforce = require('typeforce');
4+
const varuint = require('varuint-bitcoin');
15
// https://github.com/feross/buffer/blob/master/index.js#L1127
2-
function verifuint (value, max) {
3-
if (typeof value !== 'number') throw new Error('cannot write a non-number as a number')
4-
if (value < 0) throw new Error('specified a negative value for writing an unsigned value')
5-
if (value > max) throw new Error('RangeError: value out of range')
6-
if (Math.floor(value) !== value) throw new Error('value has a fractional component')
6+
function verifuint(value, max) {
7+
if (typeof value !== 'number')
8+
throw new Error('cannot write a non-number as a number');
9+
if (value < 0)
10+
throw new Error('specified a negative value for writing an unsigned value');
11+
if (value > max)
12+
throw new Error('RangeError: value out of range');
13+
if (Math.floor(value) !== value)
14+
throw new Error('value has a fractional component');
715
}
8-
9-
function readUInt64LE (buffer, offset) {
10-
var a = buffer.readUInt32LE(offset)
11-
var b = buffer.readUInt32LE(offset + 4)
12-
b *= 0x100000000
13-
14-
verifuint(b + a, 0x001fffffffffffff)
15-
16-
return b + a
16+
function readUInt64LE(buffer, offset) {
17+
const a = buffer.readUInt32LE(offset);
18+
let b = buffer.readUInt32LE(offset + 4);
19+
b *= 0x100000000;
20+
verifuint(b + a, 0x001fffffffffffff);
21+
return b + a;
1722
}
18-
19-
function readInt64LE (buffer, offset) {
20-
var a = buffer.readUInt32LE(offset)
21-
var b = buffer.readInt32LE(offset + 4)
22-
b *= 0x100000000
23-
24-
return b + a
23+
function writeUInt64LE(buffer, value, offset) {
24+
verifuint(value, 0x001fffffffffffff);
25+
buffer.writeInt32LE(value & -1, offset);
26+
buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4);
27+
return offset + 8;
2528
}
26-
27-
function writeUInt64LE (buffer, value, offset) {
28-
verifuint(value, 0x001fffffffffffff)
29-
30-
buffer.writeInt32LE(value & -1, offset)
31-
buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4)
32-
return offset + 8
29+
function reverseBuffer(buffer) {
30+
if (buffer.length < 1)
31+
return buffer;
32+
let j = buffer.length - 1;
33+
let tmp = 0;
34+
for (let i = 0; i < buffer.length / 2; i++) {
35+
tmp = buffer[i];
36+
buffer[i] = buffer[j];
37+
buffer[j] = tmp;
38+
j--;
39+
}
40+
return buffer;
3341
}
34-
35-
module.exports = {
36-
readUInt64LE: readUInt64LE,
37-
readInt64LE: readInt64LE,
38-
writeUInt64LE: writeUInt64LE
42+
/**
43+
* Helper class for serialization of bitcoin data types into a pre-allocated buffer.
44+
*/
45+
class BufferWriter {
46+
constructor(buffer, offset = 0) {
47+
this.buffer = buffer;
48+
this.offset = offset;
49+
typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
50+
}
51+
writeUInt8(i) {
52+
this.offset = this.buffer.writeUInt8(i, this.offset);
53+
}
54+
writeInt32(i) {
55+
this.offset = this.buffer.writeInt32LE(i, this.offset);
56+
}
57+
writeUInt32(i) {
58+
this.offset = this.buffer.writeUInt32LE(i, this.offset);
59+
}
60+
writeUInt64(i) {
61+
this.offset = writeUInt64LE(this.buffer, i, this.offset);
62+
}
63+
writeVarInt(i) {
64+
varuint.encode(i, this.buffer, this.offset);
65+
this.offset += varuint.encode.bytes;
66+
}
67+
writeSlice(slice) {
68+
if (this.buffer.length < this.offset + slice.length) {
69+
throw new Error('Cannot write slice out of bounds');
70+
}
71+
this.offset += slice.copy(this.buffer, this.offset);
72+
}
73+
writeVarSlice(slice) {
74+
this.writeVarInt(slice.length);
75+
this.writeSlice(slice);
76+
}
77+
writeVector(vector) {
78+
this.writeVarInt(vector.length);
79+
vector.forEach((buf) => this.writeVarSlice(buf));
80+
}
81+
}
82+
/**
83+
* Helper class for reading of bitcoin data types from a buffer.
84+
*/
85+
class BufferReader {
86+
constructor(buffer, offset = 0) {
87+
this.buffer = buffer;
88+
this.offset = offset;
89+
typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
90+
}
91+
readUInt8() {
92+
const result = this.buffer.readUInt8(this.offset);
93+
this.offset++;
94+
return result;
95+
}
96+
readInt32() {
97+
const result = this.buffer.readInt32LE(this.offset);
98+
this.offset += 4;
99+
return result;
100+
}
101+
readUInt32() {
102+
const result = this.buffer.readUInt32LE(this.offset);
103+
this.offset += 4;
104+
return result;
105+
}
106+
readUInt64() {
107+
const result = readUInt64LE(this.buffer, this.offset);
108+
this.offset += 8;
109+
return result;
110+
}
111+
readVarInt() {
112+
const vi = varuint.decode(this.buffer, this.offset);
113+
this.offset += varuint.decode.bytes;
114+
return vi;
115+
}
116+
readSlice(n) {
117+
if (this.buffer.length < this.offset + n) {
118+
throw new Error('Cannot read slice out of bounds');
119+
}
120+
const result = this.buffer.slice(this.offset, this.offset + n);
121+
this.offset += n;
122+
return result;
123+
}
124+
readVarSlice() {
125+
return this.readSlice(this.readVarInt());
126+
}
127+
readVector() {
128+
const count = this.readVarInt();
129+
const vector = [];
130+
for (let i = 0; i < count; i++)
131+
vector.push(this.readVarSlice());
132+
return vector;
133+
}
39134
}
135+
module.exports = {
136+
readUInt64LE,
137+
writeUInt64LE,
138+
reverseBuffer,
139+
BufferWriter,
140+
BufferReader,
141+
};

src/forks/zcash/bufferutils.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { BufferReader } = require('../../bufferutils')
2+
3+
class ZcashBufferReader extends BufferReader {
4+
readInt64 () {
5+
const a = this.buffer.readUInt32LE(this.offset)
6+
let b = this.buffer.readInt32LE(this.offset + 4)
7+
b *= 0x100000000
8+
this.offset += 8
9+
return b + a
10+
}
11+
}
12+
13+
module.exports = { ZcashBufferReader }

0 commit comments

Comments
 (0)