Commit Graph

322 Commits

Author SHA1 Message Date
Elle Mouton
d1fa5701eb graph/db: thread context through to DeleteLightningNode 2025-06-17 19:20:59 +02:00
Elle Mouton
dc6259fcc3 graph/db: thread context through to HasLightningNode 2025-06-17 19:20:56 +02:00
Elle Mouton
66c5a97202 graph/db: thread context through to FetchLightingNode 2025-06-17 19:20:27 +02:00
Elle Mouton
d1cfb47428 graph/db: thread context to AddLightningNode 2025-06-17 19:20:27 +02:00
Oliver Gugger
c1740c14ba Merge pull request #9887 from ellemouton/graphSQL9-chan-policies-schema
graph/db+sqldb: channel policy SQL schemas, queries and upsert CRUD
2025-06-17 16:30:23 +02:00
Elle Mouton
c327988bb3 graph/db+sqldb: implement UpdateEdgePolicy
In this commit, the various SQL queries are defined that we will need in
order to implement the SQLStore UpdateEdgePolicy method. Channel
policies can be "replaced" and so we use the upsert pattern for them
with the rule that any new channel policy must have a timestamp greater
than the previous one we persisted.

As is done for the KVStore implementation of the method, we use the
batch scheduler for this method.
2025-06-17 13:43:07 +02:00
yyforyongyu
46c5715ae5 graph: fix nil pointer deference in ForEachChannelCacheable 2025-06-16 12:02:24 +08:00
Elle Mouton
498a18d028 graph/db: provide SQLStore with chainhash
In this commit, we introduce a SQLStoreConfig struct which for the time
being only has the ChainHash of the genesis block of the chain this node
is running on. This is used to reconstruct lnwire messages from what we
have persisted in the DB. This means we dont need need to persist the
chain-hash of gossip messages since we know it will always be the same
for a given node. If a node were to be started with a different network,
the lnwire messages it reconstructs for gossip will be invalid.
2025-06-12 07:16:18 +02:00
Elle Mouton
c52c6c962b graph/db: introduce ForEachChannelCacheable
Implement ForEachChannelCacheable which is like ForEachChannel but its
call-back takes the cached versions of channel info & policies. This is
then used during graph cache population. This will be useful once the
SQL implementation is added so that we can reduce the number of DB trips
on cache population.
2025-06-10 20:10:36 +02:00
Elle Mouton
3069a67b62 graph/db: let GraghCache.AddChannel take CachedEdgeInfo
Define a new CachedEdgeInfo type and let the graph cache's AddChannel
use this. This will let us later on (for the SQL impl of the graph db)
only load from the DB what we actually need for the graph cache.
2025-06-10 20:10:35 +02:00
Elle Mouton
3ea86bfbf4 graph/db: let GraphCache.AddChannel take cached edge polies
So that the call-sites of this method dont necessarily need to fetch all
the data required to populate the full ChannelEdgePolicy.
2025-06-10 20:10:35 +02:00
Elle Mouton
f95588caca graph/db: add CachedEdgePolicy helpers 2025-06-10 20:10:35 +02:00
Elle Mouton
42c6e951ed graph/db: let GraphCache.UpdatePolicy take a cached policy
Update the GraphCache.UpdatePolicy method to take a
`models.CachedEdgePolicy` instead of a `models.ChannelEdgePolicy`.
Doing this will allow us later on to only fetch the necessary info for
populating the CachedEdgePolicy when we are populating the cache via
UpdatePolicy.
2025-06-10 20:10:35 +02:00
Elle Mouton
0816645328 graph/db: simplify GraphCache.UpdatePolicy signature
Remove the redundant "edge2" param and rather use the "policy" param to
derive the boolean.
2025-06-10 20:10:35 +02:00
Elle Mouton
2e716bf301 graph/db: remove unused GraphCache method
Remove the unused UpdateChannel method.
2025-06-10 20:10:34 +02:00
Elle Mouton
6d8bc63ad6 discovery+graph: get inbound fee directly from ChannelUpdate
Remove the previously added TODOs which would extract InboundFee info
from the ExtraOpaqueData of a ChannelUpdate at the time of
ChannelEdgePolicy construction. These can now be replaced by using the
newly added InboundFee record on the ChannelUpdate message.
2025-06-09 08:44:47 +02:00
Elle Mouton
bf72d9ec19 graph+rpcserver: add InboundFee to ChannelEdgeUpdate
And then use that new field instead of parsing from extra opaque data.
2025-06-09 08:32:15 +02:00
Elle Mouton
cb16c7177a graph/db: use InboundFee directly from ChannelEdgePolicy
Now that we know that the InboundFee on the ChannelEdgePolicy is always
set appropriately, we can update the GraphCache UpdatePolicy method to
take the InboundFee directly from the ChannelEdgePolicy object.
2025-06-09 08:31:19 +02:00
Elle Mouton
9890d74622 multi: set the InboundFee on ChannelEdgePolicy
In this commit, we make sure to set the new field wherever appropriate.
This will be any place where the ChannelEdgePolicy is constructed other
than its disk deserialisation.
2025-06-09 08:31:10 +02:00
Elle Mouton
e170ad44d9 graph/db+rpcserver: remove inbound fee extraction
For any call-site where we extract inbound fees from a
models.ChannelEdgePolicy object that was deserialised from disk, we can
now just use the new InboundFee field on the object since we know that
it would have been populated at deserialisation time.

Note that for all these call-sites, if a failure previously happened on
decoding of the TLV stream, the error would be ignored and the edge
would just be skipped. This behaviour is now still the same given how
ErrParsingExtraTLVBytes is handled on the DB layer.
2025-06-09 08:28:50 +02:00
Elle Mouton
8314bacdda graph/db: extract InboundFee at deserialisation time
Here we add an explicit InboundFee field to the ChannelEdgePolicy
struct. Then, in the graph KVStore, at deserialisation time, we extract
the InboundFee from the ExtraOpaqueData. Currently we do this at higher
levels but we are going to move it to the DB layer so that when we add
the SQL implementation of the graph store, we can have explicit columns
for inbound fees. We need to account for the fact that we may have
invalid TLV already persisted though and we dont want to fail if we
deserialise those necessarily. So we return ErrParsingExtraTLVBytes now
if we fail to parse the extra bytes as TLV and then we let the callers
handle it similarly to how ErrParsingExtraTLVBytes is handled in that we
dont necessarily fail if we receive one of these errors.

As of this commit, we can now expect the InboundFee field of a
ChannelEdgePolicy to be set (if inbound fees are set on the policy) for
any update that we read from disk.
2025-06-09 08:26:33 +02:00
Elle Mouton
239acb4063 graph/db: validate edge policy TLV data before persisting
In this commit, we start validating the extra opaque data of a channel
edge policy before persisting it. We just check that the data is valid
TLV.

NOTE: we recently [started
validating](1410a0949d)
this at the lnwire level. So really, no new update will reach the DB
layer without this already being checked. But we check it again here so
that the DB API behaves correctly as its own unit.
2025-06-09 08:26:11 +02:00
Elle Mouton
547b836180 sqldb+graph/db: fix UpsertNode bug
Account for the last_update field being null.
2025-06-02 17:29:03 +02:00
Elle Mouton
eb32b39380 graph/db: demonstrate SQL upsert node bug 2025-06-02 17:28:59 +02:00
Elle Mouton
cf542458bd graph/db+sqldb: add HighestChanID to SQLStore 2025-06-02 14:53:18 +02:00
Elle Mouton
d93d104a66 graph/db+sqldb: implement AddChannelEdge on SQLStore
In this commit, the `AddChannelEdge` method of the SQLStore is
implemented. Like the KVStore implementation, it makes use of the
available channel `batch.Scheduler` and also updates the reject and
channel caches.

