wip
This commit is contained in:
parent
d6f1f26469
commit
443688face
@ -1,15 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var bitcore = require('bitcore-lib');
|
||||
var BufferReader = bitcore.encoding.BufferReader;
|
||||
|
||||
function Encoding(servicePrefix) {
|
||||
this.servicePrefix = servicePrefix;
|
||||
this.nonP2PKPrefix = new Buffer('00', 'hex');
|
||||
this.P2PKPrefix = new Buffer('01', 'hex');
|
||||
}
|
||||
|
||||
Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
|
||||
var prefix = new Buffer('01', 'hex');
|
||||
var buffers = [this.servicePrefix, prefix];
|
||||
var buffers = [this.servicePrefix, this.nonP2PKPrefix];
|
||||
|
||||
var addressSizeBuffer = new Buffer(1);
|
||||
addressSizeBuffer.writeUInt8(address.length);
|
||||
@ -63,5 +65,56 @@ Encoding.prototype.decodeUtxoIndexValue = function(buffer) {
|
||||
};
|
||||
};
|
||||
|
||||
Encoding.prototype.encodeP2PKUtxoIndexKey = function(txid, outputIndex) {
|
||||
var buffers = [this.servicePrefix, this.P2PKPrefix];
|
||||
|
||||
assert(txid && txid.length === 64, 'Txid required');
|
||||
assert(outputIndex >= 0, 'outputIndex required');
|
||||
|
||||
var txidBuffer = new Buffer(txid);
|
||||
buffers.push(txidBuffer);
|
||||
|
||||
var outputIndexBuffer = new Buffer(4);
|
||||
outputIndexBuffer.writeUInt32BE(outputIndex);
|
||||
buffers.push(outputIndexBuffer);
|
||||
|
||||
return Buffer.concat(buffers);
|
||||
};
|
||||
|
||||
Encoding.prototype.decodeP2PKUtxoIndexKey = function(buffer) {
|
||||
var reader = new BufferReader(buffer);
|
||||
reader.read(3);
|
||||
|
||||
var addressSize = reader.readUInt8();
|
||||
var address = reader.read(addressSize).toString('utf8');
|
||||
var txid = reader.read(32).toString('hex');
|
||||
var outputIndex = reader.readUInt32BE(4);
|
||||
|
||||
return {
|
||||
address: address,
|
||||
txid: txid,
|
||||
outputIndex: outputIndex
|
||||
};
|
||||
};
|
||||
|
||||
Encoding.prototype.encodeP2PKUtxoIndexValue = function(height, satoshis, scriptBuffer) {
|
||||
var heightBuffer = new Buffer(4);
|
||||
heightBuffer.writeUInt32BE(height);
|
||||
var satoshisBuffer = new Buffer(8);
|
||||
satoshisBuffer.writeDoubleBE(satoshis);
|
||||
return Buffer.concat([heightBuffer, satoshisBuffer, scriptBuffer]);
|
||||
};
|
||||
|
||||
Encoding.prototype.decodeP2PKUtxoIndexValue = function(buffer) {
|
||||
var height = buffer.readUInt32BE();
|
||||
var satoshis = buffer.readDoubleBE(4);
|
||||
var scriptBuffer = buffer.slice(12);
|
||||
return {
|
||||
height: height,
|
||||
satoshis: satoshis,
|
||||
script: scriptBuffer
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = Encoding;
|
||||
|
||||
|
||||
@ -3,8 +3,9 @@
|
||||
var BaseService = require('../../service');
|
||||
var inherits = require('util').inherits;
|
||||
var Encoding = require('./encoding');
|
||||
var LRU = require('lru-cache');
|
||||
var utils = require('../../utils');
|
||||
var index = require('../../');
|
||||
var log = index.log;
|
||||
|
||||
function UtxoService(options) {
|
||||
BaseService.call(this, options);
|
||||
@ -79,7 +80,7 @@ UtxoService.prototype.getUtxosForAddress = function(address, callback) {
|
||||
address: address,
|
||||
height: value.height,
|
||||
satoshis: value.satoshis,
|
||||
script: value.scriptBuffer
|
||||
script: value.script
|
||||
});
|
||||
});
|
||||
|
||||
@ -92,17 +93,32 @@ UtxoService.prototype._processInputs = function(tx, inputs, connect) {
|
||||
|
||||
var operations = [];
|
||||
for(var i = 0; i < inputs.length; i++) {
|
||||
var input = inputs[i];
|
||||
|
||||
var key = input.prevHash + input.outputIndex;
|
||||
var input = inputs[i];
|
||||
|
||||
if (input.prevTxId === tx.hash) {
|
||||
this._exlusionIndexes.push(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
var ops = this._moveOutput(key, connect);
|
||||
operations = operations.concat(ops);
|
||||
var key = this._getOperationsKey({
|
||||
script: input.script,
|
||||
txid: input.prevTxId.toString('hex'),
|
||||
index: input.outputIndex
|
||||
});
|
||||
|
||||
if (key) {
|
||||
var operation = connect ? {
|
||||
type: 'del',
|
||||
key: key
|
||||
} : {
|
||||
type: 'put',
|
||||
key: key,
|
||||
value: new Buffer('00', 'hex')
|
||||
};
|
||||
|
||||
operations.push(operation);
|
||||
}
|
||||
}
|
||||
|
||||
return operations;
|
||||
@ -115,42 +131,70 @@ UtxoService.prototype._processOutputs = function(tx, outputs, block, connect) {
|
||||
for(var i = 0; i < outputs.length; i++) {
|
||||
|
||||
var output = outputs[i];
|
||||
var key = tx.hash + i;
|
||||
|
||||
if (this._exclusionIndexes.indexOf(i) > -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var action = connect ? 'put' : 'del';
|
||||
operations = operations.concat(
|
||||
{ action: action,
|
||||
key: this._getOperationsKey(key, output),
|
||||
value: this._getOperationsValue({
|
||||
height: block.__height,
|
||||
satoshis: output.satoshis,
|
||||
script: output.script
|
||||
})
|
||||
}
|
||||
);
|
||||
var key = this._getOperationsKey({
|
||||
script: output.script,
|
||||
txid: tx.id,
|
||||
index: i
|
||||
});
|
||||
|
||||
var value = this._getOperationsValue({
|
||||
height: block.__height,
|
||||
satoshis: output.satoshis,
|
||||
script: output.script
|
||||
});
|
||||
|
||||
if (key && value) {
|
||||
var operation = connect ? {
|
||||
type: 'put',
|
||||
key: key,
|
||||
value: value
|
||||
} : {
|
||||
type: 'del',
|
||||
key: key,
|
||||
value: value
|
||||
};
|
||||
|
||||
operations.push(operation);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return operations;
|
||||
|
||||
};
|
||||
|
||||
UtxoService.prototype._moveOutput = function(key, connect) {
|
||||
UtxoService.prototype._getOperationsKey = function(io) {
|
||||
|
||||
if (connect) {
|
||||
return { action: 'del', key: key };
|
||||
var address = utils.getAddressStringFromScript(io.script, this.node.network);
|
||||
|
||||
if (!address) {
|
||||
var key = this._tryP2PKOperation(io);
|
||||
if (key) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return { action: 'put', key: key, value: null };
|
||||
if (!address) {
|
||||
log.debug('could not determine address for script: ' + io.script.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
return this.encoding.encodeUtxoIndexKey(address, io.txid, io.index);
|
||||
};
|
||||
|
||||
UtxoService.prototype._getOperationsKey = function(key, output) {
|
||||
var address = utils.getAddressStringFromScript(output.script, this.node.network);
|
||||
return this.encoding.encodeUtxoIndexKey(address, key.slice(0, 64), parseInt(key.slice(64)));
|
||||
UtxoService.prototype._tryP2PKOperation = function(io) {
|
||||
|
||||
// checking for a scriptSig that has one signature
|
||||
var sig = io.script.chunks[0];
|
||||
if (sig && (sig.len > 69 && sig.len < 75)) {
|
||||
return this.encoding.encodeP2PKUtxoIndexKey(io.txid, io.index);
|
||||
}
|
||||
};
|
||||
|
||||
UtxoService.prototype._getOperationsValue = function(value) {
|
||||
|
||||
@ -121,6 +121,7 @@ describe('Utxo Operations', function() {
|
||||
utils.waitForBitcoinReady.bind(utils, self.opts),
|
||||
utils.unlockWallet.bind(utils, self.opts),
|
||||
utils.setupInitialTxs.bind(utils, self.opts),
|
||||
utils.sendTxs.bind(utils, self.opts),
|
||||
utils.startBitcoreNode.bind(utils, self.opts),
|
||||
utils.waitForBitcoreNode.bind(utils, self.opts)
|
||||
], done);
|
||||
@ -140,6 +141,8 @@ describe('Utxo Operations', function() {
|
||||
|
||||
res = JSON.parse(res);
|
||||
expect(res.address).to.equal(address);
|
||||
expect(res.utxos.length).equal(1);
|
||||
expect(Object.keys(res.utxos[0])).to.deep.equal([ 'txid', 'outputIndex', 'address', 'height', 'satoshis', 'script' ]);
|
||||
next(null, res.utxos);
|
||||
});
|
||||
}, function(err, utxos) {
|
||||
@ -147,7 +150,6 @@ describe('Utxo Operations', function() {
|
||||
if(err) {
|
||||
return done(err);
|
||||
}
|
||||
console.log('done');
|
||||
|
||||
done();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user