diff --git a/lib/services/address/constants.js b/lib/constants.js similarity index 100% rename from lib/services/address/constants.js rename to lib/constants.js diff --git a/lib/encoding.js b/lib/encoding.js new file mode 100644 index 00000000..e225785d --- /dev/null +++ b/lib/encoding.js @@ -0,0 +1,413 @@ +'use strict'; + +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; +} + +Encoding.prototype.getTerminalKey = function(startKey) { + var endKey = Buffer.from(startKey); + endKey.writeUInt8(startKey.readUInt8(startKey.length - 1) + 1, startKey.length - 1); + return endKey; +}; + +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]; + + var addressSizeBuffer = new Buffer(1); + addressSizeBuffer.writeUInt8(address.length); + var addressBuffer = new Buffer(address, 'utf8'); + + buffers.push(addressSizeBuffer); + buffers.push(addressBuffer); + + if(height !== undefined) { + var heightBuffer = new Buffer(4); + heightBuffer.writeUInt32BE(height); + buffers.push(heightBuffer); + } + + if(txid) { + var txidBuffer = new Buffer(txid, 'hex'); + buffers.push(txidBuffer); + } + + return Buffer.concat(buffers); +}; + +Encoding.prototype.decodeAddressIndexKey = function(buffer) { + var reader = new BufferReader(buffer); + var prefix = 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); + + if(txid) { + var txidBuffer = new Buffer(txid, 'hex'); + buffers.push(txidBuffer); + } + + if(outputIndex !== undefined) { + 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); + var prefix = 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(satoshis, scriptBuffer) { + var satoshisBuffer = new Buffer(8); + satoshisBuffer.writeDoubleBE(satoshis); + return Buffer.concat([satoshisBuffer, scriptBuffer]); +}; + +Encoding.prototype.decodeUtxoIndexValue = function(buffer) { + var satoshis = buffer.readDoubleBE(0); + var scriptBuffer = buffer.slice(8, buffer.length); + return { + satoshis: satoshis, + script: scriptBuffer + }; +}; + +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 * 8); + + 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 inputValues = []; + var inputValuesLength = buffer.readUInt16BE(12); + for(var i = 0; i < inputValuesLength / 8; 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; +}; + +Encoding.prototype.encodeBlockTimestampKey = function(hash) { + return Buffer.concat([this.servicePrefix, new Buffer(hash, 'hex')]); +}; + +Encoding.prototype.decodeBlockTimestampKey = function(buffer) { + return buffer.slice(2).toString('hex'); +}; + +Encoding.prototype.encodeBlockTimestampValue = function(timestamp) { + var timestampBuffer = new Buffer(new Array(8)); + timestampBuffer.writeDoubleBE(timestamp); + return timestampBuffer; +}; + +Encoding.prototype.decodeBlockTimestampValue = function(buffer) { + return buffer.readDoubleBE(0); +}; + +Encoding.prototype.encodeTimestampBlockKey = function(timestamp) { + var timestampBuffer = new Buffer(new Array(8)); + timestampBuffer.writeDoubleBE(timestamp); + return Buffer.concat([this.servicePrefix, timestampBuffer]); +}; + +Encoding.prototype.decodeTimestampBlockKey = function(buffer) { + return buffer.readDoubleBE(2); +}; + +Encoding.prototype.encodeTimestampBlockValue = function(hash) { + return new Buffer(hash, 'hex'); +}; + +Encoding.prototype.decodeTimestampBlockValue = function(buffer) { + return buffer.toString('hex'); +}; + +Encoding.prototype.encodeWalletTransactionKey = function(walletId, height, blockIndex) { + var buffers = [this.servicePrefix]; + + var walletIdSizeBuffer = new Buffer(1); + walletIdSizeBuffer.writeUInt8(walletId.length); + var walletIdBuffer = new Buffer(walletId, 'utf8'); + + buffers.push(walletIdSizeBuffer); + buffers.push(walletIdBuffer); + + if(height !== undefined) { + var heightBuffer = new Buffer(4); + heightBuffer.writeUInt32BE(height); + buffers.push(heightBuffer); + } + + if(blockIndex !== undefined) { + var blockIndexBuffer = new Buffer(4); + blockIndexBuffer.writeUInt32BE(blockIndex); + buffers.push(blockIndexBuffer); + } + + return Buffer.concat(buffers); +}; + +Encoding.prototype.decodeWalletTransactionKey = function(buffer) { + var reader = new BufferReader(buffer); + var prefix = reader.read(1); + + var walletSize = reader.readUInt8(); + var walletId = reader.read(walletSize).toString('utf8'); + var height = reader.readUInt32BE(); + var blockIndex = reader.readUInt32BE(); + + return { + walletId: walletId, + height: height, + blockIndex: blockIndex + }; +}; + +Encoding.prototype.encodeWalletTransactionValue = function(txid) { + return new Buffer(txid, 'hex'); +}; + +Encoding.prototype.decodeWalletTransactionValue = function(buffer) { + return buffer.toString('hex'); +}; + +Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) { + var buffers = [this.servicePrefix]; + + var walletIdSizeBuffer = new Buffer(1); + walletIdSizeBuffer.writeUInt8(walletId.length); + var walletIdBuffer = new Buffer(walletId, 'utf8'); + + buffers.push(walletIdSizeBuffer); + buffers.push(walletIdBuffer); + + if(txid) { + var txidBuffer = new Buffer(txid, 'hex'); + buffers.push(txidBuffer); + } + + if(outputIndex !== undefined) { + var outputIndexBuffer = new Buffer(4); + outputIndexBuffer.writeUInt32BE(outputIndex); + buffers.push(outputIndexBuffer); + } + + return Buffer.concat(buffers); +}; + +Encoding.prototype.decodeWalletUtxoKey = function(buffer) { + var reader = new BufferReader(buffer); + var prefix = reader.read(1); + + var walletIdSizeBuffer = reader.readUInt8(); + var walletIdBuffer = reader.read(walletIdSizeBuffer).toString('utf8'); + var txid = reader.read(32).toString('hex'); + var outputIndex = reader.readUInt32BE(); + return { + walletId: walletId, + txid: txid, + outputIndex: outputIndex + }; +}; + +Encoding.prototype.encodeWalletUtxoValue = function(height, satoshis, address) { + var heightBuffer = new Buffer(4); + heightBuffer.writeUInt32BE(height); + var satoshisBuffer = new Buffer(8); + satoshisBuffer.writeDoubleBE(satoshis); + var addressSizeBuffer = new Buffer(1); + addressSizeBuffer.writeUInt8(address.length); + var addressBuffer = new Buffer(address, 'utf8'); + return Buffer.concat([height, satoshisBuffer, addressBuffer]); +}; + +Encoding.prototype.decodeWalletUtxoValue = function(buffer) { + var reader = new BufferReader(buffer); + var height = reader.readUInt32BE(); + var satoshis = reader.readDoubleBE(); + var addressSize = reader.readUInt8(); + var address = reader.read(addressSize).toString('utf8'); + return { + height: height, + satoshis: satoshis, + address: address + }; +}; + +Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, txid, outputIndex) { + var buffers = [this.servicePrefix]; + + var walletIdSizeBuffer = new Buffer(1); + walletIdSizeBuffer.writeUInt8(walletId.length); + var walletIdBuffer = new Buffer(walletId, 'utf8'); + + buffers.push(walletIdSizeBuffer); + buffers.push(walletIdBuffer); + + if(satoshis !== undefined) { + var satoshisBuffer = new Buffer(8); + satoshisBuffer.writeUInt32BE(satoshis); + buffers.push(satoshisBuffer); + } + + if(txid) { + var txidBuffer = new Buffer(txid, 'hex'); + buffers.push(txidBuffer); + } + + if(outputIndex !== undefined) { + var outputIndexBuffer = new Buffer(4); + outputIndexBuffer.writeUInt32BE(outputIndex); + buffers.push(outputIndexBuffer); + } + + return Buffer.concat(buffers); +}; + +Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) { + var reader = new BufferReader(buffer); + var prefix = reader.read(1); + + var walletIdSizeBuffer = reader.readUInt8(); + var walletIdBuffer = 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, + txid: txid, + outputIndex: outputIndex + }; +}; + +Encoding.prototype.encodeWalletUtxoSatoshisValue = function(height, address) { + var heightBuffer = new Buffer(4); + heightBuffer.writeUInt32BE(height); + var addressSizeBuffer = new Buffer(1); + addressSizeBuffer.writeUInt8(address.length); + var addressBuffer = new Buffer(address, 'utf8'); + return Buffer.concat([height, addressBuffer]); +}; + +Encoding.prototype.decodeWalletUtxoSatoshisValue = function(buffer) { + var reader = new BufferReader(buffer); + var height = reader.readUInt32BE(); + var addressSize = reader.readUInt8(); + var address = reader.read(addressSize).toString('utf8'); + return { + height: height, + address: address + }; +}; + +Encoding.prototype.encodeWalletKey = function(walletId) { + return new Buffer(walletId, 'hex'); +}; + +Encoding.prototype.decodeWalletKey = function(buffer) { + return buffer.toString('hex'); +}; + +Encoding.prototype.encodeWalletValue = function(addresses, balance) { + var bufferList = []; + var addressesLengthBuffer = new Buffer(4); + addressesLengthBuffer.writeUInt32BE(addresses.length); + bufferList.push(addressesLengthBuffer); + for(var i = 0; i < addresses.length; i++) { + var addressSizeBuffer = new Buffer(1); + addressSizeBuffer.writeUInt8(addresses[i].length); + bufferList.push(addressSizeBuffer); + bufferList.push(new Buffer(addresses[i], 'utf8')); + } + var balanceBuffer = new Buffer(8); + balanceBuffer.writeUInt32BE(balance); + bufferList.push(balanceBuffer); + return Buffer.concat(bufferList); +}; + +Encoding.prototype.decodeWalletValue = function(buffer) { +}; + +module.exports = Encoding; diff --git a/lib/services/address/encoding.js b/lib/services/address/encoding.js deleted file mode 100644 index 93464f8f..00000000 --- a/lib/services/address/encoding.js +++ /dev/null @@ -1,474 +0,0 @@ -'use strict'; - -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('../wallet-api/utils'); - -var exports = {}; - -function Encoding(servicePrefix) { - this.servicePrefix = servicePrefix; -} - -Encoding.prototype.getTerminalKey = function(startKey) { - var endKey = Buffer.from(startKey); - endKey.writeUInt8(startKey.readUInt8(startKey.length - 1) + 1, startKey.length - 1); - return endKey; -}; - -Encoding.prototype.encodeAddressIndexKey = function(address, height, txid) { - // TODO if later params are given but not earlier ones, throw an error - var args = Array.prototype.slice.call(arguments); - //if (!utils.hasRequiredArgsForEncoding(args)) { - // return null; - //} - 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); - - if(height !== undefined) { - var heightBuffer = new Buffer(4); - heightBuffer.writeUInt32BE(height); - buffers.push(heightBuffer); - } - - if(txid) { - var txidBuffer = new Buffer(txid, 'hex'); - buffers.push(txidBuffer); - } - - return Buffer.concat(buffers); -}; - -Encoding.prototype.decodeAddressIndexKey = function(buffer) { - var reader = new BufferReader(buffer); - var prefix = 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); - - if(txid) { - var txidBuffer = new Buffer(txid, 'hex'); - buffers.push(txidBuffer); - } - - if(outputIndex !== undefined) { - 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); - var prefix = 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(satoshis, scriptBuffer) { - var satoshisBuffer = new Buffer(8); - satoshisBuffer.writeDoubleBE(satoshis); - return Buffer.concat([satoshisBuffer, scriptBuffer]); -}; - -Encoding.prototype.decodeUtxoIndexValue = function(buffer) { - var satoshis = buffer.readDoubleBE(0); - var scriptBuffer = buffer.slice(8, buffer.length); - return { - satoshis: satoshis, - script: scriptBuffer - }; -}; -// exports.encodeUnspentIndexKey = function(hashTypeBuffer, hashBuffer, txid, index) { -// var indexBuffer = new Buffer(4); -// indexBuffer.writeUInt32BE(index); -// var txidBuffer = new Buffer(txid, 'hex'); - -// var key = Buffer.concat([ -// constants.PREFIXES.UNSPENT, -// hashTypeBuffer, -// hashBuffer, -// constants.SPACER_MIN, -// txidBuffer, -// indexBuffer -// ]); -// }; - -// exports.decodeUnspentIndexKey = function(buffer) { -// var reader = new BufferReader(buffer); -// var prefix = reader.read(1); -// var hashTypeBuffer = reader.read(1); -// var hashBuffer = reader.read(20); - -// var spacer = reader.read(1); -// var txid = reader.read(32); -// var index = reader.readUInt32BE(); -// return { -// prefix: prefix, -// hashTypeBuffer: hashTypeBuffer, -// hashBuffer: hashBuffer, -// txid: txid, -// index: outputIndex -// }; -// }; - -// exports.encodeUnspentIndexValue = function(satoshis, height, scriptBuffer) { -// var satoshisBuffer = new Buffer(8); -// satoshisBuffer.writeDoubleBE(satoshis); - -// var heightBuffer = new Buffer(4); -// heightBuffer.writeUInt32BE(height); - -// return Buffer.concat([satoshisBuffer, heightBuffer, scriptBuffer]); -// }; - -// exports.decodeUnspentIndexValue = function(buffer) { -// var satoshis = buffer.readDoubleBE(0); -// var height = buffer.readUInt32BE(8); -// var scriptBuffer = buffer.slice(12, buffer.length); - -// return { -// satoshis: satoshis, -// height: height, -// scriptBuffer: scriptBuffer -// }; -// }; - - -// exports.encodeSpentIndexSyncKey = function(txidBuffer, outputIndex) { -// var outputIndexBuffer = new Buffer(4); -// outputIndexBuffer.writeUInt32BE(outputIndex); -// var key = Buffer.concat([ -// txidBuffer, -// outputIndexBuffer -// ]); -// return key.toString('binary'); -// }; - -// exports.encodeMempoolAddressIndexKey = function(hashBuffer, hashTypeBuffer) { -// var key = Buffer.concat([ -// hashBuffer, -// hashTypeBuffer, -// ]); -// return key.toString('binary'); -// }; - - -// exports.encodeOutputKey = function(hashBuffer, hashTypeBuffer, height, txidBuffer, outputIndex) { -// var heightBuffer = new Buffer(4); -// heightBuffer.writeUInt32BE(height); -// var outputIndexBuffer = new Buffer(4); -// outputIndexBuffer.writeUInt32BE(outputIndex); -// var key = Buffer.concat([ -// constants.PREFIXES.OUTPUTS, -// hashBuffer, -// hashTypeBuffer, -// constants.SPACER_MIN, -// heightBuffer, -// txidBuffer, -// outputIndexBuffer -// ]); -// return key; -// }; - -// exports.decodeOutputKey = function(buffer) { -// var reader = new BufferReader(buffer); -// var prefix = reader.read(1); -// var hashBuffer = reader.read(20); -// var hashTypeBuffer = reader.read(1); -// var spacer = reader.read(1); -// var height = reader.readUInt32BE(); -// var txid = reader.read(32); -// var outputIndex = reader.readUInt32BE(); -// return { -// prefix: prefix, -// hashBuffer: hashBuffer, -// hashTypeBuffer: hashTypeBuffer, -// height: height, -// txid: txid, -// outputIndex: outputIndex -// }; -// }; - -// exports.encodeOutputValue = function(satoshis, scriptBuffer) { -// var satoshisBuffer = new Buffer(8); -// satoshisBuffer.writeDoubleBE(satoshis); -// return Buffer.concat([satoshisBuffer, scriptBuffer]); -// }; - -// exports.encodeOutputMempoolValue = function(satoshis, timestampBuffer, scriptBuffer) { -// var satoshisBuffer = new Buffer(8); -// satoshisBuffer.writeDoubleBE(satoshis); -// return Buffer.concat([satoshisBuffer, timestampBuffer, scriptBuffer]); -// }; - -// exports.decodeOutputValue = function(buffer) { -// var satoshis = buffer.readDoubleBE(0); -// var scriptBuffer = buffer.slice(8, buffer.length); -// return { -// satoshis: satoshis, -// scriptBuffer: scriptBuffer -// }; -// }; - -// exports.decodeOutputMempoolValue = function(buffer) { -// var satoshis = buffer.readDoubleBE(0); -// var timestamp = buffer.readDoubleBE(8); -// var scriptBuffer = buffer.slice(16, buffer.length); -// return { -// satoshis: satoshis, -// timestamp: timestamp, -// scriptBuffer: scriptBuffer -// }; -// }; - -// exports.encodeInputKey = function(hashBuffer, hashTypeBuffer, height, prevTxIdBuffer, outputIndex) { -// var heightBuffer = new Buffer(4); -// heightBuffer.writeUInt32BE(height); -// var outputIndexBuffer = new Buffer(4); -// outputIndexBuffer.writeUInt32BE(outputIndex); -// return Buffer.concat([ -// constants.PREFIXES.SPENTS, -// hashBuffer, -// hashTypeBuffer, -// constants.SPACER_MIN, -// heightBuffer, -// prevTxIdBuffer, -// outputIndexBuffer -// ]); -// }; - -// exports.decodeInputKey = function(buffer) { -// var reader = new BufferReader(buffer); -// var prefix = reader.read(1); -// var hashBuffer = reader.read(20); -// var hashTypeBuffer = reader.read(1); -// var spacer = reader.read(1); -// var height = reader.readUInt32BE(); -// var prevTxId = reader.read(32); -// var outputIndex = reader.readUInt32BE(); -// return { -// prefix: prefix, -// hashBuffer: hashBuffer, -// hashTypeBuffer: hashTypeBuffer, -// height: height, -// prevTxId: prevTxId, -// outputIndex: outputIndex -// }; -// }; - -// exports.encodeInputValue = function(txidBuffer, inputIndex) { -// var inputIndexBuffer = new Buffer(4); -// inputIndexBuffer.writeUInt32BE(inputIndex); -// return Buffer.concat([ -// txidBuffer, -// inputIndexBuffer -// ]); -// }; - -// exports.decodeInputValue = function(buffer) { -// var txid = buffer.slice(0, 32); -// var inputIndex = buffer.readUInt32BE(32); -// return { -// txid: txid, -// inputIndex: inputIndex -// }; -// }; - -// exports.encodeInputKeyMap = function(outputTxIdBuffer, outputIndex) { -// var outputIndexBuffer = new Buffer(4); -// outputIndexBuffer.writeUInt32BE(outputIndex); -// return Buffer.concat([ -// constants.PREFIXES.SPENTSMAP, -// outputTxIdBuffer, -// outputIndexBuffer -// ]); -// }; - -// exports.decodeInputKeyMap = function(buffer) { -// var txid = buffer.slice(1, 33); -// var outputIndex = buffer.readUInt32BE(33); -// return { -// outputTxId: txid, -// outputIndex: outputIndex -// }; -// }; - -// exports.encodeInputValueMap = function(inputTxIdBuffer, inputIndex) { -// var inputIndexBuffer = new Buffer(4); -// inputIndexBuffer.writeUInt32BE(inputIndex); -// return Buffer.concat([ -// inputTxIdBuffer, -// inputIndexBuffer -// ]); -// }; - -// exports.decodeInputValueMap = function(buffer) { -// var txid = buffer.slice(0, 32); -// var inputIndex = buffer.readUInt32BE(32); -// return { -// inputTxId: txid, -// inputIndex: inputIndex -// }; -// }; - -// exports.encodeSummaryCacheKey = function(address) { -// return Buffer.concat([address.hashBuffer, constants.HASH_TYPES_MAP[address.type]]); -// }; - -// exports.decodeSummaryCacheKey = function(buffer, network) { -// var hashBuffer = buffer.read(20); -// var type = constants.HASH_TYPES_READABLE[buffer.read(20, 2).toString('hex')]; -// var address = new Address({ -// hashBuffer: hashBuffer, -// type: type, -// network: network -// }); -// return address; -// }; - -// exports.encodeSummaryCacheValue = function(cache, tipHeight, tipHash) { -// var tipHashBuffer = new Buffer(tipHash, 'hex'); -// var buffer = new Buffer(new Array(20)); -// buffer.writeUInt32BE(tipHeight); -// buffer.writeDoubleBE(cache.result.totalReceived, 4); -// buffer.writeDoubleBE(cache.result.balance, 12); -// var txidBuffers = []; -// for (var i = 0; i < cache.result.txids.length; i++) { -// var buf = new Buffer(new Array(36)); -// var txid = cache.result.txids[i]; -// buf.write(txid, 'hex'); -// buf.writeUInt32BE(cache.result.appearanceIds[txid], 32); -// txidBuffers.push(buf); -// } -// var txidsBuffer = Buffer.concat(txidBuffers); -// var value = Buffer.concat([tipHashBuffer, buffer, txidsBuffer]); - -// return value; -// }; - -// exports.decodeSummaryCacheValue = function(buffer) { - -// var hash = buffer.slice(0, 32).toString('hex'); -// var height = buffer.readUInt32BE(32); -// var totalReceived = buffer.readDoubleBE(36); -// var balance = buffer.readDoubleBE(44); - -// // read 32 byte chunks until exhausted -// var appearanceIds = {}; -// var txids = []; -// var pos = 52; -// while(pos < buffer.length) { -// var txid = buffer.slice(pos, pos + 32).toString('hex'); -// var txidHeight = buffer.readUInt32BE(pos + 32); -// txids.push(txid); -// appearanceIds[txid] = txidHeight; -// pos += 36; -// } - -// var cache = { -// height: height, -// hash: hash, -// result: { -// appearanceIds: appearanceIds, -// txids: txids, -// totalReceived: totalReceived, -// balance: balance, -// unconfirmedAppearanceIds: {}, // unconfirmed values are never stored in cache -// unconfirmedBalance: 0 -// } -// }; - -// return cache; -// }; - -// exports.getAddressInfo = function(addressStr) { -// var addrObj = bitcore.Address(addressStr); -// var hashTypeBuffer = constants.HASH_TYPES_MAP[addrObj.type]; - -// return { -// hashBuffer: addrObj.hashBuffer, -// hashTypeBuffer: hashTypeBuffer, -// hashTypeReadable: addrObj.type -// }; -// }; - -// /** -// * This function is optimized to return address information about an output script -// * without constructing a Bitcore Address instance. -// * @param {Script} - An instance of a Bitcore Script -// * @param {Network|String} - The network for the address -// */ -// exports.extractAddressInfoFromScript = function(script, network) { -// $.checkArgument(network, 'Second argument is expected to be a network'); -// var hashBuffer; -// var addressType; -// var hashTypeBuffer; -// if (script.isPublicKeyHashOut()) { -// hashBuffer = script.chunks[2].buf; -// hashTypeBuffer = constants.HASH_TYPES.PUBKEY; -// addressType = Address.PayToPublicKeyHash; -// } else if (script.isScriptHashOut()) { -// hashBuffer = script.chunks[1].buf; -// hashTypeBuffer = constants.HASH_TYPES.REDEEMSCRIPT; -// addressType = Address.PayToScriptHash; -// } else if (script.isPublicKeyOut()) { -// var pubkey = script.chunks[0].buf; -// var address = Address.fromPublicKey(new PublicKey(pubkey), network); -// hashBuffer = address.hashBuffer; -// hashTypeBuffer = constants.HASH_TYPES.PUBKEY; -// // pay-to-publickey doesn't have an address, however for compatibility -// // purposes, we can create an address -// addressType = Address.PayToPublicKeyHash; -// } else { -// return false; -// } -// return { -// hashBuffer: hashBuffer, -// hashTypeBuffer: hashTypeBuffer, -// addressType: addressType -// }; -// }; - -module.exports = Encoding; diff --git a/lib/services/address/history.js b/lib/services/address/history.js index 88b5c96b..4c9b4b61 100644 --- a/lib/services/address/history.js +++ b/lib/services/address/history.js @@ -4,7 +4,7 @@ var bitcore = require('bitcore-lib'); var async = require('async'); var _ = bitcore.deps._; -var constants = require('./constants'); +var constants = require('../../constants'); /** * This represents an instance that keeps track of data over a series of diff --git a/lib/services/address/index.js b/lib/services/address/index.js index 818b7f35..52ae4d6b 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -19,8 +19,8 @@ var Hash = bitcore.crypto.Hash; var EventEmitter = require('events').EventEmitter; var Address = bitcore.Address; var AddressHistory = require('./history'); -var constants = require('./constants'); -var Encoding = require('./encoding'); +var constants = require('../../constants'); +var Encoding = require('../../encoding'); var InputsTransformStream = require('./streams/inputs-transform'); var OutputsTransformStream = require('./streams/outputs-transform'); diff --git a/lib/services/address/streams/inputs-transform.js b/lib/services/address/streams/inputs-transform.js index 8b8f71d3..709c8d0e 100644 --- a/lib/services/address/streams/inputs-transform.js +++ b/lib/services/address/streams/inputs-transform.js @@ -3,7 +3,7 @@ var Transform = require('stream').Transform; var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); -var encodingUtil = require('../encoding'); +var encodingUtil = require('../../../encoding'); var $ = bitcore.util.preconditions; function InputsTransformStream(options) { diff --git a/lib/services/address/streams/outputs-transform.js b/lib/services/address/streams/outputs-transform.js index b9c8e8d3..21bbc189 100644 --- a/lib/services/address/streams/outputs-transform.js +++ b/lib/services/address/streams/outputs-transform.js @@ -3,7 +3,7 @@ var Transform = require('stream').Transform; var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); -var encodingUtil = require('../encoding'); +var encodingUtil = require('../../../encoding'); var $ = bitcore.util.preconditions; function OutputsTransformStream(options) { diff --git a/lib/services/timestamp.js b/lib/services/timestamp.js index e69b5b61..45e848af 100644 --- a/lib/services/timestamp.js +++ b/lib/services/timestamp.js @@ -1,4 +1,5 @@ 'use strict'; +var Encoding = require('../encoding'); var BaseService = require('../service'); var inherits = require('util').inherits; @@ -25,7 +26,7 @@ TimestampService.prototype.start = function(callback) { } self.prefix = prefix; - + self.encoding = new Encoding(self.prefix); callback(); }); }; @@ -73,13 +74,13 @@ TimestampService.prototype.blockHandler = function(block, connectBlock, callback [ { type: action, - key: self._encodeTimestampBlockKey(timestamp), - value: self._encodeTimestampBlockValue(block.header.hash) + key: self.encoding.encodeTimestampBlockKey(timestamp), + value: self.encoding.encodeTimestampBlockValue(block.header.hash) }, { type: action, - key: self._encodeBlockTimestampKey(block.header.hash), - value: self._encodeBlockTimestampValue(timestamp) + key: self.encoding.encodeBlockTimestampKey(block.header.hash), + value: self.encoding.encodeBlockTimestampValue(timestamp) } ] ); @@ -97,50 +98,14 @@ TimestampService.prototype.getTimestamp = function(hash, callback) { }); } - var key = self._encodeBlockTimestampKey(hash); + var key = self.encoding.encodeBlockTimestampKey(hash); self.store.get(key, function(err, buffer) { if(err) { return callback(err); } - return callback(null, self._decodeBlockTimestampValue(buffer)); + return callback(null, self.encoding.decodeBlockTimestampValue(buffer)); }); }; -TimestampService.prototype._encodeBlockTimestampKey = function(hash) { - return Buffer.concat([this.prefix, new Buffer(hash, 'hex')]); -}; - -TimestampService.prototype._decodeBlockTimestampKey = function(buffer) { - return buffer.slice(2).toString('hex'); -}; - -TimestampService.prototype._encodeBlockTimestampValue = function(timestamp) { - var timestampBuffer = new Buffer(new Array(8)); - timestampBuffer.writeDoubleBE(timestamp); - return timestampBuffer; -}; - -TimestampService.prototype._decodeBlockTimestampValue = function(buffer) { - return buffer.readDoubleBE(0); -}; - -TimestampService.prototype._encodeTimestampBlockKey = function(timestamp) { - var timestampBuffer = new Buffer(new Array(8)); - timestampBuffer.writeDoubleBE(timestamp); - return Buffer.concat([this.prefix, timestampBuffer]); -}; - -TimestampService.prototype._decodeTimestampBlockKey = function(buffer) { - return buffer.readDoubleBE(2); -}; - -TimestampService.prototype._encodeTimestampBlockValue = function(hash) { - return new Buffer(hash, 'hex'); -}; - -TimestampService.prototype._decodeTimestampBlockValue = function(buffer) { - return buffer.toString('hex'); -}; - module.exports = TimestampService; diff --git a/lib/services/transaction.js b/lib/services/transaction.js index 856eb42a..31ec1877 100644 --- a/lib/services/transaction.js +++ b/lib/services/transaction.js @@ -5,6 +5,7 @@ var BaseService = require('../service'); var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var _ = require('lodash'); +var Encoding = require('../encoding'); var LRU = require('lru-cache'); var utils = require('./wallet-api/utils'); var index = require('../'); @@ -78,6 +79,7 @@ TransactionService.prototype.start = function(callback) { return callback(err); } self.prefix = prefix; + self.encoding = new Encoding(self.prefix); next(); }); }], function(err) { @@ -154,8 +156,8 @@ TransactionService.prototype.blockHandler = function(block, connectBlock, callba operations.push({ type: action, - key: self._encodeTransactionKey(tx.id), - value: self._encodeTransactionValue(tx) + key: self.encoding.encodeTransactionKey(tx.id), + value: self.encoding.encodeTransactionValue(tx) }); next(); }); @@ -220,61 +222,17 @@ TransactionService.prototype.getTransaction = function(txid, options, callback) } //transaction was not in our mempool, lookup in the database - var key = self._encodeTransactionKey(txid); + var key = self.encoding.encodeTransactionKey(txid); self.node.services.db.store.get(key, function(err, buffer) { if(err) { return callback(err); } - var tx = self._decodeTransactionValue(buffer); + var tx = self.encoding.decodeTransactionValue(buffer); callback(null, tx); }); }; -TransactionService.prototype._encodeTransactionKey = function(txid) { - return Buffer.concat([this.prefix, new Buffer(txid, 'hex')]); -}; - -TransactionService.prototype._decodeTransactionKey = function(buffer) { - return buffer.slice(2).toString('hex'); -}; - -TransactionService.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 * 8); - - return new Buffer.concat([heightBuffer, timestampBuffer, - inputValuesLengthBuffer, inputValuesBuffer, transaction.toBuffer()]); -}; - -TransactionService.prototype._decodeTransactionValue = function(buffer) { - var height = buffer.readUInt32BE(); - - var timestamp = buffer.readDoubleBE(4); - - var inputValues = []; - var inputValuesLength = buffer.readUInt16BE(12); - for(var i = 0; i < inputValuesLength / 8; 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 = TransactionService; diff --git a/lib/services/wallet-api/utils.js b/lib/services/wallet-api/utils.js index d8428586..4925dfbd 100644 --- a/lib/services/wallet-api/utils.js +++ b/lib/services/wallet-api/utils.js @@ -725,10 +725,6 @@ exports.parseByteCount = function(byteCountString) { * output: bool args are valid for encoding a key to the database */ exports.hasRequiredArgsForEncoding = function(args) { - //for encoding a key to the database, the passed in args must: - // the first atg should exist - // the second arg is optional, but must exist if there is a third, fourth, nth arg - // the third arg is optional, but not if the second arg is missing, etc. function exists(arg) { return !(arg === null || arg === undefined); } diff --git a/lib/utils.js b/lib/utils.js index b4b3af7a..c4d95f85 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -39,4 +39,62 @@ utils.parseParamsWithJSON = function parseParamsWithJSON(paramsArg) { return params; }; +/* +* input: string representing a number + multiple of bytes, e.g. 500MB, 200KB, 100B +* output: integer representing the byte count +*/ +utils.parseByteCount = function(byteCountString) { + + function finish(n, m) { + var num = parseInt(n); + if (num > 0) { + return num * m; + } + return null; + } + + if (!_.isString(byteCountString)) { + return byteCountString; + } + var str = byteCountString.replace(/\s+/g, ''); + var map = { 'MB': 1E6, 'kB': 1000, 'KB': 1000, 'MiB': (1024 * 1024), + 'KiB': 1024, 'GiB': Math.pow(1024, 3), 'GB': 1E9 }; + var keys = Object.keys(map); + for(var i = 0; i < keys.length; i++) { + var re = new RegExp(keys[i] + '$'); + var match = str.match(re); + if (match) { + var num = str.slice(0, match.index); + return finish(num, map[keys[i]]); + } + } + return finish(byteCountString, 1); +}; + +/* + * input: arguments passed into originating function (whoever called us) + * output: bool args are valid for encoding a key to the database +*/ +utils.hasRequiredArgsForEncoding = function(args) { + function exists(arg) { + return !(arg === null || arg === undefined); + } + + if (!exists(args[0])) { + return false; + } + + var pastArgMissing; + + for(var i = 1; i < args.length; i++) { + var argMissing = exists(args[i]); + if (argMissing && pastArgMissing) { + return false; + } + pastArgMissing = argMissing; + } + + return true; +}; + module.exports = utils;