Commit Graph

335 Commits

Author SHA1 Message Date
Rusty Russell
af1c9640b5 hsmd: remove unused "sign_local_htlc_tx" function which onchaind used to use.
I tried removing sign_penalty_to_us, but that comment is wrong: channeld
uses that for the watchtower, so it stays (with updated comment).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-20 19:32:42 +10:30
Sangbida Chaudhuri
5fdc56c544 wallet/hsmd: fix signmessagewithkey for BIP86 wallets
The signmessagewithkey RPC was failing for BIP86 (mnemonic-based)
wallets because:

1. The wallet RPC was iterating through BIP32-derived addresses only,
   so it couldn't find BIP86-derived addresses.

2. The HSM's handle_bip137_sign_message always used bitcoin_key()
   (BIP32 derivation) regardless of wallet type.
2026-01-14 17:18:56 +10:30
Rusty Russell
9b85ce7b03 hsmd: fix derivation for non-taproot addresses in modern mnemonic (25.12+) nodes.
This is a fix from https://github.com/rauaap who correctly diagnosed the problem:

```
Error broadcasting transaction: error code: -26\nerror message\nmempool-script-verify-flag-failed (Script failed an OP_EQUALVERIFY operation), input 0 of ...
```

The decision to use the changed derivation for all addresses, not just
taproot, came up during review.  Unfortunately, the signing code
(here) was not changed to match the address generation code (in the
wallet).

Reported-by: https://github.com/postanissue
Fixes: https://github.com/ElementsProject/lightning/issues/8804
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: lightningd: we now correctly sign for non-taproot addresses given by nodes created by v25.12 or newer.
2026-01-14 17:18:56 +10:30
Rusty Russell
21d4f684f3 hsmd: check *all* anchor inputs for short sigs.
Anchors will have one input from the commitment tx, and at least on
more (in this case, 3 more); we were only checking the first one for
short signatures.

```
            total_feerate_perkw = total_fees / total_weight * 1000
>           check_feerate([l3, l2], total_feerate_perkw, feerate)

tests/test_closing.py:4064: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

nodes = [<fixtures.LightningNode object at 0x7f3e9a2c74f0>, <fixtures.LightningNode object at 0x7f3e991d5f30>]
actual_feerate = 14006.105538595726, expected_feerate = 14000

    def check_feerate(nodes, actual_feerate, expected_feerate):
        # Feerate can't be lower.
        assert actual_feerate > expected_feerate - 2
        if actual_feerate >= expected_feerate + 2:
            if any([did_short_sig(n) for n in nodes]):
                return
        # Use assert as it shows the actual values on failure
>       assert actual_feerate < expected_feerate + 2
E       AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
8a60a27662 pytest: fix feerate check in test_peer_anchor_push
We didn't log when anchor transactions had short signatures,
which causes this test to not assert (did_short_sig):

```
            total_feerate_perkw = total_fees / total_weight * 1000
>           check_feerate([l3, l2], total_feerate_perkw, feerate)

tests/test_closing.py:4063: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

nodes = [<fixtures.LightningNode object at 0x7f0fb322bb20>, <fixtures.LightningNode object at 0x7f0fb1b5ead0>]
actual_feerate = 14006.105538595726, expected_feerate = 14000

    def check_feerate(nodes, actual_feerate, expected_feerate):
        # Feerate can't be lower.
        assert actual_feerate > expected_feerate - 2
        if actual_feerate >= expected_feerate + 2:
            if any([did_short_sig(n) for n in nodes]):
                return
        # Use assert as it shows the actual values on failure
>       assert actual_feerate < expected_feerate + 2
E       AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Sangbida Chaudhuri
4c7e2d449d hsmd: fix HSM sent an unknown message type error
When we enter the wrong passphrase hsmd crashes like this with an unknown message type:

lightning_hsmd: Failed to load hsm_secret: Wrong passphrase (version v25.12rc1-7-g7713a42-modded)
0x102ba44bf ???
        send_backtrace+0x4f:0
