From def08fab59089b5ab6ac7a9687defdd291498d0a Mon Sep 17 00:00:00 2001 From: Jean Do Date: Sun, 11 Jun 2023 10:38:21 -0400 Subject: [PATCH 1/6] added tests for embit_utils.get_xpub() --- tests/test_embit_utils.py | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 tests/test_embit_utils.py diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py new file mode 100644 index 00000000..a93353b1 --- /dev/null +++ b/tests/test_embit_utils.py @@ -0,0 +1,168 @@ +import pytest + +from seedsigner.models.settings_definition import SettingsConstants as SC +from seedsigner.helpers import embit_utils + + +def test_get_standard_derivation_path(): + """tests seedsigner.helpers.embit_utils.get_standard_derivation_path()""" + + vectors_args_expected = { + # single sig + tuple(): "m/84'/0'/0'", + (SC.MAINNET,): "m/84'/0'/0'", + (SC.MAINNET, SC.SINGLE_SIG, ): "m/84'/0'/0'", + + (SC.MAINNET, SC.SINGLE_SIG, SC.NATIVE_SEGWIT): "m/84'/0'/0'", + (SC.TESTNET, SC.SINGLE_SIG, SC.NATIVE_SEGWIT): "m/84'/1'/0'", + (SC.REGTEST, SC.SINGLE_SIG, SC.NATIVE_SEGWIT): "m/84'/1'/0'", + + (SC.MAINNET, SC.SINGLE_SIG, SC.NESTED_SEGWIT): "m/49'/0'/0'", + (SC.TESTNET, SC.SINGLE_SIG, SC.NESTED_SEGWIT): "m/49'/1'/0'", + (SC.REGTEST, SC.SINGLE_SIG, SC.NESTED_SEGWIT): "m/49'/1'/0'", + + (SC.MAINNET, SC.SINGLE_SIG, SC.TAPROOT): "m/86'/0'/0'", + (SC.TESTNET, SC.SINGLE_SIG, SC.TAPROOT): "m/86'/1'/0'", + (SC.REGTEST, SC.SINGLE_SIG, SC.TAPROOT): "m/86'/1'/0'", + + # multi sig + (SC.MAINNET, SC.MULTISIG, SC.NATIVE_SEGWIT): "m/48'/0'/0'/2'", + (SC.TESTNET, SC.MULTISIG, SC.NATIVE_SEGWIT): "m/48'/1'/0'/2'", + (SC.REGTEST, SC.MULTISIG, SC.NATIVE_SEGWIT): "m/48'/1'/0'/2'", + + (SC.MAINNET, SC.MULTISIG, SC.NESTED_SEGWIT): "m/48'/0'/0'/1'", + (SC.TESTNET, SC.MULTISIG, SC.NESTED_SEGWIT): "m/48'/1'/0'/1'", + (SC.REGTEST, SC.MULTISIG, SC.NESTED_SEGWIT): "m/48'/1'/0'/1'", + + (SC.MAINNET, SC.MULTISIG, SC.TAPROOT): Exception, + (SC.TESTNET, SC.MULTISIG, SC.TAPROOT): Exception, + (SC.REGTEST, SC.MULTISIG, SC.TAPROOT): Exception, + + # nonsense arguments + ("A",): Exception, + ("B", "A"): Exception, + ("C", "B", "A"): Exception, + (True,): Exception, + (False, True): Exception, + (tuple(),): Exception, + } + func = embit_utils.get_standard_derivation_path + + print() + for args, expected in vectors_args_expected.items(): + + # test successful returns + if type(expected) is str: + # call with positional args + print(f"asserting {func.__name__}(*{args}) == {repr(expected)}") + assert func(*args) == expected + + # call with named args + a_dict = {} + if len(args) == 1: a_dict = {'network': args[0]} + elif len(args) == 2: a_dict = {'network': args[0], 'wallet_type': args[1]} + elif len(args) == 3: a_dict = {'network': args[0], 'wallet_type': args[1], 'script_type': args[2]} + print(f"asserting {func.__name__}(**{a_dict}) == {repr(expected)}") + assert func(**a_dict) == expected + + # test exceptions + else: + # call with positional args + with pytest.raises(expected): + print(f"asserting {func.__name__}(*{args}) raises Exception") + func(*args) + + # call with named args + a_dict = {} + if len(args) == 1: a_dict = {'network': args[0]} + elif len(args) == 2: a_dict = {'network': args[0], 'wallet_type': args[1]} + elif len(args) == 3: a_dict = {'network': args[0], 'wallet_type': args[1], 'script_type': args[2]} + print(f"asserting {func.__name__}(**{a_dict}) raises Exception") + with pytest.raises(expected): + func(**a_dict) + +def test_get_xpub(): + """tests seedsigner.helpers.embit_utils.get_xpub()""" + + from binascii import unhexlify + from embit import bip39, bip32 + + # test vectors originate from: + # https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki + # https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki + # https://github.com/satoshilabs/slips/blob/master/slip-0132.md + # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki + # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki + vector_seeds = ( + unhexlify("000102030405060708090a0b0c0d0e0f"), + unhexlify("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + unhexlify("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"), + unhexlify("3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678"), + bip39.mnemonic_to_seed('abandon '*11+'about'), + ) + + vectors_args_expected = { + # https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-1 + (vector_seeds[0], "m/", "main"): "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + (vector_seeds[0], "m/0'", "main"): "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw", + (vector_seeds[0], "m/0h/1", "main"): "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ", + (vector_seeds[0], "m/0'/1/2h", "main"): "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", + (vector_seeds[0], "m/0'/1/2h/2", "main"): "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV", + (vector_seeds[0], "m/0'/1/2h/2/1000000000", "main"): "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy", + + # https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-2 + (vector_seeds[1], "m/", "main"): "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", + (vector_seeds[1], "m/0", "main"): "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", + (vector_seeds[1], "m/0/2147483647'", "main"): "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a", + (vector_seeds[1], "m/0/2147483647h/1", "main"): "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon", + (vector_seeds[1], "m/0/2147483647'/1/2147483646h", "main"): "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL", + (vector_seeds[1], "m/0/2147483647h/1/2147483646'/2", "main"): "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt", + + # https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-3 + (vector_seeds[2], "m/", "main"): "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13", + (vector_seeds[2], "m/0h", "main"): "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y", + + # https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-4 + (vector_seeds[3], "m/", "main"): "xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa", + (vector_seeds[3], "m/0'", "main"): "xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m", + (vector_seeds[3], "m/0h/1'", "main"): "xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt", + + # + # embit_utils.get_xpub() returns the generic bip32 version "xpub", NOT the zpub/Zpub/ypub/Ypub extended versions + # + + # https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki#test-vectors + # https://github.com/satoshilabs/slips/blob/master/slip-0132.md#bitcoin-test-vectors + (vector_seeds[4], "m/84'/0'/0'", "main"): + bip32.HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs").to_base58(version=b'\x04\x88\xb2\x1e'), + + # https://github.com/satoshilabs/slips/blob/master/slip-0132.md#bitcoin-test-vectors + (vector_seeds[4], "m/49'/0'/0'", "main"): + bip32.HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP").to_base58(version=b'\x04\x88\xb2\x1e'), + + # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors + (vector_seeds[4], "m/49'/1'/0'", "test"): + bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY").to_base58(version=b'\x04\x35\x87\xcf'), + + # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors + (vector_seeds[4], "m/86'/0'/0'", "main"): "xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ", + + } + + func = embit_utils.get_xpub + for args, expected in vectors_args_expected.items(): + print("\nasserting...") + + # test calling w/o last param (default is "main") + if args[2] == "main": + print(f' {func.__name__}({args[0]}, "{args[1]}") returns "{expected}"') + assert str(func(args[0], args[1])) == expected + + # test calling w/ ordered params + print(f' {func.__name__}(*{args}) returns "{expected}"') + assert str(func(*args)) == expected + + # test calling w/ named params + print(f' {func.__name__}(seed_bytes={args[0]}, derivation_path="{args[1]}", embit_network="{args[2]}") returns "{expected}"') + assert str(func(seed_bytes=args[0], derivation_path=args[1], embit_network=args[2])) == expected + From 72dd6b80a45b12c41a4017bbd6d206ebd5305d77 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Sun, 11 Jun 2023 12:59:50 -0400 Subject: [PATCH 2/6] added tests for embit_utils.get_single_sig_address() --- tests/test_embit_utils.py | 75 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index a93353b1..68bd967d 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -81,6 +81,7 @@ def test_get_standard_derivation_path(): with pytest.raises(expected): func(**a_dict) + def test_get_xpub(): """tests seedsigner.helpers.embit_utils.get_xpub()""" @@ -98,7 +99,7 @@ def test_get_xpub(): unhexlify("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), unhexlify("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"), unhexlify("3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678"), - bip39.mnemonic_to_seed('abandon '*11+'about'), + bip39.mnemonic_to_seed("abandon "*11 + "about"), ) vectors_args_expected = { @@ -155,14 +156,80 @@ def test_get_xpub(): # test calling w/o last param (default is "main") if args[2] == "main": - print(f' {func.__name__}({args[0]}, "{args[1]}") returns "{expected}"') + print(f' {func.__name__}({args[0]}, "{args[1]}") == "{expected}"') assert str(func(args[0], args[1])) == expected # test calling w/ ordered params - print(f' {func.__name__}(*{args}) returns "{expected}"') + print(f' {func.__name__}(*{args}) == "{expected}"') assert str(func(*args)) == expected # test calling w/ named params - print(f' {func.__name__}(seed_bytes={args[0]}, derivation_path="{args[1]}", embit_network="{args[2]}") returns "{expected}"') + print(f' {func.__name__}(seed_bytes={args[0]}, derivation_path="{args[1]}", embit_network="{args[2]}") == "{expected}"') assert str(func(seed_bytes=args[0], derivation_path=args[1], embit_network=args[2])) == expected + +def test_get_single_sig_address(): + from embit import bip32 + + # test vectors originate from: + # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki + # https://github.com/satoshilabs/slips/blob/master/slip-0132.md + # https://iancoleman.io/bip39/ + # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki + + vectors_args_expected = { + # https://github.com/satoshilabs/slips/blob/master/slip-0132.md#bitcoin-test-vectors (first payment address of native segwit on mainnet) + (bip32.HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), "nat", 0, False, "main"): + "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", + # jdlcdl: derived via iancoleman test vector for first change address of native segwit on mainnet + (bip32.HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), "nat", 0, True, "main"): + "bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el", + + # https://github.com/satoshilabs/slips/blob/master/slip-0132.md#bitcoin-test-vectors (first payment address of nested segwit on mainnet) + (bip32.HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP"), "nes", 0, False, "main"): + "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf", + # jdlcdl: derived via iancoleman test vector for first change address of nested segwit on mainnet + (bip32.HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP"), "nes", 0, True, "main"): + "34K56kSjgUCUSD8GTtuF7c9Zzwokbs6uZ7", + + # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors (first payment address of nested segwit on testnet) + (bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, False, "test"): + "2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2", + # jdlcdl: derived test vector for first change address of nested segwit on testnet + (bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, True, "test"): + "2MvdUi5o3f2tnEFh9yGvta6FzptTZtkPJC8", + + # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors (first payment address of taproot on mainnet) + (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, False, "main"): + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", + + # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors (second payment address of taproot on mainnet) + (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 1, False, "main"): + "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh", + + # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors (first change address of taproot on mainnet) + (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, True, "main"): + "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7", + + } + + func = embit_utils.get_single_sig_address + for args, expected in vectors_args_expected.items(): + print("\nasserting...") + + # test calling w/o optional params (defaults: script_type="nat", index=0, is_change=False, embit_network="main") + if args[1:5] == ("nat", 0, False, "main"): + print(f' {func.__name__}({args[0]}) == "{expected}"') + assert str(func(args[0], args[1])) == expected + + # test calling w/ ordered params + print(f' {func.__name__}(*{args}) == "{expected}"') + assert str(func(*args)) == expected + + # test calling w/ named params + print(f' {func.__name__}(xpub={args[0]}, script_type="{args[1]}", index={args[2]}, is_change={args[3]}, embit_network="{args[4]}") == "{expected}"') + assert str(func(xpub=args[0], script_type=args[1], index=args[2], is_change=args[3], embit_network=args[4])) == expected + + +def test_get_multisig_address(): + pass From 96ca99ba7fb6e6a78ebb1f737e113e0d53f88abc Mon Sep 17 00:00:00 2001 From: Jean Do Date: Sun, 11 Jun 2023 18:17:26 -0400 Subject: [PATCH 3/6] added tests for embit_utils.get_multisig_address() --- tests/test_embit_utils.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index 68bd967d..4364b3a3 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -232,4 +232,39 @@ def test_get_single_sig_address(): def test_get_multisig_address(): - pass + from embit.descriptor import Descriptor + + # jdlcdl: these vectors created with electrum & sparrow as a 2 of 3 multisig based on bip39-bip32-standard-path wallets + # keystore1 = 0x00*16 = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about' + # keystore2 = 0x11*16 = 'baby mass dust captain baby mass dust captain baby mass dust casino' + # keystore3 = 0x22*16 = 'captain baby mass dust captain baby mass dust captain baby mass dutch' + + vector_args_expected = { + # multisig native segwit on testnet, first payment and change addresses + ("wsh(sortedmulti(2,[8d55ff0d/48h/1h/0h/2h]tpubDDxNVWk924RTUhdkVB2uLHw1hGMPNMGufpZefhkkswjbZppVZcuMdjYKQN4ewUog9vbL6RBLFPRWcgTGT7kYP79N6thyJ43ELUs4N2szXMg/{0,1}/*,[73c5da0a/48h/1h/0h/2h]tpubDFH9dgzveyD8zTbPUFuLrGmCydNvxehyNdUXKJAQN8x4aZ4j6UZqGfnqFrD4NqyaTVGKbvEW54tsvPTK2UoSbCC1PJY8iCNiwTL3RWZEheQ/{0,1}/*,[0be174ee/48h/1h/0h/2h]tpubDEsePyLPkbxbrDiZSTTWdsviiNtiQjrvvzZnkLtG72QYLBygEsXePRsTdXi8DeMA7taCuuvoEBjUAfFrsNZeQJqfvG9fFoujYWbFPYUn7ux/{0,1}/*))#zw6cnrlk" , 0, False, "test"): "tb1q7tpecll8jhp77yqdeyt2t8q5swxmmqeh2v22cqpms5dxlp6p27dqlftet8", + ("wsh(sortedmulti(2,[8d55ff0d/48h/1h/0h/2h]tpubDDxNVWk924RTUhdkVB2uLHw1hGMPNMGufpZefhkkswjbZppVZcuMdjYKQN4ewUog9vbL6RBLFPRWcgTGT7kYP79N6thyJ43ELUs4N2szXMg/{0,1}/*,[73c5da0a/48h/1h/0h/2h]tpubDFH9dgzveyD8zTbPUFuLrGmCydNvxehyNdUXKJAQN8x4aZ4j6UZqGfnqFrD4NqyaTVGKbvEW54tsvPTK2UoSbCC1PJY8iCNiwTL3RWZEheQ/{0,1}/*,[0be174ee/48h/1h/0h/2h]tpubDEsePyLPkbxbrDiZSTTWdsviiNtiQjrvvzZnkLtG72QYLBygEsXePRsTdXi8DeMA7taCuuvoEBjUAfFrsNZeQJqfvG9fFoujYWbFPYUn7ux/{0,1}/*))#zw6cnrlk" , 0, True, "test"): "tb1q7h94ywhfjrpxdfzwl4dcawrg80r4rywswjrh447x4n3e5t3m0jms9jh7pm", + + # multisig nested segwit on testnet, first payment and change addresses + ("sh(wsh(sortedmulti(2,[73c5da0a/48h/1h/1h/0h/1h]tpubDFH9dgzveyD8yHQb8VrpG8FYAuwcLMHMje2CCcbBo1FpaGzYVtJeYYxcYgRqSTta5utUFts8nPPHs9C2bqoxrey5jia6Dwf9mpwrPq7YvcJ/{0,1}/*,[0be174ee/48h/1h/0h/1h]tpubDEsePyLPkbxbnj6XuKvWwdERHaKkikZxaGJ9sJqmM7okbZXgkNSFiGU6GX6qEes6kD8f9Z9FosYB9UEnBSgBEyEwwJhj4uUcFE1WE8VtKoh/{0,1}/*,[8d55ff0d/48h/1h/0h/1h]tpubDDxNVWk924RTT3vyGLHdSDoZ2JUVX7jUsPcwCQ9MrKHAtJrW5zECTF9rFHCvqu526E4PjHp61hBknts2c5aGexvX7hvCZ8TGPvQFdzxxy59/{0,1}/*)))#2ujlfp73", 0, False, "test"): "2MtgJH28mZWNWU7VRU4ba6ciFbRRGYWZDt3", + ("sh(wsh(sortedmulti(2,[73c5da0a/48h/1h/1h/0h/1h]tpubDFH9dgzveyD8yHQb8VrpG8FYAuwcLMHMje2CCcbBo1FpaGzYVtJeYYxcYgRqSTta5utUFts8nPPHs9C2bqoxrey5jia6Dwf9mpwrPq7YvcJ/{0,1}/*,[0be174ee/48h/1h/0h/1h]tpubDEsePyLPkbxbnj6XuKvWwdERHaKkikZxaGJ9sJqmM7okbZXgkNSFiGU6GX6qEes6kD8f9Z9FosYB9UEnBSgBEyEwwJhj4uUcFE1WE8VtKoh/{0,1}/*,[8d55ff0d/48h/1h/0h/1h]tpubDDxNVWk924RTT3vyGLHdSDoZ2JUVX7jUsPcwCQ9MrKHAtJrW5zECTF9rFHCvqu526E4PjHp61hBknts2c5aGexvX7hvCZ8TGPvQFdzxxy59/{0,1}/*)))#2ujlfp73", 0, True, "test"): "2NAjjwUQqwD9XRGLeQ6TitSUyMHUz3cLiWm", + } + + func = embit_utils.get_multisig_address + for args, expected in vector_args_expected.items(): + descriptor = Descriptor.from_string(args[0]) + + print("\nasserting...") + + # test calling w/o optional params (defaults: index=0, is_change=False, embit_network="main") + if args[1:4] == (0, False, 'main'): + print(f' {func.__name__}({descriptor}) == "{expected}"') + assert func(descriptor) == expected + + # test calling w/ ordered params + print(f' {func.__name__}({descriptor}, *{args[1:4]}) == "{expected}"') + assert func(descriptor, *args[1:4]) == expected + + # test calling w/ named params + print(f' {func.__name__}(descriptor={descriptor}, index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") == "{expected}"') + assert func(descriptor=descriptor, index=args[1], is_change=args[2], embit_network=args[3]) == expected + From 7fe5d00cec1b3ac00152fc34635d8c04cfb04978 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Mon, 12 Jun 2023 06:43:02 -0400 Subject: [PATCH 4/6] cleanup prior to pull request --- tests/test_embit_utils.py | 103 ++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index 4364b3a3..07c10f80 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -5,7 +5,9 @@ from seedsigner.helpers import embit_utils def test_get_standard_derivation_path(): - """tests seedsigner.helpers.embit_utils.get_standard_derivation_path()""" + """ + tests seedsigner.helpers.embit_utils.get_standard_derivation_path() + """ vectors_args_expected = { # single sig @@ -25,6 +27,7 @@ def test_get_standard_derivation_path(): (SC.TESTNET, SC.SINGLE_SIG, SC.TAPROOT): "m/86'/1'/0'", (SC.REGTEST, SC.SINGLE_SIG, SC.TAPROOT): "m/86'/1'/0'", + # multi sig (SC.MAINNET, SC.MULTISIG, SC.NATIVE_SEGWIT): "m/48'/0'/0'/2'", (SC.TESTNET, SC.MULTISIG, SC.NATIVE_SEGWIT): "m/48'/1'/0'/2'", @@ -38,6 +41,11 @@ def test_get_standard_derivation_path(): (SC.TESTNET, SC.MULTISIG, SC.TAPROOT): Exception, (SC.REGTEST, SC.MULTISIG, SC.TAPROOT): Exception, + # intentionally fall into exceptions + (SC.MAINNET, SC.SINGLE_SIG, 'invalid'): Exception, + (SC.MAINNET, SC.MULTISIG, 'invalid'): Exception, + (SC.MAINNET, 'invalid', SC.NATIVE_SEGWIT): Exception, + # nonsense arguments ("A",): Exception, ("B", "A"): Exception, @@ -51,13 +59,13 @@ def test_get_standard_derivation_path(): print() for args, expected in vectors_args_expected.items(): - # test successful returns + # test successful calls if type(expected) is str: - # call with positional args + # call with ordered params print(f"asserting {func.__name__}(*{args}) == {repr(expected)}") assert func(*args) == expected - # call with named args + # call with named params a_dict = {} if len(args) == 1: a_dict = {'network': args[0]} elif len(args) == 2: a_dict = {'network': args[0], 'wallet_type': args[1]} @@ -67,12 +75,12 @@ def test_get_standard_derivation_path(): # test exceptions else: - # call with positional args + # call with ordered params with pytest.raises(expected): print(f"asserting {func.__name__}(*{args}) raises Exception") func(*args) - # call with named args + # call with named params a_dict = {} if len(args) == 1: a_dict = {'network': args[0]} elif len(args) == 2: a_dict = {'network': args[0], 'wallet_type': args[1]} @@ -83,7 +91,9 @@ def test_get_standard_derivation_path(): def test_get_xpub(): - """tests seedsigner.helpers.embit_utils.get_xpub()""" + """ + tests seedsigner.helpers.embit_utils.get_xpub() + """ from binascii import unhexlify from embit import bip39, bip32 @@ -149,26 +159,31 @@ def test_get_xpub(): (vector_seeds[4], "m/86'/0'/0'", "main"): "xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ", } - func = embit_utils.get_xpub + + print() for args, expected in vectors_args_expected.items(): print("\nasserting...") - # test calling w/o last param (default is "main") + # call without optional params (default is "main") if args[2] == "main": print(f' {func.__name__}({args[0]}, "{args[1]}") == "{expected}"') assert str(func(args[0], args[1])) == expected - # test calling w/ ordered params + # call with ordered params print(f' {func.__name__}(*{args}) == "{expected}"') assert str(func(*args)) == expected - # test calling w/ named params + # call with named params print(f' {func.__name__}(seed_bytes={args[0]}, derivation_path="{args[1]}", embit_network="{args[2]}") == "{expected}"') assert str(func(seed_bytes=args[0], derivation_path=args[1], embit_network=args[2])) == expected def test_get_single_sig_address(): + """ + tests seedsigner.helpers.embit_utils.get_single_sig_address() + """ + from embit import bip32 # test vectors originate from: @@ -195,7 +210,7 @@ def test_get_single_sig_address(): # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors (first payment address of nested segwit on testnet) (bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, False, "test"): "2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2", - # jdlcdl: derived test vector for first change address of nested segwit on testnet + # jdlcdl: derived via iancoleman test vector for first change address of nested segwit on testnet (bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, True, "test"): "2MvdUi5o3f2tnEFh9yGvta6FzptTZtkPJC8", @@ -211,27 +226,39 @@ def test_get_single_sig_address(): (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, True, "main"): "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7", - } + # jdlcdl: derived via electrum m/44'/1'/0 (first payment address p2pkh on testnet) + (bip32.HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, False, "test"): + "mkpZhYtJu2r87Js3pDiWJDmPte2NRZ8bJV", + # jdlcdl: derived via electrum m/44'/1'/0 (first change address p2pkh on testnet) + (bip32.HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, True, "test"): + "mi8nhzZgGZQthq6DQHbru9crMDerUdTKva", + } func = embit_utils.get_single_sig_address + + print() for args, expected in vectors_args_expected.items(): print("\nasserting...") - # test calling w/o optional params (defaults: script_type="nat", index=0, is_change=False, embit_network="main") + # call without optional params (defaults: script_type="nat", index=0, is_change=False, embit_network="main") if args[1:5] == ("nat", 0, False, "main"): print(f' {func.__name__}({args[0]}) == "{expected}"') assert str(func(args[0], args[1])) == expected - # test calling w/ ordered params + # call with ordered params print(f' {func.__name__}(*{args}) == "{expected}"') assert str(func(*args)) == expected - # test calling w/ named params + # call with named params print(f' {func.__name__}(xpub={args[0]}, script_type="{args[1]}", index={args[2]}, is_change={args[3]}, embit_network="{args[4]}") == "{expected}"') assert str(func(xpub=args[0], script_type=args[1], index=args[2], is_change=args[3], embit_network=args[4])) == expected def test_get_multisig_address(): + """ + tests seedsigner.helpers.embit_utils.get_multisig_address() + """ + from embit.descriptor import Descriptor # jdlcdl: these vectors created with electrum & sparrow as a 2 of 3 multisig based on bip39-bip32-standard-path wallets @@ -247,24 +274,46 @@ def test_get_multisig_address(): # multisig nested segwit on testnet, first payment and change addresses ("sh(wsh(sortedmulti(2,[73c5da0a/48h/1h/1h/0h/1h]tpubDFH9dgzveyD8yHQb8VrpG8FYAuwcLMHMje2CCcbBo1FpaGzYVtJeYYxcYgRqSTta5utUFts8nPPHs9C2bqoxrey5jia6Dwf9mpwrPq7YvcJ/{0,1}/*,[0be174ee/48h/1h/0h/1h]tpubDEsePyLPkbxbnj6XuKvWwdERHaKkikZxaGJ9sJqmM7okbZXgkNSFiGU6GX6qEes6kD8f9Z9FosYB9UEnBSgBEyEwwJhj4uUcFE1WE8VtKoh/{0,1}/*,[8d55ff0d/48h/1h/0h/1h]tpubDDxNVWk924RTT3vyGLHdSDoZ2JUVX7jUsPcwCQ9MrKHAtJrW5zECTF9rFHCvqu526E4PjHp61hBknts2c5aGexvX7hvCZ8TGPvQFdzxxy59/{0,1}/*)))#2ujlfp73", 0, False, "test"): "2MtgJH28mZWNWU7VRU4ba6ciFbRRGYWZDt3", ("sh(wsh(sortedmulti(2,[73c5da0a/48h/1h/1h/0h/1h]tpubDFH9dgzveyD8yHQb8VrpG8FYAuwcLMHMje2CCcbBo1FpaGzYVtJeYYxcYgRqSTta5utUFts8nPPHs9C2bqoxrey5jia6Dwf9mpwrPq7YvcJ/{0,1}/*,[0be174ee/48h/1h/0h/1h]tpubDEsePyLPkbxbnj6XuKvWwdERHaKkikZxaGJ9sJqmM7okbZXgkNSFiGU6GX6qEes6kD8f9Z9FosYB9UEnBSgBEyEwwJhj4uUcFE1WE8VtKoh/{0,1}/*,[8d55ff0d/48h/1h/0h/1h]tpubDDxNVWk924RTT3vyGLHdSDoZ2JUVX7jUsPcwCQ9MrKHAtJrW5zECTF9rFHCvqu526E4PjHp61hBknts2c5aGexvX7hvCZ8TGPvQFdzxxy59/{0,1}/*)))#2ujlfp73", 0, True, "test"): "2NAjjwUQqwD9XRGLeQ6TitSUyMHUz3cLiWm", - } + # legacy multisig p2sh on testnet, not supported + ("sh(sortedmulti(2,[8d55ff0d/45h]tpubDANogJ2yfnizHwX7fSi5kUVzybyuPXDhgHB2TR9TUvkSLZFW73cRq4STKFDpx7qjJJiisyq82tbu4CeiYtmKEmT1xoCq9P8BPvXV31HUh6d/{0,1}/*,[0be174ee/45h]tpubDBkeVF2tDNT1Pz7L47iJeBB6RokU12LX6x4E6Ph8T89hmjQfB77q1AMyGwL8qpREVGq9sCJEbWwmnemwNTxnpxGn1di7BGy8jx9wEi5Vahu/{0,1}/*,[73c5da0a/45h]tpubDBKsGC1UqBDNvx9aivFmxZNgeZTUnmsCFGhWrqkLzucUCDePvbWWm3n8tAaAwMmxBG2ihdKCG9fzBdUnMxKx5PrkiqSZFi6Vkv6msUs9ddN/{0,1}/*))#p5t8sa8c", 0, False, "test"): Exception, + + # multisig taproot on testnet, not supported + # TODO: find what a multisig-taproot descriptor would look like and add a test so we can fall into the last condition exception. + } func = embit_utils.get_multisig_address + + print() for args, expected in vector_args_expected.items(): descriptor = Descriptor.from_string(args[0]) print("\nasserting...") - # test calling w/o optional params (defaults: index=0, is_change=False, embit_network="main") - if args[1:4] == (0, False, 'main'): - print(f' {func.__name__}({descriptor}) == "{expected}"') - assert func(descriptor) == expected + # test successful calls + if type(expected) == str: + # call with optional params (defaults: index=0, is_change=False, embit_network="main") + if args[1:4] == (0, False, 'main'): + print(f' {func.__name__}({descriptor}) == "{expected}"') + assert func(descriptor) == expected - # test calling w/ ordered params - print(f' {func.__name__}({descriptor}, *{args[1:4]}) == "{expected}"') - assert func(descriptor, *args[1:4]) == expected + # call with ordered params + print(f' {func.__name__}({descriptor}, *{args[1:4]}) == "{expected}"') + assert func(descriptor, *args[1:4]) == expected - # test calling w/ named params - print(f' {func.__name__}(descriptor={descriptor}, index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") == "{expected}"') - assert func(descriptor=descriptor, index=args[1], is_change=args[2], embit_network=args[3]) == expected + # call with named params + print(f' {func.__name__}(descriptor={descriptor}, index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") == "{expected}"') + assert func(descriptor=descriptor, index=args[1], is_change=args[2], embit_network=args[3]) == expected + + # test exceptions + else: + # call with ordered params + with pytest.raises(expected): + print(f"asserting {func.__name__}(*{args}) raises Exception") + func(descriptor, *args[1:4]) + + # call with named params + with pytest.raises(expected): + print(f"asserting {func.__name__}(*{args}) raises Exception") + print(f' {func.__name__}(descriptor={descriptor}, index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") raises Exception"') + func(descriptor=descriptor, index=args[1], is_change=args[2], embit_network=args[3]) From 19f182b1e54c47707edfcd5f26d22be198764c26 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Mon, 12 Jun 2023 08:11:14 -0400 Subject: [PATCH 5/6] printed output via 'pytest -s' works when cut/pasted --- tests/test_embit_utils.py | 43 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index 07c10f80..1398c407 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -184,7 +184,7 @@ def test_get_single_sig_address(): tests seedsigner.helpers.embit_utils.get_single_sig_address() """ - from embit import bip32 + from embit.bip32 import HDKey # test vectors originate from: # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki @@ -194,44 +194,44 @@ def test_get_single_sig_address(): vectors_args_expected = { # https://github.com/satoshilabs/slips/blob/master/slip-0132.md#bitcoin-test-vectors (first payment address of native segwit on mainnet) - (bip32.HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), "nat", 0, False, "main"): + (HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), "nat", 0, False, "main"): "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", # jdlcdl: derived via iancoleman test vector for first change address of native segwit on mainnet - (bip32.HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), "nat", 0, True, "main"): + (HDKey.from_string("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), "nat", 0, True, "main"): "bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el", # https://github.com/satoshilabs/slips/blob/master/slip-0132.md#bitcoin-test-vectors (first payment address of nested segwit on mainnet) - (bip32.HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP"), "nes", 0, False, "main"): + (HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP"), "nes", 0, False, "main"): "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf", # jdlcdl: derived via iancoleman test vector for first change address of nested segwit on mainnet - (bip32.HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP"), "nes", 0, True, "main"): + (HDKey.from_string("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP"), "nes", 0, True, "main"): "34K56kSjgUCUSD8GTtuF7c9Zzwokbs6uZ7", # https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors (first payment address of nested segwit on testnet) - (bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, False, "test"): + (HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, False, "test"): "2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2", # jdlcdl: derived via iancoleman test vector for first change address of nested segwit on testnet - (bip32.HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, True, "test"): + (HDKey.from_string("upub5EFU65HtV5TeiSHmZZm7FUffBGy8UKeqp7vw43jYbvZPpoVsgU93oac7Wk3u6moKegAEWtGNF8DehrnHtv21XXEMYRUocHqguyjknFHYfgY"), "nes", 0, True, "test"): "2MvdUi5o3f2tnEFh9yGvta6FzptTZtkPJC8", # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors (first payment address of taproot on mainnet) - (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, False, "main"): + (HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, False, "main"): "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors (second payment address of taproot on mainnet) - (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 1, False, "main"): + (HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 1, False, "main"): "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh", # https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors (first change address of taproot on mainnet) - (bip32.HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, True, "main"): + (HDKey.from_string("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ"), "tr", 0, True, "main"): "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7", # jdlcdl: derived via electrum m/44'/1'/0 (first payment address p2pkh on testnet) - (bip32.HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, False, "test"): + (HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, False, "test"): "mkpZhYtJu2r87Js3pDiWJDmPte2NRZ8bJV", # jdlcdl: derived via electrum m/44'/1'/0 (first change address p2pkh on testnet) - (bip32.HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, True, "test"): + (HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, True, "test"): "mi8nhzZgGZQthq6DQHbru9crMDerUdTKva", } func = embit_utils.get_single_sig_address @@ -242,15 +242,15 @@ def test_get_single_sig_address(): # call without optional params (defaults: script_type="nat", index=0, is_change=False, embit_network="main") if args[1:5] == ("nat", 0, False, "main"): - print(f' {func.__name__}({args[0]}) == "{expected}"') - assert str(func(args[0], args[1])) == expected + print(f' {func.__name__}(HDKey.from_string("{args[0]}")) == "{expected}"') + assert str(func(args[0])) == expected # call with ordered params - print(f' {func.__name__}(*{args}) == "{expected}"') + print(f' {func.__name__}(HDKey.from_string("{args[0]}"), *{args[1:5]}) == "{expected}"') assert str(func(*args)) == expected # call with named params - print(f' {func.__name__}(xpub={args[0]}, script_type="{args[1]}", index={args[2]}, is_change={args[3]}, embit_network="{args[4]}") == "{expected}"') + print(f' {func.__name__}(xpub=HDKey.from_string("{args[0]}"), script_type="{args[1]}", index={args[2]}, is_change={args[3]}, embit_network="{args[4]}") == "{expected}"') assert str(func(xpub=args[0], script_type=args[1], index=args[2], is_change=args[3], embit_network=args[4])) == expected @@ -293,27 +293,26 @@ def test_get_multisig_address(): if type(expected) == str: # call with optional params (defaults: index=0, is_change=False, embit_network="main") if args[1:4] == (0, False, 'main'): - print(f' {func.__name__}({descriptor}) == "{expected}"') + print(f' {func.__name__}(Descriptor.from_string("{descriptor}")) == "{expected}"') assert func(descriptor) == expected # call with ordered params - print(f' {func.__name__}({descriptor}, *{args[1:4]}) == "{expected}"') + print(f' {func.__name__}(Descriptor.from_string("{descriptor}"), *{args[1:4]}) == "{expected}"') assert func(descriptor, *args[1:4]) == expected # call with named params - print(f' {func.__name__}(descriptor={descriptor}, index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") == "{expected}"') + print(f' {func.__name__}(descriptor=Descriptor.from_string("{descriptor}"), index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") == "{expected}"') assert func(descriptor=descriptor, index=args[1], is_change=args[2], embit_network=args[3]) == expected # test exceptions else: # call with ordered params with pytest.raises(expected): - print(f"asserting {func.__name__}(*{args}) raises Exception") + print(f' {func.__name__}(Descriptor.from_string("{descriptor}"), *{args[1:4]}) raises Exception') func(descriptor, *args[1:4]) # call with named params with pytest.raises(expected): - print(f"asserting {func.__name__}(*{args}) raises Exception") - print(f' {func.__name__}(descriptor={descriptor}, index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") raises Exception"') + print(f' {func.__name__}(descriptor=Descriptor.from_string("{descriptor}"), index={args[1]}, is_change={args[2]}, embit_network="{args[3]}") raises Exception"') func(descriptor=descriptor, index=args[1], is_change=args[2], embit_network=args[3]) From 5a847d683be4d1d95966b82be0af1a7faa22178e Mon Sep 17 00:00:00 2001 From: Jean Do Date: Wed, 5 Jul 2023 09:06:12 -0400 Subject: [PATCH 6/6] one more test for get_single_sig_address() --- tests/test_embit_utils.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index 1398c407..2e462bc2 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -233,6 +233,10 @@ def test_get_single_sig_address(): # jdlcdl: derived via electrum m/44'/1'/0 (first change address p2pkh on testnet) (HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "leg", 0, True, "test"): "mi8nhzZgGZQthq6DQHbru9crMDerUdTKva", + + # jdlcdl: nonsense script_type falls off end of function returning None. TODO: Would it be preferred to "else: raise ValueError"? + (HDKey.from_string("tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba"), "NONSENSE", 0, True, "test"): + "None", } func = embit_utils.get_single_sig_address @@ -280,6 +284,11 @@ def test_get_multisig_address(): # multisig taproot on testnet, not supported # TODO: find what a multisig-taproot descriptor would look like and add a test so we can fall into the last condition exception. + + # some policy that is not supported: + # TODO: find anything non supported so we can drop off the function: Would it be preferred to "else: raise ValueError()"? + #("sh(multi(2,[8d55ff0d/45h]tpubDANogJ2yfnizHwX7fSi5kUVzybyuPXDhgHB2TR9TUvkSLZFW73cRq4STKFDpx7qjJJiisyq82tbu4CeiYtmKEmT1xoCq9P8BPvXV31HUh6d/{0,1}/*,[0be174ee/45h]tpubDBkeVF2tDNT1Pz7L47iJeBB6RokU12LX6x4E6Ph8T89hmjQfB77q1AMyGwL8qpREVGq9sCJEbWwmnemwNTxnpxGn1di7BGy8jx9wEi5Vahu/{0,1}/*,[73c5da0a/45h]tpubDBKsGC1UqBDNvx9aivFmxZNgeZTUnmsCFGhWrqkLzucUCDePvbWWm3n8tAaAwMmxBG2ihdKCG9fzBdUnMxKx5PrkiqSZFi6Vkv6msUs9ddN/{0,1}/*))#", 0, False, "test"): None, + } func = embit_utils.get_multisig_address