fcoin/lib/bcoin/tx-pool.js
2014-05-06 21:33:05 +04:00

104 lines
2.3 KiB
JavaScript

var assert = require('assert');
var bn = require('bn.js');
var bcoin = require('../bcoin');
function TXPool(wallet) {
if (!(this instanceof TXPool))
return new TXPool(wallet);
this._wallet = wallet;
this._all = {};
this._unspent = {};
this._orphans = {};
}
module.exports = TXPool;
TXPool.prototype.add = function add(tx) {
var hash = tx.hash('hex');
if (!this._wallet.own(tx))
return;
// Do not add TX two times
if (this._all[hash])
return false;
this._all[hash] = tx;
// Consume unspent money or add orphans
for (var i = 0; i < tx.inputs.length; i++) {
var input = tx.inputs[i];
var key = input.out.hash + '/' + input.out.index;
var unspent = this._unspent[key];
if (unspent) {
// Add TX to inputs and spend money
tx.input(unspent.tx, unspent.index);
delete this._unspent[key];
continue;
}
// Double-spend?!
if (this._orphans[key])
continue;
// Add orphan, if no parent transaction is yet known
this._orphans[key] = { tx: tx, index: i };
}
// Add unspent outputs or fullfill orphans
for (var i = 0; i < tx.outputs.length; i++) {
var out = tx.outputs[i];
var key = hash + '/' + i;
var orphan = this._orphans[key];
if (!orphan) {
this._unspent[key] = { tx: tx, index: i };
continue;
}
delete this._orphans[key];
// Add input to orphan
orphan.tx.input(tx, orphan.index);
}
return true;
};
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);
}, this);
};
TXPool.prototype.balance = function balance() {
var acc = new bn(0);
var unspent = this.unspent();
if (unspent.length === 0)
return acc;
return unspent.reduce(function(acc, item) {
return acc.iadd(item.tx.outputs[item.index].value);
}, acc);
};
TXPool.prototype.toJSON = function toJSON() {
return {
v: 1,
type: 'tx-pool',
txs: Object.keys(this._all).map(function(hash) {
return this._all[hash].toJSON();
}, this)
};
};
TXPool.prototype.fromJSON = function fromJSON(json) {
assert.equal(json.v, 1);
assert.equal(json.type, 'tx-pool');
json.txs.forEach(function(tx) {
this.add(bcoin.tx.fromJSON(tx));
}, this);
};