Skip to content

Commit

Permalink
feat(rpc): Setup RPC Crate (#35)
Browse files Browse the repository at this point in the history
### Description

Sets up an `rpc` crate.

### Metadata

#7
  • Loading branch information
refcell authored Oct 17, 2024
1 parent 1e5b6d6 commit a809286
Show file tree
Hide file tree
Showing 11 changed files with 433 additions and 225 deletions.
375 changes: 187 additions & 188 deletions Cargo.lock

Large diffs are not rendered by default.

54 changes: 30 additions & 24 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ ser = { path = "crates/ser" }
kona-providers-local = { path = "crates/providers-local" }

# Optimism
# superchain = { version = "0.7", default-features = false }
superchain = { git = "https://github.com/anton-rs/superchain", branch = "main", default-features = false }
kona-providers = { git = "https://github.com/anton-rs/kona", branch = "main", default-features = true }
kona-providers-alloy = { git = "https://github.com/anton-rs/kona", branch = "main", default-features = true }
Expand All @@ -60,23 +59,16 @@ alloy = { version = "0.4.2", features = [
"network",
"ssz"
] }
alloy-primitives = { version = "0.8", features = ["serde"] }
alloy-rlp = "0.3"
alloy-eips = { version = "0.4", default-features = false }

# Op-Alloy
# Op Alloy
op-alloy-consensus = { version = "0.4.0", default-features = false }
op-alloy-protocol = { version = "0.4.0", default-features = false }
op-alloy-genesis = { version = "0.4.0", default-features = false }
op-alloy-rpc-types = { version = "0.4.0", default-features = false }
op-alloy-rpc-types-engine = { version = "0.4.0", default-features = false }
op-alloy-rpc-jsonrpsee = { version = "0.4.0", features = ["client"] }

# Tokio
tokio = { version = "1.21", default-features = false }

# Serialization
serde_json = "1"
ethereum_ssz = "0.7.1"
op-alloy-rpc-jsonrpsee = { version = "0.4.0", default-features = false }

# Reth
reth = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }
Expand All @@ -93,32 +85,46 @@ reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }
reth-revm = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }
reth-evm = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }
reth-tracing = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }
reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }
reth-rpc-eth-types = { git = "https://github.com/paradigmxyz/reth", rev = "a846cbd" }

# Tokio
tokio = { version = "1.21", default-features = false }

# Serialization
serde_json = "1"
ethereum_ssz = "0.8.0"

# RPC
jsonrpsee = { version = "0.24", default-features = false }
jsonrpsee-types = "0.24"

# Networking
snap = "1.1.1"
discv5 = "0.6.0"
openssl = { version = "0.10.66", features = ["vendored"] }
libp2p-identity = { version = "0.2.9", features = [ "secp256k1" ] }
libp2p = { version = "0.54.0", features = ["macros", "tokio", "tcp", "noise", "gossipsub", "ping", "yamux"] }
discv5 = "0.8.0"
libp2p = "0.54.0"
openssl = "0.10.66"
libp2p-identity = "0.2.9"

# Testing
arbtest = "0.3"
arbitrary = { version = "1", features = ["derive"] }
arbitrary = "1"

# Misc
reqwest = "0.12.7"
tracing = "0.1.0"
tracing-subscriber = "0.3.18"
url = "2.5.2"
eyre = "0.6.12"
clap = { version = "4.5.4", features = ["derive", "env"] }
clap = "4.5.4"
reqwest = "0.12"
tracing = "0.1.40"
thiserror = "1.0"
lazy_static = "1.5.0"
futures = "0.3.30"
async-trait = "0.1.81"
hashbrown = "0.14.5"
async-trait = "0.1.83"
hashbrown = "0.15.0"
parking_lot = "0.12.3"
unsigned-varint = "0.8.0"
rand = { version = "0.8.5", features = ["small_rng", "alloc", "getrandom"], default-features = false }
url = "2.5.2"
tracing-subscriber = "0.3.18"
rand = { version = "0.8.5", default-features = false }

[workspace.metadata.docs.rs]
all-features = true
Expand Down
4 changes: 2 additions & 2 deletions bin/hera/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ superchain.workspace = true

# Workspace
eyre.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
tracing.workspace = true
clap.workspace = true
clap = { workspace = true, features = ["derive", "env"] }
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }

