Exemple #1
0
def test_creation() -> None:
    psbt_str = "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA="
    psbt = Psbt.b64decode(psbt_str)
    assert psbt.b64encode() == psbt_str

    output_1 = TxOut(
        149990000,
        ScriptPubKey("0014d85c2b71d0060b09c9886aeb815e50991dda124d"))
    output_2 = TxOut(
        100000000,
        ScriptPubKey("001400aea9a2e5f0f876a588df5546e8742d1d87008f"))
    input_1 = TxIn(
        OutPoint(
            "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858",
            0),
        b"",
        0xFFFFFFFF,
    )
    input_2 = TxIn(
        OutPoint(
            "1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83",
            1),
        b"",
        0xFFFFFFFF,
    )
    transaction = Tx(2, 0, [input_1, input_2], [output_1, output_2])
    psbt_from_tx_ = Psbt.from_tx(transaction)
    assert psbt_from_tx_ == psbt
def test_p2pk() -> None:
    pub_key = "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"
    signature = "304402200A5C6163F07B8D3B013C4D1D6DBA25E780B39658D79BA37AF7057A3B7F15FFA102201FD9B4EAA9943F734928B99A83592C2E7BF342EA2680F6A2BB705167966B742001"
    script_pub_key = serialize([pub_key, "OP_CHECKSIG"])
    script_sig = serialize([signature])

    founding_tx_script = serialize(["OP_0", "OP_0"])
    tx_in = TxIn(OutPoint(b"\x00" * 32, 0xFFFFFFFF), founding_tx_script, 0xFFFFFFFF)
    funding_tx = Tx(1, 0, [tx_in], [TxOut(0, script_pub_key)])

    tx_in = TxIn(OutPoint(funding_tx.id, 0), script_sig, 0xFFFFFFFF)
    receiving_tx = Tx(1, 0, [tx_in], [TxOut(0, b"")])
    hash_ = sig_hash.from_tx(funding_tx.vout, receiving_tx, 0, sig_hash.ALL)
    assert dsa.verify_(hash_, pub_key, bytes.fromhex(signature)[:-1])
Exemple #3
0
def test_p2pk_anyonecanpay() -> None:
    pub_key = "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf"
    signature = "304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281"
    script_pub_key = serialize([pub_key, "OP_CHECKSIG"])
    script_sig = serialize([signature])

    founding_tx_script = serialize(["OP_0", "OP_0"])
    tx_in = TxIn(OutPoint(b"\x00" * 32, 0xFFFFFFFF), founding_tx_script,
                 0xFFFFFFFF)
    funding_tx = Tx(1, 0, [tx_in], [TxOut(0, script_pub_key)])

    tx_in = TxIn(OutPoint(funding_tx.id, 0), script_sig, 0xFFFFFFFF)
    receiving_tx = Tx(1, 0, [tx_in], [TxOut(0, b"")])
    hash_ = sig_hash.from_tx(funding_tx.vout, receiving_tx, 0,
                             sig_hash.ANYONECANPAY | sig_hash.ALL)
    assert dsa.verify_(hash_, pub_key, bytes.fromhex(signature)[:-1])
