From 690f1629c3adc95cd4b8b53a700c3625f4d9216b Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 21 Apr 2016 10:24:09 -0700 Subject: [PATCH] FindAndDelete. misc cleanup. --- lib/bcoin/mempool.js | 10 +--- lib/bcoin/protocol/network.js | 2 +- lib/bcoin/script.js | 102 +++++++++++++++------------------- lib/bcoin/utils.js | 44 +++++++++++++-- 4 files changed, 86 insertions(+), 72 deletions(-) diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index 0ce4f6e3..aa5fc06e 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -483,11 +483,6 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) { if (tx.mutable) tx = tx.toTX(); - if (this.chain.segwitActive) { - flags |= constants.flags.VERIFY_WITNESS; - flags |= constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM; - } - callback = utils.wrap(callback, unlock); callback = utils.asyncify(callback); @@ -684,11 +679,8 @@ Mempool.prototype.verify = function verify(tx, callback) { var ret = {}; var fee, now, free, minFee; - if (this.chain.segwitActive) { - flags |= constants.flags.VERIFY_WITNESS; - flags |= constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM; + if (this.chain.segwitActive) mandatory |= constants.flags.VERIFY_WITNESS; - } this.checkLocks(tx, lockFlags, function(err, result) { if (err) diff --git a/lib/bcoin/protocol/network.js b/lib/bcoin/protocol/network.js index 874f3cf8..edfebdb2 100644 --- a/lib/bcoin/protocol/network.js +++ b/lib/bcoin/protocol/network.js @@ -501,7 +501,7 @@ testnet.block = { pruneAfterHeight: 1000, // maxTipAge: 0x7fffffff maxTipAge: 24 * 60 * 60, - slowHeight: 700000 + slowHeight: 500000 }; testnet.witness = false; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 1b749851..64b346a0 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -944,6 +944,8 @@ Script.prototype.getSubscript = function getSubscript(lastSep) { assert(lastSep <= 0 || this.code[lastSep] === opcodes.OP_CODESEPARATOR); for (i = lastSep + 1; i < this.code.length; i++) { + if (Script.isBadPush(this.code[i])) + break; if (this.code[i] !== opcodes.OP_CODESEPARATOR) code.push(this.code[i]); } @@ -1931,26 +1933,48 @@ Script.array = function(value) { Script.prototype.removeData = function removeData(data) { var total = 0; - var opcode, sig, raw, i, a, b; + var p, sig, raw, i, a, b; - if (!this.raw) - return this.removeDataFast(data); + // We need to reserialize the + // signature as a minimal push + // Note that this is _NOT_ + // minimaldata completely. It + // _always_ encodes a pushdata + // op! + p = new BufferWriter(); + if (data.length <= 0x4b) { + p.writeU8(data.length); + p.writeBytes(data); + } else if (data.length <= 0xff) { + p.writeU8(opcodes.OP_PUSHDATA1); + p.writeU8(data.length); + p.writeBytes(data); + } else if (data.length <= 0xffff) { + p.writeU8(opcodes.OP_PUSHDATA2); + p.writeU16(data.length); + p.writeBytes(data); + } else if (data.length <= 0xffffffff) { + p.writeU8(opcodes.OP_PUSHDATA4); + p.writeU32(data.length); + p.writeBytes(data); + } else { + assert(false, 'Bad pushdata op.'); + } + sig = p.render(); - // We need to reserialize - // the signature as minimaldata. - opcode = data.opcode; - delete data.opcode; - sig = Script.encode([data]); - if (opcode != null) - data.opcode = opcode; + // Should never happen, but + // bitcoind does this anyway. + if (sig.length === 0) + return total; + // Compare on the byte level. raw = this.encode(); // Note that this is _faster_ than Buffer#indexOf. for (i = 0; i < raw.length; i++) { if (raw.length - i < sig.length) break; - if (this._cmp(raw, sig, i) === 0) { + if (utils.icmp(raw, sig, i) === 0) { a = raw.slice(0, i); b = raw.slice(i + sig.length); raw = Buffer.concat([a, b]); @@ -1958,47 +1982,10 @@ Script.prototype.removeData = function removeData(data) { } } - this.raw = raw; - - return total; -}; - -Script.prototype._cmp = function _cmp(target, data, start) { - var i, a, b; - - if (target.length - start < data.length) - return -1; - - for (i = 0; i < data.length; i++) { - a = target[i + start]; - b = data[i]; - if (a < b) - return -1; - if (a > b) - return 1; - } - - return 0; -}; - -Script.prototype.removeDataFast = function removeData(data) { - var total = 0; - var i; - - for (i = this.code.length - 1; i >= 0; i--) { - if (!Buffer.isBuffer(this.code[i])) - continue; - if (!Script.checkMinimal(this.code[i])) - continue; - if (utils.equals(this.code[i], data)) { - this.code.splice(i, 1); - total++; - } - } - - if (this.raw && total > 0) { - this.raw = null; - this.encode(); + if (total > 0) { + this.code = Script.decode(raw); + if (this.raw) + this.raw = raw; } return total; @@ -2032,6 +2019,9 @@ Script.checkMinimal = function checkMinimal(value, flags) { if (value.opcode == null) return true; + if (value.length === 0) + return value.opcode === opcodes.OP_0; + if (value.length === 1 && value[0] >= 1 && value[0] <= 16) return false; @@ -2580,10 +2570,10 @@ Script.prototype.isNulldata = function isNulldata() { op = this.code[i]; if (Buffer.isBuffer(op)) continue; - if (op > opcodes.OP_16) - return false; if (Script.isBadPush(op)) return false; + if (op > opcodes.OP_16) + return false; } return true; @@ -3413,10 +3403,10 @@ Script.prototype.isPushOnly = function isPushOnly() { op = this.code[i]; if (Buffer.isBuffer(op)) continue; - if (op > opcodes.OP_16) - return false; if (Script.isBadPush(op)) return false; + if (op > opcodes.OP_16) + return false; } return true; }; diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index f01b7d9c..c31c381c 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -457,18 +457,21 @@ utils.isHex = function isHex(msg) { * @returns {Boolean} */ -utils.equals = function isEqual(a, b) { +utils.equals = function equals(a, b) { var i; - assert(Buffer.isBuffer(a)); - assert(Buffer.isBuffer(b)); + if (!Buffer.isBuffer(a)) + return false; - if (a.length !== b.length) + if (!Buffer.isBuffer(b)) return false; if (a.compare) return a.compare(b) === 0; + if (a.length !== b.length) + return false; + for (i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; @@ -2152,6 +2155,32 @@ utils.cmp = function cmp(a, b) { return 0; }; +/** + * Memcmp for comparing a needle to a haystack. + * @param {Buffer} target - Haystack. + * @param {Buffer} data - Needle. + * @param {Number} start - Index in haystack to begin the comparison. + * @returns {Number} -1, 1, or 0. + */ + +utils.icmp = function icmp(target, data, start) { + var i, a, b; + + if (target.length - start < data.length) + return -1; + + for (i = 0; i < data.length; i++) { + a = target[i + start]; + b = data[i]; + if (a < b) + return -1; + if (a > b) + return 1; + } + + return 0; +}; + /** * memcmp in constant time (can only return true or false). * This protects us against timing attacks when @@ -2167,8 +2196,11 @@ utils.ccmp = function ccmp(a, b) { var res = 0; var i; - assert(Buffer.isBuffer(a)); - assert(Buffer.isBuffer(b)); + if (!Buffer.isBuffer(a)) + return false; + + if (!Buffer.isBuffer(b)) + return false; for (i = 0; i < a.length; i++) res |= a[i] ^ b[i];