With recent changes, particularly using postgres, we can finish the HTLC before
we force close, so the test fails. Insert an explicit hangup here so we reliably
get the result we expect:
```
@pytest.mark.parametrize("anchors", [False, True])
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd anchors not supportd')
def test_anchorspend_using_to_remote(node_factory, bitcoind, anchors):
"""Make sure we can use `to_remote` output of previous close to spend anchor"""
# Try with old output from both anchor and non-anchor channel.
l4_opts = {}
if anchors is False:
l4_opts['dev-force-features'] = "-23"
l1, l2, l3, l4 = node_factory.get_nodes(4, opts=[{},
{},
{'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC']},
l4_opts])
# Give l2 some funds, from a to-remote output. It will have to spend
# this to use anchor.
node_factory.join_nodes([l4, l2])
# l4 unilaterally closes, l2 gets to-remote with its output.
l4.rpc.pay(l2.rpc.invoice(100000000, 'test', 'test')['bolt11'])
> wait_for(lambda: only_one(l4.rpc.listpeerchannels()['channels'])['htlcs'] != [])
tests/test_closing.py:4183:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
success = <function test_anchorspend_using_to_remote.<locals>.<lambda> at 0x7f8293e7fe20>
timeout = 180
def wait_for(success, timeout=TIMEOUT):
start_time = time.time()
interval = 0.25
while not success():
time_left = start_time + timeout - time.time()
if time_left <= 0:
> raise ValueError("Timeout while waiting for {}".format(success))
E ValueError: Timeout while waiting for <function test_anchorspend_using_to_remote.<locals>.<lambda> at 0x7f8293e7fe20>
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Also gets some new timemono helpers, but we don't use them (yet).
Changelog-Fixed: Compilation on FreeBSD.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Closes: https://github.com/ElementsProject/lightning/issues/7758
Apparently clboss gives us \u UTF codes. We don't support that (use UTF-8 directly)
```
126 ../sysdeps/x86_64/multiarch/strlen-vec.S: No such file or directory.
(gdb) bt
label=label@entry=0x63e2f9604db9 "char *[]") at ccan/ccan/tal/str/str.c:137
complete=complete@entry=0x7ffe9090b0f6, destroyed=destroyed@entry=0x7ffe9090b0f7) at lightningd/plugin.c:773
```
Reported-by: Ken Sedgwick
Fixes: #8338
Changelog-None: broken in this release
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Checking a signature is a CPU-intensive operation that should be performed only
if gossmap doesn't already have the channel announcement in question and we're
not already checking for the announcement's UTxO.
Changelog-Fixed: `gossipd` doesn't waste CPU cycles checking signatures on channel announcements that are already known
Issue: https://github.com/ElementsProject/lightning/issues/7972
Ubuntu 20.04 reached its end-of-life (EOL) on April 15, 2025, and GitHub Actions subsequently removed the Ubuntu 20.04 LTS runner. As a result, we must upgrade all workflow runners to at least Ubuntu 22.04. Currently, this update has only been applied to pypi.yml for core-lightning.
Changelog-None.
The reproducible build is currently failing on Ubuntu Noble, causing the daily `Repro Build Nightly` GitHub action to fail and triggering email notifications.
This update resolves the issue by adjusting the default sqlite3 version and checksums to match the packages now available in Noble, allowing the image to build successfully.
Changelog-None.
We asserted that a node would be connected, but now we always call the
chanbackup peer_connected hook, it might not be that fast:
```
2025-05-17T08:37:58.7193306Z def test_funding_fail(node_factory, bitcoind):
...
2025-05-17T08:37:58.7204037Z # Restart l2 without ridiculous locktime.
2025-05-17T08:37:58.7204546Z del l2.daemon.opts['watchtime-blocks']
2025-05-17T08:37:58.7204990Z l2.restart()
2025-05-17T08:37:58.7206578Z l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
2025-05-17T08:37:58.7207072Z
2025-05-17T08:37:58.7207522Z # We don't have enough left to cover fees if we try to spend it all.
2025-05-17T08:37:58.7208203Z with pytest.raises(RpcError, match=r'not afford'):
2025-05-17T08:37:58.7208761Z l1.rpc.fundchannel(l2.info['id'], funds)
2025-05-17T08:37:58.7209203Z
2025-05-17T08:37:58.7209598Z # Should still be connected (we didn't contact the peer)
2025-05-17T08:37:58.7210243Z assert only_one(l1.rpc.listpeers()['peers'])['connected']
2025-05-17T08:37:58.7210875Z l2.daemon.wait_for_log('Handed peer, entering loop')
2025-05-17T08:37:58.7211439Z > assert only_one(l2.rpc.listpeers()['peers'])['connected']
2025-05-17T08:37:58.7211912Z E assert False
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
It can definitely happen (it's not dead yet):
```
2025-05-17T08:44:48.9829150Z lightningd-2 2025-05-17T08:36:43.597Z **BROKEN** 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#3: gossipd gave channel_update in CGOSSIP_CHANNEL_ANNOUNCED_DYING? update=01027cf5d46590c45eb608a7e07a7b123c998ac12a655ce11004c9d9bb59f83698e8760d7b992df0dcf925f6732503de55d596aadaa35f0a8837cee58e0769172d2a06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00006f00000100006828493f010200060000000000000000000000010000000a000000003b023380
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We picked one node and iterated. This means we would only sent to 1,
not 2 nodes if we picked the last (common if there were only a few
peers). But it also means we would generally send to the same pair of
nodes, which isn't great for redundancy.
Rework to be more random.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Now we've make it only on existing channels, and not have to call
listdatastore every time, that means we can safely turn it on by
default.
Changelog-Added: Protocol: we now offer peer storage to any peers who create a channel.
Changelog-Deprecated: Config: `--experimental-peer-storage` (it's now the default).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
When peer backup is enabled by default, it puts things in the datastore, breaking
this assumption. Narrow the test to examine the specific funder directory.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
They will in fact get truncated, and never restore. Large nodes should be using some real
backup strategy!
For this reason, we split "peer_backup" support into send vs store support, so we can
turn off send of our own without disabling storing/sending theirs.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We already get the connected hook, so in there we can add to a hash
table of suitable peers. Rather than subscribe to disconnection, we
simply remove the peer if a sendcustommsg fails.
This does make after_send_scb_single() a bit more complex, since it
needs this specific node_id: we use a `struct info` per node and a
pointer to a shared "idx" reference counter.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
By keeping a local hash table, we won't have to look up every time.
We still write to the datastore when it changes, and we need to
initialize it at plugin start.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Eclair only sets `batch_size` and `funding_txid` when its a batch larger than 1.
Adjust how we send and what we expect to receive to match this.
Changelog-None
And we timeout in:
l2.wait_for_channel_onchain(l1.info['id'])
Because the unilateral wins. This is because we tell closingd to
negotiate with a min feerate of 3750, but when it does and we check it,
our min has jumped, lightningd rejects it:
... That's below our min XXX for weight 772 at feerate 7000
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
The spec used to say you had to wait for channel to be ready, *and* 6
depth before exchanging signatures. Now the 6 depth requirement is only
on the actual announcing of the channel: you can send sigs any time.
This means our state machine goes from:
NOT_USABLE -> NOT_DEEP_ENOUGH -> NEED_PEER_SIGS -> ANNOUNCED
to:
NOT_USABLE -> NEED_PEER_SIGS -> NOT_DEEP_ENOUGH -> ANNOUNCED
However, this revealed that our state machine is insufficient, so
rework it to be more general and understandable. In particular,
check for unexpected state transitions, and thus document them.
Note that cg->sent_sigs replaces channel->replied_to_announcement_sigs,
too.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: We now exchange `announcement_signatures` as soon as we're ready, rather than waiting for 6 blocks (as per recent BOLT update)
They can all call get_block_height(); the extra argument confused me and
I thought they were called before the block height was actually updated.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We want a more fine-grained approach, so we now have:
1. update_channel_update() - returns true if it changed.
2. channel_should_enable() - should this channel be marked enabled.
3. arm_refresh_timer() - start a refresh timer for the channel_update.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This could always happen, but now we're more correct about send it, it's
a possible race that I've seen in CI.
We can never get a PONG (that's now handled by connectd directly), but we
can definitely see this:
```
2025-05-15T02:29:14.7403081Z # Even with onchain anchor channel, it still keeps reserve (just in case!).
2025-05-15T02:29:14.7403766Z > l1.rpc.close(l2.info['id'])
2025-05-15T02:29:14.7404069Z
2025-05-15T02:29:14.7404248Z tests/test_opening.py:2536:
...
2025-05-15T02:29:14.7413090Z > return self.sock.recv(length)
2025-05-15T02:29:14.7413353Z E Failed: Timeout >1800.0s
...
2025-05-15T02:29:14.8097229Z lightningd-1 2025-05-15T01:50:59.538Z DEBUG 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-closingd-chan#1: billboard perm: Expected closing_signed: 0103fad81b49d5e367cd785e3088b9acf356a7984a17a1ccda86d09da41438840b08000067000001000078c3314666731e339c0b8434f7824797a084ed7ca3655991a672da068e2c44cb53b57b53a296c133bc879109a8931dc31e6913a4bda3d58559b99b95663e6d52679cabaccc6e39dbd95a4dac90e75a258893c3aa3f733d1b8890174d5ddea8003cadffe557773c54d2c07ca1d535c4bf85885f879ae466c16a516e8ffcfec174
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Calling the funding tx an anchor is pre-spec terminology, which is now
confusing; let's rename the variable.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>