def test_p2ms_2() -> None: m = 1 # all uncompressed pub_key0 = "04 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" pub_key1 = "04 61cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d765 19aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af" pub_key2 = "04 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" uncompressed_pub_keys: List[Key] = [pub_key0, pub_key1, pub_key2] # mixed compressed / uncompressed public keys pub_key0 = "04 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" pub_key1 = "03 61cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d765" pub_key2 = "02 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" mixed_pub_keys: List[Key] = [pub_key0, pub_key1, pub_key2] for pub_keys in (uncompressed_pub_keys, mixed_pub_keys): for lexi_sort in (True, False): script_pub_key = ScriptPubKey.p2ms(m, pub_keys, lexi_sort=lexi_sort).script assert is_p2ms(script_pub_key) assert address(script_pub_key) == "" script_type, payload = type_and_payload(script_pub_key) assert script_type == "p2ms" assert payload == script_pub_key[:-1]
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))
def test_bip67() -> None: "BIP67 test vectors https://en.bitcoin.it/wiki/BIP_0067" data_folder = path.join(path.dirname(__file__), "_data") filename = path.join(data_folder, "bip67_test_vectors.json") with open(filename, "r") as file_: # json.dump(test_vectors, f, indent=4) test_vectors = json.load(file_) m = 2 for i in test_vectors: keys, addr = test_vectors[i] script_pub_key = ScriptPubKey.p2ms(m, keys, lexi_sort=True).script assert is_p2ms(script_pub_key) assert address(script_pub_key) == "" script_type, payload = type_and_payload(script_pub_key) assert script_type == "p2ms" assert payload == script_pub_key[:-1] errmsg = f"Test vector #{i}" assert addr == b58.p2sh(script_pub_key), errmsg
def test_p2ms_1() -> None: # self-consistency pub_key0 = "04 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" pub_key1 = "04 61cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d765 19aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af" # documented test case: https://learnmeabitcoin.com/guide/p2ms script_pub_key = bytes.fromhex( # fmt: off "51" # OP_1 "41" # canonical 65-bytes push + pub_key0 + "41" # noqa E148 # canonical 65-bytes push + pub_key1 + "52" # noqa E148 # OP_2 "ae" # OP_CHECKMULTISIG ) # fmt: on assert is_p2ms(script_pub_key) assert address(script_pub_key) == "" script_type, payload = type_and_payload(script_pub_key) assert script_type == "p2ms" assert payload == script_pub_key[:-1] pub_keys: List[Key] = [pub_key0, pub_key1] assert script_pub_key == ScriptPubKey.p2ms(1, pub_keys, lexi_sort=False).script err_msg = "invalid m in m-of-n: " with pytest.raises(BTClibValueError, match=err_msg): ScriptPubKey.p2ms(4, pub_keys) err_msg = "invalid n in m-of-n: " with pytest.raises(BTClibValueError, match=err_msg): # pylance cannot grok the following line ScriptPubKey.p2ms(4, [pub_key0] * 17) # type: ignore err_msg = "invalid m in m-of-n: " with pytest.raises(BTClibValueError, match=err_msg): ScriptPubKey.p2ms(0, pub_keys) err_msg = "invalid m in m-of-n: " with pytest.raises(BTClibValueError, match=err_msg): ScriptPubKey.p2ms(17, pub_keys) err_msg = "not a private or public key: " with pytest.raises(BTClibValueError, match=err_msg): ScriptPubKey.p2ms(1, [pub_key0 + "00", pub_key1]) script_: List[Command] = [ "OP_1", pub_key0 + "00", pub_key1, "OP_2", "OP_CHECKMULTISIG", ] script_pub_key = serialize(script_) assert not is_p2ms(script_pub_key) err_msg = "invalid key in p2ms" script_pub_key = serialize( ["OP_1", pub_key0, "00", "OP_2", "OP_CHECKMULTISIG"]) assert not is_p2ms(script_pub_key) script_pub_key = serialize( ["OP_1", pub_key0, pub_key1, "OP_2", "OP_CHECKMULTISIG"]) assert is_p2ms(script_pub_key) script_pub_key = serialize( ["OP_2", pub_key0, pub_key1, "OP_2", "OP_CHECKMULTISIG"]) assert is_p2ms(script_pub_key) script_pub_key = serialize( ["OP_0", pub_key0, pub_key1, "OP_2", "OP_CHECKMULTISIG"]) assert not is_p2ms(script_pub_key) script_pub_key = serialize( ["OP_3", pub_key0, pub_key1, "OP_2", "OP_CHECKMULTISIG"]) assert not is_p2ms(script_pub_key) script_pub_key = serialize(["OP_1", "OP_2", "OP_CHECKMULTISIG"]) assert not is_p2ms(script_pub_key) script_pub_key = serialize(["OP_1", pub_key0, "OP_2", "OP_CHECKMULTISIG"]) assert not is_p2ms(script_pub_key) script_pub_key = serialize( ["OP_1", pub_key0, pub_key1, "OP_3", "OP_CHECKMULTISIG"]) assert not is_p2ms(script_pub_key) pub_key2 = "04 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" script_pub_key = serialize( ["OP_1", pub_key0, pub_key1, pub_key2, "OP_3", "OP_CHECKMULTISIG"]) assert_p2ms(script_pub_key) err_msg = "invalid p2ms script_pub_key size" with pytest.raises(BTClibValueError, match=err_msg): assert_p2ms(script_pub_key[:133] + b"\x40" + script_pub_key[134:]) with pytest.raises(BTClibValueError, match=err_msg): assert_p2ms(script_pub_key[:-2] + b"\x00" + script_pub_key[-2:])