Commit Graph

613 Commits

Author SHA1 Message Date
Sander van Grieken
605b511b43 qt,qml: move get_text_not_enough_funds_mentioning_frozen and get_frozen_balance_str to backend wallet
Note: the qt gui used to include FX in get_frozen_balance_str, but that is not replicated now.
2025-01-31 18:03:21 +01:00
SomberNight
cba073dfd1 lightning: change derivation of funding_pubkey
Ideally, given an on-chain backup, after the remote force-closes, we should be able to spend our anchor output,
to CPFP the remote commitment tx (assuming the channel used OPTION_ANCHORS).
To spend the anchor output, we need to be able to sign with the local funding_privkey.

Previously we derived the funding_key from the channel_seed (which comes from os.urandom).
Prior to anchors, there was no use case for signing with the funding_key given a channel backup.
Now with anchors, we should make its derivation deterministic somehow, in a way so that it can
be derived given just an on-chain backup.
- one way would be to put some more data into the existing OP_RETURN
  - uses block space
  - the OP_RETURNs can be disabled via "use_recoverable_channels"
  - only the initiator can use OP_RETURNs (so what if channel is in incoming dir?)
- instead, new scheme for our funding_key:
  - we derive the funding_privkey from the lnworker root secret (derived from our bip32 seed)
  - for outgoing channels:
    - lnworker_root_secret + remote_node_id + funding_tx_nlocktime
  - for incoming channels:
    - lnworker_root_secret + remote_node_id + remote_funding_pubkey
  - a check is added to avoid reusing the same key between channels:
      not letting to user open more than one channel with the same peer in a single block
  - only the first 16 bytes of the remote_node_id are used, as the onchain backup OP_RETURNs only contain that
- as the funding_privkey cannot be derived from the channel_seed anymore, it is included in the
imported channel backups, which in turn need a new version defined
  - a wallet db upgrade is used to update already stored imported cbs
  - alternatively we could keep the imported cbs as-is, so no new version, no new funding_privkey field, as it is clearly somewhat redundant given on-chain backups can reconstruct it
    - however adding the field seems easier
      - otherwise the existing code would try to derive the funding_privkey from the channel_seed
      - also note: atm there is no field in the imported backups to distinguish anchor channels vs static-remotekey channels
2025-01-14 17:56:48 +00:00
ThomasV
fefd123275 wallet: always include wanted_height (for future tx) 2025-01-10 10:41:54 +01:00
ThomasV
33d0e6dbec Attach labels to outpoints instead of txids.
Move labels logic from lnworker to wallet.

Due to batching, a single transaction may have several labels attached to it.
2025-01-03 10:54:11 +01:00
ThomasV
ac1c9f088d Anchor channels: require deterministic wallet with software keystore.
This ends LN support in hardware and watching-only wallets.
2024-12-20 10:17:51 +01:00
ThomasV
ee42e09387 anchor channels: unlock wallet on startup if the wallet has channels 2024-12-20 10:10:07 +01:00
ThomasV
77ec49ac67 make_unsigned_transaction: ensure coins and inputs do not overlap
(follow-up 8bec974a39)
2024-12-17 10:54:21 +01:00
ThomasV
62af1ee887 fixes for txin.make_witness:
- add witness_sizehint
  - fix make_unsigned_transaction
  - do not remove witness_script in tx.finalize()
2024-12-13 14:44:35 +01:00
ThomasV
3b1dc194e4 Refactor lnsweep:
- txins have an optional make_witness method
 - instead of gen_tx, SweepInfo has a txin and
   an optional txout, for 1st stage HTLCs
 - sweep transactions are created by lnwatcher

The purpose of this change is to allow combining several
inputs in the same sweep transaction.
2024-12-11 17:14:14 +01:00
ThomasV
8bec974a39 wallet: add inputs and base_tx parameters to make_unsigned_transaction 2024-12-08 09:54:10 +01:00
ThomasV
58fee0d1cc Merge pull request #9265 from SomberNight/202410_ln_address_reuse_2
lnworker: reserve wallet addresses also for chan backups
2024-11-13 10:59:03 +01:00
ThomasV
60f13a977e Swaps over Nostr
- Separation between SwapManager and its transport:
   Legacy transpport uses http, Nostr uses websockets
 - The transport uses a context to open/close connections.
   This context is not async, because it needs to be called
   from the GUI
 - Swapserver fees values are initialized to None instead
   of 0, so that any attempt to use them before the swap
   manager is initialized will raise an exception.
 - Remove swapserver fees disk caching (swap_pairs file)
 - Regtests use http transport
 - Android uses http transport (until QML is ready)
2024-11-12 09:32:25 +01:00
SomberNight
b9a81cd03e lnworker: reserve wallet addresses also for chan backups
We were already reserving wallet addresses for full channels.
Now we also do the same for imported channel backups.
(but not for onchain, as we don't have enough info for that)

Without this, if the same seed is used on multiple devices (with each
device having its own set of LN channels), the wallet instances will
reuse keys (specifically the payment_basepoint, which for
static_remotekey chans is used as the to_remote output).
Now with this change, at least if the wallet instances have imported
channel backups of each other, this reuse is avoided.
2024-10-20 13:58:10 +00:00
SomberNight
e84679982e qt tx dlg: fix showing fee warnings
In qt, only the confirm_tx_dialog was showing the fee warnings, the transaction_dialog was not...

regression from bc3946d2f4
2024-10-16 12:42:58 +00:00
ThomasV
3721f04ac8 replace electrum/ecc with electrum_ecc package 2024-10-10 15:46:00 +00:00
SomberNight
16d2f0f9d4 wallet.get_tx_status: fix incorrect feerate for partial txs
The history tab would show an incorrect feerate for partial/unsigned (local) txs,
if they had any p2sh/p2wsh txins. We would just guess the script is p2wpkh, and
use that for the size calc. Now with calling add_info_from_wallet, the correct
size is used to calculate the feerate.

(The gui tx dialogs call add_info_from_wallet independently, so the size/feerate
shown there were already correct.)
2024-08-13 03:20:32 +00:00
SomberNight
3d6198eff0 trustedcoin: Wallet_2fa.make_unsigned_transaction to use **kwargs
We often forget updating the method signature of Wallet_2fa.make_unsigned_transaction
when changing Abstract_Wallet.make_unsigned_transaction.
2024-06-17 16:55:23 +00:00
ThomasV
912e1a3a5b reintroduce 'unlock' command
- the unlock command was replaced by an option to load_wallet,
because some applications (the swapserver plugin) need to be
executed with an unlocked password. Now the swapserver plugin
waits until the wallet is unlocked.
- wallet.unlock now checks password unconditionally, see #8799
2024-06-08 11:10:33 +02:00
SomberNight
e25658d724 fix plot.py
fixes https://github.com/spesmilo/electrum/issues/9058
2024-05-22 15:26:26 +00:00
SomberNight
13d9677e53 transaction: tx.sign API change: rm hex usage 2024-04-29 17:10:30 +00:00
SomberNight
2f1095510c bitcoin.py/transaction.py: API changes: rm most hex usage
Instead of some functions operating with hex strings,
and others using bytes, this consolidates most things to use bytes.

This mainly focuses on bitcoin.py and transaction.py,
and then adapts the API usages in other files.

Notably,
- scripts,
- pubkeys,
- signatures
should be bytes in almost all places now.
2024-04-29 17:10:26 +00:00
SomberNight
05599eeda5 swaps: fix get_swap_by_funding_tx, and types/type-hints
- funding txs having only one output is not true...
- batch_rbf can combine funding txs
2024-03-13 11:37:01 +00:00
SomberNight
8ab3dcce5d keystore: API changes for from_seed/from_bip43_rootseed/bip39_to_seed
- force kwargs
- add type hints
2024-02-21 15:08:19 +00:00
ThomasV
9799603779 Merge pull request #8888 from SomberNight/202402_jsonrpc_errors
cli/rpc: nicer error messages and error-passing
2024-02-21 13:20:28 +01:00
SomberNight
0925f15280 wallet/keystore: add apis for "add_slip_19_ownership_proofs_to_tx"
- implement it specifically for the "singlesig trezor" case
- aimed to be generic enough that support for more complex scripts
  and other keystores could be added later
2024-02-21 11:56:13 +00:00
SomberNight
bd492fbd14 cli/rpc: nicer error messages and error-passing
Previously, generally, in case of any error, commands would raise a generic "Exception()" and the CLI/RPC would convert that and return it as `str(e)`.

With this change, we now distinguish "user-facing exceptions" (e.g. "Password required" or "wallet not loaded") and "internal errors" (e.g. bugs).
- for "user-facing exceptions", the behaviour is unchanged
- for "internal errors", we now pass around the traceback (e.g. from daemon server to rpc client) and show it to the user (previously, assuming there was a daemon running, the user could only retrieve the exception from the log of that daemon). These errors use a new jsonrpc error code int (code 2).

As the logic only changes for "internal errors", I deem this change not to be compatibility-breaking.

----------
Examples follow.
Consider the following two commands:
```
@command('')
async def errorgood(self):
	from electrum.util import UserFacingException
	raise UserFacingException("heyheyhey")

@command('')
async def errorbad(self):
	raise Exception("heyheyhey")
```

----------
(before change)

CLI with daemon:
```
$ ./run_electrum --testnet daemon -d
starting daemon (PID 9221)
$ ./run_electrum --testnet errorgood
heyheyhey
$ ./run_electrum --testnet errorbad
heyheyhey
$ ./run_electrum --testnet stop
Daemon stopped
```

CLI without daemon:
```
$ ./run_electrum --testnet -o errorgood
heyheyhey
$ ./run_electrum --testnet -o errorbad
heyheyhey
```

RPC:
```
$ curl --data-binary '{"id":"curltext","jsonrpc":"2.0","method":"errorgood","params":[]}' http://user:pass@127.0.0.1:7777
{"id": "curltext", "jsonrpc": "2.0", "error": {"code": 1, "message": "heyheyhey"}}
$ curl --data-binary '{"id":"curltext","jsonrpc":"2.0","method":"errorbad","params":[]}' http://user:pass@127.0.0.1:7777
{"id": "curltext", "jsonrpc": "2.0", "error": {"code": 1, "message": "heyheyhey"}}
```

----------
(after change)

CLI with daemon:
```
$ ./run_electrum --testnet daemon -d
starting daemon (PID 9254)
$ ./run_electrum --testnet errorgood
heyheyhey
$ ./run_electrum --testnet errorbad
(inside daemon): Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/daemon.py", line 254, in handle
    response['result'] = await f(*params)
  File "/home/user/wspace/electrum/electrum/daemon.py", line 361, in run_cmdline
    result = await func(*args, **kwargs)
  File "/home/user/wspace/electrum/electrum/commands.py", line 163, in func_wrapper
    return await func(*args, **kwargs)
  File "/home/user/wspace/electrum/electrum/commands.py", line 217, in errorbad
    raise Exception("heyheyhey")
Exception: heyheyhey

internal error while executing RPC
$ ./run_electrum --testnet stop
Daemon stopped
```

CLI without daemon:
```
$ ./run_electrum --testnet -o errorgood
heyheyhey
$ ./run_electrum --testnet -o errorbad
  0.78 | E | __main__ | error running command (without daemon)
Traceback (most recent call last):
  File "/home/user/wspace/electrum/./run_electrum", line 534, in handle_cmd
    result = fut.result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 458, in result
    return self.__get_result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/home/user/wspace/electrum/./run_electrum", line 255, in run_offline_command
    result = await func(*args, **kwargs)
  File "/home/user/wspace/electrum/electrum/commands.py", line 163, in func_wrapper
    return await func(*args, **kwargs)
  File "/home/user/wspace/electrum/electrum/commands.py", line 217, in errorbad
    raise Exception("heyheyhey")
Exception: heyheyhey
```

RPC:
```
$ curl --data-binary '{"id":"curltext","jsonrpc":"2.0","method":"errorgood","params":[]}' http://user:pass@127.0.0.1:7777
{"id": "curltext", "jsonrpc": "2.0", "error": {"code": 1, "message": "heyheyhey"}}
$ curl --data-binary '{"id":"curltext","jsonrpc":"2.0","method":"errorbad","params":[]}' http://user:pass@127.0.0.1:7777
{"id": "curltext", "jsonrpc": "2.0", "error": {"code": 2, "message": "internal error while executing RPC", "data": {"exception": "Exception('heyheyhey')", "traceback": "Traceback (most recent call last):\n  File \"/home/user/wspace/electrum/electrum/daemon.py\", line 254, in handle\n    response['result'] = await f(*params)\n  File \"/home/user/wspace/electrum/electrum/commands.py\", line 163, in func_wrapper\n    return await func(*args, **kwargs)\n  File \"/home/user/wspace/electrum/electrum/commands.py\", line 217, in errorbad\n    raise Exception(\"heyheyhey\")\nException: heyheyhey\n"}}}
```
2024-02-12 19:02:02 +00:00
SomberNight
c84e55e957 wallet: (trivial) simplify class hierarchy
legacy cruft
2024-02-05 12:47:20 +00:00
SomberNight
87214c004e trezor: don't try to sign non-ismine inputs
progress towards coinjoin

related https://github.com/spesmilo/electrum/issues/8868
2024-02-05 07:21:28 +00:00
SomberNight
a9a8ed2eb4 follow-up: factor out more hardcoded "sat/byte" and "sat/b" strings
- rename globals
- also rm hardcoded strings from qml
- use consistent unit names in qml
  (previously mixed sat/vB and sat/byte (latter coming from core lib))
2024-02-03 05:26:31 +00:00
SomberNight
13a421aabb factor out hardcoded "sat/byte" and "sat/b" strings
Though note that the qml GUI has some more in qml/js context.
2024-02-03 04:18:46 +00:00
SomberNight
cbece71894 walletdb: rm some dead code 2024-01-23 02:20:01 +00:00
SomberNight
ef9ba0985e wallet: (trivial) add asserts re args in bump_fee and friends
for clearer exceptions in case of bugs

related https://github.com/spesmilo/electrum/issues/8571
2024-01-17 20:37:31 +00:00
SomberNight
49c3567d7d wallet: simplify bump_fee: rm txid arg
closes https://github.com/spesmilo/electrum/issues/8797
2024-01-17 19:20:29 +00:00
SomberNight
bbd3bd2ffe wallet.is_lightning_funding_tx: also check channel_backups 2024-01-17 12:24:09 +00:00
SomberNight
248e50eed0 transaction: rename tx.is_final to tx.is_rbf_enabled, and invert it 2024-01-17 02:08:15 +00:00
Sander van Grieken
d8f579ccfc Consistently use translated strings for UserFacingException raises 2024-01-16 16:25:33 +01:00
ThomasV
178a03129f submarine_swaps: define main_loop, with async with taskgroup
rm unneeded @ignore_exception wrapper in lnworker and network
2024-01-10 17:15:29 +01:00
SomberNight
2bc056ed33 wallet: refactor check_sighash/risk_of_burning_coins_as_fees
- risk_of_burning_coins_as_fees is turned into a private (helper) method, only called by check_sighash.
  UIs should only care about check_sighash.
- check_sighash returns instance of new class "TxSighashDanger" instead of tuple
- made warning levels more fine-grained (FEE_WARNING_SKIPCONFIRM vs FEE_WARNING_NEEDCONFIRM)
- this became more complicated than I had hoped for but I think it is worth it to ~merge
  check_sighash and risk_of_burning_coins_as_fees into one.

related https://github.com/spesmilo/electrum/pull/8699
2023-12-13 04:52:01 +00:00
SomberNight
e1d0247ce4 wallet: clarify difference between wallet.is_mine and adb.is_mine
related https://github.com/spesmilo/electrum/pull/8699
2023-12-12 14:17:38 +00:00
SomberNight
f7cb523b9d wallet db: deduplicate "seed_type" field
In the db, the 'seed_type' field could be present both at the top-level and inside keystores.

Note:
- both fields had usages
- the top-level field was added in 2.8 re "initial segwit support" (3a64ec0f2e)
  - there was no db upgrade for it, so older files are missing it
  - if present, valid values can be electrum types but also
    other types supported by the wizard, e.g. "bip39"
- the keystore-level field was added in 4.1 (7b7bba2299)
  - there was a db upgrade when it was introduced, so old files also have it
  - if present, valid values can only be electrum types
- there is not much value in the top-level one having a non-electrum value,
  and those values were never used by other parts of the code
  - note that when creating a standard wallet from a bip39 seed, the seed is discarded.
    Only the derived xprv and the derivation path are kept. If we changed this and also kept the seed,
    e.g. to display it to the user, then it would make sense to save the seed type (e.g. "bip39").
    However storing that seed_type would make more sense at the keystore level (not top-level).

We delete the top-level 'seed_type' field.

```
{
    "keystore": {
        "seed_type": "segwit",
        ...
    },
    "seed_type": "segwit",
    ...
}
```
2023-12-01 18:43:37 +00:00
Sander van Grieken
7b96a83350 wallet: add sighash check to class Abstract_Wallet
qml: use backend sighash check and add user confirmation path
qt: use backend sighash check and add user confirmation path
qml: include get_warning_for_risk_of_burning_coins_as_fees test in txdetails
qt: add warning icon to sighash warning
add sighash and fee checks to wallet.sign_transaction, making all warnings fatal unless ignore_warnings is set to True
tests: test sign_transaction on both code paths with ignore_warnings True and False,
raise specific exceptions TransactionPotentiallyDangerousException and TransactionDangerousException
2023-11-30 12:53:46 +01:00
SomberNight
6467db0b7d json_db: rename "_write" to sth more descriptive 2023-11-27 15:30:26 +00:00
SomberNight
7f64ecc4bd wallet.bump_fee: the glorious return of BumpFeeStrategy :D
gui/qt/rbf_dialog.py (old) lines 57-64 were implementing logic that should not be part of GUI code.
Case in point, gui/qml/qetxfinalizer.py (old) lines 511-513 duplicated half of that logic but not the other half.
That logic is now moved to wallet.get_bumpfee_strategies_for_tx().

More context: a user on irc got confused when using the qml gui. They were sending "max" and wanted to bump_fee.
The qml gui selected the "preserve_payment" strategy by default, using which there was no solution, and the user
did not notice that the strategy can be altered (via the "method" dropdown). The qt gui had logic to select
"decrease_payment" by default in such a case (which does find a solution to bump) but this logic was not
duplicated in the qml gui.
Instead of duplicating the logic, this commit moves it to shared lib code.
2023-11-20 18:55:43 +00:00
SomberNight
f1c63e2d51 commands: make payto/etc respect 'confirmed_only' config var
regression from 2f6d60c715

fixes https://github.com/spesmilo/electrum/issues/8693
2023-11-17 13:05:23 +00:00
Sander van Grieken
621a397b70 i18n: translate a few untranslated strings and avoid early translate for pr_tooltips and pr_expiration_values
fixes #8689
2023-11-14 12:07:49 +01:00
Sander van Grieken
e011bd235b qml: implement delete address for imported wallets, and fix address list on address/key add. 2023-11-10 09:30:56 +01:00
SomberNight
da8e6c2fbf wallet: check that multisig wallet does not have duplicate masterkeys
The wizard should technically disallows this at creation time,
but this second layer sanity check could not hurt.
Also, looks like the wizard check is not working properly atm
(regression from qt wizard refactor).
2023-10-30 17:22:08 +00:00
ThomasV
fac5153329 Merge pull request #8659 from accumulator/issue_8658
request: amount_msat is set to None in Request when creating request …
2023-10-25 17:55:39 +02:00
SomberNight
227e257444 (follow-up) wallet: add option to merge duplicate tx outputs 2023-10-24 14:41:39 +00:00
Sander van Grieken
420e584f4e request: amount_msat is set to None in Request when creating request and amount is 0 or undefined. 2023-10-24 13:48:00 +02:00