Browse Source

do not create multiple instances of SimpleConfig (fix #5629). Add config field to wallet

dependabot/pip/contrib/deterministic-build/ecdsa-0.13.3
ThomasV 5 years ago
parent
commit
cefa4762ba
  1. 10
      electrum/commands.py
  2. 10
      electrum/daemon.py
  3. 4
      electrum/gui/kivy/main_window.py
  4. 3
      electrum/gui/kivy/uix/dialogs/tx_dialog.py
  5. 11
      electrum/gui/kivy/uix/screens.py
  6. 2
      electrum/gui/qt/address_list.py
  7. 10
      electrum/gui/qt/main_window.py
  8. 2
      electrum/gui/qt/request_list.py
  9. 4
      electrum/lnpeer.py
  10. 80
      electrum/tests/test_wallet_vertical.py
  11. 65
      electrum/wallet.py

10
electrum/commands.py

@ -541,7 +541,7 @@ class Commands:
fee_estimator = partial(SimpleConfig.estimate_fee_for_feerate, fee_per_kb) fee_estimator = partial(SimpleConfig.estimate_fee_for_feerate, fee_per_kb)
else: else:
fee_estimator = fee fee_estimator = fee
tx = wallet.make_unsigned_transaction(coins, final_outputs, self.config, fee_estimator, change_addr) tx = wallet.make_unsigned_transaction(coins, final_outputs, fee_estimator, change_addr)
if locktime is not None: if locktime is not None:
tx.locktime = locktime tx.locktime = locktime
if rbf is None: if rbf is None:
@ -724,7 +724,7 @@ class Commands:
@command('w') @command('w')
async def listrequests(self, pending=False, expired=False, paid=False, wallet=None): async def listrequests(self, pending=False, expired=False, paid=False, wallet=None):
"""List the payment requests you made.""" """List the payment requests you made."""
out = wallet.get_sorted_requests(self.config) out = wallet.get_sorted_requests()
if pending: if pending:
f = PR_UNPAID f = PR_UNPAID
elif expired: elif expired:
@ -762,7 +762,7 @@ class Commands:
amount = satoshis(amount) amount = satoshis(amount)
expiration = int(expiration) if expiration else None expiration = int(expiration) if expiration else None
req = wallet.make_payment_request(addr, amount, memo, expiration) req = wallet.make_payment_request(addr, amount, memo, expiration)
wallet.add_payment_request(req, self.config) wallet.add_payment_request(req)
out = wallet.get_request(addr) out = wallet.get_request(addr)
return self._format_request(out) return self._format_request(out)
@ -787,13 +787,13 @@ class Commands:
@command('w') @command('w')
async def rmrequest(self, address, wallet=None): async def rmrequest(self, address, wallet=None):
"""Remove a payment request""" """Remove a payment request"""
return wallet.remove_payment_request(address, self.config) return wallet.remove_payment_request(address)
@command('w') @command('w')
async def clearrequests(self, wallet=None): async def clearrequests(self, wallet=None):
"""Remove all payment requests""" """Remove all payment requests"""
for k in list(wallet.receive_requests.keys()): for k in list(wallet.receive_requests.keys()):
wallet.remove_payment_request(k, self.config) wallet.remove_payment_request(k)
@command('n') @command('n')
async def notify(self, address: str, URL: str): async def notify(self, address: str, URL: str):

10
electrum/daemon.py

@ -430,20 +430,16 @@ class Daemon(Logger):
return True return True
async def run_cmdline(self, config_options): async def run_cmdline(self, config_options):
config = SimpleConfig(config_options) cmdname = config_options['cmd']
# FIXME this is ugly...
config.fee_estimates = self.network.config.fee_estimates.copy()
config.mempool_fees = self.network.config.mempool_fees.copy()
cmdname = config.get('cmd')
cmd = known_commands[cmdname] cmd = known_commands[cmdname]
# arguments passed to function # arguments passed to function
args = map(lambda x: config.get(x), cmd.params) args = [config_options.get(x) for x in cmd.params]
# decode json arguments # decode json arguments
args = [json_decode(i) for i in args] args = [json_decode(i) for i in args]
# options # options
kwargs = {} kwargs = {}
for x in cmd.options: for x in cmd.options:
kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)) kwargs[x] = config_options.get(x)
if cmd.requires_wallet: if cmd.requires_wallet:
kwargs['wallet_path'] = config_options.get('wallet_path') kwargs['wallet_path'] = config_options.get('wallet_path')
func = getattr(self.cmd_runner, cmd.name) func = getattr(self.cmd_runner, cmd.name)

4
electrum/gui/kivy/main_window.py

@ -817,7 +817,7 @@ class ElectrumWindow(App):
from electrum.transaction import TxOutput from electrum.transaction import TxOutput
if run_hook('abort_send', self): if run_hook('abort_send', self):
return '' return ''
inputs = self.wallet.get_spendable_coins(None, self.electrum_config) inputs = self.wallet.get_spendable_coins(None)
if not inputs: if not inputs:
return '' return ''
addr = None addr = None
@ -827,7 +827,7 @@ class ElectrumWindow(App):
addr = self.wallet.dummy_address() addr = self.wallet.dummy_address()
outputs = [TxOutput(TYPE_ADDRESS, addr, '!')] outputs = [TxOutput(TYPE_ADDRESS, addr, '!')]
try: try:
tx = self.wallet.make_unsigned_transaction(inputs, outputs, self.electrum_config) tx = self.wallet.make_unsigned_transaction(inputs, outputs)
except NoDynamicFeeEstimates as e: except NoDynamicFeeEstimates as e:
Clock.schedule_once(lambda dt, bound_e=e: self.show_error(str(bound_e))) Clock.schedule_once(lambda dt, bound_e=e: self.show_error(str(bound_e)))
return '' return ''

3
electrum/gui/kivy/uix/dialogs/tx_dialog.py

@ -223,8 +223,7 @@ class TxDialog(Factory.Popup):
return return
try: try:
new_tx = self.wallet.bump_fee(tx=self.tx, new_tx = self.wallet.bump_fee(tx=self.tx,
new_fee_rate=new_fee_rate, new_fee_rate=new_fee_rate)
config=self.app.electrum_config)
except CannotBumpFee as e: except CannotBumpFee as e:
self.app.show_error(str(e)) self.app.show_error(str(e))
return return

11
electrum/gui/kivy/uix/screens.py

@ -360,10 +360,9 @@ class SendScreen(CScreen):
def _do_send_onchain(self, amount, message, outputs, rbf): def _do_send_onchain(self, amount, message, outputs, rbf):
# make unsigned transaction # make unsigned transaction
config = self.app.electrum_config coins = self.app.wallet.get_spendable_coins(None)
coins = self.app.wallet.get_spendable_coins(None, config)
try: try:
tx = self.app.wallet.make_unsigned_transaction(coins, outputs, config, None) tx = self.app.wallet.make_unsigned_transaction(coins, outputs, None)
except NotEnoughFunds: except NotEnoughFunds:
self.app.show_error(_("Not enough funds")) self.app.show_error(_("Not enough funds"))
return return
@ -467,7 +466,7 @@ class ReceiveScreen(CScreen):
return return
self.screen.address = addr self.screen.address = addr
req = self.app.wallet.make_payment_request(addr, amount, message, self.expiry()) req = self.app.wallet.make_payment_request(addr, amount, message, self.expiry())
self.app.wallet.add_payment_request(req, self.app.electrum_config) self.app.wallet.add_payment_request(req)
key = addr key = addr
self.clear() self.clear()
self.update() self.update()
@ -497,7 +496,7 @@ class ReceiveScreen(CScreen):
def update(self): def update(self):
if not self.loaded: if not self.loaded:
return return
_list = self.app.wallet.get_sorted_requests(self.app.electrum_config) _list = self.app.wallet.get_sorted_requests()
requests_container = self.screen.ids.requests_container requests_container = self.screen.ids.requests_container
requests_container.data = [self.get_card(item) for item in _list if item.get('status') != PR_PAID] requests_container.data = [self.get_card(item) for item in _list if item.get('status') != PR_PAID]
@ -512,7 +511,7 @@ class ReceiveScreen(CScreen):
d.open() d.open()
def clear_requests_dialog(self): def clear_requests_dialog(self):
expired = [req for req in self.app.wallet.get_sorted_requests(self.app.electrum_config) if req['status'] == PR_EXPIRED] expired = [req for req in self.app.wallet.get_sorted_requests() if req['status'] == PR_EXPIRED]
if len(expired) == 0: if len(expired) == 0:
return return
def callback(c): def callback(c):

2
electrum/gui/qt/address_list.py

@ -251,7 +251,7 @@ class AddressList(MyTreeView):
else: else:
menu.addAction(_("Unfreeze"), lambda: self.parent.set_frozen_state_of_addresses([addr], False)) menu.addAction(_("Unfreeze"), lambda: self.parent.set_frozen_state_of_addresses([addr], False))
coins = self.wallet.get_spendable_coins(addrs, config=self.config) coins = self.wallet.get_spendable_coins(addrs)
if coins: if coins:
menu.addAction(_("Spend from"), lambda: self.parent.spend_coins(coins)) menu.addAction(_("Spend from"), lambda: self.parent.spend_coins(coins))

10
electrum/gui/qt/main_window.py

