bitcoind: wrap rpc errors as instances of error

This commit is contained in:
Braydon Fuller 2016-04-08 10:35:01 -04:00
parent 3ead5928a7
commit 82232c0f55
3 changed files with 57 additions and 33 deletions

View File

@ -183,24 +183,30 @@ Bitcoin.prototype._resetCaches = function() {
this.summaryCache.reset();
};
Bitcoin.prototype._wrapRPCError = function(errObj) {
var err = new Error(errObj.message);
err.code = errObj.code;
return err;
};
Bitcoin.prototype._initChain = function(callback) {
var self = this;
self.client.getBestBlockHash(function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
self.client.getBlock(response.result, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
self.height = response.result.height;
self.client.getBlockHash(0, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var blockhash = response.result;
self.getBlock(blockhash, function(err, block) {
@ -239,7 +245,7 @@ Bitcoin.prototype._zmqBlockHandler = function(node, message) {
self.tiphash = message.toString('hex');
node.client.getBlock(self.tiphash, function(err, response) {
if (err) {
return log.error(err);
return log.error(self._wrapRPCError(err));
}
self.height = response.result.height;
$.checkState(self.height >= 0);
@ -318,7 +324,7 @@ Bitcoin.prototype._checkReindex = function(node, callback) {
var interval = setInterval(function() {
node.client.syncPercentage(function(err, percentSynced) {
if (err) {
return log.error(err);
return log.error(self._wrapRPCError(err));
}
log.info('Bitcoin Core Daemon Reindex Percentage: ' + percentSynced.toFixed(2));
if (Math.round(percentSynced) >= 100) {
@ -339,15 +345,15 @@ Bitcoin.prototype._checkReindex = function(node, callback) {
Bitcoin.prototype._loadTipFromNode = function(node, callback) {
var self = this;
node.client.getBestBlockHash(function(err, response) {
if (err) {
if (!(err instanceof Error)) {
log.warn(err.message);
}
return callback(new Error('Could not connect to bitcoind RPC'));
if (err && err.code === -28) {
log.warn(err.message);
return callback(self._wrapRPCError(err));
} else if (err) {
return callback(self._wrapRPCError(err));
}
node.client.getBlock(response.result, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
self.height = response.result.height;
$.checkState(self.height >= 0);
@ -518,9 +524,10 @@ Bitcoin.prototype.isSynced = function(callback) {
* @returns {Number} An estimated percentage of the syncronization status
*/
Bitcoin.prototype.syncPercentage = function(callback) {
var self = this;
this.client.getBlockchainInfo(function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var percentSynced = response.result.verificationprogress * 100;
callback(null, percentSynced);
@ -542,7 +549,7 @@ Bitcoin.prototype.getAddressBalance = function(addressArg, options, callback) {
} else {
this.client.getAddressBalance({addresses: addresses}, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
self.balanceCache.set(cacheKey, response.result);
callback(null, response.result);
@ -565,7 +572,7 @@ Bitcoin.prototype.getAddressUnspentOutputs = function(addressArg, options, callb
} else {
self.client.getAddressUtxos({addresses: addresses}, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
self.utxosCache.set(cacheKey, response.result);
callback(null, response.result);
@ -614,7 +621,7 @@ Bitcoin.prototype.getAddressTxids = function(addressArg, options, callback) {
} else {
self.client.getAddressTxids({addresses: addresses}, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
response.result.reverse();
self.txidsCache.set(cacheKey, response.result);
@ -627,7 +634,7 @@ Bitcoin.prototype.getAddressTxids = function(addressArg, options, callback) {
if (queryMempool) {
self.client.getAddressMempool({addresses: addresses}, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
mempoolTxids = self._getTxidsFromMempool(response.result);
finish();
@ -850,7 +857,7 @@ Bitcoin.prototype.getAddressSummary = function(addressArg, options, callback) {
}
self.client.getAddressMempool({'addresses': [addressArg]}, function(err, response) {
if (err) {
return done(err);
return done(self._wrapRPCError(err));
}
mempoolTxids = self._getTxidsFromMempool(response.result);
summary.unconfirmedAppearances = mempoolTxids.length;
@ -895,7 +902,7 @@ Bitcoin.prototype.getBlock = function(blockArg, callback) {
function queryBlock(blockhash) {
self.client.getBlock(blockhash, false, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var blockObj = bitcore.Block.fromString(response.result);
self.blockCache.set(blockArg, blockObj);
@ -912,7 +919,7 @@ Bitcoin.prototype.getBlock = function(blockArg, callback) {
if (_.isNumber(blockArg)) {
self.client.getBlockHash(blockArg, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var blockhash = response.result;
queryBlock(blockhash);
@ -928,7 +935,7 @@ Bitcoin.prototype.getBlockHashesByTimestamp = function(high, low, callback) {
var self = this;
self.client.getBlockHashes(high, low, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
callback(null, response.result);
});
@ -954,7 +961,7 @@ Bitcoin.prototype.getBlockHeader = function(block, callback) {
if (err && response.error.code === -5) {
return callback(null, null);
} else if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
// TODO format response prevHash instead of previousblockhash, etc.
callback(null, response.result);
@ -966,7 +973,7 @@ Bitcoin.prototype.getBlockHeader = function(block, callback) {
if (err && response.error.code === -8) {
return callback(null, null);
} else if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var blockhash = response.result;
queryHeader(blockhash);
@ -982,9 +989,10 @@ Bitcoin.prototype.getBlockHeader = function(block, callback) {
* @returns {Number}
*/
Bitcoin.prototype.estimateFee = function(blocks, callback) {
var self = this;
this.client.estimateFee(blocks, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
callback(null, response.result);
});
@ -997,6 +1005,7 @@ Bitcoin.prototype.estimateFee = function(blocks, callback) {
* @param {Boolean} allowAbsurdFees - Enable large fees
*/
Bitcoin.prototype.sendTransaction = function(tx, allowAbsurdFees, callback) {
var self = this;
var txString;
if (tx instanceof Transaction) {
txString = tx.serialize();
@ -1010,7 +1019,7 @@ Bitcoin.prototype.sendTransaction = function(tx, allowAbsurdFees, callback) {
this.client.sendRawTransaction(txString, allowAbsurdFees, function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
callback(null, response.result);
});
@ -1035,7 +1044,7 @@ Bitcoin.prototype.getTransaction = function(txid, queryMempool, callback) {
if (err && response.error.code === -5) {
return callback(null, null);
} else if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var tx = Transaction();
tx.fromString(response.result);
@ -1066,11 +1075,10 @@ Bitcoin.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, cal
});
} else {
self.client.getRawTransaction(txid, 1, function(err, response) {
if (err) {
return callback(err);
}
if (!response.result) {
return callback(new errors.Transaction.NotFound());
if (err && response.error.code === -5) {
return callback(null, null);
} else if (err) {
return callback(self._wrapRPCError(err));
}
var tx = Transaction();
tx.fromString(response.result.hex);
@ -1091,9 +1099,10 @@ Bitcoin.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, cal
* @returns {String}
*/
Bitcoin.prototype.getBestBlockHash = function(callback) {
var self = this;
this.client.getBestBlockHash(function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
callback(null, response.result);
});
@ -1122,7 +1131,7 @@ Bitcoin.prototype.getInfo = function(callback) {
var self = this;
this.client.getInfo(function(err, response) {
if (err) {
return callback(err);
return callback(self._wrapRPCError(err));
}
var result = response.result;
result.network = self.node.network.name;

View File

@ -32,7 +32,7 @@ Transaction.prototype._populateInput = function(db, input, poolTransactions, cal
}
var txid = input.prevTxId.toString('hex');
db.getTransaction(txid, true, function(err, prevTx) {
if(err instanceof errors.Transaction.NotFoundError) {
if(!prevTx) {
// Check the pool for transaction
for(var i = 0; i < poolTransactions.length; i++) {
if(txid === poolTransactions[i].hash) {

View File

@ -149,6 +149,19 @@ describe('Bitcoind Functionality', function() {
});
});
describe('get errors as error instances', function() {
it('will wrap an rpc into a javascript error', function(done) {
bitcoind.client.getBlock(1000000000, function(err, response) {
var error = bitcoind._wrapRPCError(err);
(error instanceof Error).should.equal(true);
error.message.should.equal(err.message);
error.code.should.equal(err.code);
should.exist(error.stack);
done();
});
});
});
describe('get blocks by height', function() {
[0,1,2,3,4,5,6,7,8,9].forEach(function(i) {
@ -303,6 +316,7 @@ describe('Bitcoind Functionality', function() {
tx.to(destKey.toAddress(), utxos[1].amount * 1e8 - 1000);
bitcoind.sendTransaction(tx.uncheckedSerialize(), function(err, hash) {
should.exist(err);
(err instanceof Error).should.equal(true);
should.not.exist(hash);
done();
});
@ -316,6 +330,7 @@ describe('Bitcoind Functionality', function() {
var num = 23;
bitcoind.sendTransaction(num, function(err, hash) {
should.exist(err);
(err instanceof Error).should.equal(true);
should.not.exist(hash);
done();
});