Check objects POW
This commit is contained in:
parent
25d5b70bae
commit
56679a0f8f
|
@ -73,26 +73,28 @@ var getpubkey = exports.getpubkey = {
|
|||
/**
|
||||
* Decode `getpubkey` object message.
|
||||
* @param {Buffer} buf - Message
|
||||
* @param {?Object} opts - Decoding options
|
||||
* @return {Promise.<Object>} A promise that contains decoded
|
||||
* `getpubkey` object structure when fulfilled.
|
||||
*/
|
||||
decodeAsync: function(buf) {
|
||||
decodeAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = message.decode(buf);
|
||||
assert(decoded.command === "object", "Bad command");
|
||||
resolve(getpubkey.decodePayloadAsync(decoded.payload));
|
||||
resolve(getpubkey.decodePayloadAsync(decoded.payload, opts));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Decode `getpubkey` object message payload.
|
||||
* @param {Buffer} buf - Message payload
|
||||
* @param {?Object} opts - Decoding options
|
||||
* @return {Promise.<Object>} A promise that contains decoded
|
||||
* `getpubkey` object structure when fulfilled.
|
||||
*/
|
||||
decodePayloadAsync: function(buf) {
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = object.decodePayload(buf);
|
||||
var decoded = object.decodePayload(buf, opts);
|
||||
assert(decoded.type === object.GETPUBKEY, "Wrong object type");
|
||||
assert(decoded.version >= 2, "getpubkey version is too low");
|
||||
assert(decoded.version <= 4, "getpubkey version is too high");
|
||||
|
@ -242,7 +244,7 @@ var pubkey = exports.pubkey = {
|
|||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
opts = opts || {};
|
||||
var decoded = object.decodePayload(buf);
|
||||
var decoded = object.decodePayload(buf, opts);
|
||||
assert(decoded.type === object.PUBKEY, "Wrong object type");
|
||||
var version = decoded.version;
|
||||
assert(version >= 2, "Address version is too low");
|
||||
|
@ -552,7 +554,7 @@ var msg = exports.msg = {
|
|||
*/
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = object.decodePayload(buf);
|
||||
var decoded = object.decodePayload(buf, opts);
|
||||
assert(decoded.type === object.MSG, "Bad object type");
|
||||
assert(decoded.version === 1, "Bad msg version");
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
|
@ -738,7 +740,7 @@ var DEFAULT_ENCODING = msg.TRIVIAL;
|
|||
function tryDecryptBroadcastV4(subscriptions, buf) {
|
||||
function inner(i) {
|
||||
if (i > last) {
|
||||
var err = new Error("Failed to decrypt msg with given identities");
|
||||
var err = new Error("Failed to decrypt broadcast with given identities");
|
||||
return promise.reject(err);
|
||||
}
|
||||
return bmcrypto
|
||||
|
@ -801,7 +803,7 @@ var broadcast = exports.broadcast = {
|
|||
*/
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = object.decodePayload(buf);
|
||||
var decoded = object.decodePayload(buf, opts);
|
||||
assert(decoded.type === object.BROADCAST, "Bad object type");
|
||||
var version = decoded.version;
|
||||
assert(version === 4 || version === 5, "Bad broadcast version");
|
||||
|
|
|
@ -45,7 +45,6 @@ exports.randomBytes = function(size) {
|
|||
var B80 = new BN("1208925819614629174706176");
|
||||
exports.getTarget = function(opts) {
|
||||
var length = new BN(opts.payloadLength);
|
||||
length.iaddn(8);
|
||||
length.iaddn(opts.payloadLengthExtraBytes);
|
||||
var denominator = new BN(opts.ttl);
|
||||
denominator.iaddn(65536);
|
||||
|
|
|
@ -43,10 +43,7 @@ exports.getTarget = function(opts) {
|
|||
// Slightly rearrange calculations and compute it bottom-up,
|
||||
// right-to-left. See also:
|
||||
// <https://github.com/Bitmessage/PyBitmessage/issues/758>.
|
||||
var length = bignum(opts.payloadLength)
|
||||
// To account for the nonce which we will append later.
|
||||
.add(8)
|
||||
.add(opts.payloadLengthExtraBytes);
|
||||
var length = bignum(opts.payloadLength).add(opts.payloadLengthExtraBytes);
|
||||
var denominator = bignum(opts.ttl)
|
||||
.add(65536)
|
||||
.mul(length)
|
||||
|
|
|
@ -36,9 +36,9 @@ exports.getTarget = function(opts) {
|
|||
exports.check = function(opts) {
|
||||
var initialHash;
|
||||
var nonce;
|
||||
if (opts.data) {
|
||||
nonce = opts.data.slice(0, 8);
|
||||
initialHash = bmcrypto.sha512(opts.data.slice(8));
|
||||
if (opts.payload) {
|
||||
nonce = opts.payload.slice(0, 8);
|
||||
initialHash = bmcrypto.sha512(opts.payload.slice(8));
|
||||
} else {
|
||||
if (typeof opts.nonce === "number") {
|
||||
nonce = new Buffer(8);
|
||||
|
|
|
@ -11,6 +11,7 @@ var objectAssign = Object.assign || require("object-assign");
|
|||
var bufferEqual = require("buffer-equal");
|
||||
var assert = require("./_util").assert;
|
||||
var bmcrypto = require("./crypto");
|
||||
var POW = require("./pow");
|
||||
var util = require("./_util");
|
||||
|
||||
function isAscii(str) {
|
||||
|
@ -112,42 +113,54 @@ var object = exports.object = {
|
|||
* Decode `object` message.
|
||||
* NOTE: `nonce` and `objectPayload` are copied.
|
||||
* @param {Buffer} buf - Message
|
||||
* @param {?Object} opts - Decoding options
|
||||
* @return {Object} Decoded `object` structure.
|
||||
*/
|
||||
decode: function(buf) {
|
||||
decode: function(buf, opts) {
|
||||
var decoded = message.decode(buf);
|
||||
assert(decoded.command === "object", "Bad command");
|
||||
return object.decodePayload(decoded.payload);
|
||||
return object.decodePayload(decoded.payload, opts);
|
||||
},
|
||||
|
||||
/**
|
||||
* Decode `object` message payload.
|
||||
* NOTE: `nonce` and `objectPayload` are copied.
|
||||
* @param {Buffer} buf - Message payload
|
||||
* @param {?Object} opts - Decoding options
|
||||
* @return {Object} Decoded `object` structure.
|
||||
*/
|
||||
// FIXME(Kagami): Check a POW.
|
||||
// TODO(Kagami): Allow lower POW for friends.
|
||||
// TODO(Kagami): Option to not fail on bad POW (may be useful for
|
||||
// bitchan).
|
||||
// TODO(Kagami): Option to not fail on expired objects (would be
|
||||
// useful for bitchan).
|
||||
decodePayload: function(buf) {
|
||||
decodePayload: function(buf, opts) {
|
||||
opts = opts || {};
|
||||
// 8 + 8 + 4 + (1+) + (1+)
|
||||
assert(buf.length >= 22, "object message payload is too small");
|
||||
assert(buf.length <= 262144, "object message payload is too big");
|
||||
var nonce = new Buffer(8);
|
||||
buf.copy(nonce, 0, 0, 8);
|
||||
|
||||
// TTL.
|
||||
var expiresTime = util.readTimestamp64BE(buf.slice(8, 16));
|
||||
var ttl = expiresTime - util.tnow();
|
||||
assert(ttl >= -3600, "Object expired more than a hour ago");
|
||||
assert(ttl <= 2430000, "expiresTime is too far in the future");
|
||||
if (!opts.allowExpired) {
|
||||
assert(ttl >= -3600, "Object expired more than a hour ago");
|
||||
}
|
||||
|
||||
// POW.
|
||||
if (!opts.skipPow) {
|
||||
// User may specify trials/payload extra options and we will
|
||||
// account in here.
|
||||
var targetOpts = objectAssign({}, opts, {ttl: ttl, payload: buf});
|
||||
var target = POW.getTarget(targetOpts);
|
||||
assert(POW.check({target: target, payload: buf}), "Insufficient POW");
|
||||
}
|
||||
|
||||
var type = buf.readUInt32BE(16, true);
|
||||
var decodedVersion = var_int.decode(buf.slice(20));
|
||||
var decodedStream = var_int.decode(decodedVersion.rest);
|
||||
var headerLength = 20 + decodedVersion.length + decodedStream.length;
|
||||
var objectPayload = new Buffer(decodedStream.rest.length);
|
||||
decodedStream.rest.copy(objectPayload);
|
||||
|
||||
return {
|
||||
nonce: nonce,
|
||||
ttl: ttl,
|
||||
|
|
43
test.js
43
test.js
|
@ -33,6 +33,8 @@ var POW = bitmessage.POW;
|
|||
var Address = bitmessage.Address;
|
||||
var UserAgent = bitmessage.UserAgent;
|
||||
|
||||
var skipPow = {skipPow: true};
|
||||
|
||||
describe("Crypto", function() {
|
||||
it("should implement SHA-1 hash", function() {
|
||||
expect(bmcrypto.sha1(Buffer("test")).toString("hex")).to.equal("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3");
|
||||
|
@ -147,7 +149,7 @@ describe("Common structures", function() {
|
|||
type: 2,
|
||||
version: 1,
|
||||
objectPayload: Buffer("test"),
|
||||
}));
|
||||
}), skipPow);
|
||||
|
||||
expect(bufferEqual(nonce, res.nonce)).to.be.true;
|
||||
expect(res.ttl).to.be.at.most(100);
|
||||
|
@ -570,7 +572,7 @@ describe("Object types", function() {
|
|||
to: "BM-2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return getpubkey.decodeAsync(buf);
|
||||
return getpubkey.decodeAsync(buf, skipPow);
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(100);
|
||||
expect(res.type).to.equal(object.GETPUBKEY);
|
||||
|
@ -587,7 +589,7 @@ describe("Object types", function() {
|
|||
to: "2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return getpubkey.decodeAsync(buf);
|
||||
return getpubkey.decodeAsync(buf, skipPow);
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(100);
|
||||
expect(res.type).to.equal(object.GETPUBKEY);
|
||||
|
@ -607,7 +609,7 @@ describe("Object types", function() {
|
|||
to: "BM-onhypnh1UMhbQpmvdiPuG6soLLytYJAfH",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return pubkey.decodeAsync(buf);
|
||||
return pubkey.decodeAsync(buf, skipPow);
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(123);
|
||||
expect(res.type).to.equal(object.PUBKEY);
|
||||
|
@ -627,7 +629,7 @@ describe("Object types", function() {
|
|||
to: "BM-2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return pubkey.decodeAsync(buf);
|
||||
return pubkey.decodeAsync(buf, skipPow);
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(456);
|
||||
expect(res.type).to.equal(object.PUBKEY);
|
||||
|
@ -646,7 +648,7 @@ describe("Object types", function() {
|
|||
return pubkey.encodeAsync({ttl: 789, from: from, to: from})
|
||||
.then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return pubkey.decodeAsync(buf, {needed: from});
|
||||
return pubkey.decodeAsync(buf, {needed: from, skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(789);
|
||||
expect(res.type).to.equal(object.PUBKEY);
|
||||
|
@ -672,7 +674,7 @@ describe("Object types", function() {
|
|||
message: "test",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return msg.decodeAsync(buf, {identities: [from]});
|
||||
return msg.decodeAsync(buf, {identities: [from], skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(111);
|
||||
expect(res.type).to.equal(object.MSG);
|
||||
|
@ -701,7 +703,7 @@ describe("Object types", function() {
|
|||
message: "test",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return msg.decodeAsync(buf, {identities: [fromV2]});
|
||||
return msg.decodeAsync(buf, {identities: [fromV2], skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(111);
|
||||
expect(res.type).to.equal(object.MSG);
|
||||
|
@ -729,8 +731,9 @@ describe("Object types", function() {
|
|||
to: from,
|
||||
message: "test",
|
||||
}).then(function(buf) {
|
||||
return msg.decodeAsync(buf, {identities: []});
|
||||
}).catch(function() {
|
||||
return msg.decodeAsync(buf, {identities: [], skipPow: true});
|
||||
}).catch(function(err) {
|
||||
expect(err.message).to.match(/with given identities/i);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -744,7 +747,7 @@ describe("Object types", function() {
|
|||
subject: "Тема",
|
||||
message: "Сообщение",
|
||||
}).then(function(buf) {
|
||||
return msg.decodeAsync(buf, {identities: [from]});
|
||||
return msg.decodeAsync(buf, {identities: [from], skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.encoding).to.equal(msg.SIMPLE);
|
||||
expect(res.subject).to.equal("Тема");
|
||||
|
@ -773,7 +776,7 @@ describe("Object types", function() {
|
|||
message: "test",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return broadcast.decodeAsync(buf, {subscriptions: fromV3});
|
||||
return broadcast.decodeAsync(buf, {subscriptions: fromV3, skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(987);
|
||||
expect(res.type).to.equal(object.BROADCAST);
|
||||
|
@ -800,7 +803,7 @@ describe("Object types", function() {
|
|||
message: "test",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return broadcast.decodeAsync(buf, {subscriptions: fromV2});
|
||||
return broadcast.decodeAsync(buf, {subscriptions: fromV2, skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(999);
|
||||
expect(res.type).to.equal(object.BROADCAST);
|
||||
|
@ -827,7 +830,7 @@ describe("Object types", function() {
|
|||
message: "キタ━━━(゜∀゜)━━━!!!!!",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return broadcast.decodeAsync(buf, {subscriptions: [from]});
|
||||
return broadcast.decodeAsync(buf, {subscriptions: [from], skipPow: true});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(987);
|
||||
expect(res.type).to.equal(object.BROADCAST);
|
||||
|
@ -853,8 +856,12 @@ describe("Object types", function() {
|
|||
from: from,
|
||||
message: "test",
|
||||
}).then(function(buf) {
|
||||
return broadcast.decodeAsync(buf, {subscriptions: [fromV3]});
|
||||
}).catch(function() {
|
||||
return broadcast.decodeAsync(buf, {
|
||||
subscriptions: [fromV3],
|
||||
skipPow: true,
|
||||
});
|
||||
}).catch(function(err) {
|
||||
expect(err.message).to.match(/not interested/i);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -901,8 +908,8 @@ describe("WIF", function() {
|
|||
|
||||
describe("POW", function() {
|
||||
it("should calculate target", function() {
|
||||
expect(POW.getTarget({ttl: 2418984, payloadLength: 628, nonceTrialsPerByte: 1000, payloadLengthExtraBytes: 1000})).to.equal(297422525267);
|
||||
expect(POW.getTarget({ttl: 86400, payloadLength: 628})).to.equal(4863575534951);
|
||||
expect(POW.getTarget({ttl: 2418984, payloadLength: 636, nonceTrialsPerByte: 1000, payloadLengthExtraBytes: 1000})).to.equal(297422525267);
|
||||
expect(POW.getTarget({ttl: 86400, payloadLength: 636})).to.equal(4863575534951);
|
||||
});
|
||||
|
||||
it("should check a POW", function() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user