diff --git a/src/bitcoin.rs b/src/bitcoin.rs index 3ef09c5..c7daa85 100644 --- a/src/bitcoin.rs +++ b/src/bitcoin.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashSet, + collections::{HashMap, HashSet}, fs::File, future::Future, process::Stdio, @@ -165,6 +165,16 @@ impl BitcoinNode { ) -> bitcoincore_rpc::Result> { RpcApi::generate(self, block_num, None).await } + + pub async fn generate_block( + &self, + // Address to send the block reward to + output: String, + // Either raw txs or txids, should be in mempool and in correct order + transactions: Vec, + ) -> bitcoincore_rpc::Result> { + RpcApi::call(self, "generateblock", &[output.into(), transactions.into()]).await + } } #[async_trait] @@ -273,7 +283,11 @@ impl Restart for BitcoinNode { } } - async fn start(&mut self, config: Option) -> Result<()> { + async fn start( + &mut self, + config: Option, + _extra_args: Option>, + ) -> Result<()> { if let Some(config) = config { self.config = config; } diff --git a/src/citrea_config/batch_prover.rs b/src/citrea_config/batch_prover.rs index e173532..462766d 100644 --- a/src/citrea_config/batch_prover.rs +++ b/src/citrea_config/batch_prover.rs @@ -39,8 +39,6 @@ pub struct BatchProverConfig { pub proof_sampling_number: usize, /// If true prover will try to recover ongoing proving sessions pub enable_recovery: bool, - /// Wether to always use the latest ELF or not - pub use_latest_elf: bool, } impl Default for BatchProverConfig { @@ -49,7 +47,6 @@ impl Default for BatchProverConfig { proving_mode: ProverGuestRunConfig::Execute, proof_sampling_number: 0, enable_recovery: true, - use_latest_elf: true, } } } @@ -101,7 +98,6 @@ mod tests { proving_mode: ProverGuestRunConfig::Skip, proof_sampling_number: 500, enable_recovery: true, - use_latest_elf: true, }; assert_eq!(config, expected); } diff --git a/src/config/mod.rs b/src/config/mod.rs index 264788c..8caed19 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -49,6 +49,23 @@ impl fmt::Display for DaLayer { } } +#[derive(Clone, Debug, Default, Copy)] +pub enum CitreaMode { + #[default] + Dev, + DevAllForks, +} + +impl fmt::Display for CitreaMode { + // This trait requires `fmt` with this exact signature. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + CitreaMode::Dev => write!(f, "dev"), + CitreaMode::DevAllForks => write!(f, "dev-all-forks"), + } + } +} + #[derive(Clone, Debug, Default)] pub struct FullL2NodeConfig { pub node: T, @@ -57,6 +74,7 @@ pub struct FullL2NodeConfig { pub dir: PathBuf, pub env: Vec<(&'static str, &'static str)>, pub da_layer: Option, + pub mode: CitreaMode, } impl FullL2NodeConfig @@ -70,6 +88,7 @@ where docker_image: Option, dir: PathBuf, env: Vec<(&'static str, &'static str)>, + mode: CitreaMode, ) -> Result { let conf = Self { node, @@ -78,6 +97,7 @@ where dir, env, da_layer: None, + mode, }; let kind = FullL2NodeConfig::::kind(); @@ -190,6 +210,10 @@ where fn da_layer(&self) -> DaLayer { self.da_layer.clone().unwrap_or_default() } + + fn mode(&self) -> CitreaMode { + self.mode + } } impl LogPathProvider for FullL2NodeConfig diff --git a/src/config/test_case.rs b/src/config/test_case.rs index 8e1e921..dc8fa51 100644 --- a/src/config/test_case.rs +++ b/src/config/test_case.rs @@ -2,6 +2,7 @@ use std::{env, path::PathBuf, time::Duration}; use tempfile::TempDir; +use super::CitreaMode; use crate::utils::generate_test_id; #[derive(Clone, Default)] @@ -60,6 +61,7 @@ pub struct TestCaseConfig { // Defaults to resources/genesis/bitcoin-regtest pub genesis_dir: Option, pub test_id: String, + pub mode: CitreaMode, } impl Default for TestCaseConfig { @@ -85,6 +87,7 @@ impl Default for TestCaseConfig { docker: TestCaseDockerConfig::default(), genesis_dir: None, test_id, + mode: CitreaMode::Dev, } } } diff --git a/src/framework.rs b/src/framework.rs index be315bf..c3dc94f 100644 --- a/src/framework.rs +++ b/src/framework.rs @@ -443,6 +443,7 @@ fn generate_test_config( citrea_docker_image.clone(), sequencer_dir, env.sequencer(), + test_case.mode, )?, batch_prover: FullBatchProverConfig::new( batch_prover, @@ -450,6 +451,7 @@ fn generate_test_config( citrea_docker_image.clone(), batch_prover_dir, env.batch_prover(), + test_case.mode, )?, light_client_prover: FullLightClientProverConfig::new( light_client_prover, @@ -457,6 +459,7 @@ fn generate_test_config( citrea_docker_image.clone(), light_client_prover_dir, env.light_client_prover(), + test_case.mode, )?, full_node: FullFullNodeConfig::new( (), @@ -464,6 +467,7 @@ fn generate_test_config( citrea_docker_image, full_node_dir, env.full_node(), + test_case.mode, )?, test_case, }) diff --git a/src/node.rs b/src/node.rs index 0662002..1ac1acd 100644 --- a/src/node.rs +++ b/src/node.rs @@ -22,7 +22,7 @@ use tracing::{debug, info, trace}; use crate::{ client::Client, - config::{BitcoinConfig, DaLayer, DockerConfig, RollupConfig}, + config::{BitcoinConfig, CitreaMode, DaLayer, DockerConfig, RollupConfig}, docker::DockerEnv, log_provider::LogPathProvider, traits::{NodeT, Restart, SpawnOutput}, @@ -80,6 +80,7 @@ pub trait Config: Clone { // Not required for `full-node` fn get_node_config_args(&self) -> Option>; fn get_rollup_config_args(&self) -> Vec; + fn mode(&self) -> CitreaMode; } pub struct Node { @@ -124,7 +125,7 @@ where }) } - fn spawn(config: &C) -> Result { + fn spawn(config: &C, extra_args: Option>) -> Result { let citrea = get_citrea_path()?; let kind = C::node_kind(); @@ -144,6 +145,7 @@ where Command::new(citrea) .args(get_citrea_args(config)) + .args(extra_args.unwrap_or_default()) .envs(config.env()) .stdout(Stdio::from(stdout_file)) .stderr(Stdio::from(stderr_file)) @@ -190,7 +192,7 @@ where async fn spawn(config: &Self::Config, docker: &Arc>) -> Result { match docker.as_ref() { Some(docker) if docker.citrea() => docker.spawn(config.to_owned().into()).await, - _ => Self::spawn(config), + _ => Self::spawn(config, None), } } @@ -250,7 +252,11 @@ where Ok(()) } - async fn start(&mut self, new_config: Option) -> Result<()> { + async fn start( + &mut self, + new_config: Option, + extra_args: Option>, + ) -> Result<()> { let config = self.config_mut(); if let Some(new_config) = new_config { @@ -271,7 +277,7 @@ where copy_directory(old_dir, &new_dir)?; config.set_dir(new_dir); - *self.spawn_output() = Self::spawn(config)?; + *self.spawn_output() = Self::spawn(config, extra_args)?; self.wait_for_ready(None).await } } @@ -284,7 +290,7 @@ where let rollup_config_args = config.get_rollup_config_args(); [ - vec!["--dev".to_string()], + vec![format!("--{}", config.mode())], vec!["--da-layer".to_string(), config.da_layer().to_string()], node_config_args, rollup_config_args, diff --git a/src/traits.rs b/src/traits.rs index 20c5b71..a1ff220 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -68,11 +68,19 @@ pub trait NodeT: Send { #[async_trait] pub trait Restart: NodeT + Send { async fn wait_until_stopped(&mut self) -> Result<()>; - async fn start(&mut self, new_config: Option) -> Result<()>; + async fn start( + &mut self, + new_config: Option, + extra_args: Option>, + ) -> Result<()>; // Default implementation to support waiting for node to be fully shutdown and brough back up with new config. - async fn restart(&mut self, new_config: Option) -> Result<()> { + async fn restart( + &mut self, + new_config: Option, + extra_args: Option>, + ) -> Result<()> { self.wait_until_stopped().await?; - self.start(new_config).await + self.start(new_config, extra_args).await } } diff --git a/tests/bitcoin.rs b/tests/bitcoin.rs index 424fbf6..23af334 100644 --- a/tests/bitcoin.rs +++ b/tests/bitcoin.rs @@ -108,7 +108,7 @@ impl TestCase for RestartBitcoinTest { assert_eq!(info.txindex, None); // Restart node with txindex - da.restart(Some(new_conf)).await?; + da.restart(Some(new_conf), None).await?; let block_after = da.get_block_count().await?; let info = da.get_index_info().await?;