Fix target calculation

Relates: Bitmessage/PyBitmessage#758
This commit is contained in:
Kagami Hiiragi 2015-01-30 18:15:20 +03:00
parent e38c14239e
commit 25d5b70bae
3 changed files with 15 additions and 14 deletions

View File

@ -7,6 +7,7 @@
// `hash.js` is already required by
// `bitmessage -> eccrypto -> elliptic -> hash.js` so it won't add
// additional bytes to the bundle.
// See also: <https://github.com/indutny/elliptic/pull/26>.
var hash = require("hash.js");
// Use only one submodule from `sha.js` here and in worker because it's
// faster. It will add additional bytes to the bundle but not that much
@ -41,17 +42,16 @@ exports.randomBytes = function(size) {
};
// See `platform.js` for comments.
var B64 = new BN("18446744073709551616");
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);
denominator.imul(length);
denominator.idivn(65536);
denominator.iadd(length);
denominator.imul(new BN(opts.nonceTrialsPerByte));
var target = parseInt(B64.div(denominator).toString(16), 16);
var target = parseInt(B80.div(denominator).toString(16), 16);
assert(target <= 9007199254740991, "Unsafe target");
return target;
};

View File

@ -33,24 +33,25 @@ exports.ripemd160 = function(buf) {
exports.randomBytes = crypto.randomBytes;
// 2^64.
var B64 = bignum("18446744073709551616");
// 2^80.
var B80 = bignum("1208925819614629174706176");
// NOTE(Kagami): We can't calculate entire target in JavaScript but the
// result can be represented in native number type without losing
// precision (targets mainly much less than 2^53).
exports.getTarget = function(opts) {
// Calculate it bottom-up, right-to-left.
// 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 denominator = bignum(opts.ttl)
.add(65536)
.mul(length)
.div(65536)
.add(length)
.mul(opts.nonceTrialsPerByte);
var target = B64.div(denominator).toNumber();
var target = B80.div(denominator).toNumber();
assert(target <= 9007199254740991, "Unsafe target");
return target;
};

View File

@ -901,12 +901,12 @@ describe("WIF", function() {
describe("POW", function() {
it("should calculate target", function() {
expect(POW.getTarget({ttl: 2418984, payloadLength: 628, nonceTrialsPerByte: 1000, payloadLengthExtraBytes: 1000})).to.equal(297422593171);
expect(POW.getTarget({ttl: 86400, payloadLength: 628})).to.equal(4864647698763);
expect(POW.getTarget({ttl: 2418984, payloadLength: 628, nonceTrialsPerByte: 1000, payloadLengthExtraBytes: 1000})).to.equal(297422525267);
expect(POW.getTarget({ttl: 86400, payloadLength: 628})).to.equal(4863575534951);
});
it("should check a POW", function() {
expect(POW.check({nonce: 21997550, target: 297422593171, initialHash: Buffer("8ff2d685db89a0af2e3dbfd3f700ae96ef4d9a1eac72fd778bbb368c7510cddda349e03207e1c4965bd95c6f7265e8f1a481a08afab3874eaafb9ade09a10880", "hex")})).to.be.true;
expect(POW.check({nonce: 21997550, target: 297422525267, initialHash: Buffer("8ff2d685db89a0af2e3dbfd3f700ae96ef4d9a1eac72fd778bbb368c7510cddda349e03207e1c4965bd95c6f7265e8f1a481a08afab3874eaafb9ade09a10880", "hex")})).to.be.true;
expect(POW.check({nonce: 3122437, target: 4864647698763, initialHash: Buffer("8ff2d685db89a0af2e3dbfd3f700ae96ef4d9a1eac72fd778bbb368c7510cddda349e03207e1c4965bd95c6f7265e8f1a481a08afab3874eaafb9ade09a10880", "hex")})).to.be.true;
expect(POW.check({nonce: 3122436, target: 4864647698763, initialHash: Buffer("8ff2d685db89a0af2e3dbfd3f700ae96ef4d9a1eac72fd778bbb368c7510cddda349e03207e1c4965bd95c6f7265e8f1a481a08afab3874eaafb9ade09a10880", "hex")})).to.be.false;
});
@ -925,7 +925,7 @@ describe("POW", function() {
if (allTests) {
it("should do a POW", function() {
this.timeout(300000);
var target = typeof window === "undefined" ? 297422593171 : 10693764680411;
var target = typeof window === "undefined" ? 297422525267 : 10688385392246;
var initialHash = Buffer("8ff2d685db89a0af2e3dbfd3f700ae96ef4d9a1eac72fd778bbb368c7510cddda349e03207e1c4965bd95c6f7265e8f1a481a08afab3874eaafb9ade09a10880", "hex");
return POW.doAsync({target: target, initialHash: initialHash})
.then(function(nonce) {