diff --git a/lib/index.js b/lib/index.js index cc8d154..52e446e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -5,16 +5,6 @@ "use strict"; -/** - * `uint64_t` implementation used to represent such numbers in - * JavaScript. Default is - * [int64-native](https://www.npmjs.com/package/int64-native) for Node - * platform and [node-int64](https://www.npmjs.com/package/node-int64) - * for Browser. You may replace it with other library with the same API. - */ -// TODO(Kagami): Find another JS implementation, it should be able to -// operate with `uint64_t` not just store it. -exports.Int64 = require("int64-native"); /** Working with addresses. */ exports.Address = require("./address"); /** Working with WIF. */ diff --git a/lib/struct.js b/lib/struct.js index 84a71d0..70da705 100644 --- a/lib/struct.js +++ b/lib/struct.js @@ -7,7 +7,6 @@ "use strict"; var assert = require("assert"); -var bitmessage = require("./"); /** * var_int. @@ -17,7 +16,7 @@ var var_int = exports.var_int = { /** * Decode var_int. * @param {Buffer} buf - Buffer that starts with encoded var_int - * @return {{value: (number|Int64), length: number, rest: Buffer}} + * @return {{value: number, length: number, rest: Buffer}} * Decoded var_int structure. */ decode: function(buf) { @@ -35,12 +34,21 @@ var var_int = exports.var_int = { length = 5; break; case 255: - // TODO(Kagami): Should we still use native number if value is - // less than 2^53? var hi = buf.readUInt32BE(1); assert(hi !== 0, "Impractical var_int"); + // Max safe number = 2^53 - 1 = + // 0b0000000000011111111111111111111111111111111111111111111111111111 + // = 2097151*(2^32) + (2^32 - 1) + // So it's safe until hi <= 2097151. See + // , + // for details. + // TODO(Kagami): We may want to return raw Buffer for + // 2^53 <= value <= 2^64 - 1 range. Possible using the optional + // argument because most of the code expect to get number from + // `var_int.decode`. + assert(hi <= 2097151, "Unsafe integer"); var lo = buf.readUInt32BE(5); - value = new bitmessage.Int64(hi, lo); + value = hi * 4294967296 + lo; length = 9; break; default: @@ -53,11 +61,11 @@ var var_int = exports.var_int = { /** * Encode number into var_int. - * @param {(number|Int64|Buffer)} value - Input number + * @param {(number|Buffer)} value - Input number * @return {Buffer} Encoded var_int. */ encode: function(value) { - var buf, buf64, targetStart; + var buf, targetStart; if (typeof value === "number") { assert(value >= 0, "Value cannot be less than zero"); if (value < 253) { @@ -71,38 +79,21 @@ var var_int = exports.var_int = { buf[0] = 254; buf.writeUInt32BE(value, 1); } else { - // Value may be inaccurate (max safe int = 2^53) but we will still - // try to convert it. + assert(value <= 9007199254740991, "Unsafe integer"); buf = new Buffer(9); buf[0] = 255; buf.writeUInt32BE(Math.floor(value / 4294967296), 1); // high32 buf.writeUInt32BE(value % 4294967296, 5); // low32 } + } else if (Buffer.isBuffer(value)) { + assert(value.length <= 8, "Buffer too big"); + buf = new Buffer(9); + buf.fill(0); + buf[0] = 255; + targetStart = 1 + (8 - value.length); + value.copy(buf, targetStart); } else { - if (value.high32 && value.low32) { - // int64-native instance. - buf = new Buffer(9); - buf[0] = 255; - buf.writeUInt32BE(value.high32(), 1); - buf.writeUInt32BE(value.low32(), 5); - } else { - // Try to convert to buffer. - if (Buffer.isBuffer(value)) { - buf64 = value; - } else if (value.toBuffer) { - // node-int64 instance, rawBuffer = true (prevents extra buffer - // allocation since we copy it's value to new buffer anyway). - buf64 = value.toBuffer(true); - } else { - throw new Error("Value encode error"); - } - assert(buf64.length <= 8, "Buffer too big"); - buf = new Buffer(9); - buf.fill(0); - buf[0] = 255; - targetStart = 1 + (8 - buf64.length); - buf64.copy(buf, targetStart); - } + throw new Error("Value encode error"); } return buf; }, @@ -122,8 +113,6 @@ exports.var_str = { decode: function(buf) { var decoded = var_int.decode(buf); var strLength = decoded.value; - // FIXME(Kagami): We will fail here if var_int value is bigger than - // 2^32. Though it will require ~4G of RAM so it's not that bad. // XXX(Kagami): Spec doesn't mention encoding, using UTF-8. var str = decoded.rest.slice(0, strLength).toString(); var rest = decoded.rest.slice(strLength); @@ -156,9 +145,6 @@ exports.var_int_list = { decode: function(buf) { var decoded = var_int.decode(buf); var listLength = decoded.value; - // FIXME(Kagami): We will fail here if var_int value is bigger than - // 2^32. Though such list would require more than 4G of RAM so it's - // not that bad. var list = new Array(listLength); var rest = decoded.rest; var sumLength = decoded.length; diff --git a/package.json b/package.json index d7e7f1e..dafc693 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "description": "JavaScript Bitmessage library", "main": "./lib/index.js", "browser": { - "int64-native": "node-int64", "./lib/crypto-platform.js": "./lib/crypto-platform.browser.js" }, "scripts": { @@ -50,8 +49,6 @@ "buffer-equal": "~0.0.1", "eccrypto": "^0.1.1", "es6-promise": "^2.0.1", - "int64-native": "^0.3.2", - "node-int64": "^0.3.2", "object.assign": "^1.1.1", "ripemd160": "^0.2.0" } diff --git a/test.js b/test.js index 9ef5ab6..9c1716a 100644 --- a/test.js +++ b/test.js @@ -4,7 +4,6 @@ var allTests = typeof window === "undefined" ? window.ALL_TESTS; var bitmessage = require("./lib"); -var Int64 = bitmessage.Int64; var Address = bitmessage.Address; var wif = bitmessage.wif; var var_int = bitmessage.struct.var_int; @@ -18,6 +17,7 @@ describe("Core structures", function() { var res; expect(var_int.decode.bind(null, Buffer([]))).to.throw(Error); expect(var_int.decode.bind(null, Buffer("fd00", "hex"))).to.throw(Error); + expect(var_int.decode.bind(null, Buffer("ff004170706e9b0368", "hex"))).to.throw(Error); res = var_int.decode(Buffer([123])); expect(res.value).to.equal(123); @@ -35,7 +35,7 @@ describe("Core structures", function() { expect(res.rest.toString("hex")).to.equal("90"); res = var_int.decode(Buffer("ff0000001234567890", "hex")); - expect(res.value == 0x1234567890).to.be.true; + expect(res.value).to.equal(0x1234567890); expect(res.length).to.equal(9); expect(res.rest.length).to.equal(0); }); @@ -51,9 +51,9 @@ describe("Core structures", function() { expect(var_int.encode(0x1234).toString("hex")).to.equal("fd1234"); expect(var_int.encode(0x12345678).toString("hex")).to.equal("fe12345678"); expect(var_int.encode(0x1234567890).toString("hex")).to.equal("ff0000001234567890"); - expect(var_int.encode(new Int64("0xffffffffffffffff")).toString("hex")).to.equal("ffffffffffffffffff"); expect(var_int.encode(Buffer("1234567890", "hex")).toString("hex")).to.equal("ff0000001234567890"); expect(var_int.encode.bind(null, -123)).to.throw(Error); + expect(var_int.encode.bind(null, 0x4170706e9b0368)).to.throw(Error); expect(var_int.encode.bind(null, Buffer("123456789012345678", "hex"))).to.throw(Error); expect(var_int.encode.bind(null, "test")).to.throw(Error); });