1
0

tests: set low wallet.gap_limit_for_change to speed up tests

This commit is contained in:
SomberNight
2025-08-08 16:24:50 +00:00
parent 4800a2d9c6
commit 4f1cc8b9cb
9 changed files with 141 additions and 112 deletions

View File

@@ -4,12 +4,14 @@ import unittest
import threading import threading
import tempfile import tempfile
import shutil import shutil
import functools
import electrum import electrum
import electrum.logging import electrum.logging
from electrum import constants from electrum import constants
from electrum import util from electrum import util
from electrum.logging import Logger from electrum.logging import Logger
from electrum.wallet import restore_wallet_from_text
# Set this locally to make the test suite run faster. # Set this locally to make the test suite run faster.
@@ -92,3 +94,14 @@ def as_testnet(func):
finally: finally:
constants.net = old_net constants.net = old_net
return run_test 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,
)

View File

@@ -7,7 +7,7 @@ from os import urandom
from electrum.commands import Commands, eval_bool from electrum.commands import Commands, eval_bool
from electrum import storage, wallet from electrum import storage, wallet
from electrum.lnworker import RecvMPPResolution 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.address_synchronizer import TX_HEIGHT_UNCONFIRMED
from electrum.simple_config import SimpleConfig from electrum.simple_config import SimpleConfig
from electrum.transaction import Transaction, TxOutput, tx_from_any from electrum.transaction import Transaction, TxOutput, tx_from_any
@@ -16,6 +16,7 @@ from electrum.crypto import sha256
from electrum.lnaddr import lndecode from electrum.lnaddr import lndecode
from . import ElectrumTestCase from . import ElectrumTestCase
from . import restore_wallet_from_text__for_unittest
from .test_wallet_vertical import WalletIntegrityHelper from .test_wallet_vertical import WalletIntegrityHelper
@@ -91,9 +92,10 @@ class TestCommands(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_encrypt_decrypt(self, mock_save_db): async def test_encrypt_decrypt(self, mock_save_db):
wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN', wallet = restore_wallet_from_text__for_unittest(
path='if_this_exists_mocking_failed_648151893', 'p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN',
config=self.config)['wallet'] path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet']
cmds = Commands(config=self.config) cmds = Commands(config=self.config)
cleartext = "asdasd this is the message" cleartext = "asdasd this is the message"
pubkey = "021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da" pubkey = "021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da"
@@ -102,9 +104,10 @@ class TestCommands(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_export_private_key_imported(self, mock_save_db): async def test_export_private_key_imported(self, mock_save_db):
wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL', wallet = restore_wallet_from_text__for_unittest(
path='if_this_exists_mocking_failed_648151893', 'p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL',
config=self.config)['wallet'] path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet']
cmds = Commands(config=self.config) cmds = Commands(config=self.config)
# single address tests # single address tests
with self.assertRaises(UserFacingException): with self.assertRaises(UserFacingException):
@@ -121,10 +124,10 @@ class TestCommands(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_export_private_key_deterministic(self, mock_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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'bitter grass shiver impose acquire brush forget axis eager alone wine silver',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']
cmds = Commands(config=self.config) cmds = Commands(config=self.config)
# single address tests # single address tests
with self.assertRaises(UserFacingException): with self.assertRaises(UserFacingException):
@@ -150,10 +153,10 @@ class TestCommands(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_decrypt_enforces_strict_base64(self, mock_save_db): async def test_decrypt_enforces_strict_base64(self, mock_save_db):
cmds = Commands(config=self.config) cmds = Commands(config=self.config)
wallet = restore_wallet_from_text('9dk', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, '9dk',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet config=self.config)['wallet'] # type: Abstract_Wallet
plaintext = "hello there" plaintext = "hello there"
ciphertext = "QklFMQJEFgxfkXj+UNblbHR+4y6ZA2rGEeEhWo7h84lBFjlRY5JOPfV1zyC1fw5YmhIr7+3ceIV11lpf/Yv7gSqQCQ5Wuf1aGXceHZO0GjKVxBsuew==" ciphertext = "QklFMQJEFgxfkXj+UNblbHR+4y6ZA2rGEeEhWo7h84lBFjlRY5JOPfV1zyC1fw5YmhIr7+3ceIV11lpf/Yv7gSqQCQ5Wuf1aGXceHZO0GjKVxBsuew=="
pubkey = "02a0507c8bb3d96dfd7731bafb0ae30e6ed10bbadd6a9f9f88eaf0602b9cc99adc" pubkey = "02a0507c8bb3d96dfd7731bafb0ae30e6ed10bbadd6a9f9f88eaf0602b9cc99adc"
@@ -234,10 +237,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_getprivatekeyforpath(self, mock_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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'north rent dawn bunker hamster invest wagon market romance pig either squeeze',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']
cmds = Commands(config=self.config) cmds = Commands(config=self.config)
self.assertEqual("p2wpkh:cUzm7zPpWgLYeURgff4EsoMjhskCpsviBH4Y3aZcrBX8UJSRPjC2", self.assertEqual("p2wpkh:cUzm7zPpWgLYeURgff4EsoMjhskCpsviBH4Y3aZcrBX8UJSRPjC2",
await cmds.getprivatekeyforpath([0, 10000], wallet=wallet)) await cmds.getprivatekeyforpath([0, 10000], wallet=wallet))
@@ -248,10 +251,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_payto(self, mock_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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']
# bootstrap wallet # bootstrap wallet
funding_tx = Transaction('0200000000010165806607dd458280cb57bf64a16cf4be85d053145227b98c28932e953076b8e20000000000fdffffff02ac150700000000001600147e3ddfe6232e448a8390f3073c7a3b2044fd17eb102908000000000016001427fbe3707bc57e5bb63d6f15733ec88626d8188a02473044022049ce9efbab88808720aa563e2d9bc40226389ab459c4390ea3e89465665d593502206c1c7c30a2f640af1e463e5107ee4cfc0ee22664cfae3f2606a95303b54cdef80121026269e54d06f7070c1f967eb2874ba60de550dfc327a945c98eb773672d9411fd77181e00') funding_tx = Transaction('0200000000010165806607dd458280cb57bf64a16cf4be85d053145227b98c28932e953076b8e20000000000fdffffff02ac150700000000001600147e3ddfe6232e448a8390f3073c7a3b2044fd17eb102908000000000016001427fbe3707bc57e5bb63d6f15733ec88626d8188a02473044022049ce9efbab88808720aa563e2d9bc40226389ab459c4390ea3e89465665d593502206c1c7c30a2f640af1e463e5107ee4cfc0ee22664cfae3f2606a95303b54cdef80121026269e54d06f7070c1f967eb2874ba60de550dfc327a945c98eb773672d9411fd77181e00')
funding_txid = funding_tx.txid() funding_txid = funding_tx.txid()
@@ -276,10 +279,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_payto__confirmed_only(self, mock_save_db): async def test_payto__confirmed_only(self, mock_save_db):
"""test that payto respects 'confirmed_only' config var""" """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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']
# bootstrap wallet # bootstrap wallet
funding_tx = Transaction('0200000000010165806607dd458280cb57bf64a16cf4be85d053145227b98c28932e953076b8e20000000000fdffffff02ac150700000000001600147e3ddfe6232e448a8390f3073c7a3b2044fd17eb102908000000000016001427fbe3707bc57e5bb63d6f15733ec88626d8188a02473044022049ce9efbab88808720aa563e2d9bc40226389ab459c4390ea3e89465665d593502206c1c7c30a2f640af1e463e5107ee4cfc0ee22664cfae3f2606a95303b54cdef80121026269e54d06f7070c1f967eb2874ba60de550dfc327a945c98eb773672d9411fd77181e00') funding_tx = Transaction('0200000000010165806607dd458280cb57bf64a16cf4be85d053145227b98c28932e953076b8e20000000000fdffffff02ac150700000000001600147e3ddfe6232e448a8390f3073c7a3b2044fd17eb102908000000000016001427fbe3707bc57e5bb63d6f15733ec88626d8188a02473044022049ce9efbab88808720aa563e2d9bc40226389ab459c4390ea3e89465665d593502206c1c7c30a2f640af1e463e5107ee4cfc0ee22664cfae3f2606a95303b54cdef80121026269e54d06f7070c1f967eb2874ba60de550dfc327a945c98eb773672d9411fd77181e00')
funding_txid = funding_tx.txid() funding_txid = funding_tx.txid()
@@ -310,10 +313,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_paytomany_multiple_max_spends(self, mock_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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'kit virtual quantum festival fortune inform ladder saddle filter soldier start ghost',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']
# bootstrap wallet # bootstrap wallet
funding_tx = Transaction('02000000000101f59876b1c65bbe3e182ccc7ea7224fe397bb9b70aadcbbf4f4074c75c8a074840000000000fdffffff021f351f00000000001600144eec851dd980cc36af1f629a32325f511604d6af56732d000000000016001439267bc7f3e3fabeae3bc3f73880de22d8b01ba50247304402207eac5f639806a00878488d58ca651d690292145bca5511531845ae21fab309d102207162708bd344840cc1bacff1092e426eb8484f83f5c068ba4ca579813de324540121020e0798c267ff06ee8b838cd465f3cfa6c843a122a04917364ce000c29ca205cae5f31f00') funding_tx = Transaction('02000000000101f59876b1c65bbe3e182ccc7ea7224fe397bb9b70aadcbbf4f4074c75c8a074840000000000fdffffff021f351f00000000001600144eec851dd980cc36af1f629a32325f511604d6af56732d000000000016001439267bc7f3e3fabeae3bc3f73880de22d8b01ba50247304402207eac5f639806a00878488d58ca651d690292145bca5511531845ae21fab309d102207162708bd344840cc1bacff1092e426eb8484f83f5c068ba4ca579813de324540121020e0798c267ff06ee8b838cd465f3cfa6c843a122a04917364ce000c29ca205cae5f31f00')
funding_txid = funding_tx.txid() funding_txid = funding_tx.txid()
@@ -345,10 +348,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_signtransaction_with_wallet(self, mock_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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'bitter grass shiver impose acquire brush forget axis eager alone wine silver',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']
# bootstrap wallet1 # bootstrap wallet1
funding_tx = Transaction('01000000014576dacce264c24d81887642b726f5d64aa7825b21b350c7b75a57f337da6845010000006b483045022100a3f8b6155c71a98ad9986edd6161b20d24fad99b6463c23b463856c0ee54826d02200f606017fd987696ebbe5200daedde922eee264325a184d5bbda965ba5160821012102e5c473c051dae31043c335266d0ef89c1daab2f34d885cc7706b267f3269c609ffffffff0240420f00000000001600148a28bddb7f61864bdcf58b2ad13d5aeb3abc3c42a2ddb90e000000001976a914c384950342cb6f8df55175b48586838b03130fad88ac00000000') funding_tx = Transaction('01000000014576dacce264c24d81887642b726f5d64aa7825b21b350c7b75a57f337da6845010000006b483045022100a3f8b6155c71a98ad9986edd6161b20d24fad99b6463c23b463856c0ee54826d02200f606017fd987696ebbe5200daedde922eee264325a184d5bbda965ba5160821012102e5c473c051dae31043c335266d0ef89c1daab2f34d885cc7706b267f3269c609ffffffff0240420f00000000001600148a28bddb7f61864bdcf58b2ad13d5aeb3abc3c42a2ddb90e000000001976a914c384950342cb6f8df55175b48586838b03130fad88ac00000000')
@@ -366,10 +369,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_bumpfee(self, mock_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', wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, 'right nominee cheese afford exotic pilot mask illness rug fringe degree pottery',
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet config=self.config)['wallet'] # type: Abstract_Wallet
funding_tx = Transaction("02000000000102789e8aa8caa79d87241ff9df0e3fd757a07c85a30195d76e8efced1d57c56b670000000000fdffffff7ee2b6abd52b332f797718ae582f8d3b979b83b1799e0a3bfb2c90c6e070c29e0100000000fdffffff020820000000000000160014c0eb720c93a61615d2d66542d381be8943ca553950c3000000000000160014d7dbd0196a2cbd76420f14a19377096cf6cddb75024730440220485b491ad8d3ce3b4da034a851882da84a06ec9800edff0d3fd6aa42eeba3b440220359ea85d32a05932ac417125e133fa54e54e7e9cd20ebc54b883576b8603fd65012103860f1fbf8a482b9d35d7d4d04be8fb33d856a514117cd8b73e372d36895feec60247304402206c2ca56cc030853fa59b4b3cb293f69a3378ead0f10cb76f640f8c2888773461022079b7055d0f6af6952a48e5b97218015b0723462d667765c142b41bd35e3d9c0a01210359e303f57647094a668d69e8ff0bd46c356d00aa7da6dc533c438e71c057f0793e721f00") funding_tx = Transaction("02000000000102789e8aa8caa79d87241ff9df0e3fd757a07c85a30195d76e8efced1d57c56b670000000000fdffffff7ee2b6abd52b332f797718ae582f8d3b979b83b1799e0a3bfb2c90c6e070c29e0100000000fdffffff020820000000000000160014c0eb720c93a61615d2d66542d381be8943ca553950c3000000000000160014d7dbd0196a2cbd76420f14a19377096cf6cddb75024730440220485b491ad8d3ce3b4da034a851882da84a06ec9800edff0d3fd6aa42eeba3b440220359ea85d32a05932ac417125e133fa54e54e7e9cd20ebc54b883576b8603fd65012103860f1fbf8a482b9d35d7d4d04be8fb33d856a514117cd8b73e372d36895feec60247304402206c2ca56cc030853fa59b4b3cb293f69a3378ead0f10cb76f640f8c2888773461022079b7055d0f6af6952a48e5b97218015b0723462d667765c142b41bd35e3d9c0a01210359e303f57647094a668d69e8ff0bd46c356d00aa7da6dc533c438e71c057f0793e721f00")
funding_txid = funding_tx.txid() funding_txid = funding_tx.txid()
@@ -397,9 +400,10 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_importprivkey(self, mock_save_db): async def test_importprivkey(self, mock_save_db):
wallet = restore_wallet_from_text('p2wpkh:cQUdWZehnGDwGn7CSc911cJBcWTAcnyzpLoJYTsFNYW1w6iaq7Nw p2wpkh:cNHsDLo137ngrr2wGf3mwqpwTUvpuDVAZrqzan9heHcMTK4rP5JB', wallet = restore_wallet_from_text__for_unittest(
path='if_this_exists_mocking_failed_648151893', 'p2wpkh:cQUdWZehnGDwGn7CSc911cJBcWTAcnyzpLoJYTsFNYW1w6iaq7Nw p2wpkh:cNHsDLo137ngrr2wGf3mwqpwTUvpuDVAZrqzan9heHcMTK4rP5JB',
config=self.config)['wallet'] path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet']
cmds = Commands(config=self.config) cmds = Commands(config=self.config)
self.assertEqual(2, len(wallet.get_addresses())) self.assertEqual(2, len(wallet.get_addresses()))
# try importing a single bad privkey # try importing a single bad privkey
@@ -435,9 +439,8 @@ class TestCommandsTestnet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_hold_invoice_commands(self, mock_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', 'disagree rug lemon bean unaware square alone beach tennis exhibit fix mimic',
gap_limit=2,
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] config=self.config)['wallet']

View File

@@ -1,11 +1,12 @@
import os import os
from . import ElectrumTestCase
from electrum.simple_config import SimpleConfig 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 electrum.daemon import Daemon
from . import ElectrumTestCase
from . import restore_wallet_from_text__for_unittest
class TestContacts(ElectrumTestCase): class TestContacts(ElectrumTestCase):
TESTNET = True TESTNET = True
@@ -17,7 +18,7 @@ class TestContacts(ElectrumTestCase):
async def test_saving_contacts(self): async def test_saving_contacts(self):
text = 'cross end slow expose giraffe fuel track awake turtle capital ranch pulp' 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 = d['wallet'] # type: Abstract_Wallet
w.contacts["myNNuLYNgHE92nGQuJd5mXo6gy9gKXEDyQ"] = ("address", "alice") w.contacts["myNNuLYNgHE92nGQuJd5mXo6gy9gKXEDyQ"] = ("address", "alice")
w.contacts["tb1q4syjltptqwhe62t3u5gwz9nsw87kmcwx003z05"] = ("address", "bob") w.contacts["tb1q4syjltptqwhe62t3u5gwz9nsw87kmcwx003z05"] = ("address", "bob")

View File

@@ -4,10 +4,10 @@ from typing import Optional, Iterable
from electrum.commands import Commands from electrum.commands import Commands
from electrum.daemon import Daemon from electrum.daemon import Daemon
from electrum.simple_config import SimpleConfig 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 electrum import util
from . import ElectrumTestCase, as_testnet from . import ElectrumTestCase, as_testnet, restore_wallet_from_text__for_unittest
class DaemonTestCase(ElectrumTestCase): class DaemonTestCase(ElectrumTestCase):
@@ -34,12 +34,11 @@ class DaemonTestCase(ElectrumTestCase):
"""Returns path for created wallet.""" """Returns path for created wallet."""
basename = util.get_new_wallet_name(self.wallet_dir) basename = util.get_new_wallet_name(self.wallet_dir)
path = os.path.join(self.wallet_dir, basename) path = os.path.join(self.wallet_dir, basename)
wallet_dict = restore_wallet_from_text( wallet_dict = restore_wallet_from_text__for_unittest(
text, text,
path=path, path=path,
password=password, password=password,
encrypt_file=encrypt_file, encrypt_file=encrypt_file,
gap_limit=2,
config=self.config, config=self.config,
) )
# We return the path instead of the wallet object, as extreme # 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): async def test_wp_command_with_inmemory_wallet_has_password(self):
cmds = Commands(config=self.config, daemon=self.daemon) cmds = Commands(config=self.config, daemon=self.daemon)
wallet = restore_wallet_from_text(self.SEED, wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, self.SEED,
path=None, path=None,
password="123456", password="123456",
config=self.config)['wallet'] config=self.config)['wallet']
self.assertEqual(self.SEED, await cmds.getseed(wallet=wallet, password="123456")) self.assertEqual(self.SEED, await cmds.getseed(wallet=wallet, password="123456"))
async def test_wp_command_with_inmemory_wallet_no_password(self): async def test_wp_command_with_inmemory_wallet_no_password(self):
cmds = Commands(config=self.config, daemon=self.daemon) cmds = Commands(config=self.config, daemon=self.daemon)
wallet = restore_wallet_from_text(self.SEED, wallet = restore_wallet_from_text__for_unittest(
gap_limit=2, self.SEED,
path=None, path=None,
config=self.config)['wallet'] config=self.config)['wallet']
self.assertEqual(self.SEED, await cmds.getseed(wallet=wallet)) self.assertEqual(self.SEED, await cmds.getseed(wallet=wallet))
async def test_wp_command_with_diskfile_wallet_has_password(self): async def test_wp_command_with_diskfile_wallet_has_password(self):

View File

@@ -1,16 +1,18 @@
import os import os
import time import time
from . import ElectrumTestCase
from electrum.simple_config import SimpleConfig 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.invoices import PR_UNPAID, PR_PAID, PR_UNCONFIRMED, BaseInvoice, Invoice, LN_EXPIRY_NEVER
from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED
from electrum.transaction import Transaction, PartialTxOutput from electrum.transaction import Transaction, PartialTxOutput
from electrum.util import TxMinedInfo, InvoiceError from electrum.util import TxMinedInfo, InvoiceError
from electrum.fee_policy import FixedFeePolicy from electrum.fee_policy import FixedFeePolicy
from . import ElectrumTestCase
from . import restore_wallet_from_text__for_unittest
class TestWalletPaymentRequests(ElectrumTestCase): class TestWalletPaymentRequests(ElectrumTestCase):
"""test 'incoming' invoices""" """test 'incoming' invoices"""
TESTNET = True TESTNET = True
@@ -28,7 +30,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
def create_wallet2(self) -> Standard_Wallet: def create_wallet2(self) -> Standard_Wallet:
text = 'cross end slow expose giraffe fuel track awake turtle capital ranch pulp' 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 wallet2 = d['wallet'] # type: Standard_Wallet
# bootstrap wallet # bootstrap wallet
funding_tx = Transaction('0200000000010132515e6aade1b79ec7dd3bac0896d8b32c56195d23d07d48e21659cef24301560100000000fdffffff0112841e000000000016001477fe6d2a27e8860c278d4d2cd90bad716bb9521a02473044022041ed68ef7ef122813ac6a5e996b8284f645c53fbe6823b8e430604a8915a867802203233f5f4d347a687eb19b2aa570829ab12aeeb29a24cc6d6d20b8b3d79e971ae012102bee0ee043817e50ac1bb31132770f7c41e35946ccdcb771750fb9696bdd1b307ad951d00') 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): 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' 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 = d['wallet'] # type: Standard_Wallet
self.assertIsNotNone(wallet1.lnworker) self.assertIsNotNone(wallet1.lnworker)
self.assertTrue(wallet1.has_lightning()) 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): 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' 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 = d['wallet'] # type: Standard_Wallet
wallet1.db.put('stored_height', 1000) wallet1.db.put('stored_height', 1000)
self.assertIsNotNone(wallet1.lnworker) self.assertIsNotNone(wallet1.lnworker)
@@ -87,7 +89,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
async def test_wallet_without_ln_creates_payreq_and_gets_paid_onchain(self): 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' 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 = d['wallet'] # type: Standard_Wallet
wallet1.db.put('stored_height', 1000) wallet1.db.put('stored_height', 1000)
self.assertIsNone(wallet1.lnworker) self.assertIsNone(wallet1.lnworker)
@@ -118,7 +120,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
async def test_wallet_gets_paid_onchain_in_the_past(self): async def test_wallet_gets_paid_onchain_in_the_past(self):
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 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 = d['wallet'] # type: Standard_Wallet
wallet1.db.put('stored_height', 1000) wallet1.db.put('stored_height', 1000)
self.assertIsNotNone(wallet1.lnworker) self.assertIsNotNone(wallet1.lnworker)
@@ -148,7 +150,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
async def test_wallet_reuse_addr_of_expired_request(self): async def test_wallet_reuse_addr_of_expired_request(self):
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 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 wallet1 = d['wallet'] # type: Standard_Wallet
self.assertIsNotNone(wallet1.lnworker) self.assertIsNotNone(wallet1.lnworker)
self.assertTrue(wallet1.has_lightning()) self.assertTrue(wallet1.has_lightning())
@@ -176,7 +178,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
async def test_wallet_get_request_by_addr(self): async def test_wallet_get_request_by_addr(self):
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 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 wallet1 = d['wallet'] # type: Standard_Wallet
self.assertIsNotNone(wallet1.lnworker) self.assertIsNotNone(wallet1.lnworker)
self.assertTrue(wallet1.has_lightning()) self.assertTrue(wallet1.has_lightning())

View File

@@ -15,10 +15,11 @@ from electrum.lnutil import (
from electrum.util import bfh, MyEncoder from electrum.util import bfh, MyEncoder
from electrum.transaction import Transaction, PartialTransaction, Sighash from electrum.transaction import Transaction, PartialTransaction, Sighash
from electrum.lnworker import LNWallet 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 electrum.simple_config import SimpleConfig
from . import ElectrumTestCase, as_testnet from . import ElectrumTestCase, as_testnet
from . import restore_wallet_from_text__for_unittest
from .test_bitcoin import disable_ecdsa_r_value_grinding 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): 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==" 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}) 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 wallet1 = d['wallet'] # type: Standard_Wallet
decoded_cb = ImportedChannelBackupStorage.from_encrypted_str(encrypted_cb, password=wallet1.get_fingerprint()) decoded_cb = ImportedChannelBackupStorage.from_encrypted_str(encrypted_cb, password=wallet1.get_fingerprint())
self.assertEqual( self.assertEqual(
@@ -1097,7 +1098,7 @@ class TestLNUtil(ElectrumTestCase):
async def test_decode_imported_channel_backup_v1(self): async def test_decode_imported_channel_backup_v1(self):
encrypted_cb = "channel_backup:AVYIedu0qSLfY2M2bBxF6dA4RAxcmobp+3h9mxALWWsv5X7hhNg0XYOKNd11FE6BJOZgZnIZ4CCAlHtLNj0/9S5GbNhbNZiQXxeHMwC1lHvtjawkwSejIJyOI52DkDFHBAGZRd4fJjaPJRHnUizWfySVR4zjd08lTinpoIeL7C7tXBW1N6YqceqV7RpeoywlBXJtFfCCuw0hnUKgq3SMlBKapkNAIgGrg15aIHNcYeENxCxr5FD1s7DIwFSECqsBVnu/Ogx2oii8BfuxqJq8vuGq4Ib/BVaSVtdb2E1wklAor/CG0p9Fg9mFWND98JD+64nz9n/knPFFyHxTXErn+ct3ZcStsLYynWKUIocgu38PtzCJ7r5ivqOw4O49fbbzdjcgMUGklPYxjuinETneCo+dCPa1uepOGTqeOYmnjVYtYZYXOlWV1F5OtNoM7MwwJjAbz84=" encrypted_cb = "channel_backup:AVYIedu0qSLfY2M2bBxF6dA4RAxcmobp+3h9mxALWWsv5X7hhNg0XYOKNd11FE6BJOZgZnIZ4CCAlHtLNj0/9S5GbNhbNZiQXxeHMwC1lHvtjawkwSejIJyOI52DkDFHBAGZRd4fJjaPJRHnUizWfySVR4zjd08lTinpoIeL7C7tXBW1N6YqceqV7RpeoywlBXJtFfCCuw0hnUKgq3SMlBKapkNAIgGrg15aIHNcYeENxCxr5FD1s7DIwFSECqsBVnu/Ogx2oii8BfuxqJq8vuGq4Ib/BVaSVtdb2E1wklAor/CG0p9Fg9mFWND98JD+64nz9n/knPFFyHxTXErn+ct3ZcStsLYynWKUIocgu38PtzCJ7r5ivqOw4O49fbbzdjcgMUGklPYxjuinETneCo+dCPa1uepOGTqeOYmnjVYtYZYXOlWV1F5OtNoM7MwwJjAbz84="
config = SimpleConfig({'electrum_path': self.electrum_path}) 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 wallet1 = d['wallet'] # type: Standard_Wallet
decoded_cb = ImportedChannelBackupStorage.from_encrypted_str(encrypted_cb, password=wallet1.get_fingerprint()) decoded_cb = ImportedChannelBackupStorage.from_encrypted_str(encrypted_cb, password=wallet1.get_fingerprint())
self.assertEqual( self.assertEqual(

View File

@@ -4,10 +4,10 @@ from electrum import SimpleConfig
from electrum.invoices import Invoice from electrum.invoices import Invoice
from electrum.payment_identifier import (maybe_extract_lightning_payment_identifier, PaymentIdentifier, from electrum.payment_identifier import (maybe_extract_lightning_payment_identifier, PaymentIdentifier,
PaymentIdentifierType, invoice_from_payment_identifier) PaymentIdentifierType, invoice_from_payment_identifier)
from electrum.wallet import restore_wallet_from_text from electrum.transaction import PartialTxOutput
from . import ElectrumTestCase from . import ElectrumTestCase
from electrum.transaction import PartialTxOutput from . import restore_wallet_from_text__for_unittest
class WalletMock: class WalletMock:
@@ -286,7 +286,7 @@ class TestPaymentIdentifier(ElectrumTestCase):
self.assertEqual(2_000_000_000, invoice.amount_msat) self.assertEqual(2_000_000_000, invoice.amount_msat)
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 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 wallet2 = d['wallet'] # type: Standard_Wallet
# no amount bip21+lightning, MAX amount passed # no amount bip21+lightning, MAX amount passed

View File

@@ -11,7 +11,7 @@ import asyncio
from electrum.storage import WalletStorage from electrum.storage import WalletStorage
from electrum.wallet_db import FINAL_SEED_VERSION from electrum.wallet_db import FINAL_SEED_VERSION
from electrum.wallet import (Abstract_Wallet, Standard_Wallet, create_new_wallet, 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.exchange_rate import ExchangeBase, FxThread
from electrum.util import TxMinedInfo, InvalidPassword from electrum.util import TxMinedInfo, InvalidPassword
from electrum.bitcoin import COIN 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 electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED
from . import ElectrumTestCase from . import ElectrumTestCase
from . import restore_wallet_from_text__for_unittest
class FakeSynchronizer(object): class FakeSynchronizer(object):
@@ -93,7 +94,7 @@ class TestWalletStorage(WalletTestCase):
'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL', 'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL',
'p2wpkh:L24GxnN7NNUAfCXA6hFzB1jt59fYAAiFZMcLaJ2ZSawGpM3uqhb1' '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 wallet = d['wallet'] # type: Imported_Wallet
self.assertEqual(2, len(wallet.get_receiving_addresses())) self.assertEqual(2, len(wallet.get_receiving_addresses()))
await wallet.stop() await wallet.stop()
@@ -118,7 +119,7 @@ class TestWalletStorage(WalletTestCase):
async def test_storage_prevouts_by_scripthash_persistence(self): async def test_storage_prevouts_by_scripthash_persistence(self):
text = 'cycle rocket west magnet parrot shuffle foot correct salt library feed song' 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 wallet1 = d['wallet'] # type: Standard_Wallet
# create payreq # create payreq
addr = wallet1.get_unused_address() addr = wallet1.get_unused_address()
@@ -224,6 +225,7 @@ class TestCreateRestoreWallet(WalletTestCase):
password=password, password=password,
encrypt_file=encrypt_file, encrypt_file=encrypt_file,
gap_limit=1, gap_limit=1,
gap_limit_for_change=1,
config=self.config) config=self.config)
wallet = d['wallet'] # type: Standard_Wallet wallet = d['wallet'] # type: Standard_Wallet
@@ -240,13 +242,14 @@ class TestCreateRestoreWallet(WalletTestCase):
passphrase = 'mypassphrase' passphrase = 'mypassphrase'
password = 'mypassword' password = 'mypassword'
encrypt_file = True encrypt_file = True
d = restore_wallet_from_text(text, d = restore_wallet_from_text__for_unittest(
path=self.wallet_path, text,
passphrase=passphrase, path=self.wallet_path,
password=password, passphrase=passphrase,
encrypt_file=encrypt_file, password=password,
gap_limit=1, encrypt_file=encrypt_file,
config=self.config) gap_limit=1,
config=self.config)
wallet = d['wallet'] # type: Standard_Wallet wallet = d['wallet'] # type: Standard_Wallet
self.assertEqual(passphrase, wallet.keystore.get_passphrase(password)) self.assertEqual(passphrase, wallet.keystore.get_passphrase(password))
self.assertEqual(text, wallet.keystore.get_seed(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): async def test_restore_wallet_from_text_no_storage(self):
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 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, text,
path=None, path=None,
gap_limit=1, gap_limit=1,
@@ -268,28 +271,28 @@ class TestCreateRestoreWallet(WalletTestCase):
async def test_restore_wallet_from_text_xpub(self): async def test_restore_wallet_from_text_xpub(self):
text = 'zpub6nydoME6CFdJtMpzHW5BNoPz6i6XbeT9qfz72wsRqGdgGEYeivso6xjfw8cGcCyHwF7BNW4LDuHF35XrZsovBLWMF4qXSjmhTXYiHbWqGLt' 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 wallet = d['wallet'] # type: Standard_Wallet
self.assertEqual(text, wallet.keystore.get_master_public_key()) self.assertEqual(text, wallet.keystore.get_master_public_key())
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) 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): async def test_restore_wallet_from_text_xkey_that_is_also_a_valid_electrum_seed_by_chance(self):
text = 'yprvAJBpuoF4FKpK92ofzQ7ge6VJMtorow3maAGPvPGj38ggr2xd1xCrC9ojUVEf9jhW5L9SPu6fU2U3o64cLrRQ83zaQGNa6YP3ajZS6hHNPXj' 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 wallet = d['wallet'] # type: Standard_Wallet
self.assertEqual(text, wallet.keystore.get_master_private_key(password=None)) self.assertEqual(text, wallet.keystore.get_master_private_key(password=None))
self.assertEqual('3Pa4hfP3LFWqa2nfphYaF7PZfdJYNusAnp', wallet.get_receiving_addresses()[0]) self.assertEqual('3Pa4hfP3LFWqa2nfphYaF7PZfdJYNusAnp', wallet.get_receiving_addresses()[0])
async def test_restore_wallet_from_text_xprv(self): async def test_restore_wallet_from_text_xprv(self):
text = 'zprvAZzHPqhCMt51fskXBUYB1fTFYgG3CBjJUT4WEZTpGw6hPSDWBPZYZARC5sE9xAcX8NeWvvucFws8vZxEa65RosKAhy7r5MsmKTxr3hmNmea' 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 wallet = d['wallet'] # type: Standard_Wallet
self.assertEqual(text, wallet.keystore.get_master_private_key(password=None)) self.assertEqual(text, wallet.keystore.get_master_private_key(password=None))
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0])
async def test_restore_wallet_from_text_addresses(self): async def test_restore_wallet_from_text_addresses(self):
text = 'bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw bc1qnp78h78vp92pwdwq5xvh8eprlga5q8gu66960c' 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 wallet = d['wallet'] # type: Imported_Wallet
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0])
self.assertEqual(2, len(wallet.get_receiving_addresses())) self.assertEqual(2, len(wallet.get_receiving_addresses()))
@@ -299,7 +302,7 @@ class TestCreateRestoreWallet(WalletTestCase):
async def test_restore_wallet_from_text_privkeys(self): async def test_restore_wallet_from_text_privkeys(self):
text = 'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL p2wpkh:L24GxnN7NNUAfCXA6hFzB1jt59fYAAiFZMcLaJ2ZSawGpM3uqhb1' 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 wallet = d['wallet'] # type: Imported_Wallet
addr0 = wallet.get_receiving_addresses()[0] addr0 = wallet.get_receiving_addresses()[0]
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', addr0) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', addr0)

View File

@@ -11,7 +11,7 @@ from electrum import SimpleConfig
from electrum import util from electrum import util
from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_LOCAL, TX_HEIGHT_FUTURE 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, 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, TransactionPotentiallyDangerousException, TransactionDangerousException,
TxSighashRiskLevel) TxSighashRiskLevel)
from electrum.util import bfh, NotEnoughFunds, UnrelatedTransactionException, UserFacingException, TxMinedInfo 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 electrum.plugins.trustedcoin import trustedcoin
from . import ElectrumTestCase from . import ElectrumTestCase
from . import restore_wallet_from_text__for_unittest
UNICODE_HORROR_HEX = 'e282bf20f09f988020f09f98882020202020e3818620e38191e3819fe381be20e3828fe3828b2077cda2cda2cd9d68cda16fcda2cda120ccb8cda26bccb5cd9f6eccb4cd98c7ab77ccb8cc9b73cd9820cc80cc8177cd98cda2e1b8a9ccb561d289cca1cda27420cca7cc9568cc816fccb572cd8fccb5726f7273cca120ccb6cda1cda06cc4afccb665cd9fcd9f20ccb6cd9d696ecda220cd8f74cc9568ccb7cca1cd9f6520cd9fcd9f64cc9b61cd9c72cc95cda16bcca2cca820cda168ccb465cd8f61ccb7cca2cca17274cc81cd8f20ccb4ccb7cda0c3b2ccb5ccb666ccb82075cca7cd986ec3adcc9bcd9c63cda2cd8f6fccb7cd8f64ccb8cda265cca1cd9d3fcd9e' UNICODE_HORROR_HEX = 'e282bf20f09f988020f09f98882020202020e3818620e38191e3819fe381be20e3828fe3828b2077cda2cda2cd9d68cda16fcda2cda120ccb8cda26bccb5cd9f6eccb4cd98c7ab77ccb8cc9b73cd9820cc80cc8177cd98cda2e1b8a9ccb561d289cca1cda27420cca7cc9568cc816fccb572cd8fccb5726f7273cca120ccb6cda1cda06cc4afccb665cd9fcd9f20ccb6cd9d696ecda220cd8f74cc9568ccb7cca1cd9f6520cd9fcd9f64cc9b61cd9c72cc95cda16bcca2cca820cda168ccb465cd8f61ccb7cca2cca17274cc81cd8f20ccb4ccb7cda0c3b2ccb5ccb666ccb82075cca7cd986ec3adcc9bcd9c63cda2cd8f6fccb7cd8f64ccb8cda265cca1cd9d3fcd9e'
@@ -33,6 +34,7 @@ assert UNICODE_HORROR == '₿ 😀 😈 う けたま わる w͢͢͝h͡o͢͡
class WalletIntegrityHelper: class WalletIntegrityHelper:
gap_limit = 1 # make tests run faster 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 # TODO also use short gap limit for change addrs, for performance
@classmethod @classmethod
@@ -50,10 +52,11 @@ class WalletIntegrityHelper:
test_obj.assertFalse(ks.has_seed()) test_obj.assertFalse(ks.has_seed())
@classmethod @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 = storage.WalletDB('', storage=None, upgrade=True)
db.put('keystore', ks.dump()) db.put('keystore', ks.dump())
db.put('gap_limit', gap_limit or cls.gap_limit) 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 = Standard_Wallet(db, config=config)
w.synchronize() w.synchronize()
return w return w
@@ -69,7 +72,7 @@ class WalletIntegrityHelper:
@classmethod @classmethod
def create_multisig_wallet(cls, keystores: Sequence, multisig_type: str, *, 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.""" """Creates a multisig wallet."""
db = storage.WalletDB('', storage=None, upgrade=False) db = storage.WalletDB('', storage=None, upgrade=False)
for i, ks in enumerate(keystores): for i, ks in enumerate(keystores):
@@ -77,6 +80,7 @@ class WalletIntegrityHelper:
db.put('x%d' % cosigner_index, ks.dump()) db.put('x%d' % cosigner_index, ks.dump())
db.put('wallet_type', multisig_type) db.put('wallet_type', multisig_type)
db.put('gap_limit', gap_limit or cls.gap_limit) 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 = Multisig_Wallet(db, config=config)
w.synchronize() w.synchronize()
return w return w
@@ -2046,7 +2050,7 @@ class TestWalletSending(ElectrumTestCase):
def _create_cause_carbon_wallet(self): def _create_cause_carbon_wallet(self):
data = read_test_vector('cause_carbon_wallet.json') data = read_test_vector('cause_carbon_wallet.json')
ks = keystore.from_seed(data['seed'], passphrase='', for_multisig=False) 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) # bootstrap wallet (incoming funding_tx0)
funding_tx = Transaction(data['funding_tx']) funding_tx = Transaction(data['funding_tx'])
wallet.adb.receive_tx_callback(funding_tx, tx_height=TX_HEIGHT_UNCONFIRMED) 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') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_imported_wallet_usechange_off(self, mock_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", "p2wpkh:cVcwSp488C8Riguq55Tuktgi6TpzuyLdDwUxkBDBz3yzV7FW4af2 p2wpkh:cPWyoPvnv2hiyyxbhMkhX3gPEENzB6DqoP9bbR8SDTg5njK5SL9n",
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet config=self.config)['wallet'] # type: Abstract_Wallet
@@ -2985,7 +2989,7 @@ class TestWalletSending(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_imported_wallet_usechange_on(self, mock_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", "p2wpkh:cVcwSp488C8Riguq55Tuktgi6TpzuyLdDwUxkBDBz3yzV7FW4af2 p2wpkh:cPWyoPvnv2hiyyxbhMkhX3gPEENzB6DqoP9bbR8SDTg5njK5SL9n",
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet config=self.config)['wallet'] # type: Abstract_Wallet
@@ -3020,7 +3024,7 @@ class TestWalletSending(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_imported_wallet_usechange_on__no_more_unused_addresses(self, mock_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", "p2wpkh:cVcwSp488C8Riguq55Tuktgi6TpzuyLdDwUxkBDBz3yzV7FW4af2 p2wpkh:cPWyoPvnv2hiyyxbhMkhX3gPEENzB6DqoP9bbR8SDTg5njK5SL9n",
path='if_this_exists_mocking_failed_648151893', path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet config=self.config)['wallet'] # type: Abstract_Wallet
@@ -4259,7 +4263,7 @@ class TestWalletHistory_SimpleRandomOrder(ElectrumTestCase):
def create_old_wallet(self): def create_old_wallet(self):
ks = keystore.from_old_mpk('e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3') ks = keystore.from_old_mpk('e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3')
# seed words: powerful random nobody notice nothing important anyway look away hidden message over # 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: # some txns are beyond gap limit:
w.create_new_address(for_change=True) w.create_new_address(for_change=True)
return w return w
@@ -4364,10 +4368,11 @@ class TestWalletHistory_DoubleSpend(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_restoring_wallet_without_manual_delete(self, mock_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", w = restore_wallet_from_text__for_unittest(
path='if_this_exists_mocking_failed_648151893', "small rapid pattern language comic denial donate extend tide fever burden barrel",
gap_limit=5, path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet gap_limit=5,
config=self.config)['wallet'] # type: Abstract_Wallet
for txid in self.transactions: for txid in self.transactions:
tx = Transaction(self.transactions[txid]) tx = Transaction(self.transactions[txid])
w.adb.add_transaction(tx) w.adb.add_transaction(tx)
@@ -4378,10 +4383,11 @@ class TestWalletHistory_DoubleSpend(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_restoring_wallet_with_manual_delete(self, mock_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", w = restore_wallet_from_text__for_unittest(
path='if_this_exists_mocking_failed_648151893', "small rapid pattern language comic denial donate extend tide fever burden barrel",
gap_limit=5, path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet gap_limit=5,
config=self.config)['wallet'] # type: Abstract_Wallet
# txn A is an external incoming txn funding the wallet # txn A is an external incoming txn funding the wallet
txA = Transaction(self.transactions["a3849040f82705151ba12a4389310b58a17b78025d81116a3338595bdefa1625"]) txA = Transaction(self.transactions["a3849040f82705151ba12a4389310b58a17b78025d81116a3338595bdefa1625"])
w.adb.add_transaction(txA) w.adb.add_transaction(txA)
@@ -4479,9 +4485,10 @@ class TestImportedWallet(ElectrumTestCase):
@mock.patch.object(wallet.Abstract_Wallet, 'save_db') @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_importing_and_deleting_addresses(self, mock_save_db): async def test_importing_and_deleting_addresses(self, mock_save_db):
w = restore_wallet_from_text("tb1q7648a2pm2se425lvun0g3vlf4ahmflcthegz63", w = restore_wallet_from_text__for_unittest(
path='if_this_exists_mocking_failed_648151893', "tb1q7648a2pm2se425lvun0g3vlf4ahmflcthegz63",
config=self.config)['wallet'] # type: Abstract_Wallet path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet'] # type: Abstract_Wallet
self.assertEqual(1, len(w.get_addresses())) self.assertEqual(1, len(w.get_addresses()))
w.adb.add_transaction(Transaction(self.transactions["0e350564ee7ed4ffce24a998b538f7f3ebbab6fcb4bb331f8bb6b9d86d86fcd8"])) w.adb.add_transaction(Transaction(self.transactions["0e350564ee7ed4ffce24a998b538f7f3ebbab6fcb4bb331f8bb6b9d86d86fcd8"]))
w.adb.add_transaction(Transaction(self.transactions["54de13f7ee4853dc1a281c0e7132efb95330f7ceebc1dbce76fdf34c28028f14"])) w.adb.add_transaction(Transaction(self.transactions["54de13f7ee4853dc1a281c0e7132efb95330f7ceebc1dbce76fdf34c28028f14"]))