diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index dec81419..f307a1a1 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -264,7 +264,7 @@ Parser.prototype.parseTXOut = function parseTXOut(p) { }; Parser.prototype.parseTX = function parseTX(p) { - if (p.length < 60) + if (p.length < 10) return this._error('Invalid tx size'); var inCount = readIntv(p, 4); @@ -272,7 +272,7 @@ Parser.prototype.parseTX = function parseTX(p) { inCount = inCount.r; if (inCount < 0) return this._error('Invalid tx_in count (negative)'); - if (off + 41 * inCount + 14 > p.length) + if (off + 41 * inCount + 5 > p.length) return this._error('Invalid tx_in count (too big)'); var txIn = new Array(inCount); @@ -283,7 +283,7 @@ Parser.prototype.parseTX = function parseTX(p) { txIn[i] = tx; off += tx.size; - if (off + 14 > p.length) + if (off + 5 > p.length) return this._error('Invalid tx_in offset'); } diff --git a/lib/bcoin/tx-pool.js b/lib/bcoin/tx-pool.js index f54d7e93..e794ebe8 100644 --- a/lib/bcoin/tx-pool.js +++ b/lib/bcoin/tx-pool.js @@ -60,7 +60,7 @@ TXPool.prototype.add = function add(tx, noWrite) { this._all[hash] = tx; var own = this._wallet.ownOutput(tx); - var update = false; + var updated = false; // Consume unspent money or add orphans for (var i = 0; i < tx.inputs.length; i++) { @@ -100,15 +100,26 @@ TXPool.prototype.add = function add(tx, noWrite) { var key = hash + '/' + i; var orphan = this._orphans[key]; + // Add input to orphan + if (orphan) { + orphan.tx.input(tx, orphan.index); + var index = orphan.tx.inputIndex(tx, orphan.index); + + // Verify that input script is correct, if not - add output to unspent + // and remove orphan from storage + if (!orphan.tx.verify(orphan, index)) { + orphan = null; + if (this._storage) + this._removeTX(orphan.tx); + } + } + if (!orphan) { this._unspent[key] = { tx: tx, index: i }; updated = true; continue; } delete this._orphans[key]; - - // Add input to orphan - orphan.tx.input(tx, orphan.index); } this._lastTs = Math.max(tx.ts, this._lastTs); @@ -131,6 +142,14 @@ TXPool.prototype._storeTX = function _storeTX(hash, tx) { }); }; +TXPool.prototype._removeTX = function _removeTX(tx) { + var self = this; + this._storage.del(this._prefix + tx.hash('hex'), function(err) { + if (err) + self.emit('error', err); + }); +}; + TXPool.prototype.all = function all() { return Object.keys(this._all).map(function(key) { return this._all[key]; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 6abf7c4c..febba665 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -79,17 +79,14 @@ TX.prototype.input = function input(i, index) { }; // Try modifying existing input first - for (var i = 0; i < this.inputs.length; i++) { - var ex = this.inputs[i]; - if (ex.out.hash !== hash && ex.out.index !== index) - continue; + var index = this.inputIndex(hash, index); + if (index !== -1) { + var ex = this.inputs[index]; ex.out.tx = input.out.tx || ex.out.tx; ex.seq = input.seq || ex.seq; ex.script = input.script.length ? input.script : ex.script; - break; - } - if (i === this.inputs.length) { + } else { this.inputs.push(input); if (input.out.tx) this.funds.iadd(input.out.tx.outputs[input.out.index].value); @@ -98,6 +95,18 @@ TX.prototype.input = function input(i, index) { return this; }; +TX.prototype.inputIndex = function inputIndex(hash, index) { + if (hash instanceof TX) + hash = hash.hash('hex'); + for (var i = 0; i < this.inputs.length; i++) { + var ex = this.inputs[i]; + if (ex.out.hash === hash && ex.out.index === index) + return i; + } + + return -1; +}; + TX.prototype.out = function out(output, value) { if (output instanceof bcoin.wallet) output = output.getAddress(); @@ -161,8 +170,15 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) { return hash; }; -TX.prototype.verify = function verify() { - return this.inputs.every(function(input, i) { +TX.prototype.verify = function verify(index, force) { + // Valid if included in block + if (!force && this.ts !== 0) + return true; + + return this.inputs.filter(function(input, i) { + if (index !== undefined && index !== i) + return false; + if (!input.out.tx) return false; diff --git a/test/wallet-test.js b/test/wallet-test.js index c1327d51..0a98c467 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -91,6 +91,7 @@ describe('Wallet', function() { .out(w, 11000); var f1 = bcoin.tx().input(t4.hash(), 1) .out(f, 10000); + var fake = bcoin.tx().input(t1.hash(), 1); w.sign(t1); w.sign(t2); w.sign(t3); @@ -104,6 +105,7 @@ describe('Wallet', function() { t4.hint = 't4'; f1.hint = 'f1'; + w.addTX(fake); w.addTX(t4); assert.equal(w.balance().toString(10), '22000'); w.addTX(t1);