Merge pull request #10572 from ellemouton/g175-db-7
[g175] graph/db: add gossip-version plumbing for core graph APIs
This commit is contained in:
16 files changed
+919
-476
No files matched your search
@@ -73,12 +73,12 @@ type ChannelGraphTimeSeries interface {
|
|||||||
// in-protocol channel range queries to quickly and efficiently synchronize our
|
// in-protocol channel range queries to quickly and efficiently synchronize our
|
||||||
// channel state with all peers.
|
// channel state with all peers.
|
||||||
type ChanSeries struct {
|
type ChanSeries struct {
|
||||||
graph *graphdb.ChannelGraph
|
graph *graphdb.VersionedGraph
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChanSeries constructs a new ChanSeries backed by a channeldb.ChannelGraph.
|
// NewChanSeries constructs a new ChanSeries backed by a channeldb.ChannelGraph.
|
||||||
// The returned ChanSeries implements the ChannelGraphTimeSeries interface.
|
// The returned ChanSeries implements the ChannelGraphTimeSeries interface.
|
||||||
func NewChanSeries(graph *graphdb.ChannelGraph) *ChanSeries {
|
func NewChanSeries(graph *graphdb.VersionedGraph) *ChanSeries {
|
||||||
return &ChanSeries{
|
return &ChanSeries{
|
||||||
graph: graph,
|
graph: graph,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,8 @@
|
|||||||
nodes and channels [1](https://github.com/lightningnetwork/lnd/pull/10339)
|
nodes and channels [1](https://github.com/lightningnetwork/lnd/pull/10339)
|
||||||
[2](https://github.com/lightningnetwork/lnd/pull/10379)
|
[2](https://github.com/lightningnetwork/lnd/pull/10379)
|
||||||
[3](https://github.com/lightningnetwork/lnd/pull/10380)
|
[3](https://github.com/lightningnetwork/lnd/pull/10380)
|
||||||
[4](https://github.com/lightningnetwork/lnd/pull/10542).
|
[4](https://github.com/lightningnetwork/lnd/pull/10542),
|
||||||
|
[5](https://github.com/lightningnetwork/lnd/pull/10572).
|
||||||
|
|
||||||
## Code Health
|
## Code Health
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -573,13 +573,15 @@ func (b *Builder) pruneZombieChans() error {
|
|||||||
// both edges. If they're both disabled, then we can interpret this as
|
// both edges. If they're both disabled, then we can interpret this as
|
||||||
// the channel being closed and can prune it from our graph.
|
// the channel being closed and can prune it from our graph.
|
||||||
if b.cfg.AssumeChannelValid {
|
if b.cfg.AssumeChannelValid {
|
||||||
disabledChanIDs, err := b.cfg.Graph.DisabledChannelIDs()
|
disabledChanIDs, err := b.cfg.Graph.DisabledChannelIDs(
|
||||||
|
lnwire.GossipVersion1,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get disabled channels "+
|
return fmt.Errorf("unable to get disabled channels "+
|
||||||
"ids chans: %v", err)
|
"ids chans: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
disabledEdges, err := b.cfg.Graph.FetchChanInfos(
|
disabledEdges, err := b.v1Graph.FetchChanInfos(
|
||||||
disabledChanIDs,
|
disabledChanIDs,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -669,7 +669,8 @@ func BenchmarkGraphReadMethods(b *testing.B) {
|
|||||||
name: "ForEachNodeCacheable",
|
name: "ForEachNodeCacheable",
|
||||||
fn: func(b testing.TB, store Store) {
|
fn: func(b testing.TB, store Store) {
|
||||||
err := store.ForEachNodeCacheable(
|
err := store.ForEachNodeCacheable(
|
||||||
ctx, func(_ route.Vertex,
|
ctx, lnwire.GossipVersion1,
|
||||||
|
func(_ route.Vertex,
|
||||||
_ *lnwire.FeatureVector) error {
|
_ *lnwire.FeatureVector) error {
|
||||||
|
|
||||||
// Increment the counter to
|
// Increment the counter to
|
||||||
|
|||||||
+34
-10
@@ -1,11 +1,20 @@
|
|||||||
package graphdb
|
package graphdb
|
||||||
|
|
||||||
|
import "github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
|
||||||
|
// channelCacheKey uniquely identifies a channel entry in the channel cache by
|
||||||
|
// gossip version and channel ID.
|
||||||
|
type channelCacheKey struct {
|
||||||
|
version lnwire.GossipVersion
|
||||||
|
chanID uint64
|
||||||
|
}
|
||||||
|
|
||||||
// channelCache is an in-memory cache used to improve the performance of
|
// channelCache is an in-memory cache used to improve the performance of
|
||||||
// ChanUpdatesInHorizon. It caches the chan info and edge policies for a
|
// ChanUpdatesInHorizon. It caches the chan info and edge policies for a
|
||||||
// particular channel.
|
// particular channel.
|
||||||
type channelCache struct {
|
type channelCache struct {
|
||||||
n int
|
n int
|
||||||
channels map[uint64]ChannelEdge
|
channels map[channelCacheKey]ChannelEdge
|
||||||
}
|
}
|
||||||
|
|
||||||
// newChannelCache creates a new channelCache with maximum capacity of n
|
// newChannelCache creates a new channelCache with maximum capacity of n
|
||||||
@@ -13,13 +22,18 @@ type channelCache struct {
|
|||||||
func newChannelCache(n int) *channelCache {
|
func newChannelCache(n int) *channelCache {
|
||||||
return &channelCache{
|
return &channelCache{
|
||||||
n: n,
|
n: n,
|
||||||
channels: make(map[uint64]ChannelEdge),
|
channels: make(map[channelCacheKey]ChannelEdge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get returns the channel from the cache, if it exists.
|
// get returns the channel from the cache, if it exists.
|
||||||
func (c *channelCache) get(chanid uint64) (ChannelEdge, bool) {
|
func (c *channelCache) get(version lnwire.GossipVersion,
|
||||||
channel, ok := c.channels[chanid]
|
chanid uint64) (ChannelEdge, bool) {
|
||||||
|
|
||||||
|
channel, ok := c.channels[channelCacheKey{
|
||||||
|
version: version,
|
||||||
|
chanID: chanid,
|
||||||
|
}]
|
||||||
return channel, ok
|
return channel, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,10 +41,17 @@ func (c *channelCache) get(chanid uint64) (ChannelEdge, bool) {
|
|||||||
// exists, it will be replaced with the new entry. If the entry doesn't exist,
|
// exists, it will be replaced with the new entry. If the entry doesn't exist,
|
||||||
// it will be inserted to the cache, performing a random eviction if the cache
|
// it will be inserted to the cache, performing a random eviction if the cache
|
||||||
// is at capacity.
|
// is at capacity.
|
||||||
func (c *channelCache) insert(chanid uint64, channel ChannelEdge) {
|
func (c *channelCache) insert(version lnwire.GossipVersion, chanid uint64,
|
||||||
|
channel ChannelEdge) {
|
||||||
|
|
||||||
|
key := channelCacheKey{
|
||||||
|
version: version,
|
||||||
|
chanID: chanid,
|
||||||
|
}
|
||||||
|
|
||||||
// If entry exists, replace it.
|
// If entry exists, replace it.
|
||||||
if _, ok := c.channels[chanid]; ok {
|
if _, ok := c.channels[key]; ok {
|
||||||
c.channels[chanid] = channel
|
c.channels[key] = channel
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,10 +62,13 @@ func (c *channelCache) insert(chanid uint64, channel ChannelEdge) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.channels[chanid] = channel
|
c.channels[key] = channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove deletes an edge for chanid from the cache, if it exists.
|
// remove deletes an edge for chanid from the cache, if it exists.
|
||||||
func (c *channelCache) remove(chanid uint64) {
|
func (c *channelCache) remove(version lnwire.GossipVersion, chanid uint64) {
|
||||||
delete(c.channels, chanid)
|
delete(c.channels, channelCacheKey{
|
||||||
|
version: version,
|
||||||
|
chanID: chanid,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,37 +15,39 @@ import (
|
|||||||
func TestChannelCache(t *testing.T) {
|
func TestChannelCache(t *testing.T) {
|
||||||
const cacheSize = 100
|
const cacheSize = 100
|
||||||
|
|
||||||
|
v := lnwire.GossipVersion1
|
||||||
|
|
||||||
// Create a new channel cache with the configured max size.
|
// Create a new channel cache with the configured max size.
|
||||||
c := newChannelCache(cacheSize)
|
c := newChannelCache(cacheSize)
|
||||||
|
|
||||||
// As a sanity check, assert that querying the empty cache does not
|
// As a sanity check, assert that querying the empty cache does not
|
||||||
// return an entry.
|
// return an entry.
|
||||||
_, ok := c.get(0)
|
_, ok := c.get(v, 0)
|
||||||
if ok {
|
if ok {
|
||||||
t.Fatalf("channel cache should be empty")
|
t.Fatalf("channel cache should be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, fill up the cache entirely.
|
// Now, fill up the cache entirely.
|
||||||
for i := uint64(0); i < cacheSize; i++ {
|
for i := uint64(0); i < cacheSize; i++ {
|
||||||
c.insert(i, channelForInt(i))
|
c.insert(v, i, channelForInt(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that the cache has all of the entries just inserted, since no
|
// Assert that the cache has all of the entries just inserted, since no
|
||||||
// eviction should occur until we try to surpass the max size.
|
// eviction should occur until we try to surpass the max size.
|
||||||
assertHasChanEntries(t, c, 0, cacheSize)
|
assertHasChanEntries(t, c, v, 0, cacheSize)
|
||||||
|
|
||||||
// Now, insert a new element that causes the cache to evict an element.
|
// Now, insert a new element that causes the cache to evict an element.
|
||||||
c.insert(cacheSize, channelForInt(cacheSize))
|
c.insert(v, cacheSize, channelForInt(cacheSize))
|
||||||
|
|
||||||
// Assert that the cache has this last entry, as the cache should evict
|
// Assert that the cache has this last entry, as the cache should evict
|
||||||
// some prior element and not the newly inserted one.
|
// some prior element and not the newly inserted one.
|
||||||
assertHasChanEntries(t, c, cacheSize, cacheSize)
|
assertHasChanEntries(t, c, v, cacheSize, cacheSize)
|
||||||
|
|
||||||
// Iterate over all inserted elements and construct a set of the evicted
|
// Iterate over all inserted elements and construct a set of the evicted
|
||||||
// elements.
|
// elements.
|
||||||
evicted := make(map[uint64]struct{})
|
evicted := make(map[uint64]struct{})
|
||||||
for i := uint64(0); i < cacheSize+1; i++ {
|
for i := uint64(0); i < cacheSize+1; i++ {
|
||||||
_, ok := c.get(i)
|
_, ok := c.get(v, i)
|
||||||
if !ok {
|
if !ok {
|
||||||
evicted[i] = struct{}{}
|
evicted[i] = struct{}{}
|
||||||
}
|
}
|
||||||
@@ -58,35 +61,37 @@ func TestChannelCache(t *testing.T) {
|
|||||||
|
|
||||||
// Remove the highest item which initially caused the eviction and
|
// Remove the highest item which initially caused the eviction and
|
||||||
// reinsert the element that was evicted prior.
|
// reinsert the element that was evicted prior.
|
||||||
c.remove(cacheSize)
|
c.remove(v, cacheSize)
|
||||||
for i := range evicted {
|
for i := range evicted {
|
||||||
c.insert(i, channelForInt(i))
|
c.insert(v, i, channelForInt(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since the removal created an extra slot, the last insertion should
|
// Since the removal created an extra slot, the last insertion should
|
||||||
// not have caused an eviction and the entries for all channels in the
|
// not have caused an eviction and the entries for all channels in the
|
||||||
// original set that filled the cache should be present.
|
// original set that filled the cache should be present.
|
||||||
assertHasChanEntries(t, c, 0, cacheSize)
|
assertHasChanEntries(t, c, v, 0, cacheSize)
|
||||||
|
|
||||||
// Finally, reinsert the existing set back into the cache and test that
|
// Finally, reinsert the existing set back into the cache and test that
|
||||||
// the cache still has all the entries. If the randomized eviction were
|
// the cache still has all the entries. If the randomized eviction were
|
||||||
// happening on inserts for existing cache items, we expect this to fail
|
// happening on inserts for existing cache items, we expect this to fail
|
||||||
// with high probability.
|
// with high probability.
|
||||||
for i := uint64(0); i < cacheSize; i++ {
|
for i := uint64(0); i < cacheSize; i++ {
|
||||||
c.insert(i, channelForInt(i))
|
c.insert(v, i, channelForInt(i))
|
||||||
}
|
}
|
||||||
assertHasChanEntries(t, c, 0, cacheSize)
|
assertHasChanEntries(t, c, v, 0, cacheSize)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// assertHasEntries queries the edge cache for all channels in the range [start,
|
// assertHasEntries queries the edge cache for all channels in the range [start,
|
||||||
// end), asserting that they exist and their value matches the entry produced by
|
// end), asserting that they exist and their value matches the entry produced by
|
||||||
// entryForInt.
|
// entryForInt.
|
||||||
func assertHasChanEntries(t *testing.T, c *channelCache, start, end uint64) {
|
func assertHasChanEntries(t *testing.T, c *channelCache,
|
||||||
|
v lnwire.GossipVersion, start, end uint64) {
|
||||||
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
for i := start; i < end; i++ {
|
for i := start; i < end; i++ {
|
||||||
entry, ok := c.get(i)
|
entry, ok := c.get(v, i)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("channel cache should contain chan %d", i)
|
t.Fatalf("channel cache should contain chan %d", i)
|
||||||
}
|
}
|
||||||
|
|||||||
+99
-49
@@ -163,28 +163,42 @@ func (c *ChannelGraph) populateCache(ctx context.Context) error {
|
|||||||
log.Info("Populating in-memory channel graph, this might take a " +
|
log.Info("Populating in-memory channel graph, this might take a " +
|
||||||
"while...")
|
"while...")
|
||||||
|
|
||||||
err := c.db.ForEachNodeCacheable(ctx, func(node route.Vertex,
|
for _, v := range []lnwire.GossipVersion{
|
||||||
features *lnwire.FeatureVector) error {
|
gossipV1, gossipV2,
|
||||||
|
} {
|
||||||
|
// TODO(elle): If we have both v1 and v2 entries for the same
|
||||||
|
// node/channel, prefer v2 when merging.
|
||||||
|
err := c.db.ForEachNodeCacheable(ctx, v,
|
||||||
|
func(node route.Vertex,
|
||||||
|
features *lnwire.FeatureVector) error {
|
||||||
|
|
||||||
c.graphCache.AddNodeFeatures(node, features)
|
c.graphCache.AddNodeFeatures(node, features)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, func() {})
|
}, func() {},
|
||||||
if err != nil {
|
)
|
||||||
return err
|
if err != nil && !errors.Is(
|
||||||
}
|
err, ErrVersionNotSupportedForKVDB,
|
||||||
|
) {
|
||||||
|
|
||||||
err = c.db.ForEachChannelCacheable(
|
return err
|
||||||
func(info *models.CachedEdgeInfo,
|
}
|
||||||
policy1, policy2 *models.CachedEdgePolicy) error {
|
|
||||||
|
|
||||||
c.graphCache.AddChannel(info, policy1, policy2)
|
err = c.db.ForEachChannelCacheable(
|
||||||
|
v, func(info *models.CachedEdgeInfo,
|
||||||
|
policy1,
|
||||||
|
policy2 *models.CachedEdgePolicy) error {
|
||||||
|
|
||||||
return nil
|
c.graphCache.AddChannel(info, policy1, policy2)
|
||||||
}, func() {},
|
|
||||||
)
|
return nil
|
||||||
if err != nil {
|
}, func() {},
|
||||||
return err
|
)
|
||||||
|
if err != nil &&
|
||||||
|
!errors.Is(err, ErrVersionNotSupportedForKVDB) {
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Finished populating in-memory channel graph (took %v, %s)",
|
log.Infof("Finished populating in-memory channel graph (took %v, %s)",
|
||||||
@@ -210,7 +224,10 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(node route.Vertex,
|
|||||||
return c.graphCache.ForEachChannel(node, cb)
|
return c.graphCache.ForEachChannel(node, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.db.ForEachNodeDirectedChannel(node, cb, reset)
|
// TODO(elle): once the no-cache path needs to support
|
||||||
|
// pathfinding across gossip versions, this should iterate
|
||||||
|
// across all versions rather than defaulting to v1.
|
||||||
|
return c.db.ForEachNodeDirectedChannel(gossipV1, node, cb, reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchNodeFeatures returns the features of the given node. If no features are
|
// FetchNodeFeatures returns the features of the given node. If no features are
|
||||||
@@ -332,7 +349,9 @@ func (c *ChannelGraph) MarkEdgeLive(chanID uint64) error {
|
|||||||
if c.graphCache != nil {
|
if c.graphCache != nil {
|
||||||
// We need to add the channel back into our graph cache,
|
// We need to add the channel back into our graph cache,
|
||||||
// otherwise we won't use it for path finding.
|
// otherwise we won't use it for path finding.
|
||||||
infos, err := c.db.FetchChanInfos([]uint64{chanID})
|
infos, err := c.db.FetchChanInfos(
|
||||||
|
lnwire.GossipVersion1, []uint64{chanID},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -587,14 +606,6 @@ func (c *ChannelGraph) UpdateEdgePolicy(ctx context.Context,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEachSourceNodeChannel iterates through all channels of the source node.
|
|
||||||
func (c *ChannelGraph) ForEachSourceNodeChannel(ctx context.Context,
|
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
|
||||||
otherNode *models.Node) error, reset func()) error {
|
|
||||||
|
|
||||||
return c.db.ForEachSourceNodeChannel(ctx, cb, reset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForEachNodeChannel iterates through all channels of the given node.
|
// ForEachNodeChannel iterates through all channels of the given node.
|
||||||
func (c *ChannelGraph) ForEachNodeChannel(ctx context.Context,
|
func (c *ChannelGraph) ForEachNodeChannel(ctx context.Context,
|
||||||
v lnwire.GossipVersion, nodePub route.Vertex,
|
v lnwire.GossipVersion, nodePub route.Vertex,
|
||||||
@@ -614,10 +625,10 @@ func (c *ChannelGraph) ForEachNode(ctx context.Context,
|
|||||||
|
|
||||||
// ForEachNodeCacheable iterates through all stored vertices/nodes in the graph.
|
// ForEachNodeCacheable iterates through all stored vertices/nodes in the graph.
|
||||||
func (c *ChannelGraph) ForEachNodeCacheable(ctx context.Context,
|
func (c *ChannelGraph) ForEachNodeCacheable(ctx context.Context,
|
||||||
cb func(route.Vertex, *lnwire.FeatureVector) error,
|
v lnwire.GossipVersion, cb func(route.Vertex,
|
||||||
reset func()) error {
|
*lnwire.FeatureVector) error, reset func()) error {
|
||||||
|
|
||||||
return c.db.ForEachNodeCacheable(ctx, cb, reset)
|
return c.db.ForEachNodeCacheable(ctx, v, cb, reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeUpdatesInHorizon returns all known lightning nodes with updates in the
|
// NodeUpdatesInHorizon returns all known lightning nodes with updates in the
|
||||||
@@ -650,17 +661,11 @@ func (c *ChannelGraph) ForEachChannel(ctx context.Context,
|
|||||||
return c.db.ForEachChannel(ctx, v, cb, reset)
|
return c.db.ForEachChannel(ctx, v, cb, reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEachChannelCacheable iterates through all channel edges for the cache.
|
|
||||||
func (c *ChannelGraph) ForEachChannelCacheable(cb func(*models.CachedEdgeInfo,
|
|
||||||
*models.CachedEdgePolicy, *models.CachedEdgePolicy) error,
|
|
||||||
reset func()) error {
|
|
||||||
|
|
||||||
return c.db.ForEachChannelCacheable(cb, reset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisabledChannelIDs returns the channel ids of disabled channels.
|
// DisabledChannelIDs returns the channel ids of disabled channels.
|
||||||
func (c *ChannelGraph) DisabledChannelIDs() ([]uint64, error) {
|
func (c *ChannelGraph) DisabledChannelIDs(v lnwire.GossipVersion) (
|
||||||
return c.db.DisabledChannelIDs()
|
[]uint64, error) {
|
||||||
|
|
||||||
|
return c.db.DisabledChannelIDs(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasV1ChannelEdge returns true if the database knows of a channel edge.
|
// HasV1ChannelEdge returns true if the database knows of a channel edge.
|
||||||
@@ -684,14 +689,11 @@ func (c *ChannelGraph) AddEdgeProof(chanID lnwire.ShortChannelID,
|
|||||||
return c.db.AddEdgeProof(chanID, proof)
|
return c.db.AddEdgeProof(chanID, proof)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelID attempts to lookup the 8-byte compact channel ID.
|
|
||||||
func (c *ChannelGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
|
|
||||||
return c.db.ChannelID(chanPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HighestChanID returns the "highest" known channel ID in the channel graph.
|
// HighestChanID returns the "highest" known channel ID in the channel graph.
|
||||||
func (c *ChannelGraph) HighestChanID(ctx context.Context) (uint64, error) {
|
func (c *ChannelGraph) HighestChanID(ctx context.Context,
|
||||||
return c.db.HighestChanID(ctx)
|
v lnwire.GossipVersion) (uint64, error) {
|
||||||
|
|
||||||
|
return c.db.HighestChanID(ctx, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChanUpdatesInHorizon returns all known channel edges with updates in the
|
// ChanUpdatesInHorizon returns all known channel edges with updates in the
|
||||||
@@ -710,8 +712,10 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, endHeight uint32,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FetchChanInfos returns the set of channel edges for the passed channel IDs.
|
// FetchChanInfos returns the set of channel edges for the passed channel IDs.
|
||||||
func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
|
func (c *ChannelGraph) FetchChanInfos(v lnwire.GossipVersion,
|
||||||
return c.db.FetchChanInfos(chanIDs)
|
chanIDs []uint64) ([]ChannelEdge, error) {
|
||||||
|
|
||||||
|
return c.db.FetchChanInfos(v, chanIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchChannelEdgesByOutpoint attempts to lookup directed edges by funding
|
// FetchChannelEdgesByOutpoint attempts to lookup directed edges by funding
|
||||||
@@ -906,6 +910,14 @@ func (c *VersionedGraph) HasChannelEdge(chanID uint64) (bool, bool, error) {
|
|||||||
return c.db.HasChannelEdge(c.v, chanID)
|
return c.db.HasChannelEdge(c.v, chanID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForEachSourceNodeChannel iterates through all channels of the source node.
|
||||||
|
func (c *VersionedGraph) ForEachSourceNodeChannel(ctx context.Context,
|
||||||
|
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
||||||
|
otherNode *models.Node) error, reset func()) error {
|
||||||
|
|
||||||
|
return c.db.ForEachSourceNodeChannel(ctx, c.v, cb, reset)
|
||||||
|
}
|
||||||
|
|
||||||
// ForEachNodeChannel iterates through all channels of the given node.
|
// ForEachNodeChannel iterates through all channels of the given node.
|
||||||
func (c *VersionedGraph) ForEachNodeChannel(ctx context.Context,
|
func (c *VersionedGraph) ForEachNodeChannel(ctx context.Context,
|
||||||
nodePub route.Vertex, cb func(*models.ChannelEdgeInfo,
|
nodePub route.Vertex, cb func(*models.ChannelEdgeInfo,
|
||||||
@@ -923,6 +935,44 @@ func (c *VersionedGraph) ForEachChannel(ctx context.Context,
|
|||||||
return c.db.ForEachChannel(ctx, c.v, cb, reset)
|
return c.db.ForEachChannel(ctx, c.v, cb, reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForEachNodeCacheable iterates through all stored vertices/nodes in the graph.
|
||||||
|
func (c *VersionedGraph) ForEachNodeCacheable(ctx context.Context,
|
||||||
|
cb func(route.Vertex, *lnwire.FeatureVector) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
|
return c.db.ForEachNodeCacheable(ctx, c.v, cb, reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForEachChannelCacheable iterates through all channel edges for the cache.
|
||||||
|
func (c *VersionedGraph) ForEachChannelCacheable(
|
||||||
|
cb func(*models.CachedEdgeInfo, *models.CachedEdgePolicy,
|
||||||
|
*models.CachedEdgePolicy) error, reset func()) error {
|
||||||
|
|
||||||
|
return c.db.ForEachChannelCacheable(c.v, cb, reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisabledChannelIDs returns the channel ids of disabled channels.
|
||||||
|
func (c *VersionedGraph) DisabledChannelIDs() ([]uint64, error) {
|
||||||
|
return c.db.DisabledChannelIDs(c.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchChanInfos returns the set of channel edges for the passed channel IDs.
|
||||||
|
func (c *VersionedGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge,
|
||||||
|
error) {
|
||||||
|
|
||||||
|
return c.db.FetchChanInfos(c.v, chanIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HighestChanID returns the "highest" known channel ID in the channel graph.
|
||||||
|
func (c *VersionedGraph) HighestChanID(ctx context.Context) (uint64, error) {
|
||||||
|
return c.db.HighestChanID(ctx, c.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChannelID attempts to lookup the 8-byte compact channel ID.
|
||||||
|
func (c *VersionedGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
|
||||||
|
return c.db.ChannelID(c.v, chanPoint)
|
||||||
|
}
|
||||||
|
|
||||||
// IsPublicNode determines whether the node is seen as public in the graph.
|
// IsPublicNode determines whether the node is seen as public in the graph.
|
||||||
func (c *VersionedGraph) IsPublicNode(pubKey [33]byte) (bool, error) {
|
func (c *VersionedGraph) IsPublicNode(pubKey [33]byte) (bool, error) {
|
||||||
return c.db.IsPublicNode(c.v, pubKey)
|
return c.db.IsPublicNode(c.v, pubKey)
|
||||||
|
|||||||
+466
-271
File diff suppressed because it is too large.
Load diff
+15
-11
@@ -33,7 +33,7 @@ type NodeTraverser interface {
|
|||||||
type Store interface { //nolint:interfacebloat
|
type Store interface { //nolint:interfacebloat
|
||||||
// ForEachNodeDirectedChannel calls the callback for every channel of
|
// ForEachNodeDirectedChannel calls the callback for every channel of
|
||||||
// the given node.
|
// the given node.
|
||||||
ForEachNodeDirectedChannel(nodePub route.Vertex,
|
ForEachNodeDirectedChannel(v lnwire.GossipVersion, nodePub route.Vertex,
|
||||||
cb func(channel *DirectedChannel) error, reset func()) error
|
cb func(channel *DirectedChannel) error, reset func()) error
|
||||||
|
|
||||||
// FetchNodeFeatures returns the features of the given node.
|
// FetchNodeFeatures returns the features of the given node.
|
||||||
@@ -59,7 +59,7 @@ type Store interface { //nolint:interfacebloat
|
|||||||
// node, executing the passed callback on each. The call-back is
|
// node, executing the passed callback on each. The call-back is
|
||||||
// provided with the channel's outpoint, whether we have a policy for
|
// provided with the channel's outpoint, whether we have a policy for
|
||||||
// the channel and the channel peer's node information.
|
// the channel and the channel peer's node information.
|
||||||
ForEachSourceNodeChannel(ctx context.Context,
|
ForEachSourceNodeChannel(ctx context.Context, v lnwire.GossipVersion,
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
||||||
otherNode *models.Node) error,
|
otherNode *models.Node) error,
|
||||||
reset func()) error
|
reset func()) error
|
||||||
@@ -103,8 +103,9 @@ type Store interface { //nolint:interfacebloat
|
|||||||
// in the graph, executing the passed callback with each node
|
// in the graph, executing the passed callback with each node
|
||||||
// encountered. If the callback returns an error, then the transaction
|
// encountered. If the callback returns an error, then the transaction
|
||||||
// is aborted and the iteration stops early.
|
// is aborted and the iteration stops early.
|
||||||
ForEachNodeCacheable(ctx context.Context, cb func(route.Vertex,
|
ForEachNodeCacheable(ctx context.Context, v lnwire.GossipVersion,
|
||||||
*lnwire.FeatureVector) error, reset func()) error
|
cb func(route.Vertex, *lnwire.FeatureVector) error,
|
||||||
|
reset func()) error
|
||||||
|
|
||||||
// LookupAlias attempts to return the alias as advertised by the target
|
// LookupAlias attempts to return the alias as advertised by the target
|
||||||
// node.
|
// node.
|
||||||
@@ -182,14 +183,14 @@ type Store interface { //nolint:interfacebloat
|
|||||||
//
|
//
|
||||||
// NOTE: this method is like ForEachChannel but fetches only the data
|
// NOTE: this method is like ForEachChannel but fetches only the data
|
||||||
// required for the graph cache.
|
// required for the graph cache.
|
||||||
ForEachChannelCacheable(cb func(*models.CachedEdgeInfo,
|
ForEachChannelCacheable(v lnwire.GossipVersion,
|
||||||
*models.CachedEdgePolicy, *models.CachedEdgePolicy) error,
|
cb func(*models.CachedEdgeInfo, *models.CachedEdgePolicy,
|
||||||
reset func()) error
|
*models.CachedEdgePolicy) error, reset func()) error
|
||||||
|
|
||||||
// DisabledChannelIDs returns the channel ids of disabled channels.
|
// DisabledChannelIDs returns the channel ids of disabled channels.
|
||||||
// A channel is disabled when two of the associated ChanelEdgePolicies
|
// A channel is disabled when two of the associated ChanelEdgePolicies
|
||||||
// have their disabled bit on.
|
// have their disabled bit on.
|
||||||
DisabledChannelIDs() ([]uint64, error)
|
DisabledChannelIDs(v lnwire.GossipVersion) ([]uint64, error)
|
||||||
|
|
||||||
// AddChannelEdge adds a new (undirected, blank) edge to the graph
|
// AddChannelEdge adds a new (undirected, blank) edge to the graph
|
||||||
// database. An undirected edge from the two target nodes are created.
|
// database. An undirected edge from the two target nodes are created.
|
||||||
@@ -238,13 +239,15 @@ type Store interface { //nolint:interfacebloat
|
|||||||
// ChannelID attempt to lookup the 8-byte compact channel ID which maps
|
// ChannelID attempt to lookup the 8-byte compact channel ID which maps
|
||||||
// to the passed channel point (outpoint). If the passed channel doesn't
|
// to the passed channel point (outpoint). If the passed channel doesn't
|
||||||
// exist within the database, then ErrEdgeNotFound is returned.
|
// exist within the database, then ErrEdgeNotFound is returned.
|
||||||
ChannelID(chanPoint *wire.OutPoint) (uint64, error)
|
ChannelID(v lnwire.GossipVersion,
|
||||||
|
chanPoint *wire.OutPoint) (uint64, error)
|
||||||
|
|
||||||
// HighestChanID returns the "highest" known channel ID in the channel
|
// HighestChanID returns the "highest" known channel ID in the channel
|
||||||
// graph. This represents the "newest" channel from the PoV of the
|
// graph. This represents the "newest" channel from the PoV of the
|
||||||
// chain. This method can be used by peers to quickly determine if
|
// chain. This method can be used by peers to quickly determine if
|
||||||
// they're graphs are in sync.
|
// they're graphs are in sync.
|
||||||
HighestChanID(ctx context.Context) (uint64, error)
|
HighestChanID(ctx context.Context, v lnwire.GossipVersion) (
|
||||||
|
uint64, error)
|
||||||
|
|
||||||
// ChanUpdatesInHorizon returns all the known channel edges which have
|
// ChanUpdatesInHorizon returns all the known channel edges which have
|
||||||
// at least one edge that has an update timestamp within the specified
|
// at least one edge that has an update timestamp within the specified
|
||||||
@@ -279,7 +282,8 @@ type Store interface { //nolint:interfacebloat
|
|||||||
// edges that exist at the time of the query. This can be used to
|
// edges that exist at the time of the query. This can be used to
|
||||||
// respond to peer queries that are seeking to fill in gaps in their
|
// respond to peer queries that are seeking to fill in gaps in their
|
||||||
// view of the channel graph.
|
// view of the channel graph.
|
||||||
FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error)
|
FetchChanInfos(v lnwire.GossipVersion,
|
||||||
|
chanIDs []uint64) ([]ChannelEdge, error)
|
||||||
|
|
||||||
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges
|
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges
|
||||||
// for the channel identified by the funding outpoint. If the channel
|
// for the channel identified by the funding outpoint. If the channel
|
||||||
|
|||||||
+77
-26
@@ -496,9 +496,13 @@ func forEachChannel(db kvdb.Backend, cb func(*models.ChannelEdgeInfo,
|
|||||||
//
|
//
|
||||||
// NOTE: this method is like ForEachChannel but fetches only the data required
|
// NOTE: this method is like ForEachChannel but fetches only the data required
|
||||||
// for the graph cache.
|
// for the graph cache.
|
||||||
func (c *KVStore) ForEachChannelCacheable(cb func(*models.CachedEdgeInfo,
|
func (c *KVStore) ForEachChannelCacheable(v lnwire.GossipVersion,
|
||||||
*models.CachedEdgePolicy, *models.CachedEdgePolicy) error,
|
cb func(*models.CachedEdgeInfo, *models.CachedEdgePolicy,
|
||||||
reset func()) error {
|
*models.CachedEdgePolicy) error, reset func()) error {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
return c.db.View(func(tx kvdb.RTx) error {
|
return c.db.View(func(tx kvdb.RTx) error {
|
||||||
edges := tx.ReadBucket(edgeBucket)
|
edges := tx.ReadBucket(edgeBucket)
|
||||||
@@ -665,8 +669,13 @@ func (c *KVStore) fetchNodeFeatures(tx kvdb.RTx,
|
|||||||
// Unknown policies are passed into the callback as nil values.
|
// Unknown policies are passed into the callback as nil values.
|
||||||
//
|
//
|
||||||
// NOTE: this is part of the graphdb.NodeTraverser interface.
|
// NOTE: this is part of the graphdb.NodeTraverser interface.
|
||||||
func (c *KVStore) ForEachNodeDirectedChannel(nodePub route.Vertex,
|
func (c *KVStore) ForEachNodeDirectedChannel(v lnwire.GossipVersion,
|
||||||
cb func(channel *DirectedChannel) error, reset func()) error {
|
nodePub route.Vertex, cb func(channel *DirectedChannel) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
return c.forEachNodeDirectedChannel(nil, nodePub, cb, reset)
|
return c.forEachNodeDirectedChannel(nil, nodePub, cb, reset)
|
||||||
}
|
}
|
||||||
@@ -763,7 +772,13 @@ func (c *KVStore) ForEachNodeCached(ctx context.Context, withAddrs bool,
|
|||||||
// DisabledChannelIDs returns the channel ids of disabled channels.
|
// DisabledChannelIDs returns the channel ids of disabled channels.
|
||||||
// A channel is disabled when two of the associated ChanelEdgePolicies
|
// A channel is disabled when two of the associated ChanelEdgePolicies
|
||||||
// have their disabled bit on.
|
// have their disabled bit on.
|
||||||
func (c *KVStore) DisabledChannelIDs() ([]uint64, error) {
|
func (c *KVStore) DisabledChannelIDs(
|
||||||
|
v lnwire.GossipVersion) ([]uint64, error) {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return nil, ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
var disabledChanIDs []uint64
|
var disabledChanIDs []uint64
|
||||||
var chanEdgeFound map[uint64]struct{}
|
var chanEdgeFound map[uint64]struct{}
|
||||||
|
|
||||||
@@ -874,8 +889,12 @@ func forEachNode(db kvdb.Backend,
|
|||||||
// callback returns an error, then the transaction is aborted and the iteration
|
// callback returns an error, then the transaction is aborted and the iteration
|
||||||
// stops early.
|
// stops early.
|
||||||
func (c *KVStore) ForEachNodeCacheable(_ context.Context,
|
func (c *KVStore) ForEachNodeCacheable(_ context.Context,
|
||||||
cb func(route.Vertex, *lnwire.FeatureVector) error,
|
v lnwire.GossipVersion, cb func(route.Vertex,
|
||||||
reset func()) error {
|
*lnwire.FeatureVector) error, reset func()) error {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
traversal := func(tx kvdb.RTx) error {
|
traversal := func(tx kvdb.RTx) error {
|
||||||
// First grab the nodes bucket which stores the mapping from
|
// First grab the nodes bucket which stores the mapping from
|
||||||
@@ -1186,7 +1205,9 @@ func (c *KVStore) AddChannelEdge(ctx context.Context,
|
|||||||
c.rejectCache.remove(
|
c.rejectCache.remove(
|
||||||
lnwire.GossipVersion1, edge.ChannelID,
|
lnwire.GossipVersion1, edge.ChannelID,
|
||||||
)
|
)
|
||||||
c.chanCache.remove(edge.ChannelID)
|
c.chanCache.remove(
|
||||||
|
lnwire.GossipVersion1, edge.ChannelID,
|
||||||
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1588,7 +1609,7 @@ func (c *KVStore) PruneGraph(spentOutputs []*wire.OutPoint,
|
|||||||
|
|
||||||
for _, channel := range chansClosed {
|
for _, channel := range chansClosed {
|
||||||
c.rejectCache.remove(lnwire.GossipVersion1, channel.ChannelID)
|
c.rejectCache.remove(lnwire.GossipVersion1, channel.ChannelID)
|
||||||
c.chanCache.remove(channel.ChannelID)
|
c.chanCache.remove(lnwire.GossipVersion1, channel.ChannelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return chansClosed, prunedNodes, nil
|
return chansClosed, prunedNodes, nil
|
||||||
@@ -1855,7 +1876,7 @@ func (c *KVStore) DisconnectBlockAtHeight(height uint32) (
|
|||||||
|
|
||||||
for _, channel := range removedChans {
|
for _, channel := range removedChans {
|
||||||
c.rejectCache.remove(lnwire.GossipVersion1, channel.ChannelID)
|
c.rejectCache.remove(lnwire.GossipVersion1, channel.ChannelID)
|
||||||
c.chanCache.remove(channel.ChannelID)
|
c.chanCache.remove(lnwire.GossipVersion1, channel.ChannelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return removedChans, nil
|
return removedChans, nil
|
||||||
@@ -1974,7 +1995,7 @@ func (c *KVStore) DeleteChannelEdges(v lnwire.GossipVersion,
|
|||||||
|
|
||||||
for _, chanID := range chanIDs {
|
for _, chanID := range chanIDs {
|
||||||
c.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
c.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
c.chanCache.remove(chanID)
|
c.chanCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return infos, nil
|
return infos, nil
|
||||||
@@ -1983,7 +2004,13 @@ func (c *KVStore) DeleteChannelEdges(v lnwire.GossipVersion,
|
|||||||
// ChannelID attempt to lookup the 8-byte compact channel ID which maps to the
|
// ChannelID attempt to lookup the 8-byte compact channel ID which maps to the
|
||||||
// passed channel point (outpoint). If the passed channel doesn't exist within
|
// passed channel point (outpoint). If the passed channel doesn't exist within
|
||||||
// the database, then ErrEdgeNotFound is returned.
|
// the database, then ErrEdgeNotFound is returned.
|
||||||
func (c *KVStore) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
|
func (c *KVStore) ChannelID(v lnwire.GossipVersion,
|
||||||
|
chanPoint *wire.OutPoint) (uint64, error) {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return 0, ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
var chanID uint64
|
var chanID uint64
|
||||||
if err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
if err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||||
var err error
|
var err error
|
||||||
@@ -2029,7 +2056,13 @@ func getChanID(tx kvdb.RTx, chanPoint *wire.OutPoint) (uint64, error) {
|
|||||||
// HighestChanID returns the "highest" known channel ID in the channel graph.
|
// HighestChanID returns the "highest" known channel ID in the channel graph.
|
||||||
// This represents the "newest" channel from the PoV of the chain. This method
|
// This represents the "newest" channel from the PoV of the chain. This method
|
||||||
// can be used by peers to quickly determine if they're graphs are in sync.
|
// can be used by peers to quickly determine if they're graphs are in sync.
|
||||||
func (c *KVStore) HighestChanID(_ context.Context) (uint64, error) {
|
func (c *KVStore) HighestChanID(_ context.Context,
|
||||||
|
v lnwire.GossipVersion) (uint64, error) {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return 0, ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
var cid uint64
|
var cid uint64
|
||||||
|
|
||||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||||
@@ -2104,7 +2137,7 @@ func (c *KVStore) updateChanCacheBatch(edgesToCache map[uint64]ChannelEdge) {
|
|||||||
defer c.cacheMu.Unlock()
|
defer c.cacheMu.Unlock()
|
||||||
|
|
||||||
for cid, edge := range edgesToCache {
|
for cid, edge := range edgesToCache {
|
||||||
c.chanCache.insert(cid, edge)
|
c.chanCache.insert(lnwire.GossipVersion1, cid, edge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2256,7 +2289,10 @@ func (c *KVStore) fetchNextChanUpdateBatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check cache (we already hold shared read lock).
|
// Check cache (we already hold shared read lock).
|
||||||
if channel, ok := c.chanCache.get(chanIDInt); ok {
|
channel, ok := c.chanCache.get(
|
||||||
|
lnwire.GossipVersion1, chanIDInt,
|
||||||
|
)
|
||||||
|
if ok {
|
||||||
state.edgesSeen[chanIDInt] = struct{}{}
|
state.edgesSeen[chanIDInt] = struct{}{}
|
||||||
|
|
||||||
batch = append(batch, channel)
|
batch = append(batch, channel)
|
||||||
@@ -2300,7 +2336,7 @@ func (c *KVStore) fetchNextChanUpdateBatch(
|
|||||||
|
|
||||||
// Now we have all the information we need to build the
|
// Now we have all the information we need to build the
|
||||||
// channel edge.
|
// channel edge.
|
||||||
channel := ChannelEdge{
|
channel = ChannelEdge{
|
||||||
Info: edgeInfo,
|
Info: edgeInfo,
|
||||||
Policy1: edge1,
|
Policy1: edge1,
|
||||||
Policy2: edge2,
|
Policy2: edge2,
|
||||||
@@ -2924,7 +2960,13 @@ func (c *KVStore) FilterChannelRange(startHeight,
|
|||||||
// skipped and the result will contain only those edges that exist at the time
|
// skipped and the result will contain only those edges that exist at the time
|
||||||
// of the query. This can be used to respond to peer queries that are seeking to
|
// of the query. This can be used to respond to peer queries that are seeking to
|
||||||
// fill in gaps in their view of the channel graph.
|
// fill in gaps in their view of the channel graph.
|
||||||
func (c *KVStore) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
|
func (c *KVStore) FetchChanInfos(v lnwire.GossipVersion,
|
||||||
|
chanIDs []uint64) ([]ChannelEdge, error) {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return nil, ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
return c.fetchChanInfos(nil, chanIDs)
|
return c.fetchChanInfos(nil, chanIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3302,13 +3344,16 @@ func (c *KVStore) updateEdgeCache(e *models.ChannelEdgePolicy,
|
|||||||
// the entry with the updated policy for the direction that was just
|
// the entry with the updated policy for the direction that was just
|
||||||
// written. If the edge doesn't exist, we'll defer loading the info and
|
// written. If the edge doesn't exist, we'll defer loading the info and
|
||||||
// policies and lazily read from disk during the next query.
|
// policies and lazily read from disk during the next query.
|
||||||
if channel, ok := c.chanCache.get(e.ChannelID); ok {
|
channel, ok := c.chanCache.get(
|
||||||
|
lnwire.GossipVersion1, e.ChannelID,
|
||||||
|
)
|
||||||
|
if ok {
|
||||||
if isUpdate1 {
|
if isUpdate1 {
|
||||||
channel.Policy1 = e
|
channel.Policy1 = e
|
||||||
} else {
|
} else {
|
||||||
channel.Policy2 = e
|
channel.Policy2 = e
|
||||||
}
|
}
|
||||||
c.chanCache.insert(e.ChannelID, channel)
|
c.chanCache.insert(lnwire.GossipVersion1, e.ChannelID, channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3714,8 +3759,13 @@ func (c *KVStore) ForEachNodeChannel(_ context.Context,
|
|||||||
// channel's outpoint, whether we have a policy for the channel and the channel
|
// channel's outpoint, whether we have a policy for the channel and the channel
|
||||||
// peer's node information.
|
// peer's node information.
|
||||||
func (c *KVStore) ForEachSourceNodeChannel(_ context.Context,
|
func (c *KVStore) ForEachSourceNodeChannel(_ context.Context,
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
v lnwire.GossipVersion, cb func(chanPoint wire.OutPoint,
|
||||||
otherNode *models.Node) error, reset func()) error {
|
havePolicy bool, otherNode *models.Node) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
return kvdb.View(c.db, func(tx kvdb.RTx) error {
|
return kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||||
nodes := tx.ReadBucket(nodeBucket)
|
nodes := tx.ReadBucket(nodeBucket)
|
||||||
@@ -4215,7 +4265,7 @@ func (c *KVStore) MarkEdgeZombie(chanID uint64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
c.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
c.chanCache.remove(chanID)
|
c.chanCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -4284,7 +4334,7 @@ func (c *KVStore) markEdgeLiveUnsafe(tx kvdb.RwTx, chanID uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
c.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
c.chanCache.remove(chanID)
|
c.chanCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -4450,8 +4500,9 @@ type nodeTraverserSession struct {
|
|||||||
// node.
|
// node.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the NodeTraverser interface.
|
// NOTE: Part of the NodeTraverser interface.
|
||||||
func (c *nodeTraverserSession) ForEachNodeDirectedChannel(nodePub route.Vertex,
|
func (c *nodeTraverserSession) ForEachNodeDirectedChannel(
|
||||||
cb func(channel *DirectedChannel) error, _ func()) error {
|
nodePub route.Vertex, cb func(channel *DirectedChannel) error,
|
||||||
|
_ func()) error {
|
||||||
|
|
||||||
return c.db.forEachNodeDirectedChannel(c.tx, nodePub, cb, func() {})
|
return c.db.forEachNodeDirectedChannel(c.tx, nodePub, cb, func() {})
|
||||||
}
|
}
|
||||||
|
|||||||
+135
-86
@@ -33,6 +33,11 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/tor"
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
gossipV1 = lnwire.GossipVersion1
|
||||||
|
gossipV2 = lnwire.GossipVersion2
|
||||||
|
)
|
||||||
|
|
||||||
// SQLQueries is a subset of the sqlc.Querier interface that can be used to
|
// SQLQueries is a subset of the sqlc.Querier interface that can be used to
|
||||||
// execute queries against the SQL graph tables.
|
// execute queries against the SQL graph tables.
|
||||||
//
|
//
|
||||||
@@ -71,6 +76,8 @@ type SQLQueries interface {
|
|||||||
GetNodeFeaturesBatch(ctx context.Context, ids []int64) ([]sqlc.GraphNodeFeature, error)
|
GetNodeFeaturesBatch(ctx context.Context, ids []int64) ([]sqlc.GraphNodeFeature, error)
|
||||||
GetNodeFeaturesByPubKey(ctx context.Context, arg sqlc.GetNodeFeaturesByPubKeyParams) ([]int32, error)
|
GetNodeFeaturesByPubKey(ctx context.Context, arg sqlc.GetNodeFeaturesByPubKeyParams) ([]int32, error)
|
||||||
DeleteNodeFeature(ctx context.Context, arg sqlc.DeleteNodeFeatureParams) error
|
DeleteNodeFeature(ctx context.Context, arg sqlc.DeleteNodeFeatureParams) error
|
||||||
|
GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error)
|
||||||
|
GetV2DisabledSCIDs(ctx context.Context) ([][]byte, error)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Source node queries.
|
Source node queries.
|
||||||
@@ -114,7 +121,6 @@ type SQLQueries interface {
|
|||||||
*/
|
*/
|
||||||
UpsertEdgePolicy(ctx context.Context, arg sqlc.UpsertEdgePolicyParams) (int64, error)
|
UpsertEdgePolicy(ctx context.Context, arg sqlc.UpsertEdgePolicyParams) (int64, error)
|
||||||
GetChannelPolicyByChannelAndNode(ctx context.Context, arg sqlc.GetChannelPolicyByChannelAndNodeParams) (sqlc.GraphChannelPolicy, error)
|
GetChannelPolicyByChannelAndNode(ctx context.Context, arg sqlc.GetChannelPolicyByChannelAndNodeParams) (sqlc.GraphChannelPolicy, error)
|
||||||
GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error)
|
|
||||||
|
|
||||||
UpsertChanPolicyExtraType(ctx context.Context, arg sqlc.UpsertChanPolicyExtraTypeParams) error
|
UpsertChanPolicyExtraType(ctx context.Context, arg sqlc.UpsertChanPolicyExtraTypeParams) error
|
||||||
GetChannelPolicyExtraTypesBatch(ctx context.Context, policyIds []int64) ([]sqlc.GetChannelPolicyExtraTypesBatchRow, error)
|
GetChannelPolicyExtraTypesBatch(ctx context.Context, policyIds []int64) ([]sqlc.GetChannelPolicyExtraTypesBatchRow, error)
|
||||||
@@ -305,7 +311,7 @@ func (s *SQLStore) HasV1Node(ctx context.Context,
|
|||||||
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
dbNode, err := db.GetNodeByPubKey(
|
dbNode, err := db.GetNodeByPubKey(
|
||||||
ctx, sqlc.GetNodeByPubKeyParams{
|
ctx, sqlc.GetNodeByPubKeyParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(gossipV1),
|
||||||
PubKey: pubKey[:],
|
PubKey: pubKey[:],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -454,13 +460,26 @@ func (s *SQLStore) FetchNodeFeatures(v lnwire.GossipVersion,
|
|||||||
// have their disabled bit on.
|
// have their disabled bit on.
|
||||||
//
|
//
|
||||||
// NOTE: part of the Store interface.
|
// NOTE: part of the Store interface.
|
||||||
func (s *SQLStore) DisabledChannelIDs() ([]uint64, error) {
|
func (s *SQLStore) DisabledChannelIDs(
|
||||||
|
v lnwire.GossipVersion) ([]uint64, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctx = context.TODO()
|
ctx = context.TODO()
|
||||||
chanIDs []uint64
|
chanIDs []uint64
|
||||||
)
|
)
|
||||||
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
dbChanIDs, err := db.GetV1DisabledSCIDs(ctx)
|
var (
|
||||||
|
dbChanIDs [][]byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch v {
|
||||||
|
case gossipV1:
|
||||||
|
dbChanIDs, err = db.GetV1DisabledSCIDs(ctx)
|
||||||
|
case gossipV2:
|
||||||
|
dbChanIDs, err = db.GetV2DisabledSCIDs(ctx)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported gossip version: %d", v)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch disabled "+
|
return fmt.Errorf("unable to fetch disabled "+
|
||||||
"channels: %w", err)
|
"channels: %w", err)
|
||||||
@@ -750,7 +769,9 @@ func (s *SQLStore) AddChannelEdge(ctx context.Context,
|
|||||||
s.rejectCache.remove(
|
s.rejectCache.remove(
|
||||||
edge.Version, edge.ChannelID,
|
edge.Version, edge.ChannelID,
|
||||||
)
|
)
|
||||||
s.chanCache.remove(edge.ChannelID)
|
s.chanCache.remove(
|
||||||
|
edge.Version, edge.ChannelID,
|
||||||
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -765,10 +786,16 @@ func (s *SQLStore) AddChannelEdge(ctx context.Context,
|
|||||||
// can be used by peers to quickly determine if their graphs are in sync.
|
// can be used by peers to quickly determine if their graphs are in sync.
|
||||||
//
|
//
|
||||||
// NOTE: This is part of the Store interface.
|
// NOTE: This is part of the Store interface.
|
||||||
func (s *SQLStore) HighestChanID(ctx context.Context) (uint64, error) {
|
func (s *SQLStore) HighestChanID(ctx context.Context,
|
||||||
|
v lnwire.GossipVersion) (uint64, error) {
|
||||||
|
|
||||||
var highestChanID uint64
|
var highestChanID uint64
|
||||||
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
chanID, err := db.HighestSCID(ctx, int16(lnwire.GossipVersion1))
|
if !isKnownGossipVersion(v) {
|
||||||
|
return fmt.Errorf("unsupported gossip version: %d", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
chanID, err := db.HighestSCID(ctx, int16(v))
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil
|
return nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@@ -867,11 +894,11 @@ func (s *SQLStore) updateEdgeCache(e *models.ChannelEdgePolicy,
|
|||||||
// during the next query for this edge.
|
// during the next query for this edge.
|
||||||
if entry, ok := s.rejectCache.get(e.Version, e.ChannelID); ok {
|
if entry, ok := s.rejectCache.get(e.Version, e.ChannelID); ok {
|
||||||
switch e.Version {
|
switch e.Version {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
updateRejectCacheEntryV1(
|
updateRejectCacheEntryV1(
|
||||||
&entry, isUpdate1, e.LastUpdate,
|
&entry, isUpdate1, e.LastUpdate,
|
||||||
)
|
)
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
updateRejectCacheEntryV2(
|
updateRejectCacheEntryV2(
|
||||||
&entry, isUpdate1, e.LastBlockHeight,
|
&entry, isUpdate1, e.LastBlockHeight,
|
||||||
)
|
)
|
||||||
@@ -883,13 +910,13 @@ func (s *SQLStore) updateEdgeCache(e *models.ChannelEdgePolicy,
|
|||||||
// the entry with the updated policy for the direction that was just
|
// the entry with the updated policy for the direction that was just
|
||||||
// written. If the edge doesn't exist, we'll defer loading the info and
|
// written. If the edge doesn't exist, we'll defer loading the info and
|
||||||
// policies and lazily read from disk during the next query.
|
// policies and lazily read from disk during the next query.
|
||||||
if channel, ok := s.chanCache.get(e.ChannelID); ok {
|
if channel, ok := s.chanCache.get(e.Version, e.ChannelID); ok {
|
||||||
if isUpdate1 {
|
if isUpdate1 {
|
||||||
channel.Policy1 = e
|
channel.Policy1 = e
|
||||||
} else {
|
} else {
|
||||||
channel.Policy2 = e
|
channel.Policy2 = e
|
||||||
}
|
}
|
||||||
s.chanCache.insert(e.ChannelID, channel)
|
s.chanCache.insert(e.Version, e.ChannelID, channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,20 +927,19 @@ func (s *SQLStore) updateEdgeCache(e *models.ChannelEdgePolicy,
|
|||||||
//
|
//
|
||||||
// NOTE: part of the Store interface.
|
// NOTE: part of the Store interface.
|
||||||
func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context,
|
func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context,
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
v lnwire.GossipVersion, cb func(chanPoint wire.OutPoint,
|
||||||
otherNode *models.Node) error, reset func()) error {
|
havePolicy bool, otherNode *models.Node) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
nodeID, nodePub, err := s.getSourceNode(
|
nodeID, nodePub, err := s.getSourceNode(ctx, db, v)
|
||||||
ctx, db, lnwire.GossipVersion1,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch source node: %w",
|
return fmt.Errorf("unable to fetch source node: %w",
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return forEachNodeChannel(
|
return forEachNodeChannel(
|
||||||
ctx, db, s.cfg, lnwire.GossipVersion1, nodeID,
|
ctx, db, s.cfg, v, nodeID,
|
||||||
func(info *models.ChannelEdgeInfo,
|
func(info *models.ChannelEdgeInfo,
|
||||||
outPolicy *models.ChannelEdgePolicy,
|
outPolicy *models.ChannelEdgePolicy,
|
||||||
_ *models.ChannelEdgePolicy) error {
|
_ *models.ChannelEdgePolicy) error {
|
||||||
@@ -935,8 +961,8 @@ func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, otherNode, err := getNodeByPubKey(
|
_, otherNode, err := getNodeByPubKey(
|
||||||
ctx, s.cfg.QueryCfg, db,
|
ctx, s.cfg.QueryCfg, db, v,
|
||||||
lnwire.GossipVersion1, otherNodePub,
|
otherNodePub,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch "+
|
return fmt.Errorf("unable to fetch "+
|
||||||
@@ -982,13 +1008,14 @@ func (s *SQLStore) ForEachNode(ctx context.Context,
|
|||||||
// Unknown policies are passed into the callback as nil values.
|
// Unknown policies are passed into the callback as nil values.
|
||||||
//
|
//
|
||||||
// NOTE: this is part of the graphdb.NodeTraverser interface.
|
// NOTE: this is part of the graphdb.NodeTraverser interface.
|
||||||
func (s *SQLStore) ForEachNodeDirectedChannel(nodePub route.Vertex,
|
func (s *SQLStore) ForEachNodeDirectedChannel(v lnwire.GossipVersion,
|
||||||
cb func(channel *DirectedChannel) error, reset func()) error {
|
nodePub route.Vertex, cb func(channel *DirectedChannel) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
var ctx = context.TODO()
|
var ctx = context.TODO()
|
||||||
|
|
||||||
return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
return forEachNodeDirectedChannel(ctx, db, nodePub, cb)
|
return forEachNodeDirectedChannel(ctx, db, v, nodePub, cb)
|
||||||
}, reset)
|
}, reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,12 +1024,12 @@ func (s *SQLStore) ForEachNodeDirectedChannel(nodePub route.Vertex,
|
|||||||
// callback returns an error, then the transaction is aborted and the iteration
|
// callback returns an error, then the transaction is aborted and the iteration
|
||||||
// stops early.
|
// stops early.
|
||||||
func (s *SQLStore) ForEachNodeCacheable(ctx context.Context,
|
func (s *SQLStore) ForEachNodeCacheable(ctx context.Context,
|
||||||
cb func(route.Vertex, *lnwire.FeatureVector) error,
|
v lnwire.GossipVersion, cb func(route.Vertex,
|
||||||
reset func()) error {
|
*lnwire.FeatureVector) error, reset func()) error {
|
||||||
|
|
||||||
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
return forEachNodeCacheable(
|
return forEachNodeCacheable(
|
||||||
ctx, s.cfg.QueryCfg, db,
|
ctx, s.cfg.QueryCfg, db, v,
|
||||||
func(_ int64, nodePub route.Vertex,
|
func(_ int64, nodePub route.Vertex,
|
||||||
features *lnwire.FeatureVector) error {
|
features *lnwire.FeatureVector) error {
|
||||||
|
|
||||||
@@ -1120,7 +1147,9 @@ func (s *SQLStore) buildChannelFromRow(ctx context.Context, db SQLQueries,
|
|||||||
|
|
||||||
// updateChanCacheBatch updates the channel cache with multiple edges at once.
|
// updateChanCacheBatch updates the channel cache with multiple edges at once.
|
||||||
// This method acquires the cache lock only once for the entire batch.
|
// This method acquires the cache lock only once for the entire batch.
|
||||||
func (s *SQLStore) updateChanCacheBatch(edgesToCache map[uint64]ChannelEdge) {
|
func (s *SQLStore) updateChanCacheBatch(v lnwire.GossipVersion,
|
||||||
|
edgesToCache map[uint64]ChannelEdge) {
|
||||||
|
|
||||||
if len(edgesToCache) == 0 {
|
if len(edgesToCache) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1129,7 +1158,7 @@ func (s *SQLStore) updateChanCacheBatch(edgesToCache map[uint64]ChannelEdge) {
|
|||||||
defer s.cacheMu.Unlock()
|
defer s.cacheMu.Unlock()
|
||||||
|
|
||||||
for chanID, edge := range edgesToCache {
|
for chanID, edge := range edgesToCache {
|
||||||
s.chanCache.insert(chanID, edge)
|
s.chanCache.insert(v, chanID, edge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1232,6 +1261,7 @@ func (s *SQLStore) ChanUpdatesInHorizon(startTime, endTime time.Time,
|
|||||||
// Check cache (we already hold
|
// Check cache (we already hold
|
||||||
// shared read lock).
|
// shared read lock).
|
||||||
channel, ok := s.chanCache.get(
|
channel, ok := s.chanCache.get(
|
||||||
|
lnwire.GossipVersion1,
|
||||||
chanIDInt,
|
chanIDInt,
|
||||||
)
|
)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -1287,7 +1317,9 @@ func (s *SQLStore) ChanUpdatesInHorizon(startTime, endTime time.Time,
|
|||||||
|
|
||||||
// Update cache after successful batch yield, setting
|
// Update cache after successful batch yield, setting
|
||||||
// the cache lock only once for the entire batch.
|
// the cache lock only once for the entire batch.
|
||||||
s.updateChanCacheBatch(edgesToCache)
|
s.updateChanCacheBatch(
|
||||||
|
lnwire.GossipVersion1, edgesToCache,
|
||||||
|
)
|
||||||
edgesToCache = make(map[uint64]ChannelEdge)
|
edgesToCache = make(map[uint64]ChannelEdge)
|
||||||
|
|
||||||
// If the batch didn't yield anything, then we're done.
|
// If the batch didn't yield anything, then we're done.
|
||||||
@@ -1536,12 +1568,16 @@ func (s *SQLStore) ForEachNodeCached(ctx context.Context, withAddrs bool,
|
|||||||
//
|
//
|
||||||
// NOTE: this method is like ForEachChannel but fetches only the data
|
// NOTE: this method is like ForEachChannel but fetches only the data
|
||||||
// required for the graph cache.
|
// required for the graph cache.
|
||||||
func (s *SQLStore) ForEachChannelCacheable(cb func(*models.CachedEdgeInfo,
|
func (s *SQLStore) ForEachChannelCacheable(v lnwire.GossipVersion,
|
||||||
*models.CachedEdgePolicy, *models.CachedEdgePolicy) error,
|
cb func(*models.CachedEdgeInfo, *models.CachedEdgePolicy,
|
||||||
reset func()) error {
|
*models.CachedEdgePolicy) error, reset func()) error {
|
||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
if !isKnownGossipVersion(v) {
|
||||||
|
return fmt.Errorf("unsupported gossip version: %d", v)
|
||||||
|
}
|
||||||
|
|
||||||
handleChannel := func(_ context.Context,
|
handleChannel := func(_ context.Context,
|
||||||
row sqlc.ListChannelsWithPoliciesForCachePaginatedRow) error {
|
row sqlc.ListChannelsWithPoliciesForCachePaginatedRow) error {
|
||||||
|
|
||||||
@@ -1585,7 +1621,7 @@ func (s *SQLStore) ForEachChannelCacheable(cb func(*models.CachedEdgeInfo,
|
|||||||
|
|
||||||
return db.ListChannelsWithPoliciesForCachePaginated(
|
return db.ListChannelsWithPoliciesForCachePaginated(
|
||||||
ctx, sqlc.ListChannelsWithPoliciesForCachePaginatedParams{
|
ctx, sqlc.ListChannelsWithPoliciesForCachePaginatedParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(v),
|
||||||
ID: lastID,
|
ID: lastID,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
},
|
},
|
||||||
@@ -1779,7 +1815,7 @@ func (s *SQLStore) MarkEdgeZombie(chanID uint64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
s.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
s.chanCache.remove(chanID)
|
s.chanCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1828,7 +1864,7 @@ func (s *SQLStore) MarkEdgeLive(chanID uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
s.rejectCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
s.chanCache.remove(chanID)
|
s.chanCache.remove(lnwire.GossipVersion1, chanID)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -2010,7 +2046,7 @@ func (s *SQLStore) DeleteChannelEdges(v lnwire.GossipVersion,
|
|||||||
|
|
||||||
for _, chanID := range chanIDs {
|
for _, chanID := range chanIDs {
|
||||||
s.rejectCache.remove(v, chanID)
|
s.rejectCache.remove(v, chanID)
|
||||||
s.chanCache.remove(chanID)
|
s.chanCache.remove(v, chanID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return edges, nil
|
return edges, nil
|
||||||
@@ -2236,7 +2272,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
// We'll query the cache with the shared lock held to allow multiple
|
// We'll query the cache with the shared lock held to allow multiple
|
||||||
// readers to access values in the cache concurrently if they exist.
|
// readers to access values in the cache concurrently if they exist.
|
||||||
s.cacheMu.RLock()
|
s.cacheMu.RLock()
|
||||||
if entry, ok := s.rejectCache.get(lnwire.GossipVersion1, chanID); ok {
|
if entry, ok := s.rejectCache.get(gossipV1, chanID); ok {
|
||||||
s.cacheMu.RUnlock()
|
s.cacheMu.RUnlock()
|
||||||
node1LastUpdate = time.Unix(entry.upd1Time, 0)
|
node1LastUpdate = time.Unix(entry.upd1Time, 0)
|
||||||
node2LastUpdate = time.Unix(entry.upd2Time, 0)
|
node2LastUpdate = time.Unix(entry.upd2Time, 0)
|
||||||
@@ -2252,7 +2288,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
// The item was not found with the shared lock, so we'll acquire the
|
// The item was not found with the shared lock, so we'll acquire the
|
||||||
// exclusive lock and check the cache again in case another method added
|
// exclusive lock and check the cache again in case another method added
|
||||||
// the entry to the cache while no lock was held.
|
// the entry to the cache while no lock was held.
|
||||||
if entry, ok := s.rejectCache.get(lnwire.GossipVersion1, chanID); ok {
|
if entry, ok := s.rejectCache.get(gossipV1, chanID); ok {
|
||||||
node1LastUpdate = time.Unix(entry.upd1Time, 0)
|
node1LastUpdate = time.Unix(entry.upd1Time, 0)
|
||||||
node2LastUpdate = time.Unix(entry.upd2Time, 0)
|
node2LastUpdate = time.Unix(entry.upd2Time, 0)
|
||||||
exists, isZombie = entry.flags.unpack()
|
exists, isZombie = entry.flags.unpack()
|
||||||
@@ -2265,7 +2301,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
channel, err := db.GetChannelBySCID(
|
channel, err := db.GetChannelBySCID(
|
||||||
ctx, sqlc.GetChannelBySCIDParams{
|
ctx, sqlc.GetChannelBySCIDParams{
|
||||||
Scid: chanIDB,
|
Scid: chanIDB,
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(gossipV1),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
@@ -2273,7 +2309,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
isZombie, err = db.IsZombieChannel(
|
isZombie, err = db.IsZombieChannel(
|
||||||
ctx, sqlc.IsZombieChannelParams{
|
ctx, sqlc.IsZombieChannelParams{
|
||||||
Scid: chanIDB,
|
Scid: chanIDB,
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(gossipV1),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -2290,7 +2326,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
|
|
||||||
policy1, err := db.GetChannelPolicyByChannelAndNode(
|
policy1, err := db.GetChannelPolicyByChannelAndNode(
|
||||||
ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{
|
ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(gossipV1),
|
||||||
ChannelID: channel.ID,
|
ChannelID: channel.ID,
|
||||||
NodeID: channel.NodeID1,
|
NodeID: channel.NodeID1,
|
||||||
},
|
},
|
||||||
@@ -2304,7 +2340,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
|
|
||||||
policy2, err := db.GetChannelPolicyByChannelAndNode(
|
policy2, err := db.GetChannelPolicyByChannelAndNode(
|
||||||
ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{
|
ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(gossipV1),
|
||||||
ChannelID: channel.ID,
|
ChannelID: channel.ID,
|
||||||
NodeID: channel.NodeID2,
|
NodeID: channel.NodeID2,
|
||||||
},
|
},
|
||||||
@@ -2324,7 +2360,7 @@ func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.rejectCache.insert(
|
s.rejectCache.insert(
|
||||||
lnwire.GossipVersion1, chanID,
|
gossipV1, chanID,
|
||||||
newRejectCacheEntryV1(
|
newRejectCacheEntryV1(
|
||||||
node1LastUpdate, node2LastUpdate, exists,
|
node1LastUpdate, node2LastUpdate, exists,
|
||||||
isZombie,
|
isZombie,
|
||||||
@@ -2421,13 +2457,13 @@ func (s *SQLStore) HasChannelEdge(v lnwire.GossipVersion,
|
|||||||
err)
|
err)
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
switch v {
|
switch v {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
if policy1.LastUpdate.Valid {
|
if policy1.LastUpdate.Valid {
|
||||||
node1LastUpdate = time.Unix(
|
node1LastUpdate = time.Unix(
|
||||||
policy1.LastUpdate.Int64, 0,
|
policy1.LastUpdate.Int64, 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
if policy1.BlockHeight.Valid {
|
if policy1.BlockHeight.Valid {
|
||||||
node1Block = uint32(
|
node1Block = uint32(
|
||||||
policy1.BlockHeight.Int64,
|
policy1.BlockHeight.Int64,
|
||||||
@@ -2448,13 +2484,13 @@ func (s *SQLStore) HasChannelEdge(v lnwire.GossipVersion,
|
|||||||
err)
|
err)
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
switch v {
|
switch v {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
if policy2.LastUpdate.Valid {
|
if policy2.LastUpdate.Valid {
|
||||||
node2LastUpdate = time.Unix(
|
node2LastUpdate = time.Unix(
|
||||||
policy2.LastUpdate.Int64, 0,
|
policy2.LastUpdate.Int64, 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
if policy2.BlockHeight.Valid {
|
if policy2.BlockHeight.Valid {
|
||||||
node2Block = uint32(
|
node2Block = uint32(
|
||||||
policy2.BlockHeight.Int64,
|
policy2.BlockHeight.Int64,
|
||||||
@@ -2472,11 +2508,11 @@ func (s *SQLStore) HasChannelEdge(v lnwire.GossipVersion,
|
|||||||
|
|
||||||
var entry rejectCacheEntry
|
var entry rejectCacheEntry
|
||||||
switch v {
|
switch v {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
entry = newRejectCacheEntryV1(
|
entry = newRejectCacheEntryV1(
|
||||||
node1LastUpdate, node2LastUpdate, exists, isZombie,
|
node1LastUpdate, node2LastUpdate, exists, isZombie,
|
||||||
)
|
)
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
entry = newRejectCacheEntryV2(
|
entry = newRejectCacheEntryV2(
|
||||||
node1Block, node2Block, exists, isZombie,
|
node1Block, node2Block, exists, isZombie,
|
||||||
)
|
)
|
||||||
@@ -2491,7 +2527,9 @@ func (s *SQLStore) HasChannelEdge(v lnwire.GossipVersion,
|
|||||||
// the database, then ErrEdgeNotFound is returned.
|
// the database, then ErrEdgeNotFound is returned.
|
||||||
//
|
//
|
||||||
// NOTE: part of the Store interface.
|
// NOTE: part of the Store interface.
|
||||||
func (s *SQLStore) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
|
func (s *SQLStore) ChannelID(v lnwire.GossipVersion,
|
||||||
|
chanPoint *wire.OutPoint) (uint64, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctx = context.TODO()
|
ctx = context.TODO()
|
||||||
channelID uint64
|
channelID uint64
|
||||||
@@ -2500,7 +2538,7 @@ func (s *SQLStore) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
|
|||||||
chanID, err := db.GetSCIDByOutpoint(
|
chanID, err := db.GetSCIDByOutpoint(
|
||||||
ctx, sqlc.GetSCIDByOutpointParams{
|
ctx, sqlc.GetSCIDByOutpointParams{
|
||||||
Outpoint: chanPoint.String(),
|
Outpoint: chanPoint.String(),
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(v),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
@@ -2538,9 +2576,9 @@ func (s *SQLStore) IsPublicNode(v lnwire.GossipVersion, pubKey [33]byte) (bool,
|
|||||||
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
var err error
|
var err error
|
||||||
switch v {
|
switch v {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
isPublic, err = db.IsPublicV1Node(ctx, pubKey[:])
|
isPublic, err = db.IsPublicV1Node(ctx, pubKey[:])
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
isPublic, err = db.IsPublicV2Node(ctx, pubKey[:])
|
isPublic, err = db.IsPublicV2Node(ctx, pubKey[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2561,12 +2599,18 @@ func (s *SQLStore) IsPublicNode(v lnwire.GossipVersion, pubKey [33]byte) (bool,
|
|||||||
// fill in gaps in their view of the channel graph.
|
// fill in gaps in their view of the channel graph.
|
||||||
//
|
//
|
||||||
// NOTE: part of the Store interface.
|
// NOTE: part of the Store interface.
|
||||||
func (s *SQLStore) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
|
func (s *SQLStore) FetchChanInfos(v lnwire.GossipVersion,
|
||||||
|
chanIDs []uint64) ([]ChannelEdge, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctx = context.TODO()
|
ctx = context.TODO()
|
||||||
edges = make(map[uint64]ChannelEdge)
|
edges = make(map[uint64]ChannelEdge)
|
||||||
)
|
)
|
||||||
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
|
if !isKnownGossipVersion(v) {
|
||||||
|
return fmt.Errorf("unsupported gossip version: %d", v)
|
||||||
|
}
|
||||||
|
|
||||||
// First, collect all channel rows.
|
// First, collect all channel rows.
|
||||||
var channelRows []sqlc.GetChannelsBySCIDWithPoliciesRow
|
var channelRows []sqlc.GetChannelsBySCIDWithPoliciesRow
|
||||||
chanCallBack := func(ctx context.Context,
|
chanCallBack := func(ctx context.Context,
|
||||||
@@ -2577,7 +2621,7 @@ func (s *SQLStore) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := s.forEachChanWithPoliciesInSCIDList(
|
err := s.forEachChanWithPoliciesInSCIDList(
|
||||||
ctx, db, lnwire.GossipVersion1, chanCallBack, chanIDs,
|
ctx, db, v, chanCallBack, chanIDs,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -2901,7 +2945,7 @@ func (s *SQLStore) PruneGraph(spentOutputs []*wire.OutPoint,
|
|||||||
|
|
||||||
for _, channel := range closedChans {
|
for _, channel := range closedChans {
|
||||||
s.rejectCache.remove(channel.Version, channel.ChannelID)
|
s.rejectCache.remove(channel.Version, channel.ChannelID)
|
||||||
s.chanCache.remove(channel.ChannelID)
|
s.chanCache.remove(channel.Version, channel.ChannelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return closedChans, prunedNodes, nil
|
return closedChans, prunedNodes, nil
|
||||||
@@ -3170,7 +3214,7 @@ func (s *SQLStore) DisconnectBlockAtHeight(height uint32) (
|
|||||||
s.cacheMu.Lock()
|
s.cacheMu.Lock()
|
||||||
for _, channel := range removedChans {
|
for _, channel := range removedChans {
|
||||||
s.rejectCache.remove(channel.Version, channel.ChannelID)
|
s.rejectCache.remove(channel.Version, channel.ChannelID)
|
||||||
s.chanCache.remove(channel.ChannelID)
|
s.chanCache.remove(channel.Version, channel.ChannelID)
|
||||||
}
|
}
|
||||||
s.cacheMu.Unlock()
|
s.cacheMu.Unlock()
|
||||||
|
|
||||||
@@ -3199,7 +3243,7 @@ func (s *SQLStore) AddEdgeProof(scid lnwire.ShortChannelID,
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
switch proof.Version {
|
switch proof.Version {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
res, err = db.AddV1ChannelProof(
|
res, err = db.AddV1ChannelProof(
|
||||||
ctx, sqlc.AddV1ChannelProofParams{
|
ctx, sqlc.AddV1ChannelProofParams{
|
||||||
Scid: scidBytes,
|
Scid: scidBytes,
|
||||||
@@ -3210,7 +3254,7 @@ func (s *SQLStore) AddEdgeProof(scid lnwire.ShortChannelID,
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
res, err = db.AddV2ChannelProof(
|
res, err = db.AddV2ChannelProof(
|
||||||
ctx, sqlc.AddV2ChannelProofParams{
|
ctx, sqlc.AddV2ChannelProofParams{
|
||||||
Scid: scidBytes,
|
Scid: scidBytes,
|
||||||
@@ -3332,12 +3376,15 @@ func newSQLNodeTraverser(db SQLQueries,
|
|||||||
// node.
|
// node.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the NodeTraverser interface.
|
// NOTE: Part of the NodeTraverser interface.
|
||||||
func (s *sqlNodeTraverser) ForEachNodeDirectedChannel(nodePub route.Vertex,
|
func (s *sqlNodeTraverser) ForEachNodeDirectedChannel(
|
||||||
cb func(channel *DirectedChannel) error, _ func()) error {
|
nodePub route.Vertex, cb func(channel *DirectedChannel) error,
|
||||||
|
_ func()) error {
|
||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
return forEachNodeDirectedChannel(ctx, s.db, nodePub, cb)
|
return forEachNodeDirectedChannel(
|
||||||
|
ctx, s.db, lnwire.GossipVersion1, nodePub, cb,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchNodeFeatures returns the features of the given node. If the node is
|
// FetchNodeFeatures returns the features of the given node. If the node is
|
||||||
@@ -3357,7 +3404,8 @@ func (s *sqlNodeTraverser) FetchNodeFeatures(nodePub route.Vertex) (
|
|||||||
// channel and its incoming policy. If the node is not found, no error is
|
// channel and its incoming policy. If the node is not found, no error is
|
||||||
// returned.
|
// returned.
|
||||||
func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries,
|
func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries,
|
||||||
nodePub route.Vertex, cb func(channel *DirectedChannel) error) error {
|
v lnwire.GossipVersion, nodePub route.Vertex,
|
||||||
|
cb func(channel *DirectedChannel) error) error {
|
||||||
|
|
||||||
toNodeCallback := func() route.Vertex {
|
toNodeCallback := func() route.Vertex {
|
||||||
return nodePub
|
return nodePub
|
||||||
@@ -3365,7 +3413,7 @@ func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries,
|
|||||||
|
|
||||||
dbID, err := db.GetNodeIDByPubKey(
|
dbID, err := db.GetNodeIDByPubKey(
|
||||||
ctx, sqlc.GetNodeIDByPubKeyParams{
|
ctx, sqlc.GetNodeIDByPubKeyParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(v),
|
||||||
PubKey: nodePub[:],
|
PubKey: nodePub[:],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -3377,7 +3425,7 @@ func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries,
|
|||||||
|
|
||||||
rows, err := db.ListChannelsByNodeID(
|
rows, err := db.ListChannelsByNodeID(
|
||||||
ctx, sqlc.ListChannelsByNodeIDParams{
|
ctx, sqlc.ListChannelsByNodeIDParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(v),
|
||||||
NodeID1: dbID,
|
NodeID1: dbID,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -3464,11 +3512,12 @@ func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// forEachNodeCacheable fetches all V1 node IDs and pub keys from the database,
|
// forEachNodeCacheable fetches all node IDs and pub keys from the database,
|
||||||
// and executes the provided callback for each node. It does so via pagination
|
// and executes the provided callback for each node. It does so via pagination
|
||||||
// along with batch loading of the node feature bits.
|
// along with batch loading of the node feature bits.
|
||||||
func forEachNodeCacheable(ctx context.Context, cfg *sqldb.QueryConfig,
|
func forEachNodeCacheable(ctx context.Context, cfg *sqldb.QueryConfig,
|
||||||
db SQLQueries, processNode func(nodeID int64, nodePub route.Vertex,
|
db SQLQueries, v lnwire.GossipVersion,
|
||||||
|
processNode func(nodeID int64, nodePub route.Vertex,
|
||||||
features *lnwire.FeatureVector) error) error {
|
features *lnwire.FeatureVector) error) error {
|
||||||
|
|
||||||
handleNode := func(_ context.Context,
|
handleNode := func(_ context.Context,
|
||||||
@@ -3493,7 +3542,7 @@ func forEachNodeCacheable(ctx context.Context, cfg *sqldb.QueryConfig,
|
|||||||
|
|
||||||
return db.ListNodeIDsAndPubKeys(
|
return db.ListNodeIDsAndPubKeys(
|
||||||
ctx, sqlc.ListNodeIDsAndPubKeysParams{
|
ctx, sqlc.ListNodeIDsAndPubKeysParams{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: int16(v),
|
||||||
ID: lastID,
|
ID: lastID,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
},
|
},
|
||||||
@@ -3685,7 +3734,8 @@ func updateChanEdgePolicy(ctx context.Context, tx SQLQueries,
|
|||||||
Signature: edge.SigBytes,
|
Signature: edge.SigBytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
if version == lnwire.GossipVersion1 {
|
switch version {
|
||||||
|
case gossipV1:
|
||||||
params.LastUpdate = sqldb.SQLInt64(edge.LastUpdate.Unix())
|
params.LastUpdate = sqldb.SQLInt64(edge.LastUpdate.Unix())
|
||||||
params.Disabled = sql.NullBool{
|
params.Disabled = sql.NullBool{
|
||||||
Valid: true,
|
Valid: true,
|
||||||
@@ -3695,7 +3745,7 @@ func updateChanEdgePolicy(ctx context.Context, tx SQLQueries,
|
|||||||
Valid: edge.MessageFlags.HasMaxHtlc(),
|
Valid: edge.MessageFlags.HasMaxHtlc(),
|
||||||
Int64: int64(edge.MaxHTLC),
|
Int64: int64(edge.MaxHTLC),
|
||||||
}
|
}
|
||||||
} else {
|
case gossipV2:
|
||||||
params.BlockHeight = sqldb.SQLInt64(
|
params.BlockHeight = sqldb.SQLInt64(
|
||||||
int64(edge.LastBlockHeight),
|
int64(edge.LastBlockHeight),
|
||||||
)
|
)
|
||||||
@@ -3712,7 +3762,7 @@ func updateChanEdgePolicy(ctx context.Context, tx SQLQueries,
|
|||||||
// Convert the flat extra opaque data into a map of TLV types to
|
// Convert the flat extra opaque data into a map of TLV types to
|
||||||
// values.
|
// values.
|
||||||
extra := edge.ExtraSignedFields
|
extra := edge.ExtraSignedFields
|
||||||
if version == lnwire.GossipVersion1 {
|
if version == gossipV1 {
|
||||||
extra, err = marshalExtraOpaqueData(edge.ExtraOpaqueData)
|
extra, err = marshalExtraOpaqueData(edge.ExtraOpaqueData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node1Pub, node2Pub, false, fmt.Errorf(
|
return node1Pub, node2Pub, false, fmt.Errorf(
|
||||||
@@ -3788,9 +3838,9 @@ func buildNode(ctx context.Context, cfg *sqldb.QueryConfig, db SQLQueries,
|
|||||||
// and supported.
|
// and supported.
|
||||||
func isKnownGossipVersion(v lnwire.GossipVersion) bool {
|
func isKnownGossipVersion(v lnwire.GossipVersion) bool {
|
||||||
switch v {
|
switch v {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
return true
|
return true
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
@@ -3864,7 +3914,7 @@ func buildNodeWithBatchData(dbNode sqlc.GraphNode,
|
|||||||
|
|
||||||
// Use preloaded extra fields.
|
// Use preloaded extra fields.
|
||||||
if extraFields, exists := batchData.extraFields[dbNode.ID]; exists {
|
if extraFields, exists := batchData.extraFields[dbNode.ID]; exists {
|
||||||
if v == lnwire.GossipVersion1 {
|
if v == gossipV1 {
|
||||||
records := lnwire.CustomRecords(extraFields)
|
records := lnwire.CustomRecords(extraFields)
|
||||||
recs, err := records.Serialize()
|
recs, err := records.Serialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -3957,7 +4007,7 @@ func upsertNodeAncillaryData(ctx context.Context, db SQLQueries,
|
|||||||
// Convert the flat extra opaque data into a map of TLV types to
|
// Convert the flat extra opaque data into a map of TLV types to
|
||||||
// values.
|
// values.
|
||||||
extra := node.ExtraSignedFields
|
extra := node.ExtraSignedFields
|
||||||
if node.Version == lnwire.GossipVersion1 {
|
if node.Version == gossipV1 {
|
||||||
extra, err = marshalExtraOpaqueData(node.ExtraOpaqueData)
|
extra, err = marshalExtraOpaqueData(node.ExtraOpaqueData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to marshal extra opaque "+
|
return fmt.Errorf("unable to marshal extra opaque "+
|
||||||
@@ -3996,10 +4046,10 @@ func populateNodeParams(node *models.Node,
|
|||||||
})
|
})
|
||||||
|
|
||||||
switch node.Version {
|
switch node.Version {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
lastUpdate = sqldb.SQLInt64(node.LastUpdate.Unix())
|
lastUpdate = sqldb.SQLInt64(node.LastUpdate.Unix())
|
||||||
|
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
lastBlockHeight = sqldb.SQLInt64(int64(node.LastBlockHeight))
|
lastBlockHeight = sqldb.SQLInt64(int64(node.LastBlockHeight))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -4576,7 +4626,7 @@ func insertChannel(ctx context.Context, db SQLQueries,
|
|||||||
|
|
||||||
// Finally, insert any extra TLV fields in the channel announcement.
|
// Finally, insert any extra TLV fields in the channel announcement.
|
||||||
extra := edge.ExtraSignedFields
|
extra := edge.ExtraSignedFields
|
||||||
if v == lnwire.GossipVersion1 {
|
if v == gossipV1 {
|
||||||
extra, err = marshalExtraOpaqueData(edge.ExtraOpaqueData)
|
extra, err = marshalExtraOpaqueData(edge.ExtraOpaqueData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to marshal extra opaque "+
|
return fmt.Errorf("unable to marshal extra opaque "+
|
||||||
@@ -4722,7 +4772,7 @@ func buildEdgeInfoWithBatchData(chain chainhash.Hash,
|
|||||||
// Build the appropriate channel based on version.
|
// Build the appropriate channel based on version.
|
||||||
var channel *models.ChannelEdgeInfo
|
var channel *models.ChannelEdgeInfo
|
||||||
switch v {
|
switch v {
|
||||||
case lnwire.GossipVersion1:
|
case gossipV1:
|
||||||
// For v1, serialize extras into ExtraOpaqueData.
|
// For v1, serialize extras into ExtraOpaqueData.
|
||||||
recs, err := lnwire.CustomRecords(extras).Serialize()
|
recs, err := lnwire.CustomRecords(extras).Serialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -4771,7 +4821,7 @@ func buildEdgeInfoWithBatchData(chain chainhash.Hash,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
case lnwire.GossipVersion2:
|
case gossipV2:
|
||||||
v2Fields := &models.ChannelV2Fields{
|
v2Fields := &models.ChannelV2Fields{
|
||||||
ExtraSignedFields: extras,
|
ExtraSignedFields: extras,
|
||||||
}
|
}
|
||||||
@@ -4871,16 +4921,15 @@ func getAndBuildChanPolicies(ctx context.Context, cfg *sqldb.QueryConfig,
|
|||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(elle): update to support v2 policies.
|
|
||||||
if dbPol1 != nil &&
|
if dbPol1 != nil &&
|
||||||
lnwire.GossipVersion(dbPol1.Version) != lnwire.GossipVersion1 {
|
!isKnownGossipVersion(lnwire.GossipVersion(dbPol1.Version)) {
|
||||||
|
|
||||||
return nil, nil, fmt.Errorf("unsupported policy1 version: %d",
|
return nil, nil, fmt.Errorf("unsupported policy1 version: %d",
|
||||||
dbPol1.Version)
|
dbPol1.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbPol2 != nil &&
|
if dbPol2 != nil &&
|
||||||
lnwire.GossipVersion(dbPol2.Version) != lnwire.GossipVersion1 {
|
!isKnownGossipVersion(lnwire.GossipVersion(dbPol2.Version)) {
|
||||||
|
|
||||||
return nil, nil, fmt.Errorf("unsupported policy2 version: %d",
|
return nil, nil, fmt.Errorf("unsupported policy2 version: %d",
|
||||||
dbPol2.Version)
|
dbPol2.Version)
|
||||||
@@ -4985,7 +5034,7 @@ func buildChanPolicy(isNode1 bool, dbPolicy sqlc.GraphChannelPolicy,
|
|||||||
InboundFee: inboundFee,
|
InboundFee: inboundFee,
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Version == lnwire.GossipVersion1 {
|
if p.Version != gossipV2 {
|
||||||
recs, err := lnwire.CustomRecords(extras).Serialize()
|
recs, err := lnwire.CustomRecords(extras).Serialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to serialize extra "+
|
return nil, fmt.Errorf("unable to serialize extra "+
|
||||||
@@ -5033,7 +5082,7 @@ func extractChannelPolicies(row any) (*sqlc.GraphChannelPolicy,
|
|||||||
case sqlc.ListChannelsWithPoliciesForCachePaginatedRow:
|
case sqlc.ListChannelsWithPoliciesForCachePaginatedRow:
|
||||||
if r.Policy1Timelock.Valid {
|
if r.Policy1Timelock.Valid {
|
||||||
policy1 = &sqlc.GraphChannelPolicy{
|
policy1 = &sqlc.GraphChannelPolicy{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: r.Policy1Version.Int16,
|
||||||
Timelock: r.Policy1Timelock.Int32,
|
Timelock: r.Policy1Timelock.Int32,
|
||||||
FeePpm: r.Policy1FeePpm.Int64,
|
FeePpm: r.Policy1FeePpm.Int64,
|
||||||
BaseFeeMsat: r.Policy1BaseFeeMsat.Int64,
|
BaseFeeMsat: r.Policy1BaseFeeMsat.Int64,
|
||||||
@@ -5050,7 +5099,7 @@ func extractChannelPolicies(row any) (*sqlc.GraphChannelPolicy,
|
|||||||
}
|
}
|
||||||
if r.Policy2Timelock.Valid {
|
if r.Policy2Timelock.Valid {
|
||||||
policy2 = &sqlc.GraphChannelPolicy{
|
policy2 = &sqlc.GraphChannelPolicy{
|
||||||
Version: int16(lnwire.GossipVersion1),
|
Version: r.Policy2Version.Int16,
|
||||||
Timelock: r.Policy2Timelock.Int32,
|
Timelock: r.Policy2Timelock.Int32,
|
||||||
FeePpm: r.Policy2FeePpm.Int64,
|
FeePpm: r.Policy2FeePpm.Int64,
|
||||||
BaseFeeMsat: r.Policy2BaseFeeMsat.Int64,
|
BaseFeeMsat: r.Policy2BaseFeeMsat.Int64,
|
||||||
@@ -6352,7 +6401,7 @@ func handleZombieMarking(ctx context.Context, db SQLQueries,
|
|||||||
|
|
||||||
if strictZombiePruning {
|
if strictZombiePruning {
|
||||||
// TODO(elle): update for V2 last update times.
|
// TODO(elle): update for V2 last update times.
|
||||||
if v != lnwire.GossipVersion1 {
|
if v != gossipV1 {
|
||||||
return fmt.Errorf("strict zombie pruning only "+
|
return fmt.Errorf("strict zombie pruning only "+
|
||||||
"supported for gossip v1, got %v", v)
|
"supported for gossip v1, got %v", v)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -1461,8 +1461,7 @@ func processNodeForBlindedPath(g Graph, node route.Vertex,
|
|||||||
// Now, iterate over the node's channels in search for paths to this
|
// Now, iterate over the node's channels in search for paths to this
|
||||||
// node that can be used for blinded paths
|
// node that can be used for blinded paths
|
||||||
err = g.ForEachNodeDirectedChannel(
|
err = g.ForEachNodeDirectedChannel(
|
||||||
node,
|
node, func(channel *graphdb.DirectedChannel) error {
|
||||||
func(channel *graphdb.DirectedChannel) error {
|
|
||||||
// Keep track of how many incoming channels this node
|
// Keep track of how many incoming channels this node
|
||||||
// has. We only use a node as an introduction node if it
|
// has. We only use a node as an introduction node if it
|
||||||
// has channels other than the one that lead us to it.
|
// has channels other than the one that lead us to it.
|
||||||
|
|||||||
@@ -1042,7 +1042,9 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
return nil, fmt.Errorf("can't create router: %w", err)
|
return nil, fmt.Errorf("can't create router: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chanSeries := discovery.NewChanSeries(s.graphDB)
|
chanSeries := discovery.NewChanSeries(
|
||||||
|
graphdb.NewVersionedGraph(s.graphDB, lnwire.GossipVersion1),
|
||||||
|
)
|
||||||
gossipMessageStore, err := discovery.NewMessageStore(dbs.ChanStateDB)
|
gossipMessageStore, err := discovery.NewMessageStore(dbs.ChanStateDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -3576,7 +3578,10 @@ func (s *server) establishPersistentConnections(ctx context.Context) error {
|
|||||||
graphAddrs[pubStr] = n
|
graphAddrs[pubStr] = n
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = s.graphDB.ForEachSourceNodeChannel(
|
|
||||||
|
// TODO(elle): for now, we only fetch our V1 channels. This should be
|
||||||
|
// updated to fetch channels across all versions.
|
||||||
|
err = s.v1Graph.ForEachSourceNodeChannel(
|
||||||
ctx, forEachSrcNodeChan, func() {
|
ctx, forEachSrcNodeChan, func() {
|
||||||
clear(graphAddrs)
|
clear(graphAddrs)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2410,6 +2410,41 @@ func (q *Queries) GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error) {
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getV2DisabledSCIDs = `-- name: GetV2DisabledSCIDs :many
|
||||||
|
SELECT c.scid
|
||||||
|
FROM graph_channels c
|
||||||
|
JOIN graph_channel_policies cp ON cp.channel_id = c.id
|
||||||
|
WHERE COALESCE(cp.disable_flags, 0) != 0
|
||||||
|
AND c.version = 2
|
||||||
|
GROUP BY c.scid
|
||||||
|
HAVING COUNT(*) > 1
|
||||||
|
`
|
||||||
|
|
||||||
|
// NOTE: this is V2 specific since V2 uses a disable flag
|
||||||
|
// bit vector instead of a single boolean.
|
||||||
|
func (q *Queries) GetV2DisabledSCIDs(ctx context.Context) ([][]byte, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getV2DisabledSCIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items [][]byte
|
||||||
|
for rows.Next() {
|
||||||
|
var scid []byte
|
||||||
|
if err := rows.Scan(&scid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, scid)
|
||||||
|
}
|
||||||
|
if err := rows.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
const getZombieChannel = `-- name: GetZombieChannel :one
|
const getZombieChannel = `-- name: GetZombieChannel :one
|
||||||
SELECT scid, version, node_key_1, node_key_2
|
SELECT scid, version, node_key_1, node_key_2
|
||||||
FROM graph_zombie_channels
|
FROM graph_zombie_channels
|
||||||
@@ -3299,6 +3334,7 @@ SELECT
|
|||||||
n2.pub_key AS node2_pubkey,
|
n2.pub_key AS node2_pubkey,
|
||||||
|
|
||||||
-- Node 1 policy
|
-- Node 1 policy
|
||||||
|
cp1.version AS policy1_version,
|
||||||
cp1.timelock AS policy_1_timelock,
|
cp1.timelock AS policy_1_timelock,
|
||||||
cp1.fee_ppm AS policy_1_fee_ppm,
|
cp1.fee_ppm AS policy_1_fee_ppm,
|
||||||
cp1.base_fee_msat AS policy_1_base_fee_msat,
|
cp1.base_fee_msat AS policy_1_base_fee_msat,
|
||||||
@@ -3313,6 +3349,7 @@ SELECT
|
|||||||
cp1.disable_flags AS policy1_disable_flags,
|
cp1.disable_flags AS policy1_disable_flags,
|
||||||
|
|
||||||
-- Node 2 policy
|
-- Node 2 policy
|
||||||
|
cp2.version AS policy2_version,
|
||||||
cp2.timelock AS policy_2_timelock,
|
cp2.timelock AS policy_2_timelock,
|
||||||
cp2.fee_ppm AS policy_2_fee_ppm,
|
cp2.fee_ppm AS policy_2_fee_ppm,
|
||||||
cp2.base_fee_msat AS policy_2_base_fee_msat,
|
cp2.base_fee_msat AS policy_2_base_fee_msat,
|
||||||
@@ -3350,6 +3387,7 @@ type ListChannelsWithPoliciesForCachePaginatedRow struct {
|
|||||||
Capacity sql.NullInt64
|
Capacity sql.NullInt64
|
||||||
Node1Pubkey []byte
|
Node1Pubkey []byte
|
||||||
Node2Pubkey []byte
|
Node2Pubkey []byte
|
||||||
|
Policy1Version sql.NullInt16
|
||||||
Policy1Timelock sql.NullInt32
|
Policy1Timelock sql.NullInt32
|
||||||
Policy1FeePpm sql.NullInt64
|
Policy1FeePpm sql.NullInt64
|
||||||
Policy1BaseFeeMsat sql.NullInt64
|
Policy1BaseFeeMsat sql.NullInt64
|
||||||
@@ -3362,6 +3400,7 @@ type ListChannelsWithPoliciesForCachePaginatedRow struct {
|
|||||||
Policy1ChannelFlags sql.NullInt16
|
Policy1ChannelFlags sql.NullInt16
|
||||||
Policy1BlockHeight sql.NullInt64
|
Policy1BlockHeight sql.NullInt64
|
||||||
Policy1DisableFlags sql.NullInt16
|
Policy1DisableFlags sql.NullInt16
|
||||||
|
Policy2Version sql.NullInt16
|
||||||
Policy2Timelock sql.NullInt32
|
Policy2Timelock sql.NullInt32
|
||||||
Policy2FeePpm sql.NullInt64
|
Policy2FeePpm sql.NullInt64
|
||||||
Policy2BaseFeeMsat sql.NullInt64
|
Policy2BaseFeeMsat sql.NullInt64
|
||||||
@@ -3391,6 +3430,7 @@ func (q *Queries) ListChannelsWithPoliciesForCachePaginated(ctx context.Context,
|
|||||||
&i.Capacity,
|
&i.Capacity,
|
||||||
&i.Node1Pubkey,
|
&i.Node1Pubkey,
|
||||||
&i.Node2Pubkey,
|
&i.Node2Pubkey,
|
||||||
|
&i.Policy1Version,
|
||||||
&i.Policy1Timelock,
|
&i.Policy1Timelock,
|
||||||
&i.Policy1FeePpm,
|
&i.Policy1FeePpm,
|
||||||
&i.Policy1BaseFeeMsat,
|
&i.Policy1BaseFeeMsat,
|
||||||
@@ -3403,6 +3443,7 @@ func (q *Queries) ListChannelsWithPoliciesForCachePaginated(ctx context.Context,
|
|||||||
&i.Policy1ChannelFlags,
|
&i.Policy1ChannelFlags,
|
||||||
&i.Policy1BlockHeight,
|
&i.Policy1BlockHeight,
|
||||||
&i.Policy1DisableFlags,
|
&i.Policy1DisableFlags,
|
||||||
|
&i.Policy2Version,
|
||||||
&i.Policy2Timelock,
|
&i.Policy2Timelock,
|
||||||
&i.Policy2FeePpm,
|
&i.Policy2FeePpm,
|
||||||
&i.Policy2BaseFeeMsat,
|
&i.Policy2BaseFeeMsat,
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ type Querier interface {
|
|||||||
// structure will have a more complex disabled bit vector
|
// structure will have a more complex disabled bit vector
|
||||||
// and so the query for V2 may differ.
|
// and so the query for V2 may differ.
|
||||||
GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error)
|
GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error)
|
||||||
|
// NOTE: this is V2 specific since V2 uses a disable flag
|
||||||
|
// bit vector instead of a single boolean.
|
||||||
|
GetV2DisabledSCIDs(ctx context.Context) ([][]byte, error)
|
||||||
GetZombieChannel(ctx context.Context, arg GetZombieChannelParams) (GraphZombieChannel, error)
|
GetZombieChannel(ctx context.Context, arg GetZombieChannelParams) (GraphZombieChannel, error)
|
||||||
GetZombieChannelsSCIDs(ctx context.Context, arg GetZombieChannelsSCIDsParams) ([]GraphZombieChannel, error)
|
GetZombieChannelsSCIDs(ctx context.Context, arg GetZombieChannelsSCIDsParams) ([]GraphZombieChannel, error)
|
||||||
HighestSCID(ctx context.Context, version int16) ([]byte, error)
|
HighestSCID(ctx context.Context, version int16) ([]byte, error)
|
||||||
|
|||||||
@@ -834,6 +834,7 @@ SELECT
|
|||||||
n2.pub_key AS node2_pubkey,
|
n2.pub_key AS node2_pubkey,
|
||||||
|
|
||||||
-- Node 1 policy
|
-- Node 1 policy
|
||||||
|
cp1.version AS policy1_version,
|
||||||
cp1.timelock AS policy_1_timelock,
|
cp1.timelock AS policy_1_timelock,
|
||||||
cp1.fee_ppm AS policy_1_fee_ppm,
|
cp1.fee_ppm AS policy_1_fee_ppm,
|
||||||
cp1.base_fee_msat AS policy_1_base_fee_msat,
|
cp1.base_fee_msat AS policy_1_base_fee_msat,
|
||||||
@@ -848,6 +849,7 @@ SELECT
|
|||||||
cp1.disable_flags AS policy1_disable_flags,
|
cp1.disable_flags AS policy1_disable_flags,
|
||||||
|
|
||||||
-- Node 2 policy
|
-- Node 2 policy
|
||||||
|
cp2.version AS policy2_version,
|
||||||
cp2.timelock AS policy_2_timelock,
|
cp2.timelock AS policy_2_timelock,
|
||||||
cp2.fee_ppm AS policy_2_fee_ppm,
|
cp2.fee_ppm AS policy_2_fee_ppm,
|
||||||
cp2.base_fee_msat AS policy_2_base_fee_msat,
|
cp2.base_fee_msat AS policy_2_base_fee_msat,
|
||||||
@@ -1066,6 +1068,17 @@ AND c.version = 1
|
|||||||
GROUP BY c.scid
|
GROUP BY c.scid
|
||||||
HAVING COUNT(*) > 1;
|
HAVING COUNT(*) > 1;
|
||||||
|
|
||||||
|
-- name: GetV2DisabledSCIDs :many
|
||||||
|
SELECT c.scid
|
||||||
|
FROM graph_channels c
|
||||||
|
JOIN graph_channel_policies cp ON cp.channel_id = c.id
|
||||||
|
-- NOTE: this is V2 specific since V2 uses a disable flag
|
||||||
|
-- bit vector instead of a single boolean.
|
||||||
|
WHERE COALESCE(cp.disable_flags, 0) != 0
|
||||||
|
AND c.version = 2
|
||||||
|
GROUP BY c.scid
|
||||||
|
HAVING COUNT(*) > 1;
|
||||||
|
|
||||||
-- name: DeleteChannelPolicyExtraTypes :exec
|
-- name: DeleteChannelPolicyExtraTypes :exec
|
||||||
DELETE FROM graph_channel_policy_extra_types
|
DELETE FROM graph_channel_policy_extra_types
|
||||||
WHERE channel_policy_id = $1;
|
WHERE channel_policy_id = $1;
|
||||||
|
|||||||
Reference in new issue
Block a user