From 389ee296b044a12b53f2a4106a5f8383dc547d20 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 23 Dec 2015 16:21:49 -0800 Subject: [PATCH] improve tx building. minor style fixes. utils.uniq. --- lib/bcoin/script.js | 4 +++- lib/bcoin/tx.js | 17 ++++++++++++----- lib/bcoin/utils.js | 12 ++++++++++++ lib/bcoin/wallet.js | 18 +++++++++++++----- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 85bc0284..45498f62 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -1021,6 +1021,8 @@ script.isMultisig = function isMultisig(s, pubs) { }; script.isScripthash = function isScripthash(s, hash) { + var res; + s = script.subscript(s); if (script.lockTime(s)) @@ -1029,7 +1031,7 @@ script.isScripthash = function isScripthash(s, hash) { if (s.length !== 3) return false; - var res = s[0] === 'hash160' + res = s[0] === 'hash160' && Array.isArray(s[1]) && s[1].length === 20 && s[2] === 'eq'; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index a769e2d2..5f1ddb38 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -64,6 +64,7 @@ function TX(data, block) { this.ps = this.ts === 0 ? +new Date() / 1000 : 0; this.changeAddress = data.changeAddress || null; + this.changeOutput = data.changeOutput || null; } TX.fee = 10000; @@ -283,11 +284,13 @@ TX.prototype.signInput = function signInput(input, key, type) { break; } + // Public key is not in the prev_out script if (ki === keys.length) - throw new Error('Public key is not in the prev_out script'); + return; + // No signature slot available if (ki + 1 > len - 1) - throw new Error('No signature slot available'); + return; // Add our signature to the correct slot // and count the total number of signatures. @@ -729,13 +732,15 @@ TX.prototype.utxos = function utxos(unspent) { TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress) { var result = unspent.utxos ? unspent : this.utxos(unspent); - this.changeAddress = changeAddress || this.changeAddress; + this.changeAddress = changeAddress + || this.changeAddress + || utxos[0].output.addr; if (!result) return result; - result.utxos.forEach(function(utxo) { - this.input(utxo, null); + result.utxos.forEach(function(input) { + this.input(input); }, this); if (result.change.cmpn(TX.dust) < 0) { @@ -743,6 +748,8 @@ TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress) { assert(this.getFee().cmp(result.fee.add(result.change)) === 0); this.changeOutput = null; } else { + if (!this.changeAddress) + throw new Error('No change address'); this.output({ address: this.changeAddress, value: result.change diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 87e3cb6e..b4b88189 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -798,3 +798,15 @@ utils.writeIntv = function writeIntv(arr, value, off) { utils.writeU64(arr, value, off + 1); return 9; }; + +utils.uniq = function(obj) { + var out = []; + var i = 0; + + for (; i < obj.length; i++) { + if (!~out.indexOf(obj[i])) + out.push(obj[i]); + } + + return out; +}; diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index e93e40e3..4445ff9c 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -41,6 +41,7 @@ function Wallet(options, passphrase) { this.key = null; this.loaded = false; this.lastTs = 0; + this.changeAddress = options.changeAddress || null; if (options.priv instanceof bcoin.hd.priv) { this.hd = options.priv; @@ -459,8 +460,9 @@ Wallet.prototype.scriptOutputs = function scriptOutputs(tx, options, outputs) { return outputs.length; }; -Wallet.prototype.fillUnspent = function fillUnspent(tx, change) { - return tx.fillUnspent(this.unspent(), change || this.getFullAddress()); +Wallet.prototype.fillUnspent = function fillUnspent(tx, changeAddress) { + changeAddress = changeAddress || this.changeAddress || this.getFullAddress(); + return tx.fillUnspent(this.unspent(), changeAddress); }; Wallet.prototype.scriptInputs = function scriptInputs(tx, inputs) { @@ -544,12 +546,18 @@ Wallet.prototype.balance = function balance() { return this.tx.balance(); }; -Wallet.prototype.fill = function fill(tx, cb) { - var result = tx.fillUnspent(this.unspent(), this.getAddress()); - var err; +Wallet.prototype.fill = function fill(tx, changeAddress, cb) { + var result, err; + + if (typeof changeAddress === 'function') { + cb = changeAddress; + changeAddress = null; + } cb = utils.asyncify(cb); + result = this.fillUnspent(tx, changeAddress); + if (!result) { err = new Error('Not enough funds'); err.minBalance = tx.total;