Example #1
0
def test_non_standard_script_in_p2wsh() -> None:

    network = "mainnet"

    fed_pub_keys: List[Command] = ["00" * 33, "11" * 33, "22" * 33]
    rec_pub_keys: List[Command] = ["77" * 33, "88" * 33, "99" * 33]
    # fmt: off
    redeem_script_cmds: List[Command] = [
        "OP_IF",
        "OP_2",
        *fed_pub_keys,
        "OP_3",
        "OP_CHECKMULTISIG",  # noqa E131
        "OP_ELSE",
        500,
        "OP_CHECKLOCKTIMEVERIFY",
        "OP_DROP",  # noqa E131
        "OP_2",
        *rec_pub_keys,
        "OP_3",
        "OP_CHECKMULTISIG",  # noqa E131
        "OP_ENDIF",
    ]
    # fmt: on
    redeem_script = serialize(redeem_script_cmds)
    assert redeem_script_cmds == parse(redeem_script)
    payload = sha256(redeem_script)
    script_pub_key = (
        "00207b5310339c6001f75614daa5083839fa54d46165f6c56025cc54d397a85a5708")
    assert script_pub_key == ScriptPubKey.p2wsh(redeem_script).script.hex()
    addr = "bc1q0df3qvuuvqqlw4s5m2jsswpelf2dgct97mzkqfwv2nfe02z62uyq7n4zjj"
    assert addr == address(script_pub_key, network)
    assert addr == b32.address_from_witness(0, payload, network)
Example #2
0
    def assert_signable(self) -> None:

        self.assert_valid()

        for i, tx_in in enumerate(self.tx.vin):

            non_witness_utxo = self.inputs[i].non_witness_utxo
            witness_utxo = self.inputs[i].witness_utxo
            redeem_script = self.inputs[i].redeem_script

            if witness_utxo:
                script_pub_key = witness_utxo.script_pub_key
                script_type, payload = type_and_payload(script_pub_key.script)
                if script_type == "p2sh":
                    script_type, _ = type_and_payload(redeem_script)
                if script_type not in ("p2wpkh", "p2wsh"):
                    raise BTClibValueError(
                        "script type not it ('p2wpkh', 'p2wsh')")
            elif non_witness_utxo:
                script_pub_key = non_witness_utxo.vout[
                    tx_in.prev_out.vout].script_pub_key
                _, payload = type_and_payload(script_pub_key.script)
            else:
                err_msg = "missing script_pub_key"
                raise BTClibValueError(err_msg)

            if redeem_script and payload != hash160(redeem_script):
                raise BTClibValueError("invalid redeem script hash160")

            if self.inputs[i].witness_script:
                if redeem_script:
                    _, payload = type_and_payload(redeem_script)
                if payload != sha256(self.inputs[i].witness_script):
                    raise BTClibValueError("invalid witness script sha256")
Example #3
0
def test_p2wsh() -> None:

    # self-consistency
    pub_key = "02 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf"
    redeem_script = ScriptPubKey.p2pkh(pub_key).script
    payload = sha256(redeem_script)
    script_pub_key = serialize(["OP_0", payload])
    assert_p2wsh(script_pub_key)
    assert script_pub_key == ScriptPubKey.p2wsh(redeem_script).script
    assert ("p2wsh", payload) == type_and_payload(script_pub_key)

    # bech32 address
    network = "mainnet"
    addr = b32.p2wsh(redeem_script, network)
    assert addr == address(script_pub_key, network)
    assert addr == b32.address_from_witness(0, payload, network)

    # back from the address to the script_pub_key
    assert script_pub_key == ScriptPubKey.from_address(addr).script
    assert network == ScriptPubKey.from_address(addr).network

    # p2sh-wrapped base58 address
    addr = b58.p2wsh_p2sh(redeem_script, network)
    assert addr == "39GUePMSQ4mADpihVLd8cFQ2tih9Fy4qkz"

    err_msg = "invalid witness version: "
    with pytest.raises(BTClibValueError, match=err_msg):
        assert_p2wsh(b"\x33" + script_pub_key[1:])

    err_msg = "invalid redeem script hash length marker: "
    with pytest.raises(BTClibValueError, match=err_msg):
        assert_p2wsh(script_pub_key[:1] + b"\x00" + script_pub_key[2:])
