1
0

wallet: check that multisig wallet does not have duplicate masterkeys

The wizard should technically disallows this at creation time,
but this second layer sanity check could not hurt.
Also, looks like the wizard check is not working properly atm
(regression from qt wizard refactor).
This commit is contained in:
SomberNight
2023-10-30 17:22:08 +00:00
parent 120faa480e
commit da8e6c2fbf
2 changed files with 95 additions and 0 deletions

View File

@@ -3714,6 +3714,98 @@ class TestWalletOfflineSigning(ElectrumTestCase):
self.assertEqual('4376fa5f1f6cb37b1f3956175d3bd4ef6882169294802b250a3c672f3ff431c1', tx.wtxid())
class TestWalletCreationChecks(ElectrumTestCase):
TESTNET = True
def setUp(self):
super().setUp()
self.config = SimpleConfig({'electrum_path': self.electrum_path})
@mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_duplicate_masterkeys_in_multisig(self, mock_save_db):
# ks1 (seed) and ks2 have same xpub
with self.assertRaises(Exception) as ctx1:
w1 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True),
keystore.from_xpub('Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk'), # collides with seed
keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'),
],
'2of3', gap_limit=2,
config=self.config
)
self.assertIn('duplicate xpubs in multisig', ctx1.exception.args[0])
# ks2 and ks3 have same xpub
with self.assertRaises(Exception) as ctx2:
w2 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True),
keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'),
keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'),
],
'2of3', gap_limit=2,
config=self.config
)
self.assertIn('duplicate xpubs in multisig', ctx2.exception.args[0])
# all xpubs different. should not raise.
w3 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True),
keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'),
keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'),
],
'2of3', gap_limit=2,
config=self.config
)
@mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_heterogeneous_xpub_types_in_multisig(self, mock_save_db):
# tpub + vpub
with self.assertRaises(Exception) as ctx1:
w1 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_xpub('tpubD6NzVbkrYhZ4XYdbWCGSusTDQRAX4UnuqcikJAkqMYxBkvnGfUBvXBE84eyQS6e4To3Pz1xwLrEuxGgQayn4dqVXwNM7dWh4U4DgHai2scz'),
keystore.from_xpub('vpub5VmsevU91fpRaJkfa8b6c9MK53gKY8rSzZjrZdp6dkHZjnFhM1HN74ezHY96JCgFnbQJhRbeUyr5S1vzdcTB6qUKrrG7GBuwPYDTzBjLQmv'),
],
'2of2', gap_limit=2,
config=self.config
)
self.assertIn('multisig wallet needs to have homogeneous xpub types', ctx1.exception.args[0])
# tpub + "segwit" seed
with self.assertRaises(Exception) as ctx2:
w1 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_xpub('tpubD6NzVbkrYhZ4XYdbWCGSusTDQRAX4UnuqcikJAkqMYxBkvnGfUBvXBE84eyQS6e4To3Pz1xwLrEuxGgQayn4dqVXwNM7dWh4U4DgHai2scz'),
keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True),
],
'2of2', gap_limit=2,
config=self.config
)
self.assertIn('multisig wallet needs to have homogeneous xpub types', ctx2.exception.args[0])
# "standard" seed + "segwit" seed
with self.assertRaises(Exception) as ctx3:
w1 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True),
keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True),
],
'2of2', gap_limit=2,
config=self.config
)
self.assertIn('multisig wallet needs to have homogeneous xpub types', ctx3.exception.args[0])
# "old" seed + "standard" seed
with self.assertRaises(Exception) as ctx4:
w1 = WalletIntegrityHelper.create_multisig_wallet(
[
keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True),
keystore.from_seed('powerful random nobody notice nothing important anyway look away hidden message over', '', True),
],
'2of2', gap_limit=2,
config=self.config
)
self.assertIn('unexpected keystore type', ctx4.exception.args[0])
class TestWalletHistory_SimpleRandomOrder(ElectrumTestCase):
TESTNET = True
transactions = {

View File

@@ -3617,6 +3617,9 @@ class Multisig_Wallet(Deterministic_Wallet):
raise Exception(f"unexpected keystore type={type(ks)} in multisig")
if bip32.xpub_type(self.keystore.xpub) != bip32.xpub_type(ks.xpub):
raise Exception(f"multisig wallet needs to have homogeneous xpub types")
bip32_nodes = set({ks.get_bip32_node_for_xpub() for ks in self.get_keystores()})
if len(bip32_nodes) != len(self.get_keystores()):
raise Exception(f"duplicate xpubs in multisig")
def get_public_keys(self, address):
return [pk.hex() for pk in self.get_public_keys_with_deriv_info(address)]