Skip to content

Commit 2bb6100

Browse files
committed
discovery: use ChannelUpdate interface in handleChanUpdate
1 parent 3b9b69b commit 2bb6100

File tree

1 file changed

+125
-90
lines changed

1 file changed

+125
-90
lines changed

discovery/gossiper.go

Lines changed: 125 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,7 +2100,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
21002100
// A new authenticated channel edge update has arrived. This indicates
21012101
// that the directional information for an already known channel has
21022102
// been updated.
2103-
case *lnwire.ChannelUpdate1:
2103+
case lnwire.ChannelUpdate:
21042104
return d.handleChanUpdate(nMsg, msg, schedulerOp)
21052105

21062106
// A new signature announcement has been received. This indicates
@@ -2861,40 +2861,45 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
28612861

28622862
// handleChanUpdate processes a new channel update.
28632863
func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
2864-
upd *lnwire.ChannelUpdate1,
2865-
ops []batch.SchedulerOption) ([]networkMsg, bool) {
2864+
upd lnwire.ChannelUpdate, ops []batch.SchedulerOption) ([]networkMsg,
2865+
bool) {
28662866

2867-
log.Debugf("Processing ChannelUpdate1: peer=%v, short_chan_id=%v, ",
2868-
nMsg.peer, upd.ShortChannelID.ToUint64())
2867+
var (
2868+
scid = upd.SCID()
2869+
chainHash = upd.GetChainHash()
2870+
)
2871+
2872+
log.Debugf("Processing ChannelUpdate: peer=%v, short_chan_id=%v, ",
2873+
nMsg.peer, scid)
28692874

28702875
// We'll ignore any channel updates that target any chain other than
28712876
// the set of chains we know of.
2872-
if !bytes.Equal(upd.ChainHash[:], d.cfg.ChainHash[:]) {
2873-
err := fmt.Errorf("ignoring ChannelUpdate1 from chain=%v, "+
2874-
"gossiper on chain=%v", upd.ChainHash, d.cfg.ChainHash)
2877+
if !bytes.Equal(chainHash[:], d.cfg.ChainHash[:]) {
2878+
err := fmt.Errorf("ignoring %s from chain=%v, "+
2879+
"gossiper on chain=%v", upd.MsgType(), chainHash,
2880+
d.cfg.ChainHash)
28752881
log.Errorf(err.Error())
28762882

28772883
key := newRejectCacheKey(
2878-
upd.ShortChannelID.ToUint64(),
2879-
sourceToPub(nMsg.source),
2884+
scid.ToUint64(), sourceToPub(nMsg.source),
28802885
)
28812886
_, _ = d.recentRejects.Put(key, &cachedReject{})
28822887

28832888
nMsg.err <- err
28842889
return nil, false
28852890
}
28862891

2887-
blockHeight := upd.ShortChannelID.BlockHeight
2888-
shortChanID := upd.ShortChannelID.ToUint64()
2892+
blockHeight := upd.SCID().BlockHeight
2893+
shortChanID := upd.SCID().ToUint64()
28892894

28902895
// If the advertised inclusionary block is beyond our knowledge of the
28912896
// chain tip, then we'll put the announcement in limbo to be fully
28922897
// verified once we advance forward in the chain. If the update has an
28932898
// alias SCID, we'll skip the isPremature check. This is necessary
28942899
// since aliases start at block height 16_000_000.
28952900
d.Lock()
2896-
if nMsg.isRemote && !d.cfg.IsAlias(upd.ShortChannelID) &&
2897-
d.isPremature(upd.ShortChannelID, 0, nMsg) {
2901+
if nMsg.isRemote && !d.cfg.IsAlias(scid) &&
2902+
d.isPremature(scid, 0, nMsg) {
28982903

28992904
log.Warnf("Update announcement for short_chan_id(%v), is "+
29002905
"premature: advertises height %v, only height %v is "+
@@ -2905,31 +2910,28 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
29052910
}
29062911
d.Unlock()
29072912

2908-
// Before we perform any of the expensive checks below, we'll check
2909-
// whether this update is stale or is for a zombie channel in order to
2910-
// quickly reject it.
2911-
timestamp := time.Unix(int64(upd.Timestamp), 0)
2912-
29132913
// Fetch the SCID we should be using to lock the channelMtx and make
29142914
// graph queries with.
2915-
graphScid, err := d.cfg.FindBaseByAlias(upd.ShortChannelID)
2915+
graphScid, err := d.cfg.FindBaseByAlias(scid)
29162916
if err != nil {
29172917
// Fallback and set the graphScid to the peer-provided SCID.
29182918
// This will occur for non-option-scid-alias channels and for
29192919
// public option-scid-alias channels after 6 confirmations.
29202920
// Once public option-scid-alias channels have 6 confs, we'll
29212921
// ignore ChannelUpdates with one of their aliases.
2922-
graphScid = upd.ShortChannelID
2922+
graphScid = scid
29232923
}
29242924

2925+
// Before we perform any of the expensive checks below, we'll check
2926+
// whether this update is stale or is for a zombie channel in order to
2927+
// quickly reject it.
29252928
if d.cfg.Router.IsStaleEdgePolicy(graphScid, upd) {
29262929
log.Debugf("Ignored stale edge policy for short_chan_id(%v): "+
29272930
"peer=%v, msg=%s, is_remote=%v", shortChanID,
29282931
nMsg.peer, nMsg.msg.MsgType(), nMsg.isRemote,
29292932
)
29302933

29312934
nMsg.err <- nil
2932-
29332935
return nil, true
29342936
}
29352937

@@ -2971,7 +2973,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
29712973
// If the edge corresponding to this ChannelUpdate1 was not
29722974
// found in the graph, this might be a channel in the process
29732975
// of being opened, and we haven't processed our own
2974-
// ChannelAnnouncement1 yet, hence it is not found in the
2976+
// ChannelAnnouncement yet, hence it is not found in the
29752977
// graph. This usually gets resolved after the channel proofs
29762978
// are exchanged and the channel is broadcasted to the rest of
29772979
// the network, but in case this is a private channel this
@@ -3008,7 +3010,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
30083010
})
30093011
}
30103012

3011-
log.Debugf("Got ChannelUpdate1 for edge not found in graph"+
3013+
log.Debugf("Got ChannelUpdate for edge not found in graph"+
30123014
"(shortChanID=%v), saving for reprocessing later",
30133015
shortChanID)
30143016

@@ -3024,7 +3026,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
30243026
nMsg.err <- err
30253027

30263028
key := newRejectCacheKey(
3027-
upd.ShortChannelID.ToUint64(),
3029+
scid.ToUint64(),
30283030
sourceToPub(nMsg.source),
30293031
)
30303032
_, _ = d.recentRejects.Put(key, &cachedReject{})
@@ -3038,21 +3040,20 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
30383040
var (
30393041
pubKey *btcec.PublicKey
30403042
edgeToUpdate models.ChannelEdgePolicy
3043+
direction int
30413044
)
3042-
direction := upd.ChannelFlags & lnwire.ChanUpdateDirection
3043-
switch direction {
3044-
case 0:
3045+
if upd.IsNode1() {
30453046
pubKey, _ = chanInfo.NodeKey1()
30463047
edgeToUpdate = e1
3047-
case 1:
3048+
direction = 0
3049+
} else {
30483050
pubKey, _ = chanInfo.NodeKey2()
30493051
edgeToUpdate = e2
3052+
direction = 1
30503053
}
30513054

3052-
var chanID = chanInfo.GetChanID()
3053-
30543055
log.Debugf("Validating ChannelUpdate1: channel=%v, from node=%x, has "+
3055-
"edge=%v", chanID, pubKey.SerializeCompressed(),
3056+
"edge=%v", chanInfo.GetChanID(), pubKey.SerializeCompressed(),
30563057
edgeToUpdate != nil)
30573058

30583059
// Validate the channel announcement with the expected public key and
@@ -3064,38 +3065,21 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
30643065
if err != nil {
30653066
rErr := fmt.Errorf("unable to validate channel update "+
30663067
"announcement for short_chan_id=%v: %v",
3067-
spew.Sdump(upd.ShortChannelID), err)
3068+
spew.Sdump(scid), err)
30683069

30693070
log.Error(rErr)
30703071
nMsg.err <- rErr
30713072
return nil, false
30723073
}
30733074

3074-
var edge *models.ChannelEdgePolicy1
3075-
if edgeToUpdate != nil {
3076-
var ok bool
3077-
edge, ok = edgeToUpdate.(*models.ChannelEdgePolicy1)
3078-
if !ok {
3079-
rErr := fmt.Errorf("expected "+
3080-
"*models.ChannelEdgePolicy1, got: %T",
3081-
edgeToUpdate)
3082-
3083-
log.Error(rErr)
3084-
nMsg.err <- rErr
3085-
3086-
return nil, false
3087-
}
3088-
}
3089-
30903075
// If we have a previous version of the edge being updated, we'll want
30913076
// to rate limit its updates to prevent spam throughout the network.
3092-
if nMsg.isRemote && edge != nil {
3077+
if nMsg.isRemote && edgeToUpdate != nil {
30933078
// If it's a keep-alive update, we'll only propagate one if
30943079
// it's been a day since the previous. This follows our own
30953080
// heuristic of sending keep-alive updates after the same
30963081
// duration (see retransmitStaleAnns).
3097-
timeSinceLastUpdate := timestamp.Sub(edge.LastUpdate)
3098-
isKeepAlive, err := IsKeepAliveUpdate(upd, edge)
3082+
isKeepAlive, err := IsKeepAliveUpdate(upd, edgeToUpdate)
30993083
if err != nil {
31003084
log.Errorf("Could not determine if update is "+
31013085
"keepalive: %v", err)
@@ -3105,7 +3089,18 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
31053089
}
31063090

31073091
if isKeepAlive {
3108-
if timeSinceLastUpdate < d.cfg.RebroadcastInterval {
3092+
within, err := d.updateWithinRebroadcastInterval(
3093+
upd, edgeToUpdate,
3094+
)
3095+
if err != nil {
3096+
log.Errorf("Could not determine if update is "+
3097+
"within rebroadcast interval: %v", err)
3098+
nMsg.err <- err
3099+
3100+
return nil, false
3101+
}
3102+
3103+
if !within {
31093104
log.Debugf("Ignoring keep alive update not "+
31103105
"within %v period for channel %v",
31113106
d.cfg.RebroadcastInterval, shortChanID)
@@ -3124,7 +3119,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
31243119
// multiple aliases for a channel and we may otherwise
31253120
// rate-limit only a single alias of the channel,
31263121
// instead of the whole channel.
3127-
baseScid := chanID
3122+
baseScid := chanInfo.GetChanID()
31283123
d.Lock()
31293124
rls, ok := d.chanUpdateRateLimiter[baseScid]
31303125
if !ok {
@@ -3155,18 +3150,23 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
31553150
// different alias. This might mean that SigBytes is incorrect as it
31563151
// signs a different SCID than the database SCID, but since there will
31573152
// only be a difference if AuthProof == nil, this is fine.
3158-
update := &models.ChannelEdgePolicy1{
3159-
SigBytes: upd.Signature.ToSignatureBytes(),
3160-
ChannelID: chanID,
3161-
LastUpdate: timestamp,
3162-
MessageFlags: upd.MessageFlags,
3163-
ChannelFlags: upd.ChannelFlags,
3164-
TimeLockDelta: upd.TimeLockDelta,
3165-
MinHTLC: upd.HtlcMinimumMsat,
3166-
MaxHTLC: upd.HtlcMaximumMsat,
3167-
FeeBaseMSat: lnwire.MilliSatoshi(upd.BaseFee),
3168-
FeeProportionalMillionths: lnwire.MilliSatoshi(upd.FeeRate),
3169-
ExtraOpaqueData: upd.ExtraOpaqueData,
3153+
update, err := models.EdgePolicyFromUpdate(upd)
3154+
if err != nil {
3155+
rErr := fmt.Errorf("unable to convert update to policy for "+
3156+
"short_chan_id=%v: %v", spew.Sdump(scid), err)
3157+
3158+
log.Error(rErr)
3159+
nMsg.err <- rErr
3160+
3161+
return nil, false
3162+
}
3163+
switch upd := update.(type) {
3164+
case *models.ChannelEdgePolicy1:
3165+
upd.ChannelID = chanInfo.GetChanID()
3166+
case *models.ChannelEdgePolicy2:
3167+
upd.ShortChannelID.Val = lnwire.NewShortChanIDFromInt(
3168+
chanInfo.GetChanID(),
3169+
)
31703170
}
31713171

31723172
if err := d.cfg.Router.UpdateEdge(update, ops...); err != nil {
@@ -3182,7 +3182,8 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
31823182
// Since we know the stored SCID in the graph, we'll
31833183
// cache that SCID.
31843184
key := newRejectCacheKey(
3185-
chanID, sourceToPub(nMsg.source),
3185+
chanInfo.GetChanID(),
3186+
sourceToPub(nMsg.source),
31863187
)
31873188
_, _ = d.recentRejects.Put(key, &cachedReject{})
31883189

@@ -3191,32 +3192,33 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
31913192
}
31923193

31933194
nMsg.err <- err
3195+
31943196
return nil, false
31953197
}
31963198

31973199
// If this is a local ChannelUpdate1 without an AuthProof, it means it
31983200
// is an update to a channel that is not (yet) supposed to be announced
3199-
// to the greater network. However, our channel counter party will need
3201+
// to the greater network. However, our channel counterparty will need
32003202
// to be given the update, so we'll try sending the update directly to
32013203
// the remote peer.
3202-
if !nMsg.isRemote && chanInfo.GetAuthProof() == nil { //nolint:nestif
3203-
if nMsg.optionalMsgFields != nil {
3204+
if !nMsg.isRemote && chanInfo.GetAuthProof() == nil {
3205+
if nMsg.optionalMsgFields != nil &&
3206+
nMsg.optionalMsgFields.remoteAlias != nil {
3207+
3208+
// The remoteAlias field was specified, meaning
3209+
// that we should replace the SCID in the
3210+
// update with the remote's alias. We'll also
3211+
// need to re-sign the channel update. This is
3212+
// required for option-scid-alias feature-bit
3213+
// negotiated channels.
32043214
remoteAlias := nMsg.optionalMsgFields.remoteAlias
3205-
if remoteAlias != nil {
3206-
// The remoteAlias field was specified, meaning
3207-
// that we should replace the SCID in the
3208-
// update with the remote's alias. We'll also
3209-
// need to re-sign the channel update. This is
3210-
// required for option-scid-alias feature-bit
3211-
// negotiated channels.
3212-
upd.ShortChannelID = *remoteAlias
3213-
3214-
err := d.cfg.SignAliasUpdate(upd)
3215-
if err != nil {
3216-
log.Error(err)
3217-
nMsg.err <- err
3218-
return nil, false
3219-
}
3215+
upd.SetSCID(*remoteAlias)
3216+
3217+
err := d.cfg.SignAliasUpdate(upd)
3218+
if err != nil {
3219+
log.Error(err)
3220+
nMsg.err <- err
3221+
return nil, false
32203222
}
32213223
}
32223224

@@ -3233,7 +3235,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
32333235
if err != nil {
32343236
err := fmt.Errorf("unable to reliably send %v for "+
32353237
"channel=%v to peer=%x: %v", upd.MsgType(),
3236-
upd.ShortChannelID, remotePubKey, err)
3238+
scid, remotePubKey, err)
32373239
nMsg.err <- err
32383240
return nil, false
32393241
}
@@ -3246,7 +3248,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
32463248
// contains an alias because the network would reject this.
32473249
var announcements []networkMsg
32483250
if chanInfo.GetAuthProof() != nil &&
3249-
!d.cfg.IsAlias(upd.ShortChannelID) {
3251+
!d.cfg.IsAlias(scid) {
32503252

32513253
announcements = append(announcements, networkMsg{
32523254
peer: nMsg.peer,
@@ -3258,9 +3260,9 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
32583260

32593261
nMsg.err <- nil
32603262

3261-
log.Debugf("Processed ChannelUpdate1: peer=%v, short_chan_id=%v, "+
3262-
"timestamp=%v", nMsg.peer, upd.ShortChannelID.ToUint64(),
3263-
timestamp)
3263+
log.Debugf("Processed %s: peer=%v, short_chan_id=%v, ", upd.MsgType(),
3264+
nMsg.peer, scid.ToUint64())
3265+
32643266
return announcements, true
32653267
}
32663268

@@ -3687,6 +3689,39 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
36873689
return announcements, true
36883690
}
36893691

3692+
func (d *AuthenticatedGossiper) updateWithinRebroadcastInterval(
3693+
upd lnwire.ChannelUpdate, policy models.ChannelEdgePolicy) (bool,
3694+
error) {
3695+
3696+
switch update := upd.(type) {
3697+
case *lnwire.ChannelUpdate1:
3698+
pol, ok := policy.(*models.ChannelEdgePolicy1)
3699+
if !ok {
3700+
return false, fmt.Errorf("expected chan edge policy 1")
3701+
}
3702+
3703+
timestamp := time.Unix(int64(update.Timestamp), 0)
3704+
timeSinceLastUpdate := timestamp.Sub(pol.LastUpdate)
3705+
3706+
return timeSinceLastUpdate >= d.cfg.RebroadcastInterval, nil
3707+
3708+
case *lnwire.ChannelUpdate2:
3709+
pol, ok := policy.(*models.ChannelEdgePolicy2)
3710+
if !ok {
3711+
return false, fmt.Errorf("expected chan edge policy 2")
3712+
}
3713+
3714+
blocksSinceLastUpdate := update.BlockHeight.Val -
3715+
pol.BlockHeight.Val
3716+
3717+
return blocksSinceLastUpdate >=
3718+
uint32(d.cfg.RebroadcastInterval.Hours()*6), nil
3719+
3720+
default:
3721+
return false, fmt.Errorf("unhandled impl of Chan Update")
3722+
}
3723+
}
3724+
36903725
func buildChanProof(ann lnwire.ChannelAnnouncement) (
36913726
models.ChannelAuthProof, error) {
36923727

0 commit comments

Comments
 (0)