0x102b0900f status_failed
        common/status.c:207
0x102af1a37 hsmd_send_init_reply_failure
        hsmd/hsmd.c:301
0x102af1497 load_hsm
        hsmd/hsmd.c:446
0x102af1497 init_hsm
        hsmd/hsmd.c:548
0x102b29e63 next_plan
        ccan/ccan/io/io.c:60
0x102b29e63 do_plan
        ccan/ccan/io/io.c:422
0x102b29d8b io_ready
        ccan/ccan/io/io.c:439
0x102b2b4bf io_loop
        ccan/ccan/io/poll.c:470
0x102af0a83 main
        hsmd/hsmd.c:886
lightningd: HSM sent unknown message type

This change swaps write_all() to wire_synce_write() because write_all() is missing the wire protocol length prefix. We also don't send a stack trace anymore if the user has entered the wrong passphrase and exit cleanly.
2025-11-27 14:06:17 +10:30
Rusty Russell
f8fd97fb5d global: replace randombytes_buf() with randbytes() wrapper.
This allows us to override it for deterministic results.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-13 21:21:29 +10:30
Rusty Russell
82fff3c74b Remove litecoin support.
No idea if it works, we don't test it and nobody runs it.  I guess not.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: Config: non-functioning litecoin support (who knew we even had that?)
2025-10-26 20:31:45 +10:30
Sangbida Chaudhuri
32bb0ed20e hsmd_wire: remove hsmd_derive_bip86_key and add it to hsmd_init_reply_v4
Instead of having a separate field to derive the bip86 base key, we return it in the hsmd init reply once we know that the hsm_secret is of mnemonic type
2025-10-26 12:37:58 +10:30
Rusty Russell
16ae5a4b50 common: trivial changes from review.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-26 12:37:58 +10:30
Rusty Russell
6c15f1e364 common/hsm_secret: remove grab_file_contents now it has inspired grab_file_raw!
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
463712f3b7 utils: add a generic mlock function with a destructor
Introduces a generic utility function to replace the repeated pattern of
sodium_mlock() + tal_add_destructor()
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
266b8082c8 hsmd_wire: add HSM wire protocol support for secret type detection
Add TLV field to hsmd_init_reply_v4 to communicate the HSM secret type
(mnemonic vs legacy) from HSM to lightningd. This allows lightningd to
automatically determine whether to use BIP86 or BIP32 derivation without
needing separate address types.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
bf508387a3 hsmtool: change hsm_secret struct to have length awareness
This commit is updating hsmtool and exposesecrets to use the new pattern for storing the secret, which is the secret_data and secret_len, to support both 64 byte and 32 byte seeds.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
1b3e881d5a hsmd: find correct P2TR key for utxo
In the case where we receive a taproot utxo we want to be able to tell if it was derived using a BIP32 seed or a BIP86 seed. Considering we will only be supporting BI86 type wallet addresses for mnemonics we can check if the out secret is 64 bytes long and if it is we can use our BIP86 for the withdrawal.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
1665665271 lightningd: store base and derive pubkeys locally
RIP to this commit there's a good chance a lot of this code doesn't even make this into the final PR. Pour one out for the fallen lines of code.

This commit is doing the rest of the derivation. There was a significant overlap between the bip32_pubkey derivation and the bip86_pubkey derivation so that has been refactored in one place.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
63001745ca hsmd/libhsmd: add BIP86 base-key
BIP86 wants the full 64-byte BIP32 seed (from BIP39). This wires up BIP86
support so the HSM derives the hardened base m/86'/0'/0' inside the box,
and exposes helpers:
  • derive_bip86_base_key()   // m/86'/0'/0'
  • bip86_key(index)          // m/86'/0'/0'/0/index

Spoiler: derive_bip86_base_key() and bip86_key() now live in libhsmd.c as they will later be used to check the derived wallet address against hsmd's derivation, this is just to sanity check that we haven't had an accidental bit flip while we have generated this address.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
121fcfc92b hsmd: add BIP86 wire scaffolding (derive/check), no behavior yet
Here's some *foreshadowing* for what's to come. Here's what we're aiming for with our derivation flow:

Derivation split (hardened vs unhardened)
========================================

        ┌───────────────┐
        │      HSM      │  (secrets live here)
        │               │
        │  BIP39 → seed (64B)
        │       ↓
        │   m/86'/0'/0'           ← derive hardened base (private)
        │       ↓ (neuter)
        │   BIP86 base xpub       ← public-only + chain code
        │       ↓
        │  [send once over wire]
        └───────────────┘
                │
                ▼
        ┌───────────────────────┐
        │ lightningd / wallet   │
        │                       │
        │  local (unhardened) derivations:
        │    /0/i  → external
        │    /1/i  → change
        │                       │
        │  P2TR(BIP86) from pubkey_i
        │  (optionally: CHECK with HSM)
        └───────────────────────┘

We want to do part of the derivation inside hsmd and then send this base "pubkey" over the wire so our wallet can do the remaining derivation based on the address type and index. This lays the foundation for the base key wire message.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
fc981f4d30 hsmd/libhsmd: change hsmd_init to have secret_data and secret_len
hsmd: plumb length-aware secret into hsmd_init; keep 32B mirror

BIP86 (from BIP39) wants the full 64-byte BIP32 seed. This commit plumbs a variable-length (32/64B) secret into hsmd and uses the accessors from the previous commit. We keep the old 32B hsm_secret mirror and, for now, only use the first 32 bytes so legacy paths keep working.

Spoiler: HKDFs will keep using the 32B seed; only wallet address derivation
will switch to the full 64B in a follow-up.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
de9c6305a1 exposesecret: Add support for mnemonic-based HSM secrets
Update the exposesecret plugin to work with the new unified HSM secret
format that supports BIP39 mnemonics.

Changelog-Added - exposesecret now has a mnemonic field
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
218dc2fe20 hsmd: use the new mnemonic-compatible hsm_secret routines.
Changelog-Changed: hsmd: New nodes will now be created with a BIP-39 12-word phrase as their root secret.
Changelog-Deprecated: config: `encrypted-hsm` to require a passphrase (use `hsm-passphrase`).
Changelog-Added: config: `hsm-passphrase` indicates we should use a manual passphrase with the hsm secret.
2025-10-26 12:37:58 +10:30
Sangbida Chaudhuri
e3fe739f64 hsmd: take the passphrase raw, not the derived secret.
In preparation for BIP-39, we need to hand the passphrase (if any) to HSMD.

So we extend the hsmd wire protocol to allow that.
2025-10-26 12:37:58 +10:30
Rusty Russell
6e5cb299dd global: remove unnecessary includes from C files.
Basically, `devtools/reduce-includes.sh */*.c`.

Build time from make clean (RUST=0) (includes building external libs):

Before:
	real    0m38.944000-40.416000(40.1131+/-0.4)s
	user    3m6.790000-17.159000(15.0571+/-2.8)s
	sys     0m35.304000-37.336000(36.8942+/-0.57)s
After:
	real    0m37.872000-39.974000(39.5466+/-0.59)s
	user    3m1.211000-14.968000(12.4556+/-3.9)s
	sys     0m35.008000-36.830000(36.4143+/-0.5)s

Build time after touch config.vars (RUST=0):

Before:
	real    0m19.831000-21.862000(21.5528+/-0.58)s
	user    2m15.361000-30.731000(28.4798+/-4.4)s
	sys     0m21.056000-22.339000(22.0346+/-0.35)s

After:
	real    0m18.384000-21.307000(20.8605+/-0.92)s
	user    2m5.585000-26.843000(23.6017+/-6.7)s
	sys     0m19.650000-22.003000(21.4943+/-0.69)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-23 06:44:04 +10:30
Rusty Russell
f6a4e79420 global: remove unnecessary includes from headers.
Each header should only include the other headers it needs to compile;
`devtools/reduce-includes.sh */*.h` does this.  The C files then need
additional includes if they don't compile.

