Implement var_int_list

This commit is contained in:
Kagami Hiiragi 2015-01-02 17:27:03 +03:00
parent 1b950bb872
commit a3c4ebac7d
4 changed files with 89 additions and 20 deletions

View File

@ -35,23 +35,11 @@ With the help of browserify `bitmessage` provides different implementations for
- [ ] HMAC-SHA-256
- [ ] Core structures
- [x] var_int
- [x] encode
- [x] decode
- [ ] var_str
- [ ] encode
- [ ] decode
- [ ] var_int_list
- [ ] encode
- [ ] decode
- [x] var_str
- [x] var_int_list
- [ ] inv_vect
- [ ] encode
- [ ] decode
- [ ] net_addr
- [ ] encode
- [ ] decode
- [ ] bitfield
- [ ] encode
- [ ] decode
- [ ] High-level objects
- [ ] Address
- [x] encode
@ -63,8 +51,7 @@ With the help of browserify `bitmessage` provides different implementations for
- [ ] encode
- [ ] decode
- [x] WIF
- [x] encode
- [x] decode
- [ ] POW
- [ ] Parse PyBitmessage configs
- [ ] decode keys.dat
- [ ] decode knownnodes.dat

View File

@ -12,6 +12,8 @@
* 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");

View File

@ -35,6 +35,8 @@ 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");
var lo = buf.readUInt32BE(5);
@ -120,6 +122,8 @@ 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);
@ -137,3 +141,43 @@ exports.var_str = {
return Buffer.concat([var_int.encode(strBuf.length), strBuf]);
},
};
/**
* var_int_list.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#Variable_length_list_of_integers}
*/
exports.var_int_list = {
/**
* Decode var_int_list.
* @param {Buffer} buf - Buffer that starts with encoded var_int_list
* @return {{list: number[], length: number, rest: Buffer}}
* Decoded var_int_list structure.
*/
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;
for (var i = 0; i < listLength; i++) {
decoded = var_int.decode(rest);
list[i] = decoded.value;
rest = decoded.rest;
sumLength += decoded.length;
}
return {list: list, length: sumLength, rest: rest}
},
/**
* Encode list of numbers into var_int_list.
* @param {number[]} list - A number list
* @return {Buffer} Encoded var_int_list.
*/
encode: function(list) {
var listBuf = Buffer.concat(list.map(var_int.encode));
return Buffer.concat([var_int.encode(list.length), listBuf]);
},
};

44
test.js
View File

@ -9,6 +9,7 @@ var Address = bitmessage.Address;
var wif = bitmessage.wif;
var var_int = bitmessage.struct.var_int;
var var_str = bitmessage.struct.var_str;
var var_int_list = bitmessage.struct.var_int_list;
var bmcrypto = require("./lib/crypto");
describe("Core structures", function() {
@ -61,15 +62,20 @@ describe("Core structures", function() {
describe("var_str", function() {
it("should decode", function() {
var res;
res = var_str.decode(Buffer("00", "hex"));
expect(res.str).to.equal("");
expect(res.length).to.equal(1);
expect(res.rest.toString("hex")).to.equal("");
res = var_str.decode(Buffer("0474657374", "hex"));
expect(res.str).to.equal("test");
expect(res.length).to.equal(5);
expect(res.rest.toString("hex")).to.equal("");
res = var_str.decode(Buffer("00", "hex"));
expect(res.str).to.equal("");
expect(res.length).to.equal(1);
expect(res.rest.toString("hex")).to.equal("");
res = var_str.decode(Buffer("0474657374ffffff", "hex"));
expect(res.str).to.equal("test");
expect(res.length).to.equal(5);
expect(res.rest.toString("hex")).to.equal("ffffff");
});
it("should encode", function() {
@ -77,6 +83,36 @@ describe("Core structures", function() {
expect(var_str.encode("").toString("hex")).to.equal("00");
});
});
describe("var_int_list", function() {
it("should decode", function() {
var res;
res = var_int_list.decode(Buffer("00", "hex"));
expect(res.list).to.deep.equal([]);
expect(res.length).to.equal(1);
expect(res.rest.toString("hex")).to.equal("");
res = var_int_list.decode(Buffer("0501fd0400ff0004000000000000fd9c40fe000186a0", "hex"));
expect(res.length).to.equal(22);
expect(res.list.length).to.equal(5);
expect(res.list[0]).to.equal(1);
expect(res.list[1]).to.equal(1024);
expect(res.list[2] == 1125899906842624).to.be.true;
expect(res.list[3]).to.equal(40000);
expect(res.list[4]).to.equal(100000);
expect(res.rest.toString("hex")).to.equal("");
res = var_int_list.decode(Buffer("0501fd0400ff0004000000000000fd9c40fe000186a0ffffff", "hex"));
expect(res.length).to.equal(22);
expect(res.list.length).to.equal(5);
expect(res.rest.toString("hex")).to.equal("ffffff");
});
it("should encode", function() {
expect(var_int_list.encode([]).toString("hex")).to.equal("00");
expect(var_int_list.encode([1, 1024, 1125899906842624, 40000, 100000]).toString("hex")).to.equal("0501fd0400ff0004000000000000fd9c40fe000186a0");
});
});
});
describe("WIF", function() {