From 8f037ea430087ac8a9bc9ce7fd0bbfea2a2e3d50 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 14 Jan 2016 00:47:50 -0800 Subject: [PATCH] tx: add tbsHash method. --- lib/bcoin/block.js | 3 ++- lib/bcoin/miner.js | 9 +++++++ lib/bcoin/tx.js | 58 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 07316bb1..58d8d80e 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -437,7 +437,8 @@ Block.prototype.postVerify = function postVerify() { // BIP30 - Ensure there are no duplicate txids if (this.chain.index[tx.hash('hex')]) { // Blocks 91842 and 91880 created duplicate - // txids by carefully crafting the coinbases. + // txids by using the same exact output script + // and extraNonce. this.chain.emit('debug', 'Block is overwriting txids: %s', this.rhash); if (!(network.type === 'main' && (height === 91842 || height === 91880))) return false; diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index e276c106..e20a5653 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -205,8 +205,17 @@ Miner.prototype.createBlock = function createBlock(tx) { index: 0xffffffff }, script: [ + // Height (required in v2+ blocks) new bn(this.last.height + 1).toArray().reverse(), + // extraNonce - incremented when + // the nonce overflows. [], + // Add a nonce to ensure we don't + // collide with a previous coinbase + // of ours. + utils.nonce().toArray(), + // Let the world know this little + // miner succeeded. utils.ascii2array(this.msg || 'mined by bcoin') ], seq: 0xffffffff diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 301a4bd9..a6c19e66 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -653,6 +653,62 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) { return hash; }; +TX.prototype.tbsHash = function tbsHash(enc) { + var copy = this.clone(); + var i, j, input, s, raw, redeem, m; + + if (this.isCoinbase()) + return this.hash(enc); + + if (this._tbsHash) { + return enc === 'hex' + ? utils.toHex(this._tbsHash) + : this._tbsHash.slice(); + } + + for (i = 0; i < copy.inputs.length; i++) { + input = copy.inputs[i]; + input.out.tx = this.inputs[i].out.tx; + assert(input.out.tx); + + s = input.script; + redeem = input.out.tx.getSubscript(input.out.index); + + if (bcoin.script.isScripthash(redeem)) { + raw = s[s.length - 1]; + assert(Array.isArray(raw) && raw.length); + redeem = bcoin.script.subscript(bcoin.script.decode(raw)); + } else { + raw = null; + } + + if (bcoin.script.isPubkey(redeem)) { + input.script = [[]]; + } else if (bcoin.script.isPubkeyhash(redeem)) { + assert(Array.isArray(s[1]) && s[1].length); + input.script = [[], s[1]]; + } else if (bcoin.script.isMultisig(redeem)) { + m = s[0]; + if (Array.isArray(m)) + m = m[0]; + input.script = [[]]; + for (i = 0; i < m; i++) + input.script.push([]); + } else { + input.script = []; + } + + if (raw) + input.script.push(raw); + } + + this._tbsHash = utils.dsha256(copy.render(true)); + + return enc === 'hex' + ? utils.toHex(this._tbsHash) + : this._tbsHash.slice(); +}; + TX.prototype.verify = function verify(index, force, flags) { // Valid if included in block if (!force && this.ts !== 0) @@ -1202,7 +1258,7 @@ TX.prototype.__defineGetter__('fee', function() { }); TX.prototype.__defineGetter__('value', function() { - return this.funds('in'); + return this.funds('out'); }); TX.prototype.__defineGetter__('height', function() {