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.
This commit is contained in:
5 files changed
+59
-45
No files matched your search
@@ -142,8 +142,8 @@ func (c *GraphCache) AddChannel(info *models.CachedEdgeInfo,
|
|||||||
// Skip adding policies if both are disabled, as the channel is
|
// Skip adding policies if both are disabled, as the channel is
|
||||||
// currently unusable for routing. However, we still add the channel
|
// currently unusable for routing. However, we still add the channel
|
||||||
// structure above so that policy updates can later enable it.
|
// structure above so that policy updates can later enable it.
|
||||||
if policy1 != nil && policy1.IsDisabled() &&
|
if policy1 != nil && policy1.IsDisabled &&
|
||||||
policy2 != nil && policy2.IsDisabled() {
|
policy2 != nil && policy2.IsDisabled {
|
||||||
|
|
||||||
log.Debugf("Skipping policies for channel %v: both "+
|
log.Debugf("Skipping policies for channel %v: both "+
|
||||||
"policies are disabled (channel structure still "+
|
"policies are disabled (channel structure still "+
|
||||||
@@ -156,14 +156,14 @@ func (c *GraphCache) AddChannel(info *models.CachedEdgeInfo,
|
|||||||
// of node 2 then we have the policy 1 as seen from node 1.
|
// of node 2 then we have the policy 1 as seen from node 1.
|
||||||
if policy1 != nil {
|
if policy1 != nil {
|
||||||
fromNode, toNode := info.NodeKey1Bytes, info.NodeKey2Bytes
|
fromNode, toNode := info.NodeKey1Bytes, info.NodeKey2Bytes
|
||||||
if !policy1.IsNode1() {
|
if !policy1.IsNode1 {
|
||||||
fromNode, toNode = toNode, fromNode
|
fromNode, toNode = toNode, fromNode
|
||||||
}
|
}
|
||||||
c.UpdatePolicy(policy1, fromNode, toNode)
|
c.UpdatePolicy(policy1, fromNode, toNode)
|
||||||
}
|
}
|
||||||
if policy2 != nil {
|
if policy2 != nil {
|
||||||
fromNode, toNode := info.NodeKey2Bytes, info.NodeKey1Bytes
|
fromNode, toNode := info.NodeKey2Bytes, info.NodeKey1Bytes
|
||||||
if policy2.IsNode1() {
|
if policy2.IsNode1 {
|
||||||
fromNode, toNode = toNode, fromNode
|
fromNode, toNode = toNode, fromNode
|
||||||
}
|
}
|
||||||
c.UpdatePolicy(policy2, fromNode, toNode)
|
c.UpdatePolicy(policy2, fromNode, toNode)
|
||||||
@@ -210,7 +210,7 @@ func (c *GraphCache) UpdatePolicy(policy *models.CachedEdgePolicy, fromNode,
|
|||||||
switch {
|
switch {
|
||||||
// This is node 1, and it is edge 1, so this is the outgoing
|
// This is node 1, and it is edge 1, so this is the outgoing
|
||||||
// policy for node 1.
|
// policy for node 1.
|
||||||
case channel.IsNode1 && policy.IsNode1():
|
case channel.IsNode1 && policy.IsNode1:
|
||||||
channel.OutPolicySet = true
|
channel.OutPolicySet = true
|
||||||
policy.InboundFee.WhenSome(func(fee lnwire.Fee) {
|
policy.InboundFee.WhenSome(func(fee lnwire.Fee) {
|
||||||
channel.InboundFee = fee
|
channel.InboundFee = fee
|
||||||
@@ -218,7 +218,7 @@ func (c *GraphCache) UpdatePolicy(policy *models.CachedEdgePolicy, fromNode,
|
|||||||
|
|
||||||
// This is node 2, and it is edge 2, so this is the outgoing
|
// This is node 2, and it is edge 2, so this is the outgoing
|
||||||
// policy for node 2.
|
// policy for node 2.
|
||||||
case !channel.IsNode1 && !policy.IsNode1():
|
case !channel.IsNode1 && !policy.IsNode1:
|
||||||
channel.OutPolicySet = true
|
channel.OutPolicySet = true
|
||||||
policy.InboundFee.WhenSome(func(fee lnwire.Fee) {
|
policy.InboundFee.WhenSome(func(fee lnwire.Fee) {
|
||||||
channel.InboundFee = fee
|
channel.InboundFee = fee
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ func TestGraphCacheAddNode(t *testing.T) {
|
|||||||
runTest := func(nodeA, nodeB route.Vertex) {
|
runTest := func(nodeA, nodeB route.Vertex) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
channelFlagA, channelFlagB := 0, 1
|
isNode1A, isNode1B := true, false
|
||||||
if nodeA == pubKey2 {
|
if nodeA == pubKey2 {
|
||||||
channelFlagA, channelFlagB = 1, 0
|
isNode1A, isNode1B = false, true
|
||||||
}
|
}
|
||||||
|
|
||||||
inboundFee := lnwire.Fee{
|
inboundFee := lnwire.Fee{
|
||||||
@@ -44,8 +44,9 @@ func TestGraphCacheAddNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
outPolicy1 := &models.CachedEdgePolicy{
|
outPolicy1 := &models.CachedEdgePolicy{
|
||||||
ChannelID: 1000,
|
ChannelID: 1000,
|
||||||
ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagA),
|
IsNode1: isNode1A,
|
||||||
|
IsDisabled: false,
|
||||||
ToNodePubKey: func() route.Vertex {
|
ToNodePubKey: func() route.Vertex {
|
||||||
return nodeB
|
return nodeB
|
||||||
},
|
},
|
||||||
@@ -53,8 +54,9 @@ func TestGraphCacheAddNode(t *testing.T) {
|
|||||||
InboundFee: fn.Some(inboundFee),
|
InboundFee: fn.Some(inboundFee),
|
||||||
}
|
}
|
||||||
inPolicy1 := &models.CachedEdgePolicy{
|
inPolicy1 := &models.CachedEdgePolicy{
|
||||||
ChannelID: 1000,
|
ChannelID: 1000,
|
||||||
ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagB),
|
IsNode1: isNode1B,
|
||||||
|
IsDisabled: false,
|
||||||
ToNodePubKey: func() route.Vertex {
|
ToNodePubKey: func() route.Vertex {
|
||||||
return nodeA
|
return nodeA
|
||||||
},
|
},
|
||||||
@@ -125,8 +127,9 @@ func assertCachedPolicyEqual(t *testing.T, original,
|
|||||||
cached *models.CachedEdgePolicy) {
|
cached *models.CachedEdgePolicy) {
|
||||||
|
|
||||||
require.Equal(t, original.ChannelID, cached.ChannelID)
|
require.Equal(t, original.ChannelID, cached.ChannelID)
|
||||||
require.Equal(t, original.MessageFlags, cached.MessageFlags)
|
require.Equal(t, original.HasMaxHTLC, cached.HasMaxHTLC)
|
||||||
require.Equal(t, original.ChannelFlags, cached.ChannelFlags)
|
require.Equal(t, original.IsNode1, cached.IsNode1)
|
||||||
|
require.Equal(t, original.IsDisabled, cached.IsDisabled)
|
||||||
require.Equal(t, original.TimeLockDelta, cached.TimeLockDelta)
|
require.Equal(t, original.TimeLockDelta, cached.TimeLockDelta)
|
||||||
require.Equal(t, original.MinHTLC, cached.MinHTLC)
|
require.Equal(t, original.MinHTLC, cached.MinHTLC)
|
||||||
require.Equal(t, original.MaxHTLC, cached.MaxHTLC)
|
require.Equal(t, original.MaxHTLC, cached.MaxHTLC)
|
||||||
@@ -171,13 +174,14 @@ func TestGraphCacheDisabledPoliciesRegression(t *testing.T) {
|
|||||||
|
|
||||||
// Create two disabled policies.
|
// Create two disabled policies.
|
||||||
disabledPolicy1 := &models.CachedEdgePolicy{
|
disabledPolicy1 := &models.CachedEdgePolicy{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChannelFlags: lnwire.ChanUpdateDisabled,
|
IsNode1: true,
|
||||||
|
IsDisabled: true,
|
||||||
}
|
}
|
||||||
disabledPolicy2 := &models.CachedEdgePolicy{
|
disabledPolicy2 := &models.CachedEdgePolicy{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChannelFlags: lnwire.ChanUpdateDisabled |
|
IsNode1: false,
|
||||||
lnwire.ChanUpdateDirection,
|
IsDisabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the channel with both policies disabled (simulating
|
// Add the channel with both policies disabled (simulating
|
||||||
@@ -207,7 +211,8 @@ func TestGraphCacheDisabledPoliciesRegression(t *testing.T) {
|
|||||||
// Now simulate receiving a fresh update enabling one direction.
|
// Now simulate receiving a fresh update enabling one direction.
|
||||||
enabledPolicy1 := &models.CachedEdgePolicy{
|
enabledPolicy1 := &models.CachedEdgePolicy{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChannelFlags: 0, // NOT disabled anymore
|
IsNode1: true,
|
||||||
|
IsDisabled: false,
|
||||||
TimeLockDelta: 40,
|
TimeLockDelta: 40,
|
||||||
MinHTLC: lnwire.MilliSatoshi(1000),
|
MinHTLC: lnwire.MilliSatoshi(1000),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,15 @@ type CachedEdgePolicy struct {
|
|||||||
// and the last 2 bytes are the output index for the channel.
|
// and the last 2 bytes are the output index for the channel.
|
||||||
ChannelID uint64
|
ChannelID uint64
|
||||||
|
|
||||||
// MessageFlags is a bitfield which indicates the presence of optional
|
// HasMaxHTLC indicates whether the policy has a max HTLC value.
|
||||||
// fields (like max_htlc) in the policy.
|
HasMaxHTLC bool
|
||||||
MessageFlags lnwire.ChanUpdateMsgFlags
|
|
||||||
|
|
||||||
// ChannelFlags is a bitfield which signals the capabilities of the
|
// IsNode1 indicates whether this policy was announced by the channel's
|
||||||
// channel as well as the directed edge this update applies to.
|
// node_1.
|
||||||
ChannelFlags lnwire.ChanUpdateChanFlags
|
IsNode1 bool
|
||||||
|
|
||||||
|
// IsDisabled indicates whether the policy disables forwarding.
|
||||||
|
IsDisabled bool
|
||||||
|
|
||||||
// TimeLockDelta is the number of blocks this node will subtract from
|
// TimeLockDelta is the number of blocks this node will subtract from
|
||||||
// the expiry of an incoming HTLC. This value expresses the time buffer
|
// the expiry of an incoming HTLC. This value expresses the time buffer
|
||||||
@@ -75,24 +77,31 @@ func (c *CachedEdgePolicy) ComputeFee(
|
|||||||
return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts
|
return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDisabled returns true if the channel is disabled in the direction from the
|
|
||||||
// advertising node.
|
|
||||||
func (c *CachedEdgePolicy) IsDisabled() bool {
|
|
||||||
return c.ChannelFlags&lnwire.ChanUpdateDisabled != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNode1 returns true if this policy was announced by the channel's node_1
|
|
||||||
// node.
|
|
||||||
func (c *CachedEdgePolicy) IsNode1() bool {
|
|
||||||
return c.ChannelFlags&lnwire.ChanUpdateDirection == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCachedPolicy turns a full policy into a minimal one that can be cached.
|
// NewCachedPolicy turns a full policy into a minimal one that can be cached.
|
||||||
func NewCachedPolicy(policy *ChannelEdgePolicy) *CachedEdgePolicy {
|
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{
|
return &CachedEdgePolicy{
|
||||||
ChannelID: policy.ChannelID,
|
ChannelID: policy.ChannelID,
|
||||||
MessageFlags: policy.MessageFlags,
|
HasMaxHTLC: true,
|
||||||
ChannelFlags: policy.ChannelFlags,
|
IsNode1: !policy.SecondPeer,
|
||||||
|
IsDisabled: !policy.DisableFlags.IsEnabled(),
|
||||||
TimeLockDelta: policy.TimeLockDelta,
|
TimeLockDelta: policy.TimeLockDelta,
|
||||||
MinHTLC: policy.MinHTLC,
|
MinHTLC: policy.MinHTLC,
|
||||||
MaxHTLC: policy.MaxHTLC,
|
MaxHTLC: policy.MaxHTLC,
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func (u *unifiedEdge) amtInRange(amt lnwire.MilliSatoshi) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip channels for which this htlc is too large.
|
// Skip channels for which this htlc is too large.
|
||||||
if u.policy.MessageFlags.HasMaxHtlc() &&
|
if u.policy.HasMaxHTLC &&
|
||||||
amt > u.policy.MaxHTLC {
|
amt > u.policy.MaxHTLC {
|
||||||
|
|
||||||
log.Tracef("Exceeds policy's MaxHTLC: amt=%v, MaxHTLC=%v",
|
log.Tracef("Exceeds policy's MaxHTLC: amt=%v, MaxHTLC=%v",
|
||||||
@@ -376,7 +376,7 @@ func (u *edgeUnifier) getEdgeNetwork(netAmtReceived lnwire.MilliSatoshi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For network channels, skip the disabled ones.
|
// For network channels, skip the disabled ones.
|
||||||
if edge.policy.IsDisabled() {
|
if edge.policy.IsDisabled {
|
||||||
log.Debugf("Skipped edge %v due to it being disabled",
|
log.Debugf("Skipped edge %v due to it being disabled",
|
||||||
edge.policy.ChannelID)
|
edge.policy.ChannelID)
|
||||||
continue
|
continue
|
||||||
@@ -385,7 +385,7 @@ func (u *edgeUnifier) getEdgeNetwork(netAmtReceived lnwire.MilliSatoshi,
|
|||||||
// Track the maximal capacity for usable channels. If we don't
|
// Track the maximal capacity for usable channels. If we don't
|
||||||
// know the capacity, we fall back to MaxHTLC.
|
// know the capacity, we fall back to MaxHTLC.
|
||||||
capMsat := lnwire.NewMSatFromSatoshis(edge.capacity)
|
capMsat := lnwire.NewMSatFromSatoshis(edge.capacity)
|
||||||
if capMsat == 0 && edge.policy.MessageFlags.HasMaxHtlc() {
|
if capMsat == 0 && edge.policy.HasMaxHTLC {
|
||||||
log.Tracef("No capacity available for channel %v, "+
|
log.Tracef("No capacity available for channel %v, "+
|
||||||
"using MaxHtlcMsat (%v) as a fallback.",
|
"using MaxHtlcMsat (%v) as a fallback.",
|
||||||
edge.policy.ChannelID, edge.policy.MaxHTLC)
|
edge.policy.ChannelID, edge.policy.MaxHTLC)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func TestNodeEdgeUnifier(t *testing.T) {
|
|||||||
FeeProportionalMillionths: 100000,
|
FeeProportionalMillionths: 100000,
|
||||||
FeeBaseMSat: 30,
|
FeeBaseMSat: 30,
|
||||||
TimeLockDelta: 60,
|
TimeLockDelta: 60,
|
||||||
MessageFlags: lnwire.ChanUpdateRequiredMaxHtlc,
|
HasMaxHTLC: true,
|
||||||
MaxHTLC: 5000,
|
MaxHTLC: 5000,
|
||||||
MinHTLC: 100,
|
MinHTLC: 100,
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ func TestNodeEdgeUnifier(t *testing.T) {
|
|||||||
FeeProportionalMillionths: 190000,
|
FeeProportionalMillionths: 190000,
|
||||||
FeeBaseMSat: 10,
|
FeeBaseMSat: 10,
|
||||||
TimeLockDelta: 40,
|
TimeLockDelta: 40,
|
||||||
MessageFlags: lnwire.ChanUpdateRequiredMaxHtlc,
|
HasMaxHTLC: true,
|
||||||
MaxHTLC: 4000,
|
MaxHTLC: 4000,
|
||||||
MinHTLC: 100,
|
MinHTLC: 100,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user