Calculate POW target

This commit is contained in:
Kagami Hiiragi 2015-01-08 00:28:13 +03:00
parent 8c2f180037
commit a7eb439706
5 changed files with 90 additions and 3 deletions

View File

@ -5,6 +5,8 @@
"use strict";
var hash = require("hash.js");
var BN = require("bn.js");
var assert = require("./util").assert;
exports.sha512 = function(buf) {
return new Buffer(hash.sha512().update(buf).digest());
@ -23,3 +25,19 @@ exports.randomBytes = function(size) {
window.crypto.getRandomValues(arr);
return new Buffer(arr);
};
var B64 = new BN("18446744073709551616");
exports.getTarget = function(opts) {
var length = new BN(opts.payloadLength);
length.iaddn(8);
length.iaddn(opts.payloadLengthExtraBytes);
var denominator = new BN(opts.ttl);
denominator.imul(length);
denominator.idivn(65536);
denominator.iadd(length);
denominator.imul(new BN(opts.nonceTrialsPerByte));
var target = parseInt(B64.div(denominator).toString(16), 16);
assert(target <= 9007199254740991, "Unsafe target");
return target;
};

View File

@ -5,6 +5,9 @@
"use strict";
var crypto = require("crypto");
var bignum = require("bignum");
var assert = require("./util").assert;
var createHash = crypto.createHash;
exports.sha512 = function(buf) {
@ -20,3 +23,25 @@ exports.ripemd160 = function(buf) {
};
exports.randomBytes = crypto.randomBytes;
// 2^64.
var B64 = bignum("18446744073709551616");
// 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.
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)
.mul(length)
.div(65536)
.add(length)
.mul(opts.nonceTrialsPerByte);
var target = B64.div(denominator).toNumber();
assert(target <= 9007199254740991, "Unsafe target");
return target;
};

View File

@ -3,3 +3,34 @@
* @see {@link https://bitmessage.org/wiki/Proof_of_work}
* @module bitmessage/pow
*/
"use strict";
var platform = require("./platform");
var DEFAULT_TRIALS_PER_BYTE = 1000;
var DEFAULT_EXTRA_BYTES = 1000;
/**
* Calculate target
* @param {{ttl: number, payloadLength: number}} opts - Target options
* @return {number} Target.
*/
// Just a wrapper around platform-specific implementation.
exports.getTarget = function(opts) {
var nonceTrialsPerByte = opts.nonceTrialsPerByte;
// Automatically raise lower values per spec.
if (!nonceTrialsPerByte || nonceTrialsPerByte < DEFAULT_TRIALS_PER_BYTE) {
nonceTrialsPerByte = DEFAULT_TRIALS_PER_BYTE;
}
var payloadLengthExtraBytes = opts.payloadLengthExtraBytes;
if (!payloadLengthExtraBytes || payloadLengthExtraBytes < DEFAULT_EXTRA_BYTES) {
payloadLengthExtraBytes = DEFAULT_EXTRA_BYTES;
}
return platform.getTarget({
ttl: opts.ttl,
payloadLength: opts.payloadLength,
nonceTrialsPerByte: nonceTrialsPerByte,
payloadLengthExtraBytes: payloadLengthExtraBytes,
});
};

View File

@ -7,7 +7,7 @@
"./lib/platform.js": "./lib/platform.browser.js"
},
"scripts": {
"test": "ALL_TESTS=1 mocha && xvfb-run -a karma start && jshint .",
"test": "ALL_TESTS=1 mocha && ALL_TESTS=1 xvfb-run -a karma start && jshint .",
"m": "mocha",
"k": "xvfb-run -a karma start",
"kc": "xvfb-run -a karma start --browsers Chromium",
@ -46,10 +46,13 @@
"mocha": "*"
},
"dependencies": {
"bignum": "^0.9.0",
"bn.js": "^1.0.0",
"bs58": "^2.0.0",
"buffer-equal": "~0.0.1",
"eccrypto": "^0.1.2",
"hash.js": "^1.0.2",
"object-assign": "^2.0.0"
"object-assign": "^2.0.0",
"sha.js": "^2.3.0"
}
}

12
test.js
View File

@ -15,6 +15,7 @@ var messageEncodings = structs.messageEncodings;
var serviceFeatures = structs.serviceFeatures;
var pubkeyFeatures = structs.pubkeyFeatures;
var WIF = bitmessage.WIF;
var POW = bitmessage.POW;
var Address = bitmessage.Address;
describe("Crypto", function() {
@ -263,6 +264,13 @@ 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);
});
});
describe("High-level classes", function() {
// FIXME(Kagami): Add more fail tests.
describe("Address", function() {
@ -296,7 +304,9 @@ describe("High-level classes", function() {
expect(addr2.ripe[0]).to.equal(0);
});
if (allTests) {
// FIXME(Kagami): Don't run it in browser currently because it's
// very slow. This need to be fixed.
if (allTests && typeof window === "undefined") {
it("should allow to generate shorter address", function() {
this.timeout(60000);
var addr = Address.fromRandom({ripelen: 18});