From a73c45946ba5ad2071c59b8e1611e1ebdbe62b86 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Tue, 3 Feb 2026 12:14:59 +0200 Subject: [PATCH] multi: add ChanEdgePolicyFromWire constructor for ChannelEdgePolicy Add ChanEdgePolicyFromWire to construct ChannelEdgePolicy from channel update messages, centralizing v1/v2 field mapping. Update call sites to use the helper: - discovery/gossiper: handleChanUpdate - graph/builder: ApplyChannelUpdate - routing/router_test: ApplyChannelUpdate test helper This consolidates update-to-policy conversion logic across versions. --- discovery/gossiper.go | 20 ++++------- graph/builder.go | 20 ++++------- graph/db/models/channel_edge_policy.go | 50 ++++++++++++++++++++++++++ routing/router_test.go | 21 ++++------- 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 3e72f8a1d..d2375cb1d 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -3422,20 +3422,12 @@ func (d *AuthenticatedGossiper) handleChanUpdate(ctx context.Context, // different alias. This might mean that SigBytes is incorrect as it // signs a different SCID than the database SCID, but since there will // only be a difference if AuthProof == nil, this is fine. - update := &models.ChannelEdgePolicy{ - Version: upd.GossipVersion(), - SigBytes: upd.Signature.ToSignatureBytes(), - ChannelID: chanInfo.ChannelID, - LastUpdate: timestamp, - MessageFlags: upd.MessageFlags, - ChannelFlags: upd.ChannelFlags, - TimeLockDelta: upd.TimeLockDelta, - MinHTLC: upd.HtlcMinimumMsat, - MaxHTLC: upd.HtlcMaximumMsat, - FeeBaseMSat: lnwire.MilliSatoshi(upd.BaseFee), - FeeProportionalMillionths: lnwire.MilliSatoshi(upd.FeeRate), - InboundFee: upd.InboundFee.ValOpt(), - ExtraOpaqueData: upd.ExtraOpaqueData, + update, err := models.ChanEdgePolicyFromWire( + chanInfo.ChannelID, upd, + ) + if err != nil { + nMsg.err <- err + return nil, false } if err := d.cfg.Graph.UpdateEdge(ctx, update, ops...); err != nil { diff --git a/graph/builder.go b/graph/builder.go index 10d0b2904..fa8b0b4a9 100644 --- a/graph/builder.go +++ b/graph/builder.go @@ -952,20 +952,12 @@ func (b *Builder) ApplyChannelUpdate(msg *lnwire.ChannelUpdate1) bool { return false } - update := &models.ChannelEdgePolicy{ - Version: msg.GossipVersion(), - SigBytes: msg.Signature.ToSignatureBytes(), - ChannelID: msg.ShortChannelID.ToUint64(), - LastUpdate: time.Unix(int64(msg.Timestamp), 0), - MessageFlags: msg.MessageFlags, - ChannelFlags: msg.ChannelFlags, - TimeLockDelta: msg.TimeLockDelta, - MinHTLC: msg.HtlcMinimumMsat, - MaxHTLC: msg.HtlcMaximumMsat, - FeeBaseMSat: lnwire.MilliSatoshi(msg.BaseFee), - FeeProportionalMillionths: lnwire.MilliSatoshi(msg.FeeRate), - InboundFee: msg.InboundFee.ValOpt(), - ExtraOpaqueData: msg.ExtraOpaqueData, + update, err := models.ChanEdgePolicyFromWire( + msg.ShortChannelID.ToUint64(), msg, + ) + if err != nil { + log.Errorf("Unable to parse channel update: %v", err) + return false } err = b.UpdateEdge(ctx, update) diff --git a/graph/db/models/channel_edge_policy.go b/graph/db/models/channel_edge_policy.go index dd93c21b1..067c7861a 100644 --- a/graph/db/models/channel_edge_policy.go +++ b/graph/db/models/channel_edge_policy.go @@ -99,6 +99,56 @@ type ChannelEdgePolicy struct { ExtraSignedFields map[uint64][]byte } +// ChanEdgePolicyFromWire constructs a ChannelEdgePolicy from a channel update +// message. +func ChanEdgePolicyFromWire(scid uint64, + update lnwire.ChannelUpdate) (*ChannelEdgePolicy, error) { + + switch upd := update.(type) { + case *lnwire.ChannelUpdate1: + //nolint:ll + return &ChannelEdgePolicy{ + Version: lnwire.GossipVersion1, + SigBytes: upd.Signature.ToSignatureBytes(), + ChannelID: scid, + LastUpdate: time.Unix(int64(upd.Timestamp), 0), + MessageFlags: upd.MessageFlags, + ChannelFlags: upd.ChannelFlags, + TimeLockDelta: upd.TimeLockDelta, + MinHTLC: upd.HtlcMinimumMsat, + MaxHTLC: upd.HtlcMaximumMsat, + FeeBaseMSat: lnwire.MilliSatoshi(upd.BaseFee), + FeeProportionalMillionths: lnwire.MilliSatoshi(upd.FeeRate), + InboundFee: upd.InboundFee.ValOpt(), + ExtraOpaqueData: upd.ExtraOpaqueData, + }, nil + + case *lnwire.ChannelUpdate2: + return &ChannelEdgePolicy{ + Version: lnwire.GossipVersion2, + SigBytes: upd.Signature.Val.ToSignatureBytes(), + ChannelID: scid, + LastBlockHeight: upd.BlockHeight.Val, + SecondPeer: upd.SecondPeer.IsSome(), + DisableFlags: upd.DisabledFlags.Val, + TimeLockDelta: upd.CLTVExpiryDelta.Val, + MinHTLC: upd.HTLCMinimumMsat.Val, + MaxHTLC: upd.HTLCMaximumMsat.Val, + FeeBaseMSat: lnwire.MilliSatoshi( + upd.FeeBaseMsat.Val, + ), + FeeProportionalMillionths: lnwire.MilliSatoshi( + upd.FeeProportionalMillionths.Val, + ), + InboundFee: upd.InboundFee.ValOpt(), + ExtraSignedFields: upd.ExtraSignedFields, + }, nil + } + + return nil, fmt.Errorf("unknown channel update version: %v", + update.MsgType()) +} + // IsNode1 returns true if this policy was announced by the channel's node_1. func (c *ChannelEdgePolicy) IsNode1() bool { if c.Version == lnwire.GossipVersion1 { diff --git a/routing/router_test.go b/routing/router_test.go index 12c4adb8f..115c02c2c 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -2968,20 +2968,13 @@ func (m *mockGraphBuilder) ApplyChannelUpdate(msg *lnwire.ChannelUpdate1) bool { return false } - err := m.updateEdge(&models.ChannelEdgePolicy{ - Version: msg.GossipVersion(), - SigBytes: msg.Signature.ToSignatureBytes(), - ChannelID: msg.ShortChannelID.ToUint64(), - LastUpdate: time.Unix(int64(msg.Timestamp), 0), - MessageFlags: msg.MessageFlags, - ChannelFlags: msg.ChannelFlags, - TimeLockDelta: msg.TimeLockDelta, - MinHTLC: msg.HtlcMinimumMsat, - MaxHTLC: msg.HtlcMaximumMsat, - FeeBaseMSat: lnwire.MilliSatoshi(msg.BaseFee), - FeeProportionalMillionths: lnwire.MilliSatoshi(msg.FeeRate), - ExtraOpaqueData: msg.ExtraOpaqueData, - }) + update, err := models.ChanEdgePolicyFromWire( + msg.ShortChannelID.ToUint64(), msg, + ) + if err != nil { + return false + } + err = m.updateEdge(update) return err == nil }