|
31 | 31 | from electrum.gui.common_qt.util import draw_qr
|
32 | 32 | from electrum.gui.fonts import get_font_id
|
33 | 33 | from electrum.gui.qt.paytoedit import PayToEdit
|
34 |
| -from electrum.bitcoin import COIN, address_to_script, DummyAddress |
| 34 | +from electrum.bitcoin import DummyAddress |
35 | 35 | from electrum.payment_identifier import PaymentIdentifierType
|
36 | 36 | from electrum.plugin import hook, run_hook
|
37 | 37 | from electrum.i18n import _
|
38 |
| -from electrum.transaction import PartialTxInput, PartialTxOutput, TxOutpoint |
39 |
| -from electrum.util import make_dir, bfh |
| 38 | +from electrum.transaction import PartialTxOutput |
| 39 | +from electrum.util import make_dir |
40 | 40 | from electrum.gui.qt.util import ColorScheme, WindowModalDialog, Buttons, HelpLabel
|
41 | 41 | from electrum.gui.qt.main_window import StatusBarButton
|
42 | 42 | from electrum.gui.qt.util import read_QIcon_from_bytes, read_QPixmap_from_bytes
|
43 | 43 |
|
44 | 44 | from . import version as plugin_version
|
45 |
| -from .timelock_recovery import TimelockRecoveryPlugin, TimelockRecoveryContext, PartialTxInputWithFixedNsequence |
| 45 | +from .timelock_recovery import TimelockRecoveryPlugin, TimelockRecoveryContext |
46 | 46 |
|
47 | 47 |
|
48 | 48 | if TYPE_CHECKING:
|
49 | 49 | from electrum.gui.qt import ElectrumGui
|
50 |
| - from electrum.transaction import PartialTransaction, TxOutput |
| 50 | + from electrum.transaction import PartialTransaction |
51 | 51 | from PyQt6.QtWidgets import QStatusBar
|
52 | 52 |
|
53 | 53 |
|
54 | 54 | AGREEMENT_TEXT = "I understand that using this wallet after generating a Timelock Recovery plan might break the plan"
|
55 |
| -ANCHOR_OUTPUT_AMOUNT_SATS = 600 |
56 | 55 | MIN_LOCKTIME_DAYS = 2
|
57 | 56 | # 0xFFFF * 512 seconds = 388.36 days.
|
58 | 57 | MAX_LOCKTIME_DAYS = 388
|
@@ -350,21 +349,9 @@ def _verify_step1_details(self, context: TimelockRecoveryContext, next_button: Q
|
350 | 349 | next_button.setEnabled(True)
|
351 | 350 |
|
352 | 351 | def create_alert_fee_dialog(self, context: TimelockRecoveryContext):
|
353 |
| - alert_transaction_outputs = [ |
354 |
| - PartialTxOutput(scriptpubkey=address_to_script(context.get_alert_address()), value='!'), |
355 |
| - ] + [ |
356 |
| - PartialTxOutput(scriptpubkey=output.scriptpubkey, value=ANCHOR_OUTPUT_AMOUNT_SATS) |
357 |
| - for output in context.outputs |
358 |
| - ] |
359 |
| - make_tx = lambda fee_est, *, confirmed_only=False: context.wallet.make_unsigned_transaction( |
360 |
| - coins=context.main_window.get_coins(confirmed_only=confirmed_only), |
361 |
| - outputs=alert_transaction_outputs, |
362 |
| - fee=fee_est, |
363 |
| - is_sweep=False, |
364 |
| - ) |
365 | 352 | tx: Optional['PartialTransaction']
|
366 | 353 | is_preview: bool
|
367 |
| - tx, is_preview = context.main_window.confirm_tx_dialog(make_tx, '!', allow_preview=False) |
| 354 | + tx, is_preview = context.main_window.confirm_tx_dialog(context.make_unsigned_alert_tx, '!', allow_preview=False) |
368 | 355 | if tx is None or is_preview or tx.has_dummy_output(DummyAddress.SWAP):
|
369 | 356 | return
|
370 | 357 | if not tx.is_segwit():
|
@@ -392,39 +379,9 @@ def sign_done(success: bool):
|
392 | 379 | )
|
393 | 380 |
|
394 | 381 | def create_recovery_fee_dialog(self, context: TimelockRecoveryContext):
|
395 |
| - prevouts: List[Tuple[int, 'TxOutput']] = [ |
396 |
| - (index, tx_output) for index, tx_output in enumerate(context.alert_tx.outputs()) |
397 |
| - if tx_output.address == context.get_alert_address() and tx_output.value != ANCHOR_OUTPUT_AMOUNT_SATS |
398 |
| - ] |
399 |
| - if len(prevouts) != 1: |
400 |
| - context.main_window.show_error(_("Expected 1 output from the Alert transaction to the Alert Address, but got %d." % len(prevouts))) |
401 |
| - return |
402 |
| - prevout_index: int |
403 |
| - prevout: 'TxOutput' |
404 |
| - (prevout_index, prevout) = prevouts[0] |
405 |
| - |
406 |
| - nsequence: int = round(context.timelock_days * 24 * 60 * 60 / 512) |
407 |
| - if nsequence > 0xFFFF: |
408 |
| - # Safety check - not expected to happen |
409 |
| - raise ValueError("Sequence number is too large") |
410 |
| - nsequence += 0x00400000 # time based lock instead of block-height based lock |
411 |
| - tx_input = PartialTxInputWithFixedNsequence( |
412 |
| - prevout=TxOutpoint(txid=bfh(context.alert_tx.txid()), out_idx=prevout_index), |
413 |
| - nsequence=nsequence, |
414 |
| - ) |
415 |
| - tx_input.utxo = context.alert_tx |
416 |
| - tx_input.witness_utxo = prevout |
417 |
| - |
418 |
| - make_tx = lambda fee_est, *, confirmed_only=False: context.wallet.make_unsigned_transaction( |
419 |
| - coins=[tx_input], |
420 |
| - outputs=[output for output in context.outputs if output.value != 0], |
421 |
| - fee=fee_est, |
422 |
| - is_sweep=False, |
423 |
| - ) |
424 |
| - |
425 | 382 | tx: Optional['PartialTransaction']
|
426 | 383 | is_preview: bool
|
427 |
| - tx, is_preview = context.main_window.confirm_tx_dialog(make_tx, '!', allow_preview=False) |
| 384 | + tx, is_preview = context.main_window.confirm_tx_dialog(context.make_unsigned_recovery_tx, '!', allow_preview=False) |
428 | 385 | if tx is None or is_preview or tx.has_dummy_output(DummyAddress.SWAP):
|
429 | 386 | return
|
430 | 387 | if not tx.is_segwit():
|
@@ -545,33 +502,9 @@ def create_cancellation_dialog(self, context: TimelockRecoveryContext):
|
545 | 502 | return bool(cancel_dialog.exec())
|
546 | 503 |
|
547 | 504 | def create_cancellation_fee_dialog(self, context: TimelockRecoveryContext):
|
548 |
| - prevouts = [ |
549 |
| - (index, tx_output) for index, tx_output in enumerate(context.alert_tx.outputs()) |
550 |
| - if tx_output.address == context.get_alert_address() and tx_output.value != ANCHOR_OUTPUT_AMOUNT_SATS |
551 |
| - ] |
552 |
| - if len(prevouts) != 1: |
553 |
| - context.main_window.show_error(_("Expected 1 output from the Alert transaction to the Alert Address, but got %d." % len(prevouts))) |
554 |
| - return |
555 |
| - (prevout_index, prevout) = prevouts[0] |
556 |
| - |
557 |
| - tx_input = PartialTxInput( |
558 |
| - prevout=TxOutpoint(txid=bfh(context.alert_tx.txid()), out_idx=prevout_index), |
559 |
| - ) |
560 |
| - tx_input.utxo = context.alert_tx |
561 |
| - tx_input.witness_utxo = prevout |
562 |
| - |
563 |
| - make_tx = lambda fee_est, *, confirmed_only=False: context.wallet.make_unsigned_transaction( |
564 |
| - coins=[tx_input], |
565 |
| - outputs=[ |
566 |
| - PartialTxOutput(scriptpubkey=address_to_script(context.get_cancellation_address()), value='!'), |
567 |
| - ], |
568 |
| - fee=fee_est, |
569 |
| - is_sweep=False, |
570 |
| - ) |
571 |
| - |
572 | 505 | tx: Optional['PartialTransaction']
|
573 | 506 | is_preview: bool
|
574 |
| - tx, is_preview = context.main_window.confirm_tx_dialog(make_tx, '!', allow_preview=False) |
| 507 | + tx, is_preview = context.main_window.confirm_tx_dialog(context.make_unsigned_cancellation_tx, '!', allow_preview=False) |
575 | 508 | if tx is None or is_preview or tx.has_dummy_output(DummyAddress.SWAP):
|
576 | 509 | return
|
577 | 510 | if not tx.is_segwit():
|
@@ -733,7 +666,7 @@ def _save_recovery_plan_json(self, context: TimelockRecoveryContext, download_di
|
733 | 666 | "wallet_version": version.ELECTRUM_VERSION,
|
734 | 667 | "wallet_name": context.wallet_name,
|
735 | 668 | "timelock_days": context.timelock_days,
|
736 |
| - "anchor_amount_sats": ANCHOR_OUTPUT_AMOUNT_SATS, |
| 669 | + "anchor_amount_sats": context.ANCHOR_OUTPUT_AMOUNT_SATS, |
737 | 670 | "anchor_addresses": [output.address for output in context.outputs],
|
738 | 671 | "alert_address": context.get_alert_address(),
|
739 | 672 | "alert_inputs": [tx_input.prevout.to_str() for tx_input in context.alert_tx.inputs()],
|
@@ -935,7 +868,7 @@ def _save_recovery_plan_pdf(self, context: TimelockRecoveryContext, download_dia
|
935 | 868 | f"as we'll explain later):\n"
|
936 | 869 | )
|
937 | 870 | for output in context.alert_tx.outputs():
|
938 |
| - if output.address != context.get_alert_address() and output.value == ANCHOR_OUTPUT_AMOUNT_SATS: |
| 871 | + if output.address != context.get_alert_address() and output.value == context.ANCHOR_OUTPUT_AMOUNT_SATS: |
939 | 872 | step1_text += f"• {output.address}\n"
|
940 | 873 | else:
|
941 | 874 | step1_text += "except for a small fee.\n"
|
|
0 commit comments