diff --git a/lib/encoding.js b/lib/encoding.js index e225785d..6a054b12 100644 --- a/lib/encoding.js +++ b/lib/encoding.js @@ -2,14 +2,8 @@ var bitcore = require('bitcore-lib'); 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 exports = {}; - function Encoding(servicePrefix) { this.servicePrefix = servicePrefix; } @@ -21,12 +15,6 @@ Encoding.prototype.getTerminalKey = function(startKey) { }; 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 buffers = [this.servicePrefix, prefix]; @@ -53,7 +41,7 @@ Encoding.prototype.encodeAddressIndexKey = function(address, height, txid) { Encoding.prototype.decodeAddressIndexKey = function(buffer) { var reader = new BufferReader(buffer); - var prefix = reader.read(3); + reader.read(3); var addressSize = reader.readUInt8(); var address = reader.read(addressSize).toString('utf8'); @@ -67,6 +55,7 @@ Encoding.prototype.decodeAddressIndexKey = function(buffer) { }; Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) { +console.log('encodeUtxoIndexKey'); var prefix = new Buffer('01', 'hex'); var buffers = [this.servicePrefix, prefix]; @@ -93,7 +82,7 @@ Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) { Encoding.prototype.decodeUtxoIndexKey = function(buffer) { var reader = new BufferReader(buffer); - var prefix = reader.read(3); + reader.read(3); var addressSize = reader.readUInt8(); var address = reader.read(addressSize).toString('utf8'); @@ -230,7 +219,7 @@ Encoding.prototype.encodeWalletTransactionKey = function(walletId, height, block Encoding.prototype.decodeWalletTransactionKey = function(buffer) { var reader = new BufferReader(buffer); - var prefix = reader.read(1); + reader.read(1); var walletSize = reader.readUInt8(); var walletId = reader.read(walletSize).toString('utf8'); @@ -278,10 +267,10 @@ Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) { Encoding.prototype.decodeWalletUtxoKey = function(buffer) { var reader = new BufferReader(buffer); - var prefix = reader.read(1); + reader.read(1); - var walletIdSizeBuffer = reader.readUInt8(); - var walletIdBuffer = reader.read(walletIdSizeBuffer).toString('utf8'); + var walletIdSize = reader.readUInt8(); + var walletId = reader.read(walletIdSize).toString('utf8'); var txid = reader.read(32).toString('hex'); var outputIndex = reader.readUInt32BE(); return { @@ -347,16 +336,16 @@ Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, tx Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) { var reader = new BufferReader(buffer); - var prefix = reader.read(1); + reader.read(1); var walletIdSizeBuffer = reader.readUInt8(); - var walletIdBuffer = reader.read(walletIdSizeBuffer).toString('utf8'); + var walletId = reader.read(walletIdSizeBuffer).toString('utf8'); var satoshis = reader.readDoubleBE(); var txid = reader.read(32).toString('hex'); var outputIndex = reader.readUInt32BE(); return { walletId: walletId, - sathosis: sathosis, + satoshis: satoshis, txid: txid, outputIndex: outputIndex }; @@ -408,6 +397,21 @@ Encoding.prototype.encodeWalletValue = function(addresses, balance) { }; 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; diff --git a/lib/services/address/index.js b/lib/services/address/index.js index 52ae4d6b..17931b98 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -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) { var address = script.toAddress(); if(address) { @@ -242,7 +341,7 @@ AddressService.prototype._getAddressString = function(script, output) { return pubkey.toString('hex'); } } 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 // continue on and return null } @@ -252,7 +351,7 @@ AddressService.prototype._getAddressString = function(script, output) { 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; };