예제 #1
0
def output_derive_script(o: TxOutputType, coin: coininfo.CoinInfo,
                         keychain: seed.Keychain) -> bytes:

    if o.script_type == OutputScriptType.PAYTOOPRETURN:
        # op_return output
        if o.amount != 0:
            raise SigningError(FailureType.DataError,
                               "OP_RETURN output with non-zero amount")
        return scripts.output_script_paytoopreturn(o.op_return_data)

    if o.address_n:
        # change output
        if o.address:
            raise SigningError(FailureType.DataError,
                               "Address in change output")
        o.address = get_address_for_change(o, coin, keychain)
    else:
        if not o.address:
            raise SigningError(FailureType.DataError, "Missing address")

    if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix):
        # p2wpkh or p2wsh
        witprog = addresses.decode_bech32_address(coin.bech32_prefix,
                                                  o.address)
        return scripts.output_script_native_p2wpkh_or_p2wsh(witprog)

    if coin.cashaddr_prefix is not None and o.address.startswith(
            coin.cashaddr_prefix + ":"):
        prefix, addr = o.address.split(":")
        version, data = cashaddr.decode(prefix, addr)
        if version == cashaddr.ADDRESS_TYPE_P2KH:
            version = coin.address_type
        elif version == cashaddr.ADDRESS_TYPE_P2SH:
            version = coin.address_type_p2sh
        else:
            raise ValueError("Unknown cashaddr address type")
        raw_address = bytes([version]) + data
    else:
        raw_address = base58.decode_check(o.address, coin.b58_hash)

    if address_type.check(coin.address_type, raw_address):
        # p2pkh
        pubkeyhash = address_type.strip(coin.address_type, raw_address)
        script = scripts.output_script_p2pkh(pubkeyhash)
        if coin.bip115:
            script += scripts.script_replay_protection_bip115(
                o.block_hash_bip115, o.block_height_bip115)
        return script

    elif address_type.check(coin.address_type_p2sh, raw_address):
        # p2sh
        scripthash = address_type.strip(coin.address_type_p2sh, raw_address)
        script = scripts.output_script_p2sh(scripthash)
        if coin.bip115:
            script += scripts.script_replay_protection_bip115(
                o.block_hash_bip115, o.block_height_bip115)
        return script

    raise SigningError(FailureType.DataError, "Invalid address type")
예제 #2
0
def output_derive_script(
    o: TxOutputType, coin: coininfo.CoinInfo, keychain: seed.Keychain
) -> bytes:

    if o.script_type == OutputScriptType.PAYTOOPRETURN:
        return scripts.output_script_paytoopreturn(o.op_return_data)

    if o.address_n:
        # change output
        o.address = get_address_for_change(o, coin, keychain)

    if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix):
        # p2wpkh or p2wsh
        witprog = addresses.decode_bech32_address(coin.bech32_prefix, o.address)
        return scripts.output_script_native_p2wpkh_or_p2wsh(witprog)

    if (
        not utils.BITCOIN_ONLY
        and coin.cashaddr_prefix is not None
        and o.address.startswith(coin.cashaddr_prefix + ":")
    ):
        prefix, addr = o.address.split(":")
        version, data = cashaddr.decode(prefix, addr)
        if version == cashaddr.ADDRESS_TYPE_P2KH:
            version = coin.address_type
        elif version == cashaddr.ADDRESS_TYPE_P2SH:
            version = coin.address_type_p2sh
        else:
            raise SigningError("Unknown cashaddr address type")
        raw_address = bytes([version]) + data
    else:
        try:
            raw_address = base58.decode_check(o.address, coin.b58_hash)
        except ValueError:
            raise SigningError(FailureType.DataError, "Invalid address")

    if address_type.check(coin.address_type, raw_address):
        # p2pkh
        pubkeyhash = address_type.strip(coin.address_type, raw_address)
        script = scripts.output_script_p2pkh(pubkeyhash)
        return script

    elif address_type.check(coin.address_type_p2sh, raw_address):
        # p2sh
        scripthash = address_type.strip(coin.address_type_p2sh, raw_address)
        script = scripts.output_script_p2sh(scripthash)
        return script

    raise SigningError(FailureType.DataError, "Invalid address type")