Skip to content

Commit 6077859

Browse files
committed
ref: make VarInt code readable again
1 parent edd1b41 commit 6077859

File tree

1 file changed

+57
-44
lines changed

1 file changed

+57
-44
lines changed

dashgov.js

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
/**
1010
* @typedef Estimate
11-
* @prop {Uint53} secondsPerBlock
1211
* @prop {Uint53} voteHeight
1312
* @prop {Uint53} voteDelta
1413
* @prop {String} voteIso - date in ISO format
@@ -40,6 +39,13 @@ var DashGov = ("object" === typeof module && exports) || {};
4039
// USAGE
4140
// node ./gobject-hash-debugger.js
4241

42+
const LITTLE_ENDIAN = true;
43+
const VARINT_8_MAX = 252;
44+
const UINT_16_MAX = 65535;
45+
const UINT_32_MAX = 4294967295;
46+
47+
let textEncoder = new TextEncoder();
48+
4349
GObj._type = 0b0000010; // from SER_GETHASH (bitwise enum)
4450
GObj._typeBytes = Uint8Array.from([0b0000010]);
4551
GObj._protocalVersion = 70231; // 0x00011257 (BE) => 0x57120100 (LE)
@@ -71,37 +77,47 @@ var DashGov = ("object" === typeof module && exports) || {};
7177
* @param {number} nSize
7278
*/
7379
GObj.utils.toVarIntSize = function (nSize) {
74-
return nSize < 253
75-
? 0
76-
: nSize <= 2 ** 16 - 1
77-
? 2
78-
: nSize <= 2 ** 32 - 1
79-
? 4
80-
: 8;
80+
if (nSize <= VARINT_8_MAX) {
81+
return 1;
82+
}
83+
84+
if (nSize <= UINT_16_MAX) {
85+
return 3;
86+
}
87+
88+
if (nSize <= UINT_32_MAX) {
89+
return 5;
90+
}
91+
92+
return 9;
8193
};
8294

8395
/**
84-
* Writes `nSize` out to `dv` in a variable-length encoding.
96+
* Writes `n` out to `dv` in a variable-length encoding.
8597
* Assumes you want to write out the data of `nSize` length to `dv` afterwards.
8698
* @param {DataView} dv
87-
* @param {number} offset
88-
* @param {number} nSize
99+
* @param {Number} offset
100+
* @param {Number} n
89101
*/
90-
function WriteCompactSize(
91-
dv,
92-
offset,
93-
nSize,
94-
s = GObj.utils.toVarIntSize(nSize),
95-
) {
96-
switch (s) {
97-
case 2:
98-
case 4:
99-
case 8:
100-
dv.setBigUint64(offset + 1, BigInt(nSize), true);
101-
nSize = 252 + Math.log2(s);
102-
default:
103-
dv.setUint8(offset, nSize);
102+
function writeVarInt(dv, offset, n) {
103+
if (n <= VARINT_8_MAX) {
104+
dv.setUint8(offset, n);
105+
return;
106+
}
107+
108+
let size;
109+
if (n <= UINT_16_MAX) {
110+
size = 253;
111+
} else if (n <= UINT_32_MAX) {
112+
size = 254;
113+
} else {
114+
size = 255;
104115
}
116+
dv.setUint8(offset, size);
117+
118+
offset += 1;
119+
let bigN = BigInt(n);
120+
dv.setBigUint64(offset, bigN, LITTLE_ENDIAN);
105121
}
106122

107123
/**
@@ -131,7 +147,6 @@ var DashGov = ("object" === typeof module && exports) || {};
131147
* @prop {BigInt|Uint53} time - seconds since epoch (8 bytes)
132148
* @prop {String} hexJson - variable
133149
* @prop {null} [masternodeOutpoint] - ??
134-
* @prop {null} [collateralTxOutputIndex] - 4 bytes of 0xffs
135150
* @prop {null} [collateralTxId] - 32 bytes of 0x00s
136151
* @prop {null} [collateralTxOutputIndex] - 4 bytes of 0xffs
137152
* @prop {null} [signature] - 0 bytes
@@ -147,14 +162,13 @@ var DashGov = ("object" === typeof module && exports) || {};
147162
time,
148163
hexJson,
149164
}) {
150-
const compactSizeExtraOffset = GObj.utils.toVarIntSize(hexJson.length);
165+
const varIntSize = GObj.utils.toVarIntSize(hexJson.length);
151166

152167
const dataLen =
153168
32 + // hashParent
154169
4 + // revision
155170
8 + // time
156-
1 +
157-
compactSizeExtraOffset + // compacted length header for HexStr(vchData)
171+
varIntSize + // compacted length header for HexStr(vchData)
158172
hexJson.length + // HexStr(vchData)
159173
32 +
160174
4 + // masterNodeOutpoint (not used, so these bytes are the defaults)
@@ -172,39 +186,37 @@ var DashGov = ("object" === typeof module && exports) || {};
172186
}
173187
offset += 32;
174188

175-
dv.setInt32(offset, revision, true);
189+
dv.setInt32(offset, revision, LITTLE_ENDIAN);
176190
offset += 4;
177191

178-
dv.setBigInt64(offset, BigInt(time), true);
192+
let bigTime = BigInt(time);
193+
dv.setBigInt64(offset, bigTime, LITTLE_ENDIAN);
179194
offset += 8;
180195

181-
// Write out hexJson, with a compacted size in front
182-
WriteCompactSize(dv, offset, hexJson.length, compactSizeExtraOffset);
183-
offset += 1 + compactSizeExtraOffset;
184-
bytes.set(new TextEncoder().encode(hexJson), offset);
196+
void writeVarInt(dv, offset, hexJson.length);
197+
offset += varIntSize;
198+
let hexJsonBytes = textEncoder.encode(hexJson);
199+
bytes.set(hexJsonBytes, offset);
185200
offset += hexJson.length;
186201

187202
{
188-
// masternodeOutpoint exists in the C++ object and needs to be included,
189-
// however, it is not filled with data for our purposes.
190-
191-
// Write out empty masternodeHash
203+
// masternodeOutpointId (hash + index) is required for legacy reasons,
204+
// but not used for collateral serialization
192205
offset += 32;
193206

194207
// Write out default mastNode `n` (index)
195208
let masternodeOutpointIndex = 0xffffffff;
196-
dv.setUint32(offset, masternodeOutpointIndex, true);
209+
dv.setUint32(offset, masternodeOutpointIndex, LITTLE_ENDIAN);
197210
offset += 4;
198211

199212
// adding dummy values here to match old hashing
200213
offset += 1;
201-
dv.setUint32(offset, 0xffffffff, true);
214+
dv.setUint32(offset, 0xffffffff, LITTLE_ENDIAN);
202215
offset += 4;
203216
}
204217

205-
// In the C++ version, `vchSig` must have its length written out in `WriteCompactSize` fashion.
206-
// Then, if the length is greater than 0, `vchSig` is written out too.
207-
// However, we never need a signature here, so we just write out a `0`.
218+
// the trailing 0 byte represents the VarInt Size of the vchSig,
219+
// which is always 0 for collateral serialization
208220
offset += 1;
209221
return bytes;
210222
};
@@ -403,6 +415,7 @@ if ("object" === typeof module) {
403415
module.exports = DashGov;
404416
}
405417

418+
/** @typedef {bigint} BigInt */
406419
/** @typedef {Number} Uint8 */
407420
/** @typedef {Number} Uint32 */
408421
/** @typedef {Number} Uint53 */

0 commit comments

Comments
 (0)