Skip to content

Conversation

@niran
Copy link
Contributor

@niran niran commented Jan 12, 2026

Summary

Enable bundle metering to use the current pending flashblocks state instead of just the canonical block state. This ensures that bundle simulations see the same state that will be used when the bundle is actually included in a flashblock.

Changes

Metering Crate

  • meter.rs: Add FlashblocksState struct containing Cache and BundleState. Update meter_bundle to accept an optional FlashblocksState parameter. Implement three-layer database architecture: State<CacheDB<StateProviderDatabase>> where:
    • StateProviderDatabase reads from canonical chain state
    • CacheDB provides pending flashblock reads via the cache
    • State tracks bundle writes with flashblock prestate via with_bundle_prestate()
  • rpc.rs: Update MeteringApiImpl to integrate with flashblocks API. Get pending blocks state and pass it to meter_bundle. Include state_flashblock_index in response.
  • extension.rs: Update MeteringExtension to accept flashblocks configuration and cell.
  • lib.rs: Export FlashblocksState.

Flashblocks Crate

  • tests/state.rs: Add integration tests verifying that bundle metering correctly sees pending flashblock state changes.

Architecture

Bundle Metering Database Layers:

┌─────────────────────────────────┐
│  State (bundle tracking)        │  ← Tracks writes, includes flashblock prestate
├─────────────────────────────────┤
│  CacheDB (flashblock cache)     │  ← Provides pending reads from flashblocks
├─────────────────────────────────┤
│  StateProviderDatabase          │  ← Reads from canonical chain state
└─────────────────────────────────┘

Test Plan

  • Bundle metering correctly fails for nonce=1 tx without flashblock state (canonical nonce is 0)
  • Bundle metering succeeds for nonce=1 tx with flashblock state showing pending nonce=1
  • State visibility tests pass
  • cargo clippy passes

@niran niran force-pushed the niran/flashblocks-layering-fix branch from da51cc3 to 75e8eaf Compare January 12, 2026 20:03
@niran niran force-pushed the niran/meter-flashblocks-state-v2 branch from 994978c to 13ef63c Compare January 12, 2026 20:03
@danyalprout danyalprout added this to the v0.3.0 milestone Jan 12, 2026
@niran niran force-pushed the niran/meter-flashblocks-state-v2 branch from 13ef63c to 6817f24 Compare January 12, 2026 22:06
@niran niran force-pushed the niran/flashblocks-layering-fix branch from 75e8eaf to 0cba54d Compare January 13, 2026 00:58
@niran niran force-pushed the niran/meter-flashblocks-state-v2 branch from 6817f24 to 8dadef0 Compare January 13, 2026 00:58
Measure and report time spent calculating state root separately from
transaction execution, enabling better performance analysis:

- Add MeterBundleOutput struct with state_root_time_us field
- Calculate state root after transaction execution using merge_transitions
- Track state root calculation time separately from total execution time
- Update RPC to log state_root_time_us in metering response
- Add meter_bundle_state_root_time_invariant test

The state root is computed by calling hashed_post_state on the bundle
and then state_root_with_updates on the state provider.
@niran niran force-pushed the niran/flashblocks-layering-fix branch from 0cba54d to 8bca81f Compare January 13, 2026 01:22
@niran niran force-pushed the niran/meter-flashblocks-state-v2 branch from 8dadef0 to 724a0c9 Compare January 13, 2026 01:22
niran added 2 commits January 12, 2026 19:49
Fix the database layering in flashblocks processor to use State<CacheDB<...>>
instead of the incorrect CacheDB<State<...>>. The correct layering ensures
that State's bundle tracking captures all writes properly.

Key changes:
- Add bundle_state to PendingBlocks for tracking accumulated state changes
- Change processor to wrap CacheDB with State (not vice versa)
- Add with_bundle_prestate() to accumulate state across flashblocks
- Add layering verification tests
Add support for metering bundles against the current flashblocks pending
state instead of just the canonical block state. This ensures that bundle
simulations see the same state that will be used when the bundle is
actually included.

Key changes:
- Add FlashblocksState struct containing Cache and BundleState
- Update meter_bundle to accept optional FlashblocksState parameter
- Implement three-layer database architecture in metering
- Add integration tests for flashblock state visibility
@niran niran force-pushed the niran/meter-flashblocks-state-v2 branch from 724a0c9 to be1c7a5 Compare January 13, 2026 01:55
@niran niran force-pushed the niran/flashblocks-layering-fix branch from 8bca81f to 25c0260 Compare January 13, 2026 01:55
Comment on lines +50 to +59
let flashblocks_state = flashblocks_config.as_ref().map(|cfg| {
shared_state
.get_or_init(|| {
Arc::new(FlashblocksState::new(
ctx.provider().clone(),
cfg.max_pending_blocks_depth,
))
})
.clone()
});
Copy link
Collaborator

@danyalprout danyalprout Jan 13, 2026

Choose a reason for hiding this comment

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

I think the metering crate needing the FlashblocksConfig to init this feels like a design flaw in our node setup.

I would suggest we make the following change in main.rs

let fb_state = Arc::new(FlashblocksState::new())

install_ext::<Flashblocks>({ fb_state.clone() })
install_ext::<Metering>({ fb_state })

We should be able to just totally remove the oncecell setup and dependency. This was the symptom of a time where we had two tokio routines racing to initialize it, but I suspect we can get rid of it now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FlashblocksState needs a Client/Provider object, which we currently get from the context passed to extend_rpc_modules. Unless the builder provides a way to get a reference to something that will eventually give us a provider, we're kind of stuck. One option we still have is to move
the cell inside FlashblocksState, which should be able to give us your code snippet above. But it just moves the mess somewhere else, and probably adds more of it since FlashblocksState would be full of checks for an empty cell.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Gotcha, lets pair tomorrow morning, I have an idea

Base automatically changed from niran/flashblocks-layering-fix to main January 13, 2026 02:30
@cb-heimdall
Copy link
Collaborator

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

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.

4 participants