def evaluate(self, z): # create a copy as we may need to add to this list if we have a # RedeemScript commands = self.commands[:] stack = [] altstack = [] while len(commands) > 0: command = commands.pop(0) if type(command) == int: # do what the op code says operation = op_function(command) if command in (99, 100): # op_if/op_notif require the commands array if not operation(stack, commands): print(f'bad op: {op_name(command)}') return False elif command in (107, 108): # op_toaltstack/op_fromaltstack require the altstack if not operation(stack, altstack): print(f'bad op: {op_name(command)}') return False elif command in (172, 173, 174, 175): # these are signing operations, they need a sig_hash # to check against if not operation(stack, z): print(f'bad op: {op_name(command)}') return False else: if not operation(stack): print(f'bad op: {op_name(command)}') return False else: # add the command to the stack stack.append(command) if len(stack) == 0: return False if stack.pop() == b'': return False return True
def evaluate(self, z): # create a copy as we may need to add to this list if we have a # RedeemScript commands = self.commands[:] stack = [] altstack = [] while len(commands) > 0: command = commands.pop(0) if type(command) == int: # do what the op code says operation = op_function(command) if command in (99, 100): # op_if/op_notif require the commands array if not operation(stack, commands): print(f'bad op: {op_name(command)}') return False elif command in (107, 108): # op_toaltstack/op_fromaltstack require the altstack if not operation(stack, altstack): print(f'bad op: {op_name(command)}') return False elif command in (172, 173, 174, 175): # these are signing operations, they need a sig_hash # to check against if not operation(stack, z): print(f'bad op: {op_name(command)}') return False else: if not operation(stack): print(f'bad op: {op_name(command)}') return False else: # add the command to the stack stack.append(command) # p2sh rule. if the next three commands are: # OP_HASH160 <20 byte hash> OP_EQUAL this is the RedeemScript # OP_HASH160 == 0xa9 and OP_EQUAL == 0x87 if len(commands) == 3 and commands[0] == 0xa9 \ and type(commands[1]) == bytes and len(commands[1]) == 20 \ and commands[2] == 0x87: redeem_script = encode_varint(len(command)) + command # we execute the next three op codes commands.pop() h160 = commands.pop() commands.pop() if not op_hash160(stack): return False stack.append(h160) if not op_equal(stack): return False # final result should be a 1 if not op_verify(stack): print('bad p2sh h160') return False # hashes match! now add the RedeemScript stream = BytesIO(redeem_script) commands.extend(Script.parse(stream).commands) if len(stack) == 0: return False if stack.pop() == b'': return False return True