# Workspace Crates
op-net.workspace = true
2 changes: 1 addition & 1 deletion bin/op-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ rollup.workspace = true

# Workspace
eyre.workspace = true
clap.workspace = true
tracing.workspace = true
clap = { workspace = true, features = ["derive", "env"] }

# Reth Dependencies
reth.workspace = true
Expand Down
10 changes: 5 additions & 5 deletions crates/net/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ op-alloy-rpc-types-engine = { workspace = true, features = ["std"] }
snap.workspace = true
futures.workspace = true
discv5.workspace = true
libp2p.workspace = true
openssl.workspace = true
libp2p-identity.workspace = true
libp2p = { workspace = true, features = ["macros", "tokio", "tcp", "noise", "gossipsub", "ping", "yamux"] }
openssl = { workspace = true, features = ["vendored"] }
libp2p-identity = { workspace = true, features = [ "secp256k1" ] }

# Misc
eyre.workspace = true
Expand All @@ -32,11 +32,11 @@ lazy_static.workspace = true
unsigned-varint.workspace = true

# `arbitrary` feature dependencies
arbitrary = { workspace = true, optional = true }
arbitrary = { workspace = true, features = ["derive"], optional = true }

[dev-dependencies]
arbtest.workspace = true
arbitrary.workspace = true
arbitrary = { workspace = true, features = ["derive"] }
alloy = { workspace = true, features = ["arbitrary"] }

[features]
Expand Down
6 changes: 3 additions & 3 deletions crates/rollup/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ reth-execution-types.workspace = true

# Telemetry
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt"] }
metrics-exporter-prometheus = { version = "0.15.3", features = ["http-listener"] }
metrics-exporter-prometheus = { version = "0.16.0", features = ["http-listener"] }

# Misc
url.workspace = true
reqwest.workspace = true
serde_json.workspace = true
eyre.workspace = true
tracing.workspace = true
clap.workspace = true
async-trait.workspace = true
tokio.workspace = true
futures.workspace = true
alloy.workspace = true
hashbrown.workspace = true
clap = { workspace = true, features = ["derive", "env"] }
reqwest = { workspace = true, features = ["rustls-tls-native-roots"] }
39 changes: 39 additions & 0 deletions crates/rpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[package]
name = "op-rpc"
description = "Consensus RPC for Rollup Nodes"
version = "0.0.0"
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
keywords.workspace = true
categories.workspace = true

[dependencies]
# op-alloy
op-alloy-rpc-types.workspace = true
op-alloy-rpc-jsonrpsee = { workspace = true, features = ["client"] }

# Alloy
alloy-eips.workspace = true

# Misc
tracing.workspace = true
async-trait.workspace = true
jsonrpsee = { workspace = true, features = ["jsonrpsee-core", "client-core", "server-core", "macros"] }

# `reth` feature flag dependencies
alloy = { workspace = true, optional = true }
reqwest = { workspace = true, features = ["rustls-tls-native-roots"], optional = true }
thiserror = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }

[features]
default = ["reth"]
reth = [
"dep:alloy",
"dep:reqwest",
"dep:serde_json",
"dep:thiserror",
]
10 changes: 10 additions & 0 deletions crates/rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Consensus RPC for Rollup Nodes

#![doc(issue_tracker_base_url = "https://github.com/ithacaxyz/op-rs/issues/")]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]

pub mod rollup;

#[cfg(feature = "reth")]
pub mod sequencer;
48 changes: 48 additions & 0 deletions crates/rpc/src/rollup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Contains the RPC Definition

use alloy_eips::BlockNumberOrTag;
use async_trait::async_trait;
use jsonrpsee::core::RpcResult;
use op_alloy_rpc_jsonrpsee::traits::RollupNodeServer;
use op_alloy_rpc_types::{
config::RollupConfig, output::OutputResponse, safe_head::SafeHeadResponse, sync::SyncStatus,
};
use tracing::trace;

/// An implementation of the [`RollupNodeServer`] trait.
#[derive(Debug, Clone)]
pub struct RollupNodeRpc {
/// The version of the node.
version: String,
}

