Skip to content

FAFO Edition - #88

Closed
rsafier wants to merge 274 commits into
nGoline:mainfrom
rsafier:wip/fafo
Closed

rsafier wants to merge 274 commits into
nGoline:mainfrom
rsafier:wip/fafo

Conversation

@rsafier

@rsafier rsafier commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

No description provided.

rsafier and others added 30 commits September 25, 2026 09:53
Co-Authored-By: Claude <noreply@anthropic.com>
…sage payload lengths

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…on test

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 7923b6443098b6a4469538a854c8473b6918661a)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 66f9bc1e8938ccacb2750598a31771f29cbdca53)
Bump MessagePack/MessagePack.Annotations to 3.1.10, pin
System.Security.Cryptography.Xml 10.0.12 and SQLitePCLRaw.bundle_e_sqlite3
2.1.12 over vulnerable transitives, and suppress the SharpCompress advisory
for test tooling (LNUnit breaks on the patched SharpCompress API).

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit de6c67aa6e50391104e824a034bf0a99952c5bf2)
Serialization now builds Release.Native as Release.Native instead of
Release.Wasm. Crypto-agnostic src projects (Repositories, Contracts, Client,
Plugins, Transport.Ipc) map *.Native/*.Wasm to Debug/Release by flavour
instead of always Debug. Application.Tests and Daemon.Tests declare the
Native configurations like the other test projects and are no longer built
in Wasm configurations. scripts/check-sln-configs.py flags future drift.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 4e44083158665e0228e6b27db34a4cbe4bd07ea5)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit e26484d90889eaa7eec4d3deba12ec9673972778)
testwithcoverage.sh now discovers test/*/*.Tests.csproj instead of a
hardcoded list of removed projects; launch.json targets the net10.0 Daemon
and the existing build all task.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit d809880b0658d4e47f54fd3b6e37cc994b2fd028)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 2d02439f6be547016dba75c463eda51ff7025b07)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 33ca1e42e0dff8dd6407cc8836457d4ff99a6007)
… NL-170, NL-172, NL-173, NL-174)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit d120626a4498456967f72cd1efe517e27dc86001)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3a6ffd8e29ef7f026b171921b55e0aadd5858775)
…L-160)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 928e4c1f5f75aeeb3f496dca80311eb30946dbd7)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 94be4332033ce302c43c63af81a0a01de170f6f8)
…alue objects (NL-165)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit b772d0978f3d4959450d00275ccf06779152d758)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3ec342d351203e281d767caa02e893907261b058)
…a v1 backup (NL-158)

The libsodium Argon2 call passed the UTF-16 char count as the password byte length, so non-ASCII passwords were truncated and did not match the native backend. ICryptoProvider now takes password bytes; SecureKeyManager still opens files written with the truncated encoding and rewrites them. Atomic key file writes now keep the target's Unix mode (new files 0600), follow symlinks and delete the temp file on failure. The v1-to-v2 upgrade first copies the original to <file>.v1.bak.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 5de1a875f85e16cfcc07a6ffade6ee676071a746)
…gelog (NL-166)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit cd60e25859585ad30e4f81633cf089f72a1587b1)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 9760b3aadad0be0f7c81b251e89e09356c9a79b7)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 53402607819bdd6a565e15ed8373b12046286ed3)
…NL-106)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit e96f311657e810577c247f3071a5d83f1c6db152)
…(NL-105)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit c727245adb6790313100f2a8cd6ae9200ef10958)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 92c6bc836bdb171da9e072f0c2ef21d7ad07a575)
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 81026261e53c0184a2f2c95264b204dea97752e9)
rsafier and others added 29 commits September 25, 2026 18:11
…fromchannel and document the retry-aware htlc origin replay rule (NL-137 / NL-242 / W1-C)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit d8d7ce4)
…ll! (NL-244 / N6-T1)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 98c6af1)
…ngine with persist-before-send, first snapshot at channel_ready, startup revert and failed-channel persistence (NL-031 / NL-232 / NL-235 / NL-136 / N6-T1)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 6cc54f2)
…the shared stateful singleton (N6-T1)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit ebb28cb)
… and a fee round with identical txids at every step (NL-031 / N6-T4)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 72c576c)
…a debounced commit scheduler with a liveness check, the local-only htlc switch and startup event replay (NL-031 / NL-243 / N6-T2)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 9ca73f2)
…k with a readable error onion while the channel stays active at commitment numbers 2/2 (NL-031 / N6-T5)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit d63fa2b)
…lay and the n6 proofs in the application and test guides (N6-T2 / N6-T5)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit ddf8cda)
…ht is known instead of reporting height 0 (NL-031 / N6-T2)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit abe3ec4)
…ry send-side update and signature off that link, so no commitment_signed covers an update the peer never received (NL-031 / N6-T2)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 0c416ce)
…icy, hint routes, payment onions and invoice service (NL-114 / ONION M4-T2, M4-T3, M4-T4, M4-T6)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit ecffbf8)
… M4 / W1-B)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit ba77d61)
…n and document the final-hop accept race (NL-114 / ONION M4-T6, M4-T3)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit b346558)
…ort fee policy, reestablished and data loss (NL-241 / W1-D)

