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)
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)]
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)
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)
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)
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')
def test_binary_single(self): s = Script.from_bytes('\0') assert s.instructions == [Instruction(OP_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
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