encodePayloadAsync/decodePayloadAsync for objects
This commit is contained in:
parent
514265b7cd
commit
a25bf41036
159
lib/objects.js
159
lib/objects.js
|
@ -17,46 +17,76 @@ var assert = require("./_util").assert;
|
||||||
var promise = require("./platform").promise;
|
var promise = require("./platform").promise;
|
||||||
var bmcrypto = require("./crypto");
|
var bmcrypto = require("./crypto");
|
||||||
var Address = require("./address");
|
var Address = require("./address");
|
||||||
var var_int = require("./structs").var_int;
|
var structs = require("./structs");
|
||||||
var PubkeyBitfield = require("./structs").PubkeyBitfield;
|
|
||||||
var object = require("./structs").object;
|
|
||||||
var util = require("./_util");
|
var util = require("./_util");
|
||||||
|
|
||||||
|
var var_int = structs.var_int;
|
||||||
|
var PubkeyBitfield = structs.PubkeyBitfield;
|
||||||
|
var message = structs.message;
|
||||||
|
var object = structs.object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `getpubkey` object. When a node has the hash of a public key (from an
|
* `getpubkey` object. When a node has the hash of a public key (from an
|
||||||
* address) but not the public key itself, it must send out a request
|
* address) but not the public key itself, it must send out a request
|
||||||
* for the public key.
|
* for the public key.
|
||||||
* @see {@link https://bitmessage.org/wiki/Protocol_specification#getpubkey}
|
* @see {@link https://bitmessage.org/wiki/Protocol_specification#getpubkey}
|
||||||
* @namespace
|
* @namespace
|
||||||
|
* @static
|
||||||
*/
|
*/
|
||||||
exports.getpubkey = {
|
var getpubkey = exports.getpubkey = {
|
||||||
|
/**
|
||||||
|
* Decode `getpubkey` object message.
|
||||||
|
* @param {Buffer} buf - Message
|
||||||
|
* @return {Promise.<Object>} A promise that contains decoded
|
||||||
|
* `getpubkey` object structure when fulfilled.
|
||||||
|
*/
|
||||||
|
decodeAsync: function(buf) {
|
||||||
|
return new promise(function(resolve) {
|
||||||
|
var decoded = message.decode(buf);
|
||||||
|
assert(decoded.command === "object", "Bad command");
|
||||||
|
resolve(getpubkey.decodePayloadAsync(decoded.payload));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode `getpubkey` object message payload.
|
* Decode `getpubkey` object message payload.
|
||||||
* @param {Buffer} buf - Message payload
|
* @param {Buffer} buf - Message payload
|
||||||
* @return {Promise.<Object>} A promise that contains decoded
|
* @return {Promise.<Object>} A promise that contains decoded
|
||||||
* `getpubkey` object structure when fulfilled.
|
* `getpubkey` object structure when fulfilled.
|
||||||
*/
|
*/
|
||||||
decodeAsync: function(buf) {
|
decodePayloadAsync: function(buf) {
|
||||||
return new promise(function(resolve) {
|
return new promise(function(resolve) {
|
||||||
var decoded = object.decode(buf);
|
var decoded = object.decodePayload(buf);
|
||||||
assert(decoded.type === object.GETPUBKEY, "Wrong object type");
|
assert(decoded.type === object.GETPUBKEY, "Wrong object type");
|
||||||
assert(decoded.version >= 2, "getpubkey version is too low");
|
assert(decoded.version >= 2, "getpubkey version is too low");
|
||||||
assert(decoded.version <= 4, "getpubkey version is too high");
|
assert(decoded.version <= 4, "getpubkey version is too high");
|
||||||
var payload = decoded.payload;
|
var objectPayload = decoded.objectPayload;
|
||||||
delete decoded.payload;
|
delete decoded.objectPayload;
|
||||||
if (decoded.version < 4) {
|
if (decoded.version < 4) {
|
||||||
assert(payload.length === 20, "getpubkey ripe is too small");
|
assert(objectPayload.length === 20, "getpubkey ripe is too small");
|
||||||
// Payload is copied so it's safe to return it right away.
|
// Object payload is copied so it's safe to return it right away.
|
||||||
decoded.ripe = payload;
|
decoded.ripe = objectPayload;
|
||||||
} else {
|
} else {
|
||||||
assert(payload.length === 32, "getpubkey tag is too small");
|
assert(objectPayload.length === 32, "getpubkey tag is too small");
|
||||||
// Payload is copied so it's safe to return it right away.
|
// Object payload is copied so it's safe to return it right away.
|
||||||
decoded.tag = payload;
|
decoded.tag = objectPayload;
|
||||||
}
|
}
|
||||||
resolve(decoded);
|
resolve(decoded);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode `getpubkey` object message.
|
||||||
|
* @param {Object} opts - `getpubkey` object options
|
||||||
|
* @return {Promise.<Buffer>} A promise that contains encoded message
|
||||||
|
* when fulfilled.
|
||||||
|
*/
|
||||||
|
encodeAsync: function(opts) {
|
||||||
|
return getpubkey.encodePayloadAsync(opts).then(function(payload) {
|
||||||
|
return message.encode("object", payload);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode `getpubkey` object message payload.
|
* Encode `getpubkey` object message payload.
|
||||||
* @param {Object} opts - `getpubkey` object options
|
* @param {Object} opts - `getpubkey` object options
|
||||||
|
@ -64,7 +94,7 @@ exports.getpubkey = {
|
||||||
* payload when fulfilled.
|
* payload when fulfilled.
|
||||||
*/
|
*/
|
||||||
// FIXME(Kagami): Do a POW.
|
// FIXME(Kagami): Do a POW.
|
||||||
encodeAsync: function(opts) {
|
encodePayloadAsync: function(opts) {
|
||||||
return new promise(function(resolve) {
|
return new promise(function(resolve) {
|
||||||
opts = objectAssign({}, opts);
|
opts = objectAssign({}, opts);
|
||||||
opts.type = object.GETPUBKEY;
|
opts.type = object.GETPUBKEY;
|
||||||
|
@ -74,34 +104,36 @@ exports.getpubkey = {
|
||||||
assert(to.version <= 4, "Address version is too high");
|
assert(to.version <= 4, "Address version is too high");
|
||||||
opts.version = to.version;
|
opts.version = to.version;
|
||||||
opts.stream = to.stream;
|
opts.stream = to.stream;
|
||||||
opts.payload = to.version < 4 ? to.getRipe() : to.getTag();
|
opts.objectPayload = to.version < 4 ? to.getRipe() : to.getTag();
|
||||||
// POW calculation here.
|
// POW calculation here.
|
||||||
var nonce = new Buffer(8);
|
var nonce = new Buffer(8);
|
||||||
opts.nonce = nonce;
|
opts.nonce = nonce;
|
||||||
resolve(object.encode(opts));
|
resolve(object.encodePayload(opts));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function for `pubkey.decode`.
|
// Helper function for `pubkey.decode`.
|
||||||
function extractPubkeyV2(payload) {
|
// Extract pubkey data from decrypted object payload.
|
||||||
|
function extractPubkeyV2(buf) {
|
||||||
var decoded = {};
|
var decoded = {};
|
||||||
// Payload is copied so it's safe to return it right away.
|
// Object payload is copied so it's safe to return it right away.
|
||||||
decoded.behavior = PubkeyBitfield(payload.slice(0, 4));
|
decoded.behavior = PubkeyBitfield(buf.slice(0, 4));
|
||||||
var signPublicKey = decoded.signPublicKey = new Buffer(65);
|
var signPublicKey = decoded.signPublicKey = new Buffer(65);
|
||||||
signPublicKey[0] = 4;
|
signPublicKey[0] = 4;
|
||||||
payload.copy(signPublicKey, 1, 4, 68);
|
buf.copy(signPublicKey, 1, 4, 68);
|
||||||
var encPublicKey = decoded.encPublicKey = new Buffer(65);
|
var encPublicKey = decoded.encPublicKey = new Buffer(65);
|
||||||
encPublicKey[0] = 4;
|
encPublicKey[0] = 4;
|
||||||
payload.copy(encPublicKey, 1, 68, 132);
|
buf.copy(encPublicKey, 1, 68, 132);
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for `pubkey.decode`.
|
// Helper function for `pubkey.decode`.
|
||||||
function extractPubkeyV3(payload) {
|
// Extract pubkey data from decrypted object payload.
|
||||||
|
function extractPubkeyV3(buf) {
|
||||||
var decoded = {};
|
var decoded = {};
|
||||||
var length = 0;
|
var length = 0;
|
||||||
var decodedTrials = var_int.decode(payload);
|
var decodedTrials = var_int.decode(buf);
|
||||||
decoded.nonceTrialsPerByte = decodedTrials.value;
|
decoded.nonceTrialsPerByte = decodedTrials.value;
|
||||||
length += decodedTrials.length;
|
length += decodedTrials.length;
|
||||||
var decodedExtraBytes = var_int.decode(decodedTrials.rest);
|
var decodedExtraBytes = var_int.decode(decodedTrials.rest);
|
||||||
|
@ -111,8 +143,7 @@ function extractPubkeyV3(payload) {
|
||||||
decoded.signature = decodedSigLength.rest.slice(0, decodedSigLength.value);
|
decoded.signature = decodedSigLength.rest.slice(0, decodedSigLength.value);
|
||||||
var siglen = decodedSigLength.length + decodedSigLength.value;
|
var siglen = decodedSigLength.length + decodedSigLength.value;
|
||||||
length += siglen;
|
length += siglen;
|
||||||
// Internal value.
|
decoded._siglen = siglen; // Internal value
|
||||||
decoded._siglen = siglen;
|
|
||||||
decoded.length = length;
|
decoded.length = length;
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
@ -121,8 +152,24 @@ function extractPubkeyV3(payload) {
|
||||||
* `pubkey` object.
|
* `pubkey` object.
|
||||||
* @see {@link https://bitmessage.org/wiki/Protocol_specification#pubkey}
|
* @see {@link https://bitmessage.org/wiki/Protocol_specification#pubkey}
|
||||||
* @namespace
|
* @namespace
|
||||||
|
* @static
|
||||||
*/
|
*/
|
||||||
exports.pubkey = {
|
var pubkey = exports.pubkey = {
|
||||||
|
/**
|
||||||
|
* Decode `pubkey` object message.
|
||||||
|
* @param {Buffer} buf - Message
|
||||||
|
* @param {?Object} opts - Decoding options
|
||||||
|
* @return {Promise.<Object>} A promise that contains decoded `pubkey`
|
||||||
|
* object structure when fulfilled.
|
||||||
|
*/
|
||||||
|
decodeAsync: function(buf, opts) {
|
||||||
|
return new promise(function(resolve) {
|
||||||
|
var decoded = message.decode(buf);
|
||||||
|
assert(decoded.command === "object", "Bad command");
|
||||||
|
resolve(pubkey.decodePayloadAsync(decoded.payload, opts));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode `pubkey` object message payload.
|
* Decode `pubkey` object message payload.
|
||||||
* @param {Buffer} buf - Message payload
|
* @param {Buffer} buf - Message payload
|
||||||
|
@ -130,14 +177,14 @@ exports.pubkey = {
|
||||||
* @return {Promise.<Object>} A promise that contains decoded `pubkey`
|
* @return {Promise.<Object>} A promise that contains decoded `pubkey`
|
||||||
* object structure when fulfilled.
|
* object structure when fulfilled.
|
||||||
*/
|
*/
|
||||||
decodeAsync: function(buf, opts) {
|
decodePayloadAsync: function(buf, opts) {
|
||||||
return new promise(function(resolve, reject) {
|
return new promise(function(resolve, reject) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
var neededPubkeys = opts.neededPubkeys || {};
|
var neededPubkeys = opts.neededPubkeys || {};
|
||||||
var decoded = object.decode(buf);
|
var decoded = object.decodePayload(buf);
|
||||||
assert(decoded.type === object.PUBKEY, "Wrong object type");
|
assert(decoded.type === object.PUBKEY, "Wrong object type");
|
||||||
var payload = decoded.payload;
|
var objectPayload = decoded.objectPayload;
|
||||||
delete decoded.payload;
|
delete decoded.objectPayload;
|
||||||
var version = decoded.version;
|
var version = decoded.version;
|
||||||
assert(version >= 2, "Address version is too low");
|
assert(version >= 2, "Address version is too low");
|
||||||
assert(version <= 4, "Address version is too high");
|
assert(version <= 4, "Address version is too high");
|
||||||
|
@ -148,8 +195,10 @@ exports.pubkey = {
|
||||||
// v2 pubkey.
|
// v2 pubkey.
|
||||||
if (version === 2) {
|
if (version === 2) {
|
||||||
// 4 + 64 + 64
|
// 4 + 64 + 64
|
||||||
assert(payload.length === 132, "Bad pubkey v2 object payload length");
|
assert(
|
||||||
objectAssign(decoded, extractPubkeyV2(payload));
|
objectPayload.length === 132,
|
||||||
|
"Bad pubkey v2 object payload length");
|
||||||
|
objectAssign(decoded, extractPubkeyV2(objectPayload));
|
||||||
// Real data length.
|
// Real data length.
|
||||||
decoded.length = length;
|
decoded.length = length;
|
||||||
return resolve(decoded);
|
return resolve(decoded);
|
||||||
|
@ -158,9 +207,11 @@ exports.pubkey = {
|
||||||
// v3 pubkey.
|
// v3 pubkey.
|
||||||
if (version === 3) {
|
if (version === 3) {
|
||||||
// 4 + 64 + 64 + (1+) + (1+) + (1+)
|
// 4 + 64 + 64 + (1+) + (1+) + (1+)
|
||||||
assert(payload.length >= 135, "Bad pubkey v3 object payload length");
|
assert(
|
||||||
objectAssign(decoded, extractPubkeyV2(payload));
|
objectPayload.length >= 135,
|
||||||
objectAssign(decoded, extractPubkeyV3(payload.slice(132)));
|
"Bad pubkey v3 object payload length");
|
||||||
|
objectAssign(decoded, extractPubkeyV2(objectPayload));
|
||||||
|
objectAssign(decoded, extractPubkeyV3(objectPayload.slice(132)));
|
||||||
siglen = util.popkey(decoded, "_siglen");
|
siglen = util.popkey(decoded, "_siglen");
|
||||||
length += decoded.length;
|
length += decoded.length;
|
||||||
// Real data length.
|
// Real data length.
|
||||||
|
@ -192,13 +243,13 @@ exports.pubkey = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(payload.length >= 32, "Bad pubkey v4 object payload length");
|
assert(objectPayload.length >= 32, "Bad pubkey v4 object payload length");
|
||||||
tag = decoded.tag = payload.slice(0, 32);
|
tag = decoded.tag = objectPayload.slice(0, 32);
|
||||||
pubkeyEncPrivateKey = neededPubkeys[tag];
|
pubkeyEncPrivateKey = neededPubkeys[tag];
|
||||||
if (!pubkeyEncPrivateKey) {
|
if (!pubkeyEncPrivateKey) {
|
||||||
return reject(new Error("You are not interested in this pubkey v4"));
|
return reject(new Error("You are not interested in this pubkey v4"));
|
||||||
}
|
}
|
||||||
dataToDecrypt = payload.slice(32);
|
dataToDecrypt = objectPayload.slice(32);
|
||||||
pubkeyp = bmcrypto.decrypt(pubkeyEncPrivateKey, dataToDecrypt)
|
pubkeyp = bmcrypto.decrypt(pubkeyEncPrivateKey, dataToDecrypt)
|
||||||
.then(function(decrypted) {
|
.then(function(decrypted) {
|
||||||
// 4 + 64 + 64 + (1+) + (1+) + (1+)
|
// 4 + 64 + 64 + (1+) + (1+) + (1+)
|
||||||
|
@ -210,8 +261,8 @@ exports.pubkey = {
|
||||||
siglen = util.popkey(decoded, "_siglen");
|
siglen = util.popkey(decoded, "_siglen");
|
||||||
length += decoded.length;
|
length += decoded.length;
|
||||||
// Real data length.
|
// Real data length.
|
||||||
// Since data is encrypted, entire payload is used.
|
// Since data is encrypted, entire object payload is used.
|
||||||
decoded.length = payload.length;
|
decoded.length = objectPayload.length;
|
||||||
dataToVerify = Buffer.concat([
|
dataToVerify = Buffer.concat([
|
||||||
// Object header without nonce + tag.
|
// Object header without nonce + tag.
|
||||||
buf.slice(8, decoded.headerLength + 32),
|
buf.slice(8, decoded.headerLength + 32),
|
||||||
|
@ -227,6 +278,18 @@ exports.pubkey = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode `pubkey` object message.
|
||||||
|
* @param {Object} opts - `pubkey` object options
|
||||||
|
* @return {Promise.<Buffer>} A promise that contains encoded message
|
||||||
|
* when fulfilled.
|
||||||
|
*/
|
||||||
|
encodeAsync: function(opts) {
|
||||||
|
return pubkey.encodePayloadAsync(opts).then(function(payload) {
|
||||||
|
return message.encode("object", payload);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode `pubkey` object message payload.
|
* Encode `pubkey` object message payload.
|
||||||
* @param {Object} opts - `pubkey` object options
|
* @param {Object} opts - `pubkey` object options
|
||||||
|
@ -234,7 +297,7 @@ exports.pubkey = {
|
||||||
* payload when fulfilled.
|
* payload when fulfilled.
|
||||||
*/
|
*/
|
||||||
// FIXME(Kagami): Do a POW.
|
// FIXME(Kagami): Do a POW.
|
||||||
encodeAsync: function(opts) {
|
encodePayloadAsync: function(opts) {
|
||||||
return new promise(function(resolve) {
|
return new promise(function(resolve) {
|
||||||
opts = objectAssign({}, opts);
|
opts = objectAssign({}, opts);
|
||||||
opts.type = object.PUBKEY;
|
opts.type = object.PUBKEY;
|
||||||
|
@ -260,12 +323,12 @@ exports.pubkey = {
|
||||||
|
|
||||||
// v2 pubkey.
|
// v2 pubkey.
|
||||||
if (version === 2) {
|
if (version === 2) {
|
||||||
opts.payload = Buffer.concat([
|
opts.objectPayload = Buffer.concat([
|
||||||
from.behavior.buffer,
|
from.behavior.buffer,
|
||||||
from.signPublicKey.slice(1),
|
from.signPublicKey.slice(1),
|
||||||
from.encPublicKey.slice(1),
|
from.encPublicKey.slice(1),
|
||||||
]);
|
]);
|
||||||
obj = object.encodeWithoutNonce(opts);
|
obj = object.encodePayloadWithoutNonce(opts);
|
||||||
// POW calculation here.
|
// POW calculation here.
|
||||||
var nonce = new Buffer(8);
|
var nonce = new Buffer(8);
|
||||||
obj = Buffer.concat([nonce, obj]);
|
obj = Buffer.concat([nonce, obj]);
|
||||||
|
@ -282,8 +345,8 @@ exports.pubkey = {
|
||||||
|
|
||||||
// v3 pubkey.
|
// v3 pubkey.
|
||||||
if (version === 3) {
|
if (version === 3) {
|
||||||
opts.payload = Buffer.concat(pubkeyData);
|
opts.objectPayload = Buffer.concat(pubkeyData);
|
||||||
obj = object.encodeWithoutNonce(opts);
|
obj = object.encodePayloadWithoutNonce(opts);
|
||||||
pubkeyp = bmcrypto
|
pubkeyp = bmcrypto
|
||||||
.sign(from.signPrivateKey, obj)
|
.sign(from.signPrivateKey, obj)
|
||||||
.then(function(sig) {
|
.then(function(sig) {
|
||||||
|
@ -301,8 +364,8 @@ exports.pubkey = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// v4 pubkey.
|
// v4 pubkey.
|
||||||
opts.payload = from.getTag();
|
opts.objectPayload = from.getTag();
|
||||||
obj = object.encodeWithoutNonce(opts);
|
obj = object.encodePayloadWithoutNonce(opts);
|
||||||
var dataToSign = Buffer.concat([obj].concat(pubkeyData));
|
var dataToSign = Buffer.concat([obj].concat(pubkeyData));
|
||||||
var pubkeyEncPrivateKey = from.getPubkeyPrivateKey();
|
var pubkeyEncPrivateKey = from.getPubkeyPrivateKey();
|
||||||
var pubkeyEncPublicKey = bmcrypto.getPublic(pubkeyEncPrivateKey);
|
var pubkeyEncPublicKey = bmcrypto.getPublic(pubkeyEncPrivateKey);
|
||||||
|
|
|
@ -108,9 +108,21 @@ var object = exports.object = {
|
||||||
MSG: 2,
|
MSG: 2,
|
||||||
BROADCAST: 3,
|
BROADCAST: 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode `object` message.
|
||||||
|
* NOTE: `nonce` and `objectPayload` are copied.
|
||||||
|
* @param {Buffer} buf - Message
|
||||||
|
* @return {Object} Decoded `object` structure.
|
||||||
|
*/
|
||||||
|
decode: function(buf) {
|
||||||
|
var decoded = message.decode(buf);
|
||||||
|
assert(decoded.command === "object", "Bad command");
|
||||||
|
return object.decodePayload(decoded.payload);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode `object` message payload.
|
* Decode `object` message payload.
|
||||||
* NOTE: `nonce` and `payload` are copied.
|
* NOTE: `nonce` and `objectPayload` are copied.
|
||||||
* @param {Buffer} buf - Message payload
|
* @param {Buffer} buf - Message payload
|
||||||
* @return {Object} Decoded `object` structure.
|
* @return {Object} Decoded `object` structure.
|
||||||
*/
|
*/
|
||||||
|
@ -119,7 +131,7 @@ var object = exports.object = {
|
||||||
// bitchan).
|
// bitchan).
|
||||||
// TODO(Kagami): Option to not fail on expired objects (would be
|
// TODO(Kagami): Option to not fail on expired objects (would be
|
||||||
// useful for bitchan).
|
// useful for bitchan).
|
||||||
decode: function(buf) {
|
decodePayload: function(buf) {
|
||||||
// 8 + 8 + 4 + (1+) + (1+)
|
// 8 + 8 + 4 + (1+) + (1+)
|
||||||
assert(buf.length >= 22, "object message payload is too small");
|
assert(buf.length >= 22, "object message payload is too small");
|
||||||
var nonce = new Buffer(8);
|
var nonce = new Buffer(8);
|
||||||
|
@ -132,8 +144,8 @@ var object = exports.object = {
|
||||||
var decodedVersion = var_int.decode(buf.slice(20));
|
var decodedVersion = var_int.decode(buf.slice(20));
|
||||||
var decodedStream = var_int.decode(decodedVersion.rest);
|
var decodedStream = var_int.decode(decodedVersion.rest);
|
||||||
var headerLength = 20 + decodedVersion.length + decodedStream.length;
|
var headerLength = 20 + decodedVersion.length + decodedStream.length;
|
||||||
var payload = new Buffer(decodedStream.rest.length);
|
var objectPayload = new Buffer(decodedStream.rest.length);
|
||||||
decodedStream.rest.copy(payload);
|
decodedStream.rest.copy(objectPayload);
|
||||||
return {
|
return {
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
ttl: ttl,
|
ttl: ttl,
|
||||||
|
@ -141,17 +153,42 @@ var object = exports.object = {
|
||||||
version: decodedVersion.value,
|
version: decodedVersion.value,
|
||||||
stream: decodedStream.value,
|
stream: decodedStream.value,
|
||||||
headerLength: headerLength,
|
headerLength: headerLength,
|
||||||
payload: payload,
|
objectPayload: objectPayload,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode `object` message.
|
||||||
|
* @param {Object} opts - Object options
|
||||||
|
* @return {Buffer} Encoded message.
|
||||||
|
*/
|
||||||
|
encode: function(opts) {
|
||||||
|
var payload = object.encodePayload(opts);
|
||||||
|
return message.encode("object", payload);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode `object` message payload.
|
||||||
|
* @param {Object} opts - Object options
|
||||||
|
* @return {Buffer} Encoded payload.
|
||||||
|
*/
|
||||||
|
encodePayload: function(opts) {
|
||||||
|
assert(opts.nonce.length === 8, "Bad nonce");
|
||||||
|
// NOTE(Kagami): This may be a bit inefficient since we allocate
|
||||||
|
// twice.
|
||||||
|
return Buffer.concat([
|
||||||
|
opts.nonce,
|
||||||
|
object.encodePayloadWithoutNonce(opts),
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode `object` message payload without leading nonce field (may be
|
* Encode `object` message payload without leading nonce field (may be
|
||||||
* useful if you are going to calculate it later).
|
* useful if you are going to calculate it later).
|
||||||
* @param {Object} opts - Object options
|
* @param {Object} opts - Object options
|
||||||
* @return {Buffer} Encoded payload.
|
* @return {Buffer} Encoded payload.
|
||||||
*/
|
*/
|
||||||
encodeWithoutNonce: function(opts) {
|
encodePayloadWithoutNonce: function(opts) {
|
||||||
assert(opts.ttl > 0, "Bad TTL");
|
assert(opts.ttl > 0, "Bad TTL");
|
||||||
assert(opts.ttl <= 2430000, "TTL may not be larger than 28 days + 3 hours");
|
assert(opts.ttl <= 2430000, "TTL may not be larger than 28 days + 3 hours");
|
||||||
var expiresTime = util.tnow() + opts.ttl;
|
var expiresTime = util.tnow() + opts.ttl;
|
||||||
|
@ -163,22 +200,7 @@ var object = exports.object = {
|
||||||
type,
|
type,
|
||||||
var_int.encode(opts.version),
|
var_int.encode(opts.version),
|
||||||
var_int.encode(stream),
|
var_int.encode(stream),
|
||||||
opts.payload,
|
opts.objectPayload,
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode `object` message payload.
|
|
||||||
* @param {Object} opts - Object options
|
|
||||||
* @return {Buffer} Encoded payload.
|
|
||||||
*/
|
|
||||||
encode: function(opts) {
|
|
||||||
assert(opts.nonce.length === 8, "Bad nonce");
|
|
||||||
// NOTE(Kagami): This may be a bit inefficient since we allocate
|
|
||||||
// twice.
|
|
||||||
return Buffer.concat([
|
|
||||||
opts.nonce,
|
|
||||||
object.encodeWithoutNonce(opts),
|
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
"bn.js": "^1.0.0",
|
"bn.js": "^1.0.0",
|
||||||
"bs58": "^2.0.0",
|
"bs58": "^2.0.0",
|
||||||
"buffer-equal": "~0.0.1",
|
"buffer-equal": "~0.0.1",
|
||||||
"eccrypto": "^0.9.3",
|
"eccrypto": "^0.9.4",
|
||||||
"es6-promise": "^2.0.1",
|
"es6-promise": "^2.0.1",
|
||||||
"hash.js": "^1.0.2",
|
"hash.js": "^1.0.2",
|
||||||
"nan": "^1.4.1",
|
"nan": "^1.4.1",
|
||||||
|
|
34
test.js
34
test.js
|
@ -112,6 +112,7 @@ describe("Crypto", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO(Kagami): Add tests for encodePayload/decodePayload as well.
|
||||||
describe("Common structures", function() {
|
describe("Common structures", function() {
|
||||||
describe("message", function() {
|
describe("message", function() {
|
||||||
it("should decode", function() {
|
it("should decode", function() {
|
||||||
|
@ -143,7 +144,7 @@ describe("Common structures", function() {
|
||||||
ttl: 100,
|
ttl: 100,
|
||||||
type: 2,
|
type: 2,
|
||||||
version: 1,
|
version: 1,
|
||||||
payload: Buffer("test"),
|
objectPayload: Buffer("test"),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
expect(bufferEqual(nonce, res.nonce)).to.be.true;
|
expect(bufferEqual(nonce, res.nonce)).to.be.true;
|
||||||
|
@ -152,7 +153,7 @@ describe("Common structures", function() {
|
||||||
expect(res.version).to.equal(1);
|
expect(res.version).to.equal(1);
|
||||||
expect(res.stream).to.equal(1);
|
expect(res.stream).to.equal(1);
|
||||||
expect(res.headerLength).to.equal(22);
|
expect(res.headerLength).to.equal(22);
|
||||||
expect(res.payload.toString()).to.equal("test");
|
expect(res.objectPayload.toString()).to.equal("test");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shouldn't encode too big TTL", function() {
|
it("shouldn't encode too big TTL", function() {
|
||||||
|
@ -161,7 +162,7 @@ describe("Common structures", function() {
|
||||||
ttl: 10000000,
|
ttl: 10000000,
|
||||||
type: 2,
|
type: 2,
|
||||||
version: 1,
|
version: 1,
|
||||||
payload: Buffer("test"),
|
objectPayload: Buffer("test"),
|
||||||
})).to.throw(Error);
|
})).to.throw(Error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -360,6 +361,7 @@ describe("Common structures", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO(Kagami): Add tests for encodePayload/decodePayload as well.
|
||||||
describe("Message types", function() {
|
describe("Message types", function() {
|
||||||
describe("version", function() {
|
describe("version", function() {
|
||||||
it("should encode and decode", function() {
|
it("should encode and decode", function() {
|
||||||
|
@ -485,14 +487,17 @@ describe("Message types", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO(Kagami): Add tests for encodePayloadAsync/decodePayloadAsync as well.
|
||||||
describe("Object types", function() {
|
describe("Object types", function() {
|
||||||
describe("getpubkey", function() {
|
describe("getpubkey", function() {
|
||||||
it("should encode and decode getpubkey v3", function() {
|
it("should encode and decode getpubkey v3", function() {
|
||||||
return getpubkey.encodeAsync({
|
return getpubkey.encodeAsync({
|
||||||
ttl: 100,
|
ttl: 100,
|
||||||
to: "BM-2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU",
|
to: "BM-2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU",
|
||||||
}).then(getpubkey.decodeAsync)
|
}).then(function(buf) {
|
||||||
.then(function(res) {
|
expect(message.decode(buf).command).to.equal("object");
|
||||||
|
return getpubkey.decodeAsync(buf);
|
||||||
|
}).then(function(res) {
|
||||||
expect(res.ttl).to.be.at.most(100);
|
expect(res.ttl).to.be.at.most(100);
|
||||||
expect(res.type).to.equal(object.GETPUBKEY);
|
expect(res.type).to.equal(object.GETPUBKEY);
|
||||||
expect(res.version).to.equal(3);
|
expect(res.version).to.equal(3);
|
||||||
|
@ -506,8 +511,10 @@ describe("Object types", function() {
|
||||||
return getpubkey.encodeAsync({
|
return getpubkey.encodeAsync({
|
||||||
ttl: 100,
|
ttl: 100,
|
||||||
to: "2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z",
|
to: "2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z",
|
||||||
}).then(getpubkey.decodeAsync)
|
}).then(function(buf) {
|
||||||
.then(function(res) {
|
expect(message.decode(buf).command).to.equal("object");
|
||||||
|
return getpubkey.decodeAsync(buf);
|
||||||
|
}).then(function(res) {
|
||||||
expect(res.ttl).to.be.at.most(100);
|
expect(res.ttl).to.be.at.most(100);
|
||||||
expect(res.type).to.equal(object.GETPUBKEY);
|
expect(res.type).to.equal(object.GETPUBKEY);
|
||||||
expect(res.version).to.equal(4);
|
expect(res.version).to.equal(4);
|
||||||
|
@ -533,8 +540,10 @@ describe("Object types", function() {
|
||||||
ttl: 123,
|
ttl: 123,
|
||||||
from: from,
|
from: from,
|
||||||
to: "BM-onhypnh1UMhbQpmvdiPuG6soLLytYJAfH",
|
to: "BM-onhypnh1UMhbQpmvdiPuG6soLLytYJAfH",
|
||||||
}).then(pubkey.decodeAsync)
|
}).then(function(buf) {
|
||||||
.then(function(res) {
|
expect(message.decode(buf).command).to.equal("object");
|
||||||
|
return pubkey.decodeAsync(buf);
|
||||||
|
}).then(function(res) {
|
||||||
expect(res.ttl).to.be.at.most(123);
|
expect(res.ttl).to.be.at.most(123);
|
||||||
expect(res.type).to.equal(object.PUBKEY);
|
expect(res.type).to.equal(object.PUBKEY);
|
||||||
expect(res.version).to.equal(2);
|
expect(res.version).to.equal(2);
|
||||||
|
@ -551,8 +560,10 @@ describe("Object types", function() {
|
||||||
ttl: 456,
|
ttl: 456,
|
||||||
from: from,
|
from: from,
|
||||||
to: "BM-2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU",
|
to: "BM-2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU",
|
||||||
}).then(pubkey.decodeAsync)
|
}).then(function(buf) {
|
||||||
.then(function(res) {
|
expect(message.decode(buf).command).to.equal("object");
|
||||||
|
return pubkey.decodeAsync(buf);
|
||||||
|
}).then(function(res) {
|
||||||
expect(res.ttl).to.be.at.most(456);
|
expect(res.ttl).to.be.at.most(456);
|
||||||
expect(res.type).to.equal(object.PUBKEY);
|
expect(res.type).to.equal(object.PUBKEY);
|
||||||
expect(res.version).to.equal(3);
|
expect(res.version).to.equal(3);
|
||||||
|
@ -569,6 +580,7 @@ describe("Object types", function() {
|
||||||
it("should encode and decode pubkey v4", function() {
|
it("should encode and decode pubkey v4", function() {
|
||||||
return pubkey.encodeAsync({ttl: 789, from: from, to: from})
|
return pubkey.encodeAsync({ttl: 789, from: from, to: from})
|
||||||
.then(function(buf) {
|
.then(function(buf) {
|
||||||
|
expect(message.decode(buf).command).to.equal("object");
|
||||||
return pubkey.decodeAsync(buf, {neededPubkeys: from});
|
return pubkey.decodeAsync(buf, {neededPubkeys: from});
|
||||||
}).then(function(res) {
|
}).then(function(res) {
|
||||||
expect(res.ttl).to.be.at.most(789);
|
expect(res.ttl).to.be.at.most(789);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user