Commit graph

612 commits

Author SHA1 Message Date
bitromortac
f99e4a3004
Merge pull request #245 from bitromortac/2606-fwd-prep-14
Some checks failed
CI / RPC, mod, imports and compilation check (push) Has been cancelled
CI / Sqlc check (push) Has been cancelled
CI / lint code (push) Has been cancelled
CI / run unit tests (push) Has been cancelled
CI / run unit tests-1 (push) Has been cancelled
CI / run unit tests-2 (push) Has been cancelled
CI / run unit tests-3 (push) Has been cancelled
CI / run unit tests-4 (push) Has been cancelled
chanevents: add channel event pruning
2026-06-25 14:05:09 +02:00
bitromortac
754d660786
docs: document channel event safety pruning flags
Document the new configuration flags in the README, providing rough storage
estimation metrics (~100 bytes per event) to guide database sizing.
2026-06-25 13:53:26 +02:00
bitromortac
c5d7147ab0
itest: add channel events pruning test
Add an integration test to verify the safety pruning behavior under various
conditions.
2026-06-25 13:53:26 +02:00
bitromortac
dccbf53a17
chanevents: add channel event pruning
We add regular channel event pruning, as otherwise the database may get
filled quickly. We add two mechanisms, a retention time and a max events
number. Both can be turned on individually.
2026-06-25 13:53:26 +02:00
bitromortac
e852394bdd
db: add channel event pruning query and index
Add a PruneChannelEvents query that bounds the channel_events table by both
size and age in a single statement: an id-keyset offset enforces a maximum
event count and a timestamp filter enforces a retention window, OR-joined so
each limit applies independently. The query returns the number of rows deleted
so callers can surface pruning activity.

Add a standalone timestamp index so the global age-based prune does not scan
the full table. The existing composite index leads with channel_id and cannot
serve a channel-agnostic timestamp filter.
2026-06-22 10:10:00 +02:00
bitromortac
cc63a340ea
Merge pull request #244 from lightninglabs/faraday-forwarding-ability
Some checks failed
CI / RPC, mod, imports and compilation check (push) Has been cancelled
CI / Sqlc check (push) Has been cancelled
CI / lint code (push) Has been cancelled
CI / run unit tests (push) Has been cancelled
CI / run unit tests-1 (push) Has been cancelled
CI / run unit tests-2 (push) Has been cancelled
CI / run unit tests-3 (push) Has been cancelled
CI / run unit tests-4 (push) Has been cancelled
faraday: merge `ForwardingAbility` feature branch
2026-06-12 19:39:50 +02:00
bitromortac
689cfdd55b
itest: bump lnd to v0.21.0-beta and fix close flakes
Bump the integration test lnd binary to v0.21.0-beta. Two test fixes are
required for the new version:

- nodereport: the anchor commitment close fee changed by 10 sat, update the
  hardcoded CHANNEL_CLOSE_FEE expectation from 4535 to 4525 sat.
- test_context: closeChannel mined a block while still waiting for the pending
  close update, which confirmed the force close tx out of the mempool before
  its fee could be read, causing a 'Transaction not in mempool' failure. Only
  start mining once the close fee has been captured from the mempool.