Exemple #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)
Exemple #5
0
def test_legacy_p2pkh() -> None:
    pub_key = "04280c8f66bf2ccaeb3f60a19ad4a06365f8bd6178aab0e709df2173df8f553366549aec336aae8742a84702b6c7c3052d89f5d76d535ec3716e72187956351613"
    signature = "3045022100ea43c4800d1a860ec89b5273898a146cfb01d34ff4c364d24a110c480d0e3f7502201c82735577f932f1ca8e1c54bf653e0f8e74e408fe83666bc85cac4472ec950801"
    script_sig = serialize([signature, pub_key])
    out_point = OutPoint(
        "d8343a35ba951684f2969eafe833d9e6fe436557b9707ae76802875952e860fc", 1)
    tx_in = TxIn(out_point, script_sig, 0xFFFFFFFF)
    tx_out1 = TxOut(
        2017682,
        bytes.fromhex("76a91413bd20236d0da56492c325dce289b4da35b4b5bd88ac"))
    tx_out2 = TxOut(
        1049154982,
        bytes.fromhex("76a914da169b45781ca210f8c11617ba66bd843da76b1688ac"))
    tx = Tx(1, 0, [tx_in], [tx_out1, tx_out2])

    script_pub_key = serialize([
        "OP_DUP",
        "OP_HASH160",
        "82ac30f58baf99ec9d14e6181eee076f4e27f69c",
        "OP_EQUALVERIFY",
        "OP_CHECKSIG",
    ])
    utxo = TxOut(1051173696, script_pub_key)
    hash_ = sig_hash.from_tx([utxo], tx, 0, sig_hash.ALL)
    assert dsa.verify_(hash_, pub_key, bytes.fromhex(signature)[:-1])
Exemple #6
0
def test_dataclasses_json_dict() -> None:
    fname = "d4f3c2c3c218be868c77ae31bedb497e2f908d6ee5bbbe91e4933e6da680c970.bin"
    filename = path.join(path.dirname(__file__), "_data", fname)
    with open(filename, "rb") as binary_file_:
        temp = Tx.parse(binary_file_.read())

    tx_in = temp.vin[0]

    # TxIn dataclass
    assert isinstance(tx_in, TxIn)

    # TxIn dataclass to dict
    tx_in_dict = tx_in.to_dict()
    assert isinstance(tx_in_dict, dict)

    # TxIn dataclass dict to file
    datadir = path.join(path.dirname(__file__), "_generated_files")
    filename = path.join(datadir, "tx_in.json")
    with open(filename, "w") as file_:
        json.dump(tx_in_dict, file_, indent=4)

    # TxIn dataclass dict from file
    with open(filename, "r") as file_:
        tx_dict2 = json.load(file_)
    assert isinstance(tx_dict2, dict)

    assert tx_in_dict == tx_dict2

    # TxIn dataclass from dict
    tx_in2 = TxIn.from_dict(tx_in_dict)
    assert isinstance(tx_in2, TxIn)

    assert tx_in == tx_in2
Exemple #7
0
def test_output_scripts_serialization() -> None:
    input_1 = TxIn(
        OutPoint(
            "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858",
            0),
        b"",
        0xFFFFFFFF,
    )
    output_1 = TxOut(
        149990000,
        bytes.fromhex("a914256b3a9ae8145e5094329537dd4d7a25dbc9452087"))
    output_2 = TxOut(
        100000000,
        bytes.fromhex("001400aea9a2e5f0f876a588df5546e8742d1d87008f"))
    tx = Tx(2, 0, [input_1], [output_1, output_2])

    psbt = Psbt.from_tx(tx)

    # p2sh-p2wsh
    psbt.outputs[0].redeem_script = bytes.fromhex(
        "003BD89EE628E6EB745F99DF1E4AEF64A0DAA814850DAA509F30C0F472E0563C7A")
    psbt.outputs[0].witness_script = bytes.fromhex(
        "522103dcea327ff7b2b4449413d9dc24cef0cc9e7864bad9d6291f3f1a04b639422c312103a2c5199b333adfaed4fea7ab65485b9e23a6cb317ddae7e8c1f2bd673414bdd352ae"
    )

    assert Psbt.b64decode(psbt.b64encode()) == psbt
Exemple #8
0
    def from_dict(cls: Type["Tx"],
                  dict_: Mapping[str, Any],
                  check_validity: bool = True) -> "Tx":

        return cls(
            dict_["version"],
            dict_["locktime"],
            [TxIn.from_dict(tx_in, False) for tx_in in dict_["vin"]],
            [TxOut.from_dict(tx_out, False) for tx_out in dict_["vout"]],
            check_validity,
        )
