Added locating double spend txs.
This commit is contained in:
parent
1e04e08411
commit
7c392e9c94
@ -717,4 +717,33 @@ AddressService.prototype._processTransaction = function(tx, opts) {
|
||||
|
||||
};
|
||||
|
||||
// TODO seems spendy
|
||||
AddressService.prototype._getInputInfoForAddress = function(address) {
|
||||
|
||||
var self = this;
|
||||
var inputs = [];
|
||||
var start = self._encoding.encodeAddressIndexKey(address);
|
||||
|
||||
var criteria = {
|
||||
gte: start,
|
||||
lt: Buffer.concat(start.slice(0, address.length + 4), new Buffer(new Array(address.length + 5).join('f'), 'hex'))
|
||||
};
|
||||
|
||||
// all the info about this address
|
||||
var stream = self._db.createKeyStream(criteria);
|
||||
|
||||
stream.on('data', function(data) {
|
||||
var info = self._encoding.decodeAddressIndexKey(data);
|
||||
//only returning
|
||||
if (info.input) {
|
||||
inputs.push(info);
|
||||
}
|
||||
});
|
||||
|
||||
stream.on('end', function() {
|
||||
return inputs;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
module.exports = AddressService;
|
||||
|
||||
@ -15,6 +15,15 @@ function TransactionService(options) {
|
||||
this._header = this.node.services.header;
|
||||
this._p2p = this.node.services.p2p;
|
||||
this._timestamp = this.node.services.timestamp;
|
||||
this._address = this.node.services.address;
|
||||
this._network = this.node.network;
|
||||
|
||||
if (this._network === 'livenet') {
|
||||
this._network = 'main';
|
||||
}
|
||||
if (this._network === 'regtest') {
|
||||
this._network = 'testnet';
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TransactionService, BaseService);
|
||||
@ -37,8 +46,116 @@ TransactionService.prototype.getAPIMethods = function() {
|
||||
];
|
||||
};
|
||||
|
||||
TransactionService.prototype.getDetailedTransaction =
|
||||
TransactionService.prototype.getTransaction = function(txid, options, callback) {
|
||||
TransactionService.prototype._getDoubleSpentTxID = function(tx, callback) {
|
||||
// for there to be a tx in our mempool that is double spending this tx,
|
||||
// then at least one other tx in the mempool must be spending at least one of the
|
||||
// outputs that this tx is spending
|
||||
|
||||
// TODO
|
||||
// we don't index the mempool to easily handle this because we would have to exhaustively
|
||||
// search through all of the mempool txs
|
||||
|
||||
// we should probably have an index whose key is prevtxid + output index + spendingtxid and no value
|
||||
// then we could quickly loop over all inputs and get their spending txids in a list.
|
||||
// then subtract the list and this will be your double spending txids.
|
||||
|
||||
// when a new block comes in, it may confirm up to one of those tx's. It should be very easily to
|
||||
// delete the correct one because we have the block and the tx.
|
||||
return callback();
|
||||
|
||||
};
|
||||
|
||||
TransactionService.prototype._getConfirmationsForInputs = function(tx, callback) {
|
||||
// for every input, check to see if its referenced input is confirmed.
|
||||
};
|
||||
|
||||
TransactionService.prototype._getSpentInformationForOutputs = function(tx, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
async.mapLimit(tx.outputs, 4, function(output, next) {
|
||||
|
||||
var address = output.getAddress();
|
||||
|
||||
if (!address) {
|
||||
return next();
|
||||
}
|
||||
|
||||
address.network = self._network;
|
||||
address = address.toString();
|
||||
|
||||
self._address._getInputInfoForAddress(address, next);
|
||||
|
||||
}, function(err, inputGroups) {
|
||||
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// we have an array for every output representing all the input info for the address
|
||||
// we need to take each txid in the input info and get the tx but only if the height is greater this
|
||||
// tx's height
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
TransactionService.prototype.getDetailedTransaction = function(txid, options, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
self.getTransaction(txid, options, function(err, tx) {
|
||||
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!tx) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
// add in the following:
|
||||
// 1. double spend tx id
|
||||
// 2. is confirmed
|
||||
// 3. for every input: is input confirmed
|
||||
// 4. for every output: spent tx id (some future tx)
|
||||
// 5. for every output: spent tx index
|
||||
// 6. for every output: spent tx height
|
||||
|
||||
// is confirmed: does this tx appear in at least one block
|
||||
tx.isConfirmed = tx.confirmations > 0;
|
||||
|
||||
async.parallel([
|
||||
function(next) {
|
||||
// double spend tx: did another tx in our mempool attempt to spend ANY of the same outputs that our inputs are trying to spend?
|
||||
self._getDoubleSpentTxID(tx, next);
|
||||
},
|
||||
// is input confirmed: on every input, place a field for whether or not the input's output is confirmed
|
||||
function(next) {
|
||||
self._getConfirmationsForInputs(tx, next);
|
||||
},
|
||||
// get spent inforamtion for outputs
|
||||
function(next) {
|
||||
self._getSpentInformationForOutputs(tx, next);
|
||||
}
|
||||
], function(err) {
|
||||
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
callback(null, tx);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
TransactionService.prototype.getTransaction = function(txid, options, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user