rpc: gettxoutproof and verifytxoutproof.
This commit is contained in:
parent
b50f8cc2bb
commit
a0d109f52d
@ -1157,11 +1157,108 @@ RPC.prototype.gettxout = function gettxout(args, callback) {
|
||||
};
|
||||
|
||||
RPC.prototype.gettxoutproof = function gettxoutproof(args, callback) {
|
||||
callback(new Error('Not implemented.'));
|
||||
var self = this;
|
||||
var uniq = {};
|
||||
var i, txids, block, hash, last;
|
||||
|
||||
if (args.help || (args.length !== 1 && args.length !== 2)) {
|
||||
return callback(new RPCError('gettxoutproof'
|
||||
+ ' ["txid",...] ( blockhash )'));
|
||||
}
|
||||
|
||||
txids = args[0];
|
||||
block = args[1];
|
||||
|
||||
if (!Array.isArray(txids) || txids.length === 0)
|
||||
return callback(new RPCError('Invalid parameter.'));
|
||||
|
||||
if (block) {
|
||||
if (!utils.isHex(block) || block.length !== 64)
|
||||
return callback(new RPCError('Invalid parameter.'));
|
||||
block = utils.revHex(block);
|
||||
}
|
||||
|
||||
for (i = 0; i < txids.length; i++) {
|
||||
hash = txids[i];
|
||||
if (!utils.isHex(hash) || hash.length !== 64)
|
||||
return callback(new RPCError('Invalid parameter.'));
|
||||
hash = utils.revHex(hash);
|
||||
if (uniq[hash])
|
||||
return callback(new RPCError('Duplicate txid.'));
|
||||
uniq[hash] = true;
|
||||
txids[i] = hash;
|
||||
last = hash;
|
||||
}
|
||||
|
||||
function getBlock(callback) {
|
||||
if (hash)
|
||||
return self.chain.db.getBlock(hash, callback);
|
||||
|
||||
if (self.chain.options.indexTX) {
|
||||
return self.chain.db.getTX(last, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
if (!tx)
|
||||
return callback();
|
||||
self.chain.db.getBlock(tx.block, callback);
|
||||
});
|
||||
}
|
||||
|
||||
self.chain.db.getCoins(last, function(err, coins) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!coins)
|
||||
return callback();
|
||||
|
||||
self.chain.db.getBlock(coins.height, callback);
|
||||
});
|
||||
}
|
||||
|
||||
getBlock(function(err, block) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!block)
|
||||
return callback(new RPCError('Block not found.'));
|
||||
|
||||
for (i = 0; i < txids.length; i++) {
|
||||
if (!block.hasTX(txids[i]))
|
||||
return callback(new RPCError('Block does not contain all txids.'));
|
||||
}
|
||||
|
||||
block = bcoin.merkleblock.fromHashes(block, txids);
|
||||
|
||||
callback(null, block.toRaw().toString('hex'));
|
||||
});
|
||||
};
|
||||
|
||||
RPC.prototype.verifytxoutproof = function verifytxoutproof(args, callback) {
|
||||
callback(new Error('Not implemented.'));
|
||||
var res = [];
|
||||
var i, block, hash;
|
||||
|
||||
if (args.help || args.length !== 1)
|
||||
return callback(new RPCError('verifytxoutproof "proof"'));
|
||||
|
||||
block = bcoin.merkleblock.fromRaw(String(args[0]), 'hex');
|
||||
|
||||
if (!block.verify())
|
||||
return callback(null, res);
|
||||
|
||||
this.chain.db.get(block.hash('hex'), function(err, entry) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!entry)
|
||||
return callback(new RPCError('Block not found in chain.'));
|
||||
|
||||
for (i = 0; i < block.matches.length; i++) {
|
||||
hash = block.matches[i];
|
||||
res.push(utils.revHex(hash));
|
||||
}
|
||||
|
||||
callback(null, res);
|
||||
});
|
||||
};
|
||||
|
||||
RPC.prototype.gettxoutsetinfo = function gettxoutsetinfo(args, callback) {
|
||||
@ -1446,6 +1543,9 @@ RPC.prototype.getnetworkhashps = function getnetworkhashps(args, callback) {
|
||||
lookup = args.length > 0 ? Number(args[0]) : 120;
|
||||
height = args.length > 1 ? Number(args[1]) : -1;
|
||||
|
||||
if (!utils.isNumber(lookup) || !utils.isNumber(height))
|
||||
return callback(new RPCError('Invalid parameter.'));
|
||||
|
||||
return this._hashps(lookup, height, callback);
|
||||
};
|
||||
|
||||
@ -1461,7 +1561,7 @@ RPC.prototype.submitblock = function submitblock(args, callback) {
|
||||
+ ' ( "jsonparametersobject" )'));
|
||||
}
|
||||
|
||||
block = bcoin.block.fromRaw(args[0], 'hex');
|
||||
block = bcoin.block.fromRaw(String(args[0]), 'hex');
|
||||
|
||||
this.chain.add(block, function(err, total) {
|
||||
if (err)
|
||||
|
||||
@ -448,6 +448,59 @@ MerkleBlock.fromJSON = function fromJSON(json) {
|
||||
|
||||
MerkleBlock.fromBlock = function fromBlock(block, filter) {
|
||||
var matches = [];
|
||||
var i, tx;
|
||||
|
||||
for (i = 0; i < block.txs.length; i++) {
|
||||
tx = block.txs[i];
|
||||
if (tx.isWatched(filter))
|
||||
matches.push(1);
|
||||
else
|
||||
matches.push(0);
|
||||
}
|
||||
|
||||
return MerkleBlock.fromMatches(block, matches);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a merkleblock from an array of txids.
|
||||
* This will build the partial merkle tree.
|
||||
* @param {Block} block
|
||||
* @param {Hash[]} hashes
|
||||
* @returns {MerkleBlock}
|
||||
*/
|
||||
|
||||
MerkleBlock.fromHashes = function fromHashes(block, hashes) {
|
||||
var filter = {};
|
||||
var matches = [];
|
||||
var i, tx, hash;
|
||||
|
||||
for (i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i];
|
||||
if (Buffer.isBuffer(hash))
|
||||
hash = hash.toString('hex');
|
||||
filter[hash] = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < block.txs.length; i++) {
|
||||
tx = block.txs[i];
|
||||
if (filter[tx.hash('hex')])
|
||||
matches.push(1);
|
||||
else
|
||||
matches.push(0);
|
||||
}
|
||||
|
||||
return MerkleBlock.fromMatches(block, matches);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a merkleblock from an array of matches.
|
||||
* This will build the partial merkle tree.
|
||||
* @param {Block} block
|
||||
* @param {Number[]} matches
|
||||
* @returns {MerkleBlock}
|
||||
*/
|
||||
|
||||
MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
||||
var txs = [];
|
||||
var leaves = [];
|
||||
var bits = [];
|
||||
@ -456,12 +509,8 @@ MerkleBlock.fromBlock = function fromBlock(block, filter) {
|
||||
|
||||
for (i = 0; i < block.txs.length; i++) {
|
||||
tx = block.txs[i];
|
||||
if (tx.isWatched(filter)) {
|
||||
matches.push(1);
|
||||
if (matches[i])
|
||||
txs.push(tx);
|
||||
} else {
|
||||
matches.push(0);
|
||||
}
|
||||
leaves.push(tx.hash());
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user