light_client/
local_test_validator.rs1use std::process::{Command, Stdio};
2
3use light_prover_client::helpers::get_project_root;
4
5#[derive(Debug, Clone)]
7pub struct UpgradeableProgramConfig {
8 pub program_id: String,
10 pub program_path: String,
12 pub upgrade_authority: String,
14}
15
16impl UpgradeableProgramConfig {
17 pub fn new(program_id: String, program_path: String, upgrade_authority: String) -> Self {
18 Self {
19 program_id,
20 program_path,
21 upgrade_authority,
22 }
23 }
24}
25
26#[derive(Debug)]
27pub struct LightValidatorConfig {
28 pub enable_indexer: bool,
29 pub enable_prover: bool,
30 pub wait_time: u64,
31 pub sbf_programs: Vec<(String, String)>,
33 pub upgradeable_programs: Vec<UpgradeableProgramConfig>,
36 pub limit_ledger_size: Option<u64>,
37 pub use_surfpool: bool,
39 pub validator_args: Vec<String>,
41}
42
43impl Default for LightValidatorConfig {
44 fn default() -> Self {
45 Self {
46 enable_indexer: false,
47 enable_prover: false,
48 wait_time: 35,
49 sbf_programs: vec![],
50 upgradeable_programs: vec![],
51 limit_ledger_size: None,
52 use_surfpool: true,
53 validator_args: vec![],
54 }
55 }
56}
57
58pub async fn spawn_validator(config: LightValidatorConfig) {
59 if let Some(project_root) = get_project_root() {
60 let path = "cli/test_bin/run test-validator";
61 let mut path = format!("{}/{}", project_root.trim(), path);
62 if !config.enable_indexer {
63 path.push_str(" --skip-indexer");
64 }
65
66 if let Some(limit_ledger_size) = config.limit_ledger_size {
67 path.push_str(&format!(" --limit-ledger-size {}", limit_ledger_size));
68 }
69
70 for sbf_program in config.sbf_programs.iter() {
71 path.push_str(&format!(
72 " --sbf-program {} {}",
73 sbf_program.0, sbf_program.1
74 ));
75 }
76
77 for upgradeable_program in config.upgradeable_programs.iter() {
78 path.push_str(&format!(
79 " --upgradeable-program {} {} {}",
80 upgradeable_program.program_id,
81 upgradeable_program.program_path,
82 upgradeable_program.upgrade_authority
83 ));
84 }
85
86 if !config.enable_prover {
87 path.push_str(" --skip-prover");
88 }
89
90 if config.use_surfpool {
91 path.push_str(" --use-surfpool");
92 }
93
94 for arg in config.validator_args.iter() {
95 path.push_str(&format!(" {}", arg));
96 }
97
98 println!("Starting validator with command: {}", path);
99
100 if config.use_surfpool {
101 let mut child = Command::new("sh")
105 .arg("-c")
106 .arg(path)
107 .stdin(Stdio::null())
108 .stdout(Stdio::inherit())
109 .stderr(Stdio::inherit())
110 .spawn()
111 .expect("Failed to start server process");
112 let status = child.wait().expect("Failed to wait for CLI process");
113 assert!(status.success(), "CLI exited with error: {}", status);
114 } else {
115 let child = Command::new("sh")
116 .arg("-c")
117 .arg(path)
118 .stdin(Stdio::null())
119 .stdout(Stdio::null())
120 .stderr(Stdio::null())
121 .spawn()
122 .expect("Failed to start server process");
123 std::mem::drop(child);
124 tokio::time::sleep(tokio::time::Duration::from_secs(config.wait_time)).await;
125 }
126 }
127}