Beispiel #1
0
def test_valid_script_path() -> None:
    fname = "tapscript_test_vector.json"
    filename = path.join(path.dirname(__file__), "_data", fname)
    with open(filename, "r", encoding="ascii") as file_:
        data = json.load(file_)

    for x in data:

        prevouts = [TxOut.parse(prevout) for prevout in x["prevouts"]]
        index = x["index"]

        if not is_p2tr(prevouts[index].script_pub_key.script):
            continue

        script_sig = x["success"]["scriptSig"]
        assert not script_sig

        witness = Witness(x["success"]["witness"])
        if len(witness.stack) >= 2 and witness.stack[-1][0] == 0x50:
            witness.stack = witness.stack[:-1]

        # check script paths
        if len(witness.stack) < 2:
            continue

        Q = type_and_payload(prevouts[index].script_pub_key.script)[1]

        script = witness.stack[-2]
        control = witness.stack[-1]

        assert check_output_pubkey(Q, script, control)
Beispiel #2
0
def test_native_p2wsh_2() -> None:
    tx_bytes = "0100000002e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac00000000"
    tx = Tx.parse(tx_bytes)
    tx.vin[0].script_witness = Witness([
        "0063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac"
    ])
    tx.vin[1].script_witness = Witness([
        "5163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac"
    ])

    previous_txout_1 = TxOut(
        16777215,
        "0020ba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d")
    previous_txout_2 = TxOut(
        16777215,
        "0020d9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537")
    hash_ = sig_hash.from_tx(
        [previous_txout_1, previous_txout_2],
        tx,
        0,
        sig_hash.ANYONECANPAY | sig_hash.SINGLE,
    )
    assert hash_ == bytes.fromhex(
        "e9071e75e25b8a1e298a72f0d2e9f4f95a0f5cdf86a533cda597eb402ed13b3a")

    script_ = sig_hash.witness_v0_script(tx.vin[1].script_witness.stack[-1])[1]
    hash_ = sig_hash.segwit_v0(
        script_,
        tx,
        1,
        sig_hash.ANYONECANPAY | sig_hash.SINGLE,
        previous_txout_2.value,
    )
    assert hash_ == bytes.fromhex(
        "cd72f1f1a433ee9df816857fad88d8ebd97e09a75cd481583eb841c330275e54")
Beispiel #3
0
def _deserialize_final_script_witness(k: bytes, v: bytes) -> Witness:
    "Return the dataclass element from its binary representation."

    if len(k) != 1:
        err_msg = f"invalid final script witness key length: {len(k)}"
        raise BTClibValueError(err_msg)
    return Witness.parse(v)
Beispiel #4
0
    def parse(cls: Type[_Tx],
              data: BinaryData,
              check_validity: bool = True) -> _Tx:
        "Return a Tx by parsing binary data."

        stream = bytesio_from_binarydata(data)

        # version is a signed int (int32_t, not uint32_t)
        version = int.from_bytes(stream.read(4),
                                 byteorder="little",
                                 signed=True)

        segwit = stream.read(2) == _SEGWIT_MARKER
        if not segwit:
            # Change stream position: seek to byte offset relative to position
            stream.seek(-2, SEEK_CUR)  # current position

        n = var_int.parse(stream)
        vin = [TxIn.parse(stream) for _ in range(n)]

        n = var_int.parse(stream)
        vout = [TxOut.parse(stream) for _ in range(n)]

        if segwit:
            for tx_in in vin:
                tx_in.script_witness = Witness.parse(stream, check_validity)

        lock_time = int.from_bytes(stream.read(4),
                                   byteorder="little",
                                   signed=False)

        return cls(version, lock_time, vin, vout, check_validity)
    def __init__(
        self,
        non_witness_utxo: Optional[Tx] = None,
        witness_utxo: Optional[TxOut] = None,
        partial_sigs: Optional[Mapping[Octets, Octets]] = None,
        sig_hash_type: Optional[int] = None,
        redeem_script: Octets = b"",
        witness_script: Octets = b"",
        hd_key_paths: Optional[Mapping[Octets, BIP32KeyOrigin]] = None,
        final_script_sig: Octets = b"",
        final_script_witness: Witness = Witness(),
        unknown: Optional[Mapping[Octets, Octets]] = None,
        check_validity: bool = True,
    ) -> None:

        self.non_witness_utxo = non_witness_utxo
        self.witness_utxo = witness_utxo
        # https://docs.python.org/3/tutorial/controlflow.html#default-argument-values
        self.partial_sigs = (decode_dict_bytes_bytes(partial_sigs)
                             if partial_sigs else {})
        self.sig_hash_type = sig_hash_type
        self.redeem_script = bytes_from_octets(redeem_script)
        self.witness_script = bytes_from_octets(witness_script)
        self.hd_key_paths = decode_hd_key_paths(hd_key_paths)
        self.final_script_sig = bytes_from_octets(final_script_sig)
        self.final_script_witness = final_script_witness
        self.unknown = dict(sorted(decode_dict_bytes_bytes(unknown).items()))

        if check_validity:
            self.assert_valid()
