test(regtest): create blocks on demand instead of pacing on timeout_commit
Summary
The regression suite spent most of its time waiting, not executing. Each block took ~1.75s of timeout_commit pacing.
Why it waited. The harness creates every block with a /newBlock request. The node used to park in BeginBlocker, inside FinalizeBlock, until that request arrived. The SDK runs CometBFT with a single ABCI mutex (NewLocalClientCreator), so while parked the node served no queries and no CheckTx. The harness's only window to send txs and run checks between blocks was therefore timeout_commit (1s × TIME_FACTOR). That window is also the source of the known "operation slipped past the window" flakes.
Change (regtest build tag only)
cmd/thornode/start_regtest.go: the SDK's in-process start, with these differences:- per-connection ABCI mutexes (
NewConnSyncLocalClientCreator); timeout_commit = 0, overridable viaREGTEST_TIMEOUT_COMMIT;- an effectively infinite
timeout_propose, so a parked proposal never times out into a new round.
- per-connection ABCI mutexes (
app/app_regtest.go:- Block production parks in
PrepareProposal. - After release it re-reaps the CometBFT mempool with CometBFT's own limits (CometBFT reaps before calling
PrepareProposal), so a block holds exactly the txs sent before/newBlock. /newBlockreturns from aPrepareCheckStatehook, i.e. after Commit, so the harness always reads committed state.
- Block production parks in
- Non-regtest builds gain an identity
PrepareProposalwrapper and a no-op hook (app/app_default.go). cmd/thornode/commands.go(all builds): server commands are registered withAddCommandsWithStartCmdOptionsso regtest can swap the start command. UnlikeAddCommands, that function does not registermodule-hash-by-height, so it's added explicitly. The default build's command list andstartflags are identical to develop.
Results (same host: 48 cores, PARALLELISM=8, TIME_FACTOR=2, all 184 suites)
| Wall time | |
|---|---|
develop (b18fd3bc57) |
569s (earlier runs on this host: 563–574s) |
| this branch | 183s, 205s, 207s (median 205s) |
About 64% less wall time, ~2.8x faster. The 205/207s runs overlapped another heavy job on the host.
In CI (test-regression job, small runners)
The build step depends on the cache, so the suite-run phase (make _test-regression) is the fair comparison.
| Pipeline | Runner | Suite run | Whole job |
|---|---|---|---|
develop 5c6c301d3e |
harry-small | ~513s | 746s |
develop b18fd3bc57 |
harry-small | ~540s | 595s |
| this MR (rebased, pipeline 2918302188) | hermonie-small | ~247s | 375s |
About 2.1x faster suite run in CI. That's one run of this branch against recent develop runs. Develop runs on the larger runners (hedwig, harry, Finland) took 1000–1400s per job.
Behavior unchanged
- Fixture diff. Unfiltered regtest exports and blocks (
EXPORT=1 UNFILTER_EXPORT=1), 2251 files includingapp_hash,last_results_hashandgas_used, are byte-identical to develop on all three runs. - Race check. 52 swap / observe / outbound / refund suites pass on a
-racenode build with no data race reports. - Committed fixtures. No fixture changes are needed.
Notes
- The harness still passes
THOR_TENDERMINT_CONSENSUS_TIMEOUT_COMMIT; the regtest start command now overrides it. It could be removed in a follow-up. - CI picks this up automatically:
cover-thornodeis built with theregtesttag.