From 9407e27529647775fb78e88b4888041dcb4a27a3 Mon Sep 17 00:00:00 2001 From: Kagami Hiiragi Date: Thu, 8 Jan 2015 16:47:29 +0300 Subject: [PATCH] Check a POW --- lib/address.js | 4 ++-- lib/pow.js | 45 +++++++++++++++++++++++++++++++++++++++++++-- lib/structs.js | 2 +- test.js | 6 ++++++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/lib/address.js b/lib/address.js index ce247ef..d798497 100644 --- a/lib/address.js +++ b/lib/address.js @@ -91,8 +91,8 @@ function keys2ripe(signKey, encKey) { } else { encPublicKey = encKey; } - var concat = Buffer.concat([signPublicKey, encPublicKey]); - return bmcrypto.ripemd160(bmcrypto.sha512(concat)); + var dataToHash = Buffer.concat([signPublicKey, encPublicKey]); + return bmcrypto.ripemd160(bmcrypto.sha512(dataToHash)); } /** diff --git a/lib/pow.js b/lib/pow.js index 622c134..a05ceb0 100644 --- a/lib/pow.js +++ b/lib/pow.js @@ -6,6 +6,7 @@ "use strict"; +var bmcrypto = require("./crypto"); var platform = require("./platform"); var DEFAULT_TRIALS_PER_BYTE = 1000; @@ -13,11 +14,13 @@ var DEFAULT_EXTRA_BYTES = 1000; /** * Calculate target - * @param {{ttl: number, payloadLength: number}} opts - Target options + * @param {Object} opts - Target options * @return {number} Target. */ +// TODO(Kagami): Find a way how to document object params properly. // Just a wrapper around platform-specific implementation. exports.getTarget = function(opts) { + var payloadLength = opts.payloadLength || opts.payload.length; var nonceTrialsPerByte = opts.nonceTrialsPerByte; // Automatically raise lower values per spec. if (!nonceTrialsPerByte || nonceTrialsPerByte < DEFAULT_TRIALS_PER_BYTE) { @@ -29,8 +32,46 @@ exports.getTarget = function(opts) { } return platform.getTarget({ ttl: opts.ttl, - payloadLength: opts.payloadLength, + payloadLength: payloadLength, nonceTrialsPerByte: nonceTrialsPerByte, payloadLengthExtraBytes: payloadLengthExtraBytes, }); }; + +/** + * Check a POW. + * @param {Object} opts - Proof of work options + * @return {boolean} Is the proof of work sufficient. + */ +exports.check = function(opts) { + var initialHash; + var nonce; + if (opts.data) { + nonce = opts.data.slice(0, 8); + initialHash = bmcrypto.sha512(opts.data.slice(8)); + } else { + if (typeof opts.nonce === "number") { + nonce = new Buffer(8); + // High 32 bits. + nonce.writeUInt32BE(Math.floor(opts.nonce / 4294967296), 0, true); + // Low 32 bits. + nonce.writeUInt32BE(opts.nonce % 4294967296, 4, true); + } else { + nonce = opts.nonce; + } + initialHash = opts.initialHash; + } + var targetHi = Math.floor(opts.target / 4294967296); + var targetLo = opts.target % 4294967296; + var dataToHash = Buffer.concat([nonce, initialHash]); + var resultHash = bmcrypto.sha512(bmcrypto.sha512(dataToHash)); + var trialHi = resultHash.readUInt32BE(0, true); + if (trialHi > targetHi) { + return false; + } else if (trialHi < targetHi) { + return true; + } else { + var trialLo = resultHash.readUInt32BE(4, true); + return trialLo <= targetLo; + } +}; diff --git a/lib/structs.js b/lib/structs.js index 49bdc88..9b4373d 100644 --- a/lib/structs.js +++ b/lib/structs.js @@ -173,7 +173,7 @@ var var_int = exports.var_int = { targetStart = 1 + (8 - value.length); value.copy(buf, targetStart); } else { - throw new Error("Value encode error"); + throw new Error("Unknown value type"); } return buf; }, diff --git a/test.js b/test.js index bc2a726..7c65395 100644 --- a/test.js +++ b/test.js @@ -272,6 +272,12 @@ describe("POW", 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); }); + + it("should check a POW", function() { + expect(POW.check({nonce: 21997550, target: 297422593171, 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; + }); }); describe("High-level classes", function() {