Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions bin/host/src/interop/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use maili_protocol::BlockInfo;
use maili_registry::ROLLUP_CONFIGS;
use std::sync::Arc;
use tokio::task;
use tracing::warn;

/// The [HintHandler] for the [InteropHost].
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -531,6 +532,12 @@ impl HintHandler for InteropHintHandler {
// Store tx root preimages.
store_ordered_trie(kv.as_ref(), raw_transactions.as_slice()).await?;
}
HintType::L2PayloadWitness => {
warn!(
target: "interop_hint_handler",
"L2PayloadWitness hint not implemented for interop hint handler, ignoring hint"
);
}
}

Ok(())
Expand Down
3 changes: 2 additions & 1 deletion bin/host/src/single/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ impl SingleChainHost {
kv_store.clone(),
providers,
SingleChainHintHandler,
);
)
.with_proactive_hint(HintType::L2PayloadWitness);

task::spawn(
PreimageServer::new(
Expand Down
15 changes: 13 additions & 2 deletions bin/host/src/single/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use maili_protocol::BlockInfo;
use op_alloy_rpc_types_engine::OpPayloadAttributes;
use std::collections::HashMap;
use tracing::warn;

/// The [HintHandler] for the [SingleChainHost].
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -258,6 +259,12 @@

let hash: B256 = hint.data.as_ref().try_into()?;

warn!(target: "single_hint_handler", "L2StateNode hint was sent for node hash: {}", hash);
warn!(

Check warning on line 263 in bin/host/src/single/handler.rs

View check run for this annotation

Codecov / codecov/patch

bin/host/src/single/handler.rs#L262-L263

Added lines #L262 - L263 were not covered by tests
target: "single_hint_handler",
"`debug_executePayload` failed to return a complete witness."

Check warning on line 265 in bin/host/src/single/handler.rs

View check run for this annotation

Codecov / codecov/patch

bin/host/src/single/handler.rs#L265

Added line #L265 was not covered by tests
);

// Fetch the preimage from the L2 chain provider.
let preimage: Bytes = providers.l2.client().request("debug_dbGet", &[hash]).await?;

Expand Down Expand Up @@ -324,15 +331,19 @@
let payload_attributes: OpPayloadAttributes =
serde_json::from_slice(&hint.data[32..])?;

let execute_payload_response: ExecutionWitness = providers
let Ok(execute_payload_response) = providers
.l2
.client()
.request::<(B256, OpPayloadAttributes), ExecutionWitness>(
"debug_executePayload",
(parent_block_hash, payload_attributes),
)
.await
.map_err(|e| anyhow!("Failed to fetch preimage: {e}"))?;
else {
// Allow this hint to fail silently, as not all execution clients support
// the `debug_executePayload` method.
return Ok(());
};

let mut merged = HashMap::<B256, Bytes>::default();
merged.extend(execute_payload_response.state);
Expand Down
4 changes: 2 additions & 2 deletions crates/proof/executor/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ where
/// The parent block hash of the current block.
parent_block_header: Sealed<Header>,
/// The [TrieDBProvider]
fetcher: F,
pub fetcher: F,
/// The [TrieHinter]
hinter: H,
pub hinter: H,
}

impl<F, H> TrieDB<F, H>
Expand Down
11 changes: 10 additions & 1 deletion crates/proof/executor/src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
},
ExecutorError, ExecutorResult, TrieDBProvider,
};
use alloc::vec::Vec;
use alloc::{string::ToString, vec::Vec};
use alloy_consensus::{
Header, Sealable, Sealed, Transaction, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH,
};
Expand Down Expand Up @@ -137,6 +137,15 @@ where

let parent_block_hash: B256 = self.trie_db.parent_block_header().seal();

// Attempt to send a payload witness hint to the host. This hint instructs the host to
// populate its preimage store with the preimages required to statelessly execute
// this payload. This feature is experimental, so if the hint fails, we continue
// without it and fall back on on-demand preimage fetching for execution.
self.trie_db
.hinter
.hint_execution_witness(parent_block_hash, &payload)
.map_err(|e| TrieDBError::Provider(e.to_string()))?;

let mut state =
State::builder().with_database(&mut self.trie_db).with_bundle_update().build();

Expand Down
3 changes: 3 additions & 0 deletions crates/proof/mpt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ alloy-rlp.workspace = true
alloy-trie.workspace = true
alloy-primitives = { workspace = true, features = ["rlp"] }

# Op-alloy
op-alloy-rpc-types-engine.workspace = true

[dev-dependencies]
# Alloy
alloy-provider = { workspace = true, features = ["reqwest"] }
Expand Down
8 changes: 8 additions & 0 deletions crates/proof/mpt/src/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@
) -> Result<(), Self::Error> {
Ok(())
}

fn hint_execution_witness(
&self,
_parent_hash: B256,
_op_payload_attributes: &op_alloy_rpc_types_engine::OpPayloadAttributes,
) -> Result<(), Self::Error> {
Ok(())
}

Check warning on line 50 in crates/proof/mpt/src/noop.rs

View check run for this annotation

Codecov / codecov/patch

crates/proof/mpt/src/noop.rs#L44-L50

Added lines #L44 - L50 were not covered by tests
}
17 changes: 17 additions & 0 deletions crates/proof/mpt/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::TrieNode;
use alloc::string::ToString;
use alloy_primitives::{Address, B256, U256};
use core::fmt::Display;
use op_alloy_rpc_types_engine::OpPayloadAttributes;

/// The [TrieProvider] trait defines the synchronous interface for fetching trie node preimages.
pub trait TrieProvider {
Expand Down Expand Up @@ -65,4 +66,20 @@ pub trait TrieHinter {
slot: U256,
block_number: u64,
) -> Result<(), Self::Error>;

/// Hints the host to fetch the execution witness for the [OpPayloadAttributes] applied on top
/// of the parent block's state.
///
/// ## Takes
/// - `parent_hash` - The hash of the parent block.
/// - `op_payload_attributes` - The attributes of the operation payload.
///
/// ## Returns
/// - Ok(()): If the hint was successful.
/// - Err(Self::Error): If the hint was unsuccessful.
fn hint_execution_witness(
&self,
parent_hash: B256,
op_payload_attributes: &OpPayloadAttributes,
) -> Result<(), Self::Error>;
}
5 changes: 5 additions & 0 deletions crates/proof/proof-interop/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
L2AccountStorageProof,
/// A hint that specifies loading the payload witness for an optimistic block.
L2BlockData,
/// A hint that specifies bulk storage of all the code, state and keys generated by an
/// execution witness.
L2PayloadWitness,
}

impl HintType {
Expand Down Expand Up @@ -74,6 +77,7 @@
"l2-account-proof" => Ok(Self::L2AccountProof),
"l2-account-storage-proof" => Ok(Self::L2AccountStorageProof),
"l2-block-data" => Ok(Self::L2BlockData),
"l2-payload-witness" => Ok(Self::L2PayloadWitness),

Check warning on line 80 in crates/proof/proof-interop/src/hint.rs

View check run for this annotation

Codecov / codecov/patch

crates/proof/proof-interop/src/hint.rs#L80

Added line #L80 was not covered by tests
_ => Err(HintParsingError(value.to_string())),
}
}
Expand All @@ -97,6 +101,7 @@
HintType::L2AccountProof => "l2-account-proof",
HintType::L2AccountStorageProof => "l2-account-storage-proof",
HintType::L2BlockData => "l2-block-data",
HintType::L2PayloadWitness => "l2-payload-witness",

Check warning on line 104 in crates/proof/proof-interop/src/hint.rs

View check run for this annotation

Codecov / codecov/patch

crates/proof/proof-interop/src/hint.rs#L104

Added line #L104 was not covered by tests
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions crates/proof/proof/src/l2/chain_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,21 @@ impl<T: CommsClient> TrieHinter for OracleL2ChainProvider<T> {
.await
})
}

fn hint_execution_witness(
&self,
parent_hash: B256,
op_payload_attributes: &op_alloy_rpc_types_engine::OpPayloadAttributes,
) -> Result<(), Self::Error> {
crate::block_on(async move {
let encoded_attributes =
serde_json::to_vec(op_payload_attributes).map_err(OracleProviderError::Serde)?;

HintType::L2PayloadWitness
.with_data(&[parent_hash.as_slice(), &encoded_attributes])
.with_data(self.chain_id.map_or_else(Vec::new, |id| id.to_be_bytes().to_vec()))
.send(self.oracle.as_ref())
.await
})
}
}
Loading