multi: extract and pass through IsZombieChannel method

This commit is contained in:
Elle Mouton
2023-09-20 10:58:42 +02:00
parent 67df687f08
commit e12321cfd6
5 changed files with 77 additions and 25 deletions

View File

@@ -335,6 +335,11 @@ type Config struct {
// to without iterating over the entire set of open channels. // to without iterating over the entire set of open channels.
FindChannel func(node *btcec.PublicKey, chanID lnwire.ChannelID) ( FindChannel func(node *btcec.PublicKey, chanID lnwire.ChannelID) (
*channeldb.OpenChannel, error) *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 // 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, IgnoreHistoricalFilters: cfg.IgnoreHistoricalFilters,
BestHeight: gossiper.latestHeight, BestHeight: gossiper.latestHeight,
PinnedSyncers: cfg.PinnedSyncers, PinnedSyncers: cfg.PinnedSyncers,
IsStillZombieChannel: cfg.IsStillZombieChannel,
}) })
gossiper.reliableSender = newReliableSender(&reliableSenderCfg{ gossiper.reliableSender = newReliableSender(&reliableSenderCfg{

View File

@@ -102,6 +102,11 @@ type SyncManagerCfg struct {
// ActiveSync upon connection. These peers will never transition to // ActiveSync upon connection. These peers will never transition to
// PassiveSync. // PassiveSync.
PinnedSyncers PinnedSyncers 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 // 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, markGraphSynced: m.markGraphSynced,
maxQueryChanRangeReplies: maxQueryChanRangeReplies, maxQueryChanRangeReplies: maxQueryChanRangeReplies,
noTimestampQueryOption: m.cfg.NoTimestampQueries, noTimestampQueryOption: m.cfg.NoTimestampQueries,
isStillZombieChannel: m.cfg.IsStillZombieChannel,
}) })
// Gossip syncers are initialized by default in a PassiveSync type // Gossip syncers are initialized by default in a PassiveSync type

View File

@@ -293,6 +293,11 @@ type gossipSyncerCfg struct {
// maxQueryChanRangeReplies is the maximum number of replies we'll allow // maxQueryChanRangeReplies is the maximum number of replies we'll allow
// for a single QueryChannelRange request. // for a single QueryChannelRange request.
maxQueryChanRangeReplies uint32 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 // GossipSyncer is a struct that handles synchronizing the channel graph state

View File

@@ -888,6 +888,55 @@ func (r *ChannelRouter) syncGraphWithChain() error {
return nil 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 // pruneZombieChans is a method that will be called periodically to prune out
// any "zombie" channels. We consider channels zombies if *both* edges haven't // any "zombie" channels. We consider channels zombies if *both* edges haven't
// been updated since our zombie horizon. If AssumeChannelValid is present, // been updated since our zombie horizon. If AssumeChannelValid is present,
@@ -911,8 +960,10 @@ func (r *ChannelRouter) pruneZombieChans() error {
filterPruneChans := func(info *models.ChannelEdgeInfo, filterPruneChans := func(info *models.ChannelEdgeInfo,
e1, e2 *models.ChannelEdgePolicy) error { e1, e2 *models.ChannelEdgePolicy) error {
// Exit early in case this channel is already marked to be pruned // Exit early in case this channel is already marked to be
if _, markedToPrune := chansToPrune[info.ChannelID]; markedToPrune { // pruned
_, markedToPrune := chansToPrune[info.ChannelID]
if markedToPrune {
return nil return nil
} }
@@ -923,39 +974,22 @@ func (r *ChannelRouter) pruneZombieChans() error {
return nil return nil
} }
// If either edge hasn't been updated for a period of e1Zombie, e2Zombie, isZombieChan := r.isZombieChannel(e1, e2)
// 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
if e1Zombie { if e1Zombie {
log.Tracef("Node1 pubkey=%x of chan_id=%v is zombie", log.Tracef("Node1 pubkey=%x of chan_id=%v is zombie",
info.NodeKey1Bytes, info.ChannelID) info.NodeKey1Bytes, info.ChannelID)
} }
if e2Zombie { if e2Zombie {
log.Tracef("Node2 pubkey=%x of chan_id=%v is zombie", log.Tracef("Node2 pubkey=%x of chan_id=%v is zombie",
info.NodeKey2Bytes, info.ChannelID) info.NodeKey2Bytes, info.ChannelID)
} }
// If we're using strict zombie pruning, then a channel is only // If either edge hasn't been updated for a period of
// considered live if both edges have a recent update we know // chanExpiry, then we'll mark the channel itself as eligible
// of. // for graph pruning.
var channelIsLive bool if !isZombieChan {
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 {
return nil return nil
} }

View File

@@ -1030,6 +1030,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
FindBaseByAlias: s.aliasMgr.FindBaseSCID, FindBaseByAlias: s.aliasMgr.FindBaseSCID,
GetAlias: s.aliasMgr.GetPeerAlias, GetAlias: s.aliasMgr.GetPeerAlias,
FindChannel: s.findChannel, FindChannel: s.findChannel,
IsStillZombieChannel: s.chanRouter.IsZombieChannel,
}, nodeKeyDesc) }, nodeKeyDesc)
s.localChanMgr = &localchans.Manager{ s.localChanMgr = &localchans.Manager{