diff --git a/cmd/utils/app/import_cmd.go b/cmd/utils/app/import_cmd.go index 78bb0fef479..67905370c72 100644 --- a/cmd/utils/app/import_cmd.go +++ b/cmd/utils/app/import_cmd.go @@ -417,7 +417,9 @@ func InsertChain(ethereum *eth.Ethereum, chain *blockgen.ChainPack, setHead bool } // UpdateForkChoice has an async commit so we need to wait to make sure - // it is completed before assuming all state changes etc are inserted + // it is completed before assuming all state changes etc are inserted. + // State-change events are dispatched pre-commit, so waiting on the stream + // only ensures the dispatcher fired — not that MDBX is flushed. var lastSeenBlock uint64 for len(insertedBlocks) > 0 { req, err := stream.Recv() @@ -445,6 +447,10 @@ func InsertChain(ethereum *eth.Ethereum, chain *blockgen.ChainPack, setHead bool } } + // Wait for the FCU background commit so HeadBlockHash can't land in MDBX + // ahead of the header it points to. + ethereum.ExecutionModule().WaitIdle(ethereum.SentryCtx()) + return ethereum.ChainDB().Update(ethereum.SentryCtx(), func(tx kv.RwTx) error { rawdb.WriteHeadBlockHash(tx, lvh) return nil diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 54a35192174..2a38acb36a1 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1143,7 +1143,7 @@ var ( } FcuBackgroundCommitFlag = cli.BoolFlag{ Name: "fcu.background.commit", - Usage: "Enables background flush and commit", + Usage: "Return FCU response before MDBX flush+commit lands (commit runs in background; remote rpcdaemon 'latest' stays consistent but can lag for the commit duration)", Value: ethconfig.Defaults.FcuBackgroundCommit, } MCPDisableFlag = cli.BoolFlag{ diff --git a/docs/site/docs/fundamentals/configuring-erigon.mdx b/docs/site/docs/fundamentals/configuring-erigon.mdx index d12064c9808..5544f7b456b 100644 --- a/docs/site/docs/fundamentals/configuring-erigon.mdx +++ b/docs/site/docs/fundamentals/configuring-erigon.mdx @@ -417,7 +417,7 @@ Flags for configuring Fork Choice Update behavior. * Default: `1s` * `--fcu.background.prune`: Enables background pruning after FCU. * Default: `true` -* `--fcu.background.commit`: Enables background flush and commit after FCU. +* `--fcu.background.commit`: Returns the FCU response before MDBX flush+commit lands (commit runs in background; remote `rpcdaemon` `latest` stays consistent but can lag for the commit duration). * Default: `false` ### Execution diff --git a/docs/site/static/llms-full.txt b/docs/site/static/llms-full.txt index 9812bf8eec5..71bddd9c0bc 100644 --- a/docs/site/static/llms-full.txt +++ b/docs/site/static/llms-full.txt @@ -2319,7 +2319,7 @@ Flags for configuring Fork Choice Update behavior. * Default: `1s` * `--fcu.background.prune`: Enables background pruning after FCU. * Default: `true` -* `--fcu.background.commit`: Enables background flush and commit after FCU. +* `--fcu.background.commit`: Returns the FCU response before MDBX flush+commit lands (commit runs in background; remote `rpcdaemon` `latest` stays consistent but can lag for the commit duration). * Default: `false` ### Execution diff --git a/execution/engineapi/engine_block_downloader/block_downloader.go b/execution/engineapi/engine_block_downloader/block_downloader.go index 386bf9c589a..8cfbaa00d46 100644 --- a/execution/engineapi/engine_block_downloader/block_downloader.go +++ b/execution/engineapi/engine_block_downloader/block_downloader.go @@ -271,8 +271,31 @@ func (e *EngineBlockDownloader) downloadBlocks(ctx context.Context, req Backward return nil } +// retryBusy re-invokes call while it reports ExecutionStatusBusy (a background +// FCU commit briefly holds the exec semaphore), polling every 50ms and logging +// periodically so a stuck commit surfaces instead of hanging silently. +func (e *EngineBlockDownloader) retryBusy(ctx context.Context, label string, call func() (execmodule.ExecutionStatus, *string, common.Hash, error)) (execmodule.ExecutionStatus, *string, common.Hash, error) { + status, validationErr, lastValidHash, err := call() + logEvery := time.NewTicker(5 * time.Second) + defer logEvery.Stop() + for err == nil && status == execmodule.ExecutionStatusBusy { + if err := common.Sleep(ctx, 50*time.Millisecond); err != nil { + return status, validationErr, lastValidHash, err + } + select { + case <-logEvery.C: + e.logger.Debug("[EngineBlockDownloader] execution busy - retrying", "label", label) + default: + } + status, validationErr, lastValidHash, err = call() + } + return status, validationErr, lastValidHash, err +} + func (e *EngineBlockDownloader) execDownloadedBatch(ctx context.Context, block *types.Block, requested common.Hash) error { - status, validationErr, lastValidHash, err := e.chainRW.ValidateChain(ctx, block.Hash(), block.NumberU64()) + status, validationErr, lastValidHash, err := e.retryBusy(ctx, "ValidateChain", func() (execmodule.ExecutionStatus, *string, common.Hash, error) { + return e.chainRW.ValidateChain(ctx, block.Hash(), block.NumberU64()) + }) if err != nil { return err } @@ -297,7 +320,9 @@ func (e *EngineBlockDownloader) execDownloadedBatch(ctx context.Context, block * lastValidHash, ) } - fcuStatus, _, lastValidHash, err := e.chainRW.UpdateForkChoice(ctx, block.Hash(), common.Hash{}, common.Hash{}, 0) + fcuStatus, _, lastValidHash, err := e.retryBusy(ctx, "UpdateForkChoice", func() (execmodule.ExecutionStatus, *string, common.Hash, error) { + return e.chainRW.UpdateForkChoice(ctx, block.Hash(), common.Hash{}, common.Hash{}, 0) + }) if err != nil { return err } diff --git a/llms-full.txt b/llms-full.txt index 9812bf8eec5..71bddd9c0bc 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -2319,7 +2319,7 @@ Flags for configuring Fork Choice Update behavior. * Default: `1s` * `--fcu.background.prune`: Enables background pruning after FCU. * Default: `true` -* `--fcu.background.commit`: Enables background flush and commit after FCU. +* `--fcu.background.commit`: Returns the FCU response before MDBX flush+commit lands (commit runs in background; remote `rpcdaemon` `latest` stays consistent but can lag for the commit duration). * Default: `false` ### Execution diff --git a/node/ethconfig/config.go b/node/ethconfig/config.go index 6c795df23a5..78db4d8dd96 100644 --- a/node/ethconfig/config.go +++ b/node/ethconfig/config.go @@ -111,9 +111,13 @@ var Defaults = Config{ ProduceE2: true, ProduceE3: true, }, - FcuTimeout: 1 * time.Second, - FcuBackgroundPrune: true, - FcuBackgroundCommit: false, // to enable, we need to 1) have rawdb API go via execctx and 2) revive Coherent cache for rpcdaemon + FcuTimeout: 1 * time.Second, + FcuBackgroundPrune: true, + // FcuBackgroundCommit returns the FCU response before the MDBX commit + // lands; the commit runs in a background goroutine and successive FCUs are + // serialized by the ExecModule semaphore. "Latest" state reads can lag the + // announced head by one block for the commit's duration. + FcuBackgroundCommit: false, ExperimentalBAL: false, WarmupKzgCtxOnInit: true, }