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 via REGTEST_TIMEOUT_COMMIT;
    • an effectively infinite timeout_propose, so a parked proposal never times out into a new round.
  • 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.
    • /newBlock returns from a PrepareCheckState hook, i.e. after Commit, so the harness always reads committed state.
  • Non-regtest builds gain an identity PrepareProposal wrapper and a no-op hook (app/app_default.go).
  • cmd/thornode/commands.go (all builds): server commands are registered with AddCommandsWithStartCmdOptions so regtest can swap the start command. Unlike AddCommands, that function does not register module-hash-by-height, so it's added explicitly. The default build's command list and start flags 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 including app_hash, last_results_hash and gas_used, are byte-identical to develop on all three runs.
  • Race check. 52 swap / observe / outbound / refund suites pass on a -race node 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-thornode is built with the regtest tag.

🤖 Generated with Claude Code

Edited by Son of Odin

Merge request reports

Loading
Loading