ListChannelsClientHandler read the legacy LocalOfferedHtlcs/RemoteOfferedHtlcs
collections, which are empty after a reload since the commitment snapshot; it
now counts the snapshot's non-final HTLCs per direction (legacy lists only for
a channel without a snapshot). ChannelInfoIpcResponse appends keys 16-18
(IsReestablished, FeeBaseMsat, FeePpm); the fee policy is Node:Routing and
IsReestablished stays false until N7. DataLossDetected now comes from the model.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit e5fb8da)
…uting options and enable htlcs in the default config (NL-152 / W1-D)

CreateInvoice (9), PayInvoice (10), ListInvoices (11) and ListPayments (12):
MessagePack requests/responses (Secret? and ChannelId? formatters), scoped
client handlers over IInvoiceService/IPaymentService (argument checks,
service errors mapped to invalid_operation), and IPC handlers on a shared
ClientCommandIpcHandler base that answers "not available" while the payment
services are not registered. The client handlers are registered with
factories so a ValidateOnBuild host still builds. IOptions<RoutingOptions> is
the validated NodeOptions.Routing instance; the default appsettings template
writes Node:EnableHtlcs (true on regtest) and every Node:Routing default.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 55bac2a)
…ands with snapshot-tested printers (NL-152 / W1-D)

NamedPipeIpcClient gains the four calls on a generic SendRequestAsync;
amounts are msat ('any' or 0 = none), number arguments are checked in
ValidateArguments, and payinvoice exits 1 when the payment failed. The new
printers and ListChannelsPrinter (now with Reestablished and the fee policy)
write culture-invariant text to an injectable TextWriter, pinned by
PrinterSnapshotTests.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit bc303b2)
…ew (NL-152 / W1-D)

- payinvoice maps only the exact duplicate-hash InvalidOperationException to invalid_operation; other
  failures become server_error pointing to listpayments (payment may be in flight)
- client handler resolution: only a missing registration or payment service is 'not available';
  construction failures are server_error
- pipe instance cap 10 -> 64 and payinvoice max wait 3600 -> 300 s so long pays cannot starve polling
- cli: list count capped at 1000, payinvoice timeout at 300, amount '0' rejected (use 'any')

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit ab6cb42)
…s subscribed, stop racing the read loop on writes, and install a connection only after the init exchange (NL-239 / NL-240 / W1-E)

The responder's transport read loop started at the end of the BOLT 8 handshake, before the message, peer-communication and peer services subscribed, so the initiator's init was raised to nobody (NL-239). Now the transport starts reading only once MessageReceived has a subscriber, and each layer attaches to the one below only when it gets its own first subscriber; PeerService subscribes to messages last.

WriteMessageAsync checked the socket with Poll + Available, which the read loop could drain in between, so a live connection looked closed and our init write failed; the half-built connection stayed open and the other end's tie-break kept it (NL-240). Writes now check TcpClient.Connected, a failed PeerService constructor disposes the stack, and PeerManager installs a session only after IPeerService.WaitForInitAsync. The read loop signals its end in a finally, so a Dispose caused by a hang-up no longer waits 5 s.

Harness: the NL-239/NL-240 retry tolerance is removed; MultiNodeHarnessTests requires every sequential and simultaneous connect to settle and asserts neither bug's log line appears. New in-process PeerManagerConnectTests run two real peer managers over loopback.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit eae2f45)
…ns and check and keep the peer's (NL-099 / W1-E)

New Application/Gossip ChannelUpdateService (AddGossipServices, TryAdd): on the first Open of a channel with a scid it takes the channel lock (so the update follows channel_ready in the outbox), builds must_be_one|dont_forward, BOLT 7 direction, real scid, Routing fee/CLTV delta, htlc min/max from the peer's limits, capacity and Routing, a strictly increasing timestamp, signs it with the node key and raises it; PeerManager (optional constructor parameter) enqueues it with the new PeerOutbox.TryEnqueueGossip / IPeerService.SendGossipMessageAsync.

Inbound 258 is raised by PeerService through IPeerService.OnChannelUpdateReceived (a few kept for the first subscriber) and kept by the service only if it is for our chain, names a channel with that peer (scid or alias), has the peer's direction, verifies with the peer's node key and is newer.

Docker proof ChannelUpdateExchangeTests: after we open a channel to alice, LND GetChanInfo shows our fee base/ppm/CLTV delta, and we stored alice's own update. LND still never hints through us in addinvoice --private (it requires a public node; needs node_announcement).

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit c4834da)
… started stopping (NL-240 / W1-E)

Installing only after the init exchange widened the window in which StopAsync could run while an inbound connection still waited for its init; that connection is now disconnected and released instead of installed behind the stop.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 02fedc8)
…and prove it against lnd after a reconnect (NL-099 / W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3eb539b)
…icy change reaches lnd after a reconnect (NL-099 / W1-E)

LND ignores a same-policy keep-alive update younger than 24 h and resends its own update unchanged on reconnect; we now do the same.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 25a8543)
…k racing the read loop (NL-240 / W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 06bd208)
…nd init waits on stop and wait for inbound setups before stopping (NL-240 / W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 82c6f41)
…nels, send none when htlc_minimum exceeds the capacity, and ignore peer updates far in the future or above capacity (NL-099 / W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit b277960)
…t needs to wire channel_update into the peer manager (NL-099 / W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit eef3b88)
…ent repositories in the composition root and give the two-node harness store htlc origins (NL-114 / NL-099 / NL-137 / W1-B, W1-C, W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
…d exchange proof, since the shared alice relays other tests' channels (NL-099 / W1-E)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@rsafier rsafier closed this Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant