Skip to content

Commit 3d400f7

Browse files
authored
feat: converge on a single database for both rollup node and eth networking (#318)
* converge on a single database for both rollup node and eth networking * clean up
1 parent 16e2332 commit 3d400f7

File tree

8 files changed

+84
-59
lines changed

8 files changed

+84
-59
lines changed

crates/node/src/args.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ use aws_sdk_kms::config::BehaviorVersion;
1818
use reth_chainspec::EthChainSpec;
1919
use reth_network::NetworkProtocols;
2020
use reth_network_api::FullNetwork;
21-
use reth_node_builder::rpc::RethRpcServerHandles;
21+
use reth_node_builder::{rpc::RethRpcServerHandles, NodeConfig as RethNodeConfig};
2222
use reth_node_core::primitives::BlockHeader;
23-
use reth_scroll_chainspec::{ChainConfig, ScrollChainConfig, SCROLL_FEE_VAULT_ADDRESS};
23+
use reth_scroll_chainspec::{
24+
ChainConfig, ScrollChainConfig, ScrollChainSpec, SCROLL_FEE_VAULT_ADDRESS,
25+
};
2426
use reth_scroll_node::ScrollNetworkPrimitives;
2527
use rollup_node_chain_orchestrator::ChainOrchestrator;
2628
use rollup_node_manager::{
@@ -79,6 +81,9 @@ pub struct ScrollRollupNodeConfig {
7981
/// The gas price oracle args
8082
#[command(flatten)]
8183
pub gas_price_oracle_args: GasPriceOracleArgs,
84+
/// The database connection (not parsed via CLI but hydrated after validation).
85+
#[arg(skip)]
86+
pub database: Option<Arc<Database>>,
8287
}
8388

8489
impl ScrollRollupNodeConfig {
@@ -112,6 +117,26 @@ impl ScrollRollupNodeConfig {
112117

113118
Ok(())
114119
}
120+
121+
/// Hydrate the config by initializing the database connection.
122+
pub async fn hydrate(
123+
&mut self,
124+
node_config: RethNodeConfig<ScrollChainSpec>,
125+
) -> eyre::Result<()> {
126+
// Instantiate the database
127+
let db_path = node_config.datadir().db();
128+
let database_path = if let Some(database_path) = &self.database_args.path {
129+
database_path.to_string_lossy().to_string()
130+
} else {
131+
// append the path using strings as using `join(...)` overwrites "sqlite://"
132+
// if the path is absolute.
133+
let path = db_path.join("scroll.db?mode=rwc");
134+
"sqlite://".to_string() + &*path.to_string_lossy()
135+
};
136+
let db = Database::new(&database_path).await?;
137+
self.database = Some(Arc::new(db));
138+
Ok(())
139+
}
115140
}
116141

117142
impl ScrollRollupNodeConfig {
@@ -175,17 +200,8 @@ impl ScrollRollupNodeConfig {
175200
.expect("failed to create payload provider");
176201
let l2_provider = Arc::new(l2_provider);
177202

178-
// Instantiate the database
179-
let db_path = ctx.datadir;
180-
let database_path = if let Some(database_path) = self.database_args.path {
181-
database_path.to_string_lossy().to_string()
182-
} else {
183-
// append the path using strings as using `join(...)` overwrites "sqlite://"
184-
// if the path is absolute.
185-
let path = db_path.join("scroll.db?mode=rwc");
186-
"sqlite://".to_string() + &*path.to_string_lossy()
187-
};
188-
let db = Database::new(&database_path).await?;
203+
// Fetch the database from the hydrated config.
204+
let db = self.database.clone().expect("should hydrate config before build");
189205

190206
// Run the database migrations
191207
if let Some(named) = chain_spec.chain().named() {
@@ -215,9 +231,6 @@ impl ScrollRollupNodeConfig {
215231
tracing::info!(target: "scroll::node::args", ?genesis_hash, "Overwriting genesis hash for custom chain");
216232
}
217233

218-
// Wrap the database in an Arc
219-
let db = Arc::new(db);
220-
221234
let chain_spec_fcs = || {
222235
ForkchoiceState::head_from_chain_spec(chain_spec.clone())
223236
.expect("failed to derive forkchoice state from chain spec")
@@ -787,6 +800,7 @@ mod tests {
787800
algorithm: ConsensusAlgorithm::SystemContract,
788801
authorized_signer: None,
789802
},
803+
database: None,
790804
};
791805

792806
let result = config.validate();
@@ -817,6 +831,7 @@ mod tests {
817831
algorithm: ConsensusAlgorithm::SystemContract,
818832
authorized_signer: None,
819833
},
834+
database: None,
820835
};
821836

822837
let result = config.validate();
@@ -842,6 +857,7 @@ mod tests {
842857
network_args: NetworkArgs::default(),
843858
gas_price_oracle_args: GasPriceOracleArgs::default(),
844859
consensus_args: ConsensusArgs::noop(),
860+
database: None,
845861
};
846862

847863
assert!(config.validate().is_ok());
@@ -865,6 +881,7 @@ mod tests {
865881
network_args: NetworkArgs::default(),
866882
gas_price_oracle_args: GasPriceOracleArgs::default(),
867883
consensus_args: ConsensusArgs::noop(),
884+
database: None,
868885
};
869886

870887
assert!(config.validate().is_ok());
@@ -884,6 +901,7 @@ mod tests {
884901
network_args: NetworkArgs::default(),
885902
gas_price_oracle_args: GasPriceOracleArgs::default(),
886903
consensus_args: ConsensusArgs::noop(),
904+
database: None,
887905
};
888906

889907
assert!(config.validate().is_ok());

crates/node/src/builder/network.rs

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,26 @@ use reth_transaction_pool::{PoolTransaction, TransactionPool};
1717
use rollup_node_signer::SignatureAsBytes;
1818
use scroll_alloy_hardforks::ScrollHardforks;
1919
use scroll_db::{Database, DatabaseOperations};
20-
use std::{fmt, fmt::Debug, path::PathBuf, sync::Arc};
20+
use std::{fmt, fmt::Debug, sync::Arc};
2121
use tracing::{debug, info, trace, warn};
2222

2323
use crate::args::NetworkArgs;
2424

2525
/// The network builder for Scroll.
26-
#[derive(Debug, Default)]
26+
#[derive(Debug)]
2727
pub struct ScrollNetworkBuilder {
2828
/// Additional `RLPx` sub-protocols to be added to the network.
2929
scroll_sub_protocols: RlpxSubProtocols,
3030
/// A reference to the rollup-node `Database`.
31-
rollup_node_db_path: Option<PathBuf>,
31+
rollup_node_db: Arc<Database>,
3232
/// The address for which we should persist and serve signatures for.
3333
signer: Option<Address>,
3434
}
3535

3636
impl ScrollNetworkBuilder {
37-
/// Create a new [`ScrollNetworkBuilder`] with default configuration.
38-
pub fn new() -> Self {
39-
Self {
40-
scroll_sub_protocols: RlpxSubProtocols::default(),
41-
rollup_node_db_path: None,
42-
signer: None,
43-
}
37+
/// Create a new [`ScrollNetworkBuilder`] with provided rollup node database.
38+
pub fn new(rollup_node_db: Arc<Database>) -> Self {
39+
Self { scroll_sub_protocols: RlpxSubProtocols::default(), rollup_node_db, signer: None }
4440
}
4541

4642
/// Add a scroll sub-protocol to the network builder.
@@ -49,12 +45,6 @@ impl ScrollNetworkBuilder {
4945
self
5046
}
5147

52-
/// Add a scroll sub-protocol to the network builder.
53-
pub fn with_database_path(mut self, db_path: Option<PathBuf>) -> Self {
54-
self.rollup_node_db_path = db_path;
55-
self
56-
}
57-
5848
/// Set the signer for which we will persist and serve signatures if included in block header
5949
/// extra data field.
6050
pub const fn with_signer(mut self, signer: Option<Address>) -> Self {
@@ -82,29 +72,23 @@ where
8272
ctx: &BuilderContext<Node>,
8373
pool: Pool,
8474
) -> eyre::Result<Self::Network> {
85-
// initialize the rollup node database.
86-
let db_path = ctx.config().datadir().db();
87-
let database_path = if let Some(database_path) = self.rollup_node_db_path {
88-
database_path.to_string_lossy().to_string()
89-
} else {
90-
// append the path using strings as using `join(...)` overwrites "sqlite://"
91-
// if the path is absolute.
92-
let path = db_path.join("scroll.db?mode=rwc");
93-
"sqlite://".to_string() + &*path.to_string_lossy()
94-
};
95-
let db = Arc::new(Database::new(&database_path).await?);
96-
9775
// get the header transform.
9876
let chain_spec = ctx.chain_spec();
9977
let authorized_signer = if self.signer.is_none() {
10078
NetworkArgs::default_authorized_signer(chain_spec.chain().named())
10179
} else {
10280
self.signer
10381
};
104-
let transform =
105-
ScrollHeaderTransform::new(chain_spec.clone(), db.clone(), authorized_signer);
106-
let request_transform =
107-
ScrollRequestHeaderTransform::new(chain_spec, db.clone(), authorized_signer);
82+
let transform = ScrollHeaderTransform::new(
83+
chain_spec.clone(),
84+
self.rollup_node_db.clone(),
85+
authorized_signer,
86+
);
87+
let request_transform = ScrollRequestHeaderTransform::new(
88+
chain_spec,
89+
self.rollup_node_db.clone(),
90+
authorized_signer,
91+
);
10892

10993
// set the network mode to work.
11094
let config = ctx.network_config()?;

crates/node/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ fn main() {
2020
if let Err(err) = Cli::<ScrollChainSpecParser, ScrollRollupNodeConfig>::parse().run(
2121
|builder, args| async move {
2222
info!(target: "reth::cli", "Launching node");
23+
let config = builder.config().clone();
2324
let handle = builder
24-
.node(ScrollRollupNode::new(args))
25+
.node(ScrollRollupNode::new(args, config).await)
2526
.launch_with_fn(|builder| {
2627
info!(target: "reth::cli", config = ?builder.config().chain.config, "Running with config");
2728

crates/node/src/node.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use reth_network::protocol::IntoRlpxSubProtocol;
88
use reth_node_api::NodeTypes;
99
use reth_node_builder::{
1010
components::{BasicPayloadServiceBuilder, ComponentsBuilder},
11-
FullNodeTypes, Node, NodeAdapter, NodeComponentsBuilder,
11+
FullNodeTypes, Node, NodeAdapter, NodeComponentsBuilder, NodeConfig,
1212
};
13+
use reth_scroll_chainspec::ScrollChainSpec;
1314
use reth_scroll_node::{
1415
ScrollConsensusBuilder, ScrollExecutorBuilder, ScrollNode, ScrollPayloadBuilderBuilder,
1516
ScrollPoolBuilder,
@@ -27,11 +28,19 @@ pub struct ScrollRollupNode {
2728

2829
impl ScrollRollupNode {
2930
/// Create a new instance of [`ScrollRollupNode`].
30-
pub fn new(config: ScrollRollupNodeConfig) -> Self {
31+
pub async fn new(
32+
mut config: ScrollRollupNodeConfig,
33+
node_config: NodeConfig<ScrollChainSpec>,
34+
) -> Self {
3135
config
3236
.validate()
3337
.map_err(|e| eyre::eyre!("Configuration validation failed: {}", e))
3438
.expect("Configuration validation failed");
39+
config
40+
.hydrate(node_config)
41+
.await
42+
.map_err(|e| eyre::eyre!("Configuration hydration failed: {}", e))
43+
.expect("Configuration hydration failed");
3544

3645
Self { config, scroll_wire_events: Arc::new(Mutex::new(None)) }
3746
}
@@ -69,10 +78,11 @@ where
6978
block_da_size_limit: Some(constants::DEFAULT_PAYLOAD_SIZE_LIMIT),
7079
}))
7180
.network(
72-
ScrollNetworkBuilder::new()
73-
.with_sub_protocol(scroll_wire_handler.into_rlpx_sub_protocol())
74-
.with_database_path(self.config.database_args.path.clone())
75-
.with_signer(self.config.network_args.signer_address),
81+
ScrollNetworkBuilder::new(
82+
self.config.database.clone().expect("database is set via hydration"),
83+
)
84+
.with_sub_protocol(scroll_wire_handler.into_rlpx_sub_protocol())
85+
.with_signer(self.config.network_args.signer_address),
7686
)
7787
}
7888

crates/node/src/test_utils.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ where
8282

8383
let span = span!(Level::INFO, "node", idx);
8484
let _enter = span.enter();
85-
let node = ScrollRollupNode::new(scroll_node_config.clone());
86-
let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
87-
.testing_node(exec.clone())
85+
let testing_node = NodeBuilder::new(node_config.clone()).testing_node(exec.clone());
86+
let testing_config = testing_node.config().clone();
87+
let node = ScrollRollupNode::new(scroll_node_config.clone(), testing_config).await;
88+
let NodeHandle { node, node_exit_future: _ } = testing_node
8889
.with_types_and_provider::<ScrollRollupNode, BlockchainProvider<_>>()
8990
.with_components(node.components_builder())
9091
.with_add_ons(node.add_ons())
@@ -161,6 +162,7 @@ pub fn default_test_scroll_rollup_node_config() -> ScrollRollupNodeConfig {
161162
signer_args: Default::default(),
162163
gas_price_oracle_args: GasPriceOracleArgs::default(),
163164
consensus_args: ConsensusArgs::noop(),
165+
database: None,
164166
}
165167
}
166168

@@ -199,5 +201,6 @@ pub fn default_sequencer_test_scroll_rollup_node_config() -> ScrollRollupNodeCon
199201
signer_args: Default::default(),
200202
gas_price_oracle_args: GasPriceOracleArgs::default(),
201203
consensus_args: ConsensusArgs::noop(),
204+
database: None,
202205
}
203206
}

crates/node/tests/e2e.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ async fn can_bridge_l1_messages() -> eyre::Result<()> {
7575
signer_args: Default::default(),
7676
gas_price_oracle_args: GasPriceOracleArgs::default(),
7777
consensus_args: ConsensusArgs::noop(),
78+
database: None,
7879
};
7980
let (mut nodes, _tasks, _wallet) = setup_engine(node_args, 1, chain_spec, false, false).await?;
8081
let node = nodes.pop().unwrap();
@@ -173,6 +174,7 @@ async fn can_sequence_and_gossip_blocks() {
173174
signer_args: Default::default(),
174175
gas_price_oracle_args: GasPriceOracleArgs::default(),
175176
consensus_args: ConsensusArgs::noop(),
177+
database: None,
176178
};
177179

178180
let (nodes, _tasks, wallet) =
@@ -274,6 +276,7 @@ async fn can_penalize_peer_for_invalid_block() {
274276
gas_price_oracle_args: GasPriceOracleArgs::default(),
275277
consensus_args: ConsensusArgs::noop(),
276278
chain_orchestrator_args: ChainOrchestratorArgs::default(),
279+
database: None,
277280
};
278281

279282
let (nodes, _tasks, _) =
@@ -828,12 +831,12 @@ async fn graceful_shutdown_consolidates_most_recent_batch_on_startup() -> eyre::
828831
let mut config = default_test_scroll_rollup_node_config();
829832
let path = node.inner.config.datadir().db().join("scroll.db?mode=rwc");
830833
let path = PathBuf::from("sqlite://".to_string() + &*path.to_string_lossy());
831-
config.database_args.path = Some(path.clone());
832834
config.beacon_provider_args.url = Some(
833835
"http://dummy:8545"
834836
.parse()
835837
.expect("valid url that will not be used as test batches use calldata"),
836838
);
839+
config.hydrate(node.inner.config.clone()).await?;
837840

838841
let (_, events) = ScrollWireProtocolHandler::new(ScrollWireConfig::new(true));
839842
let (rnm, handle, l1_notification_tx) = config

crates/node/tests/sync.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ async fn test_should_consolidate_to_block_15k() -> eyre::Result<()> {
7373
signer_args: Default::default(),
7474
gas_price_oracle_args: GasPriceOracleArgs::default(),
7575
consensus_args: ConsensusArgs::noop(),
76+
database: None,
7677
};
7778

7879
let chain_spec = (*SCROLL_SEPOLIA).clone();
@@ -212,6 +213,7 @@ async fn test_should_consolidate_after_optimistic_sync() -> eyre::Result<()> {
212213
signer_args: Default::default(),
213214
gas_price_oracle_args: GasPriceOracleArgs::default(),
214215
consensus_args: ConsensusArgs::noop(),
216+
database: None,
215217
};
216218

217219
// Create the chain spec for scroll dev with Feynman activated and a test genesis.
@@ -462,6 +464,7 @@ async fn test_consolidation() -> eyre::Result<()> {
462464
signer_args: Default::default(),
463465
gas_price_oracle_args: GasPriceOracleArgs::default(),
464466
consensus_args: ConsensusArgs::noop(),
467+
database: None,
465468
};
466469

467470
// Create the chain spec for scroll dev with Feynman activated and a test genesis.
@@ -636,6 +639,7 @@ async fn test_chain_orchestrator_shallow_reorg_with_gap() -> eyre::Result<()> {
636639
signer_args: Default::default(),
637640
gas_price_oracle_args: GasPriceOracleArgs::default(),
638641
consensus_args: ConsensusArgs::noop(),
642+
database: None,
639643
};
640644

641645
// Create the chain spec for scroll dev with Feynman activated and a test genesis.

crates/sequencer/tests/e2e.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ async fn can_sequence_blocks_with_private_key_file() -> eyre::Result<()> {
520520
},
521521
gas_price_oracle_args: GasPriceOracleArgs::default(),
522522
consensus_args: ConsensusArgs::noop(),
523+
database: None,
523524
};
524525

525526
let (nodes, _tasks, wallet) =
@@ -613,6 +614,7 @@ async fn can_sequence_blocks_with_hex_key_file_without_prefix() -> eyre::Result<
613614
},
614615
gas_price_oracle_args: GasPriceOracleArgs::default(),
615616
consensus_args: ConsensusArgs::noop(),
617+
database: None,
616618
};
617619

618620
let (nodes, _tasks, wallet) =

0 commit comments

Comments
 (0)