Beispiel #6
0
def test_single_witness() -> None:
    # 4e52f7848dab7dd89ef7ba477939574198a170bfcb2fb34355c69f5e0169f63c
    tx_bytes = "010000000001019bdea7abb2fa14dead47dd14d03cf82212a25b6096a8da6b14feec3658dbcf9d0100000000ffffffff02a02526000000000017a914f987c321394968be164053d352fc49763b2be55c874361610000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220421fbbedf2ee096d6289b99973509809d5e09589040d5e0d453133dd11b2f78a02205686dbdb57e0c44e49421e9400dd4e931f1655332e8d078260c9295ba959e05d014730440220398f141917e4525d3e9e0d1c6482cb19ca3188dc5516a3a5ac29a0f4017212d902204ea405fae3a58b1fc30c5ad8ac70a76ab4f4d876e8af706a6a7b4cd6fa100f44016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000"
    tx = Tx.parse(tx_bytes)
    assert tx.serialize(include_witness=True).hex() == tx_bytes
    assert tx == Tx.from_dict(tx.to_dict())

    assert tx.version == 1
    assert tx.lock_time == 0
    assert len(tx.vin) == 1
    assert len(tx.vout) == 2

    stack = [
        "",
        "30440220421fbbedf2ee096d6289b99973509809d5e09589040d5e0d453133dd11b2f78a02205686dbdb57e0c44e49421e9400dd4e931f1655332e8d078260c9295ba959e05d01",
        "30440220398f141917e4525d3e9e0d1c6482cb19ca3188dc5516a3a5ac29a0f4017212d902204ea405fae3a58b1fc30c5ad8ac70a76ab4f4d876e8af706a6a7b4cd6fa100f4401",
        "52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae",
    ]
    witness = Witness(stack)
    assert tx.vin[0].script_witness == witness

    tx_id = "4e52f7848dab7dd89ef7ba477939574198a170bfcb2fb34355c69f5e0169f63c"
    assert tx.id.hex() == tx_id
    hash_ = "d39eb3e3954be4bdc0b3be2d980124b1e1e11fb414b886b52939b07d95a58a8f"
    assert tx.hash.hex() == hash_
    assert tx.size == 380
    assert tx.vsize == 190
    assert tx.weight == 758
    assert tx.is_segwit()
    assert any(bool(w) for w in tx.vwitness)
    assert not tx.is_coinbase()
Beispiel #7
0
def test_valid_taproot_script_path() -> None:
    tx_data = "26dc279d02d8b1a203b653fc4e0f27f408432f3f540136d33f8f930eaeba655910095142980402000000fd697cd4eb5278f1e34545cd57b6670df806fa3a0a064fd8e385a19f1a53d9ce8d8971a30f02000000378d5fb502335dbe02000000001976a9140053a23441c8478caac4c6b769c51f8476cd4b4b88ac58020000000000001976a914f2aae94a43e0d173354201d7832b46c5269c8a2488ac4a08671e"
    prevouts_data = [
        "91ca4c010000000017a9145658b58602cdf7b7e962cfe44e024cb0e366f27087",
        "cb127401000000002251201ebe8b90363bd097aa9f352c8b21914e1886bc09fe9e70c09f33ef2d2abdf4bc",
    ]
    witness_data = [
        "9675a9982c6398ea9d441cb7a943bcd6ff033cc3a2e01a0178a7d3be4575be863871c6bf3eef5ecd34721c784259385ca9101c3a313e010ac942c99de05aaaa602",
        "5799cf4b193b730fb99580b186f7477c2cca4d28957326f6f1a5d14116438530e7ec0ce1cd465ad96968ae8a6a09d4d37a060a115919f56fcfebe7b2277cc2df5cc08fb6cda9105ee2512b2e22635aba",
        "7520c7b5db9562078049719228db2ac80cb9643ec96c8055aa3b29c2c03d4d99edb0ac",
        "c1a7957acbaaf7b444c53d9e0c9436e8a8a3247fd515095d66ddf6201918b40a3668f9a4ccdffcf778da624dca2dda0b08e763ec52fd4ad403ec7563a3504d0cc168b9a77a410029e01dac89567c9b2e6cd726e840351df3f2f58fefe976200a19244150d04153909f660184d656ee95fa7bf8e1d4ec83da1fca34f64bc279b76d257ec623e08baba2cfa4ea9e99646e88f1eb1668c00c0f15b7443c8ab83481611cc3ae85eb89a7bfc40067eb1d2e6354a32426d0ce710e88bc4cc0718b99c325509c9d02a6a980d675a8969be10ee9bef82cafee2fc913475667ccda37b1bc7f13f64e56c449c532658ba8481631c02ead979754c809584a875951619cec8fb040c33f06468ae0266cd8693d6a64cea5912be32d8de95a6da6300b0c50fdcd6001ea41126e7b7e5280d455054a816560028f5ca53c9a50ee52f10e15c5337315bad1f5277acb109a1418649dc6ead2fe14699742fee7182f2f15e54279c7d932ed2799d01d73c97e68bbc94d6f7f56ee0a80efd7c76e3169e10d1a1ba3b5f1eb02369dc43af687461c7a2a3344d13eb5485dca29a67f16b4cb988923060fd3b65d0f0352bb634bcc44f2fe668836dcd0f604150049835135dc4b4fbf90fb334b3938a1f137eb32f047c65b85e6c1173b890b6d0162b48b186d1f1af8521945924ac8ac8efec321bf34f1d4b3d4a304a10313052c652d53f6ecb8a55586614e8950cde9ab6fe8e22802e93b3b9139112250b80ebc589aba231af535bb20f7eeec2e412f698c17f3fdc0a2e20924a5e38b21a628a9e3b2a61e35958e60c7f5087c",
    ]

    tx = Tx.parse(tx_data)
    prevouts = [TxOut.parse(prevout) for prevout in prevouts_data]
    index = 1
    witness = Witness(witness_data)
    tx.vin[index].script_witness = witness

    sighash_type = 0  # all
    signature = witness.stack[0][:64]
    if len(witness.stack[0]) == 65:
        sighash_type = witness.stack[0][-1]
        assert sighash_type != 0

    msg_hash = sig_hash.from_tx(prevouts, tx, index, sighash_type)

    tapscript = parse(witness.stack[-2])
    pub_key = bytes.fromhex(str(tapscript[1]))

    ssa.assert_as_valid_(msg_hash, pub_key, signature)
Beispiel #8
0
def test_wrapped_p2wsh() -> None:
    tx_bytes = "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"
    tx = Tx.parse(tx_bytes)
    stack = [
        "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae"
    ]
    tx.vin[0].script_witness = Witness(stack)

    utxo = TxOut(
        987654321,
        "0020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54",
    )

    hash_ = sig_hash.from_tx([utxo], tx, 0, sig_hash.ALL)
    assert hash_ == bytes.fromhex(
        "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
    hash_ = sig_hash.from_tx([utxo], tx, 0, sig_hash.NONE)
    assert hash_ == bytes.fromhex(
        "e9733bc60ea13c95c6527066bb975a2ff29a925e80aa14c213f686cbae5d2f36")
    hash_ = sig_hash.from_tx([utxo], tx, 0, sig_hash.SINGLE)
    assert hash_ == bytes.fromhex(
        "1e1f1c303dc025bd664acb72e583e933fae4cff9148bf78c157d1e8f78530aea")
    hash_ = sig_hash.from_tx([utxo], tx, 0,
                             sig_hash.ANYONECANPAY | sig_hash.ALL)
    assert hash_ == bytes.fromhex(
        "2a67f03e63a6a422125878b40b82da593be8d4efaafe88ee528af6e5a9955c6e")
    hash_ = sig_hash.from_tx([utxo], tx, 0,
                             sig_hash.ANYONECANPAY | sig_hash.NONE)
    assert hash_ == bytes.fromhex(
        "781ba15f3779d5542ce8ecb5c18716733a5ee42a6f51488ec96154934e2c890a")
    hash_ = sig_hash.from_tx([utxo], tx, 0,
                             sig_hash.ANYONECANPAY | sig_hash.SINGLE)
    assert hash_ == bytes.fromhex(
        "511e8e52ed574121fc1b654970395502128263f62662e076dc6baf05c2e6a99b")
Beispiel #9
0
    def from_dict(cls: Type["TxIn"],
                  dict_: Mapping[str, Any],
                  check_validity: bool = True) -> "TxIn":

        return cls(
            OutPoint.from_dict(dict_["prev_out"], False),
            dict_["scriptSig"],
            dict_["sequence"],
            Witness.from_dict(dict_["txinwitness"], False),
            check_validity,
        )
Beispiel #10
0
    def parse(cls: Type["TxIn"],
              data: BinaryData,
              check_validity: bool = True) -> "TxIn":

        stream = bytesio_from_binarydata(data)
        prev_out = OutPoint.parse(stream)
        script_sig = var_bytes.parse(stream)
        sequence = int.from_bytes(stream.read(4),
                                  byteorder="little",
                                  signed=False)

        return cls(prev_out, script_sig, sequence, Witness(), check_validity)
Beispiel #11
0
def test_dataclasses_json_dict() -> None:
    witness_bytes = "0600483045022100a2c452a28dc58984d809e445bc9429d2e5023eafc6b070e64655928034409b7e022071de7f967b0f2e3e99d636b6e5497197cd2d4dbea81c8b42f8f0a9a8709987b701483045022100cace5cc666336fd9b620f5853d0e344da3bf2face0ac28c968240a635efe71ea022000c8bf8aafeab9c62a0815efcbc11890a742d0baee9be652b316060be54dde750147304402202ed13a2a660020e030c40a49378c507e86ec73d05c59b045b8502126630a03e3022051b6160547ac9604cc30ecfbdab66545783182b8ea30ceac657366ccea08575b010101fd1e0163532102ccb438a1d9fae7aaff5c058949f0768d4fa24671f1c43643f194098316a854752102f3448accdbf6e648ff8c9c591797b57ebfbd7bab0e2a4fcaeba686f9a9df58e121033a1229e67ad80e37234edafda3fc9dc02a2e5d70e7d861c11c94515d178edaf52103519b8d8f86813e07852728d31338f1d1d772865bf4792aa87d6f1ceb1e348fcd2103cd36dabe3dfd4e473a5a62a97a40b2e6bb47bb502bcf13163c91262f0604a06855ae67029000b27552210219d79d15338a4596b2a5dc88d191e0ae85fbfdd30802a18b3c3ff0d1c1c7c6f121025dedb64d7e5046f62b506ae9ec391ab15e70acb8d3d98c5527a481526a25d4f62103cee6fe19333a1b2e11e424bb106dfe4bc61daa273badb1de86c19dbc9037cdcd53ae68"
    witness = Witness.parse(witness_bytes)

    # Witness dataclass
    assert isinstance(witness, Witness)
    assert witness.stack
    assert len(witness.stack) > 0

    # Witness dataclass to dict
    witness_dict = witness.to_dict()
    assert isinstance(witness_dict, dict)
    assert witness_dict["stack"]
    assert len(witness_dict["stack"]) > 0  # type: ignore

    # Witness dataclass dict to file
    datadir = path.join(path.dirname(__file__), "_generated_files")
    filename = path.join(datadir, "witness.json")
    with open(filename, "w", encoding="ascii") as file_:
        json.dump(witness_dict, file_, indent=4)

    # Witness dataclass dict from file
    with open(filename, "r", encoding="ascii") as file_:
        witness_dict2 = json.load(file_)
    assert isinstance(witness_dict2, dict)
    assert witness_dict2["stack"]
    assert len(witness_dict2["stack"]) > 0  # type: ignore

    assert witness_dict == witness_dict2

    # Witness dataclass from dict
    witness2 = Witness.from_dict(witness_dict)
    assert isinstance(witness2, Witness)
    assert witness2.stack
    assert len(witness2.stack) > 0

    assert witness == witness2
Beispiel #12
0
def test_double_witness() -> None:
    tx_bytes = "01000000000102322d4f05c3a4f78e97deda01bd8fc5ff96777b62c8f2daa72b02b70fa1e3e1051600000017160014e123a5263695be634abf3ad3456b4bf15f09cc6afffffffffdfee6e881f12d80cbcd6dc54c3fe390670678ebd26c3ae2dd129f41882e3efc25000000171600145946c8c3def6c79859f01b34ad537e7053cf8e73ffffffff02c763ac050000000017a9145ffd6df9bd06dedb43e7b72675388cbfc883d2098727eb180a000000001976a9145f9e96f739198f65d249ea2a0336e9aa5aa0c7ed88ac024830450221009b364c1074c602b2c5a411f4034573a486847da9c9c2467596efba8db338d33402204ccf4ac0eb7793f93a1b96b599e011fe83b3e91afdc4c7ab82d765ce1da25ace01210334d50996c36638265ad8e3cd127506994100dd7f24a5828155d531ebaf736e160247304402200c6dd55e636a2e4d7e684bf429b7800a091986479d834a8d462fbda28cf6f8010220669d1f6d963079516172f5061f923ef90099136647b38cc4b3be2a80b820bdf90121030aa2a1c2344bc8f38b7a726134501a2a45db28df8b4bee2df4428544c62d731400000000"
    tx = Tx.parse(tx_bytes)
    assert tx.serialize(include_witness=True).hex() == tx_bytes
    assert tx == Tx.from_dict(tx.to_dict())

    assert tx.version == 1
    assert tx.lock_time == 0
    assert len(tx.vin) == 2
    assert len(tx.vout) == 2

    stack1 = [
        "30450221009b364c1074c602b2c5a411f4034573a486847da9c9c2467596efba8db338d33402204ccf4ac0eb7793f93a1b96b599e011fe83b3e91afdc4c7ab82d765ce1da25ace01",
        "0334d50996c36638265ad8e3cd127506994100dd7f24a5828155d531ebaf736e16",
    ]
    witness1 = Witness(stack1)
    assert tx.vin[0].script_witness == witness1

    stack2 = [
        "304402200c6dd55e636a2e4d7e684bf429b7800a091986479d834a8d462fbda28cf6f8010220669d1f6d963079516172f5061f923ef90099136647b38cc4b3be2a80b820bdf901",
        "030aa2a1c2344bc8f38b7a726134501a2a45db28df8b4bee2df4428544c62d7314",
    ]
    witness2 = Witness(stack2)
    assert tx.vin[1].script_witness == witness2

    tx_id = "a4b76807519aba5740f7865396bc4c5ca0eb8aa7c3744ca2db88fcc9e345424c"
    assert tx.id.hex() == tx_id
    hash_ = "0936cb8dba90e11345b9c05f457f139ddce4a5329701af4708b2cf4a02d75adb"
    assert tx.hash.hex() == hash_
    assert tx.size == 421
    assert tx.vsize == 259
    assert tx.weight == 1033
    assert tx.is_segwit()
    assert any(bool(w) for w in tx.vwitness)
    assert any(bool(tx_in.script_witness) for tx_in in tx.vin)
    assert not tx.is_coinbase()
Beispiel #13
0
def test_empty_stack() -> None:

    utxo = TxOut(
        100000000,
        serialize([
            "OP_1",
            "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf"
        ]),
    )
    tx_in = TxIn(OutPoint(), "", 1, Witness([]))
    tx = Tx(vin=[tx_in], vout=[TxOut(100000000, "")])

    err_msg = "Empty stack"
    with pytest.raises(BTClibValueError, match=err_msg):
        sig_hash.from_tx([utxo], tx, 0, 0)
Beispiel #14
0
def test_wrapped_p2tr() -> None:

    script = [
        "OP_1",
        "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf",
    ]
    utxo = TxOut(
        100000000,
        serialize(["OP_HASH160",
                   hash160(serialize(script)), "OP_EQUAL"]))
    tx_in = TxIn(OutPoint(), serialize(script), 1, Witness(["0A" * 32]))
    tx = Tx(vin=[tx_in], vout=[TxOut(100000000, "")])

    err_msg = "Taproot scripts cannot be wrapped in p2sh"
    with pytest.raises(BTClibValueError, match=err_msg):
        sig_hash.from_tx([utxo], tx, 0, 0)
Beispiel #15
0
    def __init__(
        self,
        prev_out: OutPoint = OutPoint(),
        script_sig: Octets = b"",
        sequence: int = 0,
        script_witness: Witness = Witness(),
        check_validity: bool = True,
    ) -> None:

        self.prev_out = prev_out
        self.script_sig = bytes_from_octets(script_sig)
        self.sequence = sequence
        self.script_witness = script_witness

        if check_validity:
            self.assert_valid()
    def from_dict(cls: Type[_PsbtIn],
                  dict_: Mapping[str, Any],
                  check_validity: bool = True) -> _PsbtIn:

        return cls(
            Tx.from_dict(dict_["non_witness_utxo"], False)
            if dict_["non_witness_utxo"] else None,
            TxOut.from_dict(dict_["witness_utxo"], False)
            if dict_["witness_utxo"] else None,
            dict_["partial_signatures"],
            dict_["sign_hash"],
            dict_["redeem_script"],
            dict_["witness_script"],
            # FIXME
            decode_from_bip32_derivs(dict_["bip32_derivs"]),  # type: ignore
            dict_["final_script_sig"],
            Witness.from_dict(dict_["final_script_witness"], False),
            dict_["unknown"],
            check_validity,
        )
Beispiel #17
0
def test_invalid_taproot_key_path() -> None:
    fname = "tapscript_test_vector.json"
    filename = path.join(path.dirname(__file__), "_data", fname)
    with open(filename, "r", encoding="ascii") as file_:
        data = json.load(file_)

    for x in filter(lambda x: "failure" in x.keys(), data):

        tx = Tx.parse(x["tx"])
        prevouts = [TxOut.parse(prevout) for prevout in x["prevouts"]]
        index = x["index"]

        if not is_p2tr(prevouts[index].script_pub_key.script):
            continue

        witness = Witness(x["failure"]["witness"])
        tx.vin[index].script_witness = witness

        # check only key paths
        if (len(witness.stack) == 1
                or len(witness.stack) == 2 and witness.stack[-1][0] == 0x50):

            with pytest.raises(
                (BTClibRuntimeError, BTClibValueError, AssertionError)):

                assert not x["failure"]["scriptSig"]

                sighash_type = 0  # all
                signature = witness.stack[0][:64]
                if len(witness.stack[0]) == 65:
                    sighash_type = witness.stack[0][-1]
                    if sighash_type == 0:
                        raise BTClibValueError(
                            "invalid sighash 0 in 65 bytes signature")

                msg_hash = sig_hash.from_tx(prevouts, tx, index, sighash_type)

                pub_key = type_and_payload(
                    prevouts[index].script_pub_key.script)[1]

                ssa.assert_as_valid_(msg_hash, pub_key, signature)
Beispiel #18
0
def test_native_p2wsh() -> None:
    tx_bytes = "0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000"
    tx = Tx.parse(tx_bytes)
    tx.vin[1].script_witness = Witness([
        "21026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac"
    ])

    utxo = TxOut(
        4900000000,
        "00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0",
    )

    hash_ = sign_hash.from_utxo(utxo, tx, 1, sign_hash.SINGLE)
    assert hash_ == bytes.fromhex(
        "82dde6e4f1e94d02c2b7ad03d2115d691f48d064e9d52f58194a6637e4194391")

    script_ = sign_hash.witness_v0_script(
        tx.vin[1].script_witness.stack[-1])[1]
    hash_ = sign_hash.segwit_v0(script_, tx, 1, sign_hash.SINGLE, utxo.value)
    assert hash_ == bytes.fromhex(
        "fef7bd749cce710c5c052bd796df1af0d935e59cea63736268bcbe2d2134fc47")
Beispiel #19
0
    def parse(cls: Type["Tx"],
              data: BinaryData,
              check_validity: bool = True) -> "Tx":
        "Return a Tx by parsing binary data."

        stream = bytesio_from_binarydata(data)

        # version is a signed int (int32_t) in bitcoin_core
        # However there are at least two transactions:
        # 35e79ee733fad376e76d16d1f10088273c2f4c2eaba1374a837378a88e530005
        # c659729a7fea5071361c2c1a68551ca2bf77679b27086cc415adeeb03852e369
        # where the version number is negative if it is considered as a signed
        # integer. As such in btclib the version is an UNSIGNED integer.
        # This has been discussed in: https://github.com/bitcoin/bitcoin/pull/16525
        version = int.from_bytes(stream.read(4),
                                 byteorder="little",
                                 signed=False)

        segwit = stream.read(2) == _SEGWIT_MARKER
        if not segwit:
            # Change stream position: seek to byte offset relative to position
            stream.seek(-2, SEEK_CUR)  # current position

        n = var_int.parse(stream)
        vin = [TxIn.parse(stream) for _ in range(n)]

        n = var_int.parse(stream)
        vout = [TxOut.parse(stream) for _ in range(n)]

        if segwit:
            for tx_in in vin:
                tx_in.script_witness = Witness.parse(stream, check_validity)

        lock_time = int.from_bytes(stream.read(4),
                                   byteorder="little",
                                   signed=False)

        return cls(version, lock_time, vin, vout, check_validity)
Beispiel #20
0
def test_valid_taproot_key_path() -> None:
    fname = "tapscript_test_vector.json"
    filename = path.join(path.dirname(__file__), "_data", fname)
    with open(filename, "r", encoding="ascii") as file_:
        data = json.load(file_)

    for x in filter(lambda x: "TAPROOT" in x["flags"], data):

        tx = Tx.parse(x["tx"])

        prevouts = [TxOut.parse(prevout) for prevout in x["prevouts"]]
        index = x["index"]

        if not is_p2tr(prevouts[index].script_pub_key.script):
            continue

        assert not x["success"]["scriptSig"]

        witness = Witness(x["success"]["witness"])
        tx.vin[index].script_witness = witness

        if (len(witness.stack) == 1
                or len(witness.stack) == 2 and witness.stack[-1][0] == 0x50):

            sighash_type = 0  # all
            signature = witness.stack[0][:64]
            if len(witness.stack[0]) == 65:
                sighash_type = witness.stack[0][-1]
                assert sighash_type != 0

            msg_hash = sig_hash.from_tx(prevouts, tx, index, sighash_type)

            pub_key = type_and_payload(
                prevouts[index].script_pub_key.script)[1]

            ssa.assert_as_valid_(msg_hash, pub_key, signature)
Beispiel #21
0
def test_tx() -> None:
    # default constructor
    tx = Tx()
    assert not tx.is_segwit()
    assert not any(bool(w) for w in tx.vwitness)
    assert not any(bool(tx_in.script_witness) for tx_in in tx.vin)
    assert not tx.is_coinbase()
    assert tx.version == 1
    assert tx.lock_time == 0
    assert not tx.vin
    assert not tx.vout
    assert tx.nVersion == tx.version
    assert tx.nLockTime == tx.lock_time
    tx_id = "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43"
    assert tx.id.hex() == tx_id
    assert tx.hash == tx.id
    assert tx.size == 10
    assert tx.vsize == tx.size
    assert tx.weight == tx.size * 4

    tx_2 = Tx.from_dict(tx.to_dict())
    assert tx_2.is_segwit() == tx.is_segwit()
    assert tx_2 == tx

    tx_2 = Tx.parse(tx.serialize(include_witness=True))
    assert tx_2.is_segwit() == tx.is_segwit()
    assert tx_2 == tx

    tx_2 = Tx.parse(tx.serialize(include_witness=False))
    assert not tx_2.is_segwit()
    assert tx_2 == tx

    # non-default constructor, no segwit
    prev_out = OutPoint(
        "9dcfdb5836ecfe146bdaa896605ba21222f83cd014dd47adde14fab2aba7de9b", 1)
    script_sig = b""
    sequence = 0xFFFFFFFF
    tx_in = TxIn(prev_out, script_sig, sequence)

    tx_out1 = TxOut(2500000, "a914f987c321394968be164053d352fc49763b2be55c87")
    tx_out2 = TxOut(
        6381891,
        "0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d")
    version = 1
    lock_time = 0
    tx = Tx(version, lock_time, [tx_in], [tx_out1, tx_out2])
    assert not tx.is_segwit()
    assert not any(bool(w) for w in tx.vwitness)
    assert not any(bool(tx_in.script_witness) for tx_in in tx.vin)
    assert not tx.is_coinbase()
    assert tx.version == 1
    assert tx.lock_time == 0
    assert len(tx.vin) == 1
    assert len(tx.vout) == 2
    assert tx.nVersion == tx.version
    assert tx.nLockTime == tx.lock_time
    tx_id = "4e52f7848dab7dd89ef7ba477939574198a170bfcb2fb34355c69f5e0169f63c"
    assert tx.id.hex() == tx_id
    assert tx.hash == tx.id
    assert tx.size == 126
    assert tx.vsize == tx.size
    assert tx.weight == tx.size * 4

    tx_2 = Tx.from_dict(tx.to_dict())
    assert tx_2.is_segwit() == tx.is_segwit()
    assert tx_2 == tx

    tx_2 = Tx.parse(tx.serialize(include_witness=True))
    assert tx_2.is_segwit() == tx.is_segwit()
    assert tx_2 == tx

    tx_2 = Tx.parse(tx.serialize(include_witness=False))
    assert not tx_2.is_segwit()
    assert tx_2 == tx

    # non-default constructor, with segwit
    version = 1
    lock_time = 0
    tx = Tx(version, lock_time, [tx_in], [tx_out1, tx_out2])
    stack = [
        "",
        "30440220421fbbedf2ee096d6289b99973509809d5e09589040d5e0d453133dd11b2f78a02205686dbdb57e0c44e49421e9400dd4e931f1655332e8d078260c9295ba959e05d01",
        "30440220398f141917e4525d3e9e0d1c6482cb19ca3188dc5516a3a5ac29a0f4017212d902204ea405fae3a58b1fc30c5ad8ac70a76ab4f4d876e8af706a6a7b4cd6fa100f4401",
        "52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae",
    ]
    tx.vin[0].script_witness = Witness(stack)
    assert tx.is_segwit()
    assert any(bool(w) for w in tx.vwitness)
    assert any(bool(tx_in.script_witness) for tx_in in tx.vin)
    assert not tx.is_coinbase()
    assert tx.version == 1
    assert tx.lock_time == 0
    assert len(tx.vin) == 1
    assert len(tx.vout) == 2
    assert tx.nVersion == tx.version
    assert tx.nLockTime == tx.lock_time
    tx_id = "4e52f7848dab7dd89ef7ba477939574198a170bfcb2fb34355c69f5e0169f63c"
    assert tx.id.hex() == tx_id
    hash_ = "d39eb3e3954be4bdc0b3be2d980124b1e1e11fb414b886b52939b07d95a58a8f"
    assert tx.hash.hex() == hash_
    assert tx.size == 380
    assert tx.vsize == 190
    assert tx.weight == 758

    tx_2 = Tx.from_dict(tx.to_dict())
    assert tx_2.is_segwit() == tx.is_segwit()
    assert tx_2 == tx

    tx_2 = Tx.parse(tx.serialize(include_witness=True))
    assert tx_2.is_segwit() == tx.is_segwit()
    assert tx_2 == tx

    tx_2 = Tx.parse(tx.serialize(include_witness=False))
    assert not tx_2.is_segwit()
    assert tx_2 != tx
Beispiel #22
0
def test_exceptions() -> None:
    # from creator example
    psbt_str = "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA="

    psbt = Psbt.b64decode(psbt_str)
    psbt.outputs[0].redeem_script = "bad script"  # type: ignore
    with pytest.raises(TypeError):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.inputs[0].witness_script = "bad script"  # type: ignore
    with pytest.raises(TypeError):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.outputs[0].unknown = {"bad key": b""}  # type: ignore
    with pytest.raises(TypeError):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.outputs[0].unknown = {b"deadbeef": "bad value"}  # type: ignore
    with pytest.raises(TypeError):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.inputs[0].sig_hash_type = 101
    with pytest.raises(BTClibValueError, match="invalid sign_hash type: "):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.inputs[0].final_script_sig = "bad script"  # type: ignore
    with pytest.raises(TypeError):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    _, Q = dsa.gen_keys()
    pub_key = sec_point.bytes_from_point(Q)
    r = s = int.from_bytes(bytes.fromhex("FF" * 32),
                           byteorder="big",
                           signed=False)
    sig_bytes = der.Sig(r, s,
                        check_validity=False).serialize(check_validity=False)
    psbt.inputs[0].partial_sigs = {pub_key: sig_bytes}
    with pytest.raises(BTClibValueError, match="invalid partial signature: "):
        psbt.serialize()

    pub_key = bytes.fromhex("02" + 31 * "00" + "07")
    psbt.inputs[0].partial_sigs = {pub_key: sig_bytes}
    with pytest.raises(BTClibValueError,
                       match="invalid partial signature pub_key: "):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    err_msg = "invalid version: "
    psbt.version = -1
    with pytest.raises(BTClibValueError, match=err_msg):
        psbt.serialize()
    psbt.version = 0xFFFFFFFF + 1
    with pytest.raises(BTClibValueError, match=err_msg):
        psbt.serialize()
    psbt.version = 1
    # TODO: add to test vectors
    with pytest.raises(BTClibValueError, match="invalid non-zero version: "):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt_bin = psbt.serialize()
    psbt_bin = psbt_bin.replace(PSBT_SEPARATOR, PSBT_DELIMITER)
    # TODO: add to test vectors
    with pytest.raises(BTClibValueError,
                       match="malformed psbt: missing separator"):
        Psbt.parse(psbt_bin)

    psbt = Psbt.b64decode(psbt_str)
    psbt.inputs.pop()
    err_msg = "mismatched number of psb.tx.vin and psb.inputs: "
    # TODO: add to test vectors
    with pytest.raises(BTClibValueError, match=err_msg):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.tx.vin[0].script_witness = Witness([b""])
    err_msg = "non empty script_sig or witness"
    # TODO: add to test vectors
    with pytest.raises(BTClibValueError, match=err_msg):
        psbt.serialize()

    psbt = Psbt.b64decode(psbt_str)
    psbt.outputs.pop()
    err_msg = "mismatched number of psb.tx.vout and psbt.outputs: "
    # TODO: add to test vectors
    with pytest.raises(BTClibValueError, match=err_msg):
        psbt.serialize()

    psbt_str = "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA"
    psbt = Psbt.b64decode(psbt_str)
    psbt.tx.vin[0].prev_out.tx_id, psbt.tx.vin[1].prev_out.tx_id = (
        psbt.tx.vin[1].prev_out.tx_id,
        psbt.tx.vin[0].prev_out.tx_id,
    )
    err_msg = "mismatched non-witness utxo / outpoint tx_id"
    with pytest.raises(BTClibValueError, match=err_msg):
        psbt.assert_valid()
Beispiel #23
0
def test_tx_in() -> None:
    tx_in = TxIn()
    assert tx_in.prev_out == OutPoint()
    assert tx_in.script_sig == b""
    assert tx_in.sequence == 0
    assert tx_in.outpoint == tx_in.prev_out
    assert tx_in.scriptSig == tx_in.script_sig
    assert tx_in.nSequence == tx_in.nSequence
    assert tx_in.is_coinbase()
    assert not tx_in.is_segwit()
    tx_in2 = TxIn.parse(tx_in.serialize())
    assert not tx_in2.is_segwit()
    assert tx_in == tx_in2
    tx_in2 = TxIn.from_dict(tx_in.to_dict())
    assert not tx_in2.is_segwit()
    assert tx_in == tx_in2

    tx_id = "d5b5982254eebca64e4b42a3092a10bfb76ab430455b2bf0cf7c4f7f32db1c2e"
    vout = 0
    prev_out = OutPoint(tx_id, vout)
    script_sig = b""
    sequence = 0
    tx_in = TxIn(prev_out, script_sig, sequence)
    assert tx_in.prev_out == prev_out
    assert tx_in.script_sig == script_sig
    assert tx_in.sequence == sequence
    assert tx_in.outpoint == tx_in.prev_out
    assert tx_in.scriptSig == tx_in.script_sig
    assert tx_in.nSequence == tx_in.nSequence
    assert not tx_in.is_coinbase()
    assert not tx_in.is_segwit()
    tx_in2 = TxIn.parse(tx_in.serialize())
    assert not tx_in2.is_segwit()
    assert tx_in == tx_in2
    tx_in2 = TxIn.from_dict(tx_in.to_dict())
    assert not tx_in2.is_segwit()
    assert tx_in == tx_in2

    prev_out = OutPoint(
        "9dcfdb5836ecfe146bdaa896605ba21222f83cd014dd47adde14fab2aba7de9b", 1
    )
    script_sig = b""
    sequence = 0xFFFFFFFF
    tx_in = TxIn(prev_out, script_sig, sequence)
    stack = [
        "",
        "30440220421fbbedf2ee096d6289b99973509809d5e09589040d5e0d453133dd11b2f78a02205686dbdb57e0c44e49421e9400dd4e931f1655332e8d078260c9295ba959e05d01",
        "30440220398f141917e4525d3e9e0d1c6482cb19ca3188dc5516a3a5ac29a0f4017212d902204ea405fae3a58b1fc30c5ad8ac70a76ab4f4d876e8af706a6a7b4cd6fa100f4401",
        "52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae",
    ]
    tx_in.script_witness = Witness(stack)
    assert tx_in.prev_out == prev_out
    assert tx_in.script_sig == script_sig
    assert tx_in.sequence == sequence
    assert tx_in.outpoint == tx_in.prev_out
    assert tx_in.scriptSig == tx_in.script_sig
    assert tx_in.nSequence == tx_in.nSequence
    assert not tx_in.is_coinbase()
    assert tx_in.is_segwit()
    tx_in2 = TxIn.parse(tx_in.serialize())
    assert not tx_in2.is_segwit()
    assert tx_in == tx_in2 or TX_IN_COMPARES_WITNESS
    tx_in2 = TxIn.from_dict(tx_in.to_dict())
    assert tx_in2.is_segwit()
    assert tx_in == tx_in2

    assert tx_in != OutPoint()

    tx_in.sequence = 0xFFFFFFFF + 1
    with pytest.raises(BTClibValueError, match="invalid sequence: "):
        tx_in.assert_valid()
Beispiel #24
0
def test_witness() -> None:
    witness = Witness()
    assert not witness.stack
    assert len(witness) == 0
    witness.assert_valid()
    assert witness == Witness.parse(witness.serialize())
    assert witness == Witness.from_dict(witness.to_dict())

    stack = [
        "",
        "3044022077ecafa04bc23f87057bd54b572a473cf5cc6a945c167fcefe561618b86d097002200eb7c62a855295c8c288ff972c58905861a98260dafb6f8b7587cfda3091e00d01",
        "3045022100f20ba32865985e66985ba2d7ad11950309e253788b2edb27ccf5899e806f43ef02202899d98360f6476fcefbbf1dc1813595f4d0807d13237218de5ffaaeaa85640101",
        "304402206f7f5b0723d61f5d9f2ecbae448646d4cf0cf3ecade5ab50867fdfe8e131ce8f02207f0c260620e41dbdecd6ce574bf2773de248178d33f24aee71627843560137cd01",
        "01",
        "635321024713c6e66da107644c64ab84189840e78310b247cc7fa563d6f98f2a46900a0d21026cb4cc5bbde0e59806657b1780a9a3b333a8acb6fcac48ade7d52e2b34aa30042102b6615b55426b7362cd82897db26b1423e3732f98eaea5cd2c150c49a46003c6521033557edc1a6aec5a28648f6e22deb542e9ee8c9219d5bb5e81d0fe23c8f955ad221039d7f91444b2d4c4e89a1f550fa7d32c5d9b75a49b14c54f10109d95f637bb7de2103d9cdf5c6da8b2fd66fa918916cc93d831f16781c01ca759c9cf60acf94268bbd56ae67029000b275522102d02570ed9db9ee6abd13a6c269758debcfaa1aa6d0857553e5b6a5cf764ffe0a21030968209ccaaae1c0f8ee7a4a3594b3504fd3f89db1c259aedbdce3aba29f219321036069299a8a990474eb34786bf446e724088896a54bf848650c9543f18af602dc53ae68",
    ]
    witness = Witness(stack)
    assert len(witness) == 6
    witness.assert_valid()
    assert witness == Witness.parse(witness.serialize())
    assert witness == Witness.from_dict(witness.to_dict())
    def parse(
        cls: Type[_PsbtIn],
        input_map: Mapping[bytes, bytes],
        check_validity: bool = True,
    ) -> _PsbtIn:
        "Return a PsbtIn by parsing binary data."

        # FIX parse must use BinaryData

        non_witness_utxo = None
        witness_utxo = None
        partial_sigs: Dict[Octets, Octets] = {}
        sig_hash_type = None
        redeem_script = b""
        witness_script = b""
        hd_key_paths: Dict[Octets, BIP32KeyOrigin] = {}
        final_script_sig = b""
        final_script_witness = Witness()
        unknown: Dict[Octets, Octets] = {}

        for k, v in input_map.items():
            if k[:1] == PSBT_IN_NON_WITNESS_UTXO:
                if non_witness_utxo:
                    raise BTClibValueError("duplicate PsbtIn non_witness_utxo")
                non_witness_utxo = deserialize_tx(k, v, "non-witness utxo")
            elif k[:1] == PSBT_IN_WITNESS_UTXO:
                if witness_utxo:
                    raise BTClibValueError("duplicate PsbtIn witness_utxo")
                witness_utxo = _deserialize_witness_utxo(k, v)
            elif k[:1] == PSBT_IN_PARTIAL_SIG:
                if k[1:] in partial_sigs:
                    raise BTClibValueError("duplicate PsbtIn partial_sigs")
                partial_sigs[k[1:]] = v
            elif k[:1] == PSBT_IN_SIG_HASH_TYPE:
                if sig_hash_type:
                    raise BTClibValueError("duplicate PsbtIn sig_hash_type")
                sig_hash_type = deserialize_int(k, v, "sign_hash type")
            elif k[:1] == PSBT_IN_REDEEM_SCRIPT:
                if redeem_script:
                    raise BTClibValueError("duplicate PsbtIn redeem_script")
                redeem_script = deserialize_bytes(k, v, "redeem script")
            elif k[:1] == PSBT_IN_WITNESS_SCRIPT:
                if witness_script:
                    raise BTClibValueError("duplicate PsbtIn witness_script")
                witness_script = deserialize_bytes(k, v, "witness script")
            elif k[:1] == PSBT_IN_BIP32_DERIVATION:
                if k[1:] in hd_key_paths:
                    raise BTClibValueError(
                        "duplicate pub_key in PsbtIn hd_key_path")
                hd_key_paths[k[1:]] = BIP32KeyOrigin.parse(v)
            elif k[:1] == PSBT_IN_FINAL_SCRIPTSIG:
                if final_script_sig:
                    raise BTClibValueError("duplicate PsbtIn final_script_sig")
                final_script_sig = deserialize_bytes(k, v, "final script_sig")
            elif k[:1] == PSBT_IN_FINAL_SCRIPTWITNESS:
                if final_script_witness:
                    raise BTClibValueError(
                        "duplicate PsbtIn final_script_witness")
                final_script_witness = _deserialize_final_script_witness(k, v)
            else:  # unknown
                if k in unknown:
                    raise BTClibValueError("duplicate PsbtIn unknown")
                unknown[k] = v

        return cls(
            non_witness_utxo,
            witness_utxo,
            partial_sigs,
            sig_hash_type,
            redeem_script,
            witness_script,
            hd_key_paths,
            final_script_sig,
            final_script_witness,
            unknown,
            check_validity,
        )
Beispiel #26
0
    def parse(
        cls: Type["PsbtIn"],
        input_map: Mapping[bytes, bytes],
        check_validity: bool = True,
    ) -> "PsbtIn":
        "Return a PsbtIn by parsing binary data."

        # FIX parse must use BinaryData

        non_witness_utxo = None
        witness_utxo = None
        partial_sigs: Dict[Octets, Octets] = {}
        sig_hash_type = None
        redeem_script = b""
        witness_script = b""
        hd_key_paths: Dict[Octets, BIP32KeyOrigin] = {}
        final_script_sig = b""
        final_script_witness = Witness()
        ripemd160_preimages: Dict[Octets, Octets] = {}
        sha256_preimages: Dict[Octets, Octets] = {}
        hash160_preimages: Dict[Octets, Octets] = {}
        hash256_preimages: Dict[Octets, Octets] = {}
        unknown: Dict[Octets, Octets] = {}

        for k, v in input_map.items():
            if k[:1] == PSBT_IN_NON_WITNESS_UTXO:
                non_witness_utxo = deserialize_tx(k, v, "non-witness utxo")
            elif k[:1] == PSBT_IN_WITNESS_UTXO:
                witness_utxo = _deserialize_witness_utxo(k, v)
            elif k[:1] == PSBT_IN_PARTIAL_SIG:
                partial_sigs[k[1:]] = v
            elif k[:1] == PSBT_IN_SIG_HASH_TYPE:
                sig_hash_type = deserialize_int(k, v, "sig_hash type")
            elif k[:1] == PSBT_IN_REDEEM_SCRIPT:
                redeem_script = deserialize_bytes(k, v, "redeem script")
            elif k[:1] == PSBT_IN_WITNESS_SCRIPT:
                witness_script = deserialize_bytes(k, v, "witness script")
            elif k[:1] == PSBT_IN_BIP32_DERIVATION:
                hd_key_paths[k[1:]] = BIP32KeyOrigin.parse(v)
            elif k[:1] == PSBT_IN_FINAL_SCRIPTSIG:
                final_script_sig = deserialize_bytes(k, v, "final script_sig")
            elif k[:1] == PSBT_IN_RIPEMD160:
                ripemd160_preimages[k[1:]] = v
            elif k[:1] == PSBT_IN_SHA256:
                sha256_preimages[k[1:]] = v
            elif k[:1] == PSBT_IN_HASH160:
                hash160_preimages[k[1:]] = v
            elif k[:1] == PSBT_IN_HASH256:
                hash256_preimages[k[1:]] = v
            elif k[:1] == PSBT_IN_FINAL_SCRIPTWITNESS:
                final_script_witness = _deserialize_final_script_witness(k, v)
            else:  # unknown
                unknown[k] = v

        return cls(
            non_witness_utxo,
            witness_utxo,
            partial_sigs,
            sig_hash_type,
            redeem_script,
            witness_script,
            hd_key_paths,
            final_script_sig,
            final_script_witness,
            ripemd160_preimages,
            sha256_preimages,
            hash160_preimages,
            hash256_preimages,
            unknown,
            check_validity,
        )