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

View File

@ -12,7 +12,7 @@ var UserAgent = require("./user-agent");
var util = require("./util"); var util = require("./util");
/** /**
* Version message. * `version` message.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#version} * @see {@link https://bitmessage.org/wiki/Protocol_specification#version}
* @namespace * @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} * @see {@link https://bitmessage.org/wiki/Protocol_specification#addr}
* @namespace * @namespace
*/ */
@ -138,3 +138,45 @@ exports.addr = {
return Buffer.concat([structs.var_int.encode(addrs.length), addrsBuf]); 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; var SECP256K1_TYPE = 714;
/** /**

36
test.js
View File

@ -12,6 +12,7 @@ var var_int = structs.var_int;
var var_str = structs.var_str; var var_str = structs.var_str;
var var_int_list = structs.var_int_list; var var_int_list = structs.var_int_list;
var net_addr = structs.net_addr; var net_addr = structs.net_addr;
var inv_vect = structs.inv_vect;
var encrypted = structs.encrypted; var encrypted = structs.encrypted;
var messageEncodings = structs.messageEncodings; var messageEncodings = structs.messageEncodings;
var serviceFeatures = structs.serviceFeatures; var serviceFeatures = structs.serviceFeatures;
@ -19,6 +20,7 @@ var pubkeyFeatures = structs.pubkeyFeatures;
var messages = bitmessage.messages; var messages = bitmessage.messages;
var version = messages.version; var version = messages.version;
var addr = messages.addr; var addr = messages.addr;
var inv = messages.inv;
var WIF = bitmessage.WIF; var WIF = bitmessage.WIF;
var POW = bitmessage.POW; var POW = bitmessage.POW;
var Address = bitmessage.Address; 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() { it("should encode and decode", function() {
var iv = Buffer(16); var iv = Buffer(16);
var ephemPublicKey = Buffer(65); var ephemPublicKey = Buffer(65);
@ -249,7 +257,7 @@ describe("Common structures", function() {
}); });
}); });
describe("Message encodings", function() { describe("message encodings", function() {
it("should decode", function() { it("should decode", function() {
expect(messageEncodings.decode(Buffer([2])).value).to.equal(messageEncodings.SIMPLE); 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() { it("should decode", function() {
expect(serviceFeatures.decode(Buffer("0000000000000001", "hex"))).to.have.members([serviceFeatures.NODE_NETWORK]); 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() { it("should decode", function() {
expect(pubkeyFeatures.decode(Buffer("c0000000", "hex"))).to.have.members([pubkeyFeatures.DOES_ACK, pubkeyFeatures.INCLUDE_DESTINATION]); 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); 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() { describe("WIF", function() {
@ -447,7 +473,7 @@ describe("High-level classes", function() {
} }
}); });
describe("User Agent", function() { describe("UserAgent", function() {
var pybm = {name: "PyBitmessage", version: "0.4.4"}; var pybm = {name: "PyBitmessage", version: "0.4.4"};
var bnode = {name: "bitchan-node", version: "0.0.1"}; var bnode = {name: "bitchan-node", version: "0.0.1"};
var bweb = {name: "bitchan-web"}; var bweb = {name: "bitchan-web"};