Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
DBytes33 (33 bytes) records, preventing malformed TLV data from being
accepted.

- [Fixed missing graph data for local channels](https://github.com/lightningnetwork/lnd/pull/10516)
that prevented channels from being used for sending or forwarding payments.
The fix introduces a conditional mechanism to defer failure of channels with
missing edge policies when the `createMissingEdge` flag is enabled, allowing
them to be properly recreated instead of being immediately excluded from
policy updates.

# New Features

- Basic Support for [onion messaging forwarding](https://github.com/lightningnetwork/lnd/pull/9868)
Expand Down
18 changes: 13 additions & 5 deletions routing/localchans/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,19 @@ func (r *Manager) UpdatePolicy(ctx context.Context,
"a channel. Channel point: %v",
info.ChannelPoint.String())

failedUpdates = append(failedUpdates, makeFailureItem(
info.ChannelPoint,
lnrpc.UpdateFailure_UPDATE_FAILURE_NOT_FOUND,
"edge policy not found",
))
// If createMissingEdge is true, we need to keep this
// channel in unprocessedChans so it can be handled by
// the createMissingEdge logic later.
if createMissingEdge {
unprocessedChans[info.ChannelPoint] = struct{}{}
} else {
failedUpdates = append(failedUpdates,
makeFailureItem(
info.ChannelPoint,
lnrpc.UpdateFailure_UPDATE_FAILURE_NOT_FOUND,
"edge policy not found",
))
}

return nil
}
Expand Down
63 changes: 61 additions & 2 deletions routing/localchans/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ func TestManager(t *testing.T) {
t.Parallel()

type channel struct {
edgeInfo *models.ChannelEdgeInfo
edgeInfo *models.ChannelEdgeInfo
edgePolicy *models.ChannelEdgePolicy
// allowNilPolicy signals whether we should pass a nil edge policy
// to the callback instead of defaulting to currentPolicy.
allowNilPolicy bool
}

var (
Expand Down Expand Up @@ -130,7 +134,14 @@ func TestManager(t *testing.T) {
*models.ChannelEdgePolicy) error, _ func()) error {

for _, c := range channelSet {
if err := cb(c.edgeInfo, &currentPolicy); err != nil {
// Use the channel's specific edge policy if set,
// otherwise use the default current policy.
edgePolicy := c.edgePolicy
if edgePolicy == nil && !c.allowNilPolicy &&
len(c.edgeInfo.ChannelPoint.Hash) != 0 {
edgePolicy = &currentPolicy
}
Comment on lines +137 to +143
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The logic in this mock for forAllOutgoingChannels seems to prevent the new test cases from correctly testing the edge == nil scenario. The new tests ("nil edge policy recreated" and "nil edge policy not recreated") are intended to test the case where ForAllOutgoingChannels provides a nil edge policy. However, the current logic assigns &currentPolicy to edgePolicy when c.edgePolicy is nil and the channel point is valid. This means the if edge == nil block in manager.go is not actually exercised by these tests.

To ensure the new logic in manager.go is tested, this mock should be updated to allow passing a nil policy to the callback cb for the relevant test cases.

if err := cb(c.edgeInfo, edgePolicy); err != nil {
return err
}
}
Expand Down Expand Up @@ -309,6 +320,54 @@ func TestManager(t *testing.T) {
},
expectErr: nil,
},
{
// Here, the edge policy is nil but edge info exists.
// The edge should be recreated because
// createMissingEdge is true.
name: "nil edge policy recreated",
currentPolicy: models.ChannelEdgePolicy{},
newPolicy: newPolicy,
channelSet: []channel{
{
edgeInfo: &models.ChannelEdgeInfo{
Capacity: chanCap,
ChannelPoint: chanPointValid,
},
edgePolicy: nil,
allowNilPolicy: true,
},
},
specifiedChanPoints: []wire.OutPoint{chanPointValid},
createMissingEdge: true,
expectedNumUpdates: 1,
expectedUpdateFailures: []lnrpc.UpdateFailure{},
expectErr: nil,
},
{
// Here, the edge policy is nil but edge info exists.
// The edge will not be recreated because
// createMissingEdge is false.
name: "nil edge policy not recreated",
currentPolicy: models.ChannelEdgePolicy{},
newPolicy: newPolicy,
channelSet: []channel{
{
edgeInfo: &models.ChannelEdgeInfo{
Capacity: chanCap,
ChannelPoint: chanPointValid,
},
edgePolicy: nil,
allowNilPolicy: true,
},
},
specifiedChanPoints: []wire.OutPoint{chanPointValid},
createMissingEdge: false,
expectedNumUpdates: 0,
expectedUpdateFailures: []lnrpc.UpdateFailure{
lnrpc.UpdateFailure_UPDATE_FAILURE_NOT_FOUND,
},
expectErr: nil,
},
}

for _, test := range tests {
Expand Down