Exemplo n.º 1
0
def test_exceptions() -> None:

    script_pub_key: List[Command] = ["OP_2", "OP_3", "OP_ADD", "OP_5", "OP_RETURN_244"]
    err_msg = "invalid string command: OP_RETURN_244"
    with pytest.raises(BTClibValueError, match=err_msg):
        serialize(script_pub_key)

    with pytest.raises(TypeError):
        serialize(["OP_2", "OP_3", "OP_ADD", "OP_5", serialize])  # type: ignore

    err_msg = "too many bytes for OP_PUSHDATA: "
    with pytest.raises(BTClibValueError, match=err_msg):
        script_pub_key = ["1f" * 521, "OP_DROP"]
        serialize(script_pub_key)

    # A script_pub_key with OP_PUSHDATA4 can't be decoded
    script_bytes = "4e09020000" + "0A" * 521 + "75"  # ['0A'*521, 'OP_DROP']
    err_msg = "Invalid pushdata length: "
    with pytest.raises(BTClibValueError, match=err_msg):
        parse(script_bytes)

    # and can't be encoded
    script_pub_key_ = ["0A" * 521, "OP_DROP"]
    err_msg = "too many bytes for OP_PUSHDATA: "
    with pytest.raises(BTClibValueError, match=err_msg):
        serialize(script_pub_key_)
def test_nulldata() -> None:

    scripts: List[List[Command]] = [["OP_RETURN", "11" * 79],
                                    ["OP_RETURN", "00" * 79]]
    for script_pub_key in scripts:
        assert script_pub_key == parse(serialize(script_pub_key))
        assert script_pub_key == parse(serialize(script_pub_key).hex())
Exemplo n.º 3
0
def test_null_serialization() -> None:

    empty_script: List[Command] = []
    assert empty_script == parse(b"")
    assert serialize(empty_script) == b""

    assert parse(serialize([""])) == ["OP_0"]
    assert parse(serialize([" "])) == ["OP_0"]
    assert parse(serialize([b""])) == ["OP_0"]
    assert parse(serialize([b" "])) == ["20"]

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")

        assert serialize([0]) == b"\x01\x00"
        assert parse(serialize([0])) == ["00"]

        assert serialize([16]) == b"\x01\x10"
        assert serialize([17]) == b"\x01\x11"
        assert parse(serialize([16])) == ["10"]
        assert parse(serialize([17])) == ["11"]

    assert serialize(["10"]) == b"\x01\x10"
    assert serialize(["11"]) == b"\x01\x11"

    assert serialize(["OP_16"]) == b"\x60"
    assert parse(serialize(["OP_16"])) == ["OP_16"]
def test_simple_scripts() -> None:
    script_list: List[List[Command]] = [
        ["OP_2", "OP_3", "OP_ADD", "OP_5", "OP_EQUAL"],
        [0x1ADD, "OP_1ADD", 0x1ADE, "OP_EQUAL"],
        [26, "OP_1NEGATE", "OP_ADD", 26, "OP_EQUAL"],
        [0x7FFFFFFF, "OP_1NEGATE", "OP_ADD", 0x7FFFFFFF, "OP_EQUAL"],
        [0x80000000, "OP_1NEGATE", "OP_ADD", 0x7FFFFFFF, "OP_EQUAL"],
        [0xFFFFFFFF - 1, "OP_1NEGATE", "OP_ADD", 0x7FFFFFFF, "OP_EQUAL"],
        [0xFFFFFFFF, "OP_1NEGATE", "OP_ADD", 0x7FFFFFFF, "OP_EQUAL"],
        ["1F" * 250, "OP_DROP"],
        ["1F" * 520, "OP_DROP"],
    ]
    for script_pub_key in script_list:
        assert script_pub_key == parse(serialize(script_pub_key))
        assert script_pub_key == parse(serialize(script_pub_key).hex())
Exemplo n.º 5
0
def test_p2ms_3() -> None:
    # tx_id 33ac2af1a6f894276713b59ed09ce1a20fed5b36d169f20a3fe831dc45564d57
    # output n 0
    keys: List[Command] = [
        "036D568125A969DC78B963B494FA7ED5F20EE9C2F2FC2C57F86C5DF63089F2ED3A",
        "03FE4E6231D614D159741DF8371FA3B31AB93B3D28A7495CDAA0CD63A2097015C7",
    ]
    cmds: List[Command] = ["OP_1", *keys, "OP_2", "OP_CHECKMULTISIG"]
    script_pub_key = ScriptPubKey(serialize(cmds))
    assert script_pub_key == ScriptPubKey.p2ms(1, keys)

    pub_keys = script_pub_key.addresses
    exp_pub_keys = [
        "1Ng4YU2e2H3E86syX2qrsmD9opBHZ42vCF",
        "14XufxyGiY6ZBJsFYHJm6awdzpJdtsP1i3",
    ]
    for pub_key, key, exp_pub_key in zip(pub_keys, keys, exp_pub_keys):
        assert pub_key == b58.p2pkh(key)
        assert pub_key == exp_pub_key

    # tx 56214420a7c4dcc4832944298d169a75e93acf9721f00656b2ee0e4d194f9970
    # input n 1
    cmds_sig: List[Command] = [
        "OP_0",
        "3045022100dba1e9b1c8477fd364edcc1f81845928202daf465a1e2d92904c13c88761cbd002200add6af863dfdb7efb95f334baec041e90811ae9d81624f9f87f33a56761f29401",
    ]
    script_sig = Script(serialize(cmds_sig))
    script = script_sig + script_pub_key
    # parse(serialize(*)) is to enforce same string case convention
    assert script.asm == parse(serialize(cmds_sig + cmds))
Exemplo n.º 6
0
def test_regressions() -> None:
    script_list: List[List[Command]] = [
        [1],
        ["OP_1"],
        [51],
        [b"\x01"],
        ["01"],
        ["AA"],
        ["aa"],
        ["AAAA"],
        [0],
        [""],
        [b""],
        ["OP_0"],
        [-1],
        ["OP_1NEGATE"],
        [0x81],
        ["81"],
    ]
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")

        for s in script_list:
            serialized = serialize(s)
            assert serialize(parse(serialized)) == serialized
Exemplo n.º 7
0
def test_op_int_serialization() -> None:

    for i in range(-1, 17):
        op_int_str = f"OP_{i}" if i > -1 else "OP_1NEGATE"
        serialized_op_int = serialize([op_int_str])
        assert len(serialized_op_int) == 1
        assert [op_int_str] == parse(serialized_op_int)
Exemplo n.º 8
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)
Exemplo n.º 9
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)
Exemplo n.º 10
0
def test_single_byte_serialization() -> None:

    for i in range(256):
        hex_str = hex_string(i)  # e.g., "1A"
        serialized_byte = serialize([hex_str])
        assert len(serialized_byte) == 2
        assert serialized_byte[0] == 1
        assert [hex_str] == parse(serialized_byte)
Exemplo n.º 11
0
def test_integer_serialization() -> None:

    assert ["OP_0"] == parse(b"\x00")

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        assert serialize([0]) != b"\x00"
        for i in range(1, 17):
            serialized_int = serialize([i])
            assert [hex_string(i)] == parse(serialized_int)

    for i in range(17, 128):
        serialized_int = serialize([i])  # e.g., i = 26
        assert [hex_string(i)] == parse(serialized_int)

    for i in range(128, 256):
        serialized_int = serialize([i])
Exemplo n.º 12
0
def convert_script_tree(script_tree):
    if isinstance(script_tree, list):
        new_script_tree = []
        for x in script_tree:
            new_script_tree.append(convert_script_tree(x))
        return new_script_tree
    if isinstance(script_tree, dict):
        leaf = [[script_tree["leafVersion"], parse(script_tree["script"])]]
        return leaf
    return []
Exemplo n.º 13
0
def legacy_script(script_pub_key: Octets) -> List[bytes]:
    script_s: List[bytes] = []
    current_script: List[Command] = []
    for token in parse(script_pub_key)[::-1]:
        if token == "OP_CODESEPARATOR":  # nosec required for python < 3.8
            script_s.append(serialize(current_script[::-1]))
        else:
            current_script.append(token)
    script_s.append(serialize(current_script[::-1]))
    return script_s[::-1]
Exemplo n.º 14
0
def test_opcode_length() -> None:
    err_msg = "Invalid pushdata length"
    with pytest.raises(BTClibValueError, match=err_msg):
        parse(b"\x4e\x00")
    with pytest.raises(BTClibValueError, match=err_msg):
        parse(b"\x40\x00")

    assert parse(b"\x01\x00\x50") == [0, "OP_SUCCESS80"]
    assert parse(b"\x01\x00\x50", exit_on_op_success=True) == ["OP_SUCCESS"]
Exemplo n.º 15
0
def test_opcode_length() -> None:
    err_msg = "Not enough data for pushdata length"
    with pytest.raises(BTClibValueError, match=err_msg):
        parse(b"\x4e\x00")
    err_msg = "Not enough data for pushdata"
    with pytest.raises(BTClibValueError, match=err_msg):
        parse(b"\x40\x00")

    assert parse(b"\x01\x00\x50")[1] == "OP_SUCCESS80"
    assert parse(b"\x01\x00\x50", exit_on_op_success=True) == ["OP_SUCCESS"]
Exemplo n.º 16
0
def witness_v0_script(script_pub_key: Octets) -> List[bytes]:
    script_type, payload = type_and_payload(script_pub_key)

    if script_type == "p2wpkh":
        script = serialize(
            ["OP_DUP", "OP_HASH160", payload, "OP_EQUALVERIFY", "OP_CHECKSIG"])
        return [script]

    script_s: List[bytes] = []
    current_script: List[Command] = []
    for token in parse(script_pub_key)[::-1]:
        if token == "OP_CODESEPARATOR":  # nosec required for python < 3.8
            script_s.append(serialize(current_script[::-1]))
        current_script.append(token)
    script_s.append(serialize(current_script[::-1]))
    return script_s[::-1]
Exemplo n.º 17
0
def test_nulldata4() -> None:

    script_: List[Command] = [
        "OP_RETURN",
        "OP_RETURN",
        "OP_3",
        "OP_1",
        "OP_VERIF",
        "OP_0",
        "OP_3",
    ]
    # FIXME: serialization is not 0x6A{1 byte data-length}{data 6 bytes)}
    script_pub_key = serialize(script_)
    assert len(script_pub_key) == 7
    assert parse(script_pub_key) == script_
    script_type, _ = type_and_payload(script_pub_key)
    # FIXME: it should be "nulldata"
    assert script_type == "unknown"
Exemplo n.º 18
0
def test_encoding() -> None:
    script_bytes = b"jKBIP141 \\o/ Hello SegWit :-) keep it strong! LLAP Bitcoin twitter.com/khs9ne"
    assert serialize(parse(script_bytes)) == script_bytes