2026-06-12 11:13:15 +02:00
bitromortac
0402279352
multi: bump lnd and lndclient to v0.21.0
Bump the compile-time lnd dependency to v0.21.0-beta and lndclient to
v0.21.0-1 to not rely on commit hash versions.
2026-06-12 11:13:15 +02:00
bitromortac
90fd2477c1
build: bump Go version to 1.25.10
Update the Go toolchain version across CI, the Dockerfiles and the go.mod
go directives from 1.25.5 to 1.25.10.
2026-06-12 11:13:04 +02:00
bitromortac
edc3a405e6
Merge pull request #243 from bitromortac/2604-fwd-prep-12
rpc: add sparse `ForwardingAbility` endpoint
2026-06-11 12:48:39 +02:00
bitromortac
b19c698f83 itest: add forwarding ability integration test
Open a channel, seed forwarding events with payments, and assert the
ForwardingAbility RPC returns a decodable response whose window matches the
request. Note that we can only simulate forwards back to the same node
because we only have two lnd nodes available in tests.
2026-06-11 12:40:32 +02:00
bitromortac
ec5d4338b9 frcli: add forwardingability command
Add the frcli forwardingability command to query the RPC over a time range
and optional liquidity floor. It decodes the sparse response and prints each
pair with its raw effective uptime and forwarded volume, plus uptime fraction
and velocity derived from the reported window.
2026-06-11 12:40:32 +02:00
bitromortac
e13c5bda9b frdrpcserver: implement ForwardingAbility RPC handler 2026-06-11 12:40:32 +02:00
bitromortac
9d0d198ac6 frdrpc: implement sparse forwarding ability encoder and decoder
Encode the per-pair forwarding abilities into the packed, deduplicated wire
form and decode them back. Only pairs with non-zero effective uptime or
forwarded volume are emitted; the window the metrics cover is carried on the
response so consumers can derive uptime fraction and velocity themselves.
2026-06-11 12:40:32 +02:00
bitromortac
c9fc67a0b5 chanevents: compute forwarding ability over a liquidity floor
Extend the forwarding analyzer to produce a ForwardingAbility per peer pair:
the effective uptime (time the pair held at least the liquidity floor of
directional forwardable liquidity) and the total forwarded amount, both as
raw facts with no derived rates or categories. A single uniform floor is
applied to every pair so effective uptime is comparable across pairs, and
forwarded volume is reported even when uptime is zero so consumers keep the
demand signal.

The percentile threshold model and its quantile helper are removed in favour
of the single floor.
2026-06-09 13:34:34 +02:00
bitromortac
b790949a43 chanevents: paginate forwarding history fetch
Fetch lnd's forwarding history in paginated batches rather than a single
call, so the analysis is not silently truncated at lnd's default page size.
The stub forwarding client returns an empty page for non-zero offsets so the
pagination loop terminates in tests.
2026-06-09 13:15:48 +02:00
bitromortac
6a1710af94 frdrpc: add ForwardingAbility RPC schema
Add the ForwardingAbility RPC that reports, for every (peerIn, peerOut)
pair, the raw forwarding facts over a window: effective uptime in seconds
and forwarded volume in satoshis. The response is a sparse, packed encoding
(deduplicated peer keys plus packed pair indices) carrying only pairs with a
non-zero signal; an absent pair means zero over the window. A single
liquidity_floor_sat request parameter sets the directional liquidity a pair
must hold to count as economically forwardable.
2026-06-09 13:15:48 +02:00
bitromortac
fde9fef5e5 chanevents: bound per-channel event fetch with pagination
loadPeerEvents fetched an entire channel's events in a single
math.MaxInt32-limited query. Page through the store in id-ascending
batches so no single query is unbounded, and document the paging
protocol on the EventsSource contract.
2026-06-09 08:54:55 +02:00
bitromortac
2a8f4fb288
Merge pull request #241 from bitromortac/2604-fwd-prep-11
forwarding ability: add main algo
2026-06-03 18:31:28 +02:00
bitromortac
85f0a261a4 chanevents+db: widen test fixtures to testing.TB
Promote the existing test-store and test-DB constructors from
*testing.T to testing.TB so the upcoming EffectiveUptime benchmark can
share the same fixture path as the existing tests. testing.TB is the
shared interface of *testing.T and *testing.B, so every current caller
keeps type-checking unchanged.
2026-06-03 17:55:30 +02:00
bitromortac
9edc346631 chanevents: add forwarding ability analyzer
Wire EffectiveUptime as the analyzer's public entry. The pipeline
resolves channels to peers from the store, folds lnd's forwarding
history into per-pair success amounts, augments the considered set with
lnd's open and closed channels to hedge survivorship bias, seeds each
channel's state at startTime, and dispatches every peer pair to the
bidirectional walk.

calculateAllPairsUptime walks the unordered cross-product (i, j>=i) with
a lazy per-peer event cache. Each peer's events are fetched once and
replayed across every pair that consumes them. The cached events live as
a slice so the cross-pair merge can use a two-pointer walk instead of an
iter-based merge that would need goroutine plus channel synchronisation
per event.
2026-06-03 17:55:30 +02:00
bitromortac
c4000c9e59 chanevents: add initial-state seeding
Establish the boundary between the chanevents store and the upcoming
forwarding analyzer plus the seed walk every pair calculation depends
on. EventsSource is the read surface the analyzer consumes, and
ForwardingAnalyzer carries it alongside an lnd handle so the upcoming
driver can fold lnd's open and closed channel sets into the considered
population.

