@@ -139,3 +139,113 @@ func assertCachedPolicyEqual(t *testing.T, original,
139139 require .Equal (t , original .ToNodePubKey (), cached .ToNodePubKey ())
140140 }
141141}
142+
143+ // TestGraphCacheDisabledPoliciesRegression is a regression test for the bug
144+ // where channels with both policies disabled were not added to the graph cache
145+ // during population, preventing future policy updates from working.
146+ //
147+ // The bug flow was:
148+ // 1. Channel with both policies disabled exists in DB.
149+ // 2. populateCache skips adding it to graph cache entirely.
150+ // 3. Later, a policy update arrives enabling one direction.
151+ // 4. UpdateEdgePolicy updates the DB successfully.
152+ // 5. UpdateEdgePolicy tries to update graph cache but channel not found.
153+ // 6. Channel never becomes usable for routing.
154+ func TestGraphCacheDisabledPoliciesRegression (t * testing.T ) {
155+ t .Parallel ()
156+
157+ // Create a simple cache instance.
158+ cache := NewGraphCache (10 )
159+
160+ // Simulate a channel with both policies disabled.
161+ chanID := uint64 (12345 )
162+ node1 := pubKey1
163+ node2 := pubKey2
164+
165+ edgeInfo := & models.CachedEdgeInfo {
166+ ChannelID : chanID ,
167+ NodeKey1Bytes : node1 ,
168+ NodeKey2Bytes : node2 ,
169+ Capacity : 1000000 ,
170+ }
171+
172+ // Create two disabled policies.
173+ disabledPolicy1 := & models.CachedEdgePolicy {
174+ ChannelID : chanID ,
175+ ChannelFlags : lnwire .ChanUpdateDisabled ,
176+ }
177+ disabledPolicy2 := & models.CachedEdgePolicy {
178+ ChannelID : chanID ,
179+ ChannelFlags : lnwire .ChanUpdateDisabled |
180+ lnwire .ChanUpdateDirection ,
181+ }
182+
183+ // Add the channel with both policies disabled (simulating
184+ // populateCache).
185+ cache .AddChannel (edgeInfo , disabledPolicy1 , disabledPolicy2 )
186+
187+ // Verify the channel structure was added to cache.
188+ var foundChannels []* DirectedChannel
189+ err := cache .ForEachChannel (node1 , func (c * DirectedChannel ) error {
190+ if c .ChannelID == chanID {
191+ foundChannels = append (foundChannels , c )
192+ }
193+
194+ return nil
195+ })
196+ require .NoError (t , err )
197+ require .Len (t , foundChannels , 1 ,
198+ "channel structure should be in cache even when both " +
199+ "policies are disabled" )
200+
201+ // Verify policies were NOT added (both disabled).
202+ require .False (t , foundChannels [0 ].OutPolicySet ,
203+ "disabled outgoing policy should not be set in cache" )
204+ require .Nil (t , foundChannels [0 ].InPolicy ,
205+ "disabled incoming policy should not be set in cache" )
206+
207+ // Now simulate receiving a fresh update enabling one direction.
208+ enabledPolicy1 := & models.CachedEdgePolicy {
209+ ChannelID : chanID ,
210+ ChannelFlags : 0 , // NOT disabled anymore
211+ TimeLockDelta : 40 ,
212+ MinHTLC : lnwire .MilliSatoshi (1000 ),
213+ }
214+
215+ // Update the policy (simulating what UpdateEdgePolicy does).
216+ cache .UpdatePolicy (enabledPolicy1 , node1 , node2 )
217+
218+ // Verify the policy update succeeded. Before the fix, UpdatePolicy
219+ // would log "Channel not found in graph cache" and return early,
220+ // so the policy would never be added.
221+ foundChannels = nil
222+ err = cache .ForEachChannel (node1 , func (c * DirectedChannel ) error {
223+ if c .ChannelID == chanID {
224+ foundChannels = append (foundChannels , c )
225+ }
226+
227+ return nil
228+ })
229+ require .NoError (t , err )
230+ require .Len (t , foundChannels , 1 )
231+
232+ // The policy should now be set.
233+ require .True (t , foundChannels [0 ].OutPolicySet ,
234+ "REGRESSION: policy update should work even for channels that " +
235+ "had both policies disabled initially" )
236+
237+ // Verify we can also see it from node2's perspective.
238+ foundChannels = nil
239+ err = cache .ForEachChannel (node2 , func (c * DirectedChannel ) error {
240+ if c .ChannelID == chanID {
241+ foundChannels = append (foundChannels , c )
242+ }
243+
244+ return nil
245+ })
246+ require .NoError (t , err )
247+ require .Len (t , foundChannels , 1 )
248+ require .NotNil (t , foundChannels [0 ].InPolicy ,
249+ "incoming policy should be set after policy update" )
250+ require .Equal (t , uint16 (40 ), foundChannels [0 ].InPolicy .TimeLockDelta )
251+ }
0 commit comments