#[async_trait]
impl RollupNodeServer for RollupNodeRpc {
async fn op_output_at_block(
&self,
block_number: BlockNumberOrTag,
) -> RpcResult<OutputResponse> {
trace!("op_output_at_block: {:?}", block_number);
unimplemented!()
}

async fn op_safe_head_at_l1_block(
&self,
block_number: BlockNumberOrTag,
) -> RpcResult<SafeHeadResponse> {
trace!("op_safe_head_at_l1_block: {:?}", block_number);
unimplemented!()
}

async fn op_sync_status(&self) -> RpcResult<SyncStatus> {
unimplemented!()
}

async fn op_rollup_config(&self) -> RpcResult<RollupConfig> {
unimplemented!()
}

async fn op_version(&self) -> RpcResult<String> {
Ok(self.version.clone())
}
}
104 changes: 104 additions & 0 deletions crates/rpc/src/sequencer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! Optimism reth RPC Extension used to forward raw transactions to the sequencer.

use std::sync::{
atomic::{self, AtomicUsize},
Arc,
};

use alloy::primitives::hex;
use reqwest::Client;
use serde_json::json;
use tracing::warn;

/// Error type when interacting with the Sequencer
#[derive(Debug, thiserror::Error)]
pub enum SequencerClientError {
/// Wrapper around an [`reqwest::Error`].
#[error(transparent)]
HttpError(#[from] reqwest::Error),
/// Thrown when serializing transaction to forward to sequencer
#[error("invalid sequencer transaction")]
InvalidSequencerTransaction,
}

/// A client to interact with a Sequencer
#[derive(Debug, Clone)]
pub struct SequencerClient {
inner: Arc<SequencerClientInner>,
}

impl SequencerClient {
/// Creates a new [`SequencerClient`].
pub fn new(sequencer_endpoint: impl Into<String>) -> Self {
let client = Client::builder().use_rustls_tls().build().unwrap();
Self::with_client(sequencer_endpoint, client)
}

/// Creates a new [`SequencerClient`].
pub fn with_client(sequencer_endpoint: impl Into<String>, http_client: Client) -> Self {
let inner = SequencerClientInner {
sequencer_endpoint: sequencer_endpoint.into(),
http_client,
id: AtomicUsize::new(0),
};
Self { inner: Arc::new(inner) }
}

/// Returns the network of the client
pub fn endpoint(&self) -> &str {
&self.inner.sequencer_endpoint
}

/// Returns the client
pub fn http_client(&self) -> &Client {
&self.inner.http_client
}

/// Returns the next id for the request
fn next_request_id(&self) -> usize {
self.inner.id.fetch_add(1, atomic::Ordering::SeqCst)
}

/// Forwards a transaction to the sequencer endpoint.
pub async fn forward_raw_transaction(&self, tx: &[u8]) -> Result<(), SequencerClientError> {
let body = serde_json::to_string(&json!({
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [format!("0x{}", hex::encode(tx))],
"id": self.next_request_id()
}))
.map_err(|_| {
warn!(
target = "rpc::eth",
"Failed to serialize transaction for forwarding to sequencer"
);
SequencerClientError::InvalidSequencerTransaction
})?;

self.http_client()
.post(self.endpoint())
.header(reqwest::header::CONTENT_TYPE, "application/json")
.body(body)
.send()
.await
.inspect_err(|err| {
warn!(
target = "rpc::eth",
%err,
"Failed to forward transaction to sequencer",
);
})?;

Ok(())
}
}

#[derive(Debug, Default)]
struct SequencerClientInner {
/// The endpoint of the sequencer
sequencer_endpoint: String,
/// The HTTP client
http_client: Client,
/// Keeps track of unique request ids
id: AtomicUsize,
}
6 changes: 4 additions & 2 deletions crates/ser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ kona-derive.workspace = true

# Alloy
alloy-rlp = { workspace = true, features = ["derive"] }

# Op Alloy
op-alloy-rpc-types.workspace = true
op-alloy-protocol.workspace = true
op-alloy-genesis.workspace = true
op-alloy-rpc-jsonrpsee.workspace = true
op-alloy-rpc-jsonrpsee = { workspace = true, features = ["client"] }

# Misc
rand.workspace = true
eyre.workspace = true
tracing.workspace = true
rand = { workspace = true, features = ["small_rng", "alloc", "getrandom"] }

0 comments on commit a809286

Please sign in to comment.