Bitfields encoding/decoding
This commit is contained in:
parent
f356a070cc
commit
e6d4e4c029
|
@ -33,8 +33,8 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
|
||||||
- [ ] net_addr
|
- [ ] net_addr
|
||||||
- [ ] encrypted
|
- [ ] encrypted
|
||||||
- [x] message encodings
|
- [x] message encodings
|
||||||
- [ ] service features
|
- [x] service features
|
||||||
- [ ] pubkey features
|
- [x] pubkey features
|
||||||
- [ ] Message types
|
- [ ] Message types
|
||||||
- [ ] version
|
- [ ] version
|
||||||
- [ ] verack
|
- [ ] verack
|
||||||
|
|
|
@ -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,
|
IGNORE: 0,
|
||||||
|
/**
|
||||||
|
* UTF-8. No 'Subject' or 'Body' sections. Useful for simple strings
|
||||||
|
* of data, like URIs or magnet links.
|
||||||
|
*/
|
||||||
TRIVIAL: 1,
|
TRIVIAL: 1,
|
||||||
|
/**
|
||||||
|
* UTF-8. Uses 'Subject' and 'Body' sections. No MIME is used.
|
||||||
|
*/
|
||||||
SIMPLE: 2,
|
SIMPLE: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.serviceFeatures = {
|
// Creates bitfield class of the specified size.
|
||||||
NODE_NETWORK: 1,
|
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,
|
INCLUDE_DESTINATION: 30,
|
||||||
|
/**
|
||||||
|
* If true, the receiving node does send acknowledgements (rather than
|
||||||
|
* dropping them).
|
||||||
|
*/
|
||||||
DOES_ACK: 31,
|
DOES_ACK: 31,
|
||||||
};
|
});
|
||||||
|
|
42
test.js
42
test.js
|
@ -5,10 +5,14 @@ var allTests = typeof window === "undefined" ?
|
||||||
|
|
||||||
var bmcrypto = require("./lib/crypto");
|
var bmcrypto = require("./lib/crypto");
|
||||||
var bitmessage = require("./lib");
|
var bitmessage = require("./lib");
|
||||||
var message = bitmessage.structs.message;
|
var structs = bitmessage.structs;
|
||||||
var var_int = bitmessage.structs.var_int;
|
var message = structs.message;
|
||||||
var var_str = bitmessage.structs.var_str;
|
var var_int = structs.var_int;
|
||||||
var var_int_list = bitmessage.structs.var_int_list;
|
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 WIF = bitmessage.WIF;
|
||||||
var Address = bitmessage.Address;
|
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");
|
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() {
|
describe("WIF", function() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user