Files
pallectrum/tests/test_wizard.py

486 lines
20 KiB
Python
Raw Normal View History

2024-10-17 00:30:43 +02:00
import os
from electrum import SimpleConfig
from electrum.interface import ServerAddr
from electrum.network import NetworkParameters, ProxySettings
2024-10-17 00:30:43 +02:00
from electrum.plugin import Plugins
from electrum.wizard import ServerConnectWizard, NewWalletWizard
from electrum.daemon import Daemon
from . import ElectrumTestCase
from .test_wallet_vertical import UNICODE_HORROR
2024-10-17 00:30:43 +02:00
class NetworkMock:
def __init__(self):
self.reset()
def reset(self):
self.run_called = False
self.parameters = NetworkParameters(server=None, proxy=None, auto_connect=None, oneserver=None)
def run_from_another_thread(self, *args, **kwargs):
self.run_called = True
def set_parameters(self, parameters):
self.parameters = parameters
def get_parameters(self):
return self.parameters
class DaemonMock:
def __init__(self, config: SimpleConfig):
2024-10-17 00:30:43 +02:00
self.config = config
self.network = NetworkMock()
class WizardTestCase(ElectrumTestCase):
def setUp(self):
super().setUp()
self.config = SimpleConfig({
'electrum_path': self.electrum_path,
'enable_plugin_trustedcoin': True,
})
self.wallet_path = os.path.join(self.electrum_path, "somewallet")
self.plugins = Plugins(self.config, gui_name='cmdline')
self.plugins.load_plugin_by_name('trustedcoin')
2024-10-17 00:30:43 +02:00
def tearDown(self):
self.plugins.stop()
self.plugins.stopped_event.wait()
super().tearDown()
2024-10-17 00:30:43 +02:00
class ServerConnectWizardTestCase(WizardTestCase):
async def test_no_advanced(self):
w = ServerConnectWizard(DaemonMock(self.config))
v_init = w.start()
d = {'autoconnect': True, 'want_proxy': False}
self.assertTrue(w.is_last_view(v_init.view, d))
w.resolve_next(v_init.view, d)
self.assertEqual(True, self.config.NETWORK_AUTO_CONNECT)
async def test_server(self):
w = ServerConnectWizard(DaemonMock(self.config))
v_init = w.start()
d = {'autoconnect': False, 'want_proxy': False}
self.assertFalse(w.is_last_view(v_init.view, d))
v = w.resolve_next(v_init.view, d)
self.assertEqual('server_config', v.view)
self.assertEqual(False, self.config.NETWORK_AUTO_CONNECT)
async def test_proxy(self):
w = ServerConnectWizard(DaemonMock(self.config))
v_init = w.start()
w._daemon.network.reset()
d = {'autoconnect': True, 'want_proxy': True}
self.assertFalse(w.is_last_view(v_init.view, d))
v = w.resolve_next(v_init.view, d)
self.assertEqual('proxy_config', v.view)
self.assertEqual(True, self.config.NETWORK_AUTO_CONNECT)
d_proxy = {'enabled': True, 'mode': 'socks5', 'host': 'localhost', 'port': '1'}
d.update({'proxy': d_proxy})
v = w.resolve_next(v.view, d)
self.assertTrue(w.is_last_view(v.view, d))
self.assertTrue(w._daemon.network.run_called)
self.assertEqual(NetworkParameters(server=None, proxy=ProxySettings.from_dict(d_proxy), auto_connect=True, oneserver=None), w._daemon.network.parameters)
2024-10-17 00:30:43 +02:00
async def test_proxy_and_server(self):
w = ServerConnectWizard(DaemonMock(self.config))
v_init = w.start()
w._daemon.network.reset()
d = {'autoconnect': False, 'want_proxy': True}
self.assertFalse(w.is_last_view(v_init.view, d))
v = w.resolve_next(v_init.view, d)
self.assertEqual('proxy_config', v.view)
self.assertEqual(False, self.config.NETWORK_AUTO_CONNECT)
d_proxy = {'enabled': False}
d.update({'proxy': d_proxy})
v = w.resolve_next(v.view, d)
w._daemon.network.reset()
self.assertEqual('server_config', v.view)
d.update({'server': 'localhost:1:t'})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
serverobj = ServerAddr.from_str_with_inference('localhost:1:t')
self.assertTrue(w._daemon.network.run_called)
self.assertEqual(NetworkParameters(server=serverobj, proxy=None, auto_connect=False, oneserver=False), w._daemon.network.parameters)
2024-10-17 00:30:43 +02:00
class WalletWizardTestCase(WizardTestCase):
def wizard_for(self, *, name, wallet_type):
w = NewWalletWizard(DaemonMock(self.config), self.plugins)
if wallet_type == '2fa':
w.plugins.get_plugin('trustedcoin').extend_wizard(w)
v_init = w.start()
self.assertEqual('wallet_name', v_init.view)
d = {'wallet_name': name}
self.assertFalse(w.is_last_view(v_init.view, d))
v = w.resolve_next(v_init.view, d)
self.assertEqual('wallet_type', v.view)
d.update({'wallet_type': wallet_type})
w.resolve_next(v.view, d)
return w
async def test_create_standard_wallet_createseed(self):
2024-10-17 00:30:43 +02:00
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'createseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('create_seed', v.view)
d.update({
'seed': '9dk', 'seed_type': 'segwit', 'seed_extend': False, 'seed_variant': 'electrum',
})
2024-10-17 00:30:43 +02:00
v = w.resolve_next(v.view, d)
self.assertEqual('confirm_seed', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qq2tmmcngng78nllq2pvrkchcdukemtj56uyue0", wallet.get_receiving_addresses()[0])
2024-10-17 00:30:43 +02:00
async def test_create_standard_wallet_createseed_passphrase(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'createseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('create_seed', v.view)
d.update({
'seed': '9dk', 'seed_type': 'segwit', 'seed_extend': True, 'seed_variant': 'electrum',
})
v = w.resolve_next(v.view, d)
self.assertEqual('create_ext', v.view)
d.update({'seed_extra_words': UNICODE_HORROR})
v = w.resolve_next(v.view, d)
self.assertEqual('confirm_seed', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('confirm_ext', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qgvx24uzdv4mapfmtlu8azty5fxdcw9ghxu4pr4", wallet.get_receiving_addresses()[0])
async def test_create_standard_wallet_haveseed_electrum_oldseed(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_seed', v.view)
d.update({
'seed': 'powerful random nobody notice nothing important anyway look away hidden message over',
'seed_type': 'old', 'seed_extend': False, 'seed_variant': 'electrum'})
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("1FJEEB8ihPMbzs2SkLmr37dHyRFzakqUmo", wallet.get_receiving_addresses()[0])
async def test_create_standard_wallet_haveseed_electrum_oldseed_passphrase(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_seed', v.view)
d.update({
'seed': 'powerful random nobody notice nothing important anyway look away hidden message over',
'seed_type': 'old', 'seed_extend': True, 'seed_variant': 'electrum'})
v = w.resolve_next(v.view, d)
# FIXME this diverges from the actual GUIs :(
# the GUIs do validation using wizard.validate_seed() and don't go to 'have_ext' for next view.
# the validation should be moved to the base impl!
self.assertEqual('have_ext', v.view)
d.update({'seed_extra_words': UNICODE_HORROR})
with self.assertRaises(Exception) as ctx:
v = w.resolve_next(v.view, d)
self.assertTrue("cannot have passphrase" in ctx.exception.args[0])
2024-10-17 00:30:43 +02:00
async def test_create_standard_wallet_haveseed_electrum(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_seed', v.view)
d.update({'seed': '9dk', 'seed_type': 'segwit', 'seed_extend': False, 'seed_variant': 'electrum'})
2024-10-17 00:30:43 +02:00
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qq2tmmcngng78nllq2pvrkchcdukemtj56uyue0", wallet.get_receiving_addresses()[0])
2024-10-17 00:30:43 +02:00
async def test_create_standard_wallet_haveseed_electrum_passphrase(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_seed', v.view)
d.update({'seed': '9dk', 'seed_type': 'segwit', 'seed_extend': True, 'seed_variant': 'electrum'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_ext', v.view)
d.update({'seed_extra_words': UNICODE_HORROR})
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qgvx24uzdv4mapfmtlu8azty5fxdcw9ghxu4pr4", wallet.get_receiving_addresses()[0])
2024-10-17 00:30:43 +02:00
async def test_create_standard_wallet_haveseed_bip39(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_seed', v.view)
d.update({'seed': '9dk', 'seed_type': 'bip39', 'seed_extend': False, 'seed_variant': 'bip39'})
2024-10-17 00:30:43 +02:00
v = w.resolve_next(v.view, d)
self.assertEqual('script_and_derivation', v.view)
d.update({'script_type': 'p2wpkh', 'derivation_path': 'm'})
2024-10-17 00:30:43 +02:00
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qrjr8qn4669jgr3s34f2pyj9awhz02eyvk5eh8g", wallet.get_receiving_addresses()[0])
2024-10-17 00:30:43 +02:00
async def test_create_standard_wallet_haveseed_bip39_passphrase(self):
w = self.wizard_for(name='test_standard_wallet', wallet_type='standard')
v = w._current
d = v.wizard_data
self.assertEqual('keystore_type', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_seed', v.view)
d.update({'seed': '9dk', 'seed_type': 'bip39', 'seed_extend': True, 'seed_variant': 'bip39'})
v = w.resolve_next(v.view, d)
self.assertEqual('have_ext', v.view)
d.update({'seed_extra_words': UNICODE_HORROR})
v = w.resolve_next(v.view, d)
self.assertEqual('script_and_derivation', v.view)
d.update({'script_type': 'p2wpkh', 'derivation_path': 'm'})
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qjexrunguxz8rlfuul8h4apafyh3sq5yp9kg98j", wallet.get_receiving_addresses()[0])
async def test_2fa_createseed(self):
self.assertTrue(self.config.get('enable_plugin_trustedcoin'))
w = self.wizard_for(name='test_2fa_wallet', wallet_type='2fa')
v = w._current
d = v.wizard_data
self.assertEqual('trustedcoin_start', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_choose_seed', v.view)
d.update({'keystore_type': 'createseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_create_seed', v.view)
d.update({
'seed': 'oblige basket safe educate whale bacon celery demand novel slice various awkward',
'seed_type': '2fa', 'seed_extend': False, 'seed_variant': 'electrum',
})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_confirm_seed', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_tos', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_show_confirm_otp', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qnf5qafvpx0afk47433j3tt30pqkxp5wa263m77wt0pvyqq67rmfs522m94", wallet.get_receiving_addresses()[0])
async def test_2fa_haveseed(self):
self.assertTrue(self.config.get('enable_plugin_trustedcoin'))
w = self.wizard_for(name='test_2fa_wallet', wallet_type='2fa')
v = w._current
d = v.wizard_data
self.assertEqual('trustedcoin_start', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_choose_seed', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_have_seed', v.view)
d.update({
'seed': 'oblige basket safe educate whale bacon celery demand novel slice various awkward',
'seed_type': '2fa', 'seed_extend': False, 'seed_variant': 'electrum',
})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_keep_disable', v.view)
d.update({'trustedcoin_keepordisable': 'keep'})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_tos', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_show_confirm_otp', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qnf5qafvpx0afk47433j3tt30pqkxp5wa263m77wt0pvyqq67rmfs522m94", wallet.get_receiving_addresses()[0])
async def test_2fa_haveseed_passphrase(self):
2024-10-17 00:30:43 +02:00
self.assertTrue(self.config.get('enable_plugin_trustedcoin'))
w = self.wizard_for(name='test_2fa_wallet', wallet_type='2fa')
v = w._current
d = v.wizard_data
self.assertEqual('trustedcoin_start', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_choose_seed', v.view)
d.update({'keystore_type': 'haveseed'})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_have_seed', v.view)
d.update({
'seed': 'oblige basket safe educate whale bacon celery demand novel slice various awkward',
'seed_type': '2fa', 'seed_extend': True, 'seed_variant': 'electrum',
2024-10-17 00:30:43 +02:00
})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_have_ext', v.view)
d.update({'seed_extra_words': UNICODE_HORROR})
v = w.resolve_next(v.view, d)
2024-10-17 00:30:43 +02:00
self.assertEqual('trustedcoin_keep_disable', v.view)
d.update({'trustedcoin_keepordisable': 'keep'})
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_tos', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('trustedcoin_show_confirm_otp', v.view)
v = w.resolve_next(v.view, d)
self.assertEqual('wallet_password', v.view)
d.update({'password': None, 'encrypt': False})
self.assertTrue(w.is_last_view(v.view, d))
v = w.resolve_next(v.view, d)
wallet_path = os.path.join(w._daemon.config.get_datadir_wallet_path(), d['wallet_name'])
w.create_storage(wallet_path, d)
self.assertTrue(os.path.exists(wallet_path))
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
self.assertEqual("bc1qcnu9ay4v3w0tawuxe6wlh6mh33rrpauqnufdgkxx7we8vpx3e6wqa25qud", wallet.get_receiving_addresses()[0])