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

feat(ethexe): dev mode, set blob via rpc #4458

Merged
merged 4 commits into from
Jan 23, 2025
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.

10 changes: 8 additions & 2 deletions ethexe/cli/src/params/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ pub struct EthereumParams {
#[arg(long, alias = "eth-router")]
#[serde(rename = "router")]
pub ethereum_router: Option<String>,

/// Ethereum block time in seconds.
#[arg(long, alias = "eth-block-time")]
#[serde(rename = "block-time")]
pub block_time: Option<u64>,
}

impl EthereumParams {
/// Default block time in seconds.
pub const BLOCK_TIME: usize = 12;
pub const BLOCK_TIME: u64 = 12;

/// Default Ethereum RPC.
pub const DEFAULT_ETHEREUM_RPC: &str = "http://localhost:8545";
Expand All @@ -67,7 +72,7 @@ impl EthereumParams {
.ok_or_else(|| anyhow!("missing `ethereum-router`"))?
.parse()
.with_context(|| "invalid `ethereum-router`")?,
block_time: Duration::from_secs(Self::BLOCK_TIME as u64),
block_time: Duration::from_secs(self.block_time.unwrap_or(Self::BLOCK_TIME)),
})
}
}
Expand All @@ -78,6 +83,7 @@ impl MergeParams for EthereumParams {
ethereum_rpc: self.ethereum_rpc.or(with.ethereum_rpc),
ethereum_beacon_rpc: self.ethereum_beacon_rpc.or(with.ethereum_beacon_rpc),
ethereum_router: self.ethereum_router.or(with.ethereum_router),
block_time: self.block_time.or(with.block_time),
}
}
}
3 changes: 2 additions & 1 deletion ethexe/cli/src/params/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl Params {
pub fn into_config(self) -> Result<Config> {
let node = self.node.ok_or_else(|| anyhow!("missing node params"))?;
let net_dir = node.net_dir();
let dev = node.dev;

let ethereum = self
.ethereum
Expand All @@ -88,7 +89,7 @@ impl Params {
.network
.and_then(|p| p.into_config(net_dir).transpose())
.transpose()?,
rpc: self.rpc.and_then(|p| p.into_config()),
rpc: self.rpc.and_then(|p| p.into_config(dev)),
prometheus: self.prometheus.and_then(|p| p.into_config()),
})
}
Expand Down
10 changes: 8 additions & 2 deletions ethexe/cli/src/params/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ pub struct NodeParams {
#[serde(default)]
pub tmp: bool,

/// Flag to run node in development mode.
#[arg(long)]
#[serde(default)]
pub dev: bool,

/// Public key of the sequencer, if node should act as one.
#[arg(long)]
pub sequencer: Option<String>,
Expand Down Expand Up @@ -87,12 +92,13 @@ impl NodeParams {
.virtual_threads
.unwrap_or(Self::DEFAULT_VIRTUAL_THREADS)
.get() as usize,
dev: self.dev,
})
}

