tx-pool: ignore invalid orphans
This commit is contained in:
parent
0efe2e2021
commit
86088f8ae9
@ -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');
|
||||
}
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user