mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
openchannel: cancel shims with a live context
In manager.go, deferred shim cleanup was calling FundingStateStep with the original request ctx. If the user had already canceled that context, the cleanup RPC would run with a canceled context and could fail to remove the pending shim. I changed that cleanup path to use context.WithoutCancel(ctx) so the cancellation RPC still has a live context.
This commit is contained in:
parent
0b295123e7
commit
3e526faf82
2 changed files with 46 additions and 10 deletions
|
|
@ -458,9 +458,7 @@ func (m *Manager) openChannelPsbt(ctx context.Context,
|
||||||
log.Infof("Starting PSBT funding flow with pending channel ID %x.\n",
|
log.Infof("Starting PSBT funding flow with pending channel ID %x.\n",
|
||||||
pendingChanID)
|
pendingChanID)
|
||||||
|
|
||||||
// maybeCancelShim is a helper function that cancels the funding shim
|
defer func() {
|
||||||
// with the RPC server in case we end up aborting early.
|
|
||||||
maybeCancelShim := func() {
|
|
||||||
shimMu.Lock()
|
shimMu.Lock()
|
||||||
defer shimMu.Unlock()
|
defer shimMu.Unlock()
|
||||||
|
|
||||||
|
|
@ -478,15 +476,14 @@ func (m *Manager) openChannelPsbt(ctx context.Context,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := m.cfg.LightningClient.FundingStateStep(
|
_, err := m.cfg.LightningClient.FundingStateStep(
|
||||||
ctx, cancelMsg,
|
context.WithoutCancel(ctx), cancelMsg,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error canceling shim: %v\n", err)
|
log.Errorf("Error canceling shim: %v\n", err)
|
||||||
}
|
}
|
||||||
shimPending = false
|
shimPending = false
|
||||||
}
|
}
|
||||||
}
|
}()
|
||||||
defer maybeCancelShim()
|
|
||||||
|
|
||||||
// Create the PSBT funding shim that will tell the funding manager we
|
// Create the PSBT funding shim that will tell the funding manager we
|
||||||
// want to use a PSBT.
|
// want to use a PSBT.
|
||||||
|
|
|
||||||
|
|
@ -608,9 +608,10 @@ type mockLndClient struct {
|
||||||
|
|
||||||
rawClient lnrpc.LightningClient
|
rawClient lnrpc.LightningClient
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
fundingStepIdx int
|
fundingStepIdx int
|
||||||
fundingStepErr error
|
fundingStepErr error
|
||||||
|
fundingStepCtxErrs []error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockLndClient) RawClientWithMacAuth(
|
func (m *mockLndClient) RawClientWithMacAuth(
|
||||||
|
|
@ -620,13 +621,14 @@ func (m *mockLndClient) RawClientWithMacAuth(
|
||||||
return ctx, 0, m.rawClient
|
return ctx, 0, m.rawClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockLndClient) FundingStateStep(_ context.Context,
|
func (m *mockLndClient) FundingStateStep(ctx context.Context,
|
||||||
_ *lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) {
|
_ *lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) {
|
||||||
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
m.fundingStepIdx++
|
m.fundingStepIdx++
|
||||||
|
m.fundingStepCtxErrs = append(m.fundingStepCtxErrs, ctx.Err())
|
||||||
|
|
||||||
return &lnrpc.FundingStateStepResp{}, m.fundingStepErr
|
return &lnrpc.FundingStateStepResp{}, m.fundingStepErr
|
||||||
}
|
}
|
||||||
|
|
@ -746,6 +748,43 @@ func TestStreamOpenError(t *testing.T) {
|
||||||
// Verify that the shim was canceled via FundingStateStep.
|
// Verify that the shim was canceled via FundingStateStep.
|
||||||
lnClient.mu.Lock()
|
lnClient.mu.Lock()
|
||||||
require.Equal(t, 1, lnClient.fundingStepIdx)
|
require.Equal(t, 1, lnClient.fundingStepIdx)
|
||||||
|
require.Len(t, lnClient.fundingStepCtxErrs, 1)
|
||||||
|
require.NoError(t, lnClient.fundingStepCtxErrs[0])
|
||||||
|
lnClient.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestStreamOpenErrorWithCanceledContext verifies that deferred shim cleanup
|
||||||
|
// still uses a live context even if the caller canceled the original request.
|
||||||
|
func TestStreamOpenErrorWithCanceledContext(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
mockRaw := &mockRawLnrpcClient{
|
||||||
|
openErr: errors.New("connection refused"),
|
||||||
|
}
|
||||||
|
lnClient := &mockLndClient{rawClient: mockRaw}
|
||||||
|
|
||||||
|
manager := &Manager{
|
||||||
|
cfg: &Config{
|
||||||
|
LightningClient: lnClient,
|
||||||
|
ChainParams: &chaincfg.RegressionNetParams,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
req := &lnrpc.OpenChannelRequest{
|
||||||
|
LocalFundingAmount: 100000,
|
||||||
|
MinConfs: defaultUtxoMinConf,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := manager.openChannelPsbt(ctx, req, nil, 0)
|
||||||
|
require.ErrorContains(t, err, "opening stream to server failed")
|
||||||
|
|
||||||
|
lnClient.mu.Lock()
|
||||||
|
require.Equal(t, 1, lnClient.fundingStepIdx)
|
||||||
|
require.Len(t, lnClient.fundingStepCtxErrs, 1)
|
||||||
|
require.NoError(t, lnClient.fundingStepCtxErrs[0])
|
||||||
lnClient.mu.Unlock()
|
lnClient.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue