Beispiel #1
0
    def test_binary_const_pushes(self):
        for length in xrange(1, 76):
            opcode = Opcode(length)
            string = 'a' * length

            s = Script.from_bytes(chr(length) + string)

            assert s.instructions == [Instruction(opcode, string)]
Beispiel #2
0
    def from_buffer(buffer):
        # Inverse operation of Output.to_bytes(), check that out.
        amount = decode_int(buffer.read(8), big_endian = False)

        script_len = buffer.read_varint()
        script = Script.from_bytes(buffer.read(script_len))

        return Output.create(amount, script)
Beispiel #3
0
    def from_buffer(buffer):
        # Inverse operation of Output.to_bytes(), check that out.
        amount = decode_int(buffer.read(8), big_endian=False)

        script_len = buffer.read_varint()
        script = Script.from_bytes(buffer.read(script_len))

        return Output.create(amount, script)
Beispiel #4
0
    def test_binary_all_nonpush_opcodes(self):
        opcodes = []
        for name, value in inspect.getmembers(opcode):
            if isinstance(value, Opcode) and not value.is_push():
                opcodes.append(value)

        bytes = ''.join(chr(opcode.number) for opcode in opcodes)

        s = Script.from_bytes(bytes)
        assert s.instructions == map(Instruction, opcodes)
Beispiel #5
0
    def from_buffer(cls, buffer):
        # Inverse operation of Input.to_bytes(), check that out.
        tx_id     = encode_hex(buffer.read(32)[::-1]) # reversed
        txo_index = decode_int(buffer.read(4), big_endian = False)

        script_len = buffer.read_varint()
        script     = Script.from_bytes(buffer.read(script_len))

        seq_number = decode_int(buffer.read(4), big_endian = False)

        return cls(tx_id, txo_index, script, seq_number)
Beispiel #6
0
    def test_binary_var_pushes(self):
        s1 = Script.from_bytes(chr(OP_PUSHDATA1.number) + '\3' + 'abc')
        assert s1.instructions == [Instruction(OP_PUSHDATA1, 'abc')]

        s2 = Script.from_bytes(chr(OP_PUSHDATA2.number) + '\3\0' + 'abc')
        assert s2.instructions == [Instruction(OP_PUSHDATA2, 'abc')]

        s2 = Script.from_bytes(chr(OP_PUSHDATA4.number) + '\3\0\0\0' + 'abc')
        assert s2.instructions == [Instruction(OP_PUSHDATA4, 'abc')]

        with raises(Buffer.InsufficientData):
            Script.from_bytes(chr(OP_PUSHDATA1.number) + '\3' + 'a')

        with raises(Buffer.InsufficientData):
            Script.from_bytes(chr(OP_PUSHDATA2.number) + '\3\0' + 'a')

        with raises(Buffer.InsufficientData):
            Script.from_bytes(chr(OP_PUSHDATA4.number) + '\3\0\0\0' + 'a')
Beispiel #7
0
    def create(cls, amount, script):
        script = Script.create(script.instructions) # classified copy

        if isinstance(script, PayToPubkeyOut):
            return AddressOutput(amount, script)

        elif isinstance(script, PayToScriptOut):
            return ScriptOutput(amount, script)

        elif isinstance(script, OpReturnOut):
            return DataOutput(amount, script)

        else:
            return Output(amount, script)
Beispiel #8
0
    def create(cls, amount, script):
        script = Script.create(script.instructions)  # classified copy

        if isinstance(script, PayToPubkeyOut):
            return AddressOutput(amount, script)

        elif isinstance(script, PayToScriptOut):
            return ScriptOutput(amount, script)

        elif isinstance(script, OpReturnOut):
            return DataOutput(amount, script)

        else:
            return Output(amount, script)
Beispiel #9
0
    def create(cls, tx_id, txo_index, script, seq_number = FINAL_SEQ_NUMBER):
        script = Script.create(script.instructions) # classified copy
        args = (tx_id, txo_index, script, seq_number)

        if isinstance(script, PayToPubkeyIn):
            return AddressInput(*args)

        elif isinstance(script, PayToScriptIn):
            return ScriptInput(*args)

        elif isinstance(script, OpReturnOut):
            return DataOutput(*args)

        else:
            return Output(amount, script)
Beispiel #10
0
    def verify(self, script_sig, script_pubkey, tx = None, nin = 0, flags = 0):
        """
        Verifies a Script by executing it and returns true if it is valid.
        This function needs to be provided with the scriptSig and the scriptPubkey
        separately.

        :param script_sig: the script's first part (corresponding to the tx input)
        :param script_pubkey: the script's last part (corresponding to the tx output)
        :param tx: the transaction containing the script_sig in one input (used to
            check signature validity for some opcodes like OP_CHECKSIG)
        :param nin: index of the transaction input containing the scriptSig verified.
        :param flags: evaluation flags. See Interpreter.SCRIPT_* constants

        Translated from bitcoind's VerifyScript
        """
        self.initialize()
        self.script = script_sig
        self.tx = tx or Transaction([ Input('', 0, Script()) ], [ Output(0, Script()) ])
        self.nin = nin
        self.flags = flags

        if flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY and not script_sig.is_push_only():
            self.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
            return False

        # Evaluate script_sig
        if not self.evaluate():
            return False

        if self.flags & Interpreter.SCRIPT_VERIFY_P2SH:
            stack_copy = list(self.stack)

        stack = self.stack
        self.initialize()
        self.script = script_pubkey
        self.stack = stack
        self.tx = tx or Transaction([ Input('', 0, Script()) ], [ Output(0, Script()) ])
        self.nin = nin or 0
        self.flags = flags or 0

        # evaluate script_pubkey
        if not self.evaluate():
            return False

        if len(self.stack) == 0:
            self.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_RESULT'
            return False

        bytes = self.stack[-1]
        if not Interpreter.cast_to_bool(bytes):
            self.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK'
            return False

        # Additional validation for spend-to-script-hash transactions:
        if (self.flags & Interpreter.SCRIPT_VERIFY_P2SH) and script_sig.is_script_hash_out():
            # script_sig must be literals-only or validation fails
            if not script_sig.is_push_only():
                self.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
                return False

            # stack_copy cannot be empty here, because if it was the
            # P2SH  HASH <> EQUAL  script_pubkey would be evaluated with
            # an empty stack and the EvalScript above would return false.
            if len(stack_copy) == 0:
                raise Exception('internal error - stack copy empty')

            redeem_bytes = stack_copy[-1]
            redeem_script = Script.from_bytes(redeem_bytes)
            stack_copy = stack_copy[:-1]

            self.initialize()
            self.script = redeem_script
            self.stack = stack_copy
            self.tx = tx or Transaction([ Input('', 0, Script()) ], [ Output(0, Script()) ])
            self.nin = nin or 0
            self.flags = flags or 0

            # Evaluate redeem_script
            if not self.evaluate():
                return False

            if len(stack_copy) == 0:
                self.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_P2SH_STACK'
                return False

            if not Interpreter.cast_to_bool(stack_copy[-1]):
                self.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK'
                return False

        return True
Beispiel #11
0
    def test_verify_trivial_scripts(self):
        interpreter = Interpreter()

        verified = interpreter.verify(Script.compile([OP_1]),
                                      Script.compile([OP_1]))
        assert verified is True

        verified = interpreter.verify(Script.compile([OP_1]),
                                      Script.compile([OP_0]))
        assert verified is False

        verified = interpreter.verify(Script.compile([OP_0]),
                                      Script.compile([OP_1]))
        assert verified is True

        verified = interpreter.verify(Script.compile([OP_CODESEPARATOR]),
                                      Script.compile([OP_1]))
        assert verified is True

        verified = interpreter.verify(
            Script(), Script.compile([OP_DEPTH, OP_0, OP_EQUAL]))
        assert verified is True

        # verified = interpreter.verify(Script.from_string('9 0x000000000000000010'), Script())
        # assert verified is True

        verified = interpreter.verify(
            Script.compile([OP_1]),
            Script.compile([OP_15, OP_ADD, OP_16, OP_EQUAL]))
        assert verified is True

        verified = interpreter.verify(
            Script.compile([OP_0]),
            Script.compile([OP_IF, OP_VERIFY, OP_ELSE, OP_1, OP_ENDIF]))
        assert verified is True
Beispiel #12
0
    def step(self):
        """
        Based on the inner loop of bitcoind's EvalScript function
        bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
        """
        f_required_minimal = self.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA

        f_exec = False not in self.vf_exec
        instruction = self.script.instructions[self.pc]
        self.pc += 1

        if instruction.data and len(
                instruction.data) > Interpreter.MAX_SCRIPT_ELEMENT_SIZE:
            self.errstr = 'SCRIPT_ERR_PUSH_SIZE'
            return False

        # Note how Opcode.OP_RESERVED does not count towards the opcode limit.
        if instruction.opcode > OP_16:
            self.nop_count += 1  # TODO: use itertools.count
            if self.nop_count > 201:
                self.errstr = 'SCRIPT_ERR_OP_COUNT'
                return False

        if (instruction.opcode == OP_CAT or instruction.opcode == OP_SUBSTR
                or instruction.opcode == OP_LEFT
                or instruction.opcode == OP_RIGHT
                or instruction.opcode == OP_INVERT
                or instruction.opcode == OP_AND or instruction.opcode == OP_OR
                or instruction.opcode == OP_XOR
                or instruction.opcode == OP_2MUL
                or instruction.opcode == OP_2DIV
                or instruction.opcode == OP_MUL or instruction.opcode == OP_DIV
                or instruction.opcode == OP_MOD
                or instruction.opcode == OP_LSHIFT
                or instruction.opcode == OP_RSHIFT):

            self.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
            return False

        if f_exec and instruction.opcode <= OP_PUSHDATA4:
            if f_required_minimal and not instruction.is_minimal_push():
                self.errstr = 'SCRIPT_ERR_MINIMALDATA'
                return False

            if not instruction.data:
                self.stack += [Interpreter.false]
            else:
                self.stack += [instruction.data]

        elif f_exec or OP_IF <= instruction.opcode <= OP_ENDIF:
            if instruction.opcode in [
                    OP_1NEGATE, OP_1, OP_2, OP_3, OP_4, OP_5, OP_6, OP_7, OP_8,
                    OP_9, OP_10, OP_11, OP_12, OP_13, OP_14, OP_15, OP_16
            ]:
                number = instruction.opcode.number - (OP_1.number - 1)
                bytes = encode_script_number(number)
                self.stack += [bytes]
                # The result of these opcodes should always be the minimal way to
                # push data, so no need to Check MinimalPush here.

            elif instruction.opcode == OP_NOP:
                pass

            elif instruction.opcode == OP_CHECKLOCKTIMEVERIFY:
                if self.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY:
                    if self.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS:
                        self.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
                        return False

                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                # Note that elsewhere numeric opcodes are limited to
                # operands in the range -2**31+1 to 2**31-1, however it is
                # legal for opcodes to produce results exceeding that
                # range. This limitation is implemented by CScriptNum's
                # default 4-byte limit.
                #
                # If we kept to that limit we'd have a year 2038 problem,
                # even though the nLockTime field in transactions
                # themselves is uint32 which only becomes meaningless
                # after the year 2106.
                #
                # Thus as a special case we tell CScriptNum to accept up
                # to 5-byte bignums, which are good until 2**39-1, well
                # beyond the 2**32-1 limit of the nLockTime field itself.

                nlock_time = decode_script_number(self.stack[-1],
                                                  f_required_minimal, 5)

                # In the rare event that the argument may be < 0 due to
                # some arithmetic being done first, you can always use
                # 0 MAX CHECKLOCKTIMEVERIFY.

                if nlock_time < 0:
                    self.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME'
                    return False

                # Actually compare the specified lock time with the transaction.
                if not self.check_lock_time(nlock_time):
                    self.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME'
                    return False

            elif instruction.opcode in [
                    OP_NOP1, OP_NOP3, OP_NOP4, OP_NOP5, OP_NOP6, OP_NOP7,
                    OP_NOP8, OP_NOP9, OP_NOP10
            ]:
                if self.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS:
                    self.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
                    return False

            elif instruction.opcode in [OP_IF, OP_NOTIF]:
                # <expression> if [statements] [else  [statements]] endif
                f_value = False
                if f_exec:
                    if len(self.stack) < 1:
                        self.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
                        return False

                    bytes = self.stack.pop()
                    f_value = Interpreter.cast_to_bool(bytes)

                    if instruction.opcode == OP_NOTIF:
                        f_value = not f_value

                self.vf_exec += [f_value]

            elif instruction.opcode == OP_ELSE:
                if len(self.vf_exec) == 0:
                    self.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
                    return False

                self.vf_exec[-1] = not self.vf_exec[-1]

            elif instruction.opcode == OP_ENDIF:
                if len(self.vf_exec) == 0:
                    self.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
                    return False

                self.vf_exec.pop()

            elif instruction.opcode == OP_VERIFY:
                # (true -- ) or
                # (false -- false) and return
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                f_value = Interpreter.cast_to_bool(bytes)
                if f_value:
                    self.stack.pop()
                else:
                    self.errstr = 'SCRIPT_ERR_VERIFY'
                    return False

            elif instruction.opcode == OP_RETURN:
                self.errstr = 'SCRIPT_ERR_OP_RETURN'
                return False

            elif instruction.opcode == OP_TOALTSTACK:
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.altstack += self.stack[-1:]
                self.stack = self.stack[:-1]

            elif instruction.opcode == OP_FROMALTSTACK:
                if len(self.altstack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION'
                    return False

                self.stack += self.altstack[-1:]
                self.altstack = self.altstack[:-1]

            elif instruction.opcode == OP_2DROP:
                # (x1, x2 -- )
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack = self.stack[:-2]

            elif instruction.opcode == OP_2DUP:
                # (x1, x2 -- x1 x2 x1 x2)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack += [x1, x2]

            elif instruction.opcode == OP_3DUP:
                # (x1, x2, x3 -- x1 x2 x3 x1 x2 x3)
                if len(self.stack) < 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3 = self.stack[-3:]
                self.stack += [x1, x2, x3]

            elif instruction.opcode == OP_2OVER:
                # (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
                if len(self.stack) < 4:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3, x4 = self.stack[-4:]
                self.stack += [x1, x2]

            elif instruction.opcode == OP_2ROT:
                # (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
                if len(self.stack) < 6:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3, x4, x5, x6 = self.stack[-6:]
                self.stack = self.stack[:-6] + [x3, x4, x5, x6, x1, x2]

            elif instruction.opcode == OP_2SWAP:
                # (x1 x2 x3 x4 -- x3 x4 x1 x2)
                if len(self.stack) < 4:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3, x4 = self.stack[-4:]
                self.stack = self.stack[:-4] + [x3, x4, x1, x2]

            elif instruction.opcode == OP_IFDUP:
                # (x - 0 | x x)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                f_value = Interpreter.cast_to_bool(bytes)
                if f_value:
                    self.stack += [bytes]

            elif instruction.opcode == OP_DEPTH:
                bytes = encode_script_number(len(self.stack))
                self.stack += [bytes]

            elif instruction.opcode == OP_DROP:
                # ( x -- )
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack.pop()
                self.stack = self.stack[:-1]

            elif instruction.opcode == OP_DUP:
                # ( x -- x x )
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack += self.stack[-1:]

            elif instruction.opcode == OP_NIP:
                # (x1 x2 -- x2)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack = self.stack[:-2] + [x2]

            elif instruction.opcode == OP_OVER:
                # (x1 x2 -- x1 x2 x1)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack += [self.stack[-2]]

            elif instruction.opcode in [OP_PICK, OP_ROLL]:
                # (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
                # (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack.pop()
                n = decode_script_number(bytes, f_required_minimal)
                if n < 0 or n >= len(self.stack):
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-n - 1]
                if instruction.opcode == OP_ROLL:
                    self.stack.pop(-n - 1)

                self.stack += [bytes]

            elif instruction.opcode == OP_ROT:
                # (x1 x2 x3 -- x2 x3 x1)
                # x2 x1 x3  after first swap
                # x2 x3 x1  after second swap
                if len(self.stack) < 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3 = self.stack[-3:]
                self.stack = self.stack[:-3] + [x2, x3, x1]

            elif instruction.opcode == OP_SWAP:
                # (x1 x2 -- x2 x1)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack = self.stack[:-2] + [x2, x1]

            elif instruction.opcode == OP_TUCK:
                # (x1 x2 -- x2 x1 x2)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack = self.stack[:-2] + [x2, x1, x2]

            elif instruction.opcode == OP_SIZE:
                # (in -- in size)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                size = len(self.stack[-1])
                self.stack += [encode_script_number(size)]

            elif instruction.opcode in [OP_EQUAL, OP_EQUALVERIFY]:
                # case Opcode.OP_NOTEQUAL # use Opcode.OP_NUMNOTEQUAL
                # (x1 x2 - bool)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                f_equal = x1 == x2
                self.stack = self.stack[:-2] + [
                    Interpreter.bool_bytes[f_equal]
                ]

                if instruction.opcode == OP_EQUALVERIFY:
                    if f_equal:
                        self.stack.pop()
                    else:
                        self.errstr = 'SCRIPT_ERR_EQUALVERIFY'
                        return False

            elif instruction.opcode in [
                    OP_1ADD, OP_1SUB, OP_NEGATE, OP_ABS, OP_NOT, OP_0NOTEQUAL
            ]:
                # (in -- out)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                number = decode_script_number(bytes, f_required_minimal)

                if instruction.opcode == OP_1ADD:
                    number += 1

                elif instruction.opcode == OP_1SUB:
                    number -= 1

                elif instruction.opcode == OP_NEGATE:
                    number = -number

                elif instruction.opcode == OP_ABS:
                    number = abs(-1)

                elif instruction.opcode == OP_NOT:
                    number = int(number == 0)

                elif instruction.opcode == OP_0NOTEQUAL:
                    number = int(number != 0)

                self.stack = self.stack[:-1] + [encode_script_number(number)]

            elif instruction.opcode in [
                    OP_ADD, OP_SUB, OP_BOOLAND, OP_BOOLOR, OP_NUMEQUAL,
                    OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL, OP_LESSTHAN,
                    OP_GREATERTHAN, OP_LESSTHANOREQUAL, OP_GREATERTHANOREQUAL,
                    OP_MIN, OP_MAX
            ]:

                # (in -- out)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                number1 = decode_script_number(self.stack[-2],
                                               f_required_minimal)
                number2 = decode_script_number(self.stack[-1],
                                               f_required_minimal)

                if instruction.opcode == OP_ADD:
                    result = number1 + number2

                elif instruction.opcode == OP_SUB:
                    result = number1 - number2

                elif instruction.opcode == OP_BOOLAND:
                    result = all([number1, number2])

                elif instruction.opcode == OP_BOOLOR:
                    result = any([number1, number2])

                elif instruction.opcode in [OP_NUMEQUAL, OP_NUMEQUALVERIFY]:
                    result = int(number1 == number2)

                elif instruction.opcode == OP_NUMNOTEQUAL:
                    result = int(number1 != number2)

                elif instruction.opcode == OP_LESSTHAN:
                    result = number1 < number2

                elif instruction.opcode == OP_GREATERTHAN:
                    result = number1 > number2

                elif instruction.opcode == OP_LESSTHANOREQUAL:
                    result = number1 <= number2

                elif instruction.opcode == OP_GREATERTHANOREQUAL:
                    result = number1 >= number2

                elif instruction.opcode == OP_MIN:
                    result = min(number1, number2)

                elif instruction.opcode == OP_MAX:
                    result = max(number1, number2)

                self.stack = self.stack[:-2] + [encode_script_number(result)]

                if instruction.opcode == OP_NUMEQUALVERIFY:
                    if Interpreter.cast_to_bool(self.stack[-1]):
                        self.stack = self.stack[:-1]
                    else:
                        self.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY'
                        return False

            elif instruction.opcode == OP_WITHIN:
                # (x min max -- out)
                if len(self.stack) < 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                number1, number2, number3 = map(decode_script_number,
                                                self.stack[-3:])
                f_value = number2 <= number1 < number3

                self.stack = self.stack[:-3] + [
                    Interpreter.bool_bytes[f_value]
                ]

            elif instruction.opcode in [
                    OP_RIPEMD160, OP_SHA1, OP_SHA256, OP_HASH160, OP_HASH256
            ]:
                # (x min max -- out)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                if instruction.opcode == OP_RIPEMD160:
                    result = ripemd160(bytes)
                elif instruction.opcode == OP_SHA1:
                    result = sha1(bytes)
                elif instruction.opcode == OP_SHA256:
                    result = sha256(bytes)
                elif instruction.opcode == OP_HASH160:
                    result = hash160(bytes)
                elif instruction.opcode == OP_HASH256:
                    result = sha256(sha256(bytes))

                self.stack = self.stack[:-1] + [result]

            elif instruction.opcode == OP_CODESEPARATOR:
                # hash starts after the code separator
                self.pbegincodehash = self.pc

            elif instruction.opcode in [OP_CHECKSIG, OP_CHECKSIGVERIFY]:
                # (sig pubkey -- bool)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                sig_bytes, pubkey_bytes = self.stack[-2:]

                # Subset of script starting at the most recent codeseparator
                # CScript scriptCode(pbegincodehash, pend);
                from_instruction = self.pbegincodehash
                subscript = Script(self.script.instructions[from_instruction:])

                # Drop the signature, since there's no way for a signature to sign itself
                subscript.remove_opcode_by_data(sig_bytes)

                if not self.check_signature_encoding(
                        sig_bytes) or not self.check_pubkey_encoding(
                            pubkey_bytes):
                    return False

                try:
                    signature = Signature.from_tx_format(sig_bytes)
                    pubkey = PublicKey.from_bytes(pubkey_bytes)
                    f_success = self.tx.verify_signature(
                        signature, pubkey, self.nin, subscript)
                except BitforgeError:
                    f_success = False

                self.stack = self.stack[:-2] + [
                    Interpreter.bool_bytes[f_success]
                ]
                if instruction.opcode == OP_CHECKSIGVERIFY:
                    if f_success:
                        self.stack = self.stack[:-1]
                    else:
                        self.errstr = 'SCRIPT_ERR_CHECKSIGVERIFY'
                        return False

            elif instruction.opcode in [
                    OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
            ]:
                # ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                ikey = 2
                keys_count = decode_script_number(self.stack[-1],
                                                  f_required_minimal)
                if not (0 <= keys_count <= 20):
                    self.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
                    return False

                self.nop_count += keys_count
                if self.nop_count > 201:
                    self.errstr = 'SCRIPT_ERR_OP_COUNT'
                    return False

                if len(self.stack) < keys_count + 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                isig = keys_count + 3
                sigs_count = decode_script_number(self.stack[-keys_count - 2],
                                                  f_required_minimal)
                if not (0 <= sigs_count <= keys_count):
                    self.errstr = 'SCRIPT_ERR_SIG_COUNT'
                    return False

                if len(self.stack) < keys_count + sigs_count + 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                # Subset of script starting at the most recent codeseparator
                from_instruction = self.pbegincodehash
                subscript = Script(self.script.instructions[from_instruction:])

                for i in range(sigs_count):
                    sig_bytes = self.stack[-isig - i]
                    subscript.remove_opcode_by_data(sig_bytes)

                total_elements = sigs_count + keys_count + 2
                f_success = True
                while f_success and sigs_count > 0:
                    sig_bytes = self.stack[-isig]
                    pubkey_bytes = self.stack[-ikey]

                    if not self.check_signature_encoding(
                            sig_bytes) or not self.check_pubkey_encoding(
                                pubkey_bytes):
                        return False

                    try:
                        signature = Signature.from_tx_format(sig_bytes)
                        pubkey = PublicKey.from_bytes(pubkey_bytes, False)
                        f_ok = self.tx.verify_signature(
                            signature, pubkey, self.nin, subscript)
                    except BitforgeError:
                        f_ok = False

                    if f_ok:
                        isig += 1
                        sigs_count -= 1

                    ikey += 1
                    keys_count -= 1

                    # If there are more signature left than keys left,
                    # then too many signatures have failed
                    if sigs_count > keys_count:
                        f_success = False

                # Clean up stack of actual arguments
                self.stack = self.stack[:-total_elements]

                # A bug causes CHECKMULTISIG to consume one extra argument
                # whose contents were not checked in any way.
                #
                # Unfortunately this is a potential source of mutability,
                # so optionally verify it is exactly equal to zero prior
                # to removing it from the stack.
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                if (self.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY) and len(
                        self.stack[-1]):
                    self.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY'
                    return False

                self.stack = self.stack[:-1] + [
                    Interpreter.bool_bytes[f_success]
                ]

                if instruction.opcode == OP_CHECKMULTISIGVERIFY:
                    if f_success:
                        self.stack = self.stack[:-1]
                    else:
                        self.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY'
                        return False

            # Default
            else:
                self.errstr = 'SCRIPT_ERR_BAD_OPCODE'
                return False

        return True
Beispiel #13
0
 def test_binary_single(self):
     s = Script.from_bytes('\0')
     assert s.instructions == [Instruction(OP_0)]
Beispiel #14
0
    def test_verify_trivial_scripts(self):
        interpreter = Interpreter()

        verified = interpreter.verify(Script.compile([OP_1]), Script.compile([OP_1]))
        assert verified is True

        verified = interpreter.verify(Script.compile([OP_1]), Script.compile([OP_0]))
        assert verified is False

        verified = interpreter.verify(Script.compile([OP_0]), Script.compile([OP_1]))
        assert verified is True

        verified = interpreter.verify(Script.compile([OP_CODESEPARATOR]), Script.compile([OP_1]))
        assert verified is True

        verified = interpreter.verify(Script(), Script.compile([OP_DEPTH, OP_0, OP_EQUAL]))
        assert verified is True

        # verified = interpreter.verify(Script.from_string('9 0x000000000000000010'), Script())
        # assert verified is True

        verified = interpreter.verify(Script.compile([OP_1]), Script.compile([OP_15, OP_ADD, OP_16, OP_EQUAL]))
        assert verified is True

        verified = interpreter.verify(Script.compile([OP_0]), Script.compile([OP_IF, OP_VERIFY, OP_ELSE, OP_1, OP_ENDIF]))
        assert verified is True
Beispiel #15
0
 def remove_script(self):
     return self.replace_script(Script())
Beispiel #16
0
    def verify(self, script_sig, script_pubkey, tx=None, nin=0, flags=0):
        """
        Verifies a Script by executing it and returns true if it is valid.
        This function needs to be provided with the scriptSig and the scriptPubkey
        separately.

        :param script_sig: the script's first part (corresponding to the tx input)
        :param script_pubkey: the script's last part (corresponding to the tx output)
        :param tx: the transaction containing the script_sig in one input (used to
            check signature validity for some opcodes like OP_CHECKSIG)
        :param nin: index of the transaction input containing the scriptSig verified.
        :param flags: evaluation flags. See Interpreter.SCRIPT_* constants

        Translated from bitcoind's VerifyScript
        """
        self.initialize()
        self.script = script_sig
        self.tx = tx or Transaction([Input('', 0, Script())],
                                    [Output(0, Script())])
        self.nin = nin
        self.flags = flags

        if flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY and not script_sig.is_push_only(
        ):
            self.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
            return False

        # Evaluate script_sig
        if not self.evaluate():
            return False

        if self.flags & Interpreter.SCRIPT_VERIFY_P2SH:
            stack_copy = list(self.stack)

        stack = self.stack
        self.initialize()
        self.script = script_pubkey
        self.stack = stack
        self.tx = tx or Transaction([Input('', 0, Script())],
                                    [Output(0, Script())])
        self.nin = nin or 0
        self.flags = flags or 0

        # evaluate script_pubkey
        if not self.evaluate():
            return False

        if len(self.stack) == 0:
            self.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_RESULT'
            return False

        bytes = self.stack[-1]
        if not Interpreter.cast_to_bool(bytes):
            self.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK'
            return False

        # Additional validation for spend-to-script-hash transactions:
        if (self.flags & Interpreter.SCRIPT_VERIFY_P2SH
            ) and script_sig.is_script_hash_out():
            # script_sig must be literals-only or validation fails
            if not script_sig.is_push_only():
                self.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
                return False

            # stack_copy cannot be empty here, because if it was the
            # P2SH  HASH <> EQUAL  script_pubkey would be evaluated with
            # an empty stack and the EvalScript above would return false.
            if len(stack_copy) == 0:
                raise Exception('internal error - stack copy empty')

            redeem_bytes = stack_copy[-1]
            redeem_script = Script.from_bytes(redeem_bytes)
            stack_copy = stack_copy[:-1]

            self.initialize()
            self.script = redeem_script
            self.stack = stack_copy
            self.tx = tx or Transaction([Input('', 0, Script())],
                                        [Output(0, Script())])
            self.nin = nin or 0
            self.flags = flags or 0

            # Evaluate redeem_script
            if not self.evaluate():
                return False

            if len(stack_copy) == 0:
                self.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_P2SH_STACK'
                return False

            if not Interpreter.cast_to_bool(stack_copy[-1]):
                self.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK'
                return False

        return True
