diff --git a/releases/Next-ChangeLog.md b/releases/Next-ChangeLog.md index a43cec5e..541e3ea8 100644 --- a/releases/Next-ChangeLog.md +++ b/releases/Next-ChangeLog.md @@ -6,6 +6,8 @@ This lists the new changes that have not yet been published in a normal release. - Enhancement: Allow JSON files in `NFC File Share` - Bugfix: UI ordered list alignment in Seed Vault menu +- Bugfix: Do not alow to import multisig wallet duplicate with only keys shuffled + # Mk4 Specific Changes diff --git a/shared/multisig.py b/shared/multisig.py index 599b0563..5d9fa067 100644 --- a/shared/multisig.py +++ b/shared/multisig.py @@ -393,7 +393,7 @@ class MultisigWallet(WalletABC): c = self.find_match(self.M, self.N, lst, addr_fmt=self.addr_fmt) if c: # All details are same: M/N, paths, addr fmt - if self.xpubs != c.xpubs: + if sorted(self.xpubs) != sorted(c.xpubs): return None, ['xpubs'], 0 elif self.name == c.name: return None, [], 1 diff --git a/testing/test_multisig.py b/testing/test_multisig.py index b64e5f52..180c1774 100644 --- a/testing/test_multisig.py +++ b/testing/test_multisig.py @@ -2995,4 +2995,30 @@ def test_txout_explorer(psbtv2, data, clear_ms, import_ms_wallet, fake_ms_txn, start_sign(psbt) txout_explorer(data) + +@pytest.mark.parametrize("desc", [True, False]) +def test_import_duplicate_shuffled_keys(desc, clear_ms, make_multisig, import_ms_wallet, + microsd_path, pick_menu_item, cap_story, goto_home, + press_cancel): + # DO NOT allow to import wsh(sortedmulti(2, A,B)) and wsh(sortedmulti(2, B, A)) + # MUST BE treated as duplicates + clear_ms() + M, N = 2, 3 + wname = "ms02" + keys = make_multisig(M, N) + import_ms_wallet(M, N, addr_fmt="p2wsh", name=wname, accept=True, keys=keys, + descriptor=desc) + # shuffle + keys[0], keys[1] = keys[1], keys[0] + + with pytest.raises(AssertionError): + import_ms_wallet(M, N, addr_fmt="p2wsh", name=wname, accept=True, keys=keys, + descriptor=desc) + + time.sleep(.1) + title, story = cap_story() + assert 'Duplicate wallet' in story + assert 'OK to approve' not in story + press_cancel() + # EOF