diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index 080d2076..3eb64ce0 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -277,7 +277,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) { vector[0] = dummy; // Grab `n` value (number of keys). - n = prev.code[prev.code.length - 2] - 0x50; + n = Script.getSmall(prev.code[prev.code.length - 2]); // Fill script with `n` signature slots. for (i = 0; i < n; i++) @@ -434,10 +434,10 @@ MTX.prototype.signInput = function signInput(index, addr, type) { keys = prev.code.slice(1, -2); // Grab `m` value (number of sigs required). - m = prev.code[0] - 0x50; + m = Script.getSmall(prev.code[0]); // Grab `n` value (number of keys). - n = prev.code[prev.code.length - 2] - 0x50; + n = Script.getSmall(prev.code[prev.code.length - 2]); } else { // Only allow non-standard signing for // scripthash. @@ -584,7 +584,7 @@ MTX.prototype.isSigned = function isSigned(m) { return false; } else if (prev.isMultisig()) { // Grab `m` value (number of required sigs). - m = prev.code[0] - 0x50; + m = Script.getSmall(prev.code[0]); // Ensure all members are signatures. for (j = 1; j < len; j++) { @@ -737,7 +737,7 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) { } else if (prev.isMultisig()) { // Bare Multisig // Get the previous m value: - m = prev.code[0] - 0x50; + m = Script.getSmall(prev.code[0]); // OP_0 size += 1; // OP_PUSHDATA0 [signature] ... diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index 316df468..7b094bec 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -588,21 +588,19 @@ Peer.prototype._handleGetAddr = function handleGetAddr() { }; Peer.prototype._handleInv = function handleInv(items) { - var blocks, txs; + var blocks = []; + var txs = []; + var item, i; this.emit('inv', items); - txs = items.filter(function(item) { - return item.type === constants.inv.tx; - }).map(function(item) { - return item.hash; - }); - - blocks = items.filter(function(item) { - return item.type === constants.inv.block; - }).map(function(item) { - return item.hash; - }); + for (i = 0; i < items.length; i++) { + item = items[i]; + if (item.type === constants.inv.tx) + txs.push(item.hash); + else if (item.type === constants.inv.block) + blocks.push(item.hash); + } if (blocks.length > 0) this.emit('blocks', blocks); @@ -620,11 +618,16 @@ Peer.prototype._handleHeaders = function handleHeaders(headers) { }; Peer.prototype._handleReject = function handleReject(payload) { - var hash = utils.toHex(payload.data); - var entry = this._broadcast.map[hash]; + var hash, entry; this.emit('reject', payload); + if (!payload.data) + return; + + hash = utils.toHex(payload.data); + entry = this._broadcast.map[hash]; + if (!entry) return; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 8c576dcc..f2348b73 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -794,7 +794,7 @@ Pool.prototype._createPeer = function _createPeer(options) { }); peer.on('reject', function(payload) { - var data = utils.revHex(utils.toHex(payload.data)); + var data = payload.data ? utils.revHex(utils.toHex(payload.data)) : null; utils.debug( 'Reject: msg=%s ccode=%s reason=%s data=%s', diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 075f20bc..da327825 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -1295,9 +1295,9 @@ Script.createMultisig = function createMultisig(keys, m, n) { assert(m >= 1 && m <= n); assert(n >= 1 && n <= 15); - return new Script([m + 0x50].concat( + return new Script([opc[m]].concat( utils.sortKeys(keys), - [n + 0x50, opc.checkmultisig] + [opc[n], opc.checkmultisig] )); }; @@ -1357,8 +1357,8 @@ Script.prototype.isStandard = function isStandard() { var m, n; if (type === 'multisig') { - m = this.code[0] - 0x50; - n = this.code[this.code.length - 2] - 0x50; + m = Script.getSmall(this.code[0]); + n = Script.getSmall(this.code[this.code.length - 2]); if (n < 1 || n > 3) return false; @@ -1526,26 +1526,16 @@ Script.prototype.isMultisig = function isMultisig(keys) { if (this.code[this.code.length - 1] !== opc.checkmultisig) return false; - n = this.code[this.code.length - 2]; + n = Script.getSmall(this.code[this.code.length - 2]); - if (!(n >= opc['1'] && n <= opc['16'])) + if (n == null) return false; - n -= 0x50; + m = Script.getSmall(this.code[0]); - // Bitcoind technically doesn't check for the - // 15 limit here. It just counts the sigops - // later. - if (!(n >= 1 && n <= 15)) + if (m == null) return false; - m = this.code[0]; - - if (!(m >= opc['1'] && m <= opc['16'])) - return false; - - m -= 0x50; - if (!(m >= 1 && m <= n)) return false; @@ -1634,7 +1624,8 @@ Script.prototype.isWitnessProgram = function isWitnessProgram() { if (!Buffer.isBuffer(this.code[1])) return false; - return this.code[0] >= opc['0'] && this.code[0] <= opc['16'] + return (this.code[0] === opc['0'] + || (this.code[0] >= opc['1'] && this.code[0] <= opc['16'])) && this.code[1].length >= 2 && this.code[1].length <= 32; }; @@ -1644,15 +1635,15 @@ Script.prototype.getWitnessProgram = function getWitnessProgram() { if (!this.isWitnessProgram()) return; - version = this.code[0]; + version = Script.getSmall(this.code[0]); data = this.code[1]; if (version > 0) { // No interpretation of script (anyone can spend) type = 'unknown'; - } else if (version === opc['0'] && data.length === 20) { + } else if (version === 0 && data.length === 20) { type = 'witnesspubkeyhash'; - } else if (version === opc['0'] && data.length === 32) { + } else if (version === 0 && data.length === 32) { type = 'witnessscripthash'; } else { // Fail on bad version=0 @@ -1660,7 +1651,7 @@ Script.prototype.getWitnessProgram = function getWitnessProgram() { } return { - version: version === opc['0'] ? 0 : version - 0x50, + version: version, type: type, data: data }; @@ -2267,7 +2258,7 @@ Script.prototype.getArgs = function getArgs() { if (this.isMultisig()) { keys = this.code.slice(1, -2); - m = this.code[0] - 0x50; + m = Script.getSmall(this.code[0]); if (keys.length < 1 || m < 1) return -1; return m + 1; @@ -2335,6 +2326,48 @@ Script.fromString = function fromString(code) { return new Script(code); }; +Script.getSmall = function getSmall(op) { + if (typeof op !== 'number') + return null; + + if (op === opc['0']) + return 0; + + if (op >= opc['1'] && op <= opc['16']) + return op - 0x50; + + return null; +}; + +Script.fromSymbolic = function fromSymbolic(items) { + var code = new Array(items.length); + var i, op; + + for (i = 0; i < items.length; i++) { + op = items[i]; + + if (Buffer.isBuffer(op)) { + code[i] = op; + continue; + } + + if (+op === -1) + op = '1negate'; + else if (+op === 0 || op === 'false') + op = 0; + else if (+op === 1 || op === 'true') + op = 1; + else if (+op >= 1 && +op <= 16) + op = +op; + + code[i] = constants.opcodes[op]; + + assert(code[i] != null, 'Unknown opcode.'); + } + + return new Script(code); +}; + Script.verify = function verify(input, witness, output, tx, i, flags) { var copy, res, raw, redeem, hadWitness; var stack = new Stack();