This then lets us convert the following 2 unit tests to run against the
SQL backends:
- TestPartialNode
- TestAddChannelEdgeShellNodes
2025-06-02 14:53:18 +02:00
Elle Mouton
c5f159f485 graph/db: expand AddChannelEdge test
Expand the existing TestAddChannelEdgeShellNodes test so that we have
coverage for error we expect when AddChannelEdge is called a second time
if we already know of a channel.
2025-06-02 14:53:18 +02:00
Elle Mouton
2a36e17f6f graph/db: only init extra byte if not nil
In preparation for having consistency with the structs created by the
SQLStore and the KVStore (so that they have the same behaviour when
tested by the unit tests), here we make sure not to init the
ExtraOpaqueData field of the LightningNode struct unless there are
actualy bytes to set.
2025-06-02 14:53:18 +02:00
Elle Mouton
9cbc1f804e multi: use sqldb.NoOpReset helper
Define a re-usable "reset" function, sqldb.NoOpReset, that can be used
for the reset parameter in sql ExecTx calls.
2025-05-28 10:18:53 +02:00
Elle Mouton
c4e6f23c5b multi: add a re-usable TxOptions type
Add a re-usable implementation of the sqldb.TxOptions interface and make
use of this in the various spots (invoices, batch and graph/db) where we
had previously defined individual implementations that were all doing
the same thing.
2025-05-28 10:18:10 +02:00
Elle Mouton
0064d33cda sqldb+graph/db: source nodes table, queries and CRUD
In this commit, we add the `source_nodes` table. It points to entries in
the `nodes` table. This table will store one entry per protocol version
that we are announcing a node_announcement on.

With this commit, we can run the TestSourceNode unit test against our
SQL backends.
2025-05-27 18:36:59 +02:00
Elle Mouton
86d48390ca sqldb+graph/db: implement SQLStore.NodeUpdatesInHorizon
In this commit we add the necessary SQL queries and then implement the
SQLStore's NodeUpdatesInHorizon method. This lets us run the
TestNodeUpdatesInHorizon unit tests against SQL backends.
2025-05-27 18:36:59 +02:00
Elle Mouton
7a120cb584 graph/db: implement SQLStore.LookupAlias
In this commit, we let the SQLStore implement LookupAlias. This then
lets us run the TestAliasLookup unit test against the SQL backends.
2025-05-27 18:36:59 +02:00
Elle Mouton
d1f7cce68b sqldb+graphdb: SQL methods for Node CRUD
In this commit, we add the various sqlc queries that we need in order
to implement the following V1Store methods:

- AddLightningNode
- FetchLightningNode
- HasLightningNode
- AddrsForNode
- DeleteLightningNode
- FetchNodeFeatures

These are implemented by SQLStore which then lets us use the SQLStore
backend for the following unit tests:

- TestNodeInsertionAndDeletion
- TestLightningNodePersistence
2025-05-27 18:36:59 +02:00
Elle Mouton
3b449820d2 graph/db: init SQLStore caches and batch schedulers
Here, we use the new options to initialise the reject and channel caches
for the SQLStore (as is done for the KVStore) and also the channel and
node batch schedulers.
2025-05-23 11:05:39 +02:00
Elle Mouton
149e1c7d35 graph/db: add StoreOptions to NewSQLStore 2025-05-23 11:05:36 +02:00
Elle Mouton
a0a20bd0d0 graph/db: rename KVStoreOptions to StoreOptions
We'll re-use this options struct for our SQLStore too. So here we rename
it to be more generic.
2025-05-23 11:01:17 +02:00
Elle Mouton
14ca086c72 graph/db: skip TestGraphLoading for non-bbolt store
Let all the NewTestDB functions return the V1Store interface type
instead of pointers. Then add a manual skip in the TestGraphLoading test
for any non-bbolt backend. We can remove this once all the methods used
by the test have been implemented by the SQLStore. We only need the
manual skip for this one test since it is the only one that doesnt use
MakeGraphTest to init the graph db.
2025-05-23 10:53:27 +02:00
Elle Mouton
df1e6da94e batch: update to allow for read-only calls
In this commit, we update the batch schedular so that it has the ability
to do read-only calls. It will do a best effort attempt at keeping a
transaction in read-only mode and then if any requests get added to a
batch that require a read-write tx, then the entire batch's tx will be
upgraded to use a read-write tx.
2025-05-22 14:14:43 +02:00
Elle Mouton
f5a466b051 batch+graph: update batch.Schedular to be generic
In preparation for using the same logic for non-bbolt backends, we adapt
the batch.Schedular to be more generic.