Example #4
0
def test_p2wsh() -> None:

    # https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
    pub = "02 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
    script_pub_key: List[Command] = [pub, "OP_CHECKSIG"]
    witness_script_bytes = serialize(script_pub_key)

    addr = "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7"
    assert addr == b32.p2wsh(witness_script_bytes, "testnet")
    _, wit_prg, _ = b32.witness_from_address(addr)
    assert wit_prg == sha256(witness_script_bytes)

    addr = "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3"
    assert addr == b32.p2wsh(witness_script_bytes)
    _, wit_prg, _ = b32.witness_from_address(addr)
    assert wit_prg == sha256(witness_script_bytes)

    err_msg = "invalid size: "
    with pytest.raises(BTClibValueError, match=err_msg):
        b32.address_from_witness(0, witness_script_bytes)
Example #5
0
    def p2wsh(
        cls: Type["ScriptPubKey"],
        redeem_script: Octets,
        network: str = "mainnet",
        check_validity: bool = True,
    ) -> "ScriptPubKey":
        "Return the p2wsh ScriptPubKey of the provided redeem script."

        script_h256 = sha256(redeem_script)
        script = serialize(["OP_0", script_h256])
        return cls(script, network, check_validity)
Example #6
0
def _assert_valid_sha256_preimages(
        sha256_preimages: Mapping[bytes, bytes]) -> None:

    for h, preimage in sha256_preimages.items():
        if sha256(preimage) != h:
            raise BTClibValueError("Invalid SHA256 preimage")
Example #7
0
def p2wsh_p2sh(redeem_script: Octets, network: str = "mainnet") -> str:
    "Return the p2wsh-p2sh base58 address corresponding to a reedem script."
    witness_program = sha256(redeem_script)
    return _address_from_v0_witness(witness_program, network)
Example #8
0
def taproot(
    transaction: Tx,
    input_index: int,
    amounts: List[int],
    scriptpubkeys: List[ScriptPubKey],
    hashtype: int,
    ext_flag: int,
    annex: bytes,
    message_extension: bytes,
) -> bytes:

    if hashtype not in SIG_HASH_TYPES:
        raise BTClibValueError(f"Unknown hash type: {hashtype}")
    if hashtype & 0x03 == SINGLE and input_index >= len(transaction.vout):
        raise BTClibValueError("Sighash single wihout a corresponding output")

    preimage = b"\x00"
    preimage += hashtype.to_bytes(1, "little")
    preimage += transaction.nVersion.to_bytes(4, "little")
    preimage += transaction.nLockTime.to_bytes(4, "little")

    if hashtype & 0x80 != ANYONECANPAY:
        sha_prevouts = b""
        sha_amounts = b""
        sha_scriptpubkeys = b""
        sha_sequences = b""
        for i, vin in enumerate(transaction.vin):
            sha_prevouts += vin.prev_out.serialize()
            sha_amounts += amounts[i].to_bytes(8, "little")
            sha_scriptpubkeys += var_bytes.serialize(scriptpubkeys[i].script)
            sha_sequences += vin.nSequence.to_bytes(4, "little")
        preimage += sha256(sha_prevouts)
        preimage += sha256(sha_amounts)
        preimage += sha256(sha_scriptpubkeys)
        preimage += sha256(sha_sequences)

    if hashtype & 0x03 not in [NONE, SINGLE]:
        sha_outputs = b""
        for vout in transaction.vout:
            sha_outputs += vout.serialize()
        preimage += sha256(sha_outputs)

    annex_present = int(bool(annex))
    preimage += (2 * ext_flag + annex_present).to_bytes(1, "little")

    if hashtype & 0x80 == ANYONECANPAY:
        preimage += transaction.vin[input_index].prev_out.serialize()
        preimage += amounts[input_index].to_bytes(8, "little")
        preimage += var_bytes.serialize(scriptpubkeys[input_index].script)
        preimage += transaction.vin[input_index].nSequence.to_bytes(
            4, "little")
    else:
        preimage += input_index.to_bytes(4, "little")

    if annex_present:
        sha_annex = var_bytes.serialize(annex)
        preimage += sha256(sha_annex)

    if hashtype & 0x03 == SINGLE:
        preimage += sha256(transaction.vout[input_index].serialize())

    preimage += message_extension

    sig_hash = tagged_hash(b"TapSighash", preimage)
    return sig_hash
Example #9
0
def p2wsh(script_pub_key: Octets, network: str = "mainnet") -> str:
    "Return the p2wsh bech32 address corresponding to a script_pub_key."
    h256 = sha256(script_pub_key)
    return address_from_witness(0, h256, network)