diff --git a/src/convert.js b/src/convert.js index e54a466..ceb978a 100644 --- a/src/convert.js +++ b/src/convert.js @@ -134,6 +134,28 @@ function numToVarInt(num) { return [255].concat(numToBytes(num, 8)); } +/** + * Turn an VarInt into an integer + * + * "var_int" is a variable length integer used by Bitcoin's binary format. + * + * Returns { bytes: bytesUsed, number: theNumber } + */ +function varIntToNum(bytes) { + var prefix = bytes[0] + + var viBytes = + prefix < 253 ? bytes.slice(0, 1) + : prefix === 253 ? bytes.slice(1, 3) + : prefix === 254 ? bytes.slice(1, 5) + : bytes.slice(1, 9) + + return { + bytes: prefix < 253 ? viBytes : bytes.slice(0, viBytes.length + 1), + number: bytesToNum(viBytes) + } +} + function bytesToWords(bytes) { var words = []; for (var i = 0, b = 0; i < bytes.length; i++, b += 8) { @@ -176,6 +198,7 @@ module.exports = { numToBytes: numToBytes, bytesToNum: bytesToNum, numToVarInt: numToVarInt, + varIntToNum: varIntToNum, bytesToWords: bytesToWords, wordsToBytes: wordsToBytes, bytesToWordArray: bytesToWordArray, diff --git a/test/convert.js b/test/convert.js index 4727692..3fb03b1 100644 --- a/test/convert.js +++ b/test/convert.js @@ -94,6 +94,45 @@ describe('convert', function() { }) }) + describe('varIntToNum', function() { + it('works on valid input', function() { + var data = [ + [0], [128], [252], // 8-bit + [253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit + [254, 5, 0, 1, 0], // 32-bit + [255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit + ] + var expected = [ + 0, 128, 252, // 8-bit + 256, 512, 1024, // 16-bit + 65541, // 32-bit + 4294967299, // 64-bit + ] + + for (var i = 0; i < data.length; ++i) { + var actual = convert.varIntToNum(data[i]) + assert.equal(actual.number, expected[i]) + assert.deepEqual(actual.bytes, data[i]) + } + }) + + it('uses only what is necessary', function() { + var data = [ + [0, 99], + [253, 0, 1, 99], + [254, 5, 0, 1, 0, 99], + [255, 3, 0, 0, 0, 1, 0, 0, 0, 99] + ] + var expected = [0, 256, 65541, 4294967299] + + for (var i = 0; i < data.length; ++i) { + var actual = convert.varIntToNum(data[i]) + assert.equal(actual.number, expected[i]) + assert.deepEqual(actual.bytes, data[i].slice(0, -1)) + } + }) + }) + describe('reverseEndian', function() { it('works', function() { var bigEndian = "6a4062273ac4f9ea4ffca52d9fd102b08f6c32faa0a4d1318e3a7b2e437bb9c7"