From 11ef30b94232cff09363f91490d1e7127b81308e Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 20 Apr 2016 13:08:42 -0700 Subject: [PATCH] refactor and comments/explanation. --- lib/bcoin/script.js | 88 ++++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 7c1245ab..34bfd813 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -1982,18 +1982,18 @@ Script.array = function(value) { Script.prototype.removeData = function removeData(data) { var total = 0; - var op, sig, raw, i, a, b; + var opcode, sig, raw, i, a, b; if (!this.raw) return this.removeDataFast(data); // We need to reserialize // the signature as minimaldata. - op = data.op; - delete data.op; + opcode = data.opcode; + delete data.opcode; sig = Script.encode([data]); - if (op != null) - utils.hidden(data, 'op', op); + if (opcode != null) + data.opcode = opcode; raw = this.encode(); @@ -2080,7 +2080,7 @@ Script.checkMinimal = function checkMinimal(value, flags) { if (!(flags & constants.flags.VERIFY_MINIMALDATA)) return true; - if (value.op == null) + if (value.opcode == null) return true; if (value.length === 1 && value[0] >= 1 && value[0] <= 16) @@ -2090,13 +2090,13 @@ Script.checkMinimal = function checkMinimal(value, flags) { return false; if (value.length <= 75) - return value.op === value.length; + return value.opcode === value.length; if (value.length <= 255) - return value.op === opcodes.OP_PUSHDATA1; + return value.opcode === opcodes.OP_PUSHDATA1; if (value.length <= 65535) - return value.op === opcodes.OP_PUSHDATA2; + return value.opcode === opcodes.OP_PUSHDATA2; return true; }; @@ -4040,16 +4040,6 @@ Script.fromRaw = function fromRaw(data, enc) { * @returns {Array} Script code. */ -Script.isBadPush = function isBadPush(op) { - if (Buffer.isBuffer(op)) - return false; - if (op >= 0x01 && op <= 0x4b) - return true; - if (op >= opcodes.OP_PUSHDATA1 && op <= opcodes.OP_PUSHDATA4) - return true; - return false; -}; - Script.decode = function decode(buf) { var code = []; var p = new BufferReader(buf, true); @@ -4068,7 +4058,7 @@ Script.decode = function decode(buf) { continue; } data = p.readBytes(op); - utils.hidden(data, 'op', op); + data.opcode = op; code.push(data); } else if (op === opcodes.OP_PUSHDATA1) { if (p.left() < 1) { @@ -4086,7 +4076,7 @@ Script.decode = function decode(buf) { continue; } data = p.readBytes(size); - utils.hidden(data, 'op', op); + data.opcode = op; code.push(data); } else if (op === opcodes.OP_PUSHDATA2) { if (p.left() < 2) { @@ -4105,7 +4095,7 @@ Script.decode = function decode(buf) { continue; } data = p.readBytes(size); - utils.hidden(data, 'op', op); + data.opcode = op; code.push(data); } else if (op === opcodes.OP_PUSHDATA4) { if (p.left() < 4) { @@ -4126,7 +4116,7 @@ Script.decode = function decode(buf) { continue; } data = p.readBytes(size); - utils.hidden(data, 'op', op); + data.opcode = op; code.push(data); } else { code.push(op); @@ -4136,7 +4126,6 @@ Script.decode = function decode(buf) { return code; }; - /** * Encode and serialize script code. This will _not_ * include the varint size at the start. This will @@ -4162,19 +4151,19 @@ Script.encode = function encode(code, writer) { if (Buffer.isBuffer(op)) { // Check for nonstandard pushdatas that // may have been decoded from before. - if (op.op != null) { - if (op.op <= 0x4b) { + if (op.opcode != null) { + if (op.opcode <= 0x4b) { p.writeU8(op.length); p.writeBytes(op); - } else if (op.op === opcodes.OP_PUSHDATA1) { + } else if (op.opcode === opcodes.OP_PUSHDATA1) { p.writeU8(opcodes.OP_PUSHDATA1); p.writeU8(op.length); p.writeBytes(op); - } else if (op.op === opcodes.OP_PUSHDATA2) { + } else if (op.opcode === opcodes.OP_PUSHDATA2) { p.writeU8(opcodes.OP_PUSHDATA2); p.writeU16(op.length); p.writeBytes(op); - } else if (op.op === opcodes.OP_PUSHDATA4) { + } else if (op.opcode === opcodes.OP_PUSHDATA4) { p.writeU8(opcodes.OP_PUSHDATA4); p.writeU32(op.length); p.writeBytes(op); @@ -4230,6 +4219,47 @@ Script.encode = function encode(code, writer) { return p; }; +/** + * Determine whether GetOp2 should fail + * on a given op due to a bad push (either + * not enough size bytes after a PUSHDATA, + * or not enough data after the size. + * + * If bitcoind comes across a bad push, it + * will return an invalid opcode. The problem + * is bitcoind parses scripts _as_ they are + * executing, which can be slow for us because + * now every function that needs to test the + * script needs to parse the raw data. It's + * also impossible to read a script + * _backwards_ making testing for things like + * multisig outputs even more difficult. + * + * If BCoin comes accross a bad push in its + * initial parsing, it simply will _not + * consider the pushdata to be a pushdata_ + * but just another opcode in the code array + * (all of the data after the pushdata op + * will also be considered opcodes rather + * than data). This function checks to see + * if an op is a direct push, or PUSHDATA1 + * to PUSHDATA4 -- these opcodes cannot + * exist in the code array of valid parsed + * scripts. + * @param {Number|Buffer} op + * @returns {Boolean} + */ + +Script.isBadPush = function isBadPush(op) { + if (Buffer.isBuffer(op)) + return false; + if (op >= 0x01 && op <= 0x4b) + return true; + if (op >= opcodes.OP_PUSHDATA1 && op <= opcodes.OP_PUSHDATA4) + return true; + return false; +}; + /** * Test an object to see if it is a Script. * @param {Object} obj