From 7b8268d0e03e13d2a220718aefe0014413feec87 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 22 Jul 2015 15:34:15 -0400 Subject: [PATCH] Use prevHash from bitcoind block index - Changed method getChainWork into getBlockIndex - Added prevHash to getBlockIndex result --- integration/regtest.js | 17 +++++++++++++++++ lib/chain.js | 7 ++++--- lib/daemon.js | 4 ++-- lib/db.js | 21 ++++++++++++++++++--- src/bitcoindjs.cc | 24 +++++++++++++++++------- src/bitcoindjs.h | 2 +- test/chain.unit.js | 8 +++++--- test/db.unit.js | 4 +--- 8 files changed, 65 insertions(+), 22 deletions(-) diff --git a/integration/regtest.js b/integration/regtest.js index d71010b4..66adff3a 100644 --- a/integration/regtest.js +++ b/integration/regtest.js @@ -12,6 +12,7 @@ if (process.env.BITCOINDJS_ENV !== 'test') { var chai = require('chai'); var bitcore = require('bitcore'); +var BN = bitcore.crypto.BN; var rimraf = require('rimraf'); var bitcoind; @@ -261,4 +262,20 @@ describe('Daemon Binding Functionality', function() { }); + describe('get block index', function() { + var expectedWork = new BN(6); + [1,2,3,4,5,6,7,8,9].forEach(function(i) { + it('generate block ' + i, function() { + var blockIndex = bitcoind.getBlockIndex(blockHashes[i]); + should.exist(blockIndex); + should.exist(blockIndex.chainWork); + var work = new BN(blockIndex.chainWork, 'hex'); + work.cmp(expectedWork).should.equal(0); + expectedWork = expectedWork.add(new BN(2)); + should.exist(blockIndex.prevHash); + blockIndex.prevHash.should.equal(blockHashes[i - 1]); + }); + }); + }); + }); diff --git a/lib/chain.js b/lib/chain.js index b8cb942d..f9e7c200 100644 --- a/lib/chain.js +++ b/lib/chain.js @@ -85,13 +85,14 @@ Chain.prototype.buildGenesisBlock = function buildGenesisBlock(options) { Chain.prototype.getWeight = function getWeight(blockHash, callback) { var self = this; + var blockIndex = self.db.bitcoind.getBlockIndex(blockHash); setImmediate(function() { - var weight = self.db.bitcoind.getChainWork(blockHash); - if(weight === undefined) { + if (blockIndex) { + callback(null, new BN(blockIndex.chainWork, 'hex')); + } else { return callback(new Error('Weight not found for ' + blockHash)); } - callback(null, new BN(weight, 'hex')); }); }; diff --git a/lib/daemon.js b/lib/daemon.js index e5487e40..b2aaa3f2 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -340,8 +340,8 @@ Daemon.prototype.isSpent = function(txid, outputIndex) { return bitcoindjs.isSpent(txid, outputIndex); }; -Daemon.prototype.getChainWork = function(blockHash) { - return bitcoindjs.getChainWork(blockHash); +Daemon.prototype.getBlockIndex = function(blockHash) { + return bitcoindjs.getBlockIndex(blockHash); }; Daemon.prototype.sendTransaction = function(transaction, allowAbsurdFees) { diff --git a/lib/db.js b/lib/db.js index de7939fc..f950ca78 100644 --- a/lib/db.js +++ b/lib/db.js @@ -46,10 +46,20 @@ DB.prototype.getBlock = function(hash, callback) { }); }; +DB.prototype.getPrevHash = function(blockHash, callback) { + var blockIndex = this.bitcoind.getBlockIndex(blockHash); + setImmediate(function() { + if (blockIndex) { + callback(null, blockIndex.prevHash); + } else { + callback(new Error('Could not get prevHash, block not found')); + } + }); +}; + DB.prototype.putBlock = function(block, callback) { - // block is already stored in bitcoind, but we need to update - // our prevhash index still - this._updatePrevHashIndex(block, callback); + // block is already stored in bitcoind + setImmediate(callback); }; DB.prototype.getTransaction = function(txid, queryMempool, callback) { @@ -67,6 +77,11 @@ DB.prototype.validateBlockData = function(block, callback) { setImmediate(callback); }; +DB.prototype._updatePrevHashIndex = function(block, callback) { + // bitcoind has the previous hash for each block + setImmediate(callback); +}; + DB.prototype._updateWeight = function(hash, weight, callback) { // bitcoind has all work for each block setImmediate(callback); diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index c569d54b..454c61e5 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -980,12 +980,14 @@ NAN_METHOD(IsSpent) { }; /** - * GetChainWork() - * bitcoindjs.getChainWork() - * Get the total amount of work (expected number of hashes) in the chain up to - * and including this block. + * GetBlockIndex() + * bitcoindjs.getBlockIndex() + * Get index information about a block by hash including: + * - the total amount of work (expected number of hashes) in the chain up to + * and including this block. + * - the previous hash of the block */ -NAN_METHOD(GetChainWork) { +NAN_METHOD(GetBlockIndex) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -1000,7 +1002,15 @@ NAN_METHOD(GetChainWork) { } else { blockIndex = mapBlockIndex[hash]; arith_uint256 cw = blockIndex->nChainWork; - NanReturnValue(Local::New(isolate, NanNew(cw.GetHex()))); + CBlockIndex* prevBlockIndex = blockIndex->pprev; + const uint256* prevHash = prevBlockIndex->phashBlock; + + Local obj = NanNew(); + + obj->Set(NanNew("chainWork"), NanNew(cw.GetHex())); + obj->Set(NanNew("prevHash"), NanNew(prevHash->GetHex())); + + NanReturnValue(obj); } }; @@ -1229,7 +1239,7 @@ init(Handle target) { NODE_SET_METHOD(target, "getTransaction", GetTransaction); NODE_SET_METHOD(target, "getInfo", GetInfo); NODE_SET_METHOD(target, "isSpent", IsSpent); - NODE_SET_METHOD(target, "getChainWork", GetChainWork); + NODE_SET_METHOD(target, "getBlockIndex", GetBlockIndex); NODE_SET_METHOD(target, "getMempoolOutputs", GetMempoolOutputs); NODE_SET_METHOD(target, "addMempoolUncheckedTransaction", AddMempoolUncheckedTransaction); NODE_SET_METHOD(target, "verifyScript", VerifyScript); diff --git a/src/bitcoindjs.h b/src/bitcoindjs.h index 050d6830..c863e226 100644 --- a/src/bitcoindjs.h +++ b/src/bitcoindjs.h @@ -23,7 +23,7 @@ NAN_METHOD(GetBlock); NAN_METHOD(GetTransaction); NAN_METHOD(GetInfo); NAN_METHOD(IsSpent); -NAN_METHOD(GetChainWork); +NAN_METHOD(GetBlockIndex); NAN_METHOD(GetMempoolOutputs); NAN_METHOD(AddMempoolUncheckedTransaction); NAN_METHOD(VerifyScript); diff --git a/test/chain.unit.js b/test/chain.unit.js index 78ea3097..9d463005 100644 --- a/test/chain.unit.js +++ b/test/chain.unit.js @@ -93,20 +93,22 @@ describe('Bitcoin Chain', function() { var chain = new Chain(); chain.db = { bitcoind: { - getChainWork: sinon.stub().returns(work) + getBlockIndex: sinon.stub().returns({ + chainWork: work + }) } }; it('should give the weight as a BN', function(done) { chain.getWeight('hash', function(err, weight) { should.not.exist(err); - weight.toString(16).should.equal('5a7b3c42ea8b844374e9'); + weight.toString(16, 64).should.equal(work); done(); }); }); it('should give an error if the weight is undefined', function(done) { - chain.db.bitcoind.getChainWork = sinon.stub().returns(undefined); + chain.db.bitcoind.getBlockIndex = sinon.stub().returns(undefined); chain.getWeight('hash2', function(err, weight) { should.exist(err); done(); diff --git a/test/db.unit.js b/test/db.unit.js index d4334fb5..580f5292 100644 --- a/test/db.unit.js +++ b/test/db.unit.js @@ -42,12 +42,10 @@ describe('Bitcoin DB', function() { }); describe('#putBlock', function() { - it('should call _updatePrevHashIndex', function(done) { + it('should call callback', function(done) { var db = new DB({store: memdown}); - db._updatePrevHashIndex = sinon.stub().callsArg(1); db.putBlock('block', function(err) { should.not.exist(err); - db._updatePrevHashIndex.called.should.equal(true); done(); }); });