Skip to content

Add incremental trie cache optimization for flashblocks state root calculation#385

Open
cliff0412 wants to merge 7 commits intoflashbots:mainfrom
okx:feature/cliff/optimize-stateroot-calculation
Open

Add incremental trie cache optimization for flashblocks state root calculation#385
cliff0412 wants to merge 7 commits intoflashbots:mainfrom
okx:feature/cliff/optimize-stateroot-calculation

Conversation

@cliff0412
Copy link

@cliff0412 cliff0412 commented Feb 12, 2026

In this PR, we cache the trie nodes after each flashblock state root calculation. Therefore,
future flashblock state root calculation can be faster. resolving this issue #345

Full benchmark report:
benchmark_logs/TRIE_CACHE_BENCHMARK_REPORT.md

/// Enable incremental trie caching for state root calculation.
/// When enabled, subsequent flashblocks reuse trie nodes from previous flashblocks
/// for faster state root calculation (3-5x speedup expected).
#[arg(
Copy link
Collaborator

@SozinM SozinM Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO should not be configurable, if it's superior - have this as an only option.
Only one thing to consider - if this feature could produce incorrect state root

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tested that they produce same result. well, i can add a unit test for that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i just realized that

The existing test framework already validates state roots implicitly. Look at lines
225–233 in driver.rs:

  if self
      .engine_api
      .new_payload(payload.clone(), vec![], B256::ZERO, Requests::default())
      .await?
      .status
      != PayloadStatusEnum::Valid
  {
      return Err(eyre::eyre!("Invalid validation status from builder"));
  }

new_payload submits the built block to the EL, which re-executes the block and
verifies the state root independently. So, if the trie cached state root calculation method produce wrong state root. the payload validation will fail. i have checked all existing tests can pass with this trie cached approach; so i think is should be okay.

Copy link
Member

@julio4 julio4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good @cliff0412. As @SozinM said, this is pure optimization and I don't see scenarios where this should be disabled. You can remove the arg and simplify a bit build_block.
You can also add a few comments just to explain that trie updates are None in the first flashblock only.

@cliff0412 cliff0412 force-pushed the feature/cliff/optimize-stateroot-calculation branch from df54a8c to fa38fdf Compare February 25, 2026 02:53
@cliff0412
Copy link
Author

Looks very good @cliff0412. As @SozinM said, this is pure optimization and I don't see scenarios where this should be disabled. You can remove the arg and simplify a bit build_block. You can also add a few comments just to explain that trie updates are None in the first flashblock only.

config arg removed.

Apply trie updates to FlashblocksState via a local cache instead of
mutating through Option in the state-root block. Cache trie updates in
trie_updates_to_cache and set prev_trie_updates when consuming
fb_state later, so the signature can stay fb_state: Option<&mut FlashblocksState>
without requiring mut on the parameter.

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants