mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
config: no longer singleton. it is passed to Wallet.__init__
The few other cases that used SimpleConfig.get_instance() now either get passed a config instance, or they try to get a reference to something else that has a reference to a config. (see lnsweep, qt/qrcodewidget, qt/qrtextedit)
This commit is contained in:
parent
d6c7dee547
commit
04edad9984
38 changed files with 367 additions and 317 deletions
|
@ -216,7 +216,8 @@ class Commands:
|
|||
passphrase=passphrase,
|
||||
password=password,
|
||||
encrypt_file=encrypt_file,
|
||||
seed_type=seed_type)
|
||||
seed_type=seed_type,
|
||||
config=self.config)
|
||||
return {
|
||||
'seed': d['seed'],
|
||||
'path': d['wallet'].storage.path,
|
||||
|
@ -235,7 +236,8 @@ class Commands:
|
|||
path=wallet_path,
|
||||
passphrase=passphrase,
|
||||
password=password,
|
||||
encrypt_file=encrypt_file)
|
||||
encrypt_file=encrypt_file,
|
||||
config=self.config)
|
||||
return {
|
||||
'path': d['wallet'].storage.path,
|
||||
'msg': d['msg'],
|
||||
|
|
|
@ -386,7 +386,7 @@ class Daemon(Logger):
|
|||
return
|
||||
if storage.get_action():
|
||||
return
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=self.config)
|
||||
wallet.start_network(self.network)
|
||||
self._wallets[path] = wallet
|
||||
self.wallet = wallet
|
||||
|
|
|
@ -576,7 +576,7 @@ class ElectrumWindow(App):
|
|||
|
||||
def on_wizard_complete(self, wizard, storage):
|
||||
if storage:
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=self.electrum_config)
|
||||
wallet.start_network(self.daemon.network)
|
||||
self.daemon.add_wallet(wallet)
|
||||
self.load_wallet(wallet)
|
||||
|
|
|
@ -308,7 +308,7 @@ class ElectrumGui(Logger):
|
|||
# return if wallet creation is not complete
|
||||
if storage is None or storage.get_action():
|
||||
return
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=self.config)
|
||||
wallet.start_network(self.daemon.network)
|
||||
self.daemon.add_wallet(wallet)
|
||||
return wallet
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import os
|
||||
import qrcode
|
||||
|
||||
from PyQt5.QtGui import QColor, QPen
|
||||
import PyQt5.QtGui as QtGui
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication, QVBoxLayout, QTextEdit, QHBoxLayout, QPushButton, QWidget)
|
||||
QApplication, QVBoxLayout, QTextEdit, QHBoxLayout, QPushButton, QWidget,
|
||||
QFileDialog,
|
||||
)
|
||||
|
||||
import electrum
|
||||
from electrum.i18n import _
|
||||
from electrum.simple_config import SimpleConfig
|
||||
|
||||
from .util import WindowModalDialog
|
||||
from .util import WindowModalDialog, get_parent_main_window
|
||||
|
||||
|
||||
class QRCodeWidget(QWidget):
|
||||
|
@ -107,27 +106,30 @@ class QRDialog(WindowModalDialog):
|
|||
hbox = QHBoxLayout()
|
||||
hbox.addStretch(1)
|
||||
|
||||
config = SimpleConfig.get_instance()
|
||||
if config:
|
||||
filename = os.path.join(config.path, "qrcode.png")
|
||||
def print_qr():
|
||||
main_window = get_parent_main_window(self)
|
||||
if main_window:
|
||||
filename = main_window.getSaveFileName(_("Select where to save file"), "qrcode.png")
|
||||
else:
|
||||
filename, __ = QFileDialog.getSaveFileName(self, _("Select where to save file"), "qrcode.png")
|
||||
if not filename:
|
||||
return
|
||||
p = qrw.grab() # FIXME also grabs neutral colored padding
|
||||
p.save(filename, 'png')
|
||||
self.show_message(_("QR code saved to file") + " " + filename)
|
||||
|
||||
def print_qr():
|
||||
p = qrw.grab() # FIXME also grabs neutral colored padding
|
||||
p.save(filename, 'png')
|
||||
self.show_message(_("QR code saved to file") + " " + filename)
|
||||
def copy_to_clipboard():
|
||||
p = qrw.grab()
|
||||
QApplication.clipboard().setPixmap(p)
|
||||
self.show_message(_("QR code copied to clipboard"))
|
||||
|
||||
def copy_to_clipboard():
|
||||
p = qrw.grab()
|
||||
QApplication.clipboard().setPixmap(p)
|
||||
self.show_message(_("QR code copied to clipboard"))
|
||||
b = QPushButton(_("Copy"))
|
||||
hbox.addWidget(b)
|
||||
b.clicked.connect(copy_to_clipboard)
|
||||
|
||||
b = QPushButton(_("Copy"))
|
||||
hbox.addWidget(b)
|
||||
b.clicked.connect(copy_to_clipboard)
|
||||
|
||||
b = QPushButton(_("Save"))
|
||||
hbox.addWidget(b)
|
||||
b.clicked.connect(print_qr)
|
||||
b = QPushButton(_("Save"))
|
||||
hbox.addWidget(b)
|
||||
b.clicked.connect(print_qr)
|
||||
|
||||
b = QPushButton(_("Close"))
|
||||
hbox.addWidget(b)
|
||||
|
|
|
@ -4,7 +4,7 @@ from electrum.i18n import _
|
|||
from electrum.plugin import run_hook
|
||||
from electrum.simple_config import SimpleConfig
|
||||
|
||||
from .util import ButtonsTextEdit, MessageBoxMixin, ColorScheme
|
||||
from .util import ButtonsTextEdit, MessageBoxMixin, ColorScheme, get_parent_main_window
|
||||
|
||||
|
||||
class ShowQRTextEdit(ButtonsTextEdit):
|
||||
|
@ -23,7 +23,7 @@ class ShowQRTextEdit(ButtonsTextEdit):
|
|||
s = str(self.toPlainText())
|
||||
except:
|
||||
s = self.toPlainText()
|
||||
QRDialog(s).exec_()
|
||||
QRDialog(s, parent=self).exec_()
|
||||
|
||||
def contextMenuEvent(self, e):
|
||||
m = self.createStandardContextMenu()
|
||||
|
@ -56,8 +56,11 @@ class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
|
|||
|
||||
def qr_input(self):
|
||||
from electrum import qrscanner
|
||||
main_window = get_parent_main_window(self)
|
||||
assert main_window
|
||||
config = main_window.config
|
||||
try:
|
||||
data = qrscanner.scan_barcode(SimpleConfig.get_instance().get_video_device())
|
||||
data = qrscanner.scan_barcode(config.get_video_device())
|
||||
except BaseException as e:
|
||||
self.show_error(repr(e))
|
||||
data = ''
|
||||
|
|
|
@ -39,7 +39,7 @@ class ElectrumGui:
|
|||
self.str_amount = ""
|
||||
self.str_fee = ""
|
||||
|
||||
self.wallet = Wallet(storage)
|
||||
self.wallet = Wallet(storage, config=config)
|
||||
self.wallet.start_network(self.network)
|
||||
self.contacts = self.wallet.contacts
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class ElectrumGui:
|
|||
if storage.is_encrypted():
|
||||
password = getpass.getpass('Password:', stream=None)
|
||||
storage.decrypt(password)
|
||||
self.wallet = Wallet(storage)
|
||||
self.wallet = Wallet(storage, config=config)
|
||||
self.wallet.start_network(self.network)
|
||||
self.contacts = self.wallet.contacts
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ from collections import namedtuple, defaultdict
|
|||
import binascii
|
||||
import json
|
||||
from enum import Enum, auto
|
||||
from typing import Optional, Dict, List, Tuple, NamedTuple, Set, Callable, Iterable, Sequence
|
||||
from typing import Optional, Dict, List, Tuple, NamedTuple, Set, Callable, Iterable, Sequence, TYPE_CHECKING
|
||||
import time
|
||||
|
||||
from . import ecc
|
||||
|
@ -51,6 +51,9 @@ from .lnsweep import create_sweeptxs_for_our_ctx, create_sweeptxs_for_their_ctx
|
|||
from .lnsweep import create_sweeptx_for_their_revoked_htlc, SweepInfo
|
||||
from .lnhtlc import HTLCManager
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .lnworker import LNWallet
|
||||
|
||||
|
||||
class ChannelJsonEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
|
@ -110,7 +113,7 @@ class Channel(Logger):
|
|||
def __init__(self, state, *, sweep_address=None, name=None, lnworker=None, initial_feerate=None):
|
||||
self.name = name
|
||||
Logger.__init__(self)
|
||||
self.lnworker = lnworker
|
||||
self.lnworker = lnworker # type: Optional[LNWallet]
|
||||
self.sweep_address = sweep_address
|
||||
assert 'local_state' not in state
|
||||
self.config = {}
|
||||
|
|
|
@ -16,7 +16,7 @@ from .lnutil import (make_commitment_output_to_remote_address, make_commitment_o
|
|||
RevocationStore, extract_ctn_from_tx_and_chan, UnableToDeriveSecret, SENT, RECEIVED,
|
||||
map_htlcs_to_ctx_output_idxs, Direction)
|
||||
from .transaction import Transaction, TxOutput, construct_witness
|
||||
from .simple_config import estimate_fee
|
||||
from .simple_config import SimpleConfig
|
||||
from .logging import get_logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -61,7 +61,8 @@ def create_sweeptxs_for_watchtower(chan: 'Channel', ctx: Transaction, per_commit
|
|||
output_idx=output_idx,
|
||||
witness_script=witness_script,
|
||||
privkey=other_revocation_privkey,
|
||||
is_revocation=True)
|
||||
is_revocation=True,
|
||||
config=chan.lnworker.config)
|
||||
if sweep_tx:
|
||||
txs.append(sweep_tx)
|
||||
# HTLCs
|
||||
|
@ -80,7 +81,8 @@ def create_sweeptxs_for_watchtower(chan: 'Channel', ctx: Transaction, per_commit
|
|||
htlctx_witness_script=htlc_tx_witness_script,
|
||||
sweep_address=sweep_address,
|
||||
privkey=other_revocation_privkey,
|
||||
is_revocation=True)
|
||||
is_revocation=True,
|
||||
config=chan.lnworker.config)
|
||||
|
||||
ctn = extract_ctn_from_tx_and_chan(ctx, chan)
|
||||
htlc_to_ctx_output_idx_map = map_htlcs_to_ctx_output_idxs(chan=chan,
|
||||
|
@ -121,7 +123,8 @@ def create_sweeptx_for_their_revoked_ctx(chan: 'Channel', ctx: Transaction, per_
|
|||
output_idx=output_idx,
|
||||
witness_script=witness_script,
|
||||
privkey=other_revocation_privkey,
|
||||
is_revocation=True)
|
||||
is_revocation=True,
|
||||
config=chan.lnworker.config)
|
||||
return sweep_tx
|
||||
return None
|
||||
|
||||
|
@ -155,7 +158,8 @@ def create_sweeptx_for_their_revoked_htlc(chan: 'Channel', ctx: Transaction, htl
|
|||
output_idx=0,
|
||||
witness_script=witness_script,
|
||||
privkey=other_revocation_privkey,
|
||||
is_revocation=True)
|
||||
is_revocation=True,
|
||||
config=chan.lnworker.config)
|
||||
|
||||
return SweepInfo(name='redeem_htlc2',
|
||||
csv_delay=0,
|
||||
|
@ -213,7 +217,8 @@ def create_sweeptxs_for_our_ctx(*, chan: 'Channel', ctx: Transaction,
|
|||
witness_script=to_local_witness_script,
|
||||
privkey=our_localdelayed_privkey.get_secret_bytes(),
|
||||
is_revocation=False,
|
||||
to_self_delay=to_self_delay)
|
||||
to_self_delay=to_self_delay,
|
||||
config=chan.lnworker.config)
|
||||
prevout = ctx.txid() + ':%d'%output_idx
|
||||
txs[prevout] = SweepInfo(name='our_ctx_to_local',
|
||||
csv_delay=to_self_delay,
|
||||
|
@ -246,7 +251,8 @@ def create_sweeptxs_for_our_ctx(*, chan: 'Channel', ctx: Transaction,
|
|||
htlctx_witness_script=htlctx_witness_script,
|
||||
sweep_address=sweep_address,
|
||||
privkey=our_localdelayed_privkey.get_secret_bytes(),
|
||||
is_revocation=False)
|
||||
is_revocation=False,
|
||||
config=chan.lnworker.config)
|
||||
# side effect
|
||||
txs[htlc_tx.prevout(0)] = SweepInfo(name='first-stage-htlc',
|
||||
csv_delay=0,
|
||||
|
@ -352,7 +358,8 @@ def create_sweeptxs_for_their_ctx(*, chan: 'Channel', ctx: Transaction,
|
|||
sweep_address=sweep_address,
|
||||
ctx=ctx,
|
||||
output_idx=output_idx,
|
||||
our_payment_privkey=our_payment_privkey)
|
||||
our_payment_privkey=our_payment_privkey,
|
||||
config=chan.lnworker.config)
|
||||
txs[prevout] = SweepInfo(name='their_ctx_to_remote',
|
||||
csv_delay=0,
|
||||
cltv_expiry=0,
|
||||
|
@ -386,7 +393,8 @@ def create_sweeptxs_for_their_ctx(*, chan: 'Channel', ctx: Transaction,
|
|||
output_idx=ctx_output_idx,
|
||||
privkey=our_revocation_privkey if is_revocation else our_htlc_privkey.get_secret_bytes(),
|
||||
is_revocation=is_revocation,
|
||||
cltv_expiry=cltv_expiry)
|
||||
cltv_expiry=cltv_expiry,
|
||||
config=chan.lnworker.config)
|
||||
txs[prevout] = SweepInfo(name=f'their_ctx_htlc_{ctx_output_idx}',
|
||||
csv_delay=0,
|
||||
cltv_expiry=cltv_expiry,
|
||||
|
@ -432,7 +440,7 @@ def create_htlctx_that_spends_from_our_ctx(chan: 'Channel', our_pcp: bytes,
|
|||
def create_sweeptx_their_ctx_htlc(ctx: Transaction, witness_script: bytes, sweep_address: str,
|
||||
preimage: Optional[bytes], output_idx: int,
|
||||
privkey: bytes, is_revocation: bool,
|
||||
cltv_expiry: int) -> Optional[Transaction]:
|
||||
cltv_expiry: int, config: SimpleConfig) -> Optional[Transaction]:
|
||||
assert type(cltv_expiry) is int
|
||||
preimage = preimage or b'' # preimage is required iff (not is_revocation and htlc is offered)
|
||||
val = ctx.outputs()[output_idx].value
|
||||
|
@ -448,7 +456,7 @@ def create_sweeptx_their_ctx_htlc(ctx: Transaction, witness_script: bytes, sweep
|
|||
'preimage_script': bh2u(witness_script),
|
||||
}]
|
||||
tx_size_bytes = 200 # TODO (depends on offered/received and is_revocation)
|
||||
fee = estimate_fee(tx_size_bytes)
|
||||
fee = config.estimate_fee(tx_size_bytes, allow_fallback_to_static_rates=True)
|
||||
outvalue = val - fee
|
||||
if outvalue <= dust_threshold(): return None
|
||||
sweep_outputs = [TxOutput(TYPE_ADDRESS, sweep_address, outvalue)]
|
||||
|
@ -465,7 +473,8 @@ def create_sweeptx_their_ctx_htlc(ctx: Transaction, witness_script: bytes, sweep
|
|||
|
||||
|
||||
def create_sweeptx_their_ctx_to_remote(sweep_address: str, ctx: Transaction, output_idx: int,
|
||||
our_payment_privkey: ecc.ECPrivkey) -> Optional[Transaction]:
|
||||
our_payment_privkey: ecc.ECPrivkey,
|
||||
config: SimpleConfig) -> Optional[Transaction]:
|
||||
our_payment_pubkey = our_payment_privkey.get_public_key_hex(compressed=True)
|
||||
val = ctx.outputs()[output_idx].value
|
||||
sweep_inputs = [{
|
||||
|
@ -479,7 +488,7 @@ def create_sweeptx_their_ctx_to_remote(sweep_address: str, ctx: Transaction, out
|
|||
'signatures': [None],
|
||||
}]
|
||||
tx_size_bytes = 110 # approx size of p2wpkh->p2wpkh
|
||||
fee = estimate_fee(tx_size_bytes)
|
||||
fee = config.estimate_fee(tx_size_bytes, allow_fallback_to_static_rates=True)
|
||||
outvalue = val - fee
|
||||
if outvalue <= dust_threshold(): return None
|
||||
sweep_outputs = [TxOutput(TYPE_ADDRESS, sweep_address, outvalue)]
|
||||
|
@ -491,8 +500,8 @@ def create_sweeptx_their_ctx_to_remote(sweep_address: str, ctx: Transaction, out
|
|||
return sweep_tx
|
||||
|
||||
|
||||
def create_sweeptx_ctx_to_local(sweep_address: str, ctx: Transaction, output_idx: int, witness_script: str,
|
||||
privkey: bytes, is_revocation: bool,
|
||||
def create_sweeptx_ctx_to_local(*, sweep_address: str, ctx: Transaction, output_idx: int, witness_script: str,
|
||||
privkey: bytes, is_revocation: bool, config: SimpleConfig,
|
||||
to_self_delay: int=None) -> Optional[Transaction]:
|
||||
"""Create a txn that sweeps the 'to_local' output of a commitment
|
||||
transaction into our wallet.
|
||||
|
@ -516,7 +525,7 @@ def create_sweeptx_ctx_to_local(sweep_address: str, ctx: Transaction, output_idx
|
|||
assert isinstance(to_self_delay, int)
|
||||
sweep_inputs[0]['sequence'] = to_self_delay
|
||||
tx_size_bytes = 121 # approx size of to_local -> p2wpkh
|
||||
fee = estimate_fee(tx_size_bytes)
|
||||
fee = config.estimate_fee(tx_size_bytes, allow_fallback_to_static_rates=True)
|
||||
outvalue = val - fee
|
||||
if outvalue <= dust_threshold():
|
||||
return None
|
||||
|
@ -530,7 +539,8 @@ def create_sweeptx_ctx_to_local(sweep_address: str, ctx: Transaction, output_idx
|
|||
|
||||
def create_sweeptx_that_spends_htlctx_that_spends_htlc_in_ctx(*,
|
||||
htlc_tx: Transaction, htlctx_witness_script: bytes, sweep_address: str,
|
||||
privkey: bytes, is_revocation: bool, to_self_delay: int) -> Optional[Transaction]:
|
||||
privkey: bytes, is_revocation: bool, to_self_delay: int,
|
||||
config: SimpleConfig) -> Optional[Transaction]:
|
||||
val = htlc_tx.outputs()[0].value
|
||||
sweep_inputs = [{
|
||||
'scriptSig': '',
|
||||
|
@ -547,7 +557,7 @@ def create_sweeptx_that_spends_htlctx_that_spends_htlc_in_ctx(*,
|
|||
assert isinstance(to_self_delay, int)
|
||||
sweep_inputs[0]['sequence'] = to_self_delay
|
||||
tx_size_bytes = 200 # TODO
|
||||
fee = estimate_fee(tx_size_bytes)
|
||||
fee = config.estimate_fee(tx_size_bytes, allow_fallback_to_static_rates=True)
|
||||
outvalue = val - fee
|
||||
if outvalue <= dust_threshold(): return None
|
||||
sweep_outputs = [TxOutput(TYPE_ADDRESS, sweep_address, outvalue)]
|
||||
|
|
|
@ -312,6 +312,7 @@ class LNWallet(LNWorker):
|
|||
Logger.__init__(self)
|
||||
self.wallet = wallet
|
||||
self.storage = wallet.storage
|
||||
self.config = wallet.config
|
||||
xprv = self.storage.get('lightning_privkey2')
|
||||
if xprv is None:
|
||||
# TODO derive this deterministically from wallet.keystore at keystore generation time
|
||||
|
@ -384,7 +385,6 @@ class LNWallet(LNWorker):
|
|||
await watchtower.add_sweep_tx(outpoint, ctn, tx.prevout(0), str(tx))
|
||||
|
||||
def start_network(self, network: 'Network'):
|
||||
self.config = network.config
|
||||
self.lnwatcher = LNWatcher(network)
|
||||
self.lnwatcher.start_network(network)
|
||||
self.network = network
|
||||
|
|
|
@ -261,9 +261,9 @@ class Wallet_2fa(Multisig_Wallet):
|
|||
|
||||
wallet_type = '2fa'
|
||||
|
||||
def __init__(self, storage):
|
||||
def __init__(self, storage, *, config):
|
||||
self.m, self.n = 2, 3
|
||||
Deterministic_Wallet.__init__(self, storage)
|
||||
Deterministic_Wallet.__init__(self, storage, config=config)
|
||||
self.is_billing = False
|
||||
self.billing_info = None
|
||||
self._load_billing_addresses()
|
||||
|
|
|
@ -18,15 +18,15 @@ assert network.asyncio_loop.is_running()
|
|||
wallet_dir = os.path.dirname(config.get_wallet_path())
|
||||
wallet_path = os.path.join(wallet_dir, "test_wallet")
|
||||
if not os.path.exists(wallet_path):
|
||||
create_new_wallet(path=wallet_path, segwit=True)
|
||||
create_new_wallet(path=wallet_path, config=config)
|
||||
|
||||
# open wallet
|
||||
storage = WalletStorage(wallet_path)
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=config)
|
||||
wallet.start_network(network)
|
||||
|
||||
# you can use ~CLI commands by accessing command_runner
|
||||
command_runner = Commands(config, wallet=None, network=network)
|
||||
command_runner = Commands(config=config, daemon=daemon, network=network)
|
||||
command_runner.wallet = wallet
|
||||
print("balance", command_runner.getbalance())
|
||||
print("addr", command_runner.getunusedaddress())
|
||||
|
|
|
@ -36,27 +36,9 @@ FEERATE_REGTEST_HARDCODED = 180000 # for eclair compat
|
|||
_logger = get_logger(__name__)
|
||||
|
||||
|
||||
def estimate_fee(tx_size_bytes: int) -> int:
|
||||
def use_fallback_feerate():
|
||||
fee_per_kb = FEERATE_FALLBACK_STATIC_FEE
|
||||
fee = SimpleConfig.estimate_fee_for_feerate(fee_per_kb, tx_size_bytes)
|
||||
return fee
|
||||
|
||||
global _INSTANCE
|
||||
if not _INSTANCE:
|
||||
return use_fallback_feerate()
|
||||
try:
|
||||
return _INSTANCE.estimate_fee(tx_size_bytes)
|
||||
except NoDynamicFeeEstimates:
|
||||
return use_fallback_feerate()
|
||||
|
||||
FINAL_CONFIG_VERSION = 3
|
||||
|
||||
|
||||
_INSTANCE = None
|
||||
_ENFORCE_SIMPLECONFIG_SINGLETON = True # disabled in tests
|
||||
|
||||
|
||||
class SimpleConfig(Logger):
|
||||
"""
|
||||
The SimpleConfig class is responsible for handling operations involving
|
||||
|
@ -70,13 +52,6 @@ class SimpleConfig(Logger):
|
|||
|
||||
def __init__(self, options=None, read_user_config_function=None,
|
||||
read_user_dir_function=None):
|
||||
# note: To be honest, singletons are bad design... :/
|
||||
# However currently we somewhat rely on config being one.
|
||||
global _INSTANCE
|
||||
if _ENFORCE_SIMPLECONFIG_SINGLETON:
|
||||
assert _INSTANCE is None, "SimpleConfig is a singleton!"
|
||||
_INSTANCE = self
|
||||
|
||||
if options is None:
|
||||
options = {}
|
||||
|
||||
|
@ -122,10 +97,6 @@ class SimpleConfig(Logger):
|
|||
if self.requires_upgrade():
|
||||
self.upgrade()
|
||||
|
||||
@staticmethod
|
||||
def get_instance() -> Optional["SimpleConfig"]:
|
||||
return _INSTANCE
|
||||
|
||||
def electrum_path(self):
|
||||
# Read electrum_path from command line
|
||||
# Otherwise use the user's default data directory.
|
||||
|
@ -549,10 +520,14 @@ class SimpleConfig(Logger):
|
|||
fee_per_kb = self.fee_per_kb()
|
||||
return fee_per_kb / 1000 if fee_per_kb is not None else None
|
||||
|
||||
def estimate_fee(self, size: Union[int, float, Decimal]) -> int:
|
||||
def estimate_fee(self, size: Union[int, float, Decimal], *,
|
||||
allow_fallback_to_static_rates: bool = False) -> int:
|
||||
fee_per_kb = self.fee_per_kb()
|
||||
if fee_per_kb is None:
|
||||
raise NoDynamicFeeEstimates()
|
||||
if allow_fallback_to_static_rates:
|
||||
fee_per_kb = FEERATE_FALLBACK_STATIC_FEE
|
||||
else:
|
||||
raise NoDynamicFeeEstimates()
|
||||
return self.estimate_fee_for_feerate(fee_per_kb, size)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import unittest
|
||||
import threading
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from electrum import constants
|
||||
from electrum import simple_config
|
||||
|
||||
|
||||
# Set this locally to make the test suite run faster.
|
||||
|
@ -12,10 +13,7 @@ from electrum import simple_config
|
|||
FAST_TESTS = False
|
||||
|
||||
|
||||
simple_config._ENFORCE_SIMPLECONFIG_SINGLETON = False
|
||||
|
||||
|
||||
# some unit tests are modifying globals; sorry.
|
||||
# some unit tests are modifying globals...
|
||||
class SequentialTestCase(unittest.TestCase):
|
||||
|
||||
test_lock = threading.Lock()
|
||||
|
@ -29,7 +27,19 @@ class SequentialTestCase(unittest.TestCase):
|
|||
self.test_lock.release()
|
||||
|
||||
|
||||
class TestCaseForTestnet(SequentialTestCase):
|
||||
class ElectrumTestCase(SequentialTestCase):
|
||||
"""Base class for our unit tests."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUpClass()
|
||||
self.electrum_path = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDownClass()
|
||||
shutil.rmtree(self.electrum_path)
|
||||
|
||||
|
||||
class TestCaseForTestnet(ElectrumTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
|
|
@ -22,7 +22,7 @@ from electrum.keystore import xtype_from_derivation
|
|||
|
||||
from electrum import ecc_fast
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
from . import TestCaseForTestnet
|
||||
from . import FAST_TESTS
|
||||
|
||||
|
@ -84,7 +84,7 @@ def needs_test_with_all_aes_implementations(func):
|
|||
return run_test
|
||||
|
||||
|
||||
class Test_bitcoin(SequentialTestCase):
|
||||
class Test_bitcoin(ElectrumTestCase):
|
||||
|
||||
def test_libsecp256k1_is_available(self):
|
||||
# we want the unit testing framework to test with libsecp256k1 available.
|
||||
|
@ -393,7 +393,7 @@ class Test_bitcoin_testnet(TestCaseForTestnet):
|
|||
self.assertEqual(address_to_script('2NE4ZdmxFmUgwu5wtfoN2gVniyMgRDYq1kk'), 'a914e4567743d378957cd2ee7072da74b1203c1a7a0b87')
|
||||
|
||||
|
||||
class Test_xprv_xpub(SequentialTestCase):
|
||||
class Test_xprv_xpub(ElectrumTestCase):
|
||||
|
||||
xprv_xpub = (
|
||||
# Taken from test vectors in https://en.bitcoin.it/wiki/BIP_0032_TestVectors
|
||||
|
@ -585,7 +585,7 @@ class Test_xprv_xpub_testnet(TestCaseForTestnet):
|
|||
self.assertTrue(xkey_b58.startswith(xpub_headers_b58[xtype]))
|
||||
|
||||
|
||||
class Test_keyImport(SequentialTestCase):
|
||||
class Test_keyImport(ElectrumTestCase):
|
||||
|
||||
priv_pub_addr = (
|
||||
{'priv': 'KzMFjMC2MPadjvX5Cd7b8AKKjjpBSoRKUTpoAtN6B3J9ezWYyXS6',
|
||||
|
@ -751,7 +751,7 @@ class Test_keyImport(SequentialTestCase):
|
|||
raise_on_error=True)
|
||||
|
||||
|
||||
class TestBaseEncode(SequentialTestCase):
|
||||
class TestBaseEncode(ElectrumTestCase):
|
||||
|
||||
def test_base43(self):
|
||||
tx_hex = "020000000001021cd0e96f9ca202e017ca3465e3c13373c0df3a4cdd91c1fd02ea42a1a65d2a410000000000fdffffff757da7cf8322e5063785e2d8ada74702d2648fa2add2d533ba83c52eb110df690200000000fdffffff02d07e010000000000160014b544c86eaf95e3bb3b6d2cabb12ab40fc59cad9ca086010000000000232102ce0d066fbfcf150a5a1bbc4f312cd2eb080e8d8a47e5f2ce1a63b23215e54fb5ac02483045022100a9856bf10a950810abceeabc9a86e6ba533e130686e3d7863971b9377e7c658a0220288a69ef2b958a7c2ecfa376841d4a13817ed24fa9a0e0a6b9cb48e6439794c701210324e291735f83ff8de47301b12034950b80fa4724926a34d67e413d8ff8817c53024830450221008f885978f7af746679200ed55fe2e86c1303620824721f95cc41eb7965a3dfcf02207872082ac4a3c433d41a203e6d685a459e70e551904904711626ac899238c20a0121023d4c9deae1aacf3f822dd97a28deaec7d4e4ff97be746d124a63d20e582f5b290a971600"
|
||||
|
|
|
@ -7,10 +7,10 @@ from electrum.simple_config import SimpleConfig
|
|||
from electrum.blockchain import Blockchain, deserialize_header, hash_header
|
||||
from electrum.util import bh2u, bfh, make_dir
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class TestBlockchain(SequentialTestCase):
|
||||
class TestBlockchain(ElectrumTestCase):
|
||||
|
||||
HEADERS = {
|
||||
'A': deserialize_header(bfh("0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f2002000000"), 0),
|
||||
|
@ -57,15 +57,11 @@ class TestBlockchain(SequentialTestCase):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.data_dir = tempfile.mkdtemp()
|
||||
self.data_dir = self.electrum_path
|
||||
make_dir(os.path.join(self.data_dir, 'forks'))
|
||||
self.config = SimpleConfig({'electrum_path': self.data_dir})
|
||||
blockchain.blockchains = {}
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
shutil.rmtree(self.data_dir)
|
||||
|
||||
def _append_header(self, chain: Blockchain, header: dict):
|
||||
self.assertTrue(chain.can_connect(header))
|
||||
chain.save_header(header)
|
||||
|
@ -341,7 +337,7 @@ class TestBlockchain(SequentialTestCase):
|
|||
self.assertTrue(all([b.can_connect(b.read_header(i), False) for i in range(b.height())]))
|
||||
|
||||
|
||||
class TestVerifyHeader(SequentialTestCase):
|
||||
class TestVerifyHeader(ElectrumTestCase):
|
||||
|
||||
# Data for Bitcoin block header #100.
|
||||
valid_header = "0100000095194b8567fe2e8bbda931afd01a7acd399b9325cb54683e64129bcd00000000660802c98f18fd34fd16d61c63cf447568370124ac5f3be626c2e1c3c9f0052d19a76949ffff001d33f3c25d"
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
from hashlib import sha256
|
||||
from electrum.lnaddr import shorten_amount, unshorten_amount, LnAddr, lnencode, lndecode, u5_to_bitarray, bitarray_to_u5
|
||||
from decimal import Decimal
|
||||
from binascii import unhexlify, hexlify
|
||||
from electrum.segwit_addr import bech32_encode, bech32_decode
|
||||
import pprint
|
||||
import unittest
|
||||
|
||||
from electrum.lnaddr import shorten_amount, unshorten_amount, LnAddr, lnencode, lndecode, u5_to_bitarray, bitarray_to_u5
|
||||
from electrum.segwit_addr import bech32_encode, bech32_decode
|
||||
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
RHASH=unhexlify('0001020304050607080900010203040506070809000102030405060708090102')
|
||||
CONVERSION_RATE=1200
|
||||
PRIVKEY=unhexlify('e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734')
|
||||
PUBKEY=unhexlify('03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad')
|
||||
|
||||
class TestBolt11(unittest.TestCase):
|
||||
|
||||
class TestBolt11(ElectrumTestCase):
|
||||
def test_shorten_amount(self):
|
||||
tests = {
|
||||
Decimal(10)/10**12: '10p',
|
||||
|
|
|
@ -6,15 +6,17 @@ from electrum.util import create_and_start_event_loop
|
|||
from electrum.commands import Commands, eval_bool
|
||||
from electrum import storage
|
||||
from electrum.wallet import restore_wallet_from_text
|
||||
from electrum.simple_config import SimpleConfig
|
||||
|
||||
from . import TestCaseForTestnet
|
||||
from . import TestCaseForTestnet, ElectrumTestCase
|
||||
|
||||
|
||||
class TestCommands(unittest.TestCase):
|
||||
class TestCommands(ElectrumTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.asyncio_loop, self._stop_loop, self._loop_thread = create_and_start_event_loop()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
|
@ -56,7 +58,7 @@ class TestCommands(unittest.TestCase):
|
|||
self.assertTrue(eval_bool("1"))
|
||||
|
||||
def test_convert_xkey(self):
|
||||
cmds = Commands(config=None)
|
||||
cmds = Commands(config=self.config)
|
||||
xpubs = {
|
||||
("xpub6CCWFbvCbqF92kGwm9nV7t7RvVoQUKaq5USMdyVP6jvv1NgN52KAX6NNYCeE8Ca7JQC4K5tZcnQrubQcjJ6iixfPs4pwAQJAQgTt6hBjg11", "standard"),
|
||||
("ypub6X2mZGb7kWnct3U4bWa7KyCw6TwrQwaKzaxaRNPGUkJo4UVbKgUj9A2WZQbp87E2i3Js4ZV85SmQnt2BSzWjXCLzjQXMkK7egQXXVHT4eKn", "p2wpkh-p2sh"),
|
||||
|
@ -78,8 +80,9 @@ class TestCommands(unittest.TestCase):
|
|||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_encrypt_decrypt(self, mock_write):
|
||||
wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN',
|
||||
path='if_this_exists_mocking_failed_648151893')['wallet']
|
||||
cmds = Commands(config=None)
|
||||
path='if_this_exists_mocking_failed_648151893',
|
||||
config=self.config)['wallet']
|
||||
cmds = Commands(config=self.config)
|
||||
cleartext = "asdasd this is the message"
|
||||
pubkey = "021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da"
|
||||
ciphertext = cmds._run('encrypt', (pubkey, cleartext))
|
||||
|
@ -88,8 +91,9 @@ class TestCommands(unittest.TestCase):
|
|||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_export_private_key_imported(self, mock_write):
|
||||
wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL',
|
||||
path='if_this_exists_mocking_failed_648151893')['wallet']
|
||||
cmds = Commands(config=None)
|
||||
path='if_this_exists_mocking_failed_648151893',
|
||||
config=self.config)['wallet']
|
||||
cmds = Commands(config=self.config)
|
||||
# single address tests
|
||||
with self.assertRaises(Exception):
|
||||
cmds._run('getprivatekeys', ("asdasd",), wallet=wallet) # invalid addr, though might raise "not in wallet"
|
||||
|
@ -107,8 +111,9 @@ class TestCommands(unittest.TestCase):
|
|||
def test_export_private_key_deterministic(self, mock_write):
|
||||
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')['wallet']
|
||||
cmds = Commands(config=None)
|
||||
path='if_this_exists_mocking_failed_648151893',
|
||||
config=self.config)['wallet']
|
||||
cmds = Commands(config=self.config)
|
||||
# single address tests
|
||||
with self.assertRaises(Exception):
|
||||
cmds._run('getprivatekeys', ("asdasd",), wallet=wallet) # invalid addr, though might raise "not in wallet"
|
||||
|
@ -128,6 +133,7 @@ class TestCommandsTestnet(TestCaseForTestnet):
|
|||
def setUp(self):
|
||||
super().setUp()
|
||||
self.asyncio_loop, self._stop_loop, self._loop_thread = create_and_start_event_loop()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
|
@ -135,7 +141,7 @@ class TestCommandsTestnet(TestCaseForTestnet):
|
|||
self._loop_thread.join(timeout=1)
|
||||
|
||||
def test_convert_xkey(self):
|
||||
cmds = Commands(config=None)
|
||||
cmds = Commands(config=self.config)
|
||||
xpubs = {
|
||||
("tpubD8p5qNfjczgTGbh9qgNxsbFgyhv8GgfVkmp3L88qtRm5ibUYiDVCrn6WYfnGey5XVVw6Bc5QNQUZW5B4jFQsHjmaenvkFUgWtKtgj5AdPm9", "standard"),
|
||||
("upub59wfQ8qJTg6ZSuvwtR313Qdp8gP8TSBwTof5dPQ3QVsYp1N9t29Rr9TGF1pj8kAXUg3mKbmrTKasA2qmBJKb1bGUzB6ApDZpVC7LoHhyvBo", "p2wpkh-p2sh"),
|
||||
|
|
|
@ -2,11 +2,11 @@ import dns
|
|||
|
||||
from electrum import dnssec
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
from .test_bitcoin import needs_test_with_all_ecc_implementations
|
||||
|
||||
|
||||
class TestDnsSec(SequentialTestCase):
|
||||
class TestDnsSec(ElectrumTestCase):
|
||||
|
||||
@needs_test_with_all_ecc_implementations
|
||||
def test_python_validate_rrsig_ecdsa(self):
|
||||
|
|
|
@ -35,6 +35,9 @@ from electrum.lnutil import FeeUpdate
|
|||
from electrum.ecc import sig_string_from_der_sig
|
||||
from electrum.logging import console_stderr_handler
|
||||
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
one_bitcoin_in_msat = bitcoin.COIN * 1000
|
||||
|
||||
def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator, local_amount, remote_amount, privkeys, other_pubkeys, seed, cur, nex, other_node_id, l_dust, r_dust, l_csv, r_csv):
|
||||
|
@ -160,7 +163,7 @@ def create_test_channels(feerate=6000, local=None, remote=None):
|
|||
|
||||
return alice, bob
|
||||
|
||||
class TestFee(unittest.TestCase):
|
||||
class TestFee(ElectrumTestCase):
|
||||
"""
|
||||
test
|
||||
https://github.com/lightningnetwork/lightning-rfc/blob/e0c436bd7a3ed6a028e1cb472908224658a14eca/03-transactions.md#requirements-2
|
||||
|
@ -169,7 +172,7 @@ class TestFee(unittest.TestCase):
|
|||
alice_channel, bob_channel = create_test_channels(253, 10000000000, 5000000000)
|
||||
self.assertIn(9999817, [x[2] for x in alice_channel.get_latest_commitment(LOCAL).outputs()])
|
||||
|
||||
class TestChannel(unittest.TestCase):
|
||||
class TestChannel(ElectrumTestCase):
|
||||
maxDiff = 999
|
||||
|
||||
def assertOutputExistsByValue(self, tx, amt_sat):
|
||||
|
@ -181,9 +184,11 @@ class TestChannel(unittest.TestCase):
|
|||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
console_stderr_handler.setLevel(logging.DEBUG)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# Create a test channel which will be used for the duration of this
|
||||
# unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||
# and Bob having 5 BTC.
|
||||
|
@ -607,7 +612,7 @@ class TestChannel(unittest.TestCase):
|
|||
self.assertIn('Not enough local balance', cm.exception.args[0])
|
||||
|
||||
|
||||
class TestAvailableToSpend(unittest.TestCase):
|
||||
class TestAvailableToSpend(ElectrumTestCase):
|
||||
def test_DesyncHTLCs(self):
|
||||
alice_channel, bob_channel = create_test_channels()
|
||||
|
||||
|
@ -645,7 +650,7 @@ class TestAvailableToSpend(unittest.TestCase):
|
|||
force_state_transition(alice_channel, bob_channel)
|
||||
alice_channel.add_htlc(htlc_dict)
|
||||
|
||||
class TestChanReserve(unittest.TestCase):
|
||||
class TestChanReserve(ElectrumTestCase):
|
||||
def setUp(self):
|
||||
alice_channel, bob_channel = create_test_channels()
|
||||
alice_min_reserve = int(.5 * one_bitcoin_in_msat // 1000)
|
||||
|
@ -778,7 +783,7 @@ class TestChanReserve(unittest.TestCase):
|
|||
self.assertEqual(self.alice_channel.available_to_spend(REMOTE), amt2)
|
||||
self.assertEqual(self.bob_channel.available_to_spend(LOCAL), amt2)
|
||||
|
||||
class TestDust(unittest.TestCase):
|
||||
class TestDust(ElectrumTestCase):
|
||||
def test_DustLimit(self):
|
||||
alice_channel, bob_channel = create_test_channels()
|
||||
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
from pprint import pprint
|
||||
import unittest
|
||||
from typing import NamedTuple
|
||||
|
||||
from electrum.lnutil import RECEIVED, LOCAL, REMOTE, SENT, HTLCOwner, Direction
|
||||
from electrum.lnhtlc import HTLCManager
|
||||
from typing import NamedTuple
|
||||
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class H(NamedTuple):
|
||||
owner : str
|
||||
htlc_id : int
|
||||
|
||||
class TestHTLCManager(unittest.TestCase):
|
||||
class TestHTLCManager(ElectrumTestCase):
|
||||
def test_adding_htlcs_race(self):
|
||||
A = HTLCManager()
|
||||
B = HTLCManager()
|
||||
|
|
|
@ -24,7 +24,7 @@ from electrum.logging import console_stderr_handler
|
|||
from electrum.lnworker import InvoiceInfo, RECEIVED, PR_UNPAID
|
||||
|
||||
from .test_lnchannel import create_test_channels
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
|
||||
def keypair():
|
||||
priv = ECPrivkey.generate_random_key().get_secret_bytes()
|
||||
|
@ -173,7 +173,7 @@ def transport_pair(name1, name2):
|
|||
t2.other_mock_transport = t1
|
||||
return t1, t2
|
||||
|
||||
class TestPeer(SequentialTestCase):
|
||||
class TestPeer(ElectrumTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
|
|
@ -29,25 +29,15 @@ class Test_LNRouter(TestCaseForTestnet):
|
|||
# assert witness_bytes == b"", witness_bytes
|
||||
# return res
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.electrum_path = tempfile.mkdtemp()
|
||||
cls.config = SimpleConfig({'electrum_path': cls.electrum_path})
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.asyncio_loop, self._stop_loop, self._loop_thread = create_and_start_event_loop()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
shutil.rmtree(cls.electrum_path)
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
self.asyncio_loop.call_soon_threadsafe(self._stop_loop.set_result, 1)
|
||||
self._loop_thread.join(timeout=1)
|
||||
super().tearDown()
|
||||
|
||||
def test_find_path_for_payment(self):
|
||||
class fake_network:
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
from electrum.ecc import ECPrivkey
|
||||
import asyncio
|
||||
|
||||
from electrum.ecc import ECPrivkey
|
||||
from electrum.lnutil import LNPeerAddr
|
||||
from electrum.lntransport import LNResponderTransport, LNTransport
|
||||
from unittest import TestCase
|
||||
|
||||
class TestLNTransport(TestCase):
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class TestLNTransport(ElectrumTestCase):
|
||||
|
||||
def test_responder(self):
|
||||
# local static
|
||||
ls_priv=bytes.fromhex('2121212121212121212121212121212121212121212121212121212121212121')
|
||||
|
@ -32,6 +36,7 @@ class TestLNTransport(TestCase):
|
|||
return bytes.fromhex('00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba')
|
||||
transport = LNResponderTransport(ls_priv, Reader(), Writer())
|
||||
asyncio.get_event_loop().run_until_complete(transport.handshake(epriv=e_priv))
|
||||
|
||||
def test_loop(self):
|
||||
l = asyncio.get_event_loop()
|
||||
responder_shaked = asyncio.Event()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import unittest
|
||||
import json
|
||||
|
||||
from electrum import bitcoin
|
||||
from electrum.lnutil import (RevocationStore, get_per_commitment_secret_from_seed, make_offered_htlc,
|
||||
make_received_htlc, make_commitment, make_htlc_tx_witness, make_htlc_tx_output,
|
||||
|
@ -10,6 +11,9 @@ from electrum.lnutil import (RevocationStore, get_per_commitment_secret_from_see
|
|||
from electrum.util import bh2u, bfh
|
||||
from electrum.transaction import Transaction
|
||||
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
funding_tx_id = '8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be'
|
||||
funding_output_index = 0
|
||||
funding_amount_satoshi = 10000000
|
||||
|
@ -30,7 +34,8 @@ local_delayedpubkey = bytes.fromhex('03fd5960528dc152014952efdb702a88f71e3c1653b
|
|||
local_revocation_pubkey = bytes.fromhex('0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19')
|
||||
# funding wscript = 5221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae
|
||||
|
||||
class TestLNUtil(unittest.TestCase):
|
||||
|
||||
class TestLNUtil(ElectrumTestCase):
|
||||
def test_shachain_store(self):
|
||||
tests = [
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ from electrum.util import bh2u, bfh
|
|||
from electrum.mnemonic import is_new_seed, is_old_seed, seed_type
|
||||
from electrum.version import SEED_PREFIX_SW, SEED_PREFIX
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
from .test_wallet_vertical import UNICODE_HORROR, UNICODE_HORROR_HEX
|
||||
|
||||
|
||||
|
@ -95,7 +95,7 @@ SEED_TEST_CASES = {
|
|||
}
|
||||
|
||||
|
||||
class Test_NewMnemonic(SequentialTestCase):
|
||||
class Test_NewMnemonic(ElectrumTestCase):
|
||||
|
||||
def test_mnemonic_to_seed_basic(self):
|
||||
# note: not a valid electrum seed
|
||||
|
@ -125,7 +125,7 @@ class Test_NewMnemonic(SequentialTestCase):
|
|||
self.assertEqual(m.mnemonic_encode(i), seed)
|
||||
|
||||
|
||||
class Test_OldMnemonic(SequentialTestCase):
|
||||
class Test_OldMnemonic(ElectrumTestCase):
|
||||
|
||||
def test(self):
|
||||
seed = '8edad31a95e7d59f8837667510d75a4d'
|
||||
|
@ -135,7 +135,7 @@ class Test_OldMnemonic(SequentialTestCase):
|
|||
self.assertEqual(old_mnemonic.mn_decode(result), seed)
|
||||
|
||||
|
||||
class Test_BIP39Checksum(SequentialTestCase):
|
||||
class Test_BIP39Checksum(ElectrumTestCase):
|
||||
|
||||
def test(self):
|
||||
mnemonic = u'gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog'
|
||||
|
@ -144,7 +144,7 @@ class Test_BIP39Checksum(SequentialTestCase):
|
|||
self.assertTrue(is_checksum_valid)
|
||||
|
||||
|
||||
class Test_seeds(SequentialTestCase):
|
||||
class Test_seeds(ElectrumTestCase):
|
||||
""" Test old and new seeds. """
|
||||
|
||||
mnemonics = {
|
||||
|
|
|
@ -9,6 +9,8 @@ from electrum.interface import Interface
|
|||
from electrum.crypto import sha256
|
||||
from electrum.util import bh2u
|
||||
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class MockTaskGroup:
|
||||
async def spawn(self, x): return
|
||||
|
@ -36,7 +38,7 @@ class MockInterface(Interface):
|
|||
assert assert_mode in item['mock'], (assert_mode, item)
|
||||
return item
|
||||
|
||||
class TestNetwork(unittest.TestCase):
|
||||
class TestNetwork(ElectrumTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -49,7 +51,8 @@ class TestNetwork(unittest.TestCase):
|
|||
constants.set_mainnet()
|
||||
|
||||
def setUp(self):
|
||||
self.config = SimpleConfig({'electrum_path': tempfile.mkdtemp(prefix="test_network")})
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
self.interface = MockInterface(self.config)
|
||||
|
||||
def test_fork_noconflict(self):
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from electrum.plugins.revealer.revealer import RevealerPlugin
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class TestRevealer(SequentialTestCase):
|
||||
class TestRevealer(ElectrumTestCase):
|
||||
|
||||
def test_version_0_noisemap(self):
|
||||
versioned_seed = RevealerPlugin.get_versioned_seed_from_user_input('03b0c557d6d0d4308a3393851d78bd8c7861')
|
||||
|
|
|
@ -7,10 +7,10 @@ import shutil
|
|||
from io import StringIO
|
||||
from electrum.simple_config import (SimpleConfig, read_user_config)
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class Test_SimpleConfig(SequentialTestCase):
|
||||
class Test_SimpleConfig(ElectrumTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_SimpleConfig, self).setUp()
|
||||
|
@ -147,7 +147,7 @@ class Test_SimpleConfig(SequentialTestCase):
|
|||
self.assertEqual(36495000, config.fee_to_depth(0.5))
|
||||
|
||||
|
||||
class TestUserConfig(SequentialTestCase):
|
||||
class TestUserConfig(ElectrumTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestUserConfig, self).setUp()
|
||||
|
|
|
@ -278,8 +278,8 @@ class TestStorageUpgrade(WalletTestCase):
|
|||
from electrum.plugin import Plugins
|
||||
from electrum.simple_config import SimpleConfig
|
||||
|
||||
cls.electrum_path = tempfile.mkdtemp()
|
||||
config = SimpleConfig({'electrum_path': cls.electrum_path})
|
||||
cls.__electrum_path = tempfile.mkdtemp()
|
||||
config = SimpleConfig({'electrum_path': cls.__electrum_path})
|
||||
|
||||
gui_name = 'cmdline'
|
||||
# TODO it's probably wasteful to load all plugins... only need Trezor
|
||||
|
@ -288,7 +288,7 @@ class TestStorageUpgrade(WalletTestCase):
|
|||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
shutil.rmtree(cls.electrum_path)
|
||||
shutil.rmtree(cls.__electrum_path)
|
||||
|
||||
def _upgrade_storage(self, wallet_json, accounts=1):
|
||||
if accounts == 1:
|
||||
|
@ -326,7 +326,7 @@ class TestStorageUpgrade(WalletTestCase):
|
|||
def _sanity_check_upgraded_storage(self, storage):
|
||||
self.assertFalse(storage.requires_split())
|
||||
self.assertFalse(storage.requires_upgrade())
|
||||
w = Wallet(storage)
|
||||
w = Wallet(storage, config=self.config)
|
||||
|
||||
@staticmethod
|
||||
def _load_storage_from_json_string(*, wallet_json, path, manual_upgrades):
|
||||
|
|
|
@ -4,7 +4,7 @@ from electrum.bitcoin import TYPE_ADDRESS
|
|||
from electrum.keystore import xpubkey_to_address
|
||||
from electrum.util import bh2u, bfh
|
||||
|
||||
from . import SequentialTestCase, TestCaseForTestnet
|
||||
from . import ElectrumTestCase, TestCaseForTestnet
|
||||
from .test_bitcoin import needs_test_with_all_ecc_implementations
|
||||
|
||||
unsigned_blob = '45505446ff0001000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b424eb4031000000005701ff4c53ff0488b21e03ef2afea18000000089689bff23e1e7fb2f161daa37270a97a3d8c2e537584b2d304ecb47b86d21fc021b010d3bd425f8cf2e04824bfdf1f1f5ff1d51fadd9a41f9e3fb8dd3403b1bfe00000000ffffffff0140420f00000000001976a914230ac37834073a42146f11ef8414ae929feaafc388ac00000000'
|
||||
|
@ -14,7 +14,7 @@ signed_segwit_blob = "01000000000101b66d722484f2db63e827ebf41d02684fed0c6550e850
|
|||
|
||||
signed_blob_signatures = ['3046022100a82bbc57a0136751e5433f41cf000b3f1a99c6744775e76ec764fb78c54ee100022100f9e80b7de89de861dc6fb0c1429d5da72c2b6b2ee2406bc9bfb1beedd729d98501', ]
|
||||
|
||||
class TestBCDataStream(SequentialTestCase):
|
||||
class TestBCDataStream(ElectrumTestCase):
|
||||
|
||||
def test_compact_size(self):
|
||||
s = transaction.BCDataStream()
|
||||
|
@ -55,7 +55,7 @@ class TestBCDataStream(SequentialTestCase):
|
|||
self.assertEqual(s.read_bytes(4), b'r')
|
||||
self.assertEqual(s.read_bytes(1), b'')
|
||||
|
||||
class TestTransaction(SequentialTestCase):
|
||||
class TestTransaction(ElectrumTestCase):
|
||||
|
||||
@needs_test_with_all_ecc_implementations
|
||||
def test_tx_unsigned(self):
|
||||
|
|
|
@ -3,10 +3,10 @@ from decimal import Decimal
|
|||
from electrum.util import (format_satoshis, format_fee_satoshis, parse_URI,
|
||||
is_hash256_str, chunks, is_ip_address, list_enabled_bits)
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class TestUtil(SequentialTestCase):
|
||||
class TestUtil(ElectrumTestCase):
|
||||
|
||||
def test_format_satoshis(self):
|
||||
self.assertEqual("0.00001234", format_satoshis(1234))
|
||||
|
|
|
@ -15,8 +15,9 @@ from electrum.exchange_rate import ExchangeBase, FxThread
|
|||
from electrum.util import TxMinedInfo
|
||||
from electrum.bitcoin import COIN
|
||||
from electrum.json_db import JsonDB
|
||||
from electrum.simple_config import SimpleConfig
|
||||
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class FakeSynchronizer(object):
|
||||
|
@ -28,11 +29,12 @@ class FakeSynchronizer(object):
|
|||
self.store.append(address)
|
||||
|
||||
|
||||
class WalletTestCase(SequentialTestCase):
|
||||
class WalletTestCase(ElectrumTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(WalletTestCase, self).setUp()
|
||||
self.user_dir = tempfile.mkdtemp()
|
||||
self.config = SimpleConfig({'electrum_path': self.user_dir})
|
||||
|
||||
self.wallet_path = os.path.join(self.user_dir, "somewallet")
|
||||
|
||||
|
@ -114,7 +116,7 @@ class FakeWallet:
|
|||
txid = 'abc'
|
||||
ccy = 'TEST'
|
||||
|
||||
class TestFiat(SequentialTestCase):
|
||||
class TestFiat(ElectrumTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.value_sat = COIN
|
||||
|
@ -156,7 +158,8 @@ class TestCreateRestoreWallet(WalletTestCase):
|
|||
passphrase=passphrase,
|
||||
password=password,
|
||||
encrypt_file=encrypt_file,
|
||||
gap_limit=1)
|
||||
gap_limit=1,
|
||||
config=self.config)
|
||||
wallet = d['wallet'] # type: Standard_Wallet
|
||||
wallet.check_password(password)
|
||||
self.assertEqual(passphrase, wallet.keystore.get_passphrase(password))
|
||||
|
@ -173,7 +176,8 @@ class TestCreateRestoreWallet(WalletTestCase):
|
|||
passphrase=passphrase,
|
||||
password=password,
|
||||
encrypt_file=encrypt_file,
|
||||
gap_limit=1)
|
||||
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))
|
||||
|
@ -182,28 +186,28 @@ class TestCreateRestoreWallet(WalletTestCase):
|
|||
|
||||
def test_restore_wallet_from_text_xpub(self):
|
||||
text = 'zpub6nydoME6CFdJtMpzHW5BNoPz6i6XbeT9qfz72wsRqGdgGEYeivso6xjfw8cGcCyHwF7BNW4LDuHF35XrZsovBLWMF4qXSjmhTXYiHbWqGLt'
|
||||
d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1)
|
||||
d = restore_wallet_from_text(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])
|
||||
|
||||
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)
|
||||
d = restore_wallet_from_text(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])
|
||||
|
||||
def test_restore_wallet_from_text_xprv(self):
|
||||
text = 'zprvAZzHPqhCMt51fskXBUYB1fTFYgG3CBjJUT4WEZTpGw6hPSDWBPZYZARC5sE9xAcX8NeWvvucFws8vZxEa65RosKAhy7r5MsmKTxr3hmNmea'
|
||||
d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1)
|
||||
d = restore_wallet_from_text(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])
|
||||
|
||||
def test_restore_wallet_from_text_addresses(self):
|
||||
text = 'bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw bc1qnp78h78vp92pwdwq5xvh8eprlga5q8gu66960c'
|
||||
d = restore_wallet_from_text(text, path=self.wallet_path)
|
||||
d = restore_wallet_from_text(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()))
|
||||
|
@ -213,7 +217,7 @@ class TestCreateRestoreWallet(WalletTestCase):
|
|||
|
||||
def test_restore_wallet_from_text_privkeys(self):
|
||||
text = 'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL p2wpkh:L24GxnN7NNUAfCXA6hFzB1jt59fYAAiFZMcLaJ2ZSawGpM3uqhb1'
|
||||
d = restore_wallet_from_text(text, path=self.wallet_path)
|
||||
d = restore_wallet_from_text(text, path=self.wallet_path, config=self.config)
|
||||
wallet = d['wallet'] # type: Imported_Wallet
|
||||
addr0 = wallet.get_receiving_addresses()[0]
|
||||
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', addr0)
|
||||
|
|
|
@ -17,7 +17,7 @@ from electrum.mnemonic import seed_type
|
|||
from electrum.plugins.trustedcoin import trustedcoin
|
||||
|
||||
from . import TestCaseForTestnet
|
||||
from . import SequentialTestCase
|
||||
from . import ElectrumTestCase
|
||||
from .test_bitcoin import needs_test_with_all_ecc_implementations
|
||||
|
||||
|
||||
|
@ -45,25 +45,26 @@ class WalletIntegrityHelper:
|
|||
test_obj.assertFalse(ks.has_seed())
|
||||
|
||||
@classmethod
|
||||
def create_standard_wallet(cls, ks, gap_limit=None):
|
||||
def create_standard_wallet(cls, ks, *, config: SimpleConfig, gap_limit=None):
|
||||
store = storage.WalletStorage('if_this_exists_mocking_failed_648151893')
|
||||
store.put('keystore', ks.dump())
|
||||
store.put('gap_limit', gap_limit or cls.gap_limit)
|
||||
w = Standard_Wallet(store)
|
||||
w = Standard_Wallet(store, config=config)
|
||||
w.synchronize()
|
||||
return w
|
||||
|
||||
@classmethod
|
||||
def create_imported_wallet(cls, privkeys=False):
|
||||
def create_imported_wallet(cls, *, config: SimpleConfig, privkeys: bool):
|
||||
store = storage.WalletStorage('if_this_exists_mocking_failed_648151893')
|
||||
if privkeys:
|
||||
k = keystore.Imported_KeyStore({})
|
||||
store.put('keystore', k.dump())
|
||||
w = Imported_Wallet(store)
|
||||
w = Imported_Wallet(store, config=config)
|
||||
return w
|
||||
|
||||
@classmethod
|
||||
def create_multisig_wallet(cls, keystores: Sequence, multisig_type: str, gap_limit=None):
|
||||
def create_multisig_wallet(cls, keystores: Sequence, multisig_type: str, *,
|
||||
config: SimpleConfig, gap_limit=None):
|
||||
"""Creates a multisig wallet."""
|
||||
store = storage.WalletStorage('if_this_exists_mocking_failed_648151893')
|
||||
for i, ks in enumerate(keystores):
|
||||
|
@ -71,12 +72,16 @@ class WalletIntegrityHelper:
|
|||
store.put('x%d/' % cosigner_index, ks.dump())
|
||||
store.put('wallet_type', multisig_type)
|
||||
store.put('gap_limit', gap_limit or cls.gap_limit)
|
||||
w = Multisig_Wallet(store)
|
||||
w = Multisig_Wallet(store, config=config)
|
||||
w.synchronize()
|
||||
return w
|
||||
|
||||
|
||||
class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
||||
class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
@needs_test_with_all_ecc_implementations
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
|
@ -92,7 +97,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'xprv9s21ZrQH143K32jECVM729vWgGq4mUDJCk1ozqAStTphzQtCTuoFmFafNoG1g55iCnBTXUzz3zWnDb5CVLGiFvmaZjuazHDL8a81cPQ8KL6')
|
||||
self.assertEqual(ks.xpub, 'xpub661MyMwAqRbcFWohJWt7PHsFEJfZAvw9ZxwQoDa4SoMgsDDM1T7WK3u9E4edkC4ugRnZ8E4xDZRpk8Rnts3Nbt97dPwT52CwBdDWroaZf8U')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2pkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '1NNkttn1YvVGdqBW4PR6zvc3Zx3H5owKRf')
|
||||
|
@ -112,7 +117,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'zprvAZswDvNeJeha8qZ8g7efN3FXYVJLaEUsE9TW6qXDEbVe74AZ75c2sZFZXPNFzxnhChDQ89oC8C5AjWwHmH1HeRKE1c4kKBQAmjUDdKDUZw2')
|
||||
self.assertEqual(ks.xpub, 'zpub6nsHdRuY92FsMKdbn9BfjBCG6X8pyhCibNP6uDvpnw2cyrVhecvHRMa3Ne8kdJZxjxgwnpbHLkcR4bfnhHy6auHPJyDTQ3kianeuVLdkCYQ')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wpkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af')
|
||||
|
@ -132,7 +137,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'zprvAZDmEQiCLUcZXPfrBXoksCD2R6RMAzAre7SUyBotibisy9c7vGhLYvHaP3d9rYU12DKAWdZfscPNA7qEPgTkCDqX5sE93ryAJAQvkDbfLxU')
|
||||
self.assertEqual(ks.xpub, 'zpub6nD7dvF6ArArjskKHZLmEL9ky8FqaSti1LN5maDWGwFrqwwGTp1b6ic4EHwciFNaYDmCXcQYxXSiF9BjcLCMPcaYkVN2nQD6QjYQ8vpSR3Z')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wpkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1qx94dutas7ysn2my645cyttujrms5d9p57f6aam')
|
||||
|
@ -151,7 +156,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
|
||||
self.assertEqual(ks.mpk, 'e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2pkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '1FJEEB8ihPMbzs2SkLmr37dHyRFzakqUmo')
|
||||
|
@ -186,7 +191,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks3)
|
||||
self.assertTrue(isinstance(ks3, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2sh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '35L8XmCDoEBKeaWRjvmZvoZvhp8BXMMMPV')
|
||||
|
@ -221,7 +226,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks3)
|
||||
self.assertTrue(isinstance(ks3, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wsh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1qpmufh0zjp5prfsrk2yskcy82sa26srqkd97j0457andc6m0gh5asw7kqd2')
|
||||
|
@ -240,7 +245,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'xprv9zGLcNEb3cHUKizLVBz6RYeE9bEZAVPjH2pD1DEzCnPcsemWc3d3xTao8sfhfUmDLMq6e3RcEMEvJG1Et8dvfL8DV4h7mwm9J6AJsW9WXQD')
|
||||
self.assertEqual(ks.xpub, 'xpub6DFh1smUsyqmYD4obDX6ngaxhd53Zx7aeFjoobebm7vbkT6f9awJWFuGzBT9FQJEWFBL7UyhMXtYzRcwDuVbcxtv9Ce2W9eMm4KXLdvdbjv')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2pkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '16j7Dqk3Z9DdTdBtHcCVLaNQy9MTgywUUo')
|
||||
|
@ -259,7 +264,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'xprv9z8izheguGnLopSqkY7GcGFrP2Gu6rzBvvHo6uB9B8DWJhsows6WDZAsbBTaP3ncP2AVbTQphyEQkahrB9s1L7ihZtfz5WGQPMbXwsUtSik')
|
||||
self.assertEqual(ks.xpub, 'xpub6D85QDBajeLe2JXJrZeGyQCaw47PWKi3J9DPuHakjTkVBWCxVQQkmMVMSSfnw39tj9FntbozpRtb1AJ8ubjeVSBhyK4M5mzdvsXZzKPwodT')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2pkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '1F88g2naBMhDB7pYFttPWGQgryba3hPevM')
|
||||
|
@ -278,7 +283,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'yprvAJEYHeNEPcyBoQYM7sGCxDiNCTX65u4ANgZuSGTrKN5YCC9MP84SBayrgaMyZV7zvkHrr3HVPTK853s2SPk4EttPazBZBmz6QfDkXeE8Zr7')
|
||||
self.assertEqual(ks.xpub, 'ypub6XDth9u8DzXV1tcpDtoDKMf6kVMaVMn1juVWEesTshcX4zUVvfNgjPJLXrD9N7AdTLnbHFL64KmBn3SNaTe69iZYbYCqLCCNPZKbLz9niQ4')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wpkh-p2sh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '35ohQTdNykjkF1Mn9nAVEFjupyAtsPAK1W')
|
||||
|
@ -298,7 +303,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual(ks.xprv, 'zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE')
|
||||
self.assertEqual(ks.xpub, 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs')
|
||||
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wpkh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu')
|
||||
|
@ -321,7 +326,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2)
|
||||
self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2sh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '32ji3QkAgXNz6oFoRfakyD3ys1XXiERQYN')
|
||||
|
@ -344,7 +349,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2)
|
||||
self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wsh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1qvzezdcv6vs5h45ugkavp896e0nde5c5lg5h0fwe2xyfhnpkxq6gq7pnwlc')
|
||||
|
@ -367,7 +372,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2)
|
||||
self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2sh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '3JPTQ2nitVxXBJ1yhMeDwH6q417UifE3bN')
|
||||
|
@ -389,7 +394,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2)
|
||||
self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wsh-p2sh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '35LeC45QgCVeRor1tJD6LiDgPbybBXisns')
|
||||
|
@ -414,42 +419,42 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
self.assertEqual('02bf27f41683d84183e4e930e66d64fc8af5508b4b5bf3c473c505e4dbddaeed80', ks.derive_pubkey(1, 0))
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='standard') # p2pkh
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(ks.xprv, 'xprv9s21ZrQH143K3nyWMZVjzGL4KKAE1zahmhTHuV5pdw4eK3o3igC5QywgQG7UTRe6TGBniPDpPFWzXMeMUFbBj8uYsfXGjyMmF54wdNt8QBm')
|
||||
self.assertEqual(ks.xpub, 'xpub661MyMwAqRbcGH3yTb2kMQGnsLziRTJZ8vNthsVSCGbdBr8CGDWKxnGAFYgyKTzBtwvPPmfVAWJuFmxRXjSbUTg87wDkWQ5GmzpfUcN9t8Z')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '19fWEVaXqgJFFn7JYNr6ouxyjZy3uK7CdK')
|
||||
self.assertEqual(w.get_change_addresses()[0], '1EEX7da31qndYyeKdbM665w1ze5gbkkAZZ')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wpkh-p2sh')
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(ks.xprv, 'yprvABrGsX5C9janu6AdBvHNCMRZVHJfxcaCgoyWgsyi1wSXN9cGyLMe33bpRU54TLJ1ruJbTrpNqusYQeFvBx1CXNb9k1DhKtBFWo8b1sLbXhN')
|
||||
self.assertEqual(ks.xpub, 'ypub6QqdH2c5z7967aF6HwpNZVNJ3K9AN5J442u7VGPKaGyWEwwRWsftaqvJGkeZKNe7Jb3C9FG3dAfT94ZzFRrcGhMizGvB6Jtm3itJsEFhxMC')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '34SAT5gGF5UaBhhSZ8qEuuxYvZ2cm7Zi23')
|
||||
self.assertEqual(w.get_change_addresses()[0], '38unULZaetSGSKvDx7Krukh8zm8NQnxGiA')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wpkh')
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(ks.xprv, 'zprvAWgYBBk7JR8GkPMk2H4zQSX4fFT7uEZhbvVjUGsbPwpQRFRWDzXCf7FxSg2eTEwwGYRQDLQwJaE6HvsUueRDKcGkcLv7unzjnXCEQVWhrF9')
|
||||
self.assertEqual(ks.xpub, 'zpub6jftahH18ngZxsSD8JbzmaToDHHcJhHYy9RLGfHCxHMPJ3kemXqTCuaSHxc9KHJ2iE9ztirc5q212MBYy8Gd4w3KrccbgDiFKSwxFpYKEH6')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1qtuynwzd0d6wptvyqmc6ehkm70zcamxpshyzu5e')
|
||||
self.assertEqual(w.get_change_addresses()[0], 'bc1qjy5zunxh6hjysele86qqywfa437z4xwmleq8wk')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='standard') # p2sh
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config)
|
||||
self.assertEqual(ks.xprv, 'xprv9s21ZrQH143K3nyWMZVjzGL4KKAE1zahmhTHuV5pdw4eK3o3igC5QywgQG7UTRe6TGBniPDpPFWzXMeMUFbBj8uYsfXGjyMmF54wdNt8QBm')
|
||||
self.assertEqual(ks.xpub, 'xpub661MyMwAqRbcGH3yTb2kMQGnsLziRTJZ8vNthsVSCGbdBr8CGDWKxnGAFYgyKTzBtwvPPmfVAWJuFmxRXjSbUTg87wDkWQ5GmzpfUcN9t8Z')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '3F4nm8Vunb7mxVvqhUP238PYge2hpU5qYv')
|
||||
self.assertEqual(w.get_change_addresses()[0], '3N8jvKGmxzVHENn6B4zTdZt3N9bmRKjj96')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wsh-p2sh')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config)
|
||||
self.assertEqual(ks.xprv, 'YprvANkMzkodih9AKfL18akM2RmND5LwAyFo15dBc9FFPiGvzLBBjjjv8ATkEB2Y1mWv6NNaLSpVj8G3XosgVBA9frhpaUL6jHeFQXQTbqVPcv2')
|
||||
self.assertEqual(ks.xpub, 'Ypub6bjiQGLXZ4hTY9QUEcHMPZi6m7BRaRyeNJYnQXerx3ous8WLHH4AfxnE5Tc2sos1Y47B1qGAWP3xGEBkYf1ZRBUPpk2aViMkwTABT6qoiBb')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '3L1BxLLASGKE3DR1ruraWm3hZshGCKqcJx')
|
||||
self.assertEqual(w.get_change_addresses()[0], '3NDGcbZVXTpaQWRhiuVPpXsNt4g2JiCX4E')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wsh')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config)
|
||||
self.assertEqual(ks.xprv, 'ZprvAhadJRUYsNgeAxX7xwXyEWrsP3VP7bFHvC9QPY98miep3RzQzPuUkE7tFNz81gAqW1VP5vR4BncbR6VFCsaAU6PRSp2XKCTjgFU6zRpk6Xp')
|
||||
self.assertEqual(ks.xpub, 'Zpub6vZyhw1ShkEwPSbb4y4ybeobw5KsX3y9HR51BvYkL4BnvEKZXwDjJ2SN6fZcsiWvwhDymJriy3QW9WoKGMRaDR9zh5j15dBFDBDpqjK1ekQ')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'bc1q84x0yrztvcjg88qef4d6978zccxulcmc9y88xcg4ghjdau999x7q7zv2qe')
|
||||
|
@ -458,6 +463,10 @@ class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase):
|
|||
|
||||
class TestWalletKeystoreAddressIntegrityForTestnet(TestCaseForTestnet):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_bip39_multisig_seed_p2sh_segwit_testnet(self, mock_write):
|
||||
# bip39 seed: finish seminar arrange erosion sunny coil insane together pretty lunch lunch rose
|
||||
|
@ -473,7 +482,7 @@ class TestWalletKeystoreAddressIntegrityForTestnet(TestCaseForTestnet):
|
|||
WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2)
|
||||
self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore))
|
||||
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config)
|
||||
self.assertEqual(w.txin_type, 'p2wsh-p2sh')
|
||||
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '2MzsfTfTGomPRne6TkctMmoDj6LwmVkDrMt')
|
||||
|
@ -498,42 +507,42 @@ class TestWalletKeystoreAddressIntegrityForTestnet(TestCaseForTestnet):
|
|||
self.assertEqual('02bf27f41683d84183e4e930e66d64fc8af5508b4b5bf3c473c505e4dbddaeed80', ks.derive_pubkey(1, 0))
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='standard') # p2pkh
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(ks.xprv, 'tprv8ZgxMBicQKsPecD328MF9ux3dSaSFWci7FNQmuWH7uZ86eY8i3XpvjK8KSH8To2QphiZiUqaYc6nzDC6bTw8YCB9QJjaQL5pAApN4z7vh2B')
|
||||
self.assertEqual(ks.xpub, 'tpubD6NzVbkrYhZ4Y5Epun1qZKcACU6NQqocgYyC4RYaYBMWw8nuLSMR7DvzVamkqxwRgrTJ1MBMhc8wwxT2vbHqMu8RBXy4BvjWMxR5EdZroxE')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'mpBTXYfWehjW2tavFwpUdqBJbZZkup13k2')
|
||||
self.assertEqual(w.get_change_addresses()[0], 'mtkUQgf1psDtL67wMAKTv19LrdgPWy6GDQ')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wpkh-p2sh')
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(ks.xprv, 'uprv8tXDerPXZ1QsVuQ9rV8sN13YoQitC8cD2MtdZJQAVuw19kMMxhhPYnyGLeEiThgLELqNTxS91GTLsVofKAM9LRrkGeRzzEuJRtt1Tcostr7')
|
||||
self.assertEqual(ks.xpub, 'upub57Wa4MvRPNyAiPUcxWfsj8zHMSZNbbL4PapEMgon4FTz2YgWWF1e6bHkBvpDKk2Rg2Zy9LsonXFFbv7jNeCZ5kdKWv8UkfcoxpdjJrZuBX6')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '2MuzNWpcHrXyvPVKzEGT7Xrwp8uEnXXjWnK')
|
||||
self.assertEqual(w.get_change_addresses()[0], '2MzTzY5VcGLwce7YmdEwjXhgQD7LYEKLJTm')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wpkh')
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config)
|
||||
self.assertEqual(ks.xprv, 'vprv9DMUxX4ShgxMMCbGgqvVa693yNsL8kbhwUQrLhJ3svJtCrAbDMrxArdQMrCJTcLFdyxBDS2hTvotknRE2rmA8fYM8z8Ra9inhcwerEsG6Ev')
|
||||
self.assertEqual(ks.xpub, 'vpub5SLqN2bLY4WeZgfjnsTVwE5nXQhpYDKZJhLT95hfSFqs5eVjkuBCiewtD8moKegM5fgmtpUNFBboVCjJ6LcZszJvPFpuLaSJEYhNhUAnrCS')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'tb1qtuynwzd0d6wptvyqmc6ehkm70zcamxpsaze002')
|
||||
self.assertEqual(w.get_change_addresses()[0], 'tb1qjy5zunxh6hjysele86qqywfa437z4xwm4lm549')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='standard') # p2sh
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config)
|
||||
self.assertEqual(ks.xprv, 'tprv8ZgxMBicQKsPecD328MF9ux3dSaSFWci7FNQmuWH7uZ86eY8i3XpvjK8KSH8To2QphiZiUqaYc6nzDC6bTw8YCB9QJjaQL5pAApN4z7vh2B')
|
||||
self.assertEqual(ks.xpub, 'tpubD6NzVbkrYhZ4Y5Epun1qZKcACU6NQqocgYyC4RYaYBMWw8nuLSMR7DvzVamkqxwRgrTJ1MBMhc8wwxT2vbHqMu8RBXy4BvjWMxR5EdZroxE')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '2N6czpsRwQ3d8AHZPNbztf5NotzEsaZmVQ8')
|
||||
self.assertEqual(w.get_change_addresses()[0], '2NDgwz4CoaSzdSAQdrCcLFWsJaVowCNgiPA')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wsh-p2sh')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config)
|
||||
self.assertEqual(ks.xprv, 'Uprv95RJn67y7xyEvUZXo9brC5PMXCm9QVHoLdYJUZfhsgmQmvvGj75fduqC9MCC28uETouMLYSFtUqqzfRRcPW6UuyR77YQPeNJKd9t3XutF8b')
|
||||
self.assertEqual(ks.xpub, 'Upub5JQfBberxLXY8xdzuB8rZDL65Ebdox1ehrTuGx5KS2JPejFRGePvBi9fzdmgtBFKuVdx1vsvfjdkj5jVfsMWEEjzMPEtA55orYubtrCZmRr')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], '2NBZQ25GC3ipaF13ZY3UT8i2xnDuS17pJqx')
|
||||
self.assertEqual(w.get_change_addresses()[0], '2NDmUgLVX8vKvcJ4FQ37GSUre6QtBzKkb6k')
|
||||
|
||||
ks = create_keystore_from_bip32seed(xtype='p2wsh')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1')
|
||||
w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config)
|
||||
self.assertEqual(ks.xprv, 'Vprv16YtLrHXxePM6noKqtFtMtmUgBE9bEpF3fPLmpvuPksssLostujtdHBwqhEeVuzESz22UY8hyPx9ed684SQpCmUKSVhpxPFbvVNY7qnviNR')
|
||||
self.assertEqual(ks.xpub, 'Vpub5dEvVGKn7251zFq7jXvUmJRbFCk5ka19cxz84LyCp2gGhq4eXJZUomop1qjGt5uFK8kkmQUV8PzJcNM4PZmX2URbDiwJjyuJ8GyFHRrEmmG')
|
||||
self.assertEqual(w.get_receiving_addresses()[0], 'tb1q84x0yrztvcjg88qef4d6978zccxulcmc9y88xcg4ghjdau999x7qf2696k')
|
||||
|
@ -542,20 +551,13 @@ class TestWalletKeystoreAddressIntegrityForTestnet(TestCaseForTestnet):
|
|||
|
||||
class TestWalletSending(TestCaseForTestnet):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.electrum_path = tempfile.mkdtemp()
|
||||
cls.config = SimpleConfig({'electrum_path': cls.electrum_path})
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
shutil.rmtree(cls.electrum_path)
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
def create_standard_wallet_from_seed(self, seed_words):
|
||||
ks = keystore.from_seed(seed_words, '', False)
|
||||
return WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=2)
|
||||
return WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=2, config=self.config)
|
||||
|
||||
@needs_test_with_all_ecc_implementations
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
|
@ -623,7 +625,8 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'),
|
||||
keystore.from_xpub('tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet1b = WalletIntegrityHelper.create_multisig_wallet(
|
||||
[
|
||||
|
@ -631,7 +634,8 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'),
|
||||
keystore.from_xpub('tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
# ^ third seed: ghost into match ivory badge robot record tackle radar elbow traffic loud
|
||||
wallet2 = self.create_standard_wallet_from_seed('powerful random nobody notice nothing important anyway look away hidden message over')
|
||||
|
@ -699,7 +703,8 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'),
|
||||
keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet1b = WalletIntegrityHelper.create_multisig_wallet(
|
||||
[
|
||||
|
@ -707,7 +712,8 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'),
|
||||
keystore.from_xpub('Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
# ^ third seed: hedgehog sunset update estate number jungle amount piano friend donate upper wool
|
||||
wallet2a = WalletIntegrityHelper.create_multisig_wallet(
|
||||
|
@ -716,7 +722,8 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_xprv('Uprv9CvELvByqm8k2dpecJVjgLMX1z5DufEjY4fBC5YvdGF5WjGCa7GVJJ2fYni1tyuF7Hw83E6W2ZBjAhaFLZv2ri3rEsubkCd5avg4EHKoDBN'),
|
||||
keystore.from_xpub('Upub5Qb8ik4Cnu8g97KLXKgVXHqY6tH8emQvqtBncjSKsyfTZuorPtTZgX7ovKKZHuuVGBVd1MTTBkWez1XXt2weN1sWBz6SfgRPQYEkNgz81QF')
|
||||
],
|
||||
'2of2', gap_limit=2
|
||||
'2of2', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet2b = WalletIntegrityHelper.create_multisig_wallet(
|
||||
[
|
||||
|
@ -724,7 +731,8 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_xprv('Uprv9BbnKEXJxXaNvdEsRJ9VA9toYrSeFJh5UfGBpM2iKe8Uh7UhrM9K8ioL53s8gvCoGfirHHaqpABDAE7VUNw8LNU1DMJKVoWyeNKu9XcDC19'),
|
||||
keystore.from_xpub('Upub5RuakRisg8h3F7u7iL2k3UJFa1uiK7xauHamzTxYBbn4PXbM7eajr6M9Q2VCr6cVGhfhqWQqxnABvtSATuVM1xzxk4nA189jJwzaMn1QX7V')
|
||||
],
|
||||
'2of2', gap_limit=2
|
||||
'2of2', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
|
||||
# bootstrap wallet1
|
||||
|
@ -798,13 +806,15 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
keystore.from_seed('phone guilt ancient scan defy gasp off rotate approve ill word exchange', '', True),
|
||||
keystore.from_xpub('tpubD6NzVbkrYhZ4YPZ3ntVjqSCxiUUv2jikrUBU73Q3iJ7Y8iR41oYf991L5fanv7ciHjbjokdK2bjYqg1BzEUDxucU9qM5WRdBiY738wmgLP4')
|
||||
],
|
||||
'1of2', gap_limit=2
|
||||
'1of2', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
# ^ second seed: kingdom now gift initial age right velvet exotic harbor enforce kingdom kick
|
||||
wallet2 = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: uniform tank success logic lesson awesome stove elegant regular desert drip device, der: m/49'/1'/0'
|
||||
keystore.from_xprv('uprv91HGbrNZTK4x8u22nbdYGzEuWPxjaHMREUi7CNhY64KsG5ZGnVM99uCa16EMSfrnaPTFxjbRdBZ2WiBkokoM8anzAy3Vpc52o88WPkitnxi'),
|
||||
gap_limit=2
|
||||
gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
|
||||
# bootstrap wallet1
|
||||
|
@ -1306,27 +1316,22 @@ class TestWalletSending(TestCaseForTestnet):
|
|||
|
||||
class TestWalletOfflineSigning(TestCaseForTestnet):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.electrum_path = tempfile.mkdtemp()
|
||||
cls.config = SimpleConfig({'electrum_path': cls.electrum_path})
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
shutil.rmtree(cls.electrum_path)
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
@needs_test_with_all_ecc_implementations
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_sending_offline_old_electrum_seed_online_mpk(self, mock_write):
|
||||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
keystore.from_seed('alone body father children lead goodbye phone twist exist grass kick join', '', False),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_standard_wallet(
|
||||
keystore.from_master_key('cd805ed20aec61c7a8b409c121c6ba60a9221f46d20edbc2be83ebd91460e97937cd7d782e77c1cb08364c6bc1c98bc040fdad53f22f29f7d3a85c8e51f9c875'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1365,11 +1370,13 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: "qwe", der: m/44'/1'/0'
|
||||
keystore.from_xprv('tprv8gfKwjuAaqtHgqxMh1tosAQ28XvBMkcY5NeFRA3pZMpz6MR4H4YZ3MJM4fvNPnRKeXR1Td2vQGgjorNXfo94WvT5CYDsPAqjHxSn436G1Eu'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_standard_wallet(
|
||||
keystore.from_xpub('tpubDDMN69wQjDZxaJz9afZQGa48hZS7X5oSegF2hg67yddNvqfpuTN9DqvDEp7YyVf7AzXnqBqHdLhzTAStHvsoMDDb8WoJQzNrcHgDJHVYgQF'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1406,11 +1413,13 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: "qwe", der: m/49'/1'/0'
|
||||
keystore.from_xprv('uprv8zHHrMQMQ26utWwNJ5MK2SXpB9hbmy7pbPaneii69xT8cZTyFpxQFxkknGWKP8dxBTZhzy7yP6cCnLrRCQjzJDk3G61SjZpxhFQuB2NR8a5'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_standard_wallet(
|
||||
keystore.from_xpub('upub5DGeFrwFEPfD711qQ6tKPaUYjBY6BRqfxcWPT77hiHz7VMo7oNGeom5EdXoKXEazePyoN3ueJMqHBfp3MwmsaD8k9dFHoa8KGeVXev7Pbg2'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1448,11 +1457,13 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: "qwe", der: m/84'/1'/0'
|
||||
keystore.from_xprv('vprv9K9hbuA23Bidgj1KRSHUZMa59jJLeZBpXPVn4RP7sBLArNhZxJjw4AX7aQmVTErDt4YFC11ptMLjbwxgrsH8GLQ1cx77KggWeVPeDBjr9xM'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_standard_wallet(
|
||||
keystore.from_xpub('vpub5Y941QgusZGvuD5nXTpUvVWohm8q41uftcRNronjRWs9jB2iVr4BbxqbRfAoQjWHgJtDCQEXChgfsPbEuBnidtkFztZSD3zDKTrtwXa2LCa'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1487,9 +1498,9 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
@needs_test_with_all_ecc_implementations
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_sending_offline_wif_online_addr_p2pkh(self, mock_write): # compressed pubkey
|
||||
wallet_offline = WalletIntegrityHelper.create_imported_wallet(privkeys=True)
|
||||
wallet_offline = WalletIntegrityHelper.create_imported_wallet(privkeys=True, config=self.config)
|
||||
wallet_offline.import_private_key('p2pkh:cQDxbmQfwRV3vP1mdnVHq37nJekHLsuD3wdSQseBRA2ct4MFk5Pq', password=None)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('mg2jk6S5WGDhUPA8mLSxDLWpUoQnX1zzoG')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1522,9 +1533,9 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
@needs_test_with_all_ecc_implementations
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_sending_offline_wif_online_addr_p2wpkh_p2sh(self, mock_write):
|
||||
wallet_offline = WalletIntegrityHelper.create_imported_wallet(privkeys=True)
|
||||
wallet_offline = WalletIntegrityHelper.create_imported_wallet(privkeys=True, config=self.config)
|
||||
wallet_offline.import_private_key('p2wpkh-p2sh:cU9hVzhpvfn91u2zTVn8uqF2ymS7ucYH8V5TmsTDmuyMHgRk9WsJ', password=None)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('2NA2JbUVK7HGWUCK5RXSVNHrkgUYF8d9zV8')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1557,9 +1568,9 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
@needs_test_with_all_ecc_implementations
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_sending_offline_wif_online_addr_p2wpkh(self, mock_write):
|
||||
wallet_offline = WalletIntegrityHelper.create_imported_wallet(privkeys=True)
|
||||
wallet_offline = WalletIntegrityHelper.create_imported_wallet(privkeys=True, config=self.config)
|
||||
wallet_offline.import_private_key('p2wpkh:cPuQzcNEgbeYZ5at9VdGkCwkPA9r34gvEVJjuoz384rTfYpahfe7', password=None)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('tb1qm2eh4787lwanrzr6pf0ekf5c7jnmghm2y9k529')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1595,9 +1606,10 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: "qwe", der: m/44'/1'/0'
|
||||
keystore.from_xprv('tprv8gfKwjuAaqtHgqxMh1tosAQ28XvBMkcY5NeFRA3pZMpz6MR4H4YZ3MJM4fvNPnRKeXR1Td2vQGgjorNXfo94WvT5CYDsPAqjHxSn436G1Eu'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('mg2jk6S5WGDhUPA8mLSxDLWpUoQnX1zzoG')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1633,9 +1645,10 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: "qwe", der: m/49'/1'/0'
|
||||
keystore.from_xprv('uprv8zHHrMQMQ26utWwNJ5MK2SXpB9hbmy7pbPaneii69xT8cZTyFpxQFxkknGWKP8dxBTZhzy7yP6cCnLrRCQjzJDk3G61SjZpxhFQuB2NR8a5'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('2NA2JbUVK7HGWUCK5RXSVNHrkgUYF8d9zV8')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1671,9 +1684,10 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
wallet_offline = WalletIntegrityHelper.create_standard_wallet(
|
||||
# bip39: "qwe", der: m/84'/1'/0'
|
||||
keystore.from_xprv('vprv9K9hbuA23Bidgj1KRSHUZMa59jJLeZBpXPVn4RP7sBLArNhZxJjw4AX7aQmVTErDt4YFC11ptMLjbwxgrsH8GLQ1cx77KggWeVPeDBjr9xM'),
|
||||
gap_limit=4
|
||||
gap_limit=4,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('tb1qm2eh4787lwanrzr6pf0ekf5c7jnmghm2y9k529')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1713,7 +1727,8 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'),
|
||||
keystore.from_xpub('tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet_offline2 = WalletIntegrityHelper.create_multisig_wallet(
|
||||
[
|
||||
|
@ -1721,9 +1736,10 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'),
|
||||
keystore.from_xpub('tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('2N4z38eTKcWTZnfugCCfRyXtXWMLnn8HDfw')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1771,7 +1787,8 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
keystore.from_xprv('Uprv9CvELvByqm8k2dpecJVjgLMX1z5DufEjY4fBC5YvdGF5WjGCa7GVJJ2fYni1tyuF7Hw83E6W2ZBjAhaFLZv2ri3rEsubkCd5avg4EHKoDBN'),
|
||||
keystore.from_xpub('Upub5Qb8ik4Cnu8g97KLXKgVXHqY6tH8emQvqtBncjSKsyfTZuorPtTZgX7ovKKZHuuVGBVd1MTTBkWez1XXt2weN1sWBz6SfgRPQYEkNgz81QF')
|
||||
],
|
||||
'2of2', gap_limit=2
|
||||
'2of2', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet_offline2 = WalletIntegrityHelper.create_multisig_wallet(
|
||||
[
|
||||
|
@ -1779,9 +1796,10 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
keystore.from_xprv('Uprv9BbnKEXJxXaNvdEsRJ9VA9toYrSeFJh5UfGBpM2iKe8Uh7UhrM9K8ioL53s8gvCoGfirHHaqpABDAE7VUNw8LNU1DMJKVoWyeNKu9XcDC19'),
|
||||
keystore.from_xpub('Upub5RuakRisg8h3F7u7iL2k3UJFa1uiK7xauHamzTxYBbn4PXbM7eajr6M9Q2VCr6cVGhfhqWQqxnABvtSATuVM1xzxk4nA189jJwzaMn1QX7V')
|
||||
],
|
||||
'2of2', gap_limit=2
|
||||
'2of2', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('2MsHQRm1pNi6VsmXYRxYMcCTdPu7Xa1RyFe')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1830,7 +1848,8 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'),
|
||||
keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
wallet_offline2 = WalletIntegrityHelper.create_multisig_wallet(
|
||||
[
|
||||
|
@ -1838,10 +1857,11 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
|
|||
keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'),
|
||||
keystore.from_xpub('Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk')
|
||||
],
|
||||
'2of3', gap_limit=2
|
||||
'2of3', gap_limit=2,
|
||||
config=self.config
|
||||
)
|
||||
# ^ third seed: hedgehog sunset update estate number jungle amount piano friend donate upper wool
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False)
|
||||
wallet_online = WalletIntegrityHelper.create_imported_wallet(privkeys=False, config=self.config)
|
||||
wallet_online.import_address('tb1q83p6eqxkuvq4eumcha46crpzg4nj84s9p0hnynkxg8nhvfzqcc7q4erju6')
|
||||
|
||||
# bootstrap wallet_online
|
||||
|
@ -1905,11 +1925,14 @@ class TestWalletHistory_SimpleRandomOrder(TestCaseForTestnet):
|
|||
}
|
||||
txid_list = sorted(list(transactions))
|
||||
|
||||
@classmethod
|
||||
def create_old_wallet(cls):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
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)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=20, config=self.config)
|
||||
# some txns are beyond gap limit:
|
||||
w.create_new_address(for_change=True)
|
||||
return w
|
||||
|
@ -1949,28 +1972,17 @@ class TestWalletHistory_EvilGapLimit(TestCaseForTestnet):
|
|||
"268fce617aaaa4847835c2212b984d7b7741fdab65de22813288341819bc5656": "010000000001014f1bdc64da8056d08f79db7f5348d1de55946e57aa7c8279499c703889b6e0fd0100000000fdffffff0260e316000000000016001445e9879cf7cd5b4a15df7ddcaf5c6dca0e1508bacc242600000000001600141bc12094a4475dcfbf24f9920dafddf9104ca95b02483045022100ae3618912f341fefee11b67e0047c47c88c4fa031561c3fafe993259dd14d846022056fa0a5b5d8a65942fa68bcc2f848fd71fa455ba42bc2d421b67eb49ba62aa4e01210394d8f4f06c2ea9c569eb050c897737a7315e7f2104d9b536b49968cc89a1f11033181400",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.electrum_path = tempfile.mkdtemp()
|
||||
cls.config = SimpleConfig({
|
||||
'electrum_path': cls.electrum_path,
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({
|
||||
'electrum_path': self.electrum_path,
|
||||
'skipmerklecheck': True, # needed for Synchronizer to generate new addresses without SPV
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
shutil.rmtree(cls.electrum_path)
|
||||
# horrible hack. create a new config to ensure custom settings
|
||||
# don't get persisted in the "singleton" config:
|
||||
SimpleConfig({'electrum_path': cls.electrum_path})
|
||||
|
||||
@classmethod
|
||||
def create_wallet(cls):
|
||||
def create_wallet(self):
|
||||
ks = keystore.from_xpub('vpub5Vhmk4dEJKanDTTw6immKXa3thw45u3gbd1rPYjREB6viP13sVTWcH6kvbR2YeLtGjradr6SFLVt9PxWDBSrvw1Dc1nmd3oko3m24CQbfaJ')
|
||||
# seed words: nephew work weather maze pyramid employ check permit garment scene kiwi smooth
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=20)
|
||||
w = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=20, config=self.config)
|
||||
return w
|
||||
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
|
@ -2017,11 +2029,16 @@ class TestWalletHistory_DoubleSpend(TestCaseForTestnet):
|
|||
"2c9aa33d9c8ec649f9bfb84af027a5414b760be5231fe9eca4a95b9eb3f8a017": "020000000001012516fade5b5938336a11815d02787ba1580b3189432aa11b150527f8409084a30100000000fdffffff01d2410f00000000001600147880a7c79744b908a5f6d6235f2eb46c174c84f002483045022100974d27c872f09115e57c6acb674cd4da6d0b26656ad967ddb2678ff409714b9502206d91b49cf778ced6ca9e40b4094fb57b86c86fac09ce46ce53aea4afa68ff311012102254b5b20ed21c3bba75ec2a9ff230257d13a2493f6b7da066d8195dcdd484310788d1700",
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.config = SimpleConfig({'electrum_path': self.electrum_path})
|
||||
|
||||
@mock.patch.object(storage.WalletStorage, '_write')
|
||||
def test_restoring_wallet_without_manual_delete(self, mock_write):
|
||||
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)['wallet']
|
||||
gap_limit=5,
|
||||
config=self.config)['wallet']
|
||||
for txid in self.transactions:
|
||||
tx = Transaction(self.transactions[txid])
|
||||
w.add_transaction(tx.txid(), tx)
|
||||
|
@ -2034,7 +2051,8 @@ class TestWalletHistory_DoubleSpend(TestCaseForTestnet):
|
|||
def test_restoring_wallet_with_manual_delete(self, mock_write):
|
||||
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)['wallet']
|
||||
gap_limit=5,
|
||||
config=self.config)['wallet']
|
||||
# txn A is an external incoming txn funding the wallet
|
||||
txA = Transaction(self.transactions["a3849040f82705151ba12a4389310b58a17b78025d81116a3338595bdefa1625"])
|
||||
w.add_transaction(txA.txid(), txA)
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import unittest
|
||||
|
||||
from electrum.x509 import X509
|
||||
class TestX509(unittest.TestCase):
|
||||
|
||||
from . import ElectrumTestCase
|
||||
|
||||
|
||||
class TestX509(ElectrumTestCase):
|
||||
def test_generalizedtime(self):
|
||||
full = X509(b'0\x82\x05F0\x82\x03.\x02\t\x00\xfeV\xd6\xb5?\xb1j\xe40\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x000d1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\x08\x0c\nCalifornia1!0\x1f\x06\x03U\x04\n\x0c\x18Internet Widgits Pty Ltd1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14testnet.qtornado.com0 \x17\r180206010225Z\x18\x0f21180113010225Z0d1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\x08\x0c\nCalifornia1!0\x1f\x06\x03U\x04\n\x0c\x18Internet Widgits Pty Ltd1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14testnet.qtornado.com0\x82\x02"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\xc2B\xe0\xa8\xd9$M\xbc)Wx\x0cv\x00\xc0\xfa2Ew:\xce\xa7\xcb\xc8\r?\xea\xc5R(\xc7\xc3Y\xe7zq=\xcd\x8d\xe3\x86\x9ecSI\xc7\x84\xf2~\x91\xd4\x19\xc2;\x97\xe81e\xf2\xeb\xf1\xadw\xa3p\x88A*-\r\xb6Yt\x98R\xe8\x8a\xf9\xb5>"F\xac\x19%\xc8~\x1d\xac\x93A\xffk\xce\xdb\xfc9\x05\xa0\xad\xf9V\x0f0\xa2b\xd0@\xe4\xf1\xb1\xe8\xb1\x10[&\xa1\xff\x13\xcfQ\xb7\x805\xef\xe7tL\xe5|\x08W\x8c\xd72\x9d\'\xeb\x92)3N\x01M\x06\xa9\xdc\xe4\'\x13\x90x\xd8\x830\x97\xa8\xcc2d \xfa\x91\x04\xd0\x1b\xe7\xaa t\x87\xba]\xb5w\x05(\xba\x07\xc2X$~?L\xc5\x03\xb2\xdeQ\xf3\xf3\xdab\xd9\x92\xd9\x86^:\x93\xc9\x86~\xd1\x94\xd4\x80\x9c\xff0\xc6m\xf4\xf0\xd6\x18\x96l\x1d\x0c\xe8\x15 \x8c\x89\xcb\xa4*\xd9\xefg\x844\x81\xb3\xce\xa1\x8a|\xf9h\xc3\xe1!\xfeZ`\xb71\x97Kj\x0b"\xd3\x98T\r\xd9\xbb<r\x0c\xd5Q\xd0L\x02\xcb\x19\x19\xd6\xdf$\xcej\xa8l\xbd\x81\x803\x95\x0e\x907&\x81J\x88\xaf\xa23\xb4q\x96\x08\xa9]}\xb8Rs\x89{\x04\x88/\xc1m\x8c\xe8\\X\x95 \x1cj\xf2(t\xd7\xef\x10-r\xb6\x17L\xce_\x1bf\xc0c\x18\x83\x99\xdf\xd5\xad\x88\xcd \xae\x07 \xed\xb6\xfc[\x9a/f\x92\xce^\x9c\xd9\x064\xb4\xcc\x1d,d\x99\xee\x9a4\xbe\xde0\x92\x8f/keq\x94\x9frf1\xda\xadM_\x11C\x19\x01\xf0\xe0I\x84W\xf9\xaa\xd3\x12ex\x89"\xbfQ\x1f\xbdU\xa0\x92\xa3\x9d\xdb?\x86\x82\x0b\x1e\xe0\x8aSq\xce%\xea4\xfb\x82\x92\x0f\xcf\xaa\xe2\r\xedd\xba\xff\x85\xa2+\xb0x9\xba\'\xd3\xf5\xd6\xfa\xb43\x0b\xd4\xf4\xca\xa5\xb1\xe4[\xe7\xf7\xc3\xd3\xdd\x85)\xac5E\x17\xae\x03fCC(\x06\x1cU\xedM\x90r\xe87\x8d}\xf1i\xfdO\x83\x05\x83\x83y\xd9f,\xe1\xba\xf0\\y\x8d\x08`\xb1\x02\x03\x01\x00\x010\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x02\x01\x00,.\x12jC3\x9fdF\x15\x16\xea*1\x0b[\xfa-\xcf\x80\x17\xf0\xfa\xf4\x96C\xff\xf9\xe9\xa2N\xda\xf1&6\x9ecV~\xea[\x07\xc1R\x03\x95\xd4\x84B\xe2r\x92\xad<mp\xf1\xcb\xb3\x8b\xbf \x08\x12\x1e6\xe3\xad\xbd1\x81\xbe\xaex\x002\xb6\xf9\xa0\xf6\xb7E^"\r\xa0w\x08\x14\xe7\x84\x03q2\x9c\xac\xce>\xc6\x0b\x81\x81k\x0e\xd01\x16\x91\xe4A\x8c\x1a\xe9W\xd4=<\xd4m_\xd4m\xa4H\x14\xc0\xae\x12\xab\x808\xf1\xf9_\xbb\xfb\xd0U\x0e\\\xd3.?\xa36\xe1hstU"\x17P\xcb>\x83\x9c\xaa\x9b\xb7\xe5\xb4\xb5W\xdc\xc1\xee\x91K\x12\xc2\xe1U\xaf\xf7I`\x83\x91\x0c\xc0\xcb\x15\x13!V\xa9\xc1\xca\x1b\x80\xff\xd8\x1f\xd8_+\x83\xcd\xcb%\xd6\xb7\xdc\x8a2\xa8Q\x1f\xbb.\xdf\x05\xb7hD\xab\xea\xe9\xfb.\xdd\x93\xd1\xf0\xb8r\xb9t.\xab\xf6]\xac\xc9U9\x87\x9e\xe36 \x87\xe7eo\x98\xac\xf4\x87\x8e\xf4\xa86\xd3\xcapy\xee\xa0]\xdbA\xb9\x00\xe9_R\xc8\xf7\xca\x13\xc6\xb1Z|c\xe8v\xa24\xac?k\xf1\xc4\x97\x18\x07\xbaU\xc9\xf5? \x95\x8f\x11\xa7\xc9\x8eY\x9c\xdfnx?\x88\xba\x90\xef\x94WU\xb5\xcf\x0b"\xe8\xfe\xa6.\x0cr-\xaf3\x8a\xe6v\xf9\xb91\x87\x91\xc6\xb1\xe9\xb9UP\xf5\x14\xb7\x99\x80\xc0\xc5}\x9a~\x7f\x06\x1e\xb8\x05\xd5\xa2LXO\\73i\x82\xcd\xc6#\xb7\xa4q\xd7\xd4y\xb1d\xaf\xa8\t\x9e1K\xd94\xaf7\x08\x8c);\xd2\xed\x91\xc6\xed\x83\x90\r\xef\x85\xf0\xfeJi\x02;\xf0\x0b\x03\xe7\xc1\x84\xd45\xaeP\xc2Lp\x1akb\xcaP\xe9\xfc\xc1\xc8VPQu\x85\x92l\x12\xb99{\x91\xd0\xa6d\n\xde\xf85\x93e\xfa\\\xf9cKx8\x84"s\xb8\xe52~\x97\x05\xc3\xf6\x1c\xca\x0b\xda\x8b\x90\xfeu5,\x94,\x99\xf9\x9a\xf3T\x8dAZ\xc7\xe9\x95-\x98\xf2\xbaL\x89\xc0?\xba1\xb5\\t|RY_\xc6\xabr\xe8')
|
||||
full.check_date()
|
||||
|
|
|
@ -208,10 +208,12 @@ class Abstract_Wallet(AddressSynchronizer):
|
|||
max_change_outputs = 3
|
||||
gap_limit_for_change = 6
|
||||
|
||||
def __init__(self, storage: WalletStorage):
|
||||
def __init__(self, storage: WalletStorage, *, config: SimpleConfig):
|
||||
if not storage.is_ready_to_be_used_by_wallet():
|
||||
raise Exception("storage not ready to be used by Abstract_Wallet")
|
||||
|
||||
self.config = config
|
||||
assert self.config is not None, "config must not be None"
|
||||
self.storage = storage
|
||||
# load addresses needs to be called before constructor for sanity checks
|
||||
self.storage.db.load_addresses(self.wallet_type)
|
||||
|
@ -242,9 +244,6 @@ class Abstract_Wallet(AddressSynchronizer):
|
|||
|
||||
self.contacts = Contacts(self.storage)
|
||||
self._coin_price_cache = {}
|
||||
# TODO config should be passed as a param instead? SimpleConfig should not be a singleton.
|
||||
self.config = SimpleConfig.get_instance()
|
||||
assert self.config is not None, "config must not be None"
|
||||
self.lnworker = LNWallet(self) if self.config.get('lightning') else None
|
||||
|
||||
def stop_threads(self):
|
||||
|
@ -1643,8 +1642,8 @@ class Imported_Wallet(Simple_Wallet):
|
|||
wallet_type = 'imported'
|
||||
txin_type = 'address'
|
||||
|
||||
def __init__(self, storage):
|
||||
Abstract_Wallet.__init__(self, storage)
|
||||
def __init__(self, storage, *, config):
|
||||
Abstract_Wallet.__init__(self, storage, config=config)
|
||||
|
||||
def is_watching_only(self):
|
||||
return self.keystore is None
|
||||
|
@ -1831,8 +1830,8 @@ class Imported_Wallet(Simple_Wallet):
|
|||
|
||||
class Deterministic_Wallet(Abstract_Wallet):
|
||||
|
||||
def __init__(self, storage):
|
||||
Abstract_Wallet.__init__(self, storage)
|
||||
def __init__(self, storage, *, config):
|
||||
Abstract_Wallet.__init__(self, storage, config=config)
|
||||
self.gap_limit = storage.get('gap_limit', 20)
|
||||
# generate addresses now. note that without libsecp this might block
|
||||
# for a few seconds!
|
||||
|
@ -1982,8 +1981,8 @@ class Simple_Deterministic_Wallet(Simple_Wallet, Deterministic_Wallet):
|
|||
|
||||
""" Deterministic Wallet with a single pubkey per address """
|
||||
|
||||
def __init__(self, storage):
|
||||
Deterministic_Wallet.__init__(self, storage)
|
||||
def __init__(self, storage, *, config):
|
||||
Deterministic_Wallet.__init__(self, storage, config=config)
|
||||
|
||||
def get_public_key(self, address):
|
||||
sequence = self.get_address_index(address)
|
||||
|
@ -2030,10 +2029,10 @@ class Multisig_Wallet(Deterministic_Wallet):
|
|||
# generic m of n
|
||||
gap_limit = 20
|
||||
|
||||
def __init__(self, storage):
|
||||
def __init__(self, storage, *, config):
|
||||
self.wallet_type = storage.get('wallet_type')
|
||||
self.m, self.n = multisig_type(self.wallet_type)
|
||||
Deterministic_Wallet.__init__(self, storage)
|
||||
Deterministic_Wallet.__init__(self, storage, config=config)
|
||||
|
||||
def get_pubkeys(self, c, i):
|
||||
return self.derive_pubkeys(c, i)
|
||||
|
@ -2149,10 +2148,10 @@ class Wallet(object):
|
|||
This class is actually a factory that will return a wallet of the correct
|
||||
type when passed a WalletStorage instance."""
|
||||
|
||||
def __new__(self, storage):
|
||||
def __new__(self, storage: WalletStorage, *, config: SimpleConfig):
|
||||
wallet_type = storage.get('wallet_type')
|
||||
WalletClass = Wallet.wallet_class(wallet_type)
|
||||
wallet = WalletClass(storage)
|
||||
wallet = WalletClass(storage, config=config)
|
||||
return wallet
|
||||
|
||||
@staticmethod
|
||||
|
@ -2164,7 +2163,7 @@ class Wallet(object):
|
|||
raise WalletFileException("Unknown wallet type: " + str(wallet_type))
|
||||
|
||||
|
||||
def create_new_wallet(*, path, passphrase=None, password=None,
|
||||
def create_new_wallet(*, path, config: SimpleConfig, passphrase=None, password=None,
|
||||
encrypt_file=True, seed_type=None, gap_limit=None) -> dict:
|
||||
"""Create a new wallet"""
|
||||
storage = WalletStorage(path)
|
||||
|
@ -2177,7 +2176,7 @@ def create_new_wallet(*, path, passphrase=None, password=None,
|
|||
storage.put('wallet_type', 'standard')
|
||||
if gap_limit is not None:
|
||||
storage.put('gap_limit', gap_limit)
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=config)
|
||||
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
|
||||
wallet.synchronize()
|
||||
msg = "Please keep your seed in a safe place; if you lose it, you will not be able to restore your wallet."
|
||||
|
@ -2186,7 +2185,7 @@ def create_new_wallet(*, path, passphrase=None, password=None,
|
|||
return {'seed': seed, 'wallet': wallet, 'msg': msg}
|
||||
|
||||
|
||||
def restore_wallet_from_text(text, *, path,
|
||||
def restore_wallet_from_text(text, *, path, config: SimpleConfig,
|
||||
passphrase=None, password=None, encrypt_file=True,
|
||||
gap_limit=None) -> dict:
|
||||
"""Restore a wallet from text. Text can be a seed phrase, a master
|
||||
|
@ -2198,7 +2197,7 @@ def restore_wallet_from_text(text, *, path,
|
|||
|
||||
text = text.strip()
|
||||
if keystore.is_address_list(text):
|
||||
wallet = Imported_Wallet(storage)
|
||||
wallet = Imported_Wallet(storage, config=config)
|
||||
addresses = text.split()
|
||||
good_inputs, bad_inputs = wallet.import_addresses(addresses, write_to_disk=False)
|
||||
# FIXME tell user about bad_inputs
|
||||
|
@ -2207,7 +2206,7 @@ def restore_wallet_from_text(text, *, path,
|
|||
elif keystore.is_private_key_list(text, allow_spaces_inside_key=False):
|
||||
k = keystore.Imported_KeyStore({})
|
||||
storage.put('keystore', k.dump())
|
||||
wallet = Imported_Wallet(storage)
|
||||
wallet = Imported_Wallet(storage, config=config)
|
||||
keys = keystore.get_private_keys(text, allow_spaces_inside_key=False)
|
||||
good_inputs, bad_inputs = wallet.import_private_keys(keys, None, write_to_disk=False)
|
||||
# FIXME tell user about bad_inputs
|
||||
|
@ -2224,7 +2223,7 @@ def restore_wallet_from_text(text, *, path,
|
|||
storage.put('wallet_type', 'standard')
|
||||
if gap_limit is not None:
|
||||
storage.put('gap_limit', gap_limit)
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=config)
|
||||
|
||||
assert not storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk"
|
||||
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
|
||||
|
|
|
@ -211,7 +211,7 @@ async def run_offline_command(config, config_options, plugins):
|
|||
password = get_password_for_hw_device_encrypted_storage(plugins)
|
||||
config_options['password'] = password
|
||||
storage.decrypt(password)
|
||||
wallet = Wallet(storage)
|
||||
wallet = Wallet(storage, config=config)
|
||||
config_options['wallet'] = wallet
|
||||
else:
|
||||
wallet = None
|
||||
|
|
Loading…
Add table
Reference in a new issue