diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index 0502f627..6ceeafa1 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -371,13 +371,13 @@ Address.prototype._getAddressMap = function _getAddressMap() { if (!this.addressMap) { this.addressMap = {}; - this.addressMap[this.getKeyAddress()] = true; + this.addressMap[this.getKeyHash('hex')] = true; if (this.type === 'multisig') - this.addressMap[this.getScriptAddress()] = true; + this.addressMap[this.getScriptHash('hex')] = true; if (this.witness) - this.addressMap[this.getProgramAddress()] = true; + this.addressMap[this.getProgramHash('hex')] = true; } return this.addressMap; @@ -394,9 +394,9 @@ Address.prototype.ownInput = function ownInput(tx, index) { var addressMap = this._getAddressMap(); if (tx instanceof bcoin.input) - return tx.test(addressMap, this.network); + return tx.test(addressMap); - return tx.testInputs(addressMap, index, this.network); + return tx.testInputs(addressMap, index); }; /** @@ -410,9 +410,9 @@ Address.prototype.ownOutput = function ownOutput(tx, index) { var addressMap = this._getAddressMap(); if (tx instanceof bcoin.output) - return tx.test(addressMap, this.network); + return tx.test(addressMap); - return tx.testOutputs(addressMap, index, this.network); + return tx.testOutputs(addressMap, index); }; /** @@ -653,22 +653,7 @@ Address.parse = function parse(address) { */ Address.validate = function validate(address, type) { - if (!address) - return false; - - if (!Buffer.isBuffer(address) && typeof address !== 'string') - return false; - - try { - address = Address.parse(address); - } catch (e) { - return false; - } - - if (type && address.type !== type) - return false; - - return true; + return bcoin.script.Address.validate(address, type); }; Address.prototype.compileHash = function compileHash(hash, type, version) { diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index e6e4628f..449b6ee9 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -801,7 +801,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { if (self.options.indexTX) { batch.put('t/' + hash, tx.toExtended()); if (self.options.indexAddress) { - addresses = tx.getAddresses(self.network); + addresses = tx.getHashes(); for (j = 0; j < addresses.length; j++) { address = addresses[j]; batch.put('T/' + address + '/' + hash, DUMMY); @@ -819,7 +819,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { assert(input.coin); if (self.options.indexAddress) { - address = input.getAddress(self.network); + address = input.getHash(); if (address) batch.del('C/' + address + '/' + key); } @@ -841,7 +841,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { coin = bcoin.coin(tx, j); if (self.options.indexAddress) { - address = output.getAddress(self.network); + address = output.getHash(); if (address) batch.put('C/' + address + '/' + key, DUMMY); } @@ -893,7 +893,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb if (self.options.indexTX) { batch.del('t/' + hash); if (self.options.indexAddress) { - addresses = tx.getAddresses(self.network); + addresses = tx.getHashes(); for (j = 0; j < addresses.length; j++) { address = addresses[j]; batch.del('T/' + address + '/' + hash); @@ -911,7 +911,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb assert(input.coin); if (self.options.indexAddress) { - address = input.getAddress(self.network); + address = input.getHash(); if (address) batch.put('C/' + address + '/' + key, DUMMY); } @@ -929,7 +929,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb continue; if (self.options.indexAddress) { - address = output.getAddress(self.network); + address = output.getHash(); if (address) batch.del('C/' + address + '/' + key); } @@ -1110,6 +1110,9 @@ ChainDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call addresses = utils.uniq(addresses); utils.forEachSerial(addresses, function(address, next) { + address = bcoin.script.Address.getHash(address); + if (!address) + return next(); self.db.lookup({ gte: 'C/' + address, lte: 'C/' + address + '~', @@ -1149,7 +1152,10 @@ ChainDB.prototype.getTXByAddress = function getTXByAddress(addresses, callback) addresses = utils.uniq(addresses); - utils.forEachSerial(addresses, function(address, done) { + utils.forEachSerial(addresses, function(address, next) { + address = bcoin.script.Address.getHash(address); + if (!address) + return next(); self.db.lookup({ gte: 'T/' + address, lte: 'T/' + address + '~', diff --git a/lib/bcoin/input.js b/lib/bcoin/input.js index 0934acb1..fb7a1f0f 100644 --- a/lib/bcoin/input.js +++ b/lib/bcoin/input.js @@ -148,26 +148,26 @@ Input.prototype.getSubtype = function getSubtype() { * Get the previous output script's address. Will "guess" * based on the input script and/or witness if coin * is not available. - * @returns {String?} address + * @returns {ScriptAddress?} address */ -Input.prototype.getAddress = function getAddress(network) { +Input.prototype.getAddress = function getAddress() { var address; if (this.isCoinbase()) return; if (this.coin) - return this.coin.getAddress(network); + return this.coin.getAddress(); if (this._address) return this._address; if (this.witness.items.length > 0) - address = this.witness.getInputAddress(network); + address = this.witness.getInputAddress(); if (!address) - address = this.script.getInputAddress(network); + address = this.script.getInputAddress(); if (!this.mutable) this._address = address; @@ -175,6 +175,18 @@ Input.prototype.getAddress = function getAddress(network) { return address; }; +/** + * Get the address hash. + * @returns {Hash} hash + */ + +Input.prototype.getHash = function getHash(enc) { + var address = this.getAddress(); + if (!address) + return; + return address.getHash('hex'); +}; + /** * Test to see if nSequence is equal to uint32max. * @returns {Boolean} @@ -200,19 +212,19 @@ Input.prototype.isCoinbase = function isCoinbase() { * @returns {Boolean} Whether the input matched. */ -Input.prototype.test = function test(addressMap, network) { - var address = this.getAddress(network); +Input.prototype.test = function test(addressMap) { + var hash = this.getHash('hex'); - if (!address) + if (!hash) return false; if (typeof addressMap === 'string') - return address === addressMap; + return hash === addressMap; if (Array.isArray(addressMap)) - return addressMap.indexOf(address) !== -1; + return addressMap.indexOf(hash) !== -1; - if (addressMap[address] != null) + if (addressMap[hash] != null) return true; return false; diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index bc4d4a43..52899da5 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -1543,7 +1543,7 @@ Mempool.prototype._addUnchecked = function _addUnchecked(entry, callback) { batch.put('m/' + pad32(entry.ts) + '/' + hash, DUMMY); if (this.options.indexAddress) { - addresses = tx.getAddresses(this.network); + addresses = tx.getHashes(); for (i = 0; i < addresses.length; i++) batch.put('T/' + addresses[i] + '/' + hash, DUMMY); } @@ -1561,7 +1561,7 @@ Mempool.prototype._addUnchecked = function _addUnchecked(entry, callback) { batch.put('s/' + key, tx.hash()); if (this.options.indexAddress) { - address = input.getAddress(this.network); + address = input.getHash(); if (address) batch.del('C/' + address + '/' + key); } @@ -1579,7 +1579,7 @@ Mempool.prototype._addUnchecked = function _addUnchecked(entry, callback) { batch.put('c/' + key, coin); if (this.options.indexAddress) { - address = output.getAddress(this.network); + address = output.getHash(); if (address) batch.put('C/' + address + '/' + key, DUMMY); } @@ -1617,7 +1617,7 @@ Mempool.prototype._removeUnchecked = function _removeUnchecked(hash, limit, call batch.del('m/' + pad32(entry.ts) + '/' + hash); if (self.options.indexAddress) { - addresses = tx.getAddresses(self.network); + addresses = tx.getHashes(); for (i = 0; i < addresses.length; i++) batch.del('T/' + addresses[i] + '/' + hash); } @@ -1641,14 +1641,14 @@ Mempool.prototype._removeUnchecked = function _removeUnchecked(hash, limit, call if (result) { batch.put('c/' + key, input.coin.toRaw()); if (self.options.indexAddress) { - address = input.getAddress(self.network); + address = input.getHash(); if (address) batch.put('C/' + address + '/' + key, DUMMY); } } else { batch.del('c/' + key); if (self.options.indexAddress) { - address = input.getAddress(self.network); + address = input.getHash(); if (address) batch.del('C/' + address + '/' + key); } @@ -1669,7 +1669,7 @@ Mempool.prototype._removeUnchecked = function _removeUnchecked(hash, limit, call batch.del('c/' + key); if (self.options.indexAddress) { - address = output.getAddress(self.network); + address = output.getHash(); if (address) batch.del('C/' + address + '/' + key); } diff --git a/lib/bcoin/output.js b/lib/bcoin/output.js index d427b1a9..8b0450b0 100644 --- a/lib/bcoin/output.js +++ b/lib/bcoin/output.js @@ -70,16 +70,16 @@ Output.prototype.getType = function getType() { /** * Get the address. - * @returns {String?} address + * @returns {ScriptAddress} address */ -Output.prototype.getAddress = function getAddress(network) { +Output.prototype.getAddress = function getAddress() { var address; if (this._address) return this._address; - address = this.script.getAddress(network); + address = this.script.getAddress(); if (!this.mutable) this._address = address; @@ -87,6 +87,18 @@ Output.prototype.getAddress = function getAddress(network) { return address; }; +/** + * Get the address hash. + * @returns {Hash} hash + */ + +Output.prototype.getHash = function getHash() { + var address = this.getAddress(); + if (!address) + return; + return address.getHash('hex'); +}; + /** * Test the output against an address, an * array of addresses, or a map of addresses. @@ -94,19 +106,19 @@ Output.prototype.getAddress = function getAddress(network) { * @returns {Boolean} Whether the output matched. */ -Output.prototype.test = function test(addressMap, network) { - var address = this.getAddress(network); +Output.prototype.test = function test(addressMap) { + var hash = this.getHash(); - if (!address) + if (!hash) return false; if (typeof addressMap === 'string') - return address === addressMap; + return hash === addressMap; if (Array.isArray(addressMap)) - return addressMap.indexOf(address) !== -1; + return addressMap.indexOf(hash) !== -1; - if (addressMap[address] != null) + if (addressMap[hash] != null) return true; return false; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index f558c1e9..20cd629e 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -118,11 +118,7 @@ Witness.prototype.getInputType = function getInputType() { */ Witness.prototype.getInputAddress = function getInputAddress(network) { - var addr = Address.fromWitness(this); - if (!addr) - return; - - return addr.toBase58(network); + return Address.fromWitness(this); }; /** @@ -2359,12 +2355,8 @@ Script.prototype.getSize = function getSize() { * @returns {Base58Address|null} */ -Script.prototype.getInputAddress = function getInputAddress(network) { - var addr = Address.fromInputScript(this); - if (!addr) - return; - - return addr.toBase58(network); +Script.prototype.getInputAddress = function getInputAddress() { + return Address.fromInputScript(this); }; /** @@ -2374,12 +2366,8 @@ Script.prototype.getInputAddress = function getInputAddress(network) { * @returns {Base58Address|null} */ -Script.prototype.getAddress = function getAddress(network) { - var addr = Address.fromScript(this); - if (!addr) - return; - - return addr.toBase58(network); +Script.prototype.getAddress = function getAddress() { + return Address.fromScript(this); }; /** @@ -4464,4 +4452,52 @@ Address.toScript = function toScript() { assert(false, 'Bad type.'); }; +Address.validate = function validate(address, type) { + if (!address) + return false; + + if (!Buffer.isBuffer(address) && typeof address !== 'string') + return false; + + try { + address = Address.parseBase58(address); + } catch (e) { + return false; + } + + if (type && address.type !== type) + return false; + + return true; +}; + +Address.getHash = function getHash(data) { + var hash; + + if (data instanceof Address) { + hash = data.hash; + } else { + try { + hash = Address.parseBase58(data).hash; + } catch (e) { + return; + } + } + + return hash.toString('hex'); +}; + +// Address.prototype.toString = function toString() { +// return this.toBase58(); +// }; + +Address.prototype.inspect = function inspect() { + return { + hash: this.getHash('hex'), + type: this.type, + version: this.version, + address: this.toBase58() + }; +}; + Script.Address = Address; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 49cb2e6d..254756c7 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -694,16 +694,19 @@ TX.prototype.getOutputValue = function getOutputValue() { * @returns {Base58Address[]} addresses */ -TX.prototype.getInputAddresses = function getInputAddresses(network) { +TX.prototype.getInputAddresses = function getInputAddresses() { var table = {}; var addresses = []; - var i, address; + var i, address, hash; for (i = 0; i < this.inputs.length; i++) { - address = this.inputs[i].getAddress(network); - if (address && !table[address]) { - table[address] = true; - addresses.push(address); + address = this.inputs[i].getAddress(); + if (address) { + hash = address.getHash('hex'); + if (!table[hash]) { + table[hash] = true; + addresses.push(address); + } } } @@ -717,16 +720,19 @@ TX.prototype.getInputAddresses = function getInputAddresses(network) { * @returns {Base58Address[]} addresses */ -TX.prototype.getOutputAddresses = function getOutputAddresses(network) { +TX.prototype.getOutputAddresses = function getOutputAddresses() { var table = {}; var addresses = []; - var i, address; + var i, address, hash; for (i = 0; i < this.outputs.length; i++) { - address = this.outputs[i].getAddress(network); - if (address && !table[address]) { - table[address] = true; - addresses.push(address); + address = this.outputs[i].getAddress(); + if (address) { + hash = address.getHash('hex'); + if (!table[hash]) { + table[hash] = true; + addresses.push(address); + } } } @@ -740,14 +746,15 @@ TX.prototype.getOutputAddresses = function getOutputAddresses(network) { * @returns {Base58Address[]} addresses */ -TX.prototype.getAddresses = function getAddresses(network) { - var input = this.getInputAddresses(network); - var output = this.getOutputAddresses(network); - var i; +TX.prototype.getAddresses = function getAddresses() { + var input = this.getInputAddresses(); + var output = this.getOutputAddresses(); + var i, hash; for (i = 0; i < output.length; i++) { - if (!input.table[output[i]]) { - input.table[output[i]] = true; + hash = output[i].getHash('hex'); + if (!input.table[hash]) { + input.table[hash] = true; input.push(output[i]); } } @@ -755,6 +762,33 @@ TX.prototype.getAddresses = function getAddresses(network) { return input; }; +/** + * Get all input address hashes. + * @returns {Hash[]} hashes + */ + +TX.prototype.getInputHashes = function getInputHashes() { + return Object.keys(this.getInputAddresses().table); +}; + +/** + * Get all output address hashes. + * @returns {Hash[]} hashes + */ + +TX.prototype.getOutputHashes = function getOutputHashes() { + return Object.keys(this.getOutputAddresses().table); +}; + +/** + * Get all address hashes. + * @returns {Hash[]} hashes + */ + +TX.prototype.getHashes = function getHashes() { + return Object.keys(this.getAddresses().table); +}; + /** * Test the inputs against an address, an * array of addresses, or a map of addresses. @@ -763,7 +797,7 @@ TX.prototype.getAddresses = function getAddresses(network) { * @returns {Boolean} Whether the transaction matched. */ -TX.prototype.testInputs = function testInputs(addressMap, index, network) { +TX.prototype.testInputs = function testInputs(addressMap, index) { var i; if (typeof addressMap === 'string') @@ -776,10 +810,10 @@ TX.prototype.testInputs = function testInputs(addressMap, index, network) { index = this.inputs.indexOf(index); if (index != null) - return this.inputs[index].test(addressMap, network); + return this.inputs[index].test(addressMap); for (i = 0; i < this.inputs.length; i++) { - if (this.inputs[i].test(addressMap, network)) + if (this.inputs[i].test(addressMap)) return true; } @@ -794,7 +828,7 @@ TX.prototype.testInputs = function testInputs(addressMap, index, network) { * @returns {Boolean} Whether the transaction matched. */ -TX.prototype.testOutputs = function testOutputs(addressMap, index, network) { +TX.prototype.testOutputs = function testOutputs(addressMap, index) { var i; if (typeof addressMap === 'string') @@ -807,10 +841,10 @@ TX.prototype.testOutputs = function testOutputs(addressMap, index, network) { index = this.outputs.indexOf(index); if (index != null) - return this.outputs[index].test(addressMap, network); + return this.outputs[index].test(addressMap); for (i = 0; i < this.outputs.length; i++) { - if (this.outputs[i].test(addressMap, network)) + if (this.outputs[i].test(addressMap)) return true; } diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index 77c206f6..5ca0af3e 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -82,8 +82,8 @@ TXDB.prototype.getMap = function getMap(tx, callback) { if (!this.options.indexAddress) return callback(); - input = tx.getInputAddresses(this.network); - output = tx.getOutputAddresses(this.network); + input = tx.getInputHashes(); + output = tx.getOutputHashes(); addresses = utils.uniq(input.concat(output)); function cb(err, table) { @@ -340,7 +340,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) { if (tx.isCoinbase()) return next(); - address = input.getAddress(self.network); + address = input.getHash(); // Only add orphans if this input is ours. if (self.options.mapAddress) { @@ -434,7 +434,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) { // Add unspent outputs or resolve orphans utils.forEachSerial(tx.outputs, function(output, next, i) { - var address = output.getAddress(self.network); + var address = output.getHash(); var key, coin; // Do not add unspents for outputs that aren't ours. @@ -688,7 +688,7 @@ TXDB.prototype._confirm = function _confirm(tx, map, callback, force) { } utils.forEachSerial(tx.outputs, function(output, next, i) { - var address = output.getAddress(self.network); + var address = output.getHash(); // Only update coins if this output is ours. if (self.options.mapAddress) { @@ -849,7 +849,7 @@ TXDB.prototype._remove = function remove(tx, map, callback, force) { tx.inputs.forEach(function(input) { var key = input.prevout.hash + '/' + input.prevout.index; - var address = input.getAddress(self.network); + var address = input.getHash(); if (tx.isCoinbase()) return; @@ -875,7 +875,7 @@ TXDB.prototype._remove = function remove(tx, map, callback, force) { tx.outputs.forEach(function(output, i) { var key = hash + '/' + i; - var address = output.getAddress(self.network); + var address = output.getHash(); if (self.options.mapAddress) { if (!address || !map.table[address].length) diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 054dba16..83cef83d 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -508,13 +508,13 @@ Wallet.prototype.deriveAddress = function deriveAddress(change, index) { address = new bcoin.address(options); - this.addressMap[address.getKeyAddress()] = data.path; + this.addressMap[address.getKeyHash('hex')] = data.path; if (this.type === 'multisig') - this.addressMap[address.getScriptAddress()] = data.path; + this.addressMap[address.getScriptHash('hex')] = data.path; if (this.witness) - this.addressMap[address.getProgramAddress()] = data.path; + this.addressMap[address.getProgramHash('hex')] = data.path; // Update the DB with the new address. if (this.provider && this.provider.update) @@ -648,9 +648,9 @@ Wallet.prototype.setChangeDepth = function setChangeDepth(depth) { Wallet.prototype.ownInput = function ownInput(tx, index) { if (tx instanceof bcoin.input) - return tx.test(this.addressMap, this.network); + return tx.test(this.addressMap); - return tx.testInputs(this.addressMap, index, this.network); + return tx.testInputs(this.addressMap, index); }; /** @@ -662,9 +662,9 @@ Wallet.prototype.ownInput = function ownInput(tx, index) { Wallet.prototype.ownOutput = function ownOutput(tx, index) { if (tx instanceof bcoin.output) - return tx.test(this.addressMap, this.network); + return tx.test(this.addressMap); - return tx.testOutputs(this.addressMap, index, this.network); + return tx.testOutputs(this.addressMap, index); }; /** @@ -878,7 +878,7 @@ Wallet.prototype.getInputPaths = function getInputPaths(tx, index) { var i, input, address, path; if (tx instanceof bcoin.input) { - path = this.getPath(tx.coin.getAddress(this.network)); + path = this.getPath(tx.coin.getHash()); if (path) paths.push(path); return paths; @@ -892,7 +892,7 @@ Wallet.prototype.getInputPaths = function getInputPaths(tx, index) { assert(input.coin, 'Not all coins available.'); - address = input.coin.getAddress(this.network); + address = input.coin.getHash(); path = this.getPath(address); if (!path) @@ -916,7 +916,7 @@ Wallet.prototype.getOutputPaths = function getOutputPaths(tx, index) { var i, output, address, path; if (tx instanceof bcoin.output) { - path = this.getPath(tx.getAddress(this.network)); + path = this.getPath(tx.getHash()); if (path) paths.push(path); return paths; @@ -928,7 +928,7 @@ Wallet.prototype.getOutputPaths = function getOutputPaths(tx, index) { if (index != null && i !== index) continue; - address = output.getAddress(this.network); + address = output.getHash(); path = this.getPath(address); if (!path) @@ -1002,17 +1002,7 @@ Wallet.prototype.getRedeem = function getRedeem(hash, prefix) { if (typeof hash === 'string') hash = new Buffer(hash, 'hex'); - if (!prefix) { - if (hash.length === 20) - prefix = 'scripthash'; - else if (hash.length === 32) - prefix = 'witnessscripthash'; - else - return; - } - - addr = bcoin.address.compileHash(hash, prefix, null, this.network); - address = this.deriveAddress(addr); + address = this.deriveAddress(hash.toString('hex')); if (!address) return; diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index b8372228..980d59cc 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -699,18 +699,18 @@ WalletDB.prototype.update = function update(wallet, address) { batch = this.db.batch(); batch.put( - 'W/' + address.getKeyAddress() + '/' + wallet.id, + 'W/' + address.getKeyHash('hex') + '/' + wallet.id, DUMMY); if (address.type === 'multisig') { batch.put( - 'W/' + address.getScriptAddress() + '/' + wallet.id, + 'W/' + address.getScriptHash('hex') + '/' + wallet.id, DUMMY); } if (address.witness) { batch.put( - 'W/' + address.getProgramAddress() + '/' + wallet.id, + 'W/' + address.getProgramHash('hex') + '/' + wallet.id, DUMMY); }