Skip to content

Commit fa17a7b

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

File tree

4 files changed

+237
-98
lines changed

4 files changed

+237
-98
lines changed

discovery/gossiper.go

+115-42
Original file line numberDiff line numberDiff line change
@@ -2391,48 +2391,114 @@ func (d *AuthenticatedGossiper) SyncManager() *SyncManager {
23912391
// IsKeepAliveUpdate determines whether this channel update is considered a
23922392
// keep-alive update based on the previous channel update processed for the same
23932393
// direction.
2394-
func IsKeepAliveUpdate(update *lnwire.ChannelUpdate1,
2395-
prev *models.ChannelEdgePolicy1) bool {
2394+
func IsKeepAliveUpdate(update lnwire.ChannelUpdate,
2395+
prevPolicy models.ChannelEdgePolicy) (bool, error) {
23962396

2397-
// Both updates should be from the same direction.
2398-
if update.ChannelFlags&lnwire.ChanUpdateDirection !=
2399-
prev.ChannelFlags&lnwire.ChanUpdateDirection {
2397+
switch upd := update.(type) {
2398+
case *lnwire.ChannelUpdate1:
2399+
prev, ok := prevPolicy.(*models.ChannelEdgePolicy1)
2400+
if !ok {
2401+
return false, fmt.Errorf("expected chan edge policy 1")
2402+
}
24002403

2401-
return false
2402-
}
2404+
// Both updates should be from the same direction.
2405+
if upd.ChannelFlags&lnwire.ChanUpdateDirection !=
2406+
prev.ChannelFlags&lnwire.ChanUpdateDirection {
24032407

2404-
// The timestamp should always increase for a keep-alive update.
2405-
timestamp := time.Unix(int64(update.Timestamp), 0)
2406-
if !timestamp.After(prev.LastUpdate) {
2407-
return false
2408-
}
2408+
return false, nil
2409+
}
24092410

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

24382504
// latestHeight returns the gossiper's latest height known of the chain.
@@ -2838,16 +2904,14 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
28382904
graphScid = upd.ShortChannelID
28392905
}
28402906

2841-
if d.cfg.Router.IsStaleEdgePolicy(
2842-
graphScid, timestamp, upd.ChannelFlags,
2843-
) {
2844-
2907+
if d.cfg.Router.IsStaleEdgePolicy(graphScid, upd) {
28452908
log.Debugf("Ignored stale edge policy for short_chan_id(%v): "+
28462909
"peer=%v, msg=%s, is_remote=%v", shortChanID,
28472910
nMsg.peer, nMsg.msg.MsgType(), nMsg.isRemote,
28482911
)
28492912

28502913
nMsg.err <- nil
2914+
28512915
return nil, true
28522916
}
28532917

@@ -3013,7 +3077,16 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
30133077
// heuristic of sending keep-alive updates after the same
30143078
// duration (see retransmitStaleAnns).
30153079
timeSinceLastUpdate := timestamp.Sub(edge.LastUpdate)
3016-
if IsKeepAliveUpdate(upd, edge) {
3080+
isKeepAlive, err := IsKeepAliveUpdate(upd, edge)
3081+
if err != nil {
3082+
log.Errorf("Could not determine if update is "+
3083+
"keepalive: %v", err)
3084+
nMsg.err <- err
3085+
3086+
return nil, false
3087+
}
3088+
3089+
if isKeepAlive {
30173090
if timeSinceLastUpdate < d.cfg.RebroadcastInterval {
30183091
log.Debugf("Ignoring keep alive update not "+
30193092
"within %v period for channel %v",

discovery/gossiper_test.go

+10-4
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

+96-42
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.
@@ -2958,54 +2958,108 @@ func (r *ChannelRouter) IsKnownEdge(chanID lnwire.ShortChannelID) bool {
29582958
//
29592959
// NOTE: This method is part of the ChannelGraphSource interface.
29602960
func (r *ChannelRouter) IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
2961-
timestamp time.Time, flags lnwire.ChanUpdateChanFlags) bool {
2961+
update lnwire.ChannelUpdate) bool {
29622962

2963-
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
2964-
r.cfg.Graph.HasChannelEdge1(chanID.ToUint64())
2965-
if err != nil {
2966-
log.Debugf("Check stale edge policy got error: %v", err)
2967-
return false
2963+
var (
2964+
disabled = update.IsDisabled()
2965+
isNode1 = update.IsNode1()
2966+
)
29682967

2969-
}
2968+
switch upd := update.(type) {
2969+
case *lnwire.ChannelUpdate1:
2970+
timestamp := time.Unix(int64(upd.Timestamp), 0)
2971+
2972+
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
2973+
r.cfg.Graph.HasChannelEdge1(chanID.ToUint64())
2974+
if err != nil {
2975+
log.Debugf("Check stale edge policy got error: %v", err)
2976+
2977+
return false
2978+
}
29702979

2971-
// If we know of the edge as a zombie, then we'll make some additional
2972-
// checks to determine if the new policy is fresh.
2973-
if isZombie {
2974-
// When running with AssumeChannelValid, we also prune channels
2975-
// if both of their edges are disabled. We'll mark the new
2976-
// policy as stale if it remains disabled.
2977-
if r.cfg.AssumeChannelValid {
2978-
isDisabled := flags&lnwire.ChanUpdateDisabled ==
2979-
lnwire.ChanUpdateDisabled
2980-
if isDisabled {
2981-
return true
2980+
// If we know of the edge as a zombie, then we'll make some
2981+
// additional checks to determine if the new policy is fresh.
2982+
if isZombie {
2983+
// When running with AssumeChannelValid, we also prune
2984+
// channels if both of their edges are disabled. We'll
2985+
// mark the new policy as stale if it remains disabled.
2986+
if r.cfg.AssumeChannelValid {
2987+
if disabled {
2988+
return true
2989+
}
29822990
}
2991+
2992+
// Otherwise, we'll fall back to our usual
2993+
// ChannelPruneExpiry.
2994+
return time.Since(timestamp) > r.cfg.ChannelPruneExpiry
29832995
}
29842996

2985-
// Otherwise, we'll fall back to our usual ChannelPruneExpiry.
2986-
return time.Since(timestamp) > r.cfg.ChannelPruneExpiry
2987-
}
2997+
// If we don't know of the edge, then it means it's fresh (thus
2998+
// not stale).
2999+
if !exists {
3000+
return false
3001+
}
29883002

2989-
// If we don't know of the edge, then it means it's fresh (thus not
2990-
// stale).
2991-
if !exists {
2992-
return false
2993-
}
3003+
// As edges are directional edge node has a unique policy for
3004+
// the direction of the edge they control. Therefore we first
3005+
// check if we already have the most up to date information for
3006+
// that edge. If so, then we can exit early.
3007+
switch {
3008+
case isNode1:
3009+
return !edge1Timestamp.Before(timestamp)
29943010

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

30113065
return false

0 commit comments

Comments
 (0)