From 914bc8435dbe636b106c88cb77d566c03ba19362 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 11 Aug 2016 00:08:14 -0700 Subject: [PATCH] txdb: details and pathinfo. --- lib/bcoin/input.js | 6 +- lib/bcoin/txdb.js | 190 +++++++++++++++++++++++++++++++++++++++++++++ lib/bcoin/utils.js | 21 ++++- 3 files changed, 214 insertions(+), 3 deletions(-) diff --git a/lib/bcoin/input.js b/lib/bcoin/input.js index 6ce89de1..cba41a7b 100644 --- a/lib/bcoin/input.js +++ b/lib/bcoin/input.js @@ -311,7 +311,7 @@ Input.prototype.getRedeem = function getRedeem() { */ Input.prototype.getSubtype = function getSubtype() { - var redeem; + var redeem, type; if (this.isCoinbase()) return; @@ -321,7 +321,9 @@ Input.prototype.getSubtype = function getSubtype() { if (!redeem) return; - return redeem.getType(); + type = redeem.getType(); + + return constants.scriptTypesByVal[type].toLowerCase(); }; /** diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index 3d552d0e..d1120f6b 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -2334,6 +2334,196 @@ MapMember.fromPath = function fromPath(path) { return new MapMember().fromPath(path); }; +function PathInfo(tx, table) { + // All relevant Wallet-ID/Accounts for + // inputs and outputs (for database indexing). + this.keys = []; + + // All output paths (for deriving during sync). + this.paths = []; + + // All output wallet IDs (for balance & syncing). + this.wallets = []; + + // Map of address hashes->paths (for everything). + this.table = {}; + + if (tx) + this.fromTX(tx, table); +} + +PathInfo.prototype.fromTX = function fromTX(tx, table) { + var i, j, keys, wallets, hashes, hash, paths, path, key; + + this.table = table; + + keys = {}; + hashes = Object.keys(table); + + for (i = 0; i < hashes.length; i++) { + hash = hashes[i]; + paths = table[hash]; + for (j = 0; j < paths.length; j++) { + path = paths[j]; + key = path.id + '/' + path.account; + keys[key] = true; + } + } + + this.keys = Object.keys(keys); + + wallets = {}; + hashes = tx.getOutputHashes('hex'); + + for (i = 0; i < hashes.length; i++) { + hash = hashes[i]; + paths = table[hash]; + for (j = 0; j < paths.length; j++) { + path = paths[j]; + this.paths.push(path); + wallets[path.id] = true; + } + } + + this.wallets = Object.keys(wallets); +}; + +PathInfo.fromTX = function fromTX(tx, table) { + return new PathInfo().fromTX(tx, table); +}; + +/** + * Test whether the map has paths + * for a given address hash. + * @param {Hash} address + * @returns {Boolean} + */ + +PathInfo.prototype.hasPaths = function hasPaths(address) { + var paths; + + if (!address) + return false; + + paths = this.table[address]; + + return paths && paths.length !== 0; +}; + +/** + * Get paths for a given address hash. + * @param {Hash} address + * @returns {Path[]|null} + */ + +PathInfo.prototype.getPaths = function getPaths(address) { + var paths; + + if (!address) + return; + + paths = this.table[address]; + + if (!paths || paths.length === 0) + return; + + return paths; +}; + +function Details(tx, id, table) { + this.hash = tx.hash('hex'); + this.height = tx.height; + this.block = tx.block; + this.index = tx.index; + this.confirmations = tx.getConfirmations(); + this.ts = tx.ts; + this.ps = tx.ps; + this.fee = tx.getFee(); + this.tx = tx; + this.inputs = []; + this.outputs = []; + + if (id) + this.init(id, table); +} + +Details.prototype._insert = function _insert(vector, target, id, table) { + var i, j, io, address, hash, paths, path, member; + + for (i = 0; i < vector.length; i++) { + io = vector[i]; + member = new DetailsMember(); + + if (io instanceof bcoin.input) + member.value = io.coin ? io.coin.value : 0; + else + member.value = io.value; + + address = io.getAddress(); + + if (address) { + member.address = address; + + hash = address.getHash('hex'); + paths = table[hash]; + + for (j = 0; j < paths.length; j++) { + path = paths[j]; + if (path.id === id) { + member.path = path; + break; + } + } + } + + target.push(member); + } +}; + +Details.prototype.init = function init(id, table) { + this._insert(this.tx.inputs, this.inputs, id, table); + this._insert(this.tx.outputs, this.outputs, id, table); +}; + +Details.prototype.toJSON = function toJSON() { + return { + hash: utils.revHex(this.hash), + height: this.height, + block: this.block ? utils.revHex(this.block) : null, + ts: this.ts, + ps: this.ps, + index: this.index, + fee: utils.btc(this.fee), + confirmations: this.confirmations, + inputs: this.inputs.map(function(input) { + return input.toJSON(); + }), + outputs: this.outputs.map(function(output) { + return output.toJSON(); + }), + tx: this.tx.toRaw().toString('hex') + }; +}; + +function DetailsMember() { + this.value = 0; + this.address = null; + this.path = null; +} + +DetailsMember.prototype.toJSON = function toJSON() { + return { + value: utils.btc(this.value), + address: this.address + ? this.address.toBase58() + : null, + path: this.path + ? this.path.toJSON() + : null + }; +}; + + /* * Expose */ diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 59adf4ca..d270be1d 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -2192,7 +2192,7 @@ utils.toMap = function toMap(obj) { /** * Reverse a map. * @param {Object} map - * @param {Object} Reversed map. + * @returns {Object} Reversed map. */ utils.revMap = function revMap(map) { @@ -2208,6 +2208,25 @@ utils.revMap = function revMap(map) { return reversed; }; +/** + * Get object values. + * @param {Object} map + * @returns {Array} Values. + */ + +utils.values = function values(map) { + var keys = Object.keys(map); + var out = []; + var i, key; + + for (i = 0; i < keys.length; i++) { + key = keys[i]; + out.push(map[key]); + } + + return out; +}; + /** * Perform a binary search on a sorted array. * @param {Array} items