funding: fix race in itest for zero-conf funding
Fix a race condition where forwarding through a public zero-conf channel could fail with UnknownNextPeer when using the confirmed SCID. The issue occurred because ReportShortChanID (which updates the switch's baseIndex to handle the confirmed SCID) was called AFTER addToGraph (which announces the confirmed SCID to the network). With slow backends like postgres, addToGraph takes significant time, creating a window where other nodes learn about the confirmed SCID from gossip and attempt to route through it, but the receiving node's switch hasn't been updated yet to handle forwards using the confirmed SCID. The fix reorders operations to call ReportShortChanID before addToGraph, ensuring the switch is ready to handle the confirmed SCID before it's announced to the network. Forwards using either the alias or confirmed SCID will work since getLinkByMapping uses baseIndex to map both to the same link in forwardingIndex. Fixes flaky test: zero_conf-channel_policy_update_public_zero_conf
This commit is contained in:
2 files changed
+26
-21
No files matched your search
+16
-13
@@ -3957,6 +3957,22 @@ func (f *Manager) waitForZeroConfChannel(c *channeldb.OpenChannel) error {
|
||||
|
||||
// Six confirmations have been reached. If this channel is public,
|
||||
// we'll delete some of the alias mappings the gossiper uses.
|
||||
//
|
||||
// Tell the Switch to refresh the relevant ChannelLink so that forwards
|
||||
// under the confirmed SCID are possible. We do this BEFORE updating the
|
||||
// graph to avoid a race where other nodes learn about the confirmed
|
||||
// SCID from gossip before our switch is ready to handle forwards using
|
||||
// it. This is especially important for integration tests.
|
||||
err = f.cfg.ReportShortChanID(c.FundingOutpoint)
|
||||
if err != nil {
|
||||
// This should only fail if the link is not found in the
|
||||
// Switch's linkIndex map. If this is the case, then the peer
|
||||
// has gone offline and the next time the link is loaded, it
|
||||
// will have a refreshed state. Just log an error here.
|
||||
log.Errorf("unable to report scid for zero-conf channel "+
|
||||
"channel: %v", err)
|
||||
}
|
||||
|
||||
isPublic := c.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||
if isPublic {
|
||||
err = f.cfg.AliasManager.DeleteSixConfs(c.ShortChannelID)
|
||||
@@ -3985,19 +4001,6 @@ func (f *Manager) waitForZeroConfChannel(c *channeldb.OpenChannel) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Since we have now marked down the confirmed SCID, we'll also need to
|
||||
// tell the Switch to refresh the relevant ChannelLink so that forwards
|
||||
// under the confirmed SCID are possible if this is a public channel.
|
||||
err = f.cfg.ReportShortChanID(c.FundingOutpoint)
|
||||
if err != nil {
|
||||
// This should only fail if the link is not found in the
|
||||
// Switch's linkIndex map. If this is the case, then the peer
|
||||
// has gone offline and the next time the link is loaded, it
|
||||
// will have a refreshed state. Just log an error here.
|
||||
log.Errorf("unable to report scid for zero-conf channel "+
|
||||
"channel: %v", err)
|
||||
}
|
||||
|
||||
// Update the confirmed transaction's label.
|
||||
f.makeLabelForTx(c)
|
||||
|
||||
|
||||
+10
-8
@@ -4726,14 +4726,9 @@ func testZeroConf(t *testing.T, chanType *lnwire.ChannelType) {
|
||||
assertConfirmationHeight(t, alice, chanID, 1)
|
||||
assertConfirmationHeight(t, bob, chanID, 1)
|
||||
|
||||
// For taproot channels, we don't expect them to be announced atm.
|
||||
if !isTaprootChanType(chanType) {
|
||||
assertChannelAnnouncements(
|
||||
t, alice, bob, fundingAmt, nil, nil, nil, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// Both Alice and Bob should send on reportScidChan.
|
||||
// Both Alice and Bob should call ReportShortChanID first (before
|
||||
// sending announcements) to avoid a race where other nodes learn about
|
||||
// the confirmed SCID before the switch is ready.
|
||||
select {
|
||||
case <-alice.reportScidChan:
|
||||
case <-time.After(time.Second * 5):
|
||||
@@ -4746,6 +4741,13 @@ func testZeroConf(t *testing.T, chanType *lnwire.ChannelType) {
|
||||
t.Fatalf("did not call ReportShortChanID in time")
|
||||
}
|
||||
|
||||
// For taproot channels, we don't expect them to be announced atm.
|
||||
if !isTaprootChanType(chanType) {
|
||||
assertChannelAnnouncements(
|
||||
t, alice, bob, fundingAmt, nil, nil, nil, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// Send along the 6-confirmation channel so that announcement sigs can
|
||||
// be exchanged.
|
||||
alice.mockNotifier.sixConfChannel <- &chainntnfs.TxConfirmation{
|
||||
|
||||
Reference in new issue
Block a user