diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index aec5a124..b2e4c281 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -739,7 +739,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { key = stack.pop(); sig = stack.pop(); - type = sig[sig.length - 1]; if (!script.isKey(key)) return false; @@ -752,11 +751,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { return false; } + type = sig[sig.length - 1]; + if (!constants.hashTypeByVal[type & 0x1f]) return false; subscript = script.subscript(s, lastSep); - hash = tx.subscriptHash(index, subscript, type); + hash = tx.signatureHash(index, subscript, type); res = script.checksig(hash, sig.slice(0, -1), key); if (o === 'checksigverify') { @@ -804,7 +805,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { succ = 0; for (i = 0, j = 0; i < m && j < n; i++) { sig = stack.pop(); - type = sig[sig.length - 1]; if (flags.strictder !== false) { if (!script.isValidSig(sig)) @@ -814,10 +814,12 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { return false; } + type = sig[sig.length - 1]; + if (!constants.hashTypeByVal[type & 0x1f]) return false; - hash = tx.subscriptHash(index, subscript, type); + hash = tx.signatureHash(index, subscript, type); res = false; for (; !res && j < n; j++) @@ -830,15 +832,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { // Extra value if (stack.length < 1) return false; + + val = stack.pop(); + if (flags.verifynulldummy !== false) { - if (stack[stack.length - 1].length > 0) + if (!Array.isArray(val) || val.length > 0) return false; } - stack.pop(); - - // Too many signatures on stack - // if (stack.length > 0) - // return false; res = succ >= m; if (o === 'checkmultisigverify') { @@ -982,16 +982,16 @@ script.size = function size(s) { return bcoin.script.encode(s).length; }; -script.normalize = function normalize(s) { - var bytes = true; - var i; - - for (i = 0; bytes && i < s.length; i++) { +script.isEncoded = function(s) { + for (var i = 0; i < s.length; i++) { if (typeof s[i] !== 'number') - bytes = false; + return false; } + return true; +}; - if (bytes) +script.normalize = function normalize(s) { + if (script.isEncoded(s)) s = script.decode(s); s = script.subscript(s); @@ -1632,10 +1632,10 @@ script.args = function args(s) { return m + 1; } - if (this.type === 'scripthash') + if (type === 'scripthash') return 1; - if (this.type === 'nulldata') + if (type === 'nulldata') return -1; return -1; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index b242887e..f60d7ed7 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -217,7 +217,7 @@ TX.prototype.signInput = function signInput(index, key, type) { if (typeof index !== 'number') index = this.inputs.indexOf(index); - if (!type) + if (type == null) type = 'all'; if (typeof type === 'string') @@ -238,7 +238,7 @@ TX.prototype.signInput = function signInput(index, key, type) { } // Get the hash of the current tx, minus the other inputs, plus the sighash. - hash = this.subscriptHash(index, redeem, type); + hash = this.signatureHash(index, redeem, type); // Sign the transaction with our one input signature = bcoin.ecdsa.sign(hash, key.priv).toDER(); @@ -315,7 +315,6 @@ TX.prototype.signInput = function signInput(index, key, type) { } }; -// Build the scriptSig and sign it TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) { var input; @@ -363,7 +362,6 @@ TX.prototype.output = function output(obj, value) { return this; }; -// compat TX.prototype.out = TX.prototype.output; TX.prototype.scriptOutput = function scriptOutput(index, options) { @@ -493,7 +491,7 @@ TX.prototype.getSubscript = function getSubscript(index) { return bcoin.script.subscript(script); }; -TX.prototype.subscriptHash = function subscriptHash(index, s, type) { +TX.prototype.signatureHash = function signatureHash(index, s, type) { var copy = this.clone(); var msg, hash; @@ -503,6 +501,8 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) { if (typeof type === 'string') type = constants.hashType[type]; + assert(type != null); + // bitcoind used to return 1 as an error code: // it ended up being treated like a hash. if (index >= copy.inputs.length) @@ -538,6 +538,8 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) { if (i !== index) input.seq = 0; }); + } else { + assert(false); } if (type & constants.hashType.anyonecanpay) { @@ -562,9 +564,6 @@ TX.prototype.verify = function verify(index, force, flags) { if (this.inputs.length === 0) return false; - if (!flags) - flags = {}; - return this.inputs.every(function(input, i) { var output; @@ -1011,8 +1010,6 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) { return false; args += targs; } else { - // Bitcoind returns here whether true - // or false... strange behavior (bug?) return script.sigops(s, true) <= constants.script.maxScripthashSigops; } } diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 6e8c06ed..b5921b47 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -42,6 +42,7 @@ function Wallet(options, passphrase) { this.loaded = false; this.lastTs = 0; this.changeAddress = options.changeAddress || null; + this.redeem = options.redeem || options.script; if (options.priv instanceof bcoin.hd.priv) { this.hd = options.priv; @@ -85,6 +86,12 @@ function Wallet(options, passphrase) { this.multisig(options.multisig || {}); + if (this.redeem) { + if (!bcoin.script.isEncoded(this.redeem)) + this.redeem = bcoin.script.encode(this.redeem); + this.type = 'scripthash'; + } + this.tx = new bcoin.txPool(this); this._init(); @@ -450,7 +457,6 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx) { if (!input.out.tx && this.tx._all[input.out.hash]) input.out.tx = this.tx._all[input.out.hash]; - // Filter inputs that this wallet own if (!input.out.tx || !this.ownOutput(input.out.tx)) return false; @@ -466,9 +472,6 @@ Wallet.prototype.signInputs = function signInputs(tx, type) { var key = this.key; var inputs = tx.inputs; - if (!type) - type = 'all'; - inputs = inputs.filter(function(input, i) { if (!input.out.tx && this.tx._all[input.out.hash]) input.out.tx = this.tx._all[input.out.hash]; @@ -485,9 +488,6 @@ Wallet.prototype.signInputs = function signInputs(tx, type) { }; Wallet.prototype.sign = function sign(tx, type) { - if (!type) - type = 'all'; - var pub = this.getPublicKey(); var redeem = this.getScript(); var key = this.key;