The only user of the scheduler at the moment is the KVStore in the
`graph.db` package. This store instantiates the bbolt implementation of
the scheduler.
2025-05-22 14:14:42 +02:00
Elle Mouton
9b9a964975 graph/db: more test coverage for node addresses
In this commit we add more test coverage for the persistence of the
addresses of a LightningNode. This is so that we have unit test coverage
that ensures that all the various address types can be persisted and
that the order of the addresses (within a type) are preserved.
2025-05-22 14:14:42 +02:00
Elle Mouton
629e74a53c graph/db: add various error assertions
Here we expand TestEdgeInsertionDeletion to assert that the expected
error is returned when AddChannelEdge is called for a channel that has
already been persisted. We also take the opportunity to convert some of
the error checks in the test to use strict error type matching.

Finally, we test that the expected error is returned if
DeleteLightningNode is called for a node that is no longer in the DB.
2025-05-22 14:14:42 +02:00
Elle Mouton
3bc58a0d2f graph/db: test the non-cached version of ForEachNodeDirectedChannel
Expand an existing test for ForEachNodeDirectedChannel so that it also
tests the DB method and not just the ChannelGraph method which will use
the in-memory graph cache for the query.
2025-05-22 14:14:42 +02:00
Elle Mouton
b4121acb1f graph/db: add a framework for testing against SQL backends incrementally
In this commit, we implement the postgres and sqlite versions of the
NewTestDB function. We add the various build flags so that only one of
the three versions of this function can be active at a time.

We also introduce the SQLStore struct which is the SQL implementation of
the V1Store interface.

NOTE: it currently temporarily embeds the KVStore struct so that we can
implement the V1Store interface incrementally. For any method not
implemented, things will fall back to the KVStore. This is ONLY the
case for the time being while this struct is purely used in unit tests
only. Once all the methods have been implemented, the KVStore field will
be removed from the SQLStore struct.
2025-05-22 14:14:42 +02:00
Elle Mouton
b285546ce1 graph/db: add NewTestDB method
In this commit, we add a `test_kvdb.go` file with a single definition of
the `NewTestDB` function. A new version of `MakeTestGraph` (called
`MakeTestGraphNew` is added which makes use of this `NewTestDB` function
to create the backing `V1Store` passed to the `ChannelGraph` for tests.

Later on, we will add new implementations of this method backed by
sqlite and postgres.  When those are added, then build flags will
control which version of `NewTestDB` is called.

With this change, the only test call-site of `NewKVStore` is the new
`test_kvdb.go` file.
2025-05-22 14:14:42 +02:00
Elle Mouton
dc353dc50e multi: use MakeTestGraph everywhere for test graph creation
In this commit, we unify how all unit tests that make use of the graph
create their test ChannelGraph instance. This will make it easier to
ensure that once we plug in different graph DB implementations, that all
unit tests are run against all variants of the graph DB.

With this commit, `NewChannelGraph` is mainly only called via
`MakeTestGraph` for all tests _except_ for `TestGraphLoading` which
needs to be able to reload a ChannelGraph with the same backend. This
will be addressed in a follow-up commit once more helpers are defined.

Note that in all previous packages where we created a test graph using
`kvdb.GetBoltBackend`, we now need to add a `TestMain` function with a
call to `kvdb.RunTest` since the `MakeTestGraph` helper uses
`GetTestBackend` instead of `kvdb.GetBoltBackend` which requires an
embedded postgres instance to be running.
2025-05-22 14:14:42 +02:00
Elle Mouton
7a348e324d graph/db: let MakeTestGraph take ChanGraphOptions
Currently none of the calls to MakeTestGraph make use of the
KVStoreOptionModifier options but later on we will want to make use of
the `WithUseGraphCache` ChannelGraphOption and so we take this
opportunity to switch out the functional parameters that the helper
function takes.
2025-05-22 14:14:42 +02:00
Elle Mouton
4233649e6a graph/db: let MakeTestGraph require no error internally
Instead of returning an error and needing to call `require.NoError` for
each call to `MakeTestGraph`, rather just used the available testing
variable to require no error within the function itself.
2025-05-22 14:14:41 +02:00
Elle Mouton
44a92b7efe graph/db: add test coverage for AddEdgeProof 2025-05-22 14:14:41 +02:00
Elle Mouton
3dfc1725d8 graph/db: use mainnet genisis hash in tests
In preparation for our SQL Graph store which wont explicitly store the
chain hash but will instead obtain it from the runtime config, we
replace the test chainhash value with that of the mainnet genesis hash.
2025-05-22 14:14:41 +02:00