Bitfields encoding/decoding

This commit is contained in:
Kagami Hiiragi 2015-01-05 02:40:52 +03:00
parent f356a070cc
commit e6d4e4c029
3 changed files with 112 additions and 12 deletions

View File

@ -33,8 +33,8 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
- [ ] net_addr
- [ ] encrypted
- [x] message encodings
- [ ] service features
- [ ] pubkey features
- [x] service features
- [x] pubkey features
- [ ] Message types
- [ ] version
- [ ] verack

View File

@ -251,18 +251,84 @@ exports.var_int_list = {
},
};
exports.messageEncodings = Object.create(var_int);
Object.assign(exports.messageEncodings, {
/**
* Message encodings. Extends {@link var_int} by adding known encoding type
* constants.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#Message_Encodings}
*/
exports.messageEncodings = Object.assign(Object.create(var_int), {
/**
* Any data with this number may be ignored. The sending node might
* simply be sharing its public key with you.
*/
IGNORE: 0,
/**
* UTF-8. No 'Subject' or 'Body' sections. Useful for simple strings
* of data, like URIs or magnet links.
*/
TRIVIAL: 1,
/**
* UTF-8. Uses 'Subject' and 'Body' sections. No MIME is used.
*/
SIMPLE: 2,
});
exports.serviceFeatures = {
NODE_NETWORK: 1,
// Creates bitfield class of the specified size.
var bitfield = function(size) {
var bytesize = size / 8;
return {
decode: function(buf) {
assert(buf.length === bytesize, "Bad buffer size");
var features = [];
var index;
for (var i = 0; i < size; i++) {
index = bytesize - Math.floor(i / 8) - 1;
if ((buf[index] & (1 << (i % 8))) !== 0) { // jshint ignore:line
features.push(i);
}
}
return features;
},
encode: function(features) {
var buf = new Buffer(bytesize);
buf.fill(0);
features.forEach(function(feature) {
assert(feature >= 0, "Bad feature");
assert(feature <= (size - 1), "Bad feature");
var index = bytesize - Math.floor(feature / 8) - 1;
buf[index] |= 1 << (feature % 8); // jshint ignore:line
});
return buf;
},
};
};
exports.pubkeyFeatures = {
/**
* Service bitfield features. Implements encoding/decoding for a 8-byte
* buffer object.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#version}
*/
exports.serviceFeatures = Object.assign(bitfield(64), {
/** This is a normal network node. */
NODE_NETWORK: 0,
});
/**
* Pubkey bitfield features. Implements encoding/decoding for a 4-byte
* buffer object.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features}
*/
exports.pubkeyFeatures = Object.assign(bitfield(32), {
/**
* Receiving node expects that the RIPE hash encoded in their address
* preceedes the encrypted message data of msg messages bound for
* them.
*/
INCLUDE_DESTINATION: 30,
/**
* If true, the receiving node does send acknowledgements (rather than
* dropping them).
*/
DOES_ACK: 31,
};
});

42
test.js
View File

@ -5,10 +5,14 @@ var allTests = typeof window === "undefined" ?
var bmcrypto = require("./lib/crypto");
var bitmessage = require("./lib");
var message = bitmessage.structs.message;
var var_int = bitmessage.structs.var_int;
var var_str = bitmessage.structs.var_str;
var var_int_list = bitmessage.structs.var_int_list;
var structs = bitmessage.structs;
var message = structs.message;
var var_int = structs.var_int;
var var_str = structs.var_str;
var var_int_list = structs.var_int_list;
var messageEncodings = structs.messageEncodings;
var serviceFeatures = structs.serviceFeatures;
var pubkeyFeatures = structs.pubkeyFeatures;
var WIF = bitmessage.WIF;
var Address = bitmessage.Address;
@ -166,6 +170,36 @@ describe("Common structures", function() {
expect(var_int_list.encode([1, 1024, 1125899906842624, 40000, 100000]).toString("hex")).to.equal("0501fd0400ff0004000000000000fd9c40fe000186a0");
});
});
describe("Message encodings", function() {
it("should decode", function() {
expect(messageEncodings.decode(Buffer([2])).value).to.equal(messageEncodings.SIMPLE);
});
it("should encode", function() {
expect(messageEncodings.encode(messageEncodings.SIMPLE).toString("hex")).to.equal("02");
});
});
describe("Service features", function() {
it("should decode", function() {
expect(serviceFeatures.decode(Buffer("0000000000000001", "hex"))).to.have.members([serviceFeatures.NODE_NETWORK]);
});
it("should encode", function() {
expect(serviceFeatures.encode([serviceFeatures.NODE_NETWORK]).toString("hex")).to.equal("0000000000000001");
});
});
describe("Pubkey features", function() {
it("should decode", function() {
expect(pubkeyFeatures.decode(Buffer("c0000000", "hex"))).to.have.members([pubkeyFeatures.DOES_ACK, pubkeyFeatures.INCLUDE_DESTINATION]);
});
it("should encode", function() {
expect(pubkeyFeatures.encode([pubkeyFeatures.INCLUDE_DESTINATION, pubkeyFeatures.DOES_ACK]).toString("hex")).to.equal("c0000000");
});
});
});
describe("WIF", function() {