Fixed address/transaction indexing.
This commit is contained in:
parent
abf52f8136
commit
bf7cd67269
@ -16,7 +16,8 @@ var AddressService = function(options) {
|
||||
BaseService.call(this, options);
|
||||
this._db = this.node.services.db;
|
||||
this._tx = this.node.services.transaction;
|
||||
this._network = this.node.getNetworkName();
|
||||
this._network = this.node.network;
|
||||
this._timestamp = this.node.services.timestamp;
|
||||
this._p2p = this.node.services.p2p;
|
||||
};
|
||||
|
||||
@ -26,7 +27,8 @@ AddressService.dependencies = [
|
||||
'p2p',
|
||||
'db',
|
||||
'block',
|
||||
'transaction'
|
||||
'transaction',
|
||||
'timestamp'
|
||||
];
|
||||
|
||||
// ---- public function prototypes
|
||||
@ -406,7 +408,6 @@ AddressService.prototype._onReorg = function(commonAncestorHeader, oldBlockList)
|
||||
};
|
||||
|
||||
AddressService.prototype.onBlock = function(block, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
if (self.node.stopping) {
|
||||
@ -415,28 +416,26 @@ AddressService.prototype.onBlock = function(block, callback) {
|
||||
|
||||
var operations = [];
|
||||
|
||||
block.txs.forEach(function(tx) {
|
||||
operations.concat(self._processTransaction(tx, { block: block }));
|
||||
});
|
||||
|
||||
if (operations && operations.length > 0) {
|
||||
|
||||
self._db.batch(operations);
|
||||
|
||||
for(var i = 0; i < block.txs.length; i++) {
|
||||
var tx = block.txs[i];
|
||||
var ops = self._processTransaction(tx, { block: block });
|
||||
operations.push(ops);
|
||||
}
|
||||
setImmediate(function() {
|
||||
callback(null, operations);
|
||||
});
|
||||
|
||||
operations = _.flatten(operations);
|
||||
callback(null, operations);
|
||||
};
|
||||
|
||||
AddressService.prototype._processInput = function(tx, input, opts) {
|
||||
|
||||
var address = input.address;
|
||||
var address = input.getAddress();
|
||||
|
||||
if(!address) {
|
||||
return;
|
||||
}
|
||||
|
||||
address.network = this._network;
|
||||
address = address.toString();
|
||||
var txid = tx.txid();
|
||||
// address index
|
||||
var addressKey = this._encoding.encodeAddressIndexKey(address, opts.block.height, txid);
|
||||
@ -463,22 +462,23 @@ AddressService.prototype._processInput = function(tx, input, opts) {
|
||||
};
|
||||
|
||||
AddressService.prototype._processOutput = function(tx, output, index, opts) {
|
||||
|
||||
var address = output.address;
|
||||
var address = output.getAddress();
|
||||
|
||||
if(!address) {
|
||||
return;
|
||||
}
|
||||
|
||||
address.network = this._network;
|
||||
var address = address.toString();
|
||||
var txid = tx.txid();
|
||||
var addressKey = this._encoding.encodeAddressIndexKey(address, opts.block.height, txid);
|
||||
var utxoKey = this._encoding.encodeUtxoIndexKey(address, txid, index);
|
||||
var utxoValue = this._encoding.encodeUtxoIndexValue(
|
||||
opts.block.height,
|
||||
Unit.fromBTC(output.value).toSatoshis(),
|
||||
this._timestamp.getTimestampSync(opts.block.rhash()),
|
||||
output.script.toRaw()
|
||||
);
|
||||
|
||||
var operations = [{
|
||||
type: 'put',
|
||||
key: addressKey
|
||||
@ -490,6 +490,8 @@ AddressService.prototype._processOutput = function(tx, output, index, opts) {
|
||||
value: utxoValue
|
||||
});
|
||||
|
||||
return operations;
|
||||
|
||||
};
|
||||
|
||||
AddressService.prototype._processTransaction = function(tx, opts) {
|
||||
@ -505,12 +507,13 @@ AddressService.prototype._processTransaction = function(tx, opts) {
|
||||
outputOperations = _.flatten(_.compact(outputOperations));
|
||||
|
||||
var inputOperations = tx.inputs.map(function(input) {
|
||||
self._processInput(tx, input, _opts);
|
||||
return self._processInput(tx, input, _opts);
|
||||
});
|
||||
|
||||
inputOperations = _.flatten(_.compact(inputOperations));
|
||||
|
||||
return outputOperations.concat(inputOperations);
|
||||
outputOperations.concat(inputOperations);
|
||||
return outputOperations;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -193,6 +193,9 @@ HeaderService.prototype._onBlock = function(block) {
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.subscriptions.block.length; i++) {
|
||||
var prevHeader = this._headers.get(header.prevHash);
|
||||
assert(prevHeader, 'We must have a previous header in order to calculate this block\'s data.');
|
||||
block.height = prevHeader.height + 1;
|
||||
this.subscriptions.block[i].emit('header/block', block, header);
|
||||
}
|
||||
};
|
||||
@ -218,7 +221,7 @@ HeaderService.prototype._onHeaders = function(headers) {
|
||||
headerListLength = headers.length;
|
||||
}
|
||||
|
||||
var prevHeader = this._headers.get(header.prevHash);
|
||||
var prevHeader = self._headers.get(header.prevHash);
|
||||
assert(prevHeader, 'We must have a previous header in order to calculate this header\'s data.');
|
||||
|
||||
header.height = prevHeader.height + 1;
|
||||
@ -429,8 +432,6 @@ HeaderService.prototype._getPersistedHeaders = function(callback) {
|
||||
|
||||
var tipHeader = self._headers.getIndex(self._tip.height);
|
||||
self._tip.hash = tipHeader.hash;
|
||||
self._lastChainwork = tipHeader.chainwork;
|
||||
|
||||
self._db.batch(removalOps, callback);
|
||||
|
||||
});
|
||||
|
||||
@ -119,9 +119,7 @@ MempoolService.prototype.onBlock = function(block, callback) {
|
||||
key: self._encoding.encodeMempoolTransactionKey(tx.txid())
|
||||
};
|
||||
});
|
||||
setImmediate(function() {
|
||||
callback(null, ops);
|
||||
});
|
||||
callback(null, ops);
|
||||
};
|
||||
|
||||
MempoolService.prototype._onTransaction = function(tx) {
|
||||
|
||||
@ -45,14 +45,13 @@ TransactionService.prototype.getDetailedTransaction = function(txid, options, ca
|
||||
this.getTransaction(txid, options, callback);
|
||||
};
|
||||
|
||||
TransactionService.prototype.getTransaction = function(txid, options, callback) {
|
||||
|
||||
TransactionService.prototype._getTransaction = function(txid, options, callback) {
|
||||
var self = this;
|
||||
|
||||
var _tx;
|
||||
var queryMempool = _.isUndefined(options.queryMempool) ? true : options.queryMempool;
|
||||
|
||||
var key = self.encoding.encodeTransactionKey(txid);
|
||||
var key = self._encoding.encodeTransactionKey(txid);
|
||||
|
||||
self._db.get(key, function(err, tx) {
|
||||
|
||||
@ -69,6 +68,7 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
||||
}
|
||||
|
||||
if (memTx) {
|
||||
memTx = self._encoding.decodeTransactionValue(memTx);
|
||||
memTx.confirmations = 0;
|
||||
_tx = memTx;
|
||||
}
|
||||
@ -78,7 +78,9 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
||||
} else {
|
||||
|
||||
if (tx) {
|
||||
tx = self._encoding.decodeTransactionValue(tx);
|
||||
tx.confirmations = self._p2p.getBestHeight - tx.__height;
|
||||
tx.blockHash = self._header.get(tx.__height).hash;
|
||||
_tx = tx;
|
||||
}
|
||||
|
||||
@ -88,8 +90,49 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
||||
return callback();
|
||||
}
|
||||
|
||||
// TODO: this could cause crazy amounts of recursion if input values are missing from the entire chain of txs
|
||||
self._addMissingInputValues(_tx, options, callback);
|
||||
var outputSatoshis = 0;
|
||||
_tx.outputs.forEach(function(output) {
|
||||
outputSatoshis += output.value;
|
||||
});
|
||||
_tx.outputs.forEach(function(output) {
|
||||
outputSatoshis += output.value;
|
||||
});
|
||||
_tx.outputSatoshis = outputSatoshis;
|
||||
if (!_tx.inputs[0].isCoinbase()) {
|
||||
var inputSatoshis = 0;
|
||||
_tx.__inputValues.forEach(function(val) {
|
||||
if (val >- 0) {
|
||||
inputSatoshis += val;
|
||||
}
|
||||
});
|
||||
var feeSatoshis = inputSatoshis - outputSatoshis;
|
||||
_tx.inputSatosbis = inputSatoshis;
|
||||
_tx.feeSatosbis = feeSatoshis;
|
||||
}
|
||||
callback(null, _tx);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
TransactionService.prototype.getTransaction = function(txid, options, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
if (typeof callback !== 'function') {
|
||||
callback = options;
|
||||
}
|
||||
|
||||
self._getTransaction(txid, options, function(err, tx) {
|
||||
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!tx) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
self._addMissingInputValues(tx, options, callback);
|
||||
|
||||
});
|
||||
|
||||
@ -109,7 +152,7 @@ TransactionService.prototype._addMissingInputValues = function(tx, options, call
|
||||
}
|
||||
|
||||
var outputIndex = input.prevout.index;
|
||||
self.getTransaction(input.prevout.txid(), options, function(err, _tx) {
|
||||
self._getTransaction(input.prevout.txid(), options, function(err, _tx) {
|
||||
|
||||
if (err || !_tx) {
|
||||
return next(err || new Error('tx not found for tx id: ' + input.prevout.txid()));
|
||||
@ -122,7 +165,6 @@ TransactionService.prototype._addMissingInputValues = function(tx, options, call
|
||||
|
||||
});
|
||||
|
||||
|
||||
}, function(err) {
|
||||
|
||||
if (err) {
|
||||
|
||||
@ -81,11 +81,12 @@ utils.SimpleMap = function SimpleMap() {
|
||||
};
|
||||
|
||||
this.set = function (key, value, pos) {
|
||||
object[key] = array.length;
|
||||
|
||||
if (pos >= 0) {
|
||||
object[key] = pos;
|
||||
array[pos] = value;
|
||||
} else {
|
||||
object[key] = array.length;
|
||||
array.push(value);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user