From 2775382691b2bce966066a438b768eb2ecec9cc7 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 18 Apr 2016 19:19:06 -0700 Subject: [PATCH] more accurate multisig. misc fixes. --- lib/bcoin/chain.js | 9 +++- lib/bcoin/http/server.js | 14 +++++-- lib/bcoin/miner.js | 2 +- lib/bcoin/script.js | 91 +++++++++++++++++++++++----------------- lib/bcoin/tx.js | 6 +-- 5 files changed, 76 insertions(+), 46 deletions(-) diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 11faeb0c..671e1062 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1829,9 +1829,16 @@ Chain.prototype.isInitial = function isInitial() { */ Chain.prototype.getProgress = function getProgress() { + var start, current, end; + if (!this.tip) return 0; - return Math.min(1, this.tip.ts / (utils.now() - 40 * 60)); + + start = network.genesis.ts; + current = this.tip.ts - start; + end = utils.now() - start - 40 * 60; + + return Math.min(1, current / end); }; /** diff --git a/lib/bcoin/http/server.js b/lib/bcoin/http/server.js index b4578070..ad9b0d13 100644 --- a/lib/bcoin/http/server.js +++ b/lib/bcoin/http/server.js @@ -66,8 +66,11 @@ HTTPServer.prototype._init = function _init() { return res.end(); } + res.setHeader('X-Bcoin-Version', constants.USER_VERSION); + res.setHeader('X-Bcoin-Agent', constants.USER_AGENT); res.setHeader('X-Bcoin-Network', network.type); - res.setHeader('X-Bcoin-Version', constants.USER_AGENT); + res.setHeader('X-Bcoin-Height', self.node.chain.height + ''); + res.setHeader('X-Bcoin-Tip', utils.revHex(self.node.chain.tip.hash)); next(); }); @@ -182,8 +185,13 @@ HTTPServer.prototype._init = function _init() { this.get('/', function(req, res, next, send) { send(200, { - version: constants.USER_AGENT, - network: network.type + version: constants.USER_VERSION, + agent: constants.USER_AGENT, + network: network.type, + height: self.node.chain.height, + tip: utils.revHex(self.node.chain.tip.hash), + peers: self.node.pool.peers.all.length, + progress: self.node.chain.getProgress() }); }); diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index 1d5fe877..f2df1ba8 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -413,7 +413,7 @@ MinerBlock.prototype.updateCommitment = function updateCommitment() { */ MinerBlock.prototype.updateCoinbase = function updateCoinbase() { - this.coinbase.inputs[0].script[1] = this.extraNonce.toBuffer(); + this.coinbase.inputs[0].script[1] = bcoin.script.array(this.extraNonce); this.coinbase.outputs[0].value = this.block.getReward(); }; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 07f804c2..04ca3b0e 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -941,8 +941,8 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version var op, val, v1, v2, v3; var n, n1, n2, n3; var res, key, sig, type, subscript, hash; - var keys, i, j, m; - var succ, locktime; + var keys, i, j, m, ikey, isig; + var locktime; if (flags == null) flags = constants.flags.STANDARD_VERIFY_FLAGS; @@ -1399,6 +1399,10 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version key = stack.pop(); sig = stack.pop(); + subscript = this.getSubscript(lastSep); + if (version === 0) + subscript.removeData(sig); + if (!Script.isValidKey(key, flags)) throw new ScriptError('Key is not valid.', op, ip); @@ -1407,10 +1411,6 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version type = sig[sig.length - 1]; - subscript = this.getSubscript(lastSep); - if (version === 0) - subscript.removeData(sig); - hash = tx.signatureHash(index, subscript, type, version); res = Script.checksig(hash, sig, key, flags); @@ -1428,73 +1428,85 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version if (!tx) throw new ScriptError('No TX passed in.', op, ip); - if (stack.length < 4) + i = 1; + if (stack.length < i) throw new ScriptError('Stack too small.', op, ip); - n = Script.num(stack.pop(), flags).toNumber(); + n = Script.num(stack.top(-i), flags).toNumber(); - if (!(n >= 1 && n <= constants.script.MAX_MULTISIG_PUBKEYS)) + if (!(n >= 0 && n <= constants.script.MAX_MULTISIG_PUBKEYS)) throw new ScriptError('`n` is out of bounds.', op, ip); - if (stack.length < n + 1) + opCount += n; + + if (opCount > constants.script.MAX_OPS) + throw new ScriptError('Too many ops.', op, ip); + + i++; + ikey = i; + i += n; + + if (stack.length < i) throw new ScriptError('`n` exceeds stack size.', op, ip); - keys = []; - for (i = 0; i < n; i++) { - key = stack.pop(); + m = Script.num(stack.top(-i), flags).toNumber(); - if (!Script.isValidKey(key, flags)) - throw new ScriptError('Key is not valid.', op, ip); - - keys.push(key); - } - - m = Script.num(stack.pop(), flags).toNumber(); - - if (!(m >= 1 && m <= n)) + if (!(m >= 0 && m <= n)) throw new ScriptError('`m` is out of bounds.', op, ip); - if (stack.length < m) + i++; + isig = i; + i += m; + + if (stack.length < i) throw new ScriptError('`m` exceeds stack size.', op, ip); subscript = this.getSubscript(lastSep); - for (i = 0; i < m; i++) { - sig = stack.get(stack.length - 1 - i); + for (j = 0; j < m; j++) { + sig = stack.top(-isig - j); if (version === 0) subscript.removeData(sig); } - succ = 0; - for (i = 0, j = 0; i < m; i++) { - sig = stack.pop(); + res = true; + while (res && m > 0) { + sig = stack.top(-isig); + key = stack.top(-ikey); if (!Script.isValidSignature(sig, flags)) throw new ScriptError('Signature is not valid.', op, ip); - type = sig[sig.length - 1]; + if (!Script.isValidKey(key, flags)) + throw new ScriptError('Key is not valid.', op, ip); + type = sig[sig.length - 1]; hash = tx.signatureHash(index, subscript, type, version); - res = false; - for (; !res && j < n; j++) - res = Script.checksig(hash, sig, keys[j], flags); + if (Script.checksig(hash, sig, key, flags)) { + isig++; + m--; + } - if (res) - succ++; + ikey++; + n--; + + if (m > n) + res = false; } + while (i-- > 1) + stack.pop(); + if (stack.length < 1) throw new ScriptError('No dummy present.', op, ip); - val = stack.pop(); - if (flags & constants.flags.VERIFY_NULLDUMMY) { - if (!Script.isDummy(val)) + if (!Script.isDummy(stack.top(-1))) throw new ScriptError('Dummy did not verify.', op, ip); } - res = succ >= m; + stack.pop(); if (op === opcodes.OP_CHECKMULTISIGVERIFY) { if (!res) @@ -2427,6 +2439,9 @@ Script.prototype.isMultisig = function isMultisig() { if (n == null) return false; + if (n < 1) + return false; + m = Script.getSmall(this.code[0]); if (m == null) diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 5ff4751a..7894d831 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -375,8 +375,8 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) { for (i = 0; i < this.inputs.length; i++) { copy.inputs.push({ prevout: this.inputs[i].prevout, - script: this.inputs[i].script.clone(), - witness: this.inputs[i].witness.clone(), + script: this.inputs[i].script, + witness: this.inputs[i].witness, sequence: this.inputs[i].sequence }); } @@ -384,7 +384,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) { for (i = 0; i < this.outputs.length; i++) { copy.outputs.push({ value: this.outputs[i].value, - script: this.outputs[i].script.clone() + script: this.outputs[i].script }); }