diff --git a/tests/test_monero_wallet_common.py b/tests/test_monero_wallet_common.py index 753e308..3bbe743 100644 --- a/tests/test_monero_wallet_common.py +++ b/tests/test_monero_wallet_common.py @@ -22,6 +22,7 @@ MoneroAddressBookEntry, MoneroSubmitTxResult, MoneroAccountTag ) from utils import ( + MultisigSampleCodeTester, TestUtils, WalletEqualityUtils, StringUtils, AssertUtils, TxContext, GenUtils, WalletUtils, @@ -3980,4 +3981,28 @@ def test_rescan_blockchain(self, wallet: MoneroWallet) -> None: #endregion + #region Utils + + def _test_multisig_sample(self, m: int, n: int) -> None: + """ + Test multisig sample code. + + :param int m: multisig threshold. + :param int n: number of participants. + """ + # create participant wallets + wallets: list[MoneroWallet] = [] + + for i in range(n): + wallets.append(self._create_wallet(MoneroWalletConfig())) + logger.debug(f"Created multisig wallet participant {i + 1}") + + tester: MultisigSampleCodeTester = MultisigSampleCodeTester(m, wallets) + tester.test() + + if self.get_wallet_type() == WalletType.RPC: + TestUtils.free_wallet_rpc_resources() + + #endregion + #endregion diff --git a/tests/test_monero_wallet_full.py b/tests/test_monero_wallet_full.py index c3cf678..950f382 100644 --- a/tests/test_monero_wallet_full.py +++ b/tests/test_monero_wallet_full.py @@ -15,9 +15,8 @@ from utils import ( TestUtils as Utils, StringUtils, AssertUtils, WalletUtils, WalletType, - MultisigSampleCodeTester, SyncSeedTester, - SyncProgressTester, WalletEqualityUtils, - WalletErrorUtils + SyncSeedTester, SyncProgressTester, + WalletEqualityUtils, WalletErrorUtils ) from test_monero_wallet_common import BaseTestMoneroWallet @@ -698,22 +697,6 @@ def test_import_key_images(self, wallet: MoneroWallet): #region Utils - def _test_multisig_sample(self, m: int, n: int) -> None: - """ - Test multisig sample code. - - :param int m: multisig threshold. - :param int n: number of participants. - """ - # create participant wallets - wallets: list[MoneroWalletFull] = [] - for i in range(n): - wallets.append(self._create_wallet(MoneroWalletConfig())) - logger.debug(f"Created multisig wallet participant {i + 1}") - - tester: MultisigSampleCodeTester = MultisigSampleCodeTester(m, wallets) - tester.test() - def _test_sync_seed( self, daemon: MoneroDaemonRpc, diff --git a/tests/test_monero_wallet_rpc.py b/tests/test_monero_wallet_rpc.py index 1313418..17a70d6 100644 --- a/tests/test_monero_wallet_rpc.py +++ b/tests/test_monero_wallet_rpc.py @@ -248,6 +248,12 @@ def test_open_wallet(self)-> None: for wallet in wallets: self._close_wallet(wallet) + # Supports multisig sample code + @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + def test_multisig_sample(self) -> None: + self._test_multisig_sample(1, 2) + self._test_multisig_sample(2, 2) + # Can save the wallet @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") def test_save(self, wallet: MoneroWallet) -> None: diff --git a/tests/utils/multisig_sample_code_tester.py b/tests/utils/multisig_sample_code_tester.py index ff17947..5548dec 100644 --- a/tests/utils/multisig_sample_code_tester.py +++ b/tests/utils/multisig_sample_code_tester.py @@ -1,11 +1,15 @@ +import logging from monero import ( - MoneroWalletFull, MoneroMultisigInitResult, - MoneroUtils, MoneroMultisigInfo + MoneroWallet, MoneroUtils, + MoneroMultisigInitResult, MoneroMultisigInfo ) +from .wallet_utils import WalletUtils from .test_utils import TestUtils +logger: logging.Logger = logging.getLogger("MultisigSampleCodeTester") + class MultisigSampleCodeTester: """Create and test a multisig wallet with M/N configuration.""" @@ -14,23 +18,23 @@ class MultisigSampleCodeTester: """Multisig threshold.""" n: int """Multisig participants.""" - wallets: list[MoneroWalletFull] + wallets: list[MoneroWallet] """Participants test wallets.""" - def __init__(self, m: int, participants: list[MoneroWalletFull]) -> None: + def __init__(self, m: int, participants: list[MoneroWallet]) -> None: """Initialize a new create-multisig-wallet tester. :param int m: multisig threshold. - :param list[MoneroWalletFull] participants: participant wallets. + :param list[MoneroWallet] participants: participant wallets. """ n: int = len(participants) assert m <= n, "Threshold must be less or equal to number of participants" self.m = m self.n = n self.wallets = participants + self._disposed = False - def test(self) -> None: - """Test multisig wallet creation.""" + def make_multisig_wallets(self) -> list[str]: # prepare and collect multisig hex from each participant prepared_multisig_hexes: list[str] = [] @@ -51,14 +55,20 @@ def test(self) -> None: multisig_hex: str = self.wallets[i].make_multisig(peer_multisig_hexes, self.m, TestUtils.WALLET_PASSWORD) made_multisig_hexes.append(multisig_hex) + return made_multisig_hexes.copy() + + def test(self) -> None: + """Test multisig wallet creation.""" + # exchange multisig keys N - M + 1 times - multisig_hexes: list[str] = made_multisig_hexes.copy() + multisig_hexes: list[str] = self.make_multisig_wallets() for i in range(self.n - self.m + 1): # exchange multisig keys among participants and collect results for next round if applicable result_multisig_hexes: list[str] = [] for wallet in self.wallets: # import the multisig hex of other participants and collect results result: MoneroMultisigInitResult = wallet.exchange_multisig_keys(multisig_hexes, TestUtils.WALLET_PASSWORD) + logger.debug(f"Round {i + 1}, multisig init result: {result.serialize()}") assert result.multisig_hex is not None result_multisig_hexes.append(result.multisig_hex) @@ -71,8 +81,5 @@ def test(self) -> None: # TODO: replace with MoneroWallet.get_network_type() when all methods defined in interface MoneroUtils.validate_address(primary_address, TestUtils.NETWORK_TYPE) info: MoneroMultisigInfo = wallet.get_multisig_info() - assert info.is_multisig is True - assert info.is_ready is True - assert self.m == info.threshold - assert self.n == info.num_participants + WalletUtils.test_multisig_info(info, self.m, self.n) wallet.close(True) diff --git a/tests/utils/wallet_utils.py b/tests/utils/wallet_utils.py index e86524a..ed0221c 100644 --- a/tests/utils/wallet_utils.py +++ b/tests/utils/wallet_utils.py @@ -7,7 +7,7 @@ MoneroNetworkType, MoneroUtils, MoneroAccount, MoneroSubaddress, MoneroAddressBookEntry, MoneroMessageSignatureResult, MoneroWallet, - MoneroTxConfig + MoneroTxConfig, MoneroMultisigInfo ) from .gen_utils import GenUtils @@ -234,6 +234,20 @@ def test_wallet_keys(cls, address: str, view_key: str, spend_key: str, w: Monero MoneroUtils.validate_mnemonic(w.get_seed()) assert MoneroWallet.DEFAULT_LANGUAGE == w.get_seed_language() + @classmethod + def test_multisig_info(cls, info: MoneroMultisigInfo, threshold: int, num_participants: int) -> None: + """Test multisignature wallet info. + + :param MoneroMultisigInfo info: wallet multisignature info to test. + :param int threshold: expected multisig threshold. + :param int num_participants: expected number of participants. + """ + logger.debug(f"Testing multisig info: {info.serialize()}") + assert info.is_multisig is True + assert info.is_ready is True + assert threshold == info.threshold + assert num_participants == info.num_participants + @classmethod def build_payment_uri_config(cls, address: str) -> MoneroTxConfig: tx_config = MoneroTxConfig()