getInitialChannelState reconstructs a channel's state at startTime by
seeding from the latest pre-window update and replaying any residual
same-timestamp siblings the SQL keyset may have surfaced. The residual
range is bounded by definition (events between two adjacent timestamps
within a channel), so streaming would buy nothing over materialising
the slice in one call. A guard error flags later-timestamp updates in
the residual walk as schema drift.
2026-06-03 17:55:30 +02:00
bitromortac
b2af1a16ed chanevents: add bidirectional pair walk
The per-pair uptime walk derives forwarding ability for both (A→B) and
(B→A) directions in a single chronological pass over the merged event
stream. Two independent state copies, one rooted at each peer,
accumulate each direction's uptime against its own balance threshold.

A liquidity check that would otherwise be O(channels-per-peer) per tick
becomes O(1) via four running balance sums that shadow each side's
online inbound and outbound capacity. The merge loop adjusts these sums
as events mutate channel state, and the per-tick threshold check reads
the mins inline.
2026-06-03 17:55:30 +02:00
bitromortac
65ef4ab055
Merge pull request #240 from bitromortac/2604-fwd-prep-10
forwarding ability: introduce db helpers
2026-05-13 15:37:06 +02:00
bitromortac
41ce984244 chanevents: add quantile function
Add Quantile, a generic linear-interpolation q-quantile over a slice of
sortable numeric values. The forwarding-ability analyzer needs to
characterise the distribution of historical forwarded amounts and uses a
configurable percentile as the headline statistic; lifting the
computation into its own helper keeps the analyzer focused on forwarding
logic and gives the quantile contract its own table-driven test that
covers the interpolation rule and the empty/out-of-bounds error paths.
2026-05-13 14:44:50 +02:00
bitromortac
be671db05f chanevents: add short-chan-id store lookup
Add GetChannelByShortChanID, the inverse of AddChannel. The
forwarding-ability analyzer receives scids from lnd's forwarding history
and must map them back to the chanevents store's internal channel id to
query events.
2026-05-13 14:32:12 +02:00
bitromortac
2363173325 chanevents+db: add scid-to-peer index
Add ScidToPeerMap, which materialises a snapshot of every short channel
id paired with the pubkey of the channel's remote peer. Forwarding-data
sources index events by short channel id, but downstream analyses need
to attribute behaviour to the peer, not the channel. The map skips
channels whose short channel id is still zero (unconfirmed), so callers
see only fully advertised channels. Coverage extends TestStore with a
two-channel fixture pinning the join.
2026-05-13 14:32:12 +02:00
bitromortac
7431bb5d67 chanevents+db: add latest-event-before lookup
Add GetLatestChannelUpdateBefore, which fetches the most recent
EventTypeUpdate strictly before a given instant. Forwarding-ability
analyses that summarise behaviour over a window must seed their state
from the channel's balance at the window's lower bound; without the
ability to look back past that bound, the first events in the window
have no baseline to compare against. The lookup tolerates missing
predecessors by returning (nil, nil), letting callers distinguish "no
prior update" from a genuine error. Coverage exercises both the present
and absent cases against the existing TestStore fixture.
2026-05-13 14:01:43 +02:00
bitromortac
a568dfedf0
Merge pull request #239 from bitromortac/2604-fwd-prep-9
chanevents: implement GetChannelEvents rpc
2026-05-12 10:09:47 +02:00
bitromortac
f1186409c3 frcli: add chan events command
Adds a `chanevents` subcommand that wraps GetChannelEvents and exposes
chan_point, start/end time, max_events, and last_id flags. The help
text documents the manual pagination contract: keep re-running with
--last_id set to the previous response's last_id until has_more is
false, while leaving --start_time and --end_time fixed across calls.
2026-05-08 20:16:52 +02:00
bitromortac
b0e07dca5f itest: add itest for channel events store
Drives a regtest channel through open, payment, and force-close and
asserts that GetChannelEvents surfaces the expected mix of online,
offline, and balance-update events. The same window is then walked
with a small page size to verify last_id round-trip, has_more
termination, and MaxEvents clamping in one pass.
2026-05-08 20:16:32 +02:00
bitromortac
dc9b6388af frdrpcserver: implement GetChannelEvents
Implements the handler against the chanevents store. A zero end_time
defaults to the server's current wall clock so callers can omit it for
"up to now" queries. max_events is clamped to a 10000-row hard cap that
also serves as the implicit default when the caller leaves the field at
zero. An unknown chan_point maps to NotFound; negative time bounds and
start_time after end_time map to InvalidArgument. The response sets
has_more whenever the page filled to the requested limit so the client
knows to keep paginating.

