From 2b4d94cd92495992ce27425acf40440c6e025dc5 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Sat, 16 Aug 2014 14:19:19 +0800 Subject: [PATCH 1/3] Wallet: move processPendingTx & processConfirmedTx to prototype also, move processTx out of Wallet scope --- src/wallet.js | 129 ++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/src/wallet.js b/src/wallet.js index ad7ccbd..23142d5 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -49,91 +49,28 @@ function Wallet(seed, network, unspents) { me.outputs = {} } - this.processPendingTx = function(tx){ - processTx(tx, true) - } - - this.processConfirmedTx = function(tx){ - processTx(tx, false) - } - - var me = this - - function processTx(tx, isPending) { - var txid = tx.getId() - - tx.outs.forEach(function(txOut, i) { - var address - - try { - address = Address.fromOutputScript(txOut.script, network).toString() - } catch(e) { - if (!(e.message.match(/has no matching Address/))) throw e - } - - if (isMyAddress(address)) { - var output = txid + ':' + i - - me.outputs[output] = { - from: output, - value: txOut.value, - address: address, - pending: isPending - } - } - }) - - tx.ins.forEach(function(txIn, i) { - // copy and convert to big-endian hex - var txinId = new Buffer(txIn.hash) - Array.prototype.reverse.call(txinId) - txinId = txinId.toString('hex') - - var output = txinId + ':' + txIn.index - - if (!(output in me.outputs)) return - - if (isPending) { - me.outputs[output].to = txid + ':' + i - me.outputs[output].pending = true - } else { - delete me.outputs[output] - } - }) - } - this.getMasterKey = function() { return masterKey } this.getAccountZero = function() { return accountZero } this.getExternalAccount = function() { return externalAccount } this.getInternalAccount = function() { return internalAccount } this.getPrivateKeyForAddress = function(address) { - assert(isMyAddress(address), 'Unknown address. Make sure the address is from the keychain and has been generated') + var myAddresses = this.addresses.concat(this.changeAddresses) + assert(includeAddress(myAddresses, address), + 'Unknown address. Make sure the address is from the keychain and has been generated') - if (isReceiveAddress(address)) { + if (includeAddress(this.addresses, address)) { var index = this.addresses.indexOf(address) return this.getPrivateKey(index) } - if (isChangeAddress(address)) { + if (includeAddress(this.changeAddresses, address)) { var index = this.changeAddresses.indexOf(address) return this.getInternalPrivateKey(index) } } - - function isReceiveAddress(address){ - return me.addresses.indexOf(address) > -1 - } - - function isChangeAddress(address){ - return me.changeAddresses.indexOf(address) > -1 - } - - function isMyAddress(address) { - return isReceiveAddress(address) || isChangeAddress(address) - } } Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) { @@ -175,6 +112,14 @@ Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) { return tx } +Wallet.prototype.processPendingTx = function(tx){ + processTx.bind(this)(tx, true) +} + +Wallet.prototype.processConfirmedTx = function(tx){ + processTx.bind(this)(tx, false) +} + Wallet.prototype.generateAddress = function() { var k = this.addresses.length var address = this.getExternalAccount().derive(k).getAddress() @@ -316,4 +261,52 @@ function getCandidateOutputs(outputs/*, value*/) { return sortByValueDesc } +function processTx(tx, isPending) { + var txid = tx.getId() + + tx.outs.forEach(function(txOut, i) { + var address + + try { + address = Address.fromOutputScript(txOut.script, this.network).toString() + } catch(e) { + if (!(e.message.match(/has no matching Address/))) throw e + } + + var myAddresses = this.addresses.concat(this.changeAddresses) + if (includeAddress(myAddresses, address)) { + var output = txid + ':' + i + + this.outputs[output] = { + from: output, + value: txOut.value, + address: address, + pending: isPending + } + } + }, this) + + tx.ins.forEach(function(txIn, i) { + // copy and convert to big-endian hex + var txinId = new Buffer(txIn.hash) + Array.prototype.reverse.call(txinId) + txinId = txinId.toString('hex') + + var output = txinId + ':' + txIn.index + + if (!(output in this.outputs)) return + + if (isPending) { + this.outputs[output].to = txid + ':' + i + this.outputs[output].pending = true + } else { + delete this.outputs[output] + } + }, this) +} + +function includeAddress(addresses, address) { + return addresses.indexOf(address) > -1 +} + module.exports = Wallet From 00d58604a47ecbe169c991ddc4f7e5fb247f7d57 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Sat, 16 Aug 2014 14:24:24 +0800 Subject: [PATCH 2/3] Wallet: move getPrivateKeyForAddress to prototype also, move the assert to the end to simplify the logic --- src/wallet.js | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/wallet.js b/src/wallet.js index 23142d5..137ec86 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -53,24 +53,6 @@ function Wallet(seed, network, unspents) { this.getAccountZero = function() { return accountZero } this.getExternalAccount = function() { return externalAccount } this.getInternalAccount = function() { return internalAccount } - - this.getPrivateKeyForAddress = function(address) { - var myAddresses = this.addresses.concat(this.changeAddresses) - assert(includeAddress(myAddresses, address), - 'Unknown address. Make sure the address is from the keychain and has been generated') - - if (includeAddress(this.addresses, address)) { - var index = this.addresses.indexOf(address) - - return this.getPrivateKey(index) - } - - if (includeAddress(this.changeAddresses, address)) { - var index = this.changeAddresses.indexOf(address) - - return this.getInternalPrivateKey(index) - } - } } Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) { @@ -160,6 +142,22 @@ Wallet.prototype.getPrivateKey = function(index) { return this.getExternalAccount().derive(index).privKey } +Wallet.prototype.getPrivateKeyForAddress = function(address) { + if (includeAddress(this.addresses, address)) { + var index = this.addresses.indexOf(address) + + return this.getPrivateKey(index) + } + + if (includeAddress(this.changeAddresses, address)) { + var index = this.changeAddresses.indexOf(address) + + return this.getInternalPrivateKey(index) + } + + assert(false, 'Unknown address. Make sure the address is from the keychain and has been generated') +} + Wallet.prototype.getReceiveAddress = function() { if (this.addresses.length === 0) { this.generateAddress() From e55676cf8e6b441dad5d747ea5da062338971c9d Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Sat, 16 Aug 2014 14:27:12 +0800 Subject: [PATCH 3/3] Wallet: remove unncessary comments --- src/wallet.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/wallet.js b/src/wallet.js index 137ec86..6e26612 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -13,7 +13,6 @@ function Wallet(seed, network, unspents) { // Stored in a closure to make accidental serialization less likely var masterKey = HDNode.fromSeedBuffer(seed, network) - var me = this // HD first-level child derivation method should be hardened // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254 @@ -21,24 +20,19 @@ function Wallet(seed, network, unspents) { var externalAccount = accountZero.derive(0) var internalAccount = accountZero.derive(1) - // Addresses this.addresses = [] this.changeAddresses = [] - this.network = network - - // Transaction output data this.outputs = unspents ? processUnspentOutputs(unspents) : {} // FIXME: remove in 2.x.y + var me = this this.newMasterKey = function(seed) { console.warn('newMasterKey is deprecated, please make a new Wallet instance instead') seed = seed || crypto.randomBytes(32) masterKey = HDNode.fromSeedBuffer(seed, network) - // HD first-level child derivation method should be hardened - // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254 accountZero = masterKey.deriveHardened(0) externalAccount = accountZero.derive(0) internalAccount = accountZero.derive(1)