@ -1093,7 +1093,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
addr = self.wallet.create_new_address(False) addr = self.wallet.create_new_address(False)
req = self.wallet.make_payment_request(addr, amount, message, expiration) req = self.wallet.make_payment_request(addr, amount, message, expiration)
try: try:
self.wallet.add_payment_request(req, self.config) self.wallet.add_payment_request(req)
except Exception as e: except Exception as e:
self.logger.exception('Error adding payment request') self.logger.exception('Error adding payment request')
self.show_error(_('Error adding payment request') + ':\n' + repr(e)) self.show_error(_('Error adding payment request') + ':\n' + repr(e))
@ -1455,7 +1455,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
is_sweep = bool(self.tx_external_keypairs) is_sweep = bool(self.tx_external_keypairs)
make_tx = lambda fee_est: \ make_tx = lambda fee_est: \
self.wallet.make_unsigned_transaction( self.wallet.make_unsigned_transaction(
coins, outputs, self.config, coins, outputs,
fixed_fee=fee_est, is_sweep=is_sweep) fixed_fee=fee_est, is_sweep=is_sweep)
try: try:
tx = make_tx(fee_estimator) tx = make_tx(fee_estimator)
@ -1696,7 +1696,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
try: try:
is_sweep = bool(self.tx_external_keypairs) is_sweep = bool(self.tx_external_keypairs)
tx = self.wallet.make_unsigned_transaction( tx = self.wallet.make_unsigned_transaction(
coins, outputs, self.config, fixed_fee=fee_estimator, coins, outputs, fixed_fee=fee_estimator,
is_sweep=is_sweep) is_sweep=is_sweep)
except (NotEnoughFunds, NoDynamicFeeEstimates) as e: except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
self.show_message(str(e)) self.show_message(str(e))
@ -2044,7 +2044,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
if self.pay_from: if self.pay_from:
return self.pay_from return self.pay_from
else: else:
return self.wallet.get_spendable_coins(None, self.config) return self.wallet.get_spendable_coins(None)
def spend_coins(self, coins): def spend_coins(self, coins):
self.set_pay_from(coins) self.set_pay_from(coins)
@ -3116,7 +3116,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
is_final = cb.isChecked() is_final = cb.isChecked()
new_fee_rate = feerate_e.get_amount() new_fee_rate = feerate_e.get_amount()
try: try:
new_tx = self.wallet.bump_fee(tx=tx, new_fee_rate=new_fee_rate, config=self.config) new_tx = self.wallet.bump_fee(tx=tx, new_fee_rate=new_fee_rate)
except CannotBumpFee as e: except CannotBumpFee as e:
self.show_error(str(e)) self.show_error(str(e))
return return

2
electrum/gui/qt/request_list.py

@ -114,7 +114,7 @@ class RequestList(MyTreeView):
self.parent.update_receive_address_styling() self.parent.update_receive_address_styling()
self.model().clear() self.model().clear()
self.update_headers(self.__class__.headers) self.update_headers(self.__class__.headers)
for req in self.wallet.get_sorted_requests(self.config): for req in self.wallet.get_sorted_requests():
status = req.get('status') status = req.get('status')
if status == PR_PAID: if status == PR_PAID:
continue continue

4
electrum/lnpeer.py

@ -490,7 +490,7 @@ class Peer(Logger):
wallet = self.lnworker.wallet wallet = self.lnworker.wallet
# dry run creating funding tx to see if we even have enough funds # dry run creating funding tx to see if we even have enough funds
funding_tx_test = wallet.mktx([TxOutput(bitcoin.TYPE_ADDRESS, wallet.dummy_address(), funding_sat)], funding_tx_test = wallet.mktx([TxOutput(bitcoin.TYPE_ADDRESS, wallet.dummy_address(), funding_sat)],
password, self.lnworker.config, nonlocal_only=True) password, nonlocal_only=True)
await asyncio.wait_for(self.initialized.wait(), LN_P2P_NETWORK_TIMEOUT) await asyncio.wait_for(self.initialized.wait(), LN_P2P_NETWORK_TIMEOUT)
feerate = self.lnworker.current_feerate_per_kw() feerate = self.lnworker.current_feerate_per_kw()
local_config = self.make_local_config(funding_sat, push_msat, LOCAL) local_config = self.make_local_config(funding_sat, push_msat, LOCAL)
@ -570,7 +570,7 @@ class Peer(Logger):
redeem_script = funding_output_script(local_config, remote_config) redeem_script = funding_output_script(local_config, remote_config)
funding_address = bitcoin.redeem_script_to_address('p2wsh', redeem_script) funding_address = bitcoin.redeem_script_to_address('p2wsh', redeem_script)
funding_output = TxOutput(bitcoin.TYPE_ADDRESS, funding_address, funding_sat) funding_output = TxOutput(bitcoin.TYPE_ADDRESS, funding_address, funding_sat)
funding_tx = wallet.mktx([funding_output], password, self.lnworker.config, nonlocal_only=True) funding_tx = wallet.mktx([funding_output], password, nonlocal_only=True)
funding_txid = funding_tx.txid() funding_txid = funding_tx.txid()
funding_index = funding_tx.outputs().index(funding_output) funding_index = funding_tx.outputs().index(funding_output)
# remote commitment transaction # remote commitment transaction

80
electrum/tests/test_wallet_vertical.py

