Files
lnd/graph/db/models/cached_edge_policy.go
Elle Mouton 9c7a12c0e0 graph/db: refactor CachedEdgePolicy to use explicit boolean fields
Replace MessageFlags and ChannelFlags bitfields in CachedEdgePolicy
with explicit boolean fields to improve clarity and support both v1
and v2 channel updates:

- Replace MessageFlags with HasMaxHTLC boolean.
- Replace ChannelFlags with IsNode1 and IsDisabled booleans.
- Update NewCachedPolicy to extract these fields version-appropriately:
  - For v1: derive from MessageFlags and ChannelFlags bits.
  - For v2: derive from policy.SecondPeer and policy.DisableFlags.

Update all call sites that used method calls IsNode1() and IsDisabled()
to instead access the fields directly. This includes:
- graph_cache.go: policy direction and disable checks
- unified_edges.go: HasMaxHTLC and IsDisabled checks
- Tests: policy construction and assertions

This refactoring improves readability by making the cached policy's
state explicit rather than encoded in bitfields, and enables seamless
support for both gossip protocol versions.
2026-02-13 07:21:24 +02:00

113 lines
4.0 KiB
Go

package models
import (
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)
const (
// feeRateParts is the total number of parts used to express fee rates.
feeRateParts = 1e6
)
// CachedEdgePolicy is a struct that only caches the information of a
// ChannelEdgePolicy that we actually use for pathfinding and therefore need to
// store in the cache.
type CachedEdgePolicy struct {
// ChannelID is the unique channel ID for the channel. The first 3
// bytes are the block height, the next 3 the index within the block,
// and the last 2 bytes are the output index for the channel.
ChannelID uint64
// HasMaxHTLC indicates whether the policy has a max HTLC value.
HasMaxHTLC bool
// IsNode1 indicates whether this policy was announced by the channel's
// node_1.
IsNode1 bool
// IsDisabled indicates whether the policy disables forwarding.
IsDisabled bool
// TimeLockDelta is the number of blocks this node will subtract from
// the expiry of an incoming HTLC. This value expresses the time buffer
// the node would like to HTLC exchanges.
TimeLockDelta uint16
// MinHTLC is the smallest value HTLC this node will forward, expressed
// in millisatoshi.
MinHTLC lnwire.MilliSatoshi
// MaxHTLC is the largest value HTLC this node will forward, expressed
// in millisatoshi.
MaxHTLC lnwire.MilliSatoshi
// FeeBaseMSat is the base HTLC fee that will be charged for forwarding
// ANY HTLC, expressed in mSAT's.
FeeBaseMSat lnwire.MilliSatoshi
// FeeProportionalMillionths is the rate that the node will charge for
// HTLCs for each millionth of a satoshi forwarded.
FeeProportionalMillionths lnwire.MilliSatoshi
// InboundFee is the fee that the node will charge for incoming HTLCs.
InboundFee fn.Option[lnwire.Fee]
// ToNodePubKey is a function that returns the to node of a policy.
// Since we only ever store the inbound policy, this is always the node
// that we query the channels for in ForEachChannel(). Therefore, we can
// save a lot of space by not storing this information in the memory and
// instead just set this function when we copy the policy from cache in
// ForEachChannel().
ToNodePubKey func() route.Vertex
// ToNodeFeatures are the to node's features. They are never set while
// the edge is in the cache, only on the copy that is returned in
// ForEachChannel().
ToNodeFeatures *lnwire.FeatureVector
}
// ComputeFee computes the fee to forward an HTLC of `amt` milli-satoshis over
// the passed active payment channel. This value is currently computed as
// specified in BOLT07, but will likely change in the near future.
func (c *CachedEdgePolicy) ComputeFee(
amt lnwire.MilliSatoshi) lnwire.MilliSatoshi {
return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts
}
// NewCachedPolicy turns a full policy into a minimal one that can be cached.
func NewCachedPolicy(policy *ChannelEdgePolicy) *CachedEdgePolicy {
if policy.Version != lnwire.GossipVersion2 {
return &CachedEdgePolicy{
ChannelID: policy.ChannelID,
HasMaxHTLC: policy.MessageFlags.HasMaxHtlc(),
IsDisabled: policy.ChannelFlags&
lnwire.ChanUpdateDisabled != 0,
IsNode1: policy.ChannelFlags&
lnwire.ChanUpdateDirection == 0,
TimeLockDelta: policy.TimeLockDelta,
MinHTLC: policy.MinHTLC,
MaxHTLC: policy.MaxHTLC,
FeeBaseMSat: policy.FeeBaseMSat,
FeeProportionalMillionths: policy.
FeeProportionalMillionths,
InboundFee: policy.InboundFee,
}
}
return &CachedEdgePolicy{
ChannelID: policy.ChannelID,
HasMaxHTLC: true,
IsNode1: !policy.SecondPeer,
IsDisabled: !policy.DisableFlags.IsEnabled(),
TimeLockDelta: policy.TimeLockDelta,
MinHTLC: policy.MinHTLC,
MaxHTLC: policy.MaxHTLC,
FeeBaseMSat: policy.FeeBaseMSat,
FeeProportionalMillionths: policy.FeeProportionalMillionths,
InboundFee: policy.InboundFee,
}
}