Skip to content

Commit

Permalink
Move fullnode to it's own crate (#720)
Browse files Browse the repository at this point in the history
* Skeleton

* Checkin

* Use Citrea fullnode instead of sov

* Use sequencer in CitreaRollupBlueprint

* Cleanup unused import

* Fix RPC test
  • Loading branch information
rakanalh authored Jun 14, 2024
1 parent abb1f54 commit 2230af4
Show file tree
Hide file tree
Showing 14 changed files with 1,189 additions and 468 deletions.
405 changes: 218 additions & 187 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ members = [
"bin/rollup-constants",
"crates/bitcoin-da",
"crates/evm",
"crates/ethereum-rpc",
"crates/fullnode",
"crates/sequencer",
"crates/sequencer-client",
"crates/soft-confirmation-rule-enforcer",
"crates/ethereum-rpc",
"crates/shared-backup-db",
# Sovereign sdk
"crates/sovereign-sdk/rollup-interface",
"crates/sovereign-sdk/adapters/risc0",
Expand Down Expand Up @@ -50,8 +52,6 @@ members = [
"crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter",
"crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state",
"crates/sovereign-sdk/module-system/module-implementations/integration-tests",
# Offchain
"crates/shared-backup-db",
]

[workspace.package]
Expand Down
1 change: 1 addition & 0 deletions bin/citrea/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ resolver = "2"
[dependencies]
# Citrea deps
bitcoin-da = { path = "../../crates/bitcoin-da", features = ["native"] }
citrea-fullnode = { path = "../../crates/fullnode" }
citrea-prover = { path = "../../crates/prover" }
citrea-sequencer = { path = "../../crates/sequencer" }
citrea-stf = { path = "../../crates/citrea-stf", features = ["native"] }
Expand Down
11 changes: 7 additions & 4 deletions bin/citrea/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,13 @@ where
error!("Error: {}", e);
}
} else {
let rollup = rollup_blueprint
.create_new_rollup(rt_genesis_paths, rollup_config)
.await
.unwrap();
let rollup = CitreaRollupBlueprint::create_new_rollup(
&rollup_blueprint,
rt_genesis_paths,
rollup_config,
)
.await
.unwrap();
if let Err(e) = rollup.run().await {
error!("Error: {}", e);
}
Expand Down
139 changes: 139 additions & 0 deletions bin/citrea/src/rollup/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use async_trait::async_trait;
pub use bitcoin::*;
use citrea_fullnode::{CitreaFullnode, FullNode};
use citrea_prover::{CitreaProver, Prover};
use citrea_sequencer::{CitreaSequencer, Sequencer, SequencerConfig};
pub use mock::*;
use sov_modules_api::storage::HierarchicalStorageManager;
use sov_modules_api::Spec;
Expand All @@ -16,6 +18,143 @@ mod mock;
/// Overrides RollupBlueprint methods
#[async_trait]
pub trait CitreaRollupBlueprint: RollupBlueprint {
/// Creates a new sequencer
#[instrument(level = "trace", skip_all)]
async fn create_new_sequencer(
&self,
runtime_genesis_paths: &<Self::NativeRuntime as RuntimeTrait<
Self::NativeContext,
Self::DaSpec,
>>::GenesisPaths,
rollup_config: RollupConfig<Self::DaConfig>,
sequencer_config: SequencerConfig,
) -> Result<Sequencer<Self>, anyhow::Error>
where
<Self::NativeContext as Spec>::Storage: NativeStorage,
{
let da_service = self.create_da_service(&rollup_config).await;

// TODO: Double check what kind of storage needed here.
// Maybe whole "prev_root" can be initialized inside runner
// Getting block here, so prover_service doesn't have to be `Send`

let ledger_db = self.create_ledger_db(&rollup_config);
let genesis_config = self.create_genesis_config(runtime_genesis_paths, &rollup_config)?;

let mut storage_manager = self.create_storage_manager(&rollup_config)?;
let prover_storage = storage_manager.create_finalized_storage()?;

let prev_root = ledger_db
.get_head_soft_batch()?
.map(|(number, _)| prover_storage.get_root_hash(number.0 + 1))
.transpose()?;

// TODO(https://github.com/Sovereign-Labs/sovereign-sdk/issues/1218)
let rpc_methods =
self.create_rpc_methods(&prover_storage, &ledger_db, &da_service, None)?;

let native_stf = StfBlueprint::new();

let genesis_root = prover_storage.get_root_hash(1);

let init_variant = match prev_root {
Some(root_hash) => InitVariant::Initialized(root_hash),
None => match genesis_root {
Ok(root_hash) => InitVariant::Initialized(root_hash),
_ => InitVariant::Genesis(genesis_config),
},
};

let seq = CitreaSequencer::new(
da_service,
prover_storage,
sequencer_config,
native_stf,
storage_manager,
init_variant,
rollup_config.public_keys,
ledger_db,
rollup_config.rpc,
)
.unwrap();

Ok(Sequencer {
runner: seq,
rpc_methods,
})
}

/// Creates a new rollup.
#[instrument(level = "trace", skip_all)]
async fn create_new_rollup(
&self,
runtime_genesis_paths: &<Self::NativeRuntime as RuntimeTrait<
Self::NativeContext,
Self::DaSpec,
>>::GenesisPaths,
rollup_config: RollupConfig<Self::DaConfig>,
) -> Result<FullNode<Self>, anyhow::Error>
where
<Self::NativeContext as Spec>::Storage: NativeStorage,
{
let da_service = self.create_da_service(&rollup_config).await;

// TODO: Double check what kind of storage needed here.
// Maybe whole "prev_root" can be initialized inside runner
// Getting block here, so prover_service doesn't have to be `Send`

let ledger_db = self.create_ledger_db(&rollup_config);
let genesis_config = self.create_genesis_config(runtime_genesis_paths, &rollup_config)?;

let mut storage_manager = self.create_storage_manager(&rollup_config)?;
let prover_storage = storage_manager.create_finalized_storage()?;

let prev_root = ledger_db
.get_head_soft_batch()?
.map(|(number, _)| prover_storage.get_root_hash(number.0 + 1))
.transpose()?;

let runner_config = rollup_config.runner.expect("Runner config is missing");
// TODO(https://github.com/Sovereign-Labs/sovereign-sdk/issues/1218)
let rpc_methods = self.create_rpc_methods(
&prover_storage,
&ledger_db,
&da_service,
Some(runner_config.sequencer_client_url.clone()),
)?;

let native_stf = StfBlueprint::new();

let genesis_root = prover_storage.get_root_hash(1);

let init_variant = match prev_root {
Some(root_hash) => InitVariant::Initialized(root_hash),
None => match genesis_root {
Ok(root_hash) => InitVariant::Initialized(root_hash),
_ => InitVariant::Genesis(genesis_config),
},
};

let code_commitment = self.get_code_commitment();

let runner = CitreaFullnode::new(
runner_config,
rollup_config.public_keys,
rollup_config.rpc,
da_service,
ledger_db,
native_stf,
storage_manager,
init_variant,
code_commitment,
)?;

Ok(FullNode {
runner,
rpc_methods,
})
}

/// Creates a new prover
#[instrument(level = "trace", skip_all)]
async fn create_new_prover(
Expand Down
28 changes: 17 additions & 11 deletions bin/citrea/tests/test_helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use shared_backup_db::PostgresConnector;
use sov_mock_da::{MockAddress, MockDaConfig, MockDaService};
use sov_modules_api::default_signature::private_key::DefaultPrivateKey;
use sov_modules_api::PrivateKey;
use sov_modules_rollup_blueprint::RollupBlueprint;
use sov_stf_runner::{
ProverConfig, RollupConfig, RollupPublicKeys, RpcConfig, RunnerConfig, StorageConfig,
};
Expand Down Expand Up @@ -55,11 +54,14 @@ pub async fn start_rollup(
match node_mode {
NodeMode::FullNode(_) => {
let span = info_span!("FullNode");
let rollup = mock_demo_rollup
.create_new_rollup(&rt_genesis_paths, rollup_config.clone())
.instrument(span.clone())
.await
.unwrap();
let rollup = CitreaRollupBlueprint::create_new_rollup(
&mock_demo_rollup,
&rt_genesis_paths,
rollup_config.clone(),
)
.instrument(span.clone())
.await
.unwrap();
rollup
.run_and_report_rpc_port(Some(rpc_reporting_channel))
.instrument(span)
Expand Down Expand Up @@ -99,11 +101,15 @@ pub async fn start_rollup(
});

let span = info_span!("Sequencer");
let sequencer_rollup = mock_demo_rollup
.create_new_sequencer(&rt_genesis_paths, rollup_config.clone(), sequencer_config)
.instrument(span.clone())
.await
.unwrap();
let sequencer_rollup = CitreaRollupBlueprint::create_new_sequencer(
&mock_demo_rollup,
&rt_genesis_paths,
rollup_config.clone(),
sequencer_config,
)
.instrument(span.clone())
.await
.unwrap();
sequencer_rollup
.run_and_report_rpc_port(Some(rpc_reporting_channel))
.instrument(span)
Expand Down
37 changes: 37 additions & 0 deletions crates/fullnode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[package]
name = "citrea-fullnode"
version.workspace = true
authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
publish.workspace = true
repository.workspace = true

[dependencies]
# Citrea Deps
sequencer-client = { path = "../sequencer-client" }
shared-backup-db = { path = "../shared-backup-db" }

# Sov SDK deps
sov-db = { path = "../sovereign-sdk/full-node/db/sov-db" }
sov-mock-da = { path = "../sovereign-sdk/adapters/mock-da", features = ["native"] }
sov-modules-api = { path = "../sovereign-sdk/module-system/sov-modules-api", default-features = false }
sov-modules-rollup-blueprint = { path = "../sovereign-sdk/module-system/sov-modules-rollup-blueprint" }
sov-modules-stf-blueprint = { path = "../sovereign-sdk/module-system/sov-modules-stf-blueprint", features = ["native"] }
sov-rollup-interface = { path = "../sovereign-sdk/rollup-interface" }
sov-stf-runner = { path = "../sovereign-sdk/full-node/sov-stf-runner" }

# 3rd-party deps
anyhow = { workspace = true }
backoff = { workspace = true }
borsh = { workspace = true }
futures = { workspace = true }
hex = { workspace = true }
jsonrpsee = { workspace = true }
rand = { workspace = true }
rs_merkle = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
49 changes: 49 additions & 0 deletions crates/fullnode/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::net::SocketAddr;

pub use runner::*;
use sov_modules_rollup_blueprint::RollupBlueprint;
use sov_modules_stf_blueprint::StfBlueprint;
use tokio::sync::oneshot;
use tracing::instrument;
mod runner;

/// Dependencies needed to run the rollup.
pub struct FullNode<S: RollupBlueprint> {
/// The State Transition Runner.
#[allow(clippy::type_complexity)]
pub runner: CitreaFullnode<
StfBlueprint<S::NativeContext, S::DaSpec, S::Vm, S::NativeRuntime>,
S::StorageManager,
S::DaService,
S::Vm,
S::NativeContext,
>,
/// Rpc methods for the rollup.
pub rpc_methods: jsonrpsee::RpcModule<()>,
}

impl<S: RollupBlueprint> FullNode<S> {
/// Runs the rollup.
#[instrument(level = "trace", skip(self), err, ret(level = "error"))]
pub async fn run(self) -> Result<(), anyhow::Error> {
self.run_and_report_rpc_port(None).await
}

/// Only run the rpc.
pub async fn run_rpc(self) -> Result<(), anyhow::Error> {
self.runner.start_rpc_server(self.rpc_methods, None).await;
Ok(())
}

/// Runs the rollup. Reports rpc port to the caller using the provided channel.
pub async fn run_and_report_rpc_port(
self,
channel: Option<oneshot::Sender<SocketAddr>>,
) -> Result<(), anyhow::Error> {
let mut runner = self.runner;
runner.start_rpc_server(self.rpc_methods, channel).await;

runner.run().await?;
Ok(())
}
}
Loading

0 comments on commit 2230af4

Please sign in to comment.