tx-pool: save spending TXs

This commit is contained in:
Fedor Indutny 2014-05-09 21:30:55 +04:00
parent cf2e0042ff
commit 2ee4c7cd3a
4 changed files with 66 additions and 14 deletions

View File

@ -53,13 +53,14 @@ TXPool.prototype.add = function add(tx, noWrite) {
// Transaction was confirmed, update it in storage
if (tx.ts !== 0 && this._all[hash].ts === 0) {
this._all[hash].ts = tx.ts;
this._storeTX(hash, tx);
if (this._storage)
this._storeTX(hash, tx);
}
return false;
}
this._all[hash] = tx;
var own = this._wallet.own(tx);
var own = this._wallet.ownOutput(tx);
var update = false;
// Consume unspent money or add orphans
@ -87,6 +88,10 @@ TXPool.prototype.add = function add(tx, noWrite) {
if (!own) {
if (updated)
this.emit('update', this._lastTs);
// Save spending TXs without adding unspents
if (this._storage && this._wallet.ownInput(tx))
this._storeTX(hash, tx);
return;
}
@ -130,8 +135,9 @@ TXPool.prototype._storeTX = function _storeTX(hash, tx) {
TXPool.prototype.all = function all() {
return Object.keys(this._all).map(function(key) {
return this._all[key];
}, this).filter(function(item) {
return this._wallet.own(item.tx, item.index);
}, this).filter(function(tx) {
return this._wallet.ownOutput(tx) ||
this._wallet.ownInput(tx);
}, this);
};
@ -139,7 +145,7 @@ TXPool.prototype.unspent = function unspent() {
return Object.keys(this._unspent).map(function(key) {
return this._unspent[key];
}, this).filter(function(item) {
return this._wallet.own(item.tx, item.index);
return this._wallet.ownOutput(item.tx, item.index);
}, this);
};

View File

@ -163,7 +163,9 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
TX.prototype.verify = function verify() {
return this.inputs.every(function(input, i) {
assert(input.out.tx);
if (!input.out.tx)
return false;
assert(input.out.tx.outputs.length > input.out.index);
var subscript = input.out.tx.getSubscript(input.out.index);

View File

@ -142,7 +142,7 @@ Wallet.prototype.validateAddress = function validateAddress(addr) {
};
Wallet.validateAddress = Wallet.prototype.validateAddress;
Wallet.prototype.own = function own(tx, index) {
Wallet.prototype.ownOutput = function ownOutput(tx, index) {
var hash = this.getHash();
var key = this.getPublicKey();
var outputs = tx.outputs.filter(function(output, i) {
@ -165,6 +165,32 @@ Wallet.prototype.own = function own(tx, index) {
return outputs;
};
Wallet.prototype.ownInput = function ownInput(tx, index) {
var hash = this.getHash();
var key = this.getPublicKey();
var inputs = tx.inputs.filter(function(input, i) {
if (index !== undefined && index !== i)
return false;
if (!input.out.tx)
return false;
var s = input.out.tx.outputs[input.out.index].script;
if (bcoin.script.isPubkeyhash(s, hash))
return true;
if (bcoin.script.isMultisig(s, key))
return true;
return false;
}, this);
if (inputs.length === 0)
return false;
return inputs;
};
Wallet.prototype.sign = function sign(tx, type) {
if (!type)
type = 'all';
@ -172,7 +198,7 @@ Wallet.prototype.sign = function sign(tx, type) {
// Filter inputs that this wallet own
var inputs = tx.inputs.filter(function(input) {
return input.out.tx && this.own(input.out.tx);
return input.out.tx && this.ownOutput(input.out.tx);
}, this);
var pub = this.getPublicKey();

View File

@ -31,8 +31,8 @@ describe('Wallet', function() {
address: w.getAddress() + 'x'
}]
});
assert(w.own(src));
assert.equal(w.own(src).reduce(function(acc, out) {
assert(w.ownOutput(src));
assert.equal(w.ownOutput(src).reduce(function(acc, out) {
return acc.iadd(out.value);
}, new bn(0)).toString(10), 5460 * 2);
@ -58,8 +58,8 @@ describe('Wallet', function() {
address: w.getAddress() + 'x'
}]
});
assert(w.own(src));
assert.equal(w.own(src).reduce(function(acc, out) {
assert(w.ownOutput(src));
assert.equal(w.ownOutput(src).reduce(function(acc, out) {
return acc.iadd(out.value);
}, new bn(0)).toString(10), 5460 * 2);
@ -75,6 +75,7 @@ describe('Wallet', function() {
it('should have TX pool and be serializable', function() {
var w = bcoin.wallet();
var f = bcoin.wallet();
// Coinbase
var t1 = bcoin.tx().out(w, 50000).out(w, 1000);
@ -86,13 +87,22 @@ describe('Wallet', function() {
.out(w, 23000);
var t4 = bcoin.tx().input(t2.hash(), 1)
.input(t3.hash(), 0)
.out(w, 22000);
.out(w, 11000)
.out(w, 11000);
var f1 = bcoin.tx().input(t4.hash(), 1)
.out(f, 10000);
w.sign(t1);
w.sign(t2);
w.sign(t3);
w.sign(t4);
w.sign(f1);
// Just for debugging
t1.hint = 't1';
t2.hint = 't2';
t3.hint = 't3';
t4.hint = 't4';
f1.hint = 'f1';
w.addTX(t4);
assert.equal(w.balance().toString(10), '22000');
@ -102,8 +112,16 @@ describe('Wallet', function() {
assert.equal(w.balance().toString(10), '47000');
w.addTX(t3);
assert.equal(w.balance().toString(10), '22000');
w.addTX(f1);
assert.equal(w.balance().toString(10), '11000');
assert(w.all().some(function(tx) {
return tx.hash('hex') === f1.hash('hex');
}));
var w2 = bcoin.wallet.fromJSON(w.toJSON());
assert.equal(w2.balance().toString(10), '22000');
assert.equal(w2.balance().toString(10), '11000');
assert(w2.all().some(function(tx) {
return tx.hash('hex') === f1.hash('hex');
}));
});
});