From e12321cfd6a645d74b4ddee93832a9760e1b2911 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 20 Sep 2023 10:58:42 +0200 Subject: [PATCH] multi: extract and pass through IsZombieChannel method --- discovery/gossiper.go | 6 +++ discovery/sync_manager.go | 6 +++ discovery/syncer.go | 5 +++ routing/router.go | 84 +++++++++++++++++++++++++++------------ server.go | 1 + 5 files changed, 77 insertions(+), 25 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 41653cad1..8fd18bf5e 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -335,6 +335,11 @@ type Config struct { // to without iterating over the entire set of open channels. FindChannel func(node *btcec.PublicKey, chanID lnwire.ChannelID) ( *channeldb.OpenChannel, error) + + // IsStillZombieChannel takes the timestamps of the latest channel + // updates for a channel and returns true if the channel should be + // considered a zombie based on these timestamps. + IsStillZombieChannel func(time.Time, time.Time) bool } // processedNetworkMsg is a wrapper around networkMsg and a boolean. It is @@ -519,6 +524,7 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper IgnoreHistoricalFilters: cfg.IgnoreHistoricalFilters, BestHeight: gossiper.latestHeight, PinnedSyncers: cfg.PinnedSyncers, + IsStillZombieChannel: cfg.IsStillZombieChannel, }) gossiper.reliableSender = newReliableSender(&reliableSenderCfg{ diff --git a/discovery/sync_manager.go b/discovery/sync_manager.go index 69916a073..39098f70e 100644 --- a/discovery/sync_manager.go +++ b/discovery/sync_manager.go @@ -102,6 +102,11 @@ type SyncManagerCfg struct { // ActiveSync upon connection. These peers will never transition to // PassiveSync. PinnedSyncers PinnedSyncers + + // IsStillZombieChannel takes the timestamps of the latest channel + // updates for a channel and returns true if the channel should be + // considered a zombie based on these timestamps. + IsStillZombieChannel func(time.Time, time.Time) bool } // SyncManager is a subsystem of the gossiper that manages the gossip syncers @@ -501,6 +506,7 @@ func (m *SyncManager) createGossipSyncer(peer lnpeer.Peer) *GossipSyncer { markGraphSynced: m.markGraphSynced, maxQueryChanRangeReplies: maxQueryChanRangeReplies, noTimestampQueryOption: m.cfg.NoTimestampQueries, + isStillZombieChannel: m.cfg.IsStillZombieChannel, }) // Gossip syncers are initialized by default in a PassiveSync type diff --git a/discovery/syncer.go b/discovery/syncer.go index 6b0234dd7..937b0abbb 100644 --- a/discovery/syncer.go +++ b/discovery/syncer.go @@ -293,6 +293,11 @@ type gossipSyncerCfg struct { // maxQueryChanRangeReplies is the maximum number of replies we'll allow // for a single QueryChannelRange request. maxQueryChanRangeReplies uint32 + + // isStillZombieChannel takes the timestamps of the latest channel + // updates for a channel and returns true if the channel should be + // considered a zombie based on these timestamps. + isStillZombieChannel func(time.Time, time.Time) bool } // GossipSyncer is a struct that handles synchronizing the channel graph state diff --git a/routing/router.go b/routing/router.go index 48aeead18..80f647807 100644 --- a/routing/router.go +++ b/routing/router.go @@ -888,6 +888,55 @@ func (r *ChannelRouter) syncGraphWithChain() error { return nil } +// isZombieChannel takes two edge policy updates and determines if the +// corresponding channel should be considered a zombie. The first boolean is +// true if the policy update from node 1 is considered a zombie, the second +// boolean is that of node 2, and the final boolean is true if the channel +// is considered a zombie. +func (r *ChannelRouter) isZombieChannel(e1, + e2 *models.ChannelEdgePolicy) (bool, bool, bool) { + + chanExpiry := r.cfg.ChannelPruneExpiry + + e1Zombie := e1 == nil || time.Since(e1.LastUpdate) >= chanExpiry + e2Zombie := e2 == nil || time.Since(e2.LastUpdate) >= chanExpiry + + var e1Time, e2Time time.Time + if e1 != nil { + e1Time = e1.LastUpdate + } + if e2 != nil { + e2Time = e2.LastUpdate + } + + return e1Zombie, e2Zombie, r.IsZombieChannel(e1Time, e2Time) +} + +// IsZombieChannel takes the timestamps of the latest channel updates for a +// channel and returns true if the channel should be considered a zombie based +// on these timestamps. +func (r *ChannelRouter) IsZombieChannel(updateTime1, + updateTime2 time.Time) bool { + + chanExpiry := r.cfg.ChannelPruneExpiry + + e1Zombie := updateTime1.IsZero() || + time.Since(updateTime1) >= chanExpiry + + e2Zombie := updateTime2.IsZero() || + time.Since(updateTime2) >= chanExpiry + + // If we're using strict zombie pruning, then a channel is only + // considered live if both edges have a recent update we know of. + if r.cfg.StrictZombiePruning { + return e1Zombie || e2Zombie + } + + // Otherwise, if we're using the less strict variant, then a channel is + // considered live if either of the edges have a recent update. + return e1Zombie && e2Zombie +} + // pruneZombieChans is a method that will be called periodically to prune out // any "zombie" channels. We consider channels zombies if *both* edges haven't // been updated since our zombie horizon. If AssumeChannelValid is present, @@ -911,8 +960,10 @@ func (r *ChannelRouter) pruneZombieChans() error { filterPruneChans := func(info *models.ChannelEdgeInfo, e1, e2 *models.ChannelEdgePolicy) error { - // Exit early in case this channel is already marked to be pruned - if _, markedToPrune := chansToPrune[info.ChannelID]; markedToPrune { + // Exit early in case this channel is already marked to be + // pruned + _, markedToPrune := chansToPrune[info.ChannelID] + if markedToPrune { return nil } @@ -923,39 +974,22 @@ func (r *ChannelRouter) pruneZombieChans() error { return nil } - // If either edge hasn't been updated for a period of - // chanExpiry, then we'll mark the channel itself as eligible - // for graph pruning. - e1Zombie := e1 == nil || time.Since(e1.LastUpdate) >= chanExpiry - e2Zombie := e2 == nil || time.Since(e2.LastUpdate) >= chanExpiry + e1Zombie, e2Zombie, isZombieChan := r.isZombieChannel(e1, e2) if e1Zombie { log.Tracef("Node1 pubkey=%x of chan_id=%v is zombie", info.NodeKey1Bytes, info.ChannelID) } + if e2Zombie { log.Tracef("Node2 pubkey=%x of chan_id=%v is zombie", info.NodeKey2Bytes, info.ChannelID) } - // If we're using strict zombie pruning, then a channel is only - // considered live if both edges have a recent update we know - // of. - var channelIsLive bool - switch { - case r.cfg.StrictZombiePruning: - channelIsLive = !e1Zombie && !e2Zombie - - // Otherwise, if we're using the less strict variant, then a - // channel is considered live if either of the edges have a - // recent update. - default: - channelIsLive = !e1Zombie || !e2Zombie - } - - // Return early if the channel is still considered to be live - // with the current set of configuration parameters. - if channelIsLive { + // If either edge hasn't been updated for a period of + // chanExpiry, then we'll mark the channel itself as eligible + // for graph pruning. + if !isZombieChan { return nil } diff --git a/server.go b/server.go index 184e9aa90..aed4d3c85 100644 --- a/server.go +++ b/server.go @@ -1030,6 +1030,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, FindBaseByAlias: s.aliasMgr.FindBaseSCID, GetAlias: s.aliasMgr.GetPeerAlias, FindChannel: s.findChannel, + IsStillZombieChannel: s.chanRouter.IsZombieChannel, }, nodeKeyDesc) s.localChanMgr = &localchans.Manager{