Beispiel #17
0
    def step(self):
        """
        Based on the inner loop of bitcoind's EvalScript function
        bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
        """
        f_required_minimal = self.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA

        f_exec = False not in self.vf_exec
        instruction = self.script.instructions[self.pc]
        self.pc += 1

        if instruction.data and len(instruction.data) > Interpreter.MAX_SCRIPT_ELEMENT_SIZE:
            self.errstr = 'SCRIPT_ERR_PUSH_SIZE'
            return False

        # Note how Opcode.OP_RESERVED does not count towards the opcode limit.
        if instruction.opcode > OP_16:
            self.nop_count += 1  # TODO: use itertools.count
            if self.nop_count > 201:
                self.errstr = 'SCRIPT_ERR_OP_COUNT'
                return False

        if (instruction.opcode == OP_CAT or
            instruction.opcode == OP_SUBSTR or
            instruction.opcode == OP_LEFT or
            instruction.opcode == OP_RIGHT or
            instruction.opcode == OP_INVERT or
            instruction.opcode == OP_AND or
            instruction.opcode == OP_OR or
            instruction.opcode == OP_XOR or
            instruction.opcode == OP_2MUL or
            instruction.opcode == OP_2DIV or
            instruction.opcode == OP_MUL or
            instruction.opcode == OP_DIV or
            instruction.opcode == OP_MOD or
            instruction.opcode == OP_LSHIFT or
            instruction.opcode == OP_RSHIFT):

            self.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
            return False

        if f_exec and instruction.opcode <= OP_PUSHDATA4:
            if f_required_minimal and not instruction.is_minimal_push():
                self.errstr = 'SCRIPT_ERR_MINIMALDATA'
                return False

            if not instruction.data:
                self.stack += [Interpreter.false]
            else:
                self.stack += [instruction.data]

        elif f_exec or OP_IF <= instruction.opcode <= OP_ENDIF:
            if instruction.opcode in [OP_1NEGATE, OP_1, OP_2, OP_3, OP_4, OP_5, OP_6, OP_7, OP_8, OP_9, OP_10, OP_11, OP_12, OP_13, OP_14, OP_15, OP_16]:
                number = instruction.opcode.number - (OP_1.number - 1)
                bytes = encode_script_number(number)
                self.stack += [bytes]
                # The result of these opcodes should always be the minimal way to
                # push data, so no need to Check MinimalPush here.

            elif instruction.opcode == OP_NOP:
                pass

            elif instruction.opcode == OP_CHECKLOCKTIMEVERIFY:
                if self.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY:
                    if self.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS:
                        self.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
                        return False

                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                # Note that elsewhere numeric opcodes are limited to
                # operands in the range -2**31+1 to 2**31-1, however it is
                # legal for opcodes to produce results exceeding that
                # range. This limitation is implemented by CScriptNum's
                # default 4-byte limit.
                #
                # If we kept to that limit we'd have a year 2038 problem,
                # even though the nLockTime field in transactions
                # themselves is uint32 which only becomes meaningless
                # after the year 2106.
                #
                # Thus as a special case we tell CScriptNum to accept up
                # to 5-byte bignums, which are good until 2**39-1, well
                # beyond the 2**32-1 limit of the nLockTime field itself.

                nlock_time = decode_script_number(self.stack[-1], f_required_minimal, 5)

                # In the rare event that the argument may be < 0 due to
                # some arithmetic being done first, you can always use
                # 0 MAX CHECKLOCKTIMEVERIFY.

                if nlock_time < 0:
                    self.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME'
                    return False

                # Actually compare the specified lock time with the transaction.
                if not self.check_lock_time(nlock_time):
                    self.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME'
                    return False

            elif instruction.opcode in [OP_NOP1, OP_NOP3, OP_NOP4, OP_NOP5, OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10]:
                if self.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS:
                    self.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
                    return False

            elif instruction.opcode in [OP_IF, OP_NOTIF]:
                # <expression> if [statements] [else  [statements]] endif
                f_value = False
                if f_exec:
                    if len(self.stack) < 1:
                        self.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
                        return False

                    bytes = self.stack.pop()
                    f_value = Interpreter.cast_to_bool(bytes)

                    if instruction.opcode == OP_NOTIF:
                        f_value = not f_value

                self.vf_exec += [f_value]

            elif instruction.opcode == OP_ELSE:
                if len(self.vf_exec) == 0:
                    self.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
                    return False

                self.vf_exec[-1] = not self.vf_exec[-1]

            elif instruction.opcode == OP_ENDIF:
                if len(self.vf_exec) == 0:
                    self.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
                    return False

                self.vf_exec.pop()

            elif instruction.opcode == OP_VERIFY:
                # (true -- ) or
                # (false -- false) and return
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                f_value = Interpreter.cast_to_bool(bytes)
                if f_value:
                    self.stack.pop()
                else:
                    self.errstr = 'SCRIPT_ERR_VERIFY'
                    return False

            elif instruction.opcode == OP_RETURN:
                self.errstr = 'SCRIPT_ERR_OP_RETURN'
                return False

            elif instruction.opcode == OP_TOALTSTACK:
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.altstack += self.stack[-1:]
                self.stack = self.stack[:-1]

            elif instruction.opcode == OP_FROMALTSTACK:
                if len(self.altstack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION'
                    return False

                self.stack += self.altstack[-1:]
                self.altstack = self.altstack[:-1]

            elif instruction.opcode == OP_2DROP:
                # (x1, x2 -- )
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack = self.stack[:-2]

            elif instruction.opcode == OP_2DUP:
                # (x1, x2 -- x1 x2 x1 x2)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack += [x1, x2]

            elif instruction.opcode == OP_3DUP:
                # (x1, x2, x3 -- x1 x2 x3 x1 x2 x3)
                if len(self.stack) < 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3 = self.stack[-3:]
                self.stack += [x1, x2, x3]

            elif instruction.opcode == OP_2OVER:
                # (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
                if len(self.stack) < 4:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3, x4 = self.stack[-4:]
                self.stack += [x1, x2]

            elif instruction.opcode == OP_2ROT:
                # (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
                if len(self.stack) < 6:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3, x4, x5, x6 = self.stack[-6:]
                self.stack = self.stack[:-6] + [x3, x4, x5, x6, x1, x2]

            elif instruction.opcode == OP_2SWAP:
                # (x1 x2 x3 x4 -- x3 x4 x1 x2)
                if len(self.stack) < 4:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3, x4 = self.stack[-4:]
                self.stack = self.stack[:-4] + [x3, x4, x1, x2]

            elif instruction.opcode == OP_IFDUP:
                # (x - 0 | x x)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                f_value = Interpreter.cast_to_bool(bytes)
                if f_value:
                    self.stack += [bytes]

            elif instruction.opcode == OP_DEPTH:
                bytes = encode_script_number(len(self.stack))
                self.stack += [bytes]

            elif instruction.opcode == OP_DROP:
                # ( x -- )
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack.pop()
                self.stack = self.stack[:-1]

            elif instruction.opcode == OP_DUP:
                # ( x -- x x )
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack += self.stack[-1:]

            elif instruction.opcode == OP_NIP:
                # (x1 x2 -- x2)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack = self.stack[:-2] + [x2]

            elif instruction.opcode == OP_OVER:
                # (x1 x2 -- x1 x2 x1)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                self.stack += [self.stack[-2]]

            elif instruction.opcode in [OP_PICK, OP_ROLL]:
                # (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
                # (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack.pop()
                n = decode_script_number(bytes, f_required_minimal)
                if n < 0 or n >= len(self.stack):
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-n-1]
                if instruction.opcode == OP_ROLL:
                    self.stack.pop(-n-1)

                self.stack += [bytes]

            elif instruction.opcode == OP_ROT:
                # (x1 x2 x3 -- x2 x3 x1)
                # x2 x1 x3  after first swap
                # x2 x3 x1  after second swap
                if len(self.stack) < 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2, x3 = self.stack[-3:]
                self.stack = self.stack[:-3] + [x2, x3, x1]

            elif instruction.opcode == OP_SWAP:
                # (x1 x2 -- x2 x1)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack = self.stack[:-2] + [x2, x1]

            elif instruction.opcode == OP_TUCK:
                # (x1 x2 -- x2 x1 x2)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                self.stack = self.stack[:-2] + [x2, x1, x2]

            elif instruction.opcode == OP_SIZE:
                # (in -- in size)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                size = len(self.stack[-1])
                self.stack += [encode_script_number(size)]

            elif instruction.opcode in [OP_EQUAL, OP_EQUALVERIFY]:
                # case Opcode.OP_NOTEQUAL # use Opcode.OP_NUMNOTEQUAL
                # (x1 x2 - bool)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                x1, x2 = self.stack[-2:]
                f_equal = x1 == x2
                self.stack = self.stack[:-2] + [Interpreter.bool_bytes[f_equal]]

                if instruction.opcode == OP_EQUALVERIFY:
                    if f_equal:
                        self.stack.pop()
                    else:
                        self.errstr = 'SCRIPT_ERR_EQUALVERIFY'
                        return False

            elif instruction.opcode in [OP_1ADD, OP_1SUB, OP_NEGATE, OP_ABS, OP_NOT, OP_0NOTEQUAL]:
                # (in -- out)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                number = decode_script_number(bytes, f_required_minimal)

                if instruction.opcode == OP_1ADD:
                    number += 1

                elif instruction.opcode == OP_1SUB:
                    number -= 1

                elif instruction.opcode == OP_NEGATE:
                    number = -number

                elif instruction.opcode == OP_ABS:
                    number = abs(-1)

                elif instruction.opcode == OP_NOT:
                    number = int(number == 0)

                elif instruction.opcode == OP_0NOTEQUAL:
                    number = int(number != 0)

                self.stack = self.stack[:-1] + [encode_script_number(number)]

            elif instruction.opcode in [
                OP_ADD, OP_SUB, OP_BOOLAND,
                OP_BOOLOR, OP_NUMEQUAL,
                OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL,
                OP_LESSTHAN, OP_GREATERTHAN,
                OP_LESSTHANOREQUAL,
                OP_GREATERTHANOREQUAL,
                OP_MIN, OP_MAX]:

                # (in -- out)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                number1 = decode_script_number(self.stack[-2], f_required_minimal)
                number2 = decode_script_number(self.stack[-1], f_required_minimal)

                if instruction.opcode == OP_ADD:
                    result = number1 + number2

                elif instruction.opcode == OP_SUB:
                    result = number1 - number2

                elif instruction.opcode == OP_BOOLAND:
                    result = all([number1, number2])

                elif instruction.opcode == OP_BOOLOR:
                    result = any([number1, number2])

                elif instruction.opcode in [OP_NUMEQUAL, OP_NUMEQUALVERIFY]:
                    result = int(number1 == number2)

                elif instruction.opcode == OP_NUMNOTEQUAL:
                    result = int(number1 != number2)

                elif instruction.opcode == OP_LESSTHAN:
                    result = number1 < number2

                elif instruction.opcode == OP_GREATERTHAN:
                    result = number1 > number2

                elif instruction.opcode == OP_LESSTHANOREQUAL:
                    result = number1 <= number2

                elif instruction.opcode == OP_GREATERTHANOREQUAL:
                    result = number1 >= number2

                elif instruction.opcode == OP_MIN:
                    result = min(number1, number2)

                elif instruction.opcode == OP_MAX:
                    result = max(number1, number2)

                self.stack = self.stack[:-2] + [encode_script_number(result)]

                if instruction.opcode == OP_NUMEQUALVERIFY:
                    if Interpreter.cast_to_bool(self.stack[-1]):
                        self.stack = self.stack[:-1]
                    else:
                        self.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY'
                        return False

            elif instruction.opcode == OP_WITHIN:
                # (x min max -- out)
                if len(self.stack) < 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                number1, number2, number3 = map(decode_script_number, self.stack[-3:])
                f_value = number2 <= number1 < number3

                self.stack = self.stack[:-3] + [Interpreter.bool_bytes[f_value]]

            elif instruction.opcode in [OP_RIPEMD160, OP_SHA1, OP_SHA256, OP_HASH160, OP_HASH256]:
                # (x min max -- out)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                bytes = self.stack[-1]
                if instruction.opcode == OP_RIPEMD160:
                    result = ripemd160(bytes)
                elif instruction.opcode == OP_SHA1:
                    result = sha1(bytes)
                elif instruction.opcode == OP_SHA256:
                    result = sha256(bytes)
                elif instruction.opcode == OP_HASH160:
                    result = hash160(bytes)
                elif instruction.opcode == OP_HASH256:
                    result = sha256(sha256(bytes))

                self.stack = self.stack[:-1] + [result]

            elif instruction.opcode == OP_CODESEPARATOR:
                # hash starts after the code separator
                self.pbegincodehash = self.pc

            elif instruction.opcode in [OP_CHECKSIG, OP_CHECKSIGVERIFY]:
                # (sig pubkey -- bool)
                if len(self.stack) < 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                sig_bytes, pubkey_bytes = self.stack[-2:]

                # Subset of script starting at the most recent codeseparator
                # CScript scriptCode(pbegincodehash, pend);
                from_instruction = self.pbegincodehash
                subscript = Script(self.script.instructions[from_instruction:])

                # Drop the signature, since there's no way for a signature to sign itself
                subscript.remove_opcode_by_data(sig_bytes)

                if not self.check_signature_encoding(sig_bytes) or not self.check_pubkey_encoding(pubkey_bytes):
                    return False

                try:
                    signature = Signature.from_tx_format(sig_bytes)
                    pubkey = PublicKey.from_bytes(pubkey_bytes)
                    f_success = self.tx.verify_signature(signature, pubkey, self.nin, subscript)
                except BitforgeError:
                    f_success = False

                self.stack = self.stack[:-2] + [Interpreter.bool_bytes[f_success]]
                if instruction.opcode == OP_CHECKSIGVERIFY:
                    if f_success:
                        self.stack = self.stack[:-1]
                    else:
                        self.errstr = 'SCRIPT_ERR_CHECKSIGVERIFY'
                        return False

            elif instruction.opcode in [OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY]:
                # ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                ikey = 2
                keys_count = decode_script_number(self.stack[-1], f_required_minimal)
                if not (0 <= keys_count <= 20):
                    self.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
                    return False

                self.nop_count += keys_count
                if self.nop_count > 201:
                    self.errstr = 'SCRIPT_ERR_OP_COUNT'
                    return False

                if len(self.stack) < keys_count + 2:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                isig = keys_count + 3
                sigs_count = decode_script_number(self.stack[-keys_count-2], f_required_minimal)
                if not (0 <= sigs_count <= keys_count):
                    self.errstr = 'SCRIPT_ERR_SIG_COUNT'
                    return False

                if len(self.stack) < keys_count + sigs_count + 3:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                # Subset of script starting at the most recent codeseparator
                from_instruction = self.pbegincodehash
                subscript = Script(self.script.instructions[from_instruction:])

                for i in range(sigs_count):
                    sig_bytes = self.stack[-isig-i]
                    subscript.remove_opcode_by_data(sig_bytes)

                total_elements = sigs_count + keys_count + 2
                f_success = True
                while f_success and sigs_count > 0:
                    sig_bytes = self.stack[-isig]
                    pubkey_bytes = self.stack[-ikey]

                    if not self.check_signature_encoding(sig_bytes) or not self.check_pubkey_encoding(pubkey_bytes):
                        return False

                    try:
                        signature = Signature.from_tx_format(sig_bytes)
                        pubkey = PublicKey.from_bytes(pubkey_bytes, False)
                        f_ok = self.tx.verify_signature(signature, pubkey, self.nin, subscript)
                    except BitforgeError:
                        f_ok = False

                    if f_ok:
                        isig += 1
                        sigs_count -= 1

                    ikey += 1
                    keys_count -= 1

                    # If there are more signature left than keys left,
                    # then too many signatures have failed
                    if sigs_count > keys_count:
                        f_success = False

                # Clean up stack of actual arguments
                self.stack = self.stack[:-total_elements]

                # A bug causes CHECKMULTISIG to consume one extra argument
                # whose contents were not checked in any way.
                #
                # Unfortunately this is a potential source of mutability,
                # so optionally verify it is exactly equal to zero prior
                # to removing it from the stack.
                if len(self.stack) < 1:
                    self.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
                    return False

                if (self.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY) and len(self.stack[-1]):
                    self.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY'
                    return False

                self.stack = self.stack[:-1] + [Interpreter.bool_bytes[f_success]]

                if instruction.opcode == OP_CHECKMULTISIGVERIFY:
                    if f_success:
                        self.stack = self.stack[:-1]
                    else:
                        self.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY'
                        return False

            # Default
            else:
                self.errstr = 'SCRIPT_ERR_BAD_OPCODE'
                return False

        return True