contractcourt: add sync dispatch fast-path for single confirmation closes
In this commit, we add a fast-path optimization to the chain watcher's closeObserver that immediately dispatches close events when only a single confirmation is required (numConfs == 1). This addresses a timing issue with integration tests that were designed around the old synchronous blockbeat behavior, where close events were dispatched immediately upon spend detection. The recent async confirmation architecture (introduced in commit f6f716ab7) properly handles reorgs by waiting for N confirmations before dispatching close events. However, this created a race condition in integration tests that mine blocks synchronously and expect immediate close notifications. With the build tag setting numConfs to 1 for itests, the async confirmation notification could arrive after the test already started waiting for the close event, causing timeouts. We introduce a new handleSpendDispatch method that checks if numConfs == 1 and, if so, immediately calls handleCommitSpend to dispatch the close event synchronously, then returns true to skip the async state machine. This preserves the old behavior for integration tests while maintaining the full async reorg protection for production (where numConfs >= 3). The implementation adds the fast-path check in both spend detection paths (blockbeat and spend notification) to ensure consistent behavior regardless of which detects the spend first. We also update the affected unit tests to remove their expectation of confirmation registration, since the fast-path bypasses that step entirely. This approach optimizes for the integration test scenario without compromising production safety, as the fast-path only activates when a single confirmation is sufficient - a configuration that only exists in the controlled test environment.
This commit is contained in:
1 parent
bb781bbe84
commit
ebefe63f8e
2 files changed
+69
-11
No files matched your search
@@ -94,10 +94,9 @@ func TestChainWatcherRemoteUnilateralClose(t *testing.T) {
|
||||
t.Fatalf("unable to send blockbeat")
|
||||
}
|
||||
|
||||
// Wait for the chain watcher to register for confirmations and send
|
||||
// the confirmation. Since we set chanCloseConfs to 1, one confirmation
|
||||
// is sufficient.
|
||||
aliceNotifier.WaitForConfRegistrationAndSend(t)
|
||||
// With chanCloseConfs set to 1, the fast-path dispatches immediately
|
||||
// without confirmation registration. The close event should arrive
|
||||
// directly after processing the blockbeat.
|
||||
|
||||
// We should get a new spend event over the remote unilateral close
|
||||
// event channel.
|
||||
@@ -231,10 +230,9 @@ func TestChainWatcherRemoteUnilateralClosePendingCommit(t *testing.T) {
|
||||
t.Fatalf("unable to send blockbeat")
|
||||
}
|
||||
|
||||
// Wait for the chain watcher to register for confirmations and send
|
||||
// the confirmation. Since we set chanCloseConfs to 1, one confirmation
|
||||
// is sufficient.
|
||||
aliceNotifier.WaitForConfRegistrationAndSend(t)
|
||||
// With chanCloseConfs set to 1, the fast-path dispatches immediately
|
||||
// without confirmation registration. The close event should arrive
|
||||
// directly after processing the blockbeat.
|
||||
|
||||
// We should get a new spend event over the remote unilateral close
|
||||
// event channel.
|
||||
|
||||
Reference in new issue
Block a user