Merge pull request #50 from braydonf/prevhash
Use prevHash from bitcoind block index
This commit is contained in:
commit
078577499b
@ -4,22 +4,22 @@ var BitcoindJS = require('..');
|
||||
var BitcoinNode = BitcoindJS.Node;
|
||||
var chainlib = require('chainlib');
|
||||
var log = chainlib.log;
|
||||
//log.debug = function() {};
|
||||
log.debug = function() {};
|
||||
|
||||
var configuration = {
|
||||
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
||||
network: 'testnet'
|
||||
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin'
|
||||
};
|
||||
|
||||
var node = new BitcoinNode(configuration);
|
||||
|
||||
var startHeight;
|
||||
var count = 100;
|
||||
var times = new Array(count);
|
||||
var count = 0;
|
||||
var interval;
|
||||
|
||||
node.on('ready', function() {
|
||||
times[node.chain.tip.__height % count] = Date.now();
|
||||
startHeight = node.chain.tip.__height;
|
||||
interval = setInterval(function() {
|
||||
log.info('Sync Status: Tip:', node.chain.tip.hash, 'Height:', node.chain.tip.__height, 'Rate:', count/10, 'blocks per second');
|
||||
count = 0;
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
node.on('error', function(err) {
|
||||
@ -27,13 +27,5 @@ node.on('error', function(err) {
|
||||
});
|
||||
|
||||
node.chain.on('addblock', function(block) {
|
||||
console.log('New Best Tip:', block.hash);
|
||||
var startTime = times[node.chain.tip.__height % count];
|
||||
|
||||
if(startTime) {
|
||||
var timeElapsed = (Date.now() - startTime) / 1000;
|
||||
console.log(Math.round(count / timeElapsed) + ' blocks per second');
|
||||
}
|
||||
|
||||
times[node.chain.tip.__height % count] = Date.now();
|
||||
count++;
|
||||
});
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -21,7 +22,7 @@ var assert = chai.assert;
|
||||
var sinon = require('sinon');
|
||||
var BitcoinRPC = require('bitcoind-rpc');
|
||||
var blockHashes = [];
|
||||
var unspentTransactions = [];
|
||||
var utxo;
|
||||
var coinbasePrivateKey;
|
||||
var privateKey = bitcore.PrivateKey();
|
||||
var destKey = bitcore.PrivateKey();
|
||||
@ -118,9 +119,22 @@ describe('Daemon Binding Functionality', function() {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var tx = bitcore.Transaction();
|
||||
tx.fromString(response.result.hex);
|
||||
unspentTransactions.push(tx);
|
||||
var unspentTransaction = bitcore.Transaction();
|
||||
var outputIndex;
|
||||
unspentTransaction.fromString(response.result.hex);
|
||||
for (var i = 0; i < unspentTransaction.outputs.length; i++) {
|
||||
var output = unspentTransaction.outputs[i];
|
||||
if (output.script.toAddress(network).toString() === address.toString(network)) {
|
||||
outputIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
utxo = {
|
||||
txid: unspentTransaction.hash,
|
||||
outputIndex: outputIndex,
|
||||
script: unspentTransaction.outputs[outputIndex].script,
|
||||
satoshis: unspentTransaction.outputs[outputIndex].satoshis
|
||||
};
|
||||
|
||||
// Include this transaction in a block so that it can
|
||||
// be spent in tests
|
||||
@ -150,7 +164,7 @@ describe('Daemon Binding Functionality', function() {
|
||||
describe('mempool functionality', function() {
|
||||
|
||||
var fromAddress = 'mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1';
|
||||
var utxo = {
|
||||
var utxo1 = {
|
||||
address: fromAddress,
|
||||
txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
|
||||
outputIndex: 0,
|
||||
@ -160,14 +174,14 @@ describe('Daemon Binding Functionality', function() {
|
||||
var toAddress = 'mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc';
|
||||
var changeAddress = 'mgBCJAsvzgT2qNNeXsoECg2uPKrUsZ76up';
|
||||
var changeAddressP2SH = '2N7T3TAetJrSCruQ39aNrJvYLhG1LJosujf';
|
||||
var privateKey = 'cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY';
|
||||
var privateKey1 = 'cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY';
|
||||
var private1 = '6ce7e97e317d2af16c33db0b9270ec047a91bff3eff8558afb5014afb2bb5976';
|
||||
var private2 = 'c9b26b0f771a0d2dad88a44de90f05f416b3b385ff1d989343005546a0032890';
|
||||
var tx = new bitcore.Transaction();
|
||||
tx.from(utxo);
|
||||
tx.from(utxo1);
|
||||
tx.to(toAddress, 50000);
|
||||
tx.change(changeAddress);
|
||||
tx.sign(privateKey);
|
||||
tx.sign(privateKey1);
|
||||
|
||||
it('will add an unchecked transaction', function() {
|
||||
var added = bitcoind.addMempoolUncheckedTransaction(tx.serialize());
|
||||
@ -233,19 +247,26 @@ 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]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('send transaction functionality', function() {
|
||||
|
||||
it('will not error and return the transaction hash', function() {
|
||||
|
||||
var unspentTx = unspentTransactions.shift();
|
||||
|
||||
var utxo = {
|
||||
txid: unspentTx.hash,
|
||||
outputIndex: 1,
|
||||
script: unspentTx.outputs[1].script,
|
||||
satoshis: unspentTx.outputs[1].satoshis
|
||||
};
|
||||
|
||||
// create and sign the transaction
|
||||
var tx = bitcore.Transaction();
|
||||
tx.from(utxo);
|
||||
|
||||
@ -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'));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
21
lib/db.js
21
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);
|
||||
|
||||
@ -209,7 +209,7 @@ Node.prototype._loadConsensus = function(config) {
|
||||
var genesisBlock;
|
||||
if (config.genesis) {
|
||||
genesisBlock = config.genesis;
|
||||
} else if (config.testnet) {
|
||||
} else if (config.network === 'testnet') {
|
||||
genesisBlock = genesis.testnet;
|
||||
} else {
|
||||
genesisBlock = genesis.livenet;
|
||||
|
||||
@ -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<Value>::New(isolate, NanNew<String>(cw.GetHex())));
|
||||
CBlockIndex* prevBlockIndex = blockIndex->pprev;
|
||||
const uint256* prevHash = prevBlockIndex->phashBlock;
|
||||
|
||||
Local<Object> obj = NanNew<Object>();
|
||||
|
||||
obj->Set(NanNew<String>("chainWork"), NanNew<String>(cw.GetHex()));
|
||||
obj->Set(NanNew<String>("prevHash"), NanNew<String>(prevHash->GetHex()));
|
||||
|
||||
NanReturnValue(obj);
|
||||
}
|
||||
|
||||
};
|
||||
@ -1229,7 +1239,7 @@ init(Handle<Object> 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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@ -309,7 +309,7 @@ describe('Bitcoind Node', function() {
|
||||
});
|
||||
it('should use the testnet genesis if testnet is specified', function() {
|
||||
var config = {
|
||||
testnet: true
|
||||
network: 'testnet'
|
||||
};
|
||||
node._loadConsensus(config);
|
||||
should.exist(node.chain);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user