/// Get path to the database directory.
pub fn db_dir(&self) -> PathBuf {
if self.tmp {
if self.tmp || self.dev {
Self::tmp_db()
} else {
self.base().join("db")
Expand Down Expand Up @@ -144,7 +150,7 @@ impl MergeParams for NodeParams {
Self {
base: self.base.or(with.base),
tmp: self.tmp || with.tmp,

dev: self.dev || with.dev,
sequencer: self.sequencer.or(with.sequencer),
validator: self.validator.or(with.validator),

Expand Down
8 changes: 6 additions & 2 deletions ethexe/cli/src/params/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl RpcParams {
pub const DEFAULT_RPC_PORT: u16 = 9944;

/// Convert self into a proper `RpcConfig` object, if RPC service is enabled.
pub fn into_config(self) -> Option<RpcConfig> {
pub fn into_config(self, dev: bool) -> Option<RpcConfig> {
if self.no_rpc {
return None;
}
Expand Down Expand Up @@ -83,7 +83,11 @@ impl RpcParams {
})
.into();

Some(RpcConfig { listen_addr, cors })
Some(RpcConfig {
listen_addr,
cors,
dev,
})
}
}

Expand Down
1 change: 1 addition & 0 deletions ethexe/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ ethexe-runtime-common = { workspace = true, features = ["std"] }
sp-core = { workspace = true, features = ["serde"] }
gear-core = { workspace = true, features = ["std"] }
serde = { workspace = true, features = ["std"] }
ethexe-observer.workspace = true
57 changes: 57 additions & 0 deletions ethexe/rpc/src/apis/dev.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// This file is part of Gear.
//
// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use std::sync::Arc;

use ethexe_observer::MockBlobReader;
use gear_core::ids::prelude::CodeIdExt;
use gprimitives::{CodeId, H256};
use jsonrpsee::{
core::{async_trait, RpcResult},
proc_macros::rpc,
};
use sp_core::Bytes;

#[rpc(server)]
pub trait Dev {
#[method(name = "dev_setBlob")]
async fn set_blob(&self, blob: Bytes) -> RpcResult<(H256, CodeId)>;
}

#[derive(Clone)]
pub struct DevApi {
blob_reader: Arc<MockBlobReader>,
}

impl DevApi {
pub fn new(blob_reader: Arc<MockBlobReader>) -> Self {
Self { blob_reader }
}
}

#[async_trait]
impl DevServer for DevApi {
async fn set_blob(&self, blob: Bytes) -> RpcResult<(H256, CodeId)> {
let code_id = CodeId::generate(&blob);
let blob_tx = H256::random();

self.blob_reader.add_blob_transaction(blob_tx, blob.0).await;

Ok((blob_tx, code_id))
}
}
2 changes: 2 additions & 0 deletions ethexe/rpc/src/apis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

mod block;
mod dev;
mod program;

pub use block::{BlockApi, BlockServer};
pub use dev::{DevApi, DevServer};
pub use program::{ProgramApi, ProgramServer};
22 changes: 18 additions & 4 deletions ethexe/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use anyhow::{anyhow, Result};
use apis::{BlockApi, BlockServer, ProgramApi, ProgramServer};
use apis::{BlockApi, BlockServer, DevApi, DevServer, ProgramApi, ProgramServer};
use ethexe_db::Database;
use ethexe_observer::MockBlobReader;
use futures::FutureExt;
use jsonrpsee::{
server::{
Expand All @@ -27,7 +28,7 @@ use jsonrpsee::{
},
Methods, RpcModule as JsonrpcModule,
};
use std::net::SocketAddr;
use std::{net::SocketAddr, sync::Arc};
use tokio::net::TcpListener;
use tower::Service;

Expand All @@ -51,16 +52,23 @@ pub struct RpcConfig {
pub listen_addr: SocketAddr,
/// CORS.
pub cors: Option<Vec<String>>,
/// Dev mode.
pub dev: bool,
}

pub struct RpcService {
config: RpcConfig,
db: Database,
blob_reader: Option<Arc<MockBlobReader>>,
}

impl RpcService {
pub fn new(config: RpcConfig, db: Database) -> Self {
Self { config, db }
pub fn new(config: RpcConfig, db: Database, blob_reader: Option<Arc<MockBlobReader>>) -> Self {
Self {
config,
db,
blob_reader,
}
}

pub const fn port(&self) -> u16 {
Expand All @@ -82,6 +90,12 @@ impl RpcService {
module.merge(ProgramServer::into_rpc(ProgramApi::new(self.db.clone())))?;
module.merge(BlockServer::into_rpc(BlockApi::new(self.db.clone())))?;

if self.config.dev {
module.merge(DevServer::into_rpc(DevApi::new(
self.blob_reader.unwrap().clone(),
)))?;
}

let (stop_handle, server_handle) = stop_channel();

let cfg = PerConnection {
Expand Down
1 change: 1 addition & 0 deletions ethexe/service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub struct NodeConfig {
pub max_commitment_depth: u32,
pub worker_threads_override: Option<usize>,
pub virtual_threads: usize,
pub dev: bool,
}

#[derive(Debug)]
Expand Down
35 changes: 22 additions & 13 deletions ethexe/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use ethexe_common::{
use ethexe_db::{BlockMetaStorage, CodesStorage, Database};
use ethexe_ethereum::{primitives::U256, router::RouterQuery};
use ethexe_network::{db_sync, NetworkReceiverEvent};
use ethexe_observer::{RequestBlockData, RequestEvent};
use ethexe_observer::{MockBlobReader, RequestBlockData, RequestEvent};
use ethexe_processor::{LocalOutcome, ProcessorConfig};
use ethexe_prometheus::MetricsService;
use ethexe_sequencer::agro::AggregatedCommitments;
Expand Down Expand Up @@ -84,15 +84,25 @@ pub enum NetworkMessage {

impl Service {
pub async fn new(config: &Config) -> Result<Self> {
let blob_reader = Arc::new(
ethexe_observer::ConsensusLayerBlobReader::new(
&config.ethereum.rpc,
&config.ethereum.beacon_rpc,
config.ethereum.block_time,
let mock_blob_reader: Option<Arc<MockBlobReader>> = if config.node.dev {
Some(Arc::new(MockBlobReader::new(config.ethereum.block_time)))
} else {
None
};

let blob_reader: Arc<dyn ethexe_observer::BlobReader> = if config.node.dev {
mock_blob_reader.clone().unwrap()
} else {
Arc::new(
ethexe_observer::ConsensusLayerBlobReader::new(
&config.ethereum.rpc,
&config.ethereum.beacon_rpc,
config.ethereum.block_time,
)
.await
.with_context(|| "failed to create blob reader")?,
)
.await
.with_context(|| "failed to create blob reader")?,
);
};

let rocks_db = ethexe_db::RocksDatabase::open(config.node.database_path.clone())
.with_context(|| "failed to open database")?;
Expand Down Expand Up @@ -227,10 +237,9 @@ impl Service {
None
};

let rpc = config
.rpc
.as_ref()
.map(|config| ethexe_rpc::RpcService::new(config.clone(), db.clone()));
let rpc = config.rpc.as_ref().map(|config| {
ethexe_rpc::RpcService::new(config.clone(), db.clone(), mock_blob_reader.clone())
});

Ok(Self {
db,
Expand Down
2 changes: 2 additions & 0 deletions ethexe/service/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ async fn basics() {
max_commitment_depth: 1_000,
worker_threads_override: None,
virtual_threads: 16,
dev: true,
};

let eth_cfg = crate::config::EthereumConfig {
Expand Down Expand Up @@ -106,6 +107,7 @@ async fn basics() {
config.rpc = Some(RpcConfig {
listen_addr: SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 9944),
cors: None,
dev: true,
});

config.prometheus = Some(PrometheusConfig::new_with_default_registry(
Expand Down
Loading