Skip to content

refactor: move salt bucket capacity lookup into revm::Database trait#188

Open
WonderLawrence wants to merge 7 commits intomainfrom
wanglang/refactor/megadatabase-trait-v2
Open

refactor: move salt bucket capacity lookup into revm::Database trait#188
WonderLawrence wants to merge 7 commits intomainfrom
wanglang/refactor/megadatabase-trait-v2

Conversation

@WonderLawrence
Copy link

@WonderLawrence WonderLawrence commented Mar 13, 2026

Summary

This PR refactors how SALT bucket capacity is queried during EVM execution for v1.4.1, removing the SaltEnv abstraction and integrating capacity lookup directly into the revm::Database trait via a new salt_bucket_capacity(address, Option<U256>) -> (usize, u64) method.

Problem

Previously, bucket capacity was provided through ExternalEnvTypes::SaltEnv — an external environment trait injected via ExternalEnvFactory. This required the factory to accept a block: BlockNumber parameter to return historically-correct capacity values. The design was overly complex and coupled gas calculation to an external oracle abstraction rather than the database layer.

Changes

  • Remove SaltEnv trait and ExternalEnvs::salt_env field: All SALT bucket capacity queries now go through db.salt_bucket_capacity(address, key) on the revm::Database trait (added in the upstream megaeth-labs/revm-database-interface fork)
  • DynamicGasCost is no longer generic: DynamicGasCost<SaltEnvImpl>DynamicGasCost; gas functions (sstore_set_gas, new_account_gas, create_contract_gas) now take db: &DB directly
  • ExternalEnvFactory::external_envs drops the block parameter: Block context for historical capacity resolution is now handled at the database level by the caller (e.g. StateProviderDatabase wrapping a HistoricalStateProviderRef)
  • TestDatabaseWrapper introduced: Replaces TestExternalEnvs::with_bucket_capacity for test setups; wraps any revm::Database and provides configurable per-bucket capacity overrides

Motivation

The revm::Database is already the single source of truth for all state during execution. Routing capacity queries through it allows historical replay correctness to be handled entirely at the storage layer (see megaeth-labs/mega-reth#1489), without requiring the EVM execution layer to know about block numbers or provider types.

@WonderLawrence WonderLawrence force-pushed the wanglang/refactor/megadatabase-trait-v2 branch from fd83d28 to b85bede Compare March 14, 2026 16:54
@WonderLawrence WonderLawrence changed the title Wanglang/refactor/megadatabase trait v2 refactor: move salt bucket capacity lookup into revm::Database trait Mar 15, 2026
@WonderLawrence WonderLawrence changed the base branch from main to release/v1.4.1 March 15, 2026 06:16
@WonderLawrence WonderLawrence changed the base branch from release/v1.4.1 to main March 15, 2026 06:20
@WonderLawrence WonderLawrence force-pushed the wanglang/refactor/megadatabase-trait-v2 branch from b85bede to 6b530c3 Compare March 15, 2026 06:58
@WonderLawrence WonderLawrence force-pushed the wanglang/refactor/megadatabase-trait-v2 branch from 6b530c3 to 96092a6 Compare March 15, 2026 07:02
@nnsgmsone nnsgmsone self-requested a review March 17, 2026 08:13
@RealiCZ
Copy link
Contributor

RealiCZ commented Mar 17, 2026

Concern: forking revm-database-interface to add salt_bucket_capacity to revm::Database

This forks two upstream crates (revm-database-interface and revm-database) to add a MegaETH-specific method onto a core upstream trait. Costs:

  • Two forks to maintain on every revm upgrade
  • Every Database implementor must add this method, even when unrelated to SALT (e.g. StateWitnessRecorderDatabase in mega-reth resorts to unimplemented!())
  • The default impl is a panic, unlike every other Database method
  • &self receiver is inconsistent with the other four &mut self methods

Consider defining a separate trait (e.g. in megaeth-salt or a shared crate) and adding it as an additional bound where needed, rather than modifying the upstream Database trait.

/// The parent block number.
parent_block: BlockNumber,
/// The external environment for SALT bucket information.
salt_env: SaltEnvImpl,
Copy link

Choose a reason for hiding this comment

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

Would it make sense to store db as a member variable, rather than passing a reference on every interface call?

Copy link
Author

Choose a reason for hiding this comment

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

Since mega-evm can only see the Database type passed from the upper layer, and this type does not implement the Clone Trait, this implementation requires that the same db instance be stored in at least two places. Therefore, there is a conflict here.

@WonderLawrence
Copy link
Author

WonderLawrence commented Mar 18, 2026

Concern: forking revm-database-interface to add salt_bucket_capacity to revm::Database

This forks two upstream crates (revm-database-interface and revm-database) to add a MegaETH-specific method onto a core upstream trait. Costs:

  • Two forks to maintain on every revm upgrade
  • Every Database implementor must add this method, even when unrelated to SALT (e.g. StateWitnessRecorderDatabase in mega-reth resorts to unimplemented!())
  • The default impl is a panic, unlike every other Database method
  • &self receiver is inconsistent with the other four &mut self methods

Consider defining a separate trait (e.g. in megaeth-salt or a shared crate) and adding it as an additional bound where needed, rather than modifying the upstream Database trait.

I have also tried the suggested approach, such as introducing a separate Bucket Trait for salt_bucket_capacity without modifying the Database Trait itself—this is essentially the most ideal change.
The problem is that our current code has many places, especially the create_evm method in impl alloy_evm::EvmFactory for MegaEvmFactory, (

fn create_evm<DB: Database>(
) whose generic parameters depend on the Database type. If we change it as described above, compilation here will fail because adding the Bucket Trait on top of Database would narrow the types of generic parameters accepted by the create_evm method in EvmFactory.
If we further modify create_evm, the mega-reth layer would require more adaptation work for such changes. Therefore, if we introduce a new Bucket Trait, considering the numerous places where Database is depended upon, this could be a very broad change across the codebase.

Copy link

@DevinByte DevinByte left a comment

Choose a reason for hiding this comment

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

Forking upstream revm::Database to add a MegaETH-specific method is a high-cost trade-off. Adding salt_bucket_capacity to the core Database trait forces every Database implementor (including MemoryDatabase, SandboxDb, ErrorInjectingDatabase, and any future ones) to implement a MegaETH-specific concern, even when SALT is irrelevant to them. It also increases the ongoing maintenance burden of syncing with upstream revm. A local extension trait (trait DatabaseExt: Database { fn salt_bucket_capacity(...) }) would achieve the same goal without polluting the upstream interface.

I’m not sure what problem this is addressing or why the change is necessary. This should be discussed further.

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