Exemple #9
0
def test_p2pkh() -> None:
    pub_key = "038282263212C609D9EA2A6E3E172DE238D8C39CABD5AC1CA10646E23FD5F51508"
    signature = "304402206E05A6FE23C59196FFE176C9DDC31E73A9885638F9D1328D47C0C703863B8876022076FEB53811AA5B04E0E79F938EB19906CC5E67548BC555A8E8B8B0FC603D840C01"
    script_pub_key = serialize([
        "OP_DUP",
        "OP_HASH160",
        "1018853670F9F3B0582C5B9EE8CE93764AC32B93",
        "OP_EQUALVERIFY",
        "OP_CHECKSIG",
    ])
    script_sig = serialize([signature, pub_key])

    founding_tx_script = serialize(["OP_0", "OP_0"])
    tx_in = TxIn(OutPoint(b"\x00" * 32, 0xFFFFFFFF), founding_tx_script,
                 0xFFFFFFFF)
    funding_tx = Tx(1, 0, [tx_in], [TxOut(0, script_pub_key)])

    tx_in = TxIn(OutPoint(funding_tx.id, 0), script_sig, 0xFFFFFFFF)
    receiving_tx = Tx(1, 0, [tx_in], [TxOut(0, b"")])
    hash_ = sig_hash.from_tx(funding_tx.vout, receiving_tx, 0, sig_hash.ALL)
    assert dsa.verify_(hash_, pub_key, bytes.fromhex(signature)[:-1])
Exemple #10
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)
Exemple #11
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)
Exemple #12
0
def test_psbt() -> None:
    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])
    psbt = Psbt.from_tx(tx)
    assert psbt == Psbt.parse(psbt.serialize())
    assert psbt == Psbt.from_dict(psbt.to_dict())
Exemple #13
0
def test_valid_sign_2() -> None:
    psbt_str = "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriIGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GELSmumcAAACAAAAAgAQAAIAiBgPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvRC0prpnAAAAgAAAAIAFAACAAAA="
    psbt = Psbt.b64decode(psbt_str)
    assert psbt.b64encode() == psbt_str

    transaction_input = TxIn(
        OutPoint(
            "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858",
            0),
        b"",
        0xFFFFFFFF,
    )
    assert psbt.inputs[0].witness_utxo is not None
    # pylance cannot grok the following line, even considering the above line
    transaction = Tx(1, 2, [transaction_input],
                     [psbt.inputs[0].witness_utxo])  # type: ignore
    psbt.tx.vin[0].prev_out.tx_id = transaction.id
    psbt.inputs[0].non_witness_utxo = transaction
    psbt.assert_signable()
Exemple #14
0
def test_coinbase_block_1() -> None:

    coinbase_out = "00f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac"
    tx_out = TxOut.parse(coinbase_out)
    assert tx_out.serialize().hex() == coinbase_out

    coinbase_inp = (  # prev_out
        "0000000000000000000000000000000000000000000000000000000000000000ffffffff"
        "0704ffff001d0104"  # script_sig
        "ffffffff"  # sequence
    )
    tx_in = TxIn.parse(coinbase_inp)
    assert tx_in.serialize().hex() == coinbase_inp
    assert tx_in.prev_out.is_coinbase

    coinbase = "01000000" "01" + coinbase_inp + "01" + coinbase_out + "00000000"
    tx = Tx.parse(coinbase)
    assert tx.serialize(include_witness=True).hex() == coinbase
    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) == 1

    assert tx.vin[0].script_sig == tx_in.script_sig
    assert tx.vout[0].script_pub_key == tx_out.script_pub_key

    tx_id = "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
    assert tx.id.hex() == tx_id
    assert tx.id == tx.hash

    assert tx.size == 134
    assert tx.vsize == tx.size
    assert tx.weight == tx.size * 4
    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 tx.is_coinbase()
Exemple #15
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)
Exemple #16
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
Exemple #17
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()