Implement inv_vect, inv

This commit is contained in:
Kagami Hiiragi 2015-01-16 00:00:27 +03:00
parent ec616a0151
commit 73d2ad393a
4 changed files with 95 additions and 9 deletions

View File

@ -14,7 +14,7 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
## Feature matrix (both Browser and Node)
- [x] crypto
- [x] Crypto
- [x] SHA-512
- [x] SHA-256
- [x] RIPEMD-160
@ -31,6 +31,7 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
- [x] var_str
- [x] var_int_list
- [x] net_addr
- [x] inv_vect
- [x] encrypted
- [x] message encodings
- [x] service features
@ -39,7 +40,7 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
- [x] version
- [x] verack
- [x] addr
- [ ] inv
- [x] inv
- [ ] getdata
- [ ] error
- [ ] object

View File

@ -12,7 +12,7 @@ var UserAgent = require("./user-agent");
var util = require("./util");
/**
* Version message.
* `version` message.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#version}
* @namespace
*/
@ -99,7 +99,7 @@ exports.version = {
};
/**
* Addresses message. Provide information on known nodes of the network.
* `addr` message. Provide information on known nodes of the network.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#addr}
* @namespace
*/
@ -138,3 +138,45 @@ exports.addr = {
return Buffer.concat([structs.var_int.encode(addrs.length), addrsBuf]);
},
};
/**
* `inv` message. Allows a node to advertise its knowledge of one or
* more objects.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#inv}
* @namespace
*/
exports.inv = {
/**
* Decode `inv` payload.
* @param {Buffer} buf - Buffer that starts with encoded `inv` payload
* @return {Object} Decoded `inv` structure.
*/
decode: function(buf) {
var decoded = structs.var_int.decode(buf);
var listLength = decoded.value;
assert(listLength <= 50000, "Too many inventory entires");
var length = decoded.length + listLength * 32;
assert(buf.length >= length, "Buffer is too small");
var rest = decoded.rest;
var inventory = new Array(listLength);
for (var i = 0; i < listLength; i++) {
inventory[i] = rest.slice(i*32, (i+1)*32);
}
return {
inventory: inventory,
// Real data length.
length: length,
};
},
/**
* Encode `inv` payload.
* @param {Buffer[]} inventory - Inventory vectors (encoded)
* @return {Buffer} Encoded `inv` payload.
*/
encode: function(inventory) {
assert(inventory.length <= 50000, "Too many inventory entires");
var invBuf = Buffer.concat(inventory);
return Buffer.concat([structs.var_int.encode(inventory.length), invBuf]);
},
};

View File

@ -417,6 +417,23 @@ exports.net_addr = {
},
};
/**
* Inventory vector.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#Inventory_Vectors}
* @namespace
*/
// Only encode operation is defined because decode is impossible.
exports.inv_vect = {
/**
* Encode inventory vector.
* @param {Buffer} buf - Payload to calculate inventory vector for
* @return {Buffer} Encoded `inv_vect`.
*/
encode: function(buf) {
return bmcrypto.sha512(bmcrypto.sha512(buf)).slice(0, 32);
},
};
var SECP256K1_TYPE = 714;
/**

34
test.js
View File

@ -12,6 +12,7 @@ var var_int = structs.var_int;
var var_str = structs.var_str;
var var_int_list = structs.var_int_list;
var net_addr = structs.net_addr;
var inv_vect = structs.inv_vect;
var encrypted = structs.encrypted;
var messageEncodings = structs.messageEncodings;
var serviceFeatures = structs.serviceFeatures;
@ -19,6 +20,7 @@ var pubkeyFeatures = structs.pubkeyFeatures;
var messages = bitmessage.messages;
var version = messages.version;
var addr = messages.addr;
var inv = messages.inv;
var WIF = bitmessage.WIF;
var POW = bitmessage.POW;
var Address = bitmessage.Address;
@ -225,7 +227,13 @@ describe("Common structures", function() {
});
});
describe("Encrypted", function() {
describe("inv_vect", function() {
it("should encode", function() {
expect(inv_vect.encode("test").toString("hex")).to.equal("faadcaf60afd35dfcdb5e9ea0d0a0531f6338c62187cff37a1efe11f1d41a348");
});
});
describe("encrypted", function() {
it("should encode and decode", function() {
var iv = Buffer(16);
var ephemPublicKey = Buffer(65);
@ -249,7 +257,7 @@ describe("Common structures", function() {
});
});
describe("Message encodings", function() {
describe("message encodings", function() {
it("should decode", function() {
expect(messageEncodings.decode(Buffer([2])).value).to.equal(messageEncodings.SIMPLE);
});
@ -259,7 +267,7 @@ describe("Common structures", function() {
});
});
describe("Service features", function() {
describe("service features", function() {
it("should decode", function() {
expect(serviceFeatures.decode(Buffer("0000000000000001", "hex"))).to.have.members([serviceFeatures.NODE_NETWORK]);
});
@ -270,7 +278,7 @@ describe("Common structures", function() {
});
});
describe("Pubkey features", function() {
describe("pubkey features", function() {
it("should decode", function() {
expect(pubkeyFeatures.decode(Buffer("c0000000", "hex"))).to.have.members([pubkeyFeatures.DOES_ACK, pubkeyFeatures.INCLUDE_DESTINATION]);
});
@ -326,6 +334,24 @@ describe("Message types", function() {
expect(addr.decode.bind(null, var_int.encode(2000))).to.throw(/too many/i);
});
});
describe("inv", function() {
it("should encode and decode", function() {
var vect1 = inv_vect.encode(Buffer("test"));
var vect2 = inv_vect.encode(Buffer("test2"));
var inventory = [vect1, vect2];
var res = inv.decode(inv.encode(inventory));
expect(res.inventory.length).to.equal(2);
expect(bufferEqual(res.inventory[0], vect1)).to.be.true;
expect(bufferEqual(res.inventory[1], vect2)).to.be.true;
expect(res.length).to.equal(65);
});
it("shouldn't encode/decode more than 1000 entires", function() {
expect(inv.encode.bind(null, Array(60000))).to.throw(/too many/i);
expect(inv.decode.bind(null, var_int.encode(60000))).to.throw(/too many/i);
});
});
});
describe("WIF", function() {