Added Utxo index block handler.
This commit is contained in:
parent
3b76463112
commit
e2229a6516
@ -2,14 +2,8 @@
|
|||||||
|
|
||||||
var bitcore = require('bitcore-lib');
|
var bitcore = require('bitcore-lib');
|
||||||
var BufferReader = bitcore.encoding.BufferReader;
|
var BufferReader = bitcore.encoding.BufferReader;
|
||||||
var Address = bitcore.Address;
|
|
||||||
var PublicKey = bitcore.PublicKey;
|
|
||||||
var constants = require('./constants');
|
|
||||||
var $ = bitcore.util.preconditions;
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
var exports = {};
|
|
||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this.servicePrefix = servicePrefix;
|
this.servicePrefix = servicePrefix;
|
||||||
}
|
}
|
||||||
@ -21,12 +15,6 @@ Encoding.prototype.getTerminalKey = function(startKey) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeAddressIndexKey = function(address, height, txid) {
|
Encoding.prototype.encodeAddressIndexKey = function(address, height, txid) {
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
|
|
||||||
if (!utils.hasRequiredArgsForEncoding(args)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var prefix = new Buffer('00', 'hex');
|
var prefix = new Buffer('00', 'hex');
|
||||||
var buffers = [this.servicePrefix, prefix];
|
var buffers = [this.servicePrefix, prefix];
|
||||||
|
|
||||||
@ -53,7 +41,7 @@ Encoding.prototype.encodeAddressIndexKey = function(address, height, txid) {
|
|||||||
|
|
||||||
Encoding.prototype.decodeAddressIndexKey = function(buffer) {
|
Encoding.prototype.decodeAddressIndexKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var prefix = reader.read(3);
|
reader.read(3);
|
||||||
|
|
||||||
var addressSize = reader.readUInt8();
|
var addressSize = reader.readUInt8();
|
||||||
var address = reader.read(addressSize).toString('utf8');
|
var address = reader.read(addressSize).toString('utf8');
|
||||||
@ -67,6 +55,7 @@ Encoding.prototype.decodeAddressIndexKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
|
Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
|
||||||
|
console.log('encodeUtxoIndexKey');
|
||||||
var prefix = new Buffer('01', 'hex');
|
var prefix = new Buffer('01', 'hex');
|
||||||
var buffers = [this.servicePrefix, prefix];
|
var buffers = [this.servicePrefix, prefix];
|
||||||
|
|
||||||
@ -93,7 +82,7 @@ Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
|
|||||||
|
|
||||||
Encoding.prototype.decodeUtxoIndexKey = function(buffer) {
|
Encoding.prototype.decodeUtxoIndexKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var prefix = reader.read(3);
|
reader.read(3);
|
||||||
|
|
||||||
var addressSize = reader.readUInt8();
|
var addressSize = reader.readUInt8();
|
||||||
var address = reader.read(addressSize).toString('utf8');
|
var address = reader.read(addressSize).toString('utf8');
|
||||||
@ -230,7 +219,7 @@ Encoding.prototype.encodeWalletTransactionKey = function(walletId, height, block
|
|||||||
|
|
||||||
Encoding.prototype.decodeWalletTransactionKey = function(buffer) {
|
Encoding.prototype.decodeWalletTransactionKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var prefix = reader.read(1);
|
reader.read(1);
|
||||||
|
|
||||||
var walletSize = reader.readUInt8();
|
var walletSize = reader.readUInt8();
|
||||||
var walletId = reader.read(walletSize).toString('utf8');
|
var walletId = reader.read(walletSize).toString('utf8');
|
||||||
@ -278,10 +267,10 @@ Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) {
|
|||||||
|
|
||||||
Encoding.prototype.decodeWalletUtxoKey = function(buffer) {
|
Encoding.prototype.decodeWalletUtxoKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var prefix = reader.read(1);
|
reader.read(1);
|
||||||
|
|
||||||
var walletIdSizeBuffer = reader.readUInt8();
|
var walletIdSize = reader.readUInt8();
|
||||||
var walletIdBuffer = reader.read(walletIdSizeBuffer).toString('utf8');
|
var walletId = reader.read(walletIdSize).toString('utf8');
|
||||||
var txid = reader.read(32).toString('hex');
|
var txid = reader.read(32).toString('hex');
|
||||||
var outputIndex = reader.readUInt32BE();
|
var outputIndex = reader.readUInt32BE();
|
||||||
return {
|
return {
|
||||||
@ -347,16 +336,16 @@ Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, tx
|
|||||||
|
|
||||||
Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) {
|
Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var prefix = reader.read(1);
|
reader.read(1);
|
||||||
|
|
||||||
var walletIdSizeBuffer = reader.readUInt8();
|
var walletIdSizeBuffer = reader.readUInt8();
|
||||||
var walletIdBuffer = reader.read(walletIdSizeBuffer).toString('utf8');
|
var walletId = reader.read(walletIdSizeBuffer).toString('utf8');
|
||||||
var satoshis = reader.readDoubleBE();
|
var satoshis = reader.readDoubleBE();
|
||||||
var txid = reader.read(32).toString('hex');
|
var txid = reader.read(32).toString('hex');
|
||||||
var outputIndex = reader.readUInt32BE();
|
var outputIndex = reader.readUInt32BE();
|
||||||
return {
|
return {
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
sathosis: sathosis,
|
satoshis: satoshis,
|
||||||
txid: txid,
|
txid: txid,
|
||||||
outputIndex: outputIndex
|
outputIndex: outputIndex
|
||||||
};
|
};
|
||||||
@ -408,6 +397,21 @@ Encoding.prototype.encodeWalletValue = function(addresses, balance) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeWalletValue = function(buffer) {
|
Encoding.prototype.decodeWalletValue = function(buffer) {
|
||||||
|
var reader = new BufferReader(buffer);
|
||||||
|
var addressesLength = reader.readUInt32BE();
|
||||||
|
var addresses = [];
|
||||||
|
var addressSize = 0;
|
||||||
|
for(var i = 0; i < addressesLength.length; i++) {
|
||||||
|
addressSize = reader.readUInt8(addressSize);
|
||||||
|
addresses.push(reader.read(addressSize).toString('utf8'));
|
||||||
|
}
|
||||||
|
var balance = reader.readDoubleBE();
|
||||||
|
|
||||||
|
return {
|
||||||
|
addresses: addresses,
|
||||||
|
balance: balance
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Encoding;
|
module.exports = Encoding;
|
||||||
|
|||||||
@ -230,6 +230,105 @@ AddressService.prototype.concurrentBlockHandler = function(block, connectBlock,
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressService.prototype.blockHandler = function(block, connectBlock, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var txs = block.transactions;
|
||||||
|
var height = block.__height;
|
||||||
|
|
||||||
|
var action = 'put';
|
||||||
|
var reverseAction = 'del';
|
||||||
|
if (!connectBlock) {
|
||||||
|
action = 'del';
|
||||||
|
reverseAction = 'put';
|
||||||
|
}
|
||||||
|
|
||||||
|
var operations = [];
|
||||||
|
|
||||||
|
async.eachSeries(txs, function(tx, next) {
|
||||||
|
var txid = tx.id;
|
||||||
|
var inputs = tx.inputs;
|
||||||
|
var outputs = tx.outputs;
|
||||||
|
|
||||||
|
// Subscription messages
|
||||||
|
var txmessages = {};
|
||||||
|
|
||||||
|
var outputLength = outputs.length;
|
||||||
|
for (var outputIndex = 0; outputIndex < outputLength; outputIndex++) {
|
||||||
|
var output = outputs[outputIndex];
|
||||||
|
|
||||||
|
var script = output.script;
|
||||||
|
|
||||||
|
if(!script) {
|
||||||
|
log.debug('Invalid script');
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var address = self._getAddressString(script);
|
||||||
|
|
||||||
|
if(!address) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = self.encoding.encodeUtxoIndexKey(address, txid, outputIndex);
|
||||||
|
var value = self.encoding.encodeUtxoIndexValue(output.satoshis, output.script);
|
||||||
|
operations.push({
|
||||||
|
type: action,
|
||||||
|
key: key,
|
||||||
|
value: value
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tx.isCoinbase()) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO deal with P2PK
|
||||||
|
async.each(inputs, function(input, next) {
|
||||||
|
if(!input.script) {
|
||||||
|
log.debug('Invalid script');
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var inputAddress = self._getAddressString(input.script);
|
||||||
|
|
||||||
|
if(!inputAddress) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var inputKey = self.encoding.encodeUtxoIndexKey(inputAddress, input.prevTxId, input.outputIndex);
|
||||||
|
//common case is connecting blocks and deleting outputs spent by these inputs
|
||||||
|
if (connectBlock) {
|
||||||
|
operations.push({
|
||||||
|
type: 'del',
|
||||||
|
key: inputKey
|
||||||
|
});
|
||||||
|
} else { // uncommon and slower, this happens during a reorg
|
||||||
|
self.node.services.transaction.getTransaction(input.prevTxId, {}, function(err, tx) {
|
||||||
|
var utxo = tx.outputs[input.outputIndex];
|
||||||
|
var inputValue = self.encoding.encodeUtxoIndexValue(utxo.satoshis, utxo.script);
|
||||||
|
operations.push({
|
||||||
|
type: 'put',
|
||||||
|
key: inputKey,
|
||||||
|
value: inputValue
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function(err) {
|
||||||
|
if(err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
|
//we are aync predicated on reorg sitch
|
||||||
|
setImmediate(function() {
|
||||||
|
callback(null, operations);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
AddressService.prototype._getAddressString = function(script, output) {
|
AddressService.prototype._getAddressString = function(script, output) {
|
||||||
var address = script.toAddress();
|
var address = script.toAddress();
|
||||||
if(address) {
|
if(address) {
|
||||||
@ -242,7 +341,7 @@ AddressService.prototype._getAddressString = function(script, output) {
|
|||||||
return pubkey.toString('hex');
|
return pubkey.toString('hex');
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
log.warn('Error getting public key from: ', script.toASM(), script.toHex());
|
//log.warn('Error getting public key from: ', script.toASM(), script.toHex());
|
||||||
// if there is an error, it's because a pubkey can not be extracted from the script
|
// if there is an error, it's because a pubkey can not be extracted from the script
|
||||||
// continue on and return null
|
// continue on and return null
|
||||||
}
|
}
|
||||||
@ -252,7 +351,7 @@ AddressService.prototype._getAddressString = function(script, output) {
|
|||||||
return output.script.getPublicKey().toString('hex');
|
return output.script.getPublicKey().toString('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
log.warn('No utxo given for script spending a P2PK: ', script.toASM(), script.toHex());
|
//log.warn('No utxo given for script spending a P2PK: ', script.toASM(), script.toHex());
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user