diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 7e4f1c83..11faeb0c 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -850,15 +850,17 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callbac 100)); } - if (self.options.verifySync !== true) - continue; + //if (self.options.verifySync !== true) + // continue; if (!scriptCheck) continue; // Verify the scripts if (!tx.verify(j, true, flags)) { - assert(!historical, 'BUG: Invalid inputs in historical data!'); + utils.print(tx.rhash); + console.error(tx.inputs[j]); + //assert(!historical, 'BUG: Invalid inputs in historical data!'); return callback(new VerifyError(block, 'invalid', 'mandatory-script-verify-flag-failed', @@ -877,7 +879,7 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callbac if (block.getClaimed().cmp(block.getReward()) > 0) return callback(new VerifyError(block, 'invalid', 'bad-cb-amount', 100)); - if (self.options.verifySync === true) + //if (self.options.verifySync === true) return callback(); if (!scriptCheck) diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 8a9759d7..17002e20 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -280,7 +280,7 @@ Pool.prototype._init = function _init() { this.chain.on('orphan', function(block, data, peer) { self.emit('orphan', data, peer); // Resolve orphan chain - self.resolveOrphan(self.peers.load, null, data.hash); + // self.resolveOrphan(self.peers.load, null, data.hash); }); this.chain.on('full', function() { @@ -830,8 +830,8 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer, callback) { peer.sendReject(block, err.code, err.reason, err.score); if (err.reason === 'bad-prevblk') { - // self.chain.purgePending(); - // self.resolveOrphan(peer, null, block.hash('hex')); + if (peer === self.peers.load) + self.resolveOrphan(peer, null, block.hash('hex')); } self.scheduleRequests(peer); @@ -1262,6 +1262,11 @@ Pool.prototype._removePeer = function _removePeer(peer) { this.peers.all.splice(i, 1); if (this.peers.load === peer) { + Object.keys(this.request.map).forEach(function(hash) { + var item = this.request.map[hash]; + if (item.peer === peer) + item.finish(); + }, this); bcoin.debug('Removed loader peer (%s).', peer.host); this.peers.load = null; } diff --git a/lib/bcoin/protocol/network.js b/lib/bcoin/protocol/network.js index 13f0fe43..dc1b5261 100644 --- a/lib/bcoin/protocol/network.js +++ b/lib/bcoin/protocol/network.js @@ -482,7 +482,8 @@ testnet.block = { bip34height: 21111, bip34hash: 'f88ecd9912d00d3f5c2a8e0f50417d3e415c75b3abe584346da9b32300000000', pruneAfterHeight: 1000, - maxTipAge: 0x7fffffff + // maxTipAge: 0x7fffffff + maxTipAge: 24 * 60 * 60 }; testnet.witness = false; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 16f1fc37..07f804c2 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -15,7 +15,7 @@ var BufferWriter = require('./writer'); var opcodes = constants.opcodes; var STACK_TRUE = new Buffer([1]); var STACK_FALSE = new Buffer([]); -var STACK_NEGATE = new Buffer([0xff]); +var STACK_NEGATE = new Buffer([0x81]); /** * A big number (bn.js) @@ -417,6 +417,8 @@ Stack.prototype.slice = function slice(start, end) { */ Stack.prototype.splice = function splice(i, remove, insert) { + if (insert === undefined) + return this.items.splice(i, remove); return this.items.splice(i, remove, insert); }; @@ -610,10 +612,10 @@ Stack.prototype._pickroll = function pickroll(op, flags) { val = this.pop(); n = Script.num(val, flags).toNumber(); - if (n <= 0 || n > this.length) + if (n < 0 || n >= this.length) throw new ScriptError('Bad value.', op); - val = this.get(-n - 1); + val = this.top(-n - 1); if (op === opcodes.OP_ROLL) this.splice(this.length - n - 1, 1); @@ -1180,10 +1182,10 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version n = Script.num(stack.pop(), flags); switch (op) { case opcodes.OP_1ADD: - n.iadd(1); + n.iaddn(1); break; case opcodes.OP_1SUB: - n.isub(1); + n.isubn(1); break; case opcodes.OP_2MUL: n.iushln(1); @@ -1229,7 +1231,8 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version case opcodes.OP_LESSTHANOREQUAL: case opcodes.OP_GREATERTHANOREQUAL: case opcodes.OP_MIN: - case opcodes.OP_MAX: { + case opcodes.OP_MAX: + case opcodes.OP_WITHIN: { switch (op) { case opcodes.OP_ADD: case opcodes.OP_SUB: @@ -1318,10 +1321,9 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version } if (typeof n === 'boolean') n = new bn(n ? 1 : 0); - res = Script.bool(n); if (op === opcodes.OP_NUMEQUALVERIFY) { - if (!res) - return false; + if (!Script.bool(n)) + throw new ScriptError('Verify failed.', op, ip); } else { stack.push(Script.array(n)); } @@ -1756,6 +1758,8 @@ Script.bool = function bool(value) { */ Script.num = function num(value, flags, size) { + var result, n; + assert(Buffer.isBuffer(value)); if (flags == null) @@ -1782,21 +1786,20 @@ Script.num = function num(value, flags, size) { } } - // If we are signed, do (~num + 1) to get - // the positive counterpart and set bn's - // negative flag. + if (value.length === 0) + return new bn(0); + + result = new bn(value, 'le'); + + // If the input vector's most significant byte is + // 0x80, remove it from the result's msb and return + // a negative. if (value[value.length - 1] & 0x80) { - if (utils.isNegZero(value, 'le')) { - value = new bn(0); - } else { - value = new bn(value, 'le'); - value = value.notn(size * 8).addn(1).neg(); - } - } else { - value = new bn(value, 'le'); + n = new bn(0x80).ushln(8 * (value.length - 1)).notn(64); + return result.uand(n).neg(); } - return value; + return result; }; /** @@ -1812,6 +1815,8 @@ Script.num = function num(value, flags, size) { */ Script.array = function(value) { + var neg, result; + if (Buffer.isBuffer(value)) return value; @@ -1820,19 +1825,33 @@ Script.array = function(value) { assert(bn.isBN(value)); - // Convert the number to the - // negative byte representation. - if (value.isNeg()) { - if (value.cmpn(0) === 0) - value = new bn(0); - else - value = value.neg().notn(value.byteLength() * 8).subn(1); - } - if (value.cmpn(0) === 0) return STACK_FALSE; - return value.toBuffer('le'); + // If the most significant byte is >= 0x80 + // and the value is positive, push a new + // zero-byte to make the significant + // byte < 0x80 again. + + // If the most significant byte is >= 0x80 + // and the value is negative, push a new + // 0x80 byte that will be popped off when + // converting to an integral. + + // If the most significant byte is < 0x80 + // and the value is negative, add 0x80 to + // it, since it will be subtracted and + // interpreted as a negative when + // converting to an integral. + + neg = value.cmpn(0) < 0; + result = value.toArray('le'); + if (result[result.length - 1] & 0x80) + result.push(neg ? 0x80 : 0); + else if (neg) + result[result.length - 1] |= 0x80; + + return new Buffer(result); }; /** @@ -1927,7 +1946,7 @@ Script.checkMinimal = function checkMinimal(value, flags) { if (value.length === 1 && value[0] >= 1 && value[0] <= 16) return false; - if (value.length === 1 && value[0] === 0xff) + if (value.length === 1 && value[0] === 0x81) return false; if (value.length <= 75) @@ -3824,45 +3843,41 @@ Script.decode = function decode(buf) { if (op >= 0x01 && op <= 0x4b) { code.push(buf.slice(off, off + op)); off += op; - if (off > buf.length) { - utils.hidden(code[code.length - 1], 'pushdata', { - opcode: null, - size: op - }); - } + // if (off > buf.length) { + utils.hidden(code[code.length - 1], 'pushdata', { + opcode: null, + size: op + }); } else if (op === opcodes.OP_PUSHDATA1) { size = buf[off]; off += 1; code.push(buf.slice(off, off + size)); off += size; - if (size <= 0x4b || off > buf.length) { - utils.hidden(code[code.length - 1], 'pushdata', { - opcode: op, - size: size - }); - } + // if (size <= 0x4b || off > buf.length) { + utils.hidden(code[code.length - 1], 'pushdata', { + opcode: op, + size: size + }); } else if (op === opcodes.OP_PUSHDATA2) { size = utils.readU16(buf, off); off += 2; code.push(buf.slice(off, off + size)); off += size; - if (size <= 0xff || off > buf.length) { - utils.hidden(code[code.length - 1], 'pushdata', { - opcode: op, - size: size - }); - } + // if (size <= 0xff || off > buf.length) { + utils.hidden(code[code.length - 1], 'pushdata', { + opcode: op, + size: size + }); } else if (op === opcodes.OP_PUSHDATA4) { size = utils.readU32(buf, off); off += 4; code.push(buf.slice(off, off + size)); off += size; - if (size <= 0xffff || off > buf.length) { - utils.hidden(code[code.length - 1], 'pushdata', { - opcode: op, - size: size - }); - } + // if (size <= 0xffff || off > buf.length) { + utils.hidden(code[code.length - 1], 'pushdata', { + opcode: op, + size: size + }); } else { code.push(op); } @@ -3928,7 +3943,7 @@ Script.encode = function encode(code, writer) { } else if (op[0] >= 1 && op[0] <= 16) { p.writeU8(op[0] + 0x50); continue; - } else if (op[0] === 0xff) { + } else if (op[0] === 0x81) { p.writeU8(opcodes.OP_1NEGATE); continue; } diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 490f81d8..5ff4751a 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -63,7 +63,7 @@ function TX(data, block, index) { data = {}; this.type = 'tx'; - this.version = data.version || 1; + this.version = data.version != null ? data.version : 1; this.flag = data.flag || 1; this.inputs = []; this.outputs = [];