@ -572,7 +572,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet1 -> wallet2 # wallet1 -> wallet2
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 250000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 250000)]
tx = wallet1.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet1.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
self.assertTrue(tx.is_complete()) self.assertTrue(tx.is_complete())
self.assertTrue(tx.is_segwit()) self.assertTrue(tx.is_segwit())
@ -592,7 +592,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet2 -> wallet1 # wallet2 -> wallet1
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1.get_receiving_address(), 100000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1.get_receiving_address(), 100000)]
tx = wallet2.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet2.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
self.assertTrue(tx.is_complete()) self.assertTrue(tx.is_complete())
self.assertFalse(tx.is_segwit()) self.assertFalse(tx.is_segwit())
@ -645,7 +645,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet1 -> wallet2 # wallet1 -> wallet2
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 370000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 370000)]
tx = wallet1a.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet1a.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
tx = Transaction(tx.serialize()) # simulates moving partial txn between cosigners tx = Transaction(tx.serialize()) # simulates moving partial txn between cosigners
self.assertFalse(tx.is_complete()) self.assertFalse(tx.is_complete())
wallet1b.sign_transaction(tx, password=None) wallet1b.sign_transaction(tx, password=None)
@ -668,7 +668,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet2 -> wallet1 # wallet2 -> wallet1
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 100000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 100000)]
tx = wallet2.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet2.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
self.assertTrue(tx.is_complete()) self.assertTrue(tx.is_complete())
self.assertFalse(tx.is_segwit()) self.assertFalse(tx.is_segwit())
@ -736,7 +736,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet1 -> wallet2 # wallet1 -> wallet2
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2a.get_receiving_address(), 165000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2a.get_receiving_address(), 165000)]
tx = wallet1a.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet1a.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
txid = tx.txid() txid = tx.txid()
tx = Transaction(tx.serialize()) # simulates moving partial txn between cosigners tx = Transaction(tx.serialize()) # simulates moving partial txn between cosigners
self.assertEqual(txid, tx.txid()) self.assertEqual(txid, tx.txid())
@ -762,7 +762,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet2 -> wallet1 # wallet2 -> wallet1
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 100000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 100000)]
tx = wallet2a.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet2a.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
txid = tx.txid() txid = tx.txid()
tx = Transaction(tx.serialize()) # simulates moving partial txn between cosigners tx = Transaction(tx.serialize()) # simulates moving partial txn between cosigners
self.assertEqual(txid, tx.txid()) self.assertEqual(txid, tx.txid())
@ -816,7 +816,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet1 -> wallet2 # wallet1 -> wallet2
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 1000000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 1000000)]
tx = wallet1a.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet1a.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
self.assertTrue(tx.is_complete()) self.assertTrue(tx.is_complete())
self.assertFalse(tx.is_segwit()) self.assertFalse(tx.is_segwit())
@ -836,7 +836,7 @@ class TestWalletSending(TestCaseForTestnet):
# wallet2 -> wallet1 # wallet2 -> wallet1
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 300000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 300000)]
tx = wallet2.mktx(outputs=outputs, password=None, config=self.config, fee=5000, tx_version=1) tx = wallet2.mktx(outputs=outputs, password=None, fee=5000, tx_version=1)
self.assertTrue(tx.is_complete()) self.assertTrue(tx.is_complete())
self.assertTrue(tx.is_segwit()) self.assertTrue(tx.is_segwit())
@ -885,8 +885,8 @@ class TestWalletSending(TestCaseForTestnet):
# create tx # create tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', 2500000)]
coins = wallet.get_spendable_coins(domain=None, config=self.config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=self.config, fixed_fee=5000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325501 tx.locktime = 1325501
tx.version = 1 tx.version = 1
@ -911,7 +911,7 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual((0, funding_output_value - 2500000 - 5000, 0), wallet.get_balance()) self.assertEqual((0, funding_output_value - 2500000 - 5000, 0), wallet.get_balance())
# bump tx # bump tx
tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0, config=self.config) tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0)
tx.locktime = 1325501 tx.locktime = 1325501
tx.version = 1 tx.version = 1
if simulate_moving_txs: if simulate_moving_txs:
@ -976,8 +976,8 @@ class TestWalletSending(TestCaseForTestnet):
# create tx # create tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', 2500000)]
coins = wallet.get_spendable_coins(domain=None, config=self.config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=self.config, fixed_fee=5000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325499 tx.locktime = 1325499
tx.version = 1 tx.version = 1
@ -1002,7 +1002,7 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual((0, funding_output_value - 2500000 - 5000, 0), wallet.get_balance()) self.assertEqual((0, funding_output_value - 2500000 - 5000, 0), wallet.get_balance())
# bump tx # bump tx
tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0, config=self.config) tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0)
tx.locktime = 1325500 tx.locktime = 1325500
tx.version = 1 tx.version = 1
if simulate_moving_txs: if simulate_moving_txs:
@ -1032,8 +1032,8 @@ class TestWalletSending(TestCaseForTestnet):
# create tx # create tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', '!')] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', '!')]
coins = wallet.get_spendable_coins(domain=None, config=self.config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=self.config, fixed_fee=5000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325499 tx.locktime = 1325499
tx.version = 1 tx.version = 1
@ -1058,7 +1058,7 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual((0, 0, 0), wallet.get_balance()) self.assertEqual((0, 0, 0), wallet.get_balance())
# bump tx # bump tx
tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0, config=self.config) tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0)
tx.locktime = 1325500 tx.locktime = 1325500
tx.version = 1 tx.version = 1
if simulate_moving_txs: if simulate_moving_txs:
@ -1089,8 +1089,8 @@ class TestWalletSending(TestCaseForTestnet):
# create tx # create tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', '!')] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', '!')]
coins = wallet.get_spendable_coins(domain=None, config=self.config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=self.config, fixed_fee=5000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325499 tx.locktime = 1325499
tx.version = 1 tx.version = 1
@ -1123,7 +1123,7 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual((0, 5_000_000, 0), wallet.get_balance()) self.assertEqual((0, 5_000_000, 0), wallet.get_balance())
# bump tx # bump tx
tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0, config=self.config) tx = wallet.bump_fee(tx=Transaction(tx.serialize()), new_fee_rate=70.0)
tx.locktime = 1325500 tx.locktime = 1325500
tx.version = 1 tx.version = 1
if simulate_moving_txs: if simulate_moving_txs:
@ -1144,7 +1144,7 @@ class TestWalletSending(TestCaseForTestnet):
def _rbf_batching(self, *, simulate_moving_txs): def _rbf_batching(self, *, simulate_moving_txs):
wallet = self.create_standard_wallet_from_seed('frost repair depend effort salon ring foam oak cancel receive save usage') wallet = self.create_standard_wallet_from_seed('frost repair depend effort salon ring foam oak cancel receive save usage')
config = SimpleConfig({'electrum_path': self.electrum_path, 'batch_rbf': True}) wallet.config.set_key('batch_rbf', True)
# bootstrap wallet (incoming funding_tx1) # bootstrap wallet (incoming funding_tx1)
funding_tx1 = Transaction('01000000000102acd6459dec7c3c51048eb112630da756f5d4cb4752b8d39aa325407ae0885cba020000001716001455c7f5e0631d8e6f5f05dddb9f676cec48845532fdffffffd146691ef6a207b682b13da5f2388b1f0d2a2022c8cfb8dc27b65434ec9ec8f701000000171600147b3be8a7ceaf15f57d7df2a3d216bc3c259e3225fdffffff02a9875b000000000017a914ea5a99f83e71d1c1dfc5d0370e9755567fe4a141878096980000000000160014d4ca56fcbad98fb4dcafdc573a75d6a6fffb09b702483045022100dde1ba0c9a2862a65791b8d91295a6603207fb79635935a67890506c214dd96d022046c6616642ef5971103c1db07ac014e63fa3b0e15c5729eacdd3e77fcb7d2086012103a72410f185401bb5b10aaa30989c272b554dc6d53bda6da85a76f662723421af024730440220033d0be8f74e782fbcec2b396647c7715d2356076b442423f23552b617062312022063c95cafdc6d52ccf55c8ee0f9ceb0f57afb41ea9076eb74fe633f59c50c6377012103b96a4954d834fbcfb2bbf8cf7de7dc2b28bc3d661c1557d1fd1db1bfc123a94abb391400') funding_tx1 = Transaction('01000000000102acd6459dec7c3c51048eb112630da756f5d4cb4752b8d39aa325407ae0885cba020000001716001455c7f5e0631d8e6f5f05dddb9f676cec48845532fdffffffd146691ef6a207b682b13da5f2388b1f0d2a2022c8cfb8dc27b65434ec9ec8f701000000171600147b3be8a7ceaf15f57d7df2a3d216bc3c259e3225fdffffff02a9875b000000000017a914ea5a99f83e71d1c1dfc5d0370e9755567fe4a141878096980000000000160014d4ca56fcbad98fb4dcafdc573a75d6a6fffb09b702483045022100dde1ba0c9a2862a65791b8d91295a6603207fb79635935a67890506c214dd96d022046c6616642ef5971103c1db07ac014e63fa3b0e15c5729eacdd3e77fcb7d2086012103a72410f185401bb5b10aaa30989c272b554dc6d53bda6da85a76f662723421af024730440220033d0be8f74e782fbcec2b396647c7715d2356076b442423f23552b617062312022063c95cafdc6d52ccf55c8ee0f9ceb0f57afb41ea9076eb74fe633f59c50c6377012103b96a4954d834fbcfb2bbf8cf7de7dc2b28bc3d661c1557d1fd1db1bfc123a94abb391400')
@ -1155,8 +1155,8 @@ class TestWalletSending(TestCaseForTestnet):
# create tx # create tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', 2_500_000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N1VTMMFb91SH9SNRAkT7z8otP5eZEct4KL', 2_500_000)]
coins = wallet.get_spendable_coins(domain=None, config=config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=config, fixed_fee=5000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325499 tx.locktime = 1325499
tx.version = 1 tx.version = 1
@ -1191,8 +1191,8 @@ class TestWalletSending(TestCaseForTestnet):
# create new tx (output should be batched with existing!) # create new tx (output should be batched with existing!)
# no new input will be needed. just a new output, and change decreased. # no new input will be needed. just a new output, and change decreased.
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qy6xmdj96v5dzt3j08hgc05yk3kltqsnmw4r6ry', 2_500_000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qy6xmdj96v5dzt3j08hgc05yk3kltqsnmw4r6ry', 2_500_000)]
coins = wallet.get_spendable_coins(domain=None, config=config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=config, fixed_fee=20000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=20000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325499 tx.locktime = 1325499
tx.version = 1 tx.version = 1
@ -1219,8 +1219,8 @@ class TestWalletSending(TestCaseForTestnet):
# create new tx (output should be batched with existing!) # create new tx (output should be batched with existing!)
# new input will be needed! # new input will be needed!
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2NCVwbmEpvaXKHpXUGJfJr9iB5vtRN3vcut', 6_000_000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2NCVwbmEpvaXKHpXUGJfJr9iB5vtRN3vcut', 6_000_000)]
coins = wallet.get_spendable_coins(domain=None, config=config) coins = wallet.get_spendable_coins(domain=None)
tx = wallet.make_unsigned_transaction(coins, outputs, config=config, fixed_fee=100_000) tx = wallet.make_unsigned_transaction(coins, outputs, fixed_fee=100_000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325499 tx.locktime = 1325499
tx.version = 1 tx.version = 1
@ -1337,7 +1337,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qyw3c0rvn6kk2c688y3dygvckn57525y8qnxt3a', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qyw3c0rvn6kk2c688y3dygvckn57525y8qnxt3a', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1446655 tx.locktime = 1446655
tx.version = 1 tx.version = 1
@ -1380,7 +1380,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qp0mv2sxsyxxfj5gl0332f9uyez93su9cf26757', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qp0mv2sxsyxxfj5gl0332f9uyez93su9cf26757', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1421,7 +1421,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qp0mv2sxsyxxfj5gl0332f9uyez93su9cf26757', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qp0mv2sxsyxxfj5gl0332f9uyez93su9cf26757', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325341 tx.locktime = 1325341
tx.version = 1 tx.version = 1
@ -1463,7 +1463,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qp0mv2sxsyxxfj5gl0332f9uyez93su9cf26757', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1qp0mv2sxsyxxfj5gl0332f9uyez93su9cf26757', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325341 tx.locktime = 1325341
tx.version = 1 tx.version = 1
@ -1500,7 +1500,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1535,7 +1535,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1570,7 +1570,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1608,7 +1608,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1646,7 +1646,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1684,7 +1684,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, 'tb1quk7ahlhr3qmjndy0uvu9y9hxfesrtahtta9ghm', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325340 tx.locktime = 1325340
tx.version = 1 tx.version = 1
@ -1734,7 +1734,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2MuCQQHJNnrXzQzuqfUCfAwAjPqpyEHbgue', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2MuCQQHJNnrXzQzuqfUCfAwAjPqpyEHbgue', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325503 tx.locktime = 1325503
tx.version = 1 tx.version = 1
@ -1792,7 +1792,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N8CtJRwxb2GCaiWWdSHLZHHLoZy53CCyxf', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2N8CtJRwxb2GCaiWWdSHLZHHLoZy53CCyxf', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325504 tx.locktime = 1325504
tx.version = 1 tx.version = 1
@ -1852,7 +1852,7 @@ class TestWalletOfflineSigning(TestCaseForTestnet):
# create unsigned tx # create unsigned tx
outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2MyoZVy8T1t94yLmyKu8DP1SmbWvnxbkwRA', 2500000)] outputs = [TxOutput(bitcoin.TYPE_ADDRESS, '2MyoZVy8T1t94yLmyKu8DP1SmbWvnxbkwRA', 2500000)]
tx = wallet_online.mktx(outputs=outputs, password=None, config=self.config, fee=5000) tx = wallet_online.mktx(outputs=outputs, password=None, fee=5000)
tx.set_rbf(True) tx.set_rbf(True)
tx.locktime = 1325505 tx.locktime = 1325505
tx.version = 1 tx.version = 1

65
electrum/wallet.py

@ -236,7 +236,8 @@ class Abstract_Wallet(AddressSynchronizer):
self.contacts = Contacts(self.storage) self.contacts = Contacts(self.storage)
self._coin_price_cache = {} self._coin_price_cache = {}
self.lnworker = LNWallet(self) if get_config().get('lightning') else None self.config = get_config()
self.lnworker = LNWallet(self) if self.config.get('lightning') else None
def stop_threads(self): def stop_threads(self):
super().stop_threads() super().stop_threads()
@ -408,10 +409,10 @@ class Abstract_Wallet(AddressSynchronizer):
status = _('Unconfirmed') status = _('Unconfirmed')
if fee is None: if fee is None:
fee = self.db.get_tx_fee(tx_hash) fee = self.db.get_tx_fee(tx_hash)
if fee and self.network and self.network.config.has_fee_mempool(): if fee and self.network and self.config.has_fee_mempool():
size = tx.estimated_size() size = tx.estimated_size()
fee_per_byte = fee / size fee_per_byte = fee / size
exp_n = self.network.config.fee_to_depth(fee_per_byte) exp_n = self.config.fee_to_depth(fee_per_byte)
can_bump = is_mine and not tx.is_final() can_bump = is_mine and not tx.is_final()
else: else:
status = _('Local') status = _('Local')
@ -447,8 +448,8 @@ class Abstract_Wallet(AddressSynchronizer):
mempool_depth_bytes=exp_n, mempool_depth_bytes=exp_n,
) )
def get_spendable_coins(self, domain, config, *, nonlocal_only=False): def get_spendable_coins(self, domain, *, nonlocal_only=False):
confirmed_only = config.get('confirmed_only', False) confirmed_only = self.config.get('confirmed_only', False)
utxos = self.get_utxos(domain, utxos = self.get_utxos(domain,
excluded_addresses=self.frozen_addresses, excluded_addresses=self.frozen_addresses,
mature_only=True, mature_only=True,
@ -728,8 +729,8 @@ class Abstract_Wallet(AddressSynchronizer):
fee_per_byte = fee / size fee_per_byte = fee / size
extra.append(format_fee_satoshis(fee_per_byte) + ' sat/b') extra.append(format_fee_satoshis(fee_per_byte) + ' sat/b')
if fee is not None and height in (TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED) \ if fee is not None and height in (TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED) \
and self.network and self.network.config.has_fee_mempool(): and self.config.has_fee_mempool():
exp_n = self.network.config.fee_to_depth(fee_per_byte) exp_n = self.config.fee_to_depth(fee_per_byte)
if exp_n: if exp_n:
extra.append('%.2f MB'%(exp_n/1000000)) extra.append('%.2f MB'%(exp_n/1000000))
if height == TX_HEIGHT_LOCAL: if height == TX_HEIGHT_LOCAL:
@ -810,7 +811,7 @@ class Abstract_Wallet(AddressSynchronizer):
max_change = self.max_change_outputs if self.multiple_change else 1 max_change = self.max_change_outputs if self.multiple_change else 1
return change_addrs[:max_change] return change_addrs[:max_change]
def make_unsigned_transaction(self, coins, outputs, config, fixed_fee=None, def make_unsigned_transaction(self, coins, outputs, fixed_fee=None,
change_addr=None, is_sweep=False): change_addr=None, is_sweep=False):
# check outputs # check outputs
i_max = None i_max = None
@ -823,7 +824,7 @@ class Abstract_Wallet(AddressSynchronizer):
raise Exception("More than one output set to spend max") raise Exception("More than one output set to spend max")
i_max = i i_max = i
if fixed_fee is None and config.fee_per_kb() is None: if fixed_fee is None and self.config.fee_per_kb() is None:
raise NoDynamicFeeEstimates() raise NoDynamicFeeEstimates()
for item in coins: for item in coins:
@ -831,7 +832,7 @@ class Abstract_Wallet(AddressSynchronizer):
# Fee estimator # Fee estimator
if fixed_fee is None: if fixed_fee is None:
fee_estimator = config.estimate_fee fee_estimator = self.config.estimate_fee
elif isinstance(fixed_fee, Number): elif isinstance(fixed_fee, Number):
fee_estimator = lambda size: fixed_fee fee_estimator = lambda size: fixed_fee
elif callable(fixed_fee): elif callable(fixed_fee):
@ -841,10 +842,10 @@ class Abstract_Wallet(AddressSynchronizer):
if i_max is None: if i_max is None:
# Let the coin chooser select the coins to spend # Let the coin chooser select the coins to spend
coin_chooser = coinchooser.get_coin_chooser(config) coin_chooser = coinchooser.get_coin_chooser(self.config)
# If there is an unconfirmed RBF tx, merge with it # If there is an unconfirmed RBF tx, merge with it
base_tx = self.get_unconfirmed_base_tx_for_batching() base_tx = self.get_unconfirmed_base_tx_for_batching()
if config.get('batch_rbf', False) and base_tx: if self.config.get('batch_rbf', False) and base_tx:
# make sure we don't try to spend change from the tx-to-be-replaced: # make sure we don't try to spend change from the tx-to-be-replaced:
coins = [c for c in coins if c['prevout_hash'] != base_tx.txid()] coins = [c for c in coins if c['prevout_hash'] != base_tx.txid()]
is_local = self.get_tx_height(base_tx.txid()).height == TX_HEIGHT_LOCAL is_local = self.get_tx_height(base_tx.txid()).height == TX_HEIGHT_LOCAL
@ -894,10 +895,10 @@ class Abstract_Wallet(AddressSynchronizer):
run_hook('make_unsigned_transaction', self, tx) run_hook('make_unsigned_transaction', self, tx)
return tx return tx
def mktx(self, outputs, password, config, fee=None, change_addr=None, def mktx(self, outputs, password, fee=None, change_addr=None,
domain=None, rbf=False, nonlocal_only=False, *, tx_version=None): domain=None, rbf=False, nonlocal_only=False, *, tx_version=None):
coins = self.get_spendable_coins(domain, config, nonlocal_only=nonlocal_only) coins = self.get_spendable_coins(domain, nonlocal_only=nonlocal_only)
tx = self.make_unsigned_transaction(coins, outputs, config, fee, change_addr) tx = self.make_unsigned_transaction(coins, outputs, fee, change_addr)
tx.set_rbf(rbf) tx.set_rbf(rbf)
if tx_version is not None: if tx_version is not None:
tx.version = tx_version tx.version = tx_version
@ -988,7 +989,7 @@ class Abstract_Wallet(AddressSynchronizer):
max_conf = max(max_conf, tx_age) max_conf = max(max_conf, tx_age)
return max_conf >= req_conf return max_conf >= req_conf
def bump_fee(self, *, tx, new_fee_rate, config) -> Transaction: def bump_fee(self, *, tx, new_fee_rate) -> Transaction:
"""Increase the miner fee of 'tx'. """Increase the miner fee of 'tx'.
'new_fee_rate' is the target min rate in sat/vbyte 'new_fee_rate' is the target min rate in sat/vbyte
""" """
@ -1007,7 +1008,7 @@ class Abstract_Wallet(AddressSynchronizer):
# method 1: keep all inputs, keep all not is_mine outputs, # method 1: keep all inputs, keep all not is_mine outputs,
# allow adding new inputs # allow adding new inputs
tx_new = self._bump_fee_through_coinchooser( tx_new = self._bump_fee_through_coinchooser(
tx=tx, new_fee_rate=new_fee_rate, config=config) tx=tx, new_fee_rate=new_fee_rate)
method_used = 1 method_used = 1
except CannotBumpFee: except CannotBumpFee:
# method 2: keep all inputs, no new inputs are added, # method 2: keep all inputs, no new inputs are added,
@ -1028,7 +1029,7 @@ class Abstract_Wallet(AddressSynchronizer):
tx_new.locktime = get_locktime_for_new_transaction(self.network) tx_new.locktime = get_locktime_for_new_transaction(self.network)
return tx_new return tx_new
def _bump_fee_through_coinchooser(self, *, tx, new_fee_rate, config): def _bump_fee_through_coinchooser(self, *, tx, new_fee_rate):
tx = Transaction(tx.serialize()) tx = Transaction(tx.serialize())
tx.deserialize(force_full_parse=True) # need to parse inputs tx.deserialize(force_full_parse=True) # need to parse inputs
tx.remove_signatures() tx.remove_signatures()
@ -1053,12 +1054,12 @@ class Abstract_Wallet(AddressSynchronizer):
else: else:
fixed_outputs = old_outputs fixed_outputs = old_outputs
coins = self.get_spendable_coins(None, config) coins = self.get_spendable_coins(None)
for item in coins: for item in coins:
self.add_input_info(item) self.add_input_info(item)
def fee_estimator(size): def fee_estimator(size):
return config.estimate_fee_for_feerate(fee_per_kb=new_fee_rate*1000, size=size) return self.config.estimate_fee_for_feerate(fee_per_kb=new_fee_rate*1000, size=size)
coin_chooser = coinchooser.get_coin_chooser(config) coin_chooser = coinchooser.get_coin_chooser(self.config)
try: try:
return coin_chooser.make_tx(coins, old_inputs, fixed_outputs, change_addrs, return coin_chooser.make_tx(coins, old_inputs, fixed_outputs, change_addrs,
fee_estimator, self.dust_threshold()) fee_estimator, self.dust_threshold())
@ -1324,8 +1325,6 @@ class Abstract_Wallet(AddressSynchronizer):
return status, conf return status, conf
def get_request(self, key): def get_request(self, key):
from .simple_config import get_config
config = get_config()
if key in self.receive_requests: if key in self.receive_requests:
req = self.get_payment_request(key) req = self.get_payment_request(key)
elif self.lnworker: elif self.lnworker:
@ -1334,11 +1333,11 @@ class Abstract_Wallet(AddressSynchronizer):
req = None req = None
if not req: if not req:
return return
if config.get('payserver_port'): if self.config.get('payserver_port'):
host = config.get('payserver_host', 'localhost') host = self.config.get('payserver_host', 'localhost')
port = config.get('payserver_port') port = self.config.get('payserver_port')
root = config.get('payserver_root', '/r') root = self.config.get('payserver_root', '/r')
use_ssl = bool(config.get('ssl_keyfile')) use_ssl = bool(self.config.get('ssl_keyfile'))
protocol = 'https' if use_ssl else 'http' protocol = 'https' if use_ssl else 'http'
base = '%s://%s:%d'%(protocol, host, port) base = '%s://%s:%d'%(protocol, host, port)
req['view_url'] = base + root + '/pay?id=' + key req['view_url'] = base + root + '/pay?id=' + key
@ -1371,7 +1370,7 @@ class Abstract_Wallet(AddressSynchronizer):
self.receive_requests[key] = req self.receive_requests[key] = req
self.storage.put('payment_requests', self.receive_requests) self.storage.put('payment_requests', self.receive_requests)
def add_payment_request(self, req, config): def add_payment_request(self, req):
addr = req['address'] addr = req['address']
if not bitcoin.is_address(addr): if not bitcoin.is_address(addr):
raise Exception(_('Invalid Bitcoin address.')) raise Exception(_('Invalid Bitcoin address.'))
@ -1388,7 +1387,7 @@ class Abstract_Wallet(AddressSynchronizer):
def delete_request(self, key): def delete_request(self, key):
""" lightning or on-chain """ """ lightning or on-chain """
if key in self.receive_requests: if key in self.receive_requests:
self.remove_payment_request(key, {}) self.remove_payment_request(key)
elif self.lnworker: elif self.lnworker:
self.lnworker.delete_invoice(key) self.lnworker.delete_invoice(key)
@ -1400,14 +1399,14 @@ class Abstract_Wallet(AddressSynchronizer):
elif self.lnworker: elif self.lnworker:
self.lnworker.delete_invoice(key) self.lnworker.delete_invoice(key)
def remove_payment_request(self, addr, config): def remove_payment_request(self, addr):
if addr not in self.receive_requests: if addr not in self.receive_requests:
return False return False
self.receive_requests.pop(addr) self.receive_requests.pop(addr)
self.storage.put('payment_requests', self.receive_requests) self.storage.put('payment_requests', self.receive_requests)
return True return True
def get_sorted_requests(self, config): def get_sorted_requests(self):
""" sorted by timestamp """ """ sorted by timestamp """
out = [self.get_request(x) for x in self.receive_requests.keys()] out = [self.get_request(x) for x in self.receive_requests.keys()]
if self.lnworker: if self.lnworker:
@ -1692,7 +1691,7 @@ class Imported_Wallet(Simple_Wallet):
self.unverified_tx.pop(tx_hash, None) self.unverified_tx.pop(tx_hash, None)
self.db.remove_transaction(tx_hash) self.db.remove_transaction(tx_hash)
self.set_label(address, None) self.set_label(address, None)
self.remove_payment_request(address, {}) self.remove_payment_request(address)
self.set_frozen_state_of_addresses([address], False) self.set_frozen_state_of_addresses([address], False)
pubkey = self.get_public_key(address) pubkey = self.get_public_key(address)
self.db.remove_imported_address(address) self.db.remove_imported_address(address)

Loading…
Cancel
Save