diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 98b31d15..d24a451f 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -942,6 +942,25 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { return true; }; +script.num = function num(value, useNum) { + if (utils.isFinite(value)) + return useNum ? value : new bn(value, 'le'); + + assert(utils.isBuffer(value)); + + value = new bn(value, 'le'); + + if (useNum) { + try { + return value.toNumber(); + } catch (e) { + return 0; + } + } + + return value; +}; + script.redeem = function redeem(keys, m, n) { if (keys.length !== n) throw new Error(n + ' keys are required to generate redeem script'); @@ -1041,15 +1060,10 @@ script.spendable = function spendable(s, lockTime) { script.isPubkey = function isPubkey(s, key) { var res; - s = script.subscript(s); - - if (script.lockTime(s)) - s = s.slice(3); - if (s.length !== 2) return false; - res = Array.isArray(s[0]) && s[1] === 'checksig'; + res = script.isKey(s[0]) && s[1] === 'checksig'; if (!res) return false; @@ -1063,17 +1077,12 @@ script.isPubkey = function isPubkey(s, key) { script.isPubkeyhash = function isPubkeyhash(s, hash) { var res; - s = script.subscript(s); - - if (script.lockTime(s)) - s = s.slice(3); - if (s.length !== 5) return false; res = s[0] === 'dup' && s[1] === 'hash160' - && Array.isArray(s[2]) + && script.isHash(s[2]) && s[3] === 'eqverify' && s[4] === 'checksig'; @@ -1090,11 +1099,6 @@ script.isMultisig = function isMultisig(s, keys) { var m, n, i, j; var total = 0; - s = script.subscript(s); - - if (script.lockTime(s)) - s = s.slice(3); - if (s.length < 4) return false; @@ -1103,23 +1107,14 @@ script.isMultisig = function isMultisig(s, keys) { n = s[s.length - 2]; - if (Array.isArray(n)) { - if (n.length !== 1) - return false; - n = n[0]; - } - + // Bitcoind technically doesn't check for the + // 15 limit here. It just counts the sigops + // later. if (!(n >= 1 && n <= 15)) return false; m = s[0]; - if (Array.isArray(m)) { - if (m.length !== 1) - return false; - m = m[0]; - } - if (!(m >= 1 && m <= n)) return false; @@ -1127,7 +1122,7 @@ script.isMultisig = function isMultisig(s, keys) { return false; for (i = 1; i < n + 1; i++) { - if (!Array.isArray(s[i])) + if (!script.isKey(s[i])) return false; } @@ -1151,17 +1146,11 @@ script.isMultisig = function isMultisig(s, keys) { script.isScripthash = function isScripthash(s, hash) { var res; - s = script.subscript(s); - - if (script.lockTime(s)) - s = s.slice(3); - if (s.length !== 3) return false; res = s[0] === 'hash160' - && Array.isArray(s[1]) - && s[1].length === 20 + && script.isHash(s[1]) && s[2] === 'eq'; if (!res) @@ -1174,8 +1163,6 @@ script.isScripthash = function isScripthash(s, hash) { }; script.isNulldata = function isNulldata(s) { - s = script.subscript(s); - if (s.length !== 2) return false; @@ -1188,7 +1175,7 @@ script.nulldata = function nulldata(s) { if (!script.isNulldata(s)) return false; - return script.subscript(s)[1]; + return s[1]; }; script.standardInput = function standardInput(s) { @@ -1200,8 +1187,6 @@ script.standardInput = function standardInput(s) { }; script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) { - s = script.subscript(s); - if (s.length !== 1 || !Array.isArray(s[0])) return false; @@ -1221,8 +1206,6 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) { }; script.isPubkeyhashInput = function isPubkeyhashInput(s, key) { - s = script.subscript(s); - if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1])) return false; @@ -1246,8 +1229,6 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) { if (script.isScripthashInput(s)) return false; - s = script.subscript(s); - if (s.length < 3) return false; @@ -1286,8 +1267,6 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) { script.isScripthashInput = function isScripthashInput(s, data) { var raw, redeem; - s = script.subscript(s); - // Grab the raw redeem script. raw = s[s.length - 1]; @@ -1303,7 +1282,7 @@ script.isScripthashInput = function isScripthashInput(s, data) { // P2SH redeem scripts can be nonstandard: make // it easier for other functions to parse this. - redeem = script.normalize(raw); + redeem = script.subscript(script.decode(raw)); // Get the "real" scriptSig s = s.slice(0, -1); @@ -1429,6 +1408,13 @@ script.isCoinbase = function isCoinbase(s, block, strict) { return coinbase; }; +script.isHash = function isHash(hash) { + if (!utils.isBuffer(hash)) + return false; + + return hash.length === 20; +}; + script.isKey = function isKey(key) { if (!utils.isBuffer(key)) return false; @@ -1636,7 +1622,9 @@ script.pushOnly = function pushOnly(s) { var i, op; for (i = 0; i < s.length; i++) { op = s[i]; - if (Array.isArray(op) || (op >= 1 && op <= 16)) + // if (Array.isArray(op) || (constants.opcodes[op] <= constants.opcodes['16'])) + // continue; + if (Array.isArray(op) || (op >= -1 && op <= 16)) continue; if (constants.opcodes[op] == null) return false; @@ -1678,7 +1666,7 @@ script.sigopsScripthash = function sigopsScripthash(s) { if (!script.pushOnly(s)) return 0; - s = script.decode(s[s.length - 1]); + s = script.subscript(script.decode(s[s.length - 1])); return script.sigops(s, true); }; @@ -1686,11 +1674,6 @@ script.sigopsScripthash = function sigopsScripthash(s) { script.args = function args(s) { var keys, m; - s = bcoin.script.subscript(s); - - if (script.lockTime(s)) - s = s.slice(3); - if (script.isPubkey(s)) return 1; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 2c996d94..ea4aa477 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -177,7 +177,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) { // P2SH if (bcoin.script.isScripthash(s)) { assert(redeem); - s = bcoin.script.normalize(redeem); + s = bcoin.script.subscript(bcoin.script.decode(redeem)); } else { redeem = null; } @@ -268,7 +268,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // P2SH if (bcoin.script.isScripthash(s)) { - s = bcoin.script.normalize(redeem); + s = bcoin.script.subscript(redeem); // Decrement `len` to avoid the redeem script len--; } @@ -325,7 +325,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // Something is very wrong here. Abort. if (len - 1 > n) - return; + return false; // Count the number of current signatures. signatures = 0; @@ -336,7 +336,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // Signatures are already finalized. if (signatures === m && len - 1 === m) - return; + return true; // This can happen in a case where another // implementation adds signatures willy-nilly @@ -362,7 +362,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // script. We tried to sign a transaction // that is not redeemable by us. if (ki === keys.length) - return; + return false; // Offset key index by one to turn it into // "sig index". Accounts for OP_0 byte at @@ -740,7 +740,7 @@ TX.prototype.maxSize = function maxSize() { // the isMultisig clause. // OP_PUSHDATA2 [redeem] size += 3 + s.length; - s = bcoin.script.normalize(s); + s = bcoin.script.subscript(bcoin.script.decode(s)); } if (bcoin.script.isPubkey(s)) { @@ -1169,7 +1169,7 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) { if (!Array.isArray(s)) return false; - s = bcoin.script.decode(s); + s = bcoin.script.subscript(bcoin.script.decode(s)); if (bcoin.script.standard(s)) { targs = bcoin.script.args(s);