def build_htlc_script(secret_hash: bytes, redeemer_pkh: bytes, timeout: int, funder_pkh: bytes) -> str: ''' Parameterizes the HTLC script with the arguments. ''' if len(secret_hash) != 32: raise ValueError('Expected a 32-byte digest. ' f'Got {len(secret_hash)} bytes') if len(redeemer_pkh) != 20: raise ValueError('Expected a 20-byte redeemer pubkeyhash. ' f'Got {len(redeemer_pkh)} bytes') if len(funder_pkh) != 20: raise ValueError('Expected a 20-byte funder pubkeyhash. ' f'Got {len(redeemer_pkh)} bytes') return htlc_script.format(secret_hash=secret_hash.hex(), pkh0=rutils.sha256(redeemer_pkh).hex(), timeout=rutils.i2le(timeout), pkh1=rutils.sha256(funder_pkh).hex())
def _ser_script_to_sh_address(script_bytes: bytes, witness: bool = False, cashaddr: bool = True) -> str: '''makes a p2sh address from a serialized script''' if witness: script_hash = utils.sha256(script_bytes) else: script_hash = utils.hash160(script_bytes) return _hash_to_sh_address(script_hash=script_hash, witness=witness, cashaddr=cashaddr)
def make_sh_script_pubkey(script_bytes: bytes, witness: bool = False) -> bytes: output_script = bytearray() if witness: script_hash = utils.sha256(script_bytes) output_script.extend(riemann.network.P2WSH_PREFIX) output_script.extend(script_hash) else: script_hash = utils.hash160(script_bytes) output_script.extend(b'\xa9\x14') # OP_HASH160 PUSH0x14 output_script.extend(script_hash) output_script.extend(b'\x87') # OP_EQUAL return bytes(output_script)
def address_to_electrum_scripthash(address: str) -> str: '''Electrum is lame and uses backwards sha hashes of output scripts Args: address (str): a valid bitcoin address Returns: (str): the electrum-formatted scripthash in hex ''' try: e = addr.to_output_script(address) except ValueError: raise scripthash = rutils.sha256(e) return scripthash[::-1].hex()
def validate_address(address: AddressEntry) -> bool: ''' Validates the address data structure ''' try: h = addr.parse_hash(address['address']) if address['script'] == b'': return True if address['script_pubkeys'] != pubkeys_from_script(address['script']): return False if h in [ rutils.sha256(address['script']), # p2wsh rutils.hash160(address['script']) ]: # p2sh return True except (ValueError, TypeError, KeyError): pass return False
def _ser_script_to_sh_address(script_bytes: bytes, witness: bool = False, cashaddr: bool = True) -> str: ''' Turns a serialized script into a SH address. Prefers Cashaddrs to legacy addresses whenever supported. Args: script_bytes: The serialized script, as a bytestring witness: Pass True to generate a witness address if supported. Default False. cashaddr: Pass False to prefer legacy to cashaddr. Default True Returns: The encoded address ''' if witness: script_hash = utils.sha256(script_bytes) else: script_hash = utils.hash160(script_bytes) return _hash_to_sh_address(script_hash=script_hash, witness=witness, cashaddr=cashaddr)
def make_sh_script_pubkey(script_bytes: bytes, witness: bool = False) -> bytes: ''' Make a P2SH or P2WSH script pubkey from a serialized script. Does not support Compatibility p2wsh-via-p2sh output scripts. Args: script_bytes: The serialized redeem script or witness script. witness: Pass True to make a P2WSH script pubkey. Returns: The script pubkey containing the hash of the serialized script. ''' output_script = bytearray() if witness: script_hash = utils.sha256(script_bytes) output_script.extend(riemann.network.P2WSH_PREFIX) output_script.extend(script_hash) else: script_hash = utils.hash160(script_bytes) output_script.extend(b'\xa9\x14') # OP_HASH160 PUSH0x14 output_script.extend(script_hash) output_script.extend(b'\x87') # OP_EQUAL return bytes(output_script)
'OP_EQUALVERIFY ' 'OP_CHECKSIG') # this spends via the HTLC secret revelation path # Needs (signature, pubkey, secret, TRUE) # IN THAT ORDER! htlc_stack_script_execute = '{sig} {pk} {secret} OP_1' # this spends via the timelocked refund path # Needs (signature, pubkey, FALSE serialized_redeem_script) # IN THAT ORDER! htlc_stack_script_refund = '{sig} {pk} OP_0' # Worst secret in the world :D secret = '32' * 32 secret_hash = utils.sha256(bytes.fromhex(secret)).hex() # Use real pubkeys! fake_pk_execute = '02' * 32 fake_pk_refund = '03' * 32 # Use a real sig! fake_sig = '04' * 32 # Use a real timelock! timeout = 'deadbeef' # string formatting to fill parameters filled_in_redeem_script = htlc_redeem_script.format( secret_hash=secret_hash, pkh0=utils.hash160(bytes.fromhex(fake_pk_execute)).hex(),