fix(simulator): remove double-application of scaleFactor in targetCalls#183
Closed
meyer9 wants to merge 4 commits into
Closed
fix(simulator): remove double-application of scaleFactor in targetCalls#183meyer9 wants to merge 4 commits into
meyer9 wants to merge 4 commits into
Conversation
…empty blocks The sequencer was dispatching engine_forkchoiceUpdatedWithAttributes immediately after sendTxs, whose duration is proportional to tx workload. For heavy payloads (ecrecover at 150M gas), this left the FCU arriving with <75ms until block_timestamp, below flashblocks' leeway window, causing 'FCU arrived too late' and deposit-only empty blocks. Fix: sleep until the next whole-second Unix boundary before dispatching the FCU. block_timestamp is set to boundary+1s, so the builder always sees exactly ~1000ms of building time minus FCU RPC latency, regardless of sendTxs duration. The getBuiltPayload sleep is changed to sleep until boundary+1s rather than a fixed 1s, so total block period is unchanged. Tested before/after with ecrecover simulator payload at 150M gas, 20 blocks: Before: 1 empty block (block #11, 1 tx, deposit only) After: 0 empty blocks (all 20 blocks full at 352 txs)
…argetCalls
When scaleFactor > 1 (e.g. base-mainnet-simulation with avg_gas_used=35M and
GasLimit=200M gives scaleFactor≈5.71, targetCalls=572), the previous guard
if pendingTxs >= targetCalls { callsToSend = 0 }
allowed pendingTxs to accumulate past targetCalls after just 2 blocks (572 sent,
only ~50 included per block → pendingTxs grows to 1044 ≥ 572). From that point
callsToSend=0 forever and every subsequent block is empty (deposit-tx only).
The gate should use numCallsPerBlock (unscaled) since scaleFactor scales the
ops-per-tx, not the tx count threshold for backpressure. With numCallsPerBlock=100
as the gate, pending tx buildup is bounded to one block's worth and the simulator
continues generating txs regardless of scaleFactor.
scaleFactor is applied per-tx inside sendTxs at line 608: expected = payloadParams.Mul(numCalls+1 * scaleFactor) meaning each tx already does scaleFactor times the base operations. targetCalls was then computed as: numCallsPerBlock * scaleFactor which multiplied scaleFactor in again — resulting in 5.71x more txs being targeted than actually needed (e.g. 572 instead of 100 for base-mainnet-simulation with GasLimit=200M, avg_gas_used=35M). Since the builder only absorbs ~100 txs/block worth of those scaled ops, pendingTxs accumulated beyond targetCalls after 2 blocks, causing callsToSend=0 forever and 7,000+ consecutive empty (deposit-only) blocks in a 900-block run. Fix: targetCalls = numCallsPerBlock (the tx count, not the ops count). scaleFactor belongs only in the per-tx operation calculation.
Collaborator
🟡 Heimdall Review Status
|
Collaborator
Author
|
Replaced by cleaner branch — one commit, one file. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
scaleFactoris applied per-tx insidesendTxsto scale up the operations each transaction performs:So each tx already does
scaleFactor × payloadParamsoperations (e.g. withavg_gas_used=35MandGasLimit=200M,scaleFactor≈5.71, each tx does ~280 storage reads instead of 49).targetCallswas then computed as:This multiplies
scaleFactorin a second time at the tx-count level. The result: the simulator tries to keep 572 txs in flight per block, but the builder only absorbs ~100 (the actualnumCallsPerBlockworth of gas). After 2 blocks,pendingTxsgrows past 572 andcallsToSend=0forever — producing empty (deposit-only) blocks for the rest of the run.Observed: 7,000+ consecutive empty blocks in a 900-block
base-mainnet-simulationrun (GasLimit=200M,calls_per_block=100,avg_gas_used=35M).Fix
targetCallsshould benumCallsPerBlock— the number of txs to send per block.scaleFactorbelongs only inside the per-tx operation calculation.The
configForAllBlocksstorage pre-allocation at Setup (line 392) correctly usesnumCallsPerBlock × numBlocks × scaleFactor × 1.05— scaleFactor appears once there too, so no change needed.