def test_slip132_test_vectors() -> None: """SLIP132 test vector https://github.com/satoshilabs/slips/blob/master/slip-0132.md """ mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" kpath = "m/0/0" test_vectors: List[Tuple[bytes, str, str, str, str]] = [ ( NETWORKS["mainnet"].bip32_prv, "m / 44h / 0h / 0h", "xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb", "xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj", "1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA", ), ( NETWORKS["mainnet"].slip132_p2wpkh_p2sh_prv, "m / 49h / 0h / 0h", "yprvAHwhK6RbpuS3dgCYHM5jc2ZvEKd7Bi61u9FVhYMpgMSuZS613T1xxQeKTffhrHY79hZ5PsskBjcc6C2V7DrnsMsNaGDaWev3GLRQRgV7hxF", "ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP", "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf", ), ( NETWORKS["mainnet"].slip132_p2wpkh_prv, "m / 84h / 0h / 0h", "zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE", "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", ), ] for version, der_path, prv, pub, addr in test_vectors: rxprv = bip39.mxprv_from_mnemonic(mnemonic, "") mxprv = bip32.derive(rxprv, der_path, version) assert prv == mxprv mxpub = bip32.xpub_from_xprv(mxprv) assert pub == mxpub xpub = bip32.derive(mxpub, kpath) address = slip132.address_from_xpub(xpub) assert addr == address address = slip132.address_from_xkey(xpub) assert addr == address xprv = bip32.derive(mxprv, kpath) address = slip132.address_from_xkey(xprv) assert addr == address if version == NETWORKS["mainnet"].bip32_prv: address = b58.p2pkh(xpub) assert addr == address address = b58.p2pkh(xprv) assert addr == address elif version == NETWORKS["mainnet"].slip132_p2wpkh_p2sh_prv: address = b58.p2wpkh_p2sh(xpub) assert addr == address address = b58.p2wpkh_p2sh(xprv) assert addr == address elif version == NETWORKS["mainnet"].slip132_p2wpkh_prv: address = b32.p2wpkh(xpub) assert addr == address address = b32.p2wpkh(xprv) assert addr == address
def test_p2wpkh_p2sh() -> None: # https://matthewdowney.github.io/create-segwit-address.html pub = " 03 a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f" address = b58.p2wpkh_p2sh(pub) assert address == "36NvZTcMsMowbt78wPzJaHHWaNiyR73Y4g" address = b58.p2wpkh_p2sh(pub, "testnet") assert address == "2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2" # http://bitcoinscri.pt/pages/segwit_p2sh_p2wpkh pub = "02 f118cc409775419a931c57664d0c19c405e856ac0ee2f0e2a4137d8250531128" address = b58.p2wpkh_p2sh(pub) assert address == "3Mwz6cg8Fz81B7ukexK8u8EVAW2yymgWNd"
def test_address_from_wif() -> None: q = 0x19E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 test_cases: List[Tuple[bool, str, str, str]] = [ ( False, "mainnet", "5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW", "1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig", ), ( True, "mainnet", "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162", "1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB", ), ( False, "testnet", "91nKEXyJCPYaK9maw7bTJ7ZcCu6dy2gybvNtUWF1LTCYggzhZgy", "mzuJRVe3ERecM6F6V4R6GN9B5fKiPC9HxF", ), ( True, "testnet", "cNT1UjhUuGWN37hnmr754XxvPWwtAJTSq8bcCQ4pUrdxqxbA1iU1", "mwp9QoLuLK65XZUFKhPtvfujBjmgkZnmPx", ), ] for compressed, network, wif, address in test_cases: assert wif == b58.wif_from_prv_key(q, network, compressed) assert prv_keyinfo_from_prv_key(wif) == (q, network, compressed) assert address == b58.p2pkh(wif) script_type, payload, net = b58.h160_from_address(address) assert net == network assert script_type == "p2pkh" if compressed: b32_address = b32.p2wpkh(wif) assert (0, payload, net) == b32.witness_from_address(b32_address) b58_address = b58.p2wpkh_p2sh(wif) script_bin = hash160(b"\x00\x14" + payload) assert ("p2sh", script_bin, net) == b58.h160_from_address(b58_address) else: err_msg = "not a private or compressed public key: " with pytest.raises(BTClibValueError, match=err_msg): b32.p2wpkh(wif) # type: ignore with pytest.raises(BTClibValueError, match=err_msg): b58.p2wpkh_p2sh(wif) # type: ignore
def test_p2wpkh() -> None: # self-consistency pub_key = "02 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" payload = hash160(pub_key) script_pub_key = serialize(["OP_0", payload]) assert_p2wpkh(script_pub_key) assert script_pub_key == ScriptPubKey.p2wpkh(pub_key).script assert ("p2wpkh", payload) == type_and_payload(script_pub_key) # bech32 address network = "mainnet" addr = b32.p2wpkh(pub_key, 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.p2wpkh_p2sh(pub_key, network) assert addr == "3BJxz2r8zY7LxJfdGjUpjjHNh6YEiitvf2" err_msg = "invalid witness version: " with pytest.raises(BTClibValueError, match=err_msg): assert_p2wpkh(b"\x33" + script_pub_key[1:]) err_msg = "invalid pub_key hash length marker: " with pytest.raises(BTClibValueError, match=err_msg): assert_p2wpkh(script_pub_key[:1] + b"\x00" + script_pub_key[2:])
def test_p2w_p2sh() -> None: pub_key_str = "03 a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f" pub_key, network = pub_keyinfo_from_key(pub_key_str, compressed=True) witness_program = hash160(pub_key) b58addr = b58.p2wpkh_p2sh(pub_key, network) assert b58addr == "36NvZTcMsMowbt78wPzJaHHWaNiyR73Y4g" script_pub_key = serialize([ "OP_DUP", "OP_HASH160", witness_program, "OP_EQUALVERIFY", "OP_CHECKSIG" ]) b58addr = b58.p2wsh_p2sh(script_pub_key, network) assert b58addr == "3QHRam4Hvp1GZVkgjoKWUC1GEd8ck8e4WX"
def test_p2w_p2sh() -> None: pub_key = "03 a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f" witness_program, network = hash160_from_key(pub_key) b58addr = b58.p2wpkh_p2sh(pub_key, network) assert b58addr == b58.address_from_v0_witness(witness_program, network) script_pub_key = serialize([ "OP_DUP", "OP_HASH160", witness_program, "OP_EQUALVERIFY", "OP_CHECKSIG" ]) witness_program = sha256(script_pub_key) b58addr = b58.p2wsh_p2sh(script_pub_key, network) assert b58addr == b58.address_from_v0_witness(witness_program, network) err_msg = "invalid size: " with pytest.raises(BTClibValueError, match=err_msg): b58.address_from_v0_witness(witness_program[:-1], network)
def test_segwit() -> None: msg = "test".encode() wif = "L4xAvhKR35zFcamyHME2ZHfhw5DEyeJvEMovQHQ7DttPTM8NLWCK" b58_p2pkh = b58.p2pkh(wif) b32_p2wpkh = b32.p2wpkh(wif) b58_p2wpkh_p2sh = b58.p2wpkh_p2sh(wif) # p2pkh base58 address (Core, Electrum, BIP137) exp_sig = "IBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU=" assert bms.verify(msg, b58_p2pkh, exp_sig) bms_sig = bms.sign(msg, wif) # no address: p2pkh assumed assert bms.verify(msg, b58_p2pkh, bms_sig) assert bms_sig.b64encode() == exp_sig # p2wpkh-p2sh base58 address (Electrum) assert bms.verify(msg, b58_p2wpkh_p2sh, bms_sig) # p2wpkh bech32 address (Electrum) assert bms.verify(msg, b32_p2wpkh, bms_sig) # p2wpkh-p2sh base58 address (BIP137) # different first letter in bms_sig because of different rf exp_sig = "JBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU=" assert bms.verify(msg, b58_p2wpkh_p2sh, exp_sig) bms_sig = bms.sign(msg, wif, b58_p2wpkh_p2sh) assert bms.verify(msg, b58_p2wpkh_p2sh, bms_sig) assert bms_sig.b64encode() == exp_sig # p2wpkh bech32 address (BIP137) # different first letter in bms_sig because of different rf exp_sig = "KBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU=" assert bms.verify(msg, b32_p2wpkh, exp_sig) bms_sig = bms.sign(msg, wif, b32_p2wpkh) assert bms.verify(msg, b32_p2wpkh, bms_sig) assert bms_sig.b64encode() == exp_sig
def sign(msg: Octets, prv_key: PrvKey, addr: Optional[String] = None) -> Sig: "Generate address-based compact signature for the provided message." # first sign the message magic_msg = magic_message(msg) q, network, compressed = prv_keyinfo_from_prv_key(prv_key) dsa_sig = dsa.sign(magic_msg, q) # now calculate the key_id # TODO do the match in Jacobian coordinates avoiding mod_inv pub_keys = dsa.recover_pub_keys(magic_msg, dsa_sig) Q = mult(q) # key_id is in [0, 3] # first two bits in rf are reserved for it key_id = pub_keys.index(Q) pub_key = bytes_from_point(Q, compressed=compressed) if isinstance(addr, str): addr = addr.strip() elif isinstance(addr, bytes): addr = addr.decode("ascii") # finally, calculate the recovery flag if addr is None or addr == p2pkh(pub_key, network, compressed): rf = key_id + 27 # third bit in rf is reserved for the 'compressed' boolean rf += 4 if compressed else 0 # BIP137 elif addr == p2wpkh_p2sh(pub_key, network): rf = key_id + 35 elif addr == p2wpkh(pub_key, network): rf = key_id + 39 else: raise BTClibValueError("mismatch between private key and address") return Sig(rf, dsa_sig)
from btclib.b32 import p2wpkh from btclib.ecc.bms import sign, verify from btclib.to_prv_key import prv_keyinfo_from_prv_key from btclib.to_pub_key import pub_keyinfo_from_prv_key msg = "Paolo is afraid of ephemeral random numbers".encode() print("\n0. Message:", msg.decode()) wif = b"Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C" print("1. Compressed WIF:", wif.decode()) pubkey, network = pub_keyinfo_from_prv_key(wif) print("2. Addresses") address1 = p2pkh(pubkey) print(" p2pkh:", address1) address2 = p2wpkh_p2sh(pubkey) print("p2wpkh_p2sh:", address2) address3 = p2wpkh(pubkey) print(" p2wpkh:", address3) print( "\n3. Sign message with no address (i.e., with default compressed p2pkh address):" ) sig1 = sign(msg, wif) print(f"rf1: {sig1.rf}") print(f" r1: {hex(sig1.dsa_sig.r).upper()}") print(f" s1: {hex(sig1.dsa_sig.r).upper()}") bsmsig1 = sig1.serialize() print("4. Serialized signature:")
def test_exceptions() -> None: msg = "test".encode() wif = "KwELaABegYxcKApCb3kJR9ymecfZZskL9BzVUkQhsqFiUKftb4tu" address = b58.p2pkh(wif) exp_sig = "IHdKsFF1bUrapA8GMoQUbgI+Ad0ZXyX1c/yAZHmJn5hSNBi7J+TrI1615FG3g9JEOPGVvcfDWIFWrg2exLNtoVc=" bms.assert_as_valid(msg, address, exp_sig) bms_sig = bms.Sig.b64decode(exp_sig) err_msg = "not a p2wpkh address: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b32.p2wsh(32 * b"\x00"), exp_sig) err_msg = "invalid recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.Sig(26, bms_sig.dsa_sig) exp_sig = "IHdKsFF1bUrapA8GMoQUbgI+Ad0ZXyX1c/yAZHmJn5hNBi7J+TrI1615FG3g9JEOPGVvcfDWIFWrg2exLoVc=" err_msg = "invalid decoded length: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, address, exp_sig) assert not bms.verify(msg, address, exp_sig) exp_sig = "GpNLHqEKSzwXV+KwwBfQthQ848mn5qSkmGDXpqshDuPYJELOnSuRYGQQgBR4PpI+w2tJdD4v+hxElvAaUSqv2eU=" err_msg = "invalid recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, address, exp_sig) assert not bms.verify(msg, address, exp_sig) exp_sig = "QpNLHqEKSzwXV+KwwBfQthQ848mn5qSkmGDXpqshDuPYJELOnSuRYGQQgBR4PpI+w2tJdD4v+hxElvAaUSqv2eU=" with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, address, exp_sig) assert not bms.verify(msg, address, exp_sig) # compressed wif, uncompressed address wif = "Ky1XfDK2v6wHPazA6ECaD8UctEoShXdchgABjpU9GWGZDxVRDBMJ" address = "19f7adDYqhHSJm2v7igFWZAqxXHj1vUa3T" err_msg = "mismatch between private key and address" with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, address) # uncompressed wif, compressed address wif = "5JDopdKaxz5bXVYXcAnfno6oeSL8dpipxtU1AhfKe3Z58X48srn" address = "1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5" err_msg = "not a private or compressed public key for mainnet: " # FIXME puzzling error message with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, address) msg = "test".encode() wif = "L4xAvhKR35zFcamyHME2ZHfhw5DEyeJvEMovQHQ7DttPTM8NLWCK" b58_p2pkh = b58.p2pkh(wif) b32_p2wpkh = b32.p2wpkh(wif) b58_p2wpkh_p2sh = b58.p2wpkh_p2sh(wif) wif = "Ky1XfDK2v6wHPazA6ECaD8UctEoShXdchgABjpU9GWGZDxVRDBMJ" err_msg = "mismatch between private key and address" with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, b58_p2pkh) with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, b32_p2wpkh) with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, b58_p2wpkh_p2sh) # Invalid recovery flag (39) for base58 p2pkh address exp_sig = "IHdKsFF1bUrapA8GMoQUbgI+Ad0ZXyX1c/yAZHmJn5hSNBi7J+TrI1615FG3g9JEOPGVvcfDWIFWrg2exLNtoVc=" bms_sig = bms.Sig.b64decode(exp_sig) bms_sig = bms.Sig(39, bms_sig.dsa_sig, check_validity=False) sig_encoded = bms_sig.b64encode(check_validity=False) err_msg = "invalid p2pkh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b58_p2pkh, sig_encoded) # Invalid recovery flag (35) for bech32 p2wpkh address exp_sig = "IBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU=" bms_sig = bms.Sig.b64decode(exp_sig) bms_sig = bms.Sig(35, bms_sig.dsa_sig, check_validity=False) err_msg = "invalid p2wpkh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b32_p2wpkh, bms_sig)
def test_one_prv_key_multiple_addresses() -> None: msg = "Paolo is afraid of ephemeral random numbers".encode() # Compressed WIF wif = "Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C" b58_p2pkh_compressed = b58.p2pkh(wif) b58_p2wpkh_p2sh = b58.p2wpkh_p2sh(wif) b32_p2wpkh = b32.p2wpkh(wif) # sign with no address sig1 = bms.sign(msg, wif) # True for Bitcoin Core bms.assert_as_valid(msg, b58_p2pkh_compressed, sig1) assert bms.verify(msg, b58_p2pkh_compressed, sig1) # True for Electrum p2wpkh_p2sh bms.assert_as_valid(msg, b58_p2wpkh_p2sh, sig1) assert bms.verify(msg, b58_p2wpkh_p2sh, sig1) # True for Electrum p2wpkh bms.assert_as_valid(msg, b32_p2wpkh, sig1) assert bms.verify(msg, b32_p2wpkh, sig1) # sign with p2pkh address sig1 = bms.sign(msg, wif, b58_p2pkh_compressed) # True for Bitcoin Core bms.assert_as_valid(msg, b58_p2pkh_compressed, sig1) assert bms.verify(msg, b58_p2pkh_compressed, sig1) # True for Electrum p2wpkh_p2sh bms.assert_as_valid(msg, b58_p2wpkh_p2sh, sig1) assert bms.verify(msg, b58_p2wpkh_p2sh, sig1) # True for Electrum p2wpkh bms.assert_as_valid(msg, b32_p2wpkh, sig1) assert bms.verify(msg, b32_p2wpkh, sig1) assert sig1 == bms.sign(msg, wif, b58_p2pkh_compressed.encode("ascii")) # sign with p2wpkh_p2sh address (BIP137) sig2 = bms.sign(msg, wif, b58_p2wpkh_p2sh) # False for Bitcoin Core err_msg = "invalid p2pkh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b58_p2pkh_compressed, sig2) assert not bms.verify(msg, b58_p2pkh_compressed, sig2) # True for BIP137 p2wpkh_p2sh bms.assert_as_valid(msg, b58_p2wpkh_p2sh, sig2) assert bms.verify(msg, b58_p2wpkh_p2sh, sig2) # False for BIP137 p2wpkh err_msg = "invalid p2wpkh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b32_p2wpkh, sig2) assert not bms.verify(msg, b32_p2wpkh, sig2) assert sig2 == bms.sign(msg, wif, b58_p2wpkh_p2sh.encode("ascii")) # sign with p2wpkh address (BIP137) sig3 = bms.sign(msg, wif, b32_p2wpkh) # False for Bitcoin Core err_msg = "invalid p2pkh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b58_p2pkh_compressed, sig3) assert not bms.verify(msg, b58_p2pkh_compressed, sig3) # False for BIP137 p2wpkh_p2sh err_msg = "invalid p2wpkh-p2sh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b58_p2wpkh_p2sh, sig3) assert not bms.verify(msg, b58_p2wpkh_p2sh, sig3) # True for BIP137 p2wpkh bms.assert_as_valid(msg, b32_p2wpkh, sig3) assert bms.verify(msg, b32_p2wpkh, sig3) assert sig3 == bms.sign(msg, wif, b32_p2wpkh.encode("ascii")) # uncompressed WIF / p2pkh address q, network, _ = prv_keyinfo_from_prv_key(wif) wif2 = b58.wif_from_prv_key(q, network, False) b58_p2pkh_uncompressed = b58.p2pkh(wif2) # sign with uncompressed p2pkh sig4 = bms.sign(msg, wif2, b58_p2pkh_uncompressed) # False for Bitcoin Core compressed p2pkh with pytest.raises(BTClibValueError, match="invalid p2pkh address: "): bms.assert_as_valid(msg, b58_p2pkh_compressed, sig4) assert not bms.verify(msg, b58_p2pkh_compressed, sig4) # False for BIP137 p2wpkh_p2sh err_msg = "invalid p2wpkh-p2sh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b58_p2wpkh_p2sh, sig4) assert not bms.verify(msg, b58_p2wpkh_p2sh, sig4) # False for BIP137 p2wpkh err_msg = "invalid p2wpkh address recovery flag: " with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, b32_p2wpkh, sig4) assert not bms.verify(msg, b32_p2wpkh, sig4) # True for Bitcoin Core uncompressed p2pkh bms.assert_as_valid(msg, b58_p2pkh_uncompressed, sig4) assert bms.verify(msg, b58_p2pkh_uncompressed, sig4) assert sig4 == bms.sign(msg, wif2, b58_p2pkh_uncompressed.encode("ascii")) # unrelated different wif wif3 = "KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617" b58_p2pkh_compressed = b58.p2pkh(wif3) b58_p2wpkh_p2sh = b58.p2wpkh_p2sh(wif3) b32_p2wpkh = b32.p2wpkh(wif3) # False for Bitcoin Core compressed p2pkh with pytest.raises(BTClibValueError, match="invalid p2pkh address: "): bms.assert_as_valid(msg, b58_p2pkh_compressed, sig1) assert not bms.verify(msg, b58_p2pkh_compressed, sig1) # False for BIP137 p2wpkh_p2sh with pytest.raises(BTClibValueError, match="invalid p2wpkh-p2sh address: "): bms.assert_as_valid(msg, b58_p2wpkh_p2sh, sig1) assert not bms.verify(msg, b58_p2wpkh_p2sh, sig1) # False for BIP137 p2wpkh with pytest.raises(BTClibValueError, match="invalid p2wpkh address: "): bms.assert_as_valid(msg, b32_p2wpkh, sig1) assert not bms.verify(msg, b32_p2wpkh, sig1) # FIXME: puzzling error message err_msg = "not a private or compressed public key for mainnet: " with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif2, b58_p2pkh_compressed) err_msg = "mismatch between private key and address" with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, b58_p2pkh_uncompressed)