Fixed address/transaction indexing.

This commit is contained in:
Chris Kleeschulte 2017-08-10 17:46:27 -04:00
parent abf52f8136
commit bf7cd67269
5 changed files with 79 additions and 34 deletions

View File

@ -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;
};

View File

@ -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);
});

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}