Skip to content

Commit 3b9b69b

Browse files
committed
discovery+routing: update to use ChanUpdate interface
In the IsKeepAlive and IsStaleEdgePolicy functions
1 parent 02b2760 commit 3b9b69b

File tree

4 files changed

+237
-98
lines changed

4 files changed

+237
-98
lines changed

discovery/gossiper.go

Lines changed: 115 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,48 +2407,114 @@ func (d *AuthenticatedGossiper) SyncManager() *SyncManager {
24072407
// IsKeepAliveUpdate determines whether this channel update is considered a
24082408
// keep-alive update based on the previous channel update processed for the same
24092409
// direction.
2410-
func IsKeepAliveUpdate(update *lnwire.ChannelUpdate1,
2411-
prev *models.ChannelEdgePolicy1) bool {
2410+
func IsKeepAliveUpdate(update lnwire.ChannelUpdate,
2411+
prevPolicy models.ChannelEdgePolicy) (bool, error) {
24122412

2413-
// Both updates should be from the same direction.
2414-
if update.ChannelFlags&lnwire.ChanUpdateDirection !=
2415-
prev.ChannelFlags&lnwire.ChanUpdateDirection {
2413+
switch upd := update.(type) {
2414+
case *lnwire.ChannelUpdate1:
2415+
prev, ok := prevPolicy.(*models.ChannelEdgePolicy1)
2416+
if !ok {
2417+
return false, fmt.Errorf("expected chan edge policy 1")
2418+
}
24162419

2417-
return false
2418-
}
2420+
// Both updates should be from the same direction.
2421+
if upd.ChannelFlags&lnwire.ChanUpdateDirection !=
2422+
prev.ChannelFlags&lnwire.ChanUpdateDirection {
24192423

2420-
// The timestamp should always increase for a keep-alive update.
2421-
timestamp := time.Unix(int64(update.Timestamp), 0)
2422-
if !timestamp.After(prev.LastUpdate) {
2423-
return false
2424-
}
2424+
return false, nil
2425+
}
24252426

2426-
// None of the remaining fields should change for a keep-alive update.
2427-
if update.ChannelFlags.IsDisabled() != prev.ChannelFlags.IsDisabled() {
2428-
return false
2429-
}
2430-
if lnwire.MilliSatoshi(update.BaseFee) != prev.FeeBaseMSat {
2431-
return false
2432-
}
2433-
if lnwire.MilliSatoshi(update.FeeRate) != prev.FeeProportionalMillionths {
2434-
return false
2435-
}
2436-
if update.TimeLockDelta != prev.TimeLockDelta {
2437-
return false
2438-
}
2439-
if update.HtlcMinimumMsat != prev.MinHTLC {
2440-
return false
2441-
}
2442-
if update.MessageFlags.HasMaxHtlc() && !prev.MessageFlags.HasMaxHtlc() {
2443-
return false
2444-
}
2445-
if update.HtlcMaximumMsat != prev.MaxHTLC {
2446-
return false
2447-
}
2448-
if !bytes.Equal(update.ExtraOpaqueData, prev.ExtraOpaqueData) {
2449-
return false
2427+
// The timestamp should always increase for a keep-alive update.
2428+
timestamp := time.Unix(int64(upd.Timestamp), 0)
2429+
if !timestamp.After(prev.LastUpdate) {
2430+
return false, nil
2431+
}
2432+
2433+
// None of the remaining fields should change for a keep-alive
2434+
// update.
2435+
if upd.ChannelFlags.IsDisabled() !=
2436+
prev.ChannelFlags.IsDisabled() {
2437+
2438+
return false, nil
2439+
}
2440+
if lnwire.MilliSatoshi(upd.BaseFee) != prev.FeeBaseMSat {
2441+
return false, nil
2442+
}
2443+
if lnwire.MilliSatoshi(upd.FeeRate) !=
2444+
prev.FeeProportionalMillionths {
2445+
2446+
return false, nil
2447+
}
2448+
if upd.TimeLockDelta != prev.TimeLockDelta {
2449+
return false, nil
2450+
}
2451+
if upd.HtlcMinimumMsat != prev.MinHTLC {
2452+
return false, nil
2453+
}
2454+
if upd.MessageFlags.HasMaxHtlc() &&
2455+
!prev.MessageFlags.HasMaxHtlc() {
2456+
2457+
return false, nil
2458+
}
2459+
if upd.HtlcMaximumMsat != prev.MaxHTLC {
2460+
return false, nil
2461+
}
2462+
if !bytes.Equal(upd.ExtraOpaqueData, prev.ExtraOpaqueData) {
2463+
return false, nil
2464+
}
2465+
2466+
return true, nil
2467+
2468+
case *lnwire.ChannelUpdate2:
2469+
prev, ok := prevPolicy.(*models.ChannelEdgePolicy2)
2470+
if !ok {
2471+
return false, fmt.Errorf("expected chan edge policy 2")
2472+
}
2473+
2474+
// Both updates should be from the same direction.
2475+
if upd.IsNode1() != prev.IsNode1() {
2476+
return false, nil
2477+
}
2478+
2479+
// The block-height should always increase for a keep-alive
2480+
// update.
2481+
if upd.BlockHeight.Val <= prev.BlockHeight.Val {
2482+
return false, nil
2483+
}
2484+
2485+
// None of the remaining fields should change for a keep-alive
2486+
// update.
2487+
if upd.IsDisabled() != prev.IsDisabled() {
2488+
return false, nil
2489+
}
2490+
fwd := upd.ForwardingPolicy()
2491+
prevFwd := upd.ForwardingPolicy()
2492+
2493+
if fwd.BaseFee != prevFwd.BaseFee {
2494+
return false, nil
2495+
}
2496+
if fwd.FeeRate != prevFwd.FeeRate {
2497+
return false, nil
2498+
}
2499+
if fwd.TimeLockDelta != prevFwd.TimeLockDelta {
2500+
return false, nil
2501+
}
2502+
if fwd.MinHTLC != prevFwd.MinHTLC {
2503+
return false, nil
2504+
}
2505+
if fwd.MaxHTLC != prevFwd.MinHTLC {
2506+
return false, nil
2507+
}
2508+
if !bytes.Equal(upd.ExtraOpaqueData, prev.ExtraOpaqueData) {
2509+
return false, nil
2510+
}
2511+
2512+
return true, nil
2513+
2514+
default:
2515+
return false, fmt.Errorf("unhandled implementation of "+
2516+
"ChannelUpdate: %T", update)
24502517
}
2451-
return true
24522518
}
24532519

24542520
// latestHeight returns the gossiper's latest height known of the chain.
@@ -2856,16 +2922,14 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
28562922
graphScid = upd.ShortChannelID
28572923
}
28582924

2859-
if d.cfg.Router.IsStaleEdgePolicy(
2860-
graphScid, timestamp, upd.ChannelFlags,
2861-
) {
2862-
2925+
if d.cfg.Router.IsStaleEdgePolicy(graphScid, upd) {
28632926
log.Debugf("Ignored stale edge policy for short_chan_id(%v): "+
28642927
"peer=%v, msg=%s, is_remote=%v", shortChanID,
28652928
nMsg.peer, nMsg.msg.MsgType(), nMsg.isRemote,
28662929
)
28672930

28682931
nMsg.err <- nil
2932+
28692933
return nil, true
28702934
}
28712935

@@ -3031,7 +3095,16 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
30313095
// heuristic of sending keep-alive updates after the same
30323096
// duration (see retransmitStaleAnns).
30333097
timeSinceLastUpdate := timestamp.Sub(edge.LastUpdate)
3034-
if IsKeepAliveUpdate(upd, edge) {
3098+
isKeepAlive, err := IsKeepAliveUpdate(upd, edge)
3099+
if err != nil {
3100+
log.Errorf("Could not determine if update is "+
3101+
"keepalive: %v", err)
3102+
nMsg.err <- err
3103+
3104+
return nil, false
3105+
}
3106+
3107+
if isKeepAlive {
30353108
if timeSinceLastUpdate < d.cfg.RebroadcastInterval {
30363109
log.Debugf("Ignoring keep alive update not "+
30373110
"within %v period for channel %v",

discovery/gossiper_test.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,18 @@ func (r *mockGraphSource) IsKnownEdge(chanID lnwire.ShortChannelID) bool {
343343
// IsStaleEdgePolicy returns true if the graph source has a channel edge for
344344
// the passed channel ID (and flags) that have a more recent timestamp.
345345
func (r *mockGraphSource) IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
346-
timestamp time.Time, flags lnwire.ChanUpdateChanFlags) bool {
346+
policy lnwire.ChannelUpdate) bool {
347347

348348
r.mu.Lock()
349349
defer r.mu.Unlock()
350350

351+
pol, ok := policy.(*lnwire.ChannelUpdate1)
352+
if !ok {
353+
panic("expected chan update 1")
354+
}
355+
356+
timestamp := time.Unix(int64(pol.Timestamp), 0)
357+
351358
chanIDInt := chanID.ToUint64()
352359
edges, ok := r.edges[chanIDInt]
353360
if !ok {
@@ -357,23 +364,22 @@ func (r *mockGraphSource) IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
357364
if !isZombie {
358365
return false
359366
}
360-
361367
// Since it exists within our zombie index, we'll check that it
362368
// respects the router's live edge horizon to determine whether
363369
// it is stale or not.
364370
return time.Since(timestamp) > routing.DefaultChannelPruneExpiry
365371
}
366372

367373
switch {
368-
case flags&lnwire.ChanUpdateDirection == 0 && edges[0] != nil:
374+
case policy.IsNode1() && edges[0] != nil:
369375
switch edge := edges[0].(type) {
370376
case *models.ChannelEdgePolicy1:
371377
return !timestamp.After(edge.LastUpdate)
372378
default:
373379
panic(fmt.Sprintf("unhandled: %T", edges[0]))
374380
}
375381

376-
case flags&lnwire.ChanUpdateDirection == 1 && edges[1] != nil:
382+
case !policy.IsNode1() && edges[1] != nil:
377383
switch edge := edges[1].(type) {
378384
case *models.ChannelEdgePolicy1:
379385
return !timestamp.After(edge.LastUpdate)

routing/router.go

Lines changed: 96 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ type ChannelGraphSource interface {
168168
// IsStaleEdgePolicy returns true if the graph source has a channel
169169
// edge for the passed channel ID (and flags) that have a more recent
170170
// timestamp.
171-
IsStaleEdgePolicy(chanID lnwire.ShortChannelID, timestamp time.Time,
172-
flags lnwire.ChanUpdateChanFlags) bool
171+
IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
172+
policy lnwire.ChannelUpdate) bool
173173

174174
// MarkEdgeLive clears an edge from our zombie index, deeming it as
175175
// live.
@@ -2966,54 +2966,108 @@ func (r *ChannelRouter) IsKnownEdge(chanID lnwire.ShortChannelID) bool {
29662966
//
29672967
// NOTE: This method is part of the ChannelGraphSource interface.
29682968
func (r *ChannelRouter) IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
2969-
timestamp time.Time, flags lnwire.ChanUpdateChanFlags) bool {
2969+
update lnwire.ChannelUpdate) bool {
29702970

2971-
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
2972-
r.cfg.Graph.HasChannelEdge1(chanID.ToUint64())
2973-
if err != nil {
2974-
log.Debugf("Check stale edge policy got error: %v", err)
2975-
return false
2971+
var (
2972+
disabled = update.IsDisabled()
2973+
isNode1 = update.IsNode1()
2974+
)
29762975

2977-
}
2976+
switch upd := update.(type) {
2977+
case *lnwire.ChannelUpdate1:
2978+
timestamp := time.Unix(int64(upd.Timestamp), 0)
2979+
2980+
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
2981+
r.cfg.Graph.HasChannelEdge1(chanID.ToUint64())
2982+
if err != nil {
2983+
log.Debugf("Check stale edge policy got error: %v", err)
2984+
2985+
return false
2986+
}
29782987

2979-
// If we know of the edge as a zombie, then we'll make some additional
2980-
// checks to determine if the new policy is fresh.
2981-
if isZombie {
2982-
// When running with AssumeChannelValid, we also prune channels
2983-
// if both of their edges are disabled. We'll mark the new
2984-
// policy as stale if it remains disabled.
2985-
if r.cfg.AssumeChannelValid {
2986-
isDisabled := flags&lnwire.ChanUpdateDisabled ==
2987-
lnwire.ChanUpdateDisabled
2988-
if isDisabled {
2989-
return true
2988+
// If we know of the edge as a zombie, then we'll make some
2989+
// additional checks to determine if the new policy is fresh.
2990+
if isZombie {
2991+
// When running with AssumeChannelValid, we also prune
2992+
// channels if both of their edges are disabled. We'll
2993+
// mark the new policy as stale if it remains disabled.
2994+
if r.cfg.AssumeChannelValid {
2995+
if disabled {
2996+
return true
2997+
}
29902998
}
2999+
3000+
// Otherwise, we'll fall back to our usual
3001+
// ChannelPruneExpiry.
3002+
return time.Since(timestamp) > r.cfg.ChannelPruneExpiry
29913003
}
29923004

2993-
// Otherwise, we'll fall back to our usual ChannelPruneExpiry.
2994-
return time.Since(timestamp) > r.cfg.ChannelPruneExpiry
2995-
}
3005+
// If we don't know of the edge, then it means it's fresh (thus
3006+
// not stale).
3007+
if !exists {
3008+
return false
3009+
}
29963010

2997-
// If we don't know of the edge, then it means it's fresh (thus not
2998-
// stale).
2999-
if !exists {
3000-
return false
3001-
}
3011+
// As edges are directional edge node has a unique policy for
3012+
// the direction of the edge they control. Therefore we first
3013+
// check if we already have the most up to date information for
3014+
// that edge. If so, then we can exit early.
3015+
switch {
3016+
case isNode1:
3017+
return !edge1Timestamp.Before(timestamp)
30023018

3003-
// As edges are directional edge node has a unique policy for the
3004-
// direction of the edge they control. Therefore we first check if we
3005-
// already have the most up to date information for that edge. If so,
3006-
// then we can exit early.
3007-
switch {
3008-
// A flag set of 0 indicates this is an announcement for the "first"
3009-
// node in the channel.
3010-
case flags&lnwire.ChanUpdateDirection == 0:
3011-
return !edge1Timestamp.Before(timestamp)
3012-
3013-
// Similarly, a flag set of 1 indicates this is an announcement for the
3014-
// "second" node in the channel.
3015-
case flags&lnwire.ChanUpdateDirection == 1:
3016-
return !edge2Timestamp.Before(timestamp)
3019+
case !isNode1:
3020+
return !edge2Timestamp.Before(timestamp)
3021+
}
3022+
3023+
case *lnwire.ChannelUpdate2:
3024+
height := upd.BlockHeight
3025+
3026+
edge1Height, edge2Height, exists, isZombie, err :=
3027+
r.cfg.Graph.HasChannelEdge2(chanID.ToUint64())
3028+
if err != nil {
3029+
log.Debugf("Check stale edge policy got error: %v", err)
3030+
3031+
return false
3032+
}
3033+
3034+
// If we know of the edge as a zombie, then we'll make some
3035+
// additional checks to determine if the new policy is fresh.
3036+
if isZombie {
3037+
// When running with AssumeChannelValid, we also prune
3038+
// channels if both of their edges are disabled. We'll
3039+
// mark the new policy as stale if it remains disabled.
3040+
if r.cfg.AssumeChannelValid {
3041+
if disabled {
3042+
return true
3043+
}
3044+
}
3045+
3046+
// Otherwise, we'll fall back to our usual
3047+
// ChannelPruneExpiry.
3048+
blocksSince := r.SyncedHeight() - height.Val
3049+
3050+
return blocksSince >
3051+
uint32(r.cfg.ChannelPruneExpiry.Hours()*6)
3052+
}
3053+
3054+
// If we don't know of the edge, then it means it's fresh (thus
3055+
// not stale).
3056+
if !exists {
3057+
return false
3058+
}
3059+
3060+
// As edges are directional edge node has a unique policy for
3061+
// the direction of the edge they control. Therefore we first
3062+
// check if we already have the most up to date information for
3063+
// that edge. If so, then we can exit early.
3064+
switch {
3065+
case isNode1:
3066+
return edge1Height >= height.Val
3067+
3068+
case !isNode1:
3069+
return edge2Height >= height.Val
3070+
}
30173071
}
30183072

30193073
return false

0 commit comments

Comments
 (0)