diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 300eebf9..9e6886a5 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -130,7 +130,30 @@ script.verify = function verify(hash, sig, pub) { } }; +script._next = function(to, s, pc) { + var depth = 0; + while (s[pc]) { + var o = s[pc]; + if (o === 'if_' || o === 'notif') + depth++; + else if (o === 'else') + depth--; + else if (o === 'endif') + depth--; + if (depth < 0) + break; + if (depth === 0 && o === to) + return pc; + if (o === 'else') + depth++; + pc++; + } + return -1; +}; + script.execute = function execute(s, stack, tx, index) { + s = s.slice(); + if (s.length > 10000) return false; @@ -153,6 +176,47 @@ script.execute = function execute(s, stack, tx, index) { } switch (o) { + case 'if_': + case 'notif': { + var val = false; + if (stack.length < 1) + return false; + var v = stack.pop(); + val = new bn(v).cmp(0) !== 0; + if (o === 'notif') + val = !val; + var if_ = pc; + var else_ = script._next('else_', s, pc); + var endif = script._next('endif', s, pc); + // Splice out the statement blocks we don't need + if (val) { + if (endif === -1) + return false; + if (else_ === -1) { + s.splice(endif, 1); + s.splice(if_, 1); + } else { + s.splice(else_, (endif - else_) + 1); + s.splice(if_, 1); + } + } else { + if (endif === -1) + return false; + if (else_ === -1) + s.splice(if_, (endif - if_) + 1); + else + s.splice(if_, (else_ - if_) + 1); + } + // Subtract one since we removed the if/notif opcode + pc--; + break; + } + case 'else_': { + return false; + } + case 'endif': { + return false; + } case 'dup': { if (stack.length === 0) return false;