diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index fd41ec29..4511d6d0 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -762,6 +762,15 @@ script.execute = function execute(s, stack, tx, index) { return true; }; +script.exec = function(input, output, tx, i) { + var stack = []; + script.execute(input, stack, tx, i); + var res = script.execute(output, stack, tx, i); + if (!res || stack.length === 0 || !utils.isEqual(stack.pop(), [ 1 ])) + return false; + return true; +}; + script.multisig = function(keys, m, n) { if (keys.length < m) throw new Error('Wrong amount of pubkeys for multisig script'); @@ -889,11 +898,13 @@ script.isMultisig = function isMultisig(s, pubs) { if (!pubs) return keys; - return m === keys.filter(function(k) { + var total = keys.filter(function(k) { return pubs.some(function(pub) { return utils.isEqual(k, pub); }); }).length; + + return total >= m; }; script.isScripthash = function isScripthash(s, hash) { @@ -903,12 +914,12 @@ script.isScripthash = function isScripthash(s, hash) { if (s.length !== 3) return false; - var ret = s[0] === 'hash160' && + var res = s[0] === 'hash160' && Array.isArray(s[1]) && s[1].length === 20 && s[2] === 'eq'; - if (!ret) + if (!res) return false; if (hash) @@ -941,29 +952,32 @@ script.standardInput = function standardInput(s) { || null; }; -script.isPubkeyInput = function isPubkeyInput(s, key) { - if (key) - throw new Error('Cannot check for pubkey in p2pk input.'); - +script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) { if (s.length !== 1 || !Array.isArray(s[0])) return false; - // return script.isValidSig(s[0]); + // var res = script.isValidSig(s[0]); + var res = 9 <= s[0].length && s[0].length <= 73; + if (!res) + return false; - return 9 <= s[0].length && s[0].length <= 73; + if (key) + return script.exec(s, [key, 'checksig'], tx, i); + + return true; }; script.isPubkeyhashInput = function isPubkeyhashInput(s, key) { if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1])) return false; - // var ret = script.isValidSig(s[0]) && + // var res = script.isValidSig(s[0]) && // 33 <= s[1].length && s[1].length <= 65; - var ret = 9 <= s[0].length && s[0].length <= 73 && + var res = 9 <= s[0].length && s[0].length <= 73 && 33 <= s[1].length && s[1].length <= 65; - if (!ret) + if (!res) return false; if (key) @@ -972,71 +986,50 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) { return true; }; -script.isMultisigInput = function isMultisigInput(s, pubs) { +script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) { if (s.length < 3) return false; if (!Array.isArray(s[0]) || s[0].length !== 0) return false; - if (pubs && !Array.isArray(pubs[0])) - pubs = [pubs]; - - var total = 0; for (var i = 1; i < s.length; i++) { - var ret = Array.isArray(s[i]) && 33 <= s[i].length && s[i].length <= 65; - if (!ret) + // var res = Array.isArray(s[i]) && script.isValidSig(s[i]); + var res = Array.isArray(s[i]) && 9 <= s[i].length && s[i].length <= 73; + if (!res) return false; - if (pubs) { - var has = pubs.some(function(pub) { - return utils.isEqual(s[i], pub); - }); - if (has) - total++; - } } - if (!pubs) - return true; + if (pubs && pubs.length >= 2) { + var o = script.multisig(pubs, 2, pubs.length); + return script.exec(s, o, tx, i); + } - return total; + return true; }; -script.isScripthashInput = function isScripthashInput(s, pubs) { +script.isScripthashInput = function isScripthashInput(s, redeem) { if (s.length < 4) return false; if (!Array.isArray(s[0]) || s[0].length !== 0) return false; - if (pubs && !Array.isArray(pubs[0])) - pubs = [pubs]; - - var total = 0; for (var i = 1; i < s.length - 1; i++) { - var ret = Array.isArray(s[i]) && 33 <= s[i].length && s[i].length <= 65; - if (!ret) + // var res = Array.isArray(s[i]) && script.isValidSig(s[i]); + var res = Array.isArray(s[i]) && 9 <= s[i].length && s[i].length <= 73; + if (!res) return false; - if (pubs) { - var has = pubs.some(function(pub) { - return utils.isEqual(s[i], pub); - }); - if (has) - total++; - } } var r = Array.isArray(s[s.length - 1]) && s[s.length - 1]; if (r[r.length - 1] !== constants.opcodes.checkmultisig) return false; - if (!pubs) - return true; + if (redeem) + return utils.isEqual(redeem, r); - // var m = r[0]; - // return m === total; - - return total; + return true; }; // https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 3cf3a48f..339251a1 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -125,18 +125,40 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) { return -1; }; -TX.prototype.signature = function(input, key, type) { +TX.prototype.signatureHash = function(i, type) { + if (typeof i === 'object') + i = this.inputs.indexOf(i); + if (!type) type = 'all'; if (typeof type === 'string') type = constants.hashType[type]; + // Get the current input. + var input = this.inputs[i]; + // Get the previous output's subscript var s = input.out.tx.getSubscript(input.out.index); // Get the hash of the current tx, minus the other inputs, plus the sighash. - var hash = this.subscriptHash(tx.inputs.indexOf(input), s, type); + var hash = this.subscriptHash(i, s, type); + + return hash; +}; + +TX.prototype.signature = function(i, key, type) { + if (typeof i === 'object') + i = this.inputs.indexOf(i); + + if (!type) + type = 'all'; + + if (typeof type === 'string') + type = constants.hashType[type]; + + // Get the hash of the current tx, minus the other inputs, plus the sighash. + var hash = this.sigHash(i, type); // Sign the transaction with our one input var signature = bcoin.ecdsa.sign(hash, key.priv).toDER(); diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 515cc4bf..323246a6 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -357,6 +357,7 @@ Wallet.validateAddress = Wallet.prototype.validateAddress; Wallet.prototype.ownOutput = function ownOutput(tx, index) { var scriptHash = this.getFullHash(); var hash = this.getOwnHash(); + var key = this.getOwnPublicKey(); var keys = this.getPublicKeys(); var outputs = tx.outputs.filter(function(output, i) { @@ -365,7 +366,7 @@ Wallet.prototype.ownOutput = function ownOutput(tx, index) { var s = output.script; - if (bcoin.script.isPubkey(s, hash)) + if (bcoin.script.isPubkey(s, key)) return true; if (bcoin.script.isPubkeyhash(s, hash)) @@ -390,19 +391,33 @@ Wallet.prototype.ownInput = function ownInput(tx, index) { var scriptHash = this.getFullHash(); var hash = this.getOwnHash(); var key = this.getOwnPublicKey(); + var redeem = this.getFullPublicKey(); var keys = this.getPublicKeys(); var inputs = tx.inputs.filter(function(input, i) { if (index !== undefined && index !== i) return false; + // if (bcoin.script.isPubkeyInput(input.script, key, tx, i)) + // return true; + if (bcoin.script.isPubkeyhashInput(input.script, key)) return true; + if (bcoin.script.isScripthashInput(input.script, redeem)) + return true; + + // if (bcoin.script.isMultisigInput(input.script, key, tx, i)) + // return true; + if (!input.out.tx) return false; var s = input.out.tx.outputs[input.out.index].script; + + if (bcoin.script.isPubkey(s, key)) + return true; + if (bcoin.script.isPubkeyhash(s, hash)) return true;