Also registers the new endpoint in the macaroon permissions table
under the channels:read entitlement.
2026-05-08 20:13:58 +02:00
bitromortac
44bb23186a faraday+frdrpcserver: pass in chan events store
Threads the chanevents.Store the daemon already constructs into the
frdrpcserver.Config so the upcoming GetChannelEvents handler has a
read path. Both standalone and subserver startup wire the same store
instance.
2026-05-08 20:13:58 +02:00
bitromortac
9e10faa805 frdrpc: add GetChannelEvents
Adds the GetChannelEvents RPC to the proto and regenerates the gRPC,
gateway, swagger, and JSON stubs. The request carries a chan_point,
inclusive start_time and exclusive end_time bounds, a max_events cap,
and a last_id keyset cursor; the response echoes last_id and a has_more
flag so callers can drive pagination without server-side state.
2026-05-08 20:13:58 +02:00
bitromortac
c1ada7a4a3 db+chanevents: change to paginated GetChannelEvents
Switches the GetChannelEvents query from a timestamp-ordered scan to an
id-keyset cursor (WHERE id > $cursor ORDER BY id ASC LIMIT $n). The
keyset cursor is stable under concurrent inserts and survives a future
retention job that prunes the oldest rows: a positional OFFSET would
silently skip events whenever rows below the cursor are deleted, while
"id > $cursor" keeps advancing past whatever the caller has already
seen. The id field is documented in the proto as a server-assigned
monotonic identity, so callers persist last_id as their sync watermark.

Adds a (channel_id, id) composite index to back the new query; the
existing (channel_id, timestamp) index does not cover it and would
force a per-channel filter after a global id scan.
2026-05-08 20:13:58 +02:00
bitromortac
629047fcb7 chanevents: add trace logs
Logs every AddChannelEvent at trace level so operators can confirm
which lnd events are being persisted.
2026-05-08 20:13:41 +02:00
bitromortac
26bdf9151b chanevents: export channel error 2026-05-08 20:13:14 +02:00
bitromortac
afadac9d6f
Merge pull request #237 from bitromortac/2604-fwd-prep-8
chanevents+faraday: add chan events store and start
2026-04-08 16:05:32 +02:00
bitromortac
f3a3de9ac4
faraday: start chan events monitor 2026-04-08 15:13:24 +02:00
bitromortac
14d664e93d
faraday: register channel events logger
Also refactor the root logger.
2026-04-08 13:44:22 +02:00
bitromortac
1bd6c5f669
chanevents: add channel event monitor 2026-04-08 13:44:22 +02:00
bitromortac
188163c8dd
faraday: initialize stores 2026-04-02 12:25:36 +02:00
bitromortac
14b4e01731
chanevents: add IsSync 2026-04-02 12:25:36 +02:00
bitromortac
53148c5232
chanevents+db: add sync row
We want to know if an update came from an initial sync. This also helps
us to identify data gaps and one can be sure it was not due to an actual
event. Modify the migration as it's unreleased.
2026-04-02 12:25:36 +02:00
bitromortac
34d84ff937
chanevents: add event comparison test helper
Introduce requireEqualEvent to reduce boilerplate in store tests,
comparing all user-set fields while ignoring the auto-assigned ID.
2026-04-02 12:25:36 +02:00
bitromortac
e0467adbfc
chanevents: add event types
This was forgotten previously.
2026-04-02 12:25:36 +02:00
bitromortac
0af64175a9
Merge pull request #236 from bitromortac/2603-fwd-prep-7
db: implement sql tables and store for channel events
2026-04-02 10:22:04 +02:00
bitromortac
d2df787da6
chanevents: implement store 2026-04-01 15:06:37 +02:00
bitromortac
fcb52aa2b4
github: sqlc check 2026-04-01 15:06:37 +02:00
bitromortac
3157dbc870
db: add chanevents tables and queries 2026-04-01 15:06:37 +02:00