Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: override eth_getProof to enable withdrawals #97

Merged
merged 12 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
8 changes: 8 additions & 0 deletions Cargo.lock

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

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ alloy-eips = "0.6.4"
alloy-network = "0.6.4"
alloy-primitives = "0.8.11"
alloy-rpc-types = "0.6.4"
alloy-rpc-types-eth = "0.6.4"
alloy-signer-local = { version = "0.6.4", features = ["mnemonic"] }

# tokio
Expand All @@ -158,6 +159,7 @@ tokio = { version = "1.21", default-features = false }
reth-chainspec = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-cli = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-cli-util = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-errors = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-evm = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-node-api = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
Expand Down Expand Up @@ -185,9 +187,12 @@ reth-provider = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aa
"optimism",
] }
reth-revm = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-rpc-types-compat = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-rpc-eth-types = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-storage-api = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-tracing = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-trie-common = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-trie-db = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-network = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
reth-network-types = { git = "https://github.com/paradigmxyz/reth.git", rev = "f211aac" }
Expand Down
11 changes: 10 additions & 1 deletion bin/odyssey/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ use alloy_primitives::Address;
use alloy_signer_local::PrivateKeySigner;
use clap::Parser;
use eyre::Context;
use odyssey_node::{chainspec::OdysseyChainSpecParser, node::OdysseyNode};
use odyssey_node::{
chainspec::OdysseyChainSpecParser,
node::OdysseyNode,
rpc::{EthApiExt, EthApiOverrideServer},
};
use odyssey_wallet::{OdysseyWallet, OdysseyWalletApiServer};
use odyssey_walltime::{OdysseyWallTime, OdysseyWallTimeRpcApiServer};
use reth_node_builder::{engine_tree_config::TreeConfig, EngineNodeLauncher};
Expand Down Expand Up @@ -56,6 +60,11 @@ fn main() {
.with_components(OdysseyNode::components(&rollup_args))
.with_add_ons(OpAddOns::new(rollup_args.sequencer_http))
.extend_rpc_modules(move |ctx| {
// override eth namespace
ctx.modules.replace_configured(
EthApiExt::new(ctx.registry.eth_api().clone()).into_rpc(),
)?;

// register odyssey wallet namespace
if let Ok(sk) = std::env::var("EXP1_SK") {
let signer: PrivateKeySigner =
Expand Down
9 changes: 9 additions & 0 deletions crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ revm-precompile.workspace = true
revm-primitives.workspace = true

reth-cli.workspace = true
reth-errors.workspace = true
reth-node-api.workspace = true
reth-node-builder.workspace = true
reth-optimism-node.workspace = true
Expand All @@ -25,18 +26,26 @@ reth-payload-builder.workspace = true
reth-primitives.workspace = true
reth-evm.workspace = true
reth-revm.workspace = true
reth-rpc-eth-api.workspace = true
reth-rpc-eth-types.workspace = true
reth-rpc-types-compat.workspace = true
reth-transaction-pool.workspace = true
reth-trie-common.workspace = true
reth-trie-db.workspace = true
reth-network.workspace = true
reth-network-types.workspace = true

alloy-consensus.workspace = true
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-rpc-types.workspace = true
alloy-rpc-types-eth.workspace = true


serde_json.workspace = true
tracing.workspace = true
eyre.workspace = true
jsonrpsee.workspace = true

[lints]
workspace = true
1 change: 1 addition & 0 deletions crates/node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
pub mod chainspec;
pub mod evm;
pub mod node;
pub mod rpc;
115 changes: 115 additions & 0 deletions crates/node/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//! Odyssey rpc logic.
//!
//! `eth_` namespace overrides:
//!
//! - `eth_getProof` will _ONLY_ return the storage proofs _WITHOUT_ an account proof _IF_ targeting
//! the withdrawal contract. Otherwise, it fallbacks to default behaviour.

use alloy_eips::BlockId;
use alloy_primitives::Address;
use alloy_rpc_types::serde_helpers::JsonStorageKey;
use alloy_rpc_types_eth::EIP1186AccountProofResponse;
use jsonrpsee::{
core::{async_trait, RpcResult},
proc_macros::rpc,
};
use reth_errors::RethError;
use reth_rpc_eth_api::{
helpers::{EthState, FullEthApi},
FromEthApiError,
};
use reth_rpc_eth_types::EthApiError;
use reth_rpc_types_compat::proof::from_primitive_account_proof;
use reth_trie_common::AccountProof;
use tracing::trace;

const WITHDRAWAL_CONTRACT: alloy_primitives::Address =
onbjerg marked this conversation as resolved.
Show resolved Hide resolved
alloy_primitives::address!("4200000000000000000000000000000000000011");

/// Odyssey `eth_` RPC namespace overrides.
#[cfg_attr(not(test), rpc(server, namespace = "eth"))]
#[cfg_attr(test, rpc(server, client, namespace = "eth"))]
pub trait EthApiOverride {
/// Returns the account and storage values of the specified account including the Merkle-proof.
/// This call can be used to verify that the data you are pulling from is not tampered with.
#[method(name = "getProof")]
async fn get_proof(
&self,
address: Address,
keys: Vec<JsonStorageKey>,
block_number: Option<BlockId>,
) -> RpcResult<EIP1186AccountProofResponse>;
}

/// Implementation of the `eth_` namespace override
#[derive(Debug)]
pub struct EthApiExt<Eth> {
eth_api: Eth,
}

impl<E> EthApiExt<E> {
/// Create a new `EthApiExt` module.
pub const fn new(eth_api: E) -> Self {
Self { eth_api }
}
}

#[async_trait]
impl<Eth> EthApiOverrideServer for EthApiExt<Eth>
where
Eth: FullEthApi + Send + Sync + 'static,
{
async fn get_proof(
&self,
address: Address,
keys: Vec<JsonStorageKey>,
block_number: Option<BlockId>,
) -> RpcResult<EIP1186AccountProofResponse> {
trace!(target: "rpc::eth", ?address, ?keys, ?block_number, "Serving eth_getProof");

// If we are targeting the withdrawal contract, then we only need to provide the storage
// proofs for withdrawal.
if address == WITHDRAWAL_CONTRACT {
Copy link
Member

Choose a reason for hiding this comment

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

is this something we want to bake into op-reth as well?

let _permit = self
.eth_api
.acquire_owned()
.await
.map_err(RethError::other)
.map_err(EthApiError::Internal)?;

return self
.eth_api
.spawn_blocking_io(move |this| {
let state = this.state_at_block_id(block_number.unwrap_or_default())?;
let storage_root = state
.storage_root(WITHDRAWAL_CONTRACT, Default::default())
.map_err(EthApiError::from_eth_err)?;
let storage_proofs = keys
.iter()
.map(|key| {
state.storage_proof(
WITHDRAWAL_CONTRACT,
key.as_b256(),
Default::default(),
)
})
.collect::<Result<Vec<_>, _>>()
.map_err(EthApiError::from_eth_err)?;
let proof = AccountProof {
address,
storage_root,
storage_proofs,
..Default::default()
};
Ok(from_primitive_account_proof(proof, keys))
})
.await
.map_err(Into::into);
}

EthState::get_proof(&self.eth_api, address, keys, block_number)
.map_err(Into::into)?
.await
.map_err(Into::into)
}
}