From b5d67135ae593019c342d5b714c8919db2e9a24d Mon Sep 17 00:00:00 2001 From: Chris Kleeschulte Date: Sun, 9 Jul 2017 19:50:30 -0400 Subject: [PATCH] wip --- lib/services/address/encoding.js | 68 ------ lib/services/address/index.js | 343 --------------------------- lib/services/transaction/encoding.js | 55 ----- lib/services/transaction/index.js | 160 ------------- lib/services/utxo/encoding.js | 131 ---------- lib/services/utxo/index.js | 209 ---------------- 6 files changed, 966 deletions(-) delete mode 100644 lib/services/address/encoding.js delete mode 100644 lib/services/address/index.js delete mode 100644 lib/services/transaction/encoding.js delete mode 100644 lib/services/transaction/index.js delete mode 100644 lib/services/utxo/encoding.js delete mode 100644 lib/services/utxo/index.js diff --git a/lib/services/address/encoding.js b/lib/services/address/encoding.js deleted file mode 100644 index e4a76908..00000000 --- a/lib/services/address/encoding.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -var bitcore = require('bitcore-lib'); -var BufferReader = bitcore.encoding.BufferReader; - -function Encoding(servicePrefix) { - this.servicePrefix = servicePrefix; -} - -Encoding.prototype.encodeAddressIndexKey = function(address, height, txid) { - var prefix = new Buffer('00', 'hex'); - var buffers = [this.servicePrefix, prefix]; - - var addressSizeBuffer = new Buffer(1); - addressSizeBuffer.writeUInt8(address.length); - var addressBuffer = new Buffer(address, 'utf8'); - - buffers.push(addressSizeBuffer); - buffers.push(addressBuffer); - - var heightBuffer = new Buffer(4); - heightBuffer.writeUInt32BE(height || 0); - buffers.push(heightBuffer); - - var txidBuffer = new Buffer(txid || Array(65).join('0'), 'hex'); - buffers.push(txidBuffer); - - return Buffer.concat(buffers); -}; - -Encoding.prototype.decodeAddressIndexKey = function(buffer) { - var reader = new BufferReader(buffer); - reader.read(3); - - var addressSize = reader.readUInt8(); - var address = reader.read(addressSize).toString('utf8'); - var height = reader.readUInt32BE(); - var txid = reader.read(32).toString('hex'); - return { - address: address, - height: height, - txid: txid, - }; -}; - -Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) { - var prefix = new Buffer('01', 'hex'); - var buffers = [this.servicePrefix, prefix]; - - var addressSizeBuffer = new Buffer(1); - addressSizeBuffer.writeUInt8(address.length); - var addressBuffer = new Buffer(address, 'utf8'); - - buffers.push(addressSizeBuffer); - buffers.push(addressBuffer); - - var txidBuffer = new Buffer(txid || new Array(65).join('0'), 'hex'); - buffers.push(txidBuffer); - - var outputIndexBuffer = new Buffer(4); - outputIndexBuffer.writeUInt32BE(outputIndex || 0); - buffers.push(outputIndexBuffer); - - return Buffer.concat(buffers); -}; - -module.exports = Encoding; - diff --git a/lib/services/address/index.js b/lib/services/address/index.js deleted file mode 100644 index 6ee6613b..00000000 --- a/lib/services/address/index.js +++ /dev/null @@ -1,343 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var BaseService = require('../../service'); -var inherits = require('util').inherits; -var async = require('async'); -var index = require('../../'); -var log = index.log; -var errors = index.errors; -var _ = require('lodash'); -var Encoding = require('./encoding'); -var utils = require('../../utils'); - -var AddressService = function(options) { - BaseService.call(this, options); -}; - -inherits(AddressService, BaseService); - -AddressService.dependencies = ['transaction']; - -AddressService.prototype.start = function(callback) { - var self = this; - - this.db = this.node.services.db; - this.db.getPrefix(this.name, function(err, prefix) { - - if(err) { - return callback(err); - } - - self.prefix = prefix; - - self._encoding = new Encoding(self.prefix); - self._setListeners(); - callback(); - - }); -}; - -AddressService.prototype.stop = function(callback) { - callback(); -}; - -AddressService.prototype.getAPIMethods = function() { - return [ - ['getBalance', this, this.getBalance, 2], - ['getOutputs', this, this.getOutputs, 2], - ['getUtxos', this, this.getUtxos, 2], - ['getAddressHistory', this, this.getAddressHistory, 2], - ['getAddressSummary', this, this.getAddressSummary, 1] - ]; -}; - -AddressService.prototype.getPublishEvents = function() { - return []; -}; - -AddressService.prototype._setupListeners = function() { - this._startSubscriptions(); -}; - -AddressService.prototype._startSubscriptions = function() { - - var self = this; - - if (self._subscribed) { - return; - } - - self._subscribed = true; - self.bus = self.node.openBus({remoteAddress: 'localhost'}); - - self.bus.subscribe('block/reorg'); - self.bus.on('block/block', self._onBlock.bind(self)); - self.bus.on('block/reorg', self._onReorg.bind(self)); - -}; - -AddressService.prototype._onBlock = function(block) { - -}; - -AddressService.prototype._onReorg = function(commonAncestorBlock) { -}; - - -AddressService.prototype.subscribe = function(name, emitter, addresses) { - - for(var i = 0; i < addresses.length; i++) { - var hashHex = bitcore.Address(addresses[i]).hashBuffer.toString('hex'); - if(!this.subscriptions[name][hashHex]) { - this.subscriptions[name][hashHex] = []; - } - this.subscriptions[name][hashHex].push(emitter); - } -}; - -AddressService.prototype.unsubscribe = function(name, emitter, addresses) { - - if(!addresses) { - return this.unsubscribeAll(name, emitter); - } - - for(var i = 0; i < addresses.length; i++) { - var hashHex = bitcore.Address(addresses[i]).hashBuffer.toString('hex'); - if(this.subscriptions[name][hashHex]) { - var emitters = this.subscriptions[name][hashHex]; - var index = emitters.indexOf(emitter); - if(index > -1) { - emitters.splice(index, 1); - } - } - } -}; - -AddressService.prototype.unsubscribeAll = function(name, emitter) { - - for(var hashHex in this.subscriptions[name]) { - var emitters = this.subscriptions[name][hashHex]; - var index = emitters.indexOf(emitter); - if(index > -1) { - emitters.splice(index, 1); - } - } -}; - -AddressService.prototype.getBalance = function(address, queryMempool, callback) { - this.getUtxos(address, queryMempool, function(err, outputs) { - if(err) { - return callback(err); - } - - var satoshis = outputs.map(function(output) { - return output.satoshis; - }); - - var sum = satoshis.reduce(function(a, b) { - return a + b; - }, 0); - - return callback(null, sum); - }); -}; - - -AddressService.prototype.getUtxos = function(addresses, queryMempool, callback) { - var self = this; - - if(!Array.isArray(addresses)) { - addresses = [addresses]; - } - - var utxos = []; - - async.eachSeries(addresses, function(address, next) { - self.getUtxosForAddress(address, queryMempool, function(err, unspents) { - if(err && err instanceof errors.NoOutputs) { - return next(); - } else if(err) { - return next(err); - } - - utxos = utxos.concat(unspents); - next(); - }); - }, function(err) { - callback(err, utxos); - }); -}; - -AddressService.prototype.getUtxosForAddress = function(address, queryMempool, callback) { - - var self = this; - - var stream = self.db.createReadStream({ - gte: self._encoding.encodeUtxoIndexKey(address), - lt: self._encoding.encodeUtxoIndexKey(utils.getTerminalKey(new Buffer(address))) - }); - - var utxos = []; - stream.on('data', function(data) { - var key = self._encoding.decodeUtxoIndexKey(data.key); - var value = self._encoding.decodeUtxoIndexValue(data.value); - utxos.push({ - address: key.address, - txid: key.txid, - outputIndex: key.outputIndex, - satoshis: value.satoshis, - height: value.height, - script: value.script - }); - }); - - stream.on('end', function() { - return callback(null, utxos); - }); - stream.on('error', function(err) { - if(err) { - return callback(err); - } - }); -}; - -AddressService.prototype.isUnspent = function(output, options, callback) { -}; - -AddressService.prototype.getAddressHistory = function(addresses, options, callback) { - var self = this; - - var txids = []; - - async.eachLimit(addresses, self.concurrency, function(address, next) { - self.getAddressTxids(address, options, function(err, tmpTxids) { - if(err) { - return next(err); - } - - txids = _.union(txids, tmpTxids); - return next(); - }); - }, function() { - async.mapLimit(txids, self.concurrency, function(txid, next) { - self.node.services.transaction.getTransaction(txid.toString('hex'), options, function(err, tx) { - if(err) { - return next(err); - } - - var txObj = tx.toObject(); - for(var i = 0; i < txObj.inputs.length; i++) { - txObj.inputs[i].satoshis = tx.__inputValues[i]; - } - - next(null, txObj); - }); - }, callback); - }); -}; - -AddressService.prototype.getAddressTxids = function(address, options, callback) { - var self = this; - - var opts = options || { start: 0, end: 0xffffffff, txid: new Array(65).join('0') }; - var txids = {}; - - var start = self._encoding.encodeAddressIndexKey(address, opts.start, opts.txid); - var end = self._encoding.encodeAddressIndexKey(address, opts.end, opts.txid); - - var stream = self.db.createKeyStream({ - gte: start, - lt: end - }); - - var streamErr = null; - stream.on('close', function() { - }); - - stream.on('data', function(buffer) { - var key = self._encoding.decodeAddressIndexKey(buffer); - txids[key.txid] = true; - }); - - stream.on('end', function() { - callback(streamErr, Object.keys(txids)); - }); - - stream.on('error', function(err) { - streamErr = err; - }); -}; - -AddressService.prototype.getAddressTxidsWithHeights = function(address, options, callback) { - var self = this; - - var opts = options || {}; - var txids = {}; - - var start = self._encoding.encodeAddressIndexKey(address, opts.start || 0); //the start and end must be the same length - var end = Buffer.concat([ start.slice(0, -36), new Buffer((opts.end || 'ffffffff'), 'hex') ]); - - var stream = self.db.createKeyStream({ - gte: start, - lt: end - }); - - var streamErr = null; - - stream.on('data', function(buffer) { - var key = self._encoding.decodeAddressIndexKey(buffer); - assert(key.txid.length === 64, 'AddressService, Txid: ' + key.txid + ' with length: ' + key.txid.length + ' does not resemble a txid.'); - txids[key.txid] = key.height; - }); - - stream.on('end', function() { - callback(streamErr, txids); - }); - - stream.on('error', function(err) { - streamErr = err; - }); -}; - -AddressService.prototype.getAddressSummary = function(addressArg, options, callback) { - var self = this; - - var startTime = new Date(); - var address = new Address(addressArg); - - if (_.isUndefined(options.queryMempool)) { - options.queryMempool = true; - } - - async.waterfall([ - function(next) { - self._getAddressConfirmedSummary(address, options, next); - }, - function(result, next) { - self._getAddressMempoolSummary(address, options, result, next); - }, - function(result, next) { - self._setAndSortTxidsFromAppearanceIds(result, next); - } - ], function(err, result) { - if (err) { - return callback(err); - } - - var summary = self._transformAddressSummaryFromResult(result, options); - - var timeDelta = new Date() - startTime; - if (timeDelta > 5000) { - var seconds = Math.round(timeDelta / 1000); - log.warn('Slow (' + seconds + 's) getAddressSummary request for address: ' + address.toString()); - } - - callback(null, summary); - - }); - -}; - - -module.exports = AddressService; diff --git a/lib/services/transaction/encoding.js b/lib/services/transaction/encoding.js deleted file mode 100644 index 6831fe79..00000000 --- a/lib/services/transaction/encoding.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; - -var bitcore = require('bitcore-lib'); - -function Encoding(servicePrefix) { - //if you add any more encoding keys, be sure to add a subkey - this.servicePrefix = servicePrefix; -} - -Encoding.prototype.encodeTransactionKey = function(txid) { - return Buffer.concat([this.servicePrefix, new Buffer(txid, 'hex')]); -}; - -Encoding.prototype.decodeTransactionKey = function(buffer) { - return buffer.slice(2).toString('hex'); -}; - -Encoding.prototype.encodeTransactionValue = function(transaction) { - var heightBuffer = new Buffer(4); - heightBuffer.writeUInt32BE(transaction.__height); - - var timestampBuffer = new Buffer(8); - timestampBuffer.writeDoubleBE(transaction.__timestamp); - - var inputValues = transaction.__inputValues; - var inputValuesBuffer = new Buffer(8 * inputValues.length); - for(var i = 0; i < inputValues.length; i++) { - inputValuesBuffer.writeDoubleBE(inputValues[i], i * 8); - } - - var inputValuesLengthBuffer = new Buffer(2); - inputValuesLengthBuffer.writeUInt16BE(inputValues.length); - - return new Buffer.concat([heightBuffer, timestampBuffer, - inputValuesLengthBuffer, inputValuesBuffer, transaction.toBuffer()]); -}; - -Encoding.prototype.decodeTransactionValue = function(buffer) { - var height = buffer.readUInt32BE(); - var timestamp = buffer.readDoubleBE(4); - - var inputValuesLength = buffer.readUInt16BE(12); - var inputValues = []; - for(var i = 0; i < inputValuesLength; i++) { - inputValues.push(buffer.readDoubleBE(i * 8 + 14)); - } - var transaction = new bitcore.Transaction(buffer.slice(inputValues.length * 8 + 14)); - transaction.__height = height; - transaction.__inputValues = inputValues; - transaction.__timestamp = timestamp; - return transaction; -}; - -module.exports = Encoding; - diff --git a/lib/services/transaction/index.js b/lib/services/transaction/index.js deleted file mode 100644 index de4fa198..00000000 --- a/lib/services/transaction/index.js +++ /dev/null @@ -1,160 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var async = require('async'); -var BaseService = require('../../service'); -var inherits = require('util').inherits; -var Encoding = require('./encoding'); -var levelup = require('levelup'); - -function TransactionService(options) { - BaseService.call(this, options); - this.concurrency = options.concurrency || 20; - this.currentTransactions = {}; -} - -inherits(TransactionService, BaseService); - -TransactionService.dependencies = [ - 'db', - 'timestamp', - 'mempool' -]; - -TransactionService.prototype.start = function(callback) { - var self = this; - - self.db = this.node.services.db; - - self.db.getPrefix(self.name, function(err, prefix) { - if(err) { - return callback(err); - } - self.prefix = prefix; - self.encoding = new Encoding(self.prefix); - self._setListeners(); - callback(); - }); -}; - -TransactionService.prototype.stop = function(callback) { - setImmediate(callback); -}; - - -TransactionService.prototype._setListeners = function() { - this._startSubscriptions(); -}; - -TransactionService.prototype._startSubscriptions = function() { - var self = this; - - if (self._subscribed) { - return; - } - - self._subscribed = true; - self.bus = self.node.openBus({remoteAddress: 'localhost'}); - - self.bus.on('block/block', self._onBlock.bind(self)); - self.bus.subscribe('block/block'); - -}; - -TransactionService.prototype._onBlock = function(block) { -}; - -TransactionService.prototype._getMissingInputValues = function(tx, callback) { - var self = this; - - if (tx.isCoinbase()) { - return callback(null, []); - } - - async.eachOf(tx.inputs, function(input, index, next) { - if (tx.__inputValues[index]) { - return next(); - } - self.getTransaction(input.prevTxId.toString('hex'), {}, function(err, prevTx) { - if(err) { - return next(err); - } - if (!prevTx) { - return next(new Error('previous Tx missing.')); - } - if (!prevTx.outputs[input.outputIndex]) { - return next(new Error('Input did not have utxo.')); - } - var satoshis = prevTx.outputs[input.outputIndex].satoshis; - tx.__inputValues[index] = satoshis; - next(); - }); - }, callback); -}; - -TransactionService.prototype._getInputValues = function(tx, callback) { - var self = this; - - if (tx.isCoinbase()) { - return callback(null, []); - } - - async.mapLimit(tx.inputs, this.concurrency, function(input, next) { - self.getTransaction(input.prevTxId.toString('hex'), {}, function(err, prevTx) { - if(err) { - return next(err); - } - if (!prevTx.outputs[input.outputIndex]) { - return next(new Error('Input did not have utxo: ' + prevTx.id + ' for tx: ' + tx.id)); - } - var satoshis = prevTx.outputs[input.outputIndex].satoshis; - next(null, satoshis); - }); - }, callback); -}; - -TransactionService.prototype.getTransaction = function(txid, options, callback) { - var self = this; - - assert(txid.length === 64, 'Transaction, Txid: ' + - txid + ' with length: ' + txid.length + ' does not resemble a txid.'); - - if(self.currentTransactions[txid]) { - return setImmediate(function() { - callback(null, self.currentTransactions[txid]); - }); - } - - var key = self.encoding.encodeTransactionKey(txid); - - async.waterfall([ - function(next) { - self.node.services.db.get(key, function(err, buffer) { - if (err instanceof levelup.errors.NotFoundError) { - return next(null, false); - } else if (err) { - return callback(err); - } - var tx = self.encoding.decodeTransactionValue(buffer); - next(null, tx); - }); - }, function(tx, next) { - if (tx) { - return next(null, tx); - } - if (!options || !options.queryMempool) { - return next(new Error('Transaction: ' + txid + ' not found in index')); - } - self.node.services.mempool.getTransaction(txid, function(err, tx) { - if (err instanceof levelup.errors.NotFoundError) { - return callback(new Error('Transaction: ' + txid + ' not found in index or mempool')); - } else if (err) { - return callback(err); - } - self._getMissingInputValues(tx, next); - }); - }], callback); -}; - - -module.exports = TransactionService; diff --git a/lib/services/utxo/encoding.js b/lib/services/utxo/encoding.js deleted file mode 100644 index b52ccc59..00000000 --- a/lib/services/utxo/encoding.js +++ /dev/null @@ -1,131 +0,0 @@ -'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) { - - assert(address, 'address is required'); - var buffers = [this.servicePrefix, this.nonP2PKPrefix]; - - var addressSizeBuffer = new Buffer(1); - addressSizeBuffer.writeUInt8(address.length); - var addressBuffer = new Buffer(address, 'utf8'); - - buffers.push(addressSizeBuffer); - buffers.push(addressBuffer); - - if (txid) { - var txidBuffer = new Buffer(txid, 'hex'); - buffers.push(txidBuffer); - } - - if (outputIndex >= 0) { - var outputIndexBuffer = new Buffer(4); - outputIndexBuffer.writeUInt32BE(outputIndex); - buffers.push(outputIndexBuffer); - } - - return Buffer.concat(buffers); -}; - -Encoding.prototype.decodeUtxoIndexKey = 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.encodeUtxoIndexValue = 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.decodeUtxoIndexValue = function(buffer) { - - var height = buffer.readUInt32BE(); - var satoshis = buffer.readDoubleBE(4); - var scriptBuffer = buffer.slice(12); - return { - height: height, - satoshis: satoshis, - script: scriptBuffer - }; - -}; - -Encoding.prototype.encodeP2PKUtxoIndexKey = function(txid, outputIndex) { - - assert(txid, 'txid is required'); - var buffers = [this.servicePrefix, this.P2PKPrefix]; - - 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; - diff --git a/lib/services/utxo/index.js b/lib/services/utxo/index.js deleted file mode 100644 index 1505f9f8..00000000 --- a/lib/services/utxo/index.js +++ /dev/null @@ -1,209 +0,0 @@ -'use strict'; - -var BaseService = require('../../service'); -var inherits = require('util').inherits; -var Encoding = require('./encoding'); -var utils = require('../../utils'); -var index = require('../../'); -var log = index.log; - -function UtxoService(options) { - BaseService.call(this, options); - this._exclusionIndexes = []; -} - -inherits(UtxoService, BaseService); - -UtxoService.dependencies = ['db']; - -UtxoService.prototype.start = function(callback) { - var self = this; - - self.db = this.node.services.db; - - self.db.getPrefix(self.name, function(err, prefix) { - if (err) { - return callback(err); - } - self.prefix = prefix; - self.encoding = new Encoding(self.prefix); - callback(); - }); -}; - -UtxoService.prototype.stop = function(callback) { - if (callback) { - setImmediate(callback); - } -}; - -UtxoService.prototype.blockHandler = function(block, connect, callback) { - - var self = this; - - self._exclusionIndexes.length = 0; - var operations = []; - - for(var i = 0; i < block.transactions.length; i++) { - - var tx = block.transactions[i]; - var inputs = tx.inputs; - var outputs = tx.outputs; - - if (!tx.isCoinbase()) { - operations = self._processInputs(tx, inputs, connect).concat(operations); - } - - operations = self._processOutputs(tx, outputs, block, connect).concat(operations); - } - - setImmediate(function() { - callback(null, operations); - }); -}; - -UtxoService.prototype.getUtxosForAddress = function(address, callback) { - - var self = this; - var utxos = []; - - var start = self.encoding.encodeUtxoIndexKey(address); - - var stream = self.db.createReadStream({ - gte: start, - lt: utils.getTerminalKey(start) - }); - - stream.on('data', function(data) { - - var key = self.encoding.decodeUtxoIndexKey(data.key); - var value = self.encoding.decodeUtxoIndexValue(data.value); - utxos.push({ - address: address, - txId: key.txid, - outputIndex: key.outputIndex, - height: value.height, - satoshis: value.satoshis, - script: value.script.toString('hex') - }); - }); - - stream.on('end', function() { - callback(null, utxos); - }); -}; - -UtxoService.prototype._processInputs = function(tx, inputs, connect) { - - var operations = []; - for(var i = 0; i < inputs.length; i++) { - - var input = inputs[i]; - - if (input.prevTxId === tx.hash) { - this._exlusionIndexes.push(i); - continue; - } - - 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; - -}; - -UtxoService.prototype._processOutputs = function(tx, outputs, block, connect) { - - var operations = []; - for(var i = 0; i < outputs.length; i++) { - - var output = outputs[i]; - - if (this._exclusionIndexes.indexOf(i) > -1) { - continue; - } - - 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) { -//console.log(this.encoding.decodeUtxoIndexKey(key)); - var operation = connect ? { - type: 'put', - key: key, - value: value - } : { - type: 'del', - key: key, - value: value - }; - - operations.push(operation); - } - - - } - - return operations; - -}; - -UtxoService.prototype._getOperationsKey = function(io) { - - var address = utils.getAddressStringFromScript(io.script, this.node.network); - - if (!address) { - var key = this._tryP2PKOperation(io); - if (key) { - return key; - } - } - - 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._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) { - return this.encoding.encodeUtxoIndexValue(value.height, value.satoshis, value.script.toBuffer()); -}; - -module.exports = UtxoService;