From 4f1cc8b9cbb5dc59cfd0538148cfdc90321996c6 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Fri, 8 Aug 2025 16:24:50 +0000 Subject: [PATCH] tests: set low wallet.gap_limit_for_change to speed up tests --- tests/__init__.py | 13 +++++ tests/test_commands.py | 91 +++++++++++++++++--------------- tests/test_contacts.py | 9 ++-- tests/test_daemon.py | 25 +++++---- tests/test_invoices.py | 22 ++++---- tests/test_lnutil.py | 7 +-- tests/test_payment_identifier.py | 6 +-- tests/test_wallet.py | 35 ++++++------ tests/test_wallet_vertical.py | 45 +++++++++------- 9 files changed, 141 insertions(+), 112 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index 624a3e3e0..2c4e6f038 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -4,12 +4,14 @@ import unittest import threading import tempfile import shutil +import functools import electrum import electrum.logging from electrum import constants from electrum import util from electrum.logging import Logger +from electrum.wallet import restore_wallet_from_text # Set this locally to make the test suite run faster. @@ -92,3 +94,14 @@ def as_testnet(func): finally: constants.net = old_net return run_test + + +@functools.wraps(restore_wallet_from_text) +def restore_wallet_from_text__for_unittest(*args, gap_limit=2, gap_limit_for_change=1, **kwargs): + """much lower default gap limits (to save compute time)""" + return restore_wallet_from_text( + *args, + gap_limit=gap_limit, + gap_limit_for_change=gap_limit_for_change, + **kwargs, + ) diff --git a/tests/test_commands.py b/tests/test_commands.py index 7a888ad66..c312daa79 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -7,7 +7,7 @@ from os import urandom from electrum.commands import Commands, eval_bool from electrum import storage, wallet from electrum.lnworker import RecvMPPResolution -from electrum.wallet import restore_wallet_from_text, Abstract_Wallet +from electrum.wallet import Abstract_Wallet from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED from electrum.simple_config import SimpleConfig from electrum.transaction import Transaction, TxOutput, tx_from_any @@ -16,6 +16,7 @@ from electrum.crypto import sha256 from electrum.lnaddr import lndecode from . import ElectrumTestCase +from . import restore_wallet_from_text__for_unittest from .test_wallet_vertical import WalletIntegrityHelper @@ -91,9 +92,10 @@ class TestCommands(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_encrypt_decrypt(self, mock_save_db): - wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN', - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] cmds = Commands(config=self.config) cleartext = "asdasd this is the message" pubkey = "021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da" @@ -102,9 +104,10 @@ class TestCommands(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_export_private_key_imported(self, mock_save_db): - wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL', - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] cmds = Commands(config=self.config) # single address tests with self.assertRaises(UserFacingException): @@ -121,10 +124,10 @@ class TestCommands(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_export_private_key_deterministic(self, mock_save_db): - wallet = restore_wallet_from_text('bitter grass shiver impose acquire brush forget axis eager alone wine silver', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'bitter grass shiver impose acquire brush forget axis eager alone wine silver', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] cmds = Commands(config=self.config) # single address tests with self.assertRaises(UserFacingException): @@ -150,10 +153,10 @@ class TestCommands(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_decrypt_enforces_strict_base64(self, mock_save_db): cmds = Commands(config=self.config) - wallet = restore_wallet_from_text('9dk', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] # type: Abstract_Wallet + wallet = restore_wallet_from_text__for_unittest( + '9dk', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # type: Abstract_Wallet plaintext = "hello there" ciphertext = "QklFMQJEFgxfkXj+UNblbHR+4y6ZA2rGEeEhWo7h84lBFjlRY5JOPfV1zyC1fw5YmhIr7+3ceIV11lpf/Yv7gSqQCQ5Wuf1aGXceHZO0GjKVxBsuew==" pubkey = "02a0507c8bb3d96dfd7731bafb0ae30e6ed10bbadd6a9f9f88eaf0602b9cc99adc" @@ -234,10 +237,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_getprivatekeyforpath(self, mock_save_db): - wallet = restore_wallet_from_text('north rent dawn bunker hamster invest wagon market romance pig either squeeze', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'north rent dawn bunker hamster invest wagon market romance pig either squeeze', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] cmds = Commands(config=self.config) self.assertEqual("p2wpkh:cUzm7zPpWgLYeURgff4EsoMjhskCpsviBH4Y3aZcrBX8UJSRPjC2", await cmds.getprivatekeyforpath([0, 10000], wallet=wallet)) @@ -248,10 +251,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_payto(self, mock_save_db): - wallet = restore_wallet_from_text('disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # bootstrap wallet funding_tx = Transaction('0200000000010165806607dd458280cb57bf64a16cf4be85d053145227b98c28932e953076b8e20000000000fdffffff02ac150700000000001600147e3ddfe6232e448a8390f3073c7a3b2044fd17eb102908000000000016001427fbe3707bc57e5bb63d6f15733ec88626d8188a02473044022049ce9efbab88808720aa563e2d9bc40226389ab459c4390ea3e89465665d593502206c1c7c30a2f640af1e463e5107ee4cfc0ee22664cfae3f2606a95303b54cdef80121026269e54d06f7070c1f967eb2874ba60de550dfc327a945c98eb773672d9411fd77181e00') funding_txid = funding_tx.txid() @@ -276,10 +279,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_payto__confirmed_only(self, mock_save_db): """test that payto respects 'confirmed_only' config var""" - wallet = restore_wallet_from_text('disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # bootstrap wallet funding_tx = Transaction('0200000000010165806607dd458280cb57bf64a16cf4be85d053145227b98c28932e953076b8e20000000000fdffffff02ac150700000000001600147e3ddfe6232e448a8390f3073c7a3b2044fd17eb102908000000000016001427fbe3707bc57e5bb63d6f15733ec88626d8188a02473044022049ce9efbab88808720aa563e2d9bc40226389ab459c4390ea3e89465665d593502206c1c7c30a2f640af1e463e5107ee4cfc0ee22664cfae3f2606a95303b54cdef80121026269e54d06f7070c1f967eb2874ba60de550dfc327a945c98eb773672d9411fd77181e00') funding_txid = funding_tx.txid() @@ -310,10 +313,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_paytomany_multiple_max_spends(self, mock_save_db): - wallet = restore_wallet_from_text('kit virtual quantum festival fortune inform ladder saddle filter soldier start ghost', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'kit virtual quantum festival fortune inform ladder saddle filter soldier start ghost', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # bootstrap wallet funding_tx = Transaction('02000000000101f59876b1c65bbe3e182ccc7ea7224fe397bb9b70aadcbbf4f4074c75c8a074840000000000fdffffff021f351f00000000001600144eec851dd980cc36af1f629a32325f511604d6af56732d000000000016001439267bc7f3e3fabeae3bc3f73880de22d8b01ba50247304402207eac5f639806a00878488d58ca651d690292145bca5511531845ae21fab309d102207162708bd344840cc1bacff1092e426eb8484f83f5c068ba4ca579813de324540121020e0798c267ff06ee8b838cd465f3cfa6c843a122a04917364ce000c29ca205cae5f31f00') funding_txid = funding_tx.txid() @@ -345,10 +348,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_signtransaction_with_wallet(self, mock_save_db): - wallet = restore_wallet_from_text('bitter grass shiver impose acquire brush forget axis eager alone wine silver', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'bitter grass shiver impose acquire brush forget axis eager alone wine silver', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # bootstrap wallet1 funding_tx = Transaction('01000000014576dacce264c24d81887642b726f5d64aa7825b21b350c7b75a57f337da6845010000006b483045022100a3f8b6155c71a98ad9986edd6161b20d24fad99b6463c23b463856c0ee54826d02200f606017fd987696ebbe5200daedde922eee264325a184d5bbda965ba5160821012102e5c473c051dae31043c335266d0ef89c1daab2f34d885cc7706b267f3269c609ffffffff0240420f00000000001600148a28bddb7f61864bdcf58b2ad13d5aeb3abc3c42a2ddb90e000000001976a914c384950342cb6f8df55175b48586838b03130fad88ac00000000') @@ -366,10 +369,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_bumpfee(self, mock_save_db): - wallet = restore_wallet_from_text('right nominee cheese afford exotic pilot mask illness rug fringe degree pottery', - gap_limit=2, - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] # type: Abstract_Wallet + wallet = restore_wallet_from_text__for_unittest( + 'right nominee cheese afford exotic pilot mask illness rug fringe degree pottery', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # type: Abstract_Wallet funding_tx = Transaction("02000000000102789e8aa8caa79d87241ff9df0e3fd757a07c85a30195d76e8efced1d57c56b670000000000fdffffff7ee2b6abd52b332f797718ae582f8d3b979b83b1799e0a3bfb2c90c6e070c29e0100000000fdffffff020820000000000000160014c0eb720c93a61615d2d66542d381be8943ca553950c3000000000000160014d7dbd0196a2cbd76420f14a19377096cf6cddb75024730440220485b491ad8d3ce3b4da034a851882da84a06ec9800edff0d3fd6aa42eeba3b440220359ea85d32a05932ac417125e133fa54e54e7e9cd20ebc54b883576b8603fd65012103860f1fbf8a482b9d35d7d4d04be8fb33d856a514117cd8b73e372d36895feec60247304402206c2ca56cc030853fa59b4b3cb293f69a3378ead0f10cb76f640f8c2888773461022079b7055d0f6af6952a48e5b97218015b0723462d667765c142b41bd35e3d9c0a01210359e303f57647094a668d69e8ff0bd46c356d00aa7da6dc533c438e71c057f0793e721f00") funding_txid = funding_tx.txid() @@ -397,9 +400,10 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_importprivkey(self, mock_save_db): - wallet = restore_wallet_from_text('p2wpkh:cQUdWZehnGDwGn7CSc911cJBcWTAcnyzpLoJYTsFNYW1w6iaq7Nw p2wpkh:cNHsDLo137ngrr2wGf3mwqpwTUvpuDVAZrqzan9heHcMTK4rP5JB', - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + 'p2wpkh:cQUdWZehnGDwGn7CSc911cJBcWTAcnyzpLoJYTsFNYW1w6iaq7Nw p2wpkh:cNHsDLo137ngrr2wGf3mwqpwTUvpuDVAZrqzan9heHcMTK4rP5JB', + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] cmds = Commands(config=self.config) self.assertEqual(2, len(wallet.get_addresses())) # try importing a single bad privkey @@ -435,9 +439,8 @@ class TestCommandsTestnet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_hold_invoice_commands(self, mock_save_db): - wallet: Abstract_Wallet = restore_wallet_from_text( + wallet: Abstract_Wallet = restore_wallet_from_text__for_unittest( 'disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic', - gap_limit=2, path='if_this_exists_mocking_failed_648151893', config=self.config)['wallet'] diff --git a/tests/test_contacts.py b/tests/test_contacts.py index b2c28e00b..d1c920d44 100644 --- a/tests/test_contacts.py +++ b/tests/test_contacts.py @@ -1,11 +1,12 @@ import os -from . import ElectrumTestCase - from electrum.simple_config import SimpleConfig -from electrum.wallet import restore_wallet_from_text, Abstract_Wallet +from electrum.wallet import Abstract_Wallet from electrum.daemon import Daemon +from . import ElectrumTestCase +from . import restore_wallet_from_text__for_unittest + class TestContacts(ElectrumTestCase): TESTNET = True @@ -17,7 +18,7 @@ class TestContacts(ElectrumTestCase): async def test_saving_contacts(self): text = 'cross end slow expose giraffe fuel track awake turtle capital ranch pulp' - d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, config=self.config) w = d['wallet'] # type: Abstract_Wallet w.contacts["myNNuLYNgHE92nGQuJd5mXo6gy9gKXEDyQ"] = ("address", "alice") w.contacts["tb1q4syjltptqwhe62t3u5gwz9nsw87kmcwx003z05"] = ("address", "bob") diff --git a/tests/test_daemon.py b/tests/test_daemon.py index ed60e421a..5cb6c619f 100644 --- a/tests/test_daemon.py +++ b/tests/test_daemon.py @@ -4,10 +4,10 @@ from typing import Optional, Iterable from electrum.commands import Commands from electrum.daemon import Daemon from electrum.simple_config import SimpleConfig -from electrum.wallet import restore_wallet_from_text, Abstract_Wallet +from electrum.wallet import Abstract_Wallet from electrum import util -from . import ElectrumTestCase, as_testnet +from . import ElectrumTestCase, as_testnet, restore_wallet_from_text__for_unittest class DaemonTestCase(ElectrumTestCase): @@ -34,12 +34,11 @@ class DaemonTestCase(ElectrumTestCase): """Returns path for created wallet.""" basename = util.get_new_wallet_name(self.wallet_dir) path = os.path.join(self.wallet_dir, basename) - wallet_dict = restore_wallet_from_text( + wallet_dict = restore_wallet_from_text__for_unittest( text, path=path, password=password, encrypt_file=encrypt_file, - gap_limit=2, config=self.config, ) # We return the path instead of the wallet object, as extreme @@ -193,19 +192,19 @@ class TestCommandsWithDaemon(DaemonTestCase): async def test_wp_command_with_inmemory_wallet_has_password(self): cmds = Commands(config=self.config, daemon=self.daemon) - wallet = restore_wallet_from_text(self.SEED, - gap_limit=2, - path=None, - password="123456", - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + self.SEED, + path=None, + password="123456", + config=self.config)['wallet'] self.assertEqual(self.SEED, await cmds.getseed(wallet=wallet, password="123456")) async def test_wp_command_with_inmemory_wallet_no_password(self): cmds = Commands(config=self.config, daemon=self.daemon) - wallet = restore_wallet_from_text(self.SEED, - gap_limit=2, - path=None, - config=self.config)['wallet'] + wallet = restore_wallet_from_text__for_unittest( + self.SEED, + path=None, + config=self.config)['wallet'] self.assertEqual(self.SEED, await cmds.getseed(wallet=wallet)) async def test_wp_command_with_diskfile_wallet_has_password(self): diff --git a/tests/test_invoices.py b/tests/test_invoices.py index d155b3694..d1f1a5c2f 100644 --- a/tests/test_invoices.py +++ b/tests/test_invoices.py @@ -1,16 +1,18 @@ import os import time -from . import ElectrumTestCase - from electrum.simple_config import SimpleConfig -from electrum.wallet import restore_wallet_from_text, Standard_Wallet, Abstract_Wallet +from electrum.wallet import Standard_Wallet, Abstract_Wallet from electrum.invoices import PR_UNPAID, PR_PAID, PR_UNCONFIRMED, BaseInvoice, Invoice, LN_EXPIRY_NEVER from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED from electrum.transaction import Transaction, PartialTxOutput from electrum.util import TxMinedInfo, InvoiceError from electrum.fee_policy import FixedFeePolicy +from . import ElectrumTestCase +from . import restore_wallet_from_text__for_unittest + + class TestWalletPaymentRequests(ElectrumTestCase): """test 'incoming' invoices""" TESTNET = True @@ -28,7 +30,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): def create_wallet2(self) -> Standard_Wallet: text = 'cross end slow expose giraffe fuel track awake turtle capital ranch pulp' - d = restore_wallet_from_text(text, path=self.wallet2_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet2_path, config=self.config) wallet2 = d['wallet'] # type: Standard_Wallet # bootstrap wallet funding_tx = Transaction('0200000000010132515e6aade1b79ec7dd3bac0896d8b32c56195d23d07d48e21659cef24301560100000000fdffffff0112841e000000000016001477fe6d2a27e8860c278d4d2cd90bad716bb9521a02473044022041ed68ef7ef122813ac6a5e996b8284f645c53fbe6823b8e430604a8915a867802203233f5f4d347a687eb19b2aa570829ab12aeeb29a24cc6d6d20b8b3d79e971ae012102bee0ee043817e50ac1bb31132770f7c41e35946ccdcb771750fb9696bdd1b307ad951d00') @@ -39,7 +41,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): async def test_wallet_with_ln_creates_payreq_and_gets_paid_on_ln(self): text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet1_path, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet self.assertIsNotNone(wallet1.lnworker) self.assertTrue(wallet1.has_lightning()) @@ -56,7 +58,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): async def test_wallet_with_ln_creates_payreq_and_gets_paid_onchain(self): text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet1_path, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet wallet1.db.put('stored_height', 1000) self.assertIsNotNone(wallet1.lnworker) @@ -87,7 +89,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): async def test_wallet_without_ln_creates_payreq_and_gets_paid_onchain(self): text = 'cycle rocket west magnet parrot shuffle foot correct salt library feed song' - d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet1_path, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet wallet1.db.put('stored_height', 1000) self.assertIsNone(wallet1.lnworker) @@ -118,7 +120,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): async def test_wallet_gets_paid_onchain_in_the_past(self): text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet1_path, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet wallet1.db.put('stored_height', 1000) self.assertIsNotNone(wallet1.lnworker) @@ -148,7 +150,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): async def test_wallet_reuse_addr_of_expired_request(self): text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=3, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet1_path, gap_limit=3, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet self.assertIsNotNone(wallet1.lnworker) self.assertTrue(wallet1.has_lightning()) @@ -176,7 +178,7 @@ class TestWalletPaymentRequests(ElectrumTestCase): async def test_wallet_get_request_by_addr(self): text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=3, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet1_path, gap_limit=3, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet self.assertIsNotNone(wallet1.lnworker) self.assertTrue(wallet1.has_lightning()) diff --git a/tests/test_lnutil.py b/tests/test_lnutil.py index 7d9e49725..273e9d041 100644 --- a/tests/test_lnutil.py +++ b/tests/test_lnutil.py @@ -15,10 +15,11 @@ from electrum.lnutil import ( from electrum.util import bfh, MyEncoder from electrum.transaction import Transaction, PartialTransaction, Sighash from electrum.lnworker import LNWallet -from electrum.wallet import restore_wallet_from_text, Standard_Wallet +from electrum.wallet import Standard_Wallet from electrum.simple_config import SimpleConfig from . import ElectrumTestCase, as_testnet +from . import restore_wallet_from_text__for_unittest from .test_bitcoin import disable_ecdsa_r_value_grinding @@ -1069,7 +1070,7 @@ class TestLNUtil(ElectrumTestCase): async def test_decode_imported_channel_backup_v0(self): encrypted_cb = "channel_backup:Adn87xcGIs9H2kfp4VpsOaNKWCHX08wBoqq37l1cLYKGlJamTeoaLEwpJA81l1BXF3GP/mRxqkY+whZG9l51G8izIY/kmMSvnh0DOiZEdwaaT/1/MwEHfsEomruFqs+iW24SFJPHbMM7f80bDtIxcLfZkKmgcKBAOlcqtq+dL3U3yH74S8BDDe2L4snaxxpCjF0JjDMBx1UR/28D+QlIi+lbvv1JMaCGXf+AF1+3jLQf8+lVI+rvFdyArws6Ocsvjf+ANQeSGUwW6Nb2xICQcMRgr1DO7bO4pgGu408eYRr2v3ayJBVtnKwSwd49gF5SDSjTDAO4CCM0uj9H5RxyzH7fqotkd9J80MBr84RiBXAeXKz+Ap8608/FVqgQ9BOcn6LhuAQdE5zXpmbQyw5jUGkPvHuseR+rzthzncy01odUceqTNg==" config = SimpleConfig({'electrum_path': self.electrum_path}) - d = restore_wallet_from_text("9dk", path=None, gap_limit=2, config=config) + d = restore_wallet_from_text__for_unittest("9dk", path=None, config=config) wallet1 = d['wallet'] # type: Standard_Wallet decoded_cb = ImportedChannelBackupStorage.from_encrypted_str(encrypted_cb, password=wallet1.get_fingerprint()) self.assertEqual( @@ -1097,7 +1098,7 @@ class TestLNUtil(ElectrumTestCase): async def test_decode_imported_channel_backup_v1(self): encrypted_cb = "channel_backup:AVYIedu0qSLfY2M2bBxF6dA4RAxcmobp+3h9mxALWWsv5X7hhNg0XYOKNd11FE6BJOZgZnIZ4CCAlHtLNj0/9S5GbNhbNZiQXxeHMwC1lHvtjawkwSejIJyOI52DkDFHBAGZRd4fJjaPJRHnUizWfySVR4zjd08lTinpoIeL7C7tXBW1N6YqceqV7RpeoywlBXJtFfCCuw0hnUKgq3SMlBKapkNAIgGrg15aIHNcYeENxCxr5FD1s7DIwFSECqsBVnu/Ogx2oii8BfuxqJq8vuGq4Ib/BVaSVtdb2E1wklAor/CG0p9Fg9mFWND98JD+64nz9n/knPFFyHxTXErn+ct3ZcStsLYynWKUIocgu38PtzCJ7r5ivqOw4O49fbbzdjcgMUGklPYxjuinETneCo+dCPa1uepOGTqeOYmnjVYtYZYXOlWV1F5OtNoM7MwwJjAbz84=" config = SimpleConfig({'electrum_path': self.electrum_path}) - d = restore_wallet_from_text("9dk", path=None, gap_limit=2, config=config) + d = restore_wallet_from_text__for_unittest("9dk", path=None, config=config) wallet1 = d['wallet'] # type: Standard_Wallet decoded_cb = ImportedChannelBackupStorage.from_encrypted_str(encrypted_cb, password=wallet1.get_fingerprint()) self.assertEqual( diff --git a/tests/test_payment_identifier.py b/tests/test_payment_identifier.py index c007f1b47..6f4b4f506 100644 --- a/tests/test_payment_identifier.py +++ b/tests/test_payment_identifier.py @@ -4,10 +4,10 @@ from electrum import SimpleConfig from electrum.invoices import Invoice from electrum.payment_identifier import (maybe_extract_lightning_payment_identifier, PaymentIdentifier, PaymentIdentifierType, invoice_from_payment_identifier) -from electrum.wallet import restore_wallet_from_text +from electrum.transaction import PartialTxOutput from . import ElectrumTestCase -from electrum.transaction import PartialTxOutput +from . import restore_wallet_from_text__for_unittest class WalletMock: @@ -286,7 +286,7 @@ class TestPaymentIdentifier(ElectrumTestCase): self.assertEqual(2_000_000_000, invoice.amount_msat) text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text(text, path=self.wallet2_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet2_path, config=self.config) wallet2 = d['wallet'] # type: Standard_Wallet # no amount bip21+lightning, MAX amount passed diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 0fa9d8910..759bcbd28 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -11,7 +11,7 @@ import asyncio from electrum.storage import WalletStorage from electrum.wallet_db import FINAL_SEED_VERSION from electrum.wallet import (Abstract_Wallet, Standard_Wallet, create_new_wallet, - restore_wallet_from_text, Imported_Wallet, Wallet) + Imported_Wallet, Wallet) from electrum.exchange_rate import ExchangeBase, FxThread from electrum.util import TxMinedInfo, InvalidPassword from electrum.bitcoin import COIN @@ -24,6 +24,7 @@ from electrum.transaction import tx_from_any from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED from . import ElectrumTestCase +from . import restore_wallet_from_text__for_unittest class FakeSynchronizer(object): @@ -93,7 +94,7 @@ class TestWalletStorage(WalletTestCase): 'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL', 'p2wpkh:L24GxnN7NNUAfCXA6hFzB1jt59fYAAiFZMcLaJ2ZSawGpM3uqhb1' ]) - d = restore_wallet_from_text(text, path=self.wallet_path, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, config=self.config) wallet = d['wallet'] # type: Imported_Wallet self.assertEqual(2, len(wallet.get_receiving_addresses())) await wallet.stop() @@ -118,7 +119,7 @@ class TestWalletStorage(WalletTestCase): async def test_storage_prevouts_by_scripthash_persistence(self): text = 'cycle rocket west magnet parrot shuffle foot correct salt library feed song' - d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=2, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, config=self.config) wallet1 = d['wallet'] # type: Standard_Wallet # create payreq addr = wallet1.get_unused_address() @@ -224,6 +225,7 @@ class TestCreateRestoreWallet(WalletTestCase): password=password, encrypt_file=encrypt_file, gap_limit=1, + gap_limit_for_change=1, config=self.config) wallet = d['wallet'] # type: Standard_Wallet @@ -240,13 +242,14 @@ class TestCreateRestoreWallet(WalletTestCase): passphrase = 'mypassphrase' password = 'mypassword' encrypt_file = True - d = restore_wallet_from_text(text, - path=self.wallet_path, - passphrase=passphrase, - password=password, - encrypt_file=encrypt_file, - gap_limit=1, - config=self.config) + d = restore_wallet_from_text__for_unittest( + text, + path=self.wallet_path, + passphrase=passphrase, + password=password, + encrypt_file=encrypt_file, + gap_limit=1, + config=self.config) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(passphrase, wallet.keystore.get_passphrase(password)) self.assertEqual(text, wallet.keystore.get_seed(password)) @@ -255,7 +258,7 @@ class TestCreateRestoreWallet(WalletTestCase): async def test_restore_wallet_from_text_no_storage(self): text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' - d = restore_wallet_from_text( + d = restore_wallet_from_text__for_unittest( text, path=None, gap_limit=1, @@ -268,28 +271,28 @@ class TestCreateRestoreWallet(WalletTestCase): async def test_restore_wallet_from_text_xpub(self): text = 'zpub6nydoME6CFdJtMpzHW5BNoPz6i6XbeT9qfz72wsRqGdgGEYeivso6xjfw8cGcCyHwF7BNW4LDuHF35XrZsovBLWMF4qXSjmhTXYiHbWqGLt' - d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, gap_limit=1, config=self.config) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(text, wallet.keystore.get_master_public_key()) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) async def test_restore_wallet_from_text_xkey_that_is_also_a_valid_electrum_seed_by_chance(self): text = 'yprvAJBpuoF4FKpK92ofzQ7ge6VJMtorow3maAGPvPGj38ggr2xd1xCrC9ojUVEf9jhW5L9SPu6fU2U3o64cLrRQ83zaQGNa6YP3ajZS6hHNPXj' - d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, gap_limit=1, config=self.config) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(text, wallet.keystore.get_master_private_key(password=None)) self.assertEqual('3Pa4hfP3LFWqa2nfphYaF7PZfdJYNusAnp', wallet.get_receiving_addresses()[0]) async def test_restore_wallet_from_text_xprv(self): text = 'zprvAZzHPqhCMt51fskXBUYB1fTFYgG3CBjJUT4WEZTpGw6hPSDWBPZYZARC5sE9xAcX8NeWvvucFws8vZxEa65RosKAhy7r5MsmKTxr3hmNmea' - d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, gap_limit=1, config=self.config) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(text, wallet.keystore.get_master_private_key(password=None)) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) async def test_restore_wallet_from_text_addresses(self): text = 'bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw bc1qnp78h78vp92pwdwq5xvh8eprlga5q8gu66960c' - d = restore_wallet_from_text(text, path=self.wallet_path, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, config=self.config) wallet = d['wallet'] # type: Imported_Wallet self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) self.assertEqual(2, len(wallet.get_receiving_addresses())) @@ -299,7 +302,7 @@ class TestCreateRestoreWallet(WalletTestCase): async def test_restore_wallet_from_text_privkeys(self): text = 'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL p2wpkh:L24GxnN7NNUAfCXA6hFzB1jt59fYAAiFZMcLaJ2ZSawGpM3uqhb1' - d = restore_wallet_from_text(text, path=self.wallet_path, config=self.config) + d = restore_wallet_from_text__for_unittest(text, path=self.wallet_path, config=self.config) wallet = d['wallet'] # type: Imported_Wallet addr0 = wallet.get_receiving_addresses()[0] self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', addr0) diff --git a/tests/test_wallet_vertical.py b/tests/test_wallet_vertical.py index aa53b0886..700e9e47c 100644 --- a/tests/test_wallet_vertical.py +++ b/tests/test_wallet_vertical.py @@ -11,7 +11,7 @@ from electrum import SimpleConfig from electrum import util from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_LOCAL, TX_HEIGHT_FUTURE from electrum.wallet import (sweep, Multisig_Wallet, Standard_Wallet, Imported_Wallet, - restore_wallet_from_text, Abstract_Wallet, CannotBumpFee, BumpFeeStrategy, + Abstract_Wallet, CannotBumpFee, BumpFeeStrategy, TransactionPotentiallyDangerousException, TransactionDangerousException, TxSighashRiskLevel) from electrum.util import bfh, NotEnoughFunds, UnrelatedTransactionException, UserFacingException, TxMinedInfo @@ -23,6 +23,7 @@ from electrum.network import Network from electrum.plugins.trustedcoin import trustedcoin from . import ElectrumTestCase +from . import restore_wallet_from_text__for_unittest UNICODE_HORROR_HEX = 'e282bf20f09f988020f09f98882020202020e3818620e38191e3819fe381be20e3828fe3828b2077cda2cda2cd9d68cda16fcda2cda120ccb8cda26bccb5cd9f6eccb4cd98c7ab77ccb8cc9b73cd9820cc80cc8177cd98cda2e1b8a9ccb561d289cca1cda27420cca7cc9568cc816fccb572cd8fccb5726f7273cca120ccb6cda1cda06cc4afccb665cd9fcd9f20ccb6cd9d696ecda220cd8f74cc9568ccb7cca1cd9f6520cd9fcd9f64cc9b61cd9c72cc95cda16bcca2cca820cda168ccb465cd8f61ccb7cca2cca17274cc81cd8f20ccb4ccb7cda0c3b2ccb5ccb666ccb82075cca7cd986ec3adcc9bcd9c63cda2cd8f6fccb7cd8f64ccb8cda265cca1cd9d3fcd9e' @@ -33,6 +34,7 @@ assert UNICODE_HORROR == '₿ 😀 😈 う けたま わる w͢͢͝h͡o͢͡ class WalletIntegrityHelper: gap_limit = 1 # make tests run faster + gap_limit_for_change = 1 # make tests run faster # TODO also use short gap limit for change addrs, for performance @classmethod @@ -50,10 +52,11 @@ class WalletIntegrityHelper: test_obj.assertFalse(ks.has_seed()) @classmethod - def create_standard_wallet(cls, ks, *, config: SimpleConfig, gap_limit=None): + def create_standard_wallet(cls, ks, *, config: SimpleConfig, gap_limit=None, gap_limit_for_change=None): db = storage.WalletDB('', storage=None, upgrade=True) db.put('keystore', ks.dump()) db.put('gap_limit', gap_limit or cls.gap_limit) + db.put('gap_limit_for_change', gap_limit_for_change or cls.gap_limit_for_change) w = Standard_Wallet(db, config=config) w.synchronize() return w @@ -69,7 +72,7 @@ class WalletIntegrityHelper: @classmethod def create_multisig_wallet(cls, keystores: Sequence, multisig_type: str, *, - config: SimpleConfig, gap_limit=None): + config: SimpleConfig, gap_limit=None, gap_limit_for_change=None): """Creates a multisig wallet.""" db = storage.WalletDB('', storage=None, upgrade=False) for i, ks in enumerate(keystores): @@ -77,6 +80,7 @@ class WalletIntegrityHelper: db.put('x%d' % cosigner_index, ks.dump()) db.put('wallet_type', multisig_type) db.put('gap_limit', gap_limit or cls.gap_limit) + db.put('gap_limit_for_change', gap_limit_for_change or cls.gap_limit_for_change) w = Multisig_Wallet(db, config=config) w.synchronize() return w @@ -2046,7 +2050,7 @@ class TestWalletSending(ElectrumTestCase): def _create_cause_carbon_wallet(self): data = read_test_vector('cause_carbon_wallet.json') ks = keystore.from_seed(data['seed'], passphrase='', for_multisig=False) - wallet = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=2, config=self.config) + wallet = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=2, gap_limit_for_change=2, config=self.config) # bootstrap wallet (incoming funding_tx0) funding_tx = Transaction(data['funding_tx']) wallet.adb.receive_tx_callback(funding_tx, tx_height=TX_HEIGHT_UNCONFIRMED) @@ -2949,7 +2953,7 @@ class TestWalletSending(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_imported_wallet_usechange_off(self, mock_save_db): - wallet = restore_wallet_from_text( + wallet = restore_wallet_from_text__for_unittest( "p2wpkh:cVcwSp488C8Riguq55Tuktgi6TpzuyLdDwUxkBDBz3yzV7FW4af2 p2wpkh:cPWyoPvnv2hiyyxbhMkhX3gPEENzB6DqoP9bbR8SDTg5njK5SL9n", path='if_this_exists_mocking_failed_648151893', config=self.config)['wallet'] # type: Abstract_Wallet @@ -2985,7 +2989,7 @@ class TestWalletSending(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_imported_wallet_usechange_on(self, mock_save_db): - wallet = restore_wallet_from_text( + wallet = restore_wallet_from_text__for_unittest( "p2wpkh:cVcwSp488C8Riguq55Tuktgi6TpzuyLdDwUxkBDBz3yzV7FW4af2 p2wpkh:cPWyoPvnv2hiyyxbhMkhX3gPEENzB6DqoP9bbR8SDTg5njK5SL9n", path='if_this_exists_mocking_failed_648151893', config=self.config)['wallet'] # type: Abstract_Wallet @@ -3020,7 +3024,7 @@ class TestWalletSending(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_imported_wallet_usechange_on__no_more_unused_addresses(self, mock_save_db): - wallet = restore_wallet_from_text( + wallet = restore_wallet_from_text__for_unittest( "p2wpkh:cVcwSp488C8Riguq55Tuktgi6TpzuyLdDwUxkBDBz3yzV7FW4af2 p2wpkh:cPWyoPvnv2hiyyxbhMkhX3gPEENzB6DqoP9bbR8SDTg5njK5SL9n", path='if_this_exists_mocking_failed_648151893', config=self.config)['wallet'] # type: Abstract_Wallet @@ -4259,7 +4263,7 @@ class TestWalletHistory_SimpleRandomOrder(ElectrumTestCase): def create_old_wallet(self): ks = keystore.from_old_mpk('e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3') # seed words: powerful random nobody notice nothing important anyway look away hidden message over - w = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=20, config=self.config) + w = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=20, gap_limit_for_change=6, config=self.config) # some txns are beyond gap limit: w.create_new_address(for_change=True) return w @@ -4364,10 +4368,11 @@ class TestWalletHistory_DoubleSpend(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_restoring_wallet_without_manual_delete(self, mock_save_db): - w = restore_wallet_from_text("small rapid pattern language comic denial donate extend tide fever burden barrel", - path='if_this_exists_mocking_failed_648151893', - gap_limit=5, - config=self.config)['wallet'] # type: Abstract_Wallet + w = restore_wallet_from_text__for_unittest( + "small rapid pattern language comic denial donate extend tide fever burden barrel", + path='if_this_exists_mocking_failed_648151893', + gap_limit=5, + config=self.config)['wallet'] # type: Abstract_Wallet for txid in self.transactions: tx = Transaction(self.transactions[txid]) w.adb.add_transaction(tx) @@ -4378,10 +4383,11 @@ class TestWalletHistory_DoubleSpend(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_restoring_wallet_with_manual_delete(self, mock_save_db): - w = restore_wallet_from_text("small rapid pattern language comic denial donate extend tide fever burden barrel", - path='if_this_exists_mocking_failed_648151893', - gap_limit=5, - config=self.config)['wallet'] # type: Abstract_Wallet + w = restore_wallet_from_text__for_unittest( + "small rapid pattern language comic denial donate extend tide fever burden barrel", + path='if_this_exists_mocking_failed_648151893', + gap_limit=5, + config=self.config)['wallet'] # type: Abstract_Wallet # txn A is an external incoming txn funding the wallet txA = Transaction(self.transactions["a3849040f82705151ba12a4389310b58a17b78025d81116a3338595bdefa1625"]) w.adb.add_transaction(txA) @@ -4479,9 +4485,10 @@ class TestImportedWallet(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_importing_and_deleting_addresses(self, mock_save_db): - w = restore_wallet_from_text("tb1q7648a2pm2se425lvun0g3vlf4ahmflcthegz63", - path='if_this_exists_mocking_failed_648151893', - config=self.config)['wallet'] # type: Abstract_Wallet + w = restore_wallet_from_text__for_unittest( + "tb1q7648a2pm2se425lvun0g3vlf4ahmflcthegz63", + path='if_this_exists_mocking_failed_648151893', + config=self.config)['wallet'] # type: Abstract_Wallet self.assertEqual(1, len(w.get_addresses())) w.adb.add_transaction(Transaction(self.transactions["0e350564ee7ed4ffce24a998b538f7f3ebbab6fcb4bb331f8bb6b9d86d86fcd8"])) w.adb.add_transaction(Transaction(self.transactions["54de13f7ee4853dc1a281c0e7132efb95330f7ceebc1dbce76fdf34c28028f14"]))