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;
|
module.exports = AddressService;
|
||||||
|
|||||||
@ -15,6 +15,15 @@ function TransactionService(options) {
|
|||||||
this._header = this.node.services.header;
|
this._header = this.node.services.header;
|
||||||
this._p2p = this.node.services.p2p;
|
this._p2p = this.node.services.p2p;
|
||||||
this._timestamp = this.node.services.timestamp;
|
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);
|
inherits(TransactionService, BaseService);
|
||||||
@ -37,8 +46,116 @@ TransactionService.prototype.getAPIMethods = function() {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
TransactionService.prototype.getDetailedTransaction =
|
TransactionService.prototype._getDoubleSpentTxID = function(tx, callback) {
|
||||||
TransactionService.prototype.getTransaction = function(txid, options, 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;
|
var self = this;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user