Skip to content

Commit d02804a

Browse files
committed
discovery+routing: update to use ChanUpdate interface
In the IsKeepAlive and IsStaleEdgePolicy functions
1 parent 23ae902 commit d02804a

File tree

4 files changed

+234
-98
lines changed

4 files changed

+234
-98
lines changed

discovery/gossiper.go

Lines changed: 111 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,48 +2377,110 @@ func (d *AuthenticatedGossiper) SyncManager() *SyncManager {
23772377
// IsKeepAliveUpdate determines whether this channel update is considered a
23782378
// keep-alive update based on the previous channel update processed for the same
23792379
// direction.
2380-
func IsKeepAliveUpdate(update *lnwire.ChannelUpdate1,
2381-
prev *models.ChannelEdgePolicy1) bool {
2380+
func IsKeepAliveUpdate(update lnwire.ChannelUpdate,
2381+
prevPolicy models.ChannelEdgePolicy) (bool, error) {
23822382

2383-
// Both updates should be from the same direction.
2384-
if update.ChannelFlags&lnwire.ChanUpdateDirection !=
2385-
prev.ChannelFlags&lnwire.ChanUpdateDirection {
2383+
switch upd := update.(type) {
2384+
case *lnwire.ChannelUpdate1:
2385+
prev, ok := prevPolicy.(*models.ChannelEdgePolicy1)
2386+
if !ok {
2387+
return false, fmt.Errorf("expected chan edge policy 1")
2388+
}
23862389

2387-
return false
2388-
}
2390+
// Both updates should be from the same direction.
2391+
if upd.ChannelFlags&lnwire.ChanUpdateDirection !=
2392+
prev.ChannelFlags&lnwire.ChanUpdateDirection {
23892393

2390-
// The timestamp should always increase for a keep-alive update.
2391-
timestamp := time.Unix(int64(update.Timestamp), 0)
2392-
if !timestamp.After(prev.LastUpdate) {
2393-
return false
2394-
}
2394+
return false, nil
2395+
}
23952396

2396-
// None of the remaining fields should change for a keep-alive update.
2397-
if update.ChannelFlags.IsDisabled() != prev.ChannelFlags.IsDisabled() {
2398-
return false
2399-
}
2400-
if lnwire.MilliSatoshi(update.BaseFee) != prev.FeeBaseMSat {
2401-
return false
2402-
}
2403-
if lnwire.MilliSatoshi(update.FeeRate) != prev.FeeProportionalMillionths {
2404-
return false
2405-
}
2406-
if update.TimeLockDelta != prev.TimeLockDelta {
2407-
return false
2408-
}
2409-
if update.HtlcMinimumMsat != prev.MinHTLC {
2410-
return false
2411-
}
2412-
if update.MessageFlags.HasMaxHtlc() && !prev.MessageFlags.HasMaxHtlc() {
2413-
return false
2414-
}
2415-
if update.HtlcMaximumMsat != prev.MaxHTLC {
2416-
return false
2417-
}
2418-
if !bytes.Equal(update.ExtraOpaqueData, prev.ExtraOpaqueData) {
2419-
return false
2397+
// The timestamp should always increase for a keep-alive update.
2398+
timestamp := time.Unix(int64(upd.Timestamp), 0)
2399+
if !timestamp.After(prev.LastUpdate) {
2400+
return false, nil
2401+
}
2402+
2403+
// None of the remaining fields should change for a keep-alive
2404+
// update.
2405+
if upd.ChannelFlags.IsDisabled() !=
2406+
prev.ChannelFlags.IsDisabled() {
2407+
2408+
return false, nil
2409+
}
2410+
if lnwire.MilliSatoshi(upd.BaseFee) != prev.FeeBaseMSat {
2411+
return false, nil
2412+
}
2413+
if lnwire.MilliSatoshi(upd.FeeRate) !=
2414+
prev.FeeProportionalMillionths {
2415+
2416+
return false, nil
2417+
}
2418+
if upd.TimeLockDelta != prev.TimeLockDelta {
2419+
return false, nil
2420+
}
2421+
if upd.HtlcMinimumMsat != prev.MinHTLC {
2422+
return false, nil
2423+
}
2424+
if upd.MessageFlags.HasMaxHtlc() &&
2425+
!prev.MessageFlags.HasMaxHtlc() {
2426+
return false, nil
2427+
}
2428+
if upd.HtlcMaximumMsat != prev.MaxHTLC {
2429+
return false, nil
2430+
}
2431+
if !bytes.Equal(upd.ExtraOpaqueData, prev.ExtraOpaqueData) {
2432+
return false, nil
2433+
}
2434+
return true, nil
2435+
2436+
case *lnwire.ChannelUpdate2:
2437+
prev, ok := prevPolicy.(*models.ChannelEdgePolicy2)
2438+
if !ok {
2439+
return false, fmt.Errorf("expected chan edge policy 2")
2440+
}
2441+
2442+
// Both updates should be from the same direction.
2443+
if upd.IsNode1() != prev.IsNode1() {
2444+
return false, nil
2445+
}
2446+
2447+
// The block-height should always increase for a keep-alive
2448+
// update.
2449+
if upd.BlockHeight <= prev.BlockHeight {
2450+
return false, nil
2451+
}
2452+
2453+
// None of the remaining fields should change for a keep-alive update.
2454+
if upd.IsDisabled() != prev.IsDisabled() {
2455+
return false, nil
2456+
}
2457+
fwd := upd.ForwardingPolicy()
2458+
prevFwd := upd.ForwardingPolicy()
2459+
2460+
if fwd.BaseFee != prevFwd.BaseFee {
2461+
return false, nil
2462+
}
2463+
if fwd.FeeRate != prevFwd.FeeRate {
2464+
return false, nil
2465+
}
2466+
if fwd.TimeLockDelta != prevFwd.TimeLockDelta {
2467+
return false, nil
2468+
}
2469+
if fwd.MinHTLC != prevFwd.MinHTLC {
2470+
return false, nil
2471+
}
2472+
if fwd.MaxHTLC != prevFwd.MinHTLC {
2473+
return false, nil
2474+
}
2475+
if !bytes.Equal(upd.ExtraOpaqueData, prev.ExtraOpaqueData) {
2476+
return false, nil
2477+
}
2478+
return true, nil
2479+
2480+
default:
2481+
return false, fmt.Errorf("unhandled implementation of "+
2482+
"ChannelUpdate: %T", update)
24202483
}
2421-
return true
24222484
}
24232485

24242486
// latestHeight returns the gossiper's latest height known of the chain.
@@ -2824,16 +2886,14 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
28242886
graphScid = upd.ShortChannelID
28252887
}
28262888

2827-
if d.cfg.Router.IsStaleEdgePolicy(
2828-
graphScid, timestamp, upd.ChannelFlags,
2829-
) {
2830-
2889+
if d.cfg.Router.IsStaleEdgePolicy(graphScid, upd) {
28312890
log.Debugf("Ignored stale edge policy for short_chan_id(%v): "+
28322891
"peer=%v, msg=%s, is_remote=%v", shortChanID,
28332892
nMsg.peer, nMsg.msg.MsgType(), nMsg.isRemote,
28342893
)
28352894

28362895
nMsg.err <- nil
2896+
28372897
return nil, true
28382898
}
28392899

@@ -2995,7 +3055,16 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
29953055
// heuristic of sending keep-alive updates after the same
29963056
// duration (see retransmitStaleAnns).
29973057
timeSinceLastUpdate := timestamp.Sub(edge.LastUpdate)
2998-
if IsKeepAliveUpdate(upd, edge) {
3058+
isKeepAlive, err := IsKeepAliveUpdate(upd, edge)
3059+
if err != nil {
3060+
log.Errorf("Could not determine if update is "+
3061+
"keepalive: %v", err)
3062+
nMsg.err <- err
3063+
3064+
return nil, false
3065+
}
3066+
3067+
if isKeepAlive {
29993068
if timeSinceLastUpdate < d.cfg.RebroadcastInterval {
30003069
log.Debugf("Ignoring keep alive update not "+
30013070
"within %v period for channel %v",

discovery/gossiper_test.go

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

350350
r.mu.Lock()
351351
defer r.mu.Unlock()
352352

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

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

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

routing/router.go

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

175175
// MarkEdgeLive clears an edge from our zombie index, deeming it as
176176
// live.
@@ -3003,54 +3003,108 @@ func (r *ChannelRouter) IsKnownEdge(chanID lnwire.ShortChannelID) bool {
30033003
//
30043004
// NOTE: This method is part of the ChannelGraphSource interface.
30053005
func (r *ChannelRouter) IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
3006-
timestamp time.Time, flags lnwire.ChanUpdateChanFlags) bool {
3006+
update lnwire.ChannelUpdate) bool {
30073007

3008-
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
3009-
r.cfg.Graph.HasChannelEdge1(chanID.ToUint64())
3010-
if err != nil {
3011-
log.Debugf("Check stale edge policy got error: %v", err)
3012-
return false
3008+
var (
3009+
disabled = update.IsDisabled()
3010+
isNode1 = update.IsNode1()
3011+
)
30133012

3014-
}
3013+
switch upd := update.(type) {
3014+
case *lnwire.ChannelUpdate1:
3015+
timestamp := time.Unix(int64(upd.Timestamp), 0)
30153016

3016-
// If we know of the edge as a zombie, then we'll make some additional
3017-
// checks to determine if the new policy is fresh.
3018-
if isZombie {
3019-
// When running with AssumeChannelValid, we also prune channels
3020-
// if both of their edges are disabled. We'll mark the new
3021-
// policy as stale if it remains disabled.
3022-
if r.cfg.AssumeChannelValid {
3023-
isDisabled := flags&lnwire.ChanUpdateDisabled ==
3024-
lnwire.ChanUpdateDisabled
3025-
if isDisabled {
3026-
return true
3017+
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
3018+
r.cfg.Graph.HasChannelEdge1(chanID.ToUint64())
3019+
if err != nil {
3020+
log.Debugf("Check stale edge policy got error: %v", err)
3021+
return false
3022+
3023+
}
3024+
3025+
// If we know of the edge as a zombie, then we'll make some
3026+
// additional checks to determine if the new policy is fresh.
3027+
if isZombie {
3028+
// When running with AssumeChannelValid, we also prune
3029+
// channels if both of their edges are disabled. We'll
3030+
// mark the new policy as stale if it remains disabled.
3031+
if r.cfg.AssumeChannelValid {
3032+
if disabled {
3033+
return true
3034+
}
30273035
}
3036+
3037+
// Otherwise, we'll fall back to our usual
3038+
// ChannelPruneExpiry.
3039+
return time.Since(timestamp) > r.cfg.ChannelPruneExpiry
30283040
}
30293041

3030-
// Otherwise, we'll fall back to our usual ChannelPruneExpiry.
3031-
return time.Since(timestamp) > r.cfg.ChannelPruneExpiry
3032-
}
3042+
// If we don't know of the edge, then it means it's fresh (thus
3043+
// not stale).
3044+
if !exists {
3045+
return false
3046+
}
30333047

3034-
// If we don't know of the edge, then it means it's fresh (thus not
3035-
// stale).
3036-
if !exists {
3037-
return false
3038-
}
3048+
// As edges are directional edge node has a unique policy for the
3049+
// direction of the edge they control. Therefore we first check if we
3050+
// already have the most up to date information for that edge. If so,
3051+
// then we can exit early.
3052+
switch {
3053+
case isNode1:
3054+
return !edge1Timestamp.Before(timestamp)
30393055

3040-
// As edges are directional edge node has a unique policy for the
3041-
// direction of the edge they control. Therefore we first check if we
3042-
// already have the most up to date information for that edge. If so,
3043-
// then we can exit early.
3044-
switch {
3045-
// A flag set of 0 indicates this is an announcement for the "first"
3046-
// node in the channel.
3047-
case flags&lnwire.ChanUpdateDirection == 0:
3048-
return !edge1Timestamp.Before(timestamp)
3049-
3050-
// Similarly, a flag set of 1 indicates this is an announcement for the
3051-
// "second" node in the channel.
3052-
case flags&lnwire.ChanUpdateDirection == 1:
3053-
return !edge2Timestamp.Before(timestamp)
3056+
case !isNode1:
3057+
return !edge2Timestamp.Before(timestamp)
3058+
}
3059+
3060+
case *lnwire.ChannelUpdate2:
3061+
height := upd.BlockHeight
3062+
3063+
edge1Height, edge2Height, exists, isZombie, err :=
3064+
r.cfg.Graph.HasChannelEdge2(chanID.ToUint64())
3065+
if err != nil {
3066+
log.Debugf("Check stale edge policy got error: %v", err)
3067+
return false
3068+
3069+
}
3070+
3071+
// If we know of the edge as a zombie, then we'll make some
3072+
// additional checks to determine if the new policy is fresh.
3073+
if isZombie {
3074+
// When running with AssumeChannelValid, we also prune
3075+
// channels if both of their edges are disabled. We'll
3076+
// mark the new policy as stale if it remains disabled.
3077+
if r.cfg.AssumeChannelValid {
3078+
if disabled {
3079+
return true
3080+
}
3081+
}
3082+
3083+
// Otherwise, we'll fall back to our usual
3084+
// ChannelPruneExpiry.
3085+
blocksSince := r.SyncedHeight() - height
3086+
3087+
return blocksSince >
3088+
uint32(r.cfg.ChannelPruneExpiry.Hours()*6)
3089+
}
3090+
3091+
// If we don't know of the edge, then it means it's fresh (thus
3092+
// not stale).
3093+
if !exists {
3094+
return false
3095+
}
3096+
3097+
// As edges are directional edge node has a unique policy for the
3098+
// direction of the edge they control. Therefore we first check if we
3099+
// already have the most up to date information for that edge. If so,
3100+
// then we can exit early.
3101+
switch {
3102+
case isNode1:
3103+
return edge1Height >= height
3104+
3105+
case !isNode1:
3106+
return edge2Height >= height
3107+
}
30543108
}
30553109

30563110
return false

0 commit comments

Comments
 (0)