From 4a6c73fc8e504401608b983ce5c3027b780d07ee Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 11 Feb 2016 01:29:35 -0800 Subject: [PATCH] refactor signing. --- lib/bcoin/address.js | 27 ++++++++++++++++++++++----- lib/bcoin/tx.js | 35 ++++++++++++++++++----------------- lib/bcoin/wallet.js | 12 ++++++------ test/wallet-test.js | 4 ++-- 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index df456a2f..dbf89891 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -331,12 +331,18 @@ Address.prototype.ownInput = function ownInput(tx, index) { return inputs; }; -Address.prototype.scriptInputs = function scriptInputs(tx) { +Address.prototype.scriptInputs = function scriptInputs(tx, index) { var self = this; var publicKey = this.getPublicKey(); var redeem = this.getScript(); + if (index && typeof index === 'object') + index = tx.inputs.indexOf(index); + return tx.inputs.reduce(function(total, input, i) { + if (index != null && index !== i) + return total; + if (!input.output) return total; @@ -350,15 +356,21 @@ Address.prototype.scriptInputs = function scriptInputs(tx) { }, 0); }; -Address.prototype.signInputs = function signInputs(tx, type) { +Address.prototype.signInputs = function signInputs(tx, type, index) { var self = this; var key = this.key; var total = 0; + if (index && typeof index === 'object') + index = tx.inputs.indexOf(index); + if (!key.privateKey) return 0; return tx.inputs.reduce(function(total, input, i) { + if (index != null && index !== i) + return total; + if (!input.output) return total; @@ -372,17 +384,22 @@ Address.prototype.signInputs = function signInputs(tx, type) { }, 0); }; -Address.prototype.sign = function sign(tx, type) { +Address.prototype.sign = function sign(tx, type, index) { var self = this; - var publicKey = this.getPublicKey(); var redeem = this.getScript(); var key = this.key; + if (index && typeof index === 'object') + index = tx.inputs.indexOf(index); + if (!key.privateKey) return 0; // Add signature script to each input return tx.inputs.reduce(function(total, input, i) { + if (index != null && index !== i) + return total; + // Filter inputs that this wallet own if (!input.output) return total; @@ -390,7 +407,7 @@ Address.prototype.sign = function sign(tx, type) { if (!self.ownOutput(input.output)) return total; - if (tx.scriptSig(i, key, publicKey, redeem, type)) + if (tx.sign(i, key, redeem, type)) total++; return total; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index f36cb61c..24ae2e69 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -218,7 +218,7 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) { return -1; }; -TX.prototype.scriptInput = function scriptInput(index, pub, redeem) { +TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { var input, s, n, i; if (typeof index !== 'number') @@ -249,7 +249,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) { if (bcoin.script.isPubkey(s)) { // P2PK - if (!utils.isEqual(s[0], pub)) + if (!utils.isEqual(s[0], publicKey)) return false; // Already has a script template (at least) if (input.script.length) @@ -257,16 +257,16 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) { input.script = [[]]; } else if (bcoin.script.isPubkeyhash(s)) { // P2PKH - if (!utils.isEqual(s[2], bcoin.address.hash160(pub))) + if (!utils.isEqual(s[2], bcoin.address.hash160(publicKey))) return false; // Already has a script template (at least) if (input.script.length) return true; - input.script = [[], pub]; + input.script = [[], publicKey]; } else if (bcoin.script.isMultisig(s)) { // Multisig for (i = 0; i < s.length; i++) { - if (utils.isEqual(s[i], pub)) + if (utils.isEqual(s[i], publicKey)) break; } @@ -290,7 +290,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) { input.script[i + 1] = []; } else { for (i = 0; i < s.length; i++) { - if (utils.isEqual(s[i], pub)) + if (utils.isEqual(s[i], publicKey)) break; } @@ -371,8 +371,8 @@ TX.prototype.signature = TX.prototype.createSignature; // Sign the now-built scriptSigs TX.prototype.signInput = function signInput(index, key, type) { - var input, s, hash, signature; - var len, m, n, keys, pub, pkh, ki, signatures, i; + var input, s, signature, ki, signatures, i; + var len, m, n, keys, publicKey, keyHash; if (typeof index !== 'number') index = this.inputs.indexOf(index); @@ -401,9 +401,8 @@ TX.prototype.signInput = function signInput(index, key, type) { len--; } - // Get pubkey and pubkey hash. - pub = key.getPublic(true, 'array'); - pkh = bcoin.address.hash160(pub); + // Get pubkey. + publicKey = key.getPublic(true, 'array'); // Add signatures. if (bcoin.script.isPubkey(s)) { @@ -418,7 +417,7 @@ TX.prototype.signInput = function signInput(index, key, type) { return true; // Make sure the pubkey is ours. - if (!utils.isEqual(pub, s[0])) + if (!utils.isEqual(publicKey, s[0])) return false; input.script[0] = signature; @@ -438,7 +437,8 @@ TX.prototype.signInput = function signInput(index, key, type) { return true; // Make sure the pubkey hash is ours. - if (!utils.isEqual(pkh, s[2])) + keyHash = bcoin.address.hash160(publicKey); + if (!utils.isEqual(keyHash, s[2])) return false; input.script[0] = signature; @@ -502,7 +502,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // Find the key index so we can place // the signature in the same index. for (ki = 0; ki < keys.length; ki++) { - if (utils.isEqual(pub, keys[ki])) + if (utils.isEqual(publicKey, keys[ki])) break; } @@ -555,7 +555,8 @@ TX.prototype.signInput = function signInput(index, key, type) { return signatures === m; }; -TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) { +TX.prototype.sign = function sign(index, key, redeem, type) { + var publicKey = key.getPublic(true, 'array'); var input; if (index && typeof index === 'object') @@ -565,14 +566,14 @@ TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) { assert(input); // Build script for input - if (!this.scriptInput(index, pub, redeem)) + if (!this.scriptInput(index, publicKey, redeem)) return false; // Sign input if (!this.signInput(index, key, type)) return false; - return input.script; + return true; }; TX.prototype.isSigned = function isSigned(index, required) { diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index c52f31b9..9b506223 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -683,27 +683,27 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx) { this.setReceiveDepth(depth.receive); }; -Wallet.prototype.scriptInputs = function scriptInputs(tx) { +Wallet.prototype.scriptInputs = function scriptInputs(tx, index) { this.fillPrevout(tx); var addresses = this.deriveInputs(tx); return addresses.reduce(function(total, address) { - return total + address.scriptInputs(tx); + return total + address.scriptInputs(tx, index); }, 0); }; -Wallet.prototype.signInputs = function signInputs(tx, type) { +Wallet.prototype.signInputs = function signInputs(tx, type, index) { this.fillPrevout(tx); var addresses = this.deriveInputs(tx); return addresses.reduce(function(total, address) { - return total + address.signInputs(tx, type); + return total + address.signInputs(tx, type, index); }, 0); }; -Wallet.prototype.sign = function sign(tx, type) { +Wallet.prototype.sign = function sign(tx, type, index) { this.fillPrevout(tx); var addresses = this.deriveInputs(tx); return addresses.reduce(function(total, address) { - return total + address.sign(tx, type); + return total + address.sign(tx, type, index); }, 0); }; diff --git a/test/wallet-test.js b/test/wallet-test.js index cd7ec392..ddda39dc 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -256,8 +256,8 @@ describe('Wallet', function() { tx.input(unspent1[1]); tx.input(unspent1[2]); tx.input(unspent2[1]); - assert.equal(w1.sign(tx, 'all', tx.inputs.slice()), 2); - assert.equal(w2.sign(tx, 'all', tx.inputs.slice(2)), 1); + assert.equal(w1.sign(tx, 'all'), 2); + assert.equal(w2.sign(tx, 'all'), 1); // Verify assert.equal(tx.verify(), true);