def sig_hash(self, input_index, hash_type): '''Returns the integer representation of the hash that needs to get signed for index input_index''' # create a new set of tx_ins (alt_tx_ins) alt_tx_ins = [] # iterate over self.tx_ins for tx_in in self.tx_ins: # create a new TxIn that has a blank script_sig (b'') and add to alt_tx_ins alt_tx_ins.append( TxIn( prev_tx=tx_in.prev_tx, prev_index=tx_in.prev_index, script_sig=b'', sequence=tx_in.sequence, )) # grab the input at the input_index signing_input = alt_tx_ins[input_index] # grab the script_pubkey of the input script_pubkey = signing_input.script_pubkey(self.testnet) signing_input.script_sig = script_pubkey # Exercise 6.2 REPLACE THIS LINE!!! # Exercise 6.2: get the sig type from script_pubkey.type() # Exercise 6.2: the script_sig of the signing_input should be script_pubkey for p2pkh # Exercise 6.2: replace the input's scriptSig with the scriptPubKey # Exercise 6.2: the script_sig of the signing_input should be the redeemScript # of the current input of the real tx_in (self.tx_ins[input_index].redeem_script() # Exercise 6.2: replace the input's scriptSig with the RedeemScript # Exercise 6.2: replace the input's scriptSig with the Script.parse(redeem_script) # create an alternate transaction with the modified tx_ins alt_tx = self.__class__(version=self.version, tx_ins=alt_tx_ins, tx_outs=self.tx_outs, locktime=self.locktime) # add the hash_type int 4 bytes, little endian result = alt_tx.serialize() + int_to_little_endian(hash_type, 4) # get the double_sha256 of the tx serialization s256 = double_sha256(result) # convert this to a big-endian integer using int.from_bytes(x, 'big') return int.from_bytes(s256, 'big')
def sig_hash(self, input_index, hash_type): '''Returns the integer representation of the hash that needs to get signed for index input_index''' # create a transaction serialization where # all the input script_sigs are blanked out alt_tx_ins = [] for tx_in in self.tx_ins: alt_tx_ins.append(TxIn( prev_tx=tx_in.prev_tx, prev_index=tx_in.prev_index, script_sig=b'', sequence=tx_in.sequence, value=tx_in.value(), script_pubkey=tx_in.script_pubkey().serialize(), )) # replace the input's scriptSig with the scriptPubKey signing_input = alt_tx_ins[input_index] script_pubkey = signing_input.script_pubkey(self.testnet) sig_type = script_pubkey.type() if sig_type == 'p2pkh': signing_input.script_sig = script_pubkey elif sig_type == 'p2sh': current_input = self.tx_ins[input_index] signing_input.script_sig = Script.parse( current_input.redeem_script()) else: raise RuntimeError('no valid sig_type') alt_tx = self.__class__( version=self.version, tx_ins=alt_tx_ins, tx_outs=self.tx_outs, locktime=self.locktime, ) # add the hash_type result = alt_tx.serialize() result += int_to_little_endian(hash_type, 4) result += self.sighash_append return int.from_bytes(double_sha256(result), 'big')
def address(self, compressed=True, testnet=False): '''Returns the address string''' # get the sec # hash160 the sec # raw is hash 160 prepended w/ b'\x00' for mainnet, b'\x6f' for testnet # checksum is first 4 bytes of double_sha256 of raw # encode_base58 the raw + checksum # return as a string, you can use .decode('ascii') to do this. sec_format = self.sec(compressed) # hash160 the result h160 = hash160(sec_format) print(h160) # prepend b'\x00' for mainnet b'\x6f' for testnet prepend = [ b'\x00', b'\x6f'] # raw is the prefix + h160 prefix = prepend[0] if not testnet else prepend[1] raw = prefix + h160 # get the double_sha256 of raw, first 4 bytes are the checksum raw = raw + double_sha256(raw)[:4] # append checksum # encode_base58 the whole thing addr = encode_base58(raw) return addr.decode('ascii')
def sig_hash_bip143(self, input_index, hash_type, prev_block=False, sbtc=False): '''Returns the integer representation of the hash that needs to get signed for index input_index''' tx_in = self.tx_ins[input_index] # per BIP143 spec s = int_to_little_endian(self.version, 4) if prev_block: s += self.prev_block_hash[::-1] s += self.hash_prevouts() + self.hash_sequence() s += tx_in.prev_tx[::-1] + int_to_little_endian(tx_in.prev_index, 4) ser = tx_in.script_pubkey() s += bytes([len(ser)]) + ser # script pubkey s += int_to_little_endian(tx_in.value(), 8) s += int_to_little_endian(tx_in.sequence, 4) s += self.hash_outputs() s += int_to_little_endian(self.locktime, 4) s += int_to_little_endian(hash_type, 4) if sbtc: s += b'sbtc' return int.from_bytes(double_sha256(s), 'big')
def hash(self): """ witness id """ return double_sha256(self.serialize())[::-1]
def txid(self): """ non-witness serialization for txid """ # as TxIn doesn't include signature anymore this serialization is immune to tx malleability problem return double_sha256(self.serialize(with_witness=False))[::-1]
def sig_hash_w0(self, input_index, hash_type): # support only ALL type for now s256 = double_sha256(self.sig_hash_w0_preimage(input_index, hash_type)) return int.from_bytes(s256, 'big')
def hash_sequence(self, hash_type=SIGHASH_ALL): # serialize sequence return double_sha256(b''.join([int_to_little_endian(tx_in.sequence, 4) for tx_in in self.tx_ins]))
def hash_outputs(self, hash_type=SIGHASH_ALL): return double_sha256(b''.join([tx_out.serialize() for tx_out in self.tx_outs]))
def sig_hash_bip143(self, input_index, hash_type): s = self.sig_hash_preimage_bip143(input_index, hash_type) return int.from_bytes(double_sha256(s), 'big')
def __init__(self, private_keys): self.pks = [] for i in range(len(private_keys)): secret = little_endian_to_int(double_sha256(private_keys[i])) self.pks.append(PrivateKey(secret=secret)) self.points = [pk.point for pk in self.pks]
def H(*args): return double_sha256(b''.join(args))
def op_hash256(stack): if len(stack) < 1: return False element = stack.pop() stack.append(double_sha256(element)) return True
def hash(self): return double_sha256(self.serialize())[::-1]
def proof(self): '''Calculate the proof-of-work for this block''' # get the double_sha256 of the serialization of this block sha = double_sha256(self.serialize()) # interpret this hash as a little-endian number return little_endian_to_int(sha)
def hash(self): '''Returns the double-sha256 interpreted little endian of the block''' return double_sha256(self.serialize())[::-1]
def hash(self): '''Binary hash of the legacy serialization''' return double_sha256(self.serialize())[::-1]