And remove the entirely useless wire/onion_wire.h, which only serves to include wire/onion_wiregen.h.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-23 06:44:04 +10:30
Rusty Russell
e120f87083 Makefile: create a library containing common, wire and bitcoin objects.
This means we don't have to manually choose what to link against,
which is much of the complexity of our Makefiles: the compiler will
automatically use any object files it needs to link.

We already do this for ccan as libccan.a, now we have libcommon.a.

We don't link against it for *everything*, as some tests require their own
versions.

Notes:
1. I get rid of the weird plugins/test/Makefile2 (accidental commit?)
2. Many tests change due to update-mocks.
3. In some places I added the missing dependency on the Makefile itself, though most are in the next
   patch.

Before:
	Total program size:     221366528
	Total tests size:       364243856

After:
	Total program size:     190733656
	Total tests size:       337880888

Build time from make clean (RUST=0) (includes building external libs):

Before:
	real    0m38.227000-44.245000(41.8222+/-1.6)s
	user    3m2.105000-33.696000(23.1442+/-8.4)s
	sys     0m35.054000-42.269000(39.7231+/-2)s
After:
	real    0m38.944000-40.416000(40.1131+/-0.4)s
	user    3m6.790000-17.159000(15.0571+/-2.8)s
	sys     0m35.304000-37.336000(36.8942+/-0.57)s

Build time after touch config.vars (RUST=0):

Before:
	real    0m18.928000-22.776000(21.5084+/-1.1)s
	user    2m8.613000-36.567000(27.7281+/-7.7)s
	sys     0m20.458000-23.436000(22.3963+/-0.77)s

After:
	real    0m19.831000-21.862000(21.5528+/-0.58)s
	user    2m15.361000-30.731000(28.4798+/-4.4)s
	sys     0m21.056000-22.339000(22.0346+/-0.35)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

rusty@rusty-Framework:~/devel/cvs/lightni
2025-10-23 06:44:04 +10:30
Rusty Russell
992771bbdf pytest: fix flakes in feerates.
Sometimes we get a shorter signature than expected, and we're supposed
to disable the feerate tests in that case.  But we didn't catch all the
cases where we make signatures.

```
2025-10-13T02:36:24.1901527Z ____________________________ test_peer_anchor_push _____________________________
2025-10-13T02:36:24.1902251Z [gw5] linux -- Python 3.10.18 /home/runner/work/lightning/lightning/.venv/bin/python
2025-10-13T02:36:24.1902731Z 
2025-10-13T02:36:24.1903045Z node_factory = <pyln.testing.utils.NodeFactory object at 0x7f17fdffd6f0>
2025-10-13T02:36:24.1903740Z bitcoind = <pyln.testing.utils.BitcoinD object at 0x7f17fdffe830>
2025-10-13T02:36:24.1904495Z executor = <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f17fdffcbb0>
2025-10-13T02:36:24.1906158Z chainparams = {'bip173_prefix': 'bcrt', 'chain_hash': '06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f', 'elements': False, 'example_addr': 'bcrt1qeyyk6sl5pr49ycpqyckvmttus5ttj25pd0zpvg', ...}
2025-10-13T02:36:24.1907285Z 
2025-10-13T02:36:24.1907600Z     @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd anchors not supportd')
2025-10-13T02:36:24.1908344Z     def test_peer_anchor_push(node_factory, bitcoind, executor, chainparams):
2025-10-13T02:36:24.1909033Z         """Test that we use anchor on peer's commit to CPFP tx"""
2025-10-13T02:36:24.1909853Z         l1, l2, l3 = node_factory.line_graph(3, opts=[{},
2025-10-13T02:36:24.1910334Z                                                       {'min-emergency-msat': 546000,
2025-10-13T02:36:24.1910825Z                                                        'dev-warn-on-overgrind': None,
2025-10-13T02:36:24.1911313Z                                                        'broken_log': 'overgrind: short signature length'},
2025-10-13T02:36:24.1911662Z                                                       {'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC'],
2025-10-13T02:36:24.1911976Z                                                        'dev-warn-on-overgrind': None,
2025-10-13T02:36:24.1912304Z                                                        'broken_log': 'overgrind: short signature length'}],
2025-10-13T02:36:24.1912790Z                                              wait_for_announce=True)
2025-10-13T02:36:24.1913041Z     
2025-10-13T02:36:24.1913305Z         # We splinter l2's funds so it's forced to use more than one UTXO to push.
2025-10-13T02:36:24.1914043Z         fundsats = int(Millisatoshi(only_one(l2.rpc.listfunds()['outputs'])['amount_msat']).to_satoshi())
2025-10-13T02:36:24.1914443Z         OUTPUT_SAT = 10000
2025-10-13T02:36:24.1914647Z         NUM_OUTPUTS = 10
2025-10-13T02:36:24.1914903Z         psbt = l2.rpc.fundpsbt("all", "1000perkw", 1000)['psbt']
2025-10-13T02:36:24.1915520Z         # Pay 5k sats in fees.
2025-10-13T02:36:24.1916329Z         psbt = l2.rpc.addpsbtoutput(fundsats - OUTPUT_SAT * NUM_OUTPUTS - 5000, psbt, destination=l3.rpc.newaddr()['bech32'])['psbt']
2025-10-13T02:36:24.1917156Z         for _ in range(NUM_OUTPUTS):
2025-10-13T02:36:24.1917638Z             psbt = l2.rpc.addpsbtoutput(OUTPUT_SAT, psbt)['psbt']
2025-10-13T02:36:24.1918194Z         l2.rpc.sendpsbt(l2.rpc.signpsbt(psbt)['signed_psbt'])
2025-10-13T02:36:24.1918731Z         bitcoind.generate_block(1, wait_for_mempool=1)
2025-10-13T02:36:24.1919232Z         sync_blockheight(bitcoind, [l1, l2])
2025-10-13T02:36:24.1919634Z     
2025-10-13T02:36:24.1919847Z         # Make sure all amounts are below OUTPUT_SAT sats!
2025-10-13T02:36:24.1920318Z         assert [x for x in l2.rpc.listfunds()['outputs'] if x['amount_msat'] > Millisatoshi(str(OUTPUT_SAT) + "sat")] == []
2025-10-13T02:36:24.1920735Z     
2025-10-13T02:36:24.1920957Z         # Get HTLC stuck, so l2 has reason to push commitment tx.
2025-10-13T02:36:24.1921244Z         amt = 100_000_000
2025-10-13T02:36:24.1921517Z         sticky_inv = l3.rpc.invoice(amt, 'sticky', 'sticky')
2025-10-13T02:36:24.1921842Z         route = l1.rpc.getroute(l3.info['id'], amt, 1)['route']
2025-10-13T02:36:24.1922277Z         l1.rpc.sendpay(route, sticky_inv['payment_hash'], payment_secret=sticky_inv['payment_secret'])
2025-10-13T02:36:24.1922751Z         l3.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
2025-10-13T02:36:24.1923060Z     
2025-10-13T02:36:24.1923241Z         # Make sure HTLC expiry is what we expect!
2025-10-13T02:36:24.1923637Z         l2.daemon.wait_for_log('Adding HTLC 0 amount=100000000msat cltv=119 gave CHANNEL_ERR_ADD_OK')
2025-10-13T02:36:24.1923998Z     
2025-10-13T02:36:24.1924229Z         # l3 drops to chain, but make sure it doesn't CPFP its own anchor.
2025-10-13T02:36:24.1924685Z         wait_for(lambda: only_one(l3.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] != [])
2025-10-13T02:36:24.1925688Z         closetx = l3.rpc.dev_sign_last_tx(l2.info['id'])['tx']
2025-10-13T02:36:24.1926132Z         l3.stop()
2025-10-13T02:36:24.1926337Z         # We don't care about l1 any more, either
2025-10-13T02:36:24.1926579Z         l1.stop()
2025-10-13T02:36:24.1926739Z     
2025-10-13T02:36:24.1926941Z         # We put l3's tx in the mempool, but won't mine it.
2025-10-13T02:36:24.1927316Z         bitcoind.rpc.sendrawtransaction(closetx)
2025-10-13T02:36:24.1927754Z     
2025-10-13T02:36:24.1928139Z         # We aim for feerate ~3750, so this won't mine l3's unilateral close.
2025-10-13T02:36:24.1928991Z         # HTLC's going to time out at block 120 (we give one block grace)
2025-10-13T02:36:24.1929527Z         for block in range(110, 120):
2025-10-13T02:36:24.1929989Z             bitcoind.generate_block(1, needfeerate=5000)
2025-10-13T02:36:24.1930510Z             assert bitcoind.rpc.getblockcount() == block
2025-10-13T02:36:24.1931014Z             sync_blockheight(bitcoind, [l2])
2025-10-13T02:36:24.1931715Z         assert only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['state'] == 'CHANNELD_NORMAL'
2025-10-13T02:36:24.1932368Z     
2025-10-13T02:36:24.1932642Z         # Drops to chain
2025-10-13T02:36:24.1933030Z         bitcoind.generate_block(1, needfeerate=5000)
2025-10-13T02:36:24.1933824Z         wait_for(lambda: only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['state'] == 'AWAITING_UNILATERAL')
2025-10-13T02:36:24.1934522Z     
2025-10-13T02:36:24.1935254Z         # But, l3's tx already there, and identical feerate will not RBF.
2025-10-13T02:36:24.1935839Z         l2.daemon.wait_for_log("rejecting replacement")
2025-10-13T02:36:24.1936357Z         wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 2)
2025-10-13T02:36:24.1936801Z     
2025-10-13T02:36:24.1937127Z         # As blocks pass, we will use anchor to boost l3's tx.
2025-10-13T02:36:24.1937666Z         for block, feerate in zip(range(120, 124), (12000, 13000, 14000, 15000)):
2025-10-13T02:36:24.1938560Z             l2.daemon.wait_for_log(fr"Worth fee [0-9]*sat for remote commit tx to get 100000000msat at block 125 \(\+{125 - block}\) at feerate {feerate}perkw")
2025-10-13T02:36:24.1939369Z             l2.daemon.wait_for_log("sendrawtx exit 0")
2025-10-13T02:36:24.1939902Z             # Check feerate for entire package (commitment tx + anchor) is ~ correct
2025-10-13T02:36:24.1940473Z             details = bitcoind.rpc.getrawmempool(True).values()
2025-10-13T02:36:24.1940920Z             print(f"mempool = {details}")
2025-10-13T02:36:24.1941347Z             total_weight = sum([d['weight'] for d in details])
2025-10-13T02:36:24.1941903Z             total_fees = sum([float(d['fees']['base']) * 100_000_000 for d in details])
2025-10-13T02:36:24.1942467Z             total_feerate_perkw = total_fees / total_weight * 1000
2025-10-13T02:36:24.1942972Z >           check_feerate([l3, l2], total_feerate_perkw, feerate)
2025-10-13T02:36:24.1943279Z 
2025-10-13T02:36:24.1943411Z tests/test_closing.py:4064: 
2025-10-13T02:36:24.1943813Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2025-10-13T02:36:24.1944170Z 
2025-10-13T02:36:24.1944685Z nodes = [<fixtures.LightningNode object at 0x7f17fdf684f0>, <fixtures.LightningNode object at 0x7f17fdf6af50>]
2025-10-13T02:36:24.1945708Z actual_feerate = 13005.66942869603, expected_feerate = 13000
2025-10-13T02:36:24.1946091Z 
2025-10-13T02:36:24.1946247Z     def check_feerate(nodes, actual_feerate, expected_feerate):
2025-10-13T02:36:24.1946558Z         # Feerate can't be lower.
2025-10-13T02:36:24.1946870Z         assert actual_feerate > expected_feerate - 2
2025-10-13T02:36:24.1947365Z         if actual_feerate >= expected_feerate + 2:
2025-10-13T02:36:24.1947830Z             if any([did_short_sig(n) for n in nodes]):
2025-10-13T02:36:24.1948239Z                 return
2025-10-13T02:36:24.1948589Z         # Use assert as it shows the actual values on failure
2025-10-13T02:36:24.1949043Z >       assert actual_feerate < expected_feerate + 2
2025-10-13T02:36:24.1949489Z E       AssertionError
2025-10-13T02:36:24.1949704Z 
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-14 09:48:02 +10:30
Rusty Russell
6a94683db4 hsmd: don't assert that our own locktime is > 0.
By policy, our stub hsmd accepts everything: openingd is supposed to
sort this out (or use VLS for a real HSM implementation!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Config: the node no longer crashes if you set `watchtime-blocks` to 0 (which is fine for testing: don't do this on mainnet!).
2025-08-07 14:55:30 +09:30
Lagrang3
7343502c69 hsmd: refactor hsmd_init
Add preapprove_check capabilities:
WIRE_HSMD_PREAPPROVE_INCOICE_CHECK and
WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK to the capabilities array
if dev_no_preapprove_check is not set.
Do not assume those occupy the last two slots in the array.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 13:19:03 +09:30
Lagrang3
b6388c710f HSMD: add new wire BIP137 sign message API
Changelog-Added: HSMD: add new wire API to sign messages with bitcoin wallet keys according to BIP137.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 13:19:03 +09:30
Rusty Russell
c0d68c5c2c pytest: create warning if we grind signature shorter than 71 bytes, don't fail.
One in 256 times, we will grind a signature to 70 bytes (or shorter).  This breaks
our feerate tests.  Unfortunately the grinding is deterministic, so there doesn't
seem to be a way to avoid it.  So we add a log message, and then we skip the
feerate test if it happens.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
2154289911 hsmd: rename simple_htlc to hsm_htlc, don't gratuitously dynamically allocate.
The renaming makes it clear that it's HSM specific.

And it has no pointers, so we can have an array instead of an array of pointers.

I tested this hadn't accidentally changed the wire format by disabling
version checks and using an old hsmd with the altered daemons and
running the test suite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
29c8693b26 hsmd: roll the definition of simple_htlc into the csv.
This is such a simple struct that we can actually define it in csv.
This prevents us from accidentally breaking the ABI in future.

I tested this hadn't accidentally changed the wire format by disabling
version checks and using an old hsmd with the altered daemons and
running the test suite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
daf1560eb4 hsmd: make our private utxo type, to ensure binary compatibility.
I'm about to update our utxo type, but Christian spotted that this is
part of the ABI for the hsm.  So make that a private "hsm_utxo" type,
to insulate it from changes.

In particular, the HSM versions only contain the fields that the
hsm cares about, and the wire format is consistent (even though that
*did* include some of those fields, they are now dummies).

In the long term, this should be removed from the ABI: once we
no longer have "close_info" utxos, this information should already be
in the PSBT.

I tested this hadn't accidentally changed the wire format by disabling
version checks and using an old hsmd with the altered daemons and
running the test suite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Jon Griffiths
8fc4cb6bef hsmd: enable caching of sub-hashes when signing our PSBT inputs
Enabling the cache makes signing significantly faster for segwit inputs,
particularly taproot which was designed with caching in mind.

Changelog-None

Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
2025-03-21 09:48:57 +10:30
Rusty Russell
74ef03d361 lightningd: use tweak on node_id of different key, for createinvoicerequest.
It's an internal difference, so doesn't actually break compatibility
(it would if we tried to prove we owned an old invoicerequest, but we
don't have infrastructure for that anyway).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
e8a38f111d hsmd: create an hsm variant to sign a bolt12 invoice using a tweak on our key.
The current interface, if given a tweak, uses a *different secret key*
and tweaks it.  This was an early experiment: we will switch to using
a secret tweak for invoice_requests like we do for invoice path ids.

To make sure there's no funny business, *hsmd* hashes to form the
tweak (i.e. no zero tweaks!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
b6d7ee1f11 common: No longer support new channels without option_static_remotekey.
We still support *existing* channels.  Just not new ones (before they could,
in theory, explicitly ask for one).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Ken Sedgwick
cfcdde14d8 hsmd: support HSM_VERSION 6
Changelog-Changed: hsmd: the hsmd now supports HSM_VERSION 6

This is actually optional, everything would be ok leaving native hsmd
support at HSM_VERSION 5 instead.
2024-05-14 10:39:12 -05:00
Ken Sedgwick
eda0b28cbb hsmd: HSM_VERSION 6: get_per_commitment_point never returns secret
Changelog-Changed: hsmd: HSM_VERSION 6: get_per_commitment_point does
not imply index - 2 is revoked, makes it safe to call on any index.
2024-05-14 10:39:12 -05:00
Ken Sedgwick
37fe32aa17 hsmd: make the negotiated hsmd version available to libhsmd
Changelog-None: hsmd internals
2024-05-14 10:39:12 -05:00
Rusty Russell
c7339ea310 pytest: test various preapprove scenarios.
We wire through --dev options into the hsmd, and test preapprove accept and deby
with both old and new protocols.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
6ea95da342 hsmd: add variant of preapprove commands to have it check only, not do anything.
Apparently VLS actually does something when we preapprove: if caller is just
checking we want to tell it not to do that!

I put in a flag so we can test both old and new APIs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
33cfef84d8 hsmd: add preinit message to set HSM dev flags.
This should make VLS's life easier: they can ignore dev flags they
don't understand, but we will know their capabilites after init and so
know what they didn't understand (if required).

The only flag for now is a flag to force failure for "preapprove" calls.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
9450d46db1 bitcoin/short_channel_id: pass by copy everywhere.
It's a u64, we should pass by copy.  This is a big sweeping change,
but mainly mechanical (change one, compile, fix breakage, repeat).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-03-20 13:51:48 +10:30
Rusty Russell
e0e879c003 common: remove type_to_string files altogther.
This means including <common/utils.h> where it was indirectly included.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-03-20 13:51:48 +10:30
Rusty Russell
37d22f9141 global: change all type_to_string to fmt_X.
This has the benefit of being shorter, as well as more reliable (you
will get a link error if we can't print it, not a runtime one!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-03-20 13:51:48 +10:30
Jon Griffiths
aa23c2a2b2 script: consistently take the script length in identification functions
Standardizes the is_xxx script function all take a script length, and changes
their first-level callers to pass it. This has several knock on benefits:

- We remove the repeated tal_count/tal_bytelen calls on the script, in
  particular the redundant calls that result when we must check for multiple
  types of script - which is almost all cases.
- We remove the dependency on the memory being tal-allocated (It is, in
  all cases, but theres no reason we need to require that).
- We remove all cases where we create a copy of the script just to id it.
- We remove all allocations for non-interesting scripts while iterating block
  txs in process_getfilteredblock_step1().
- We remove all allocations *including for potentially interesting scripts* in
  topo_add_utxos().

Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
2024-03-18 12:24:49 +10:30
Vincenzo Palazzo
af41cd5192 hsmd: remove deprecated init v2
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-02-27 14:04:44 +01:00
Vincenzo Palazzo
ef40b2face hsmd: increase the min version
Increasing the min version of the hsmd due that we
added new code that required the hsmd to sign an announcements.

One of the solution is to increase the min version in this way
a signer like VLS fails directly during the init phase.

Link: https://github.com/ElementsProject/lightning/issues/7074
Changelog-None: hsmd: increase the min version
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-02-27 14:04:44 +01:00
Rusty Russell
ad4a8a510d hsmd: add command to allow lightningd to sign channel announcement.
Before this it was channeld doing it, which was tied to a particular
channel.  Create an API for lightningd to sign for any channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-01-31 14:47:33 +10:30