cargo_tangle/command/run/
eigenlayer.rs1use blueprint_core::info;
2use blueprint_manager::sources::{BlueprintArgs, BlueprintEnvVars};
3use blueprint_runner::config::{BlueprintEnvironment, Protocol, SupportedChains};
4use blueprint_std::fs;
5use blueprint_std::path::PathBuf;
6use color_eyre::eyre::{Result, eyre};
7use tokio::io::AsyncBufReadExt;
8use tokio::io::BufReader;
9use tokio::process::{Child, Command};
10use toml::Value;
11
12fn get_binary_name() -> Result<String> {
13 let cargo_toml = fs::read_to_string("Cargo.toml")?;
14 let cargo_data: Value = toml::from_str(&cargo_toml)?;
15
16 if let Some(Value::Array(bins)) = cargo_data.get("bin") {
18 if let Some(first_bin) = bins.first() {
19 if let Some(name) = first_bin.get("name").and_then(|n| n.as_str()) {
20 return Ok(name.to_string());
21 }
22 }
23 }
24
25 if let Some(package) = cargo_data.get("package") {
27 if let Some(name) = package.get("name").and_then(|n| n.as_str()) {
28 return Ok(name.to_string());
29 }
30 }
31
32 Err(eyre!("Could not find binary name in Cargo.toml"))
33}
34
35#[allow(clippy::missing_panics_doc)]
42pub async fn run_eigenlayer_avs(
43 config: BlueprintEnvironment,
44 chain: SupportedChains,
45 binary_path: Option<PathBuf>,
46) -> Result<Child> {
47 let binary_path = if let Some(path) = binary_path {
48 path
49 } else {
50 let target_dir = PathBuf::from("./target/release");
51 let binary_name = get_binary_name()?;
52 target_dir.join(&binary_name)
53 };
54
55 println!(
56 "Attempting to run Eigenlayer AVS binary at: {}",
57 binary_path.display()
58 );
59
60 if !binary_path.exists() {
62 info!("Binary not found at {}, building...", binary_path.display());
63 let status = Command::new("cargo")
64 .arg("build")
65 .arg("--release")
66 .status()
67 .await?;
68
69 if !status.success() {
70 return Err(eyre!("Failed to build AVS binary"));
71 }
72 }
73
74 let contract_addresses = config
76 .protocol_settings
77 .eigenlayer()
78 .map_err(|_| eyre!("Missing Eigenlayer contract addresses"))?;
79
80 println!("Starting AVS...");
82 let mut command = Command::new(&binary_path);
83
84 let env = BlueprintEnvVars {
85 http_rpc_endpoint: config.http_rpc_endpoint,
86 ws_rpc_endpoint: config.ws_rpc_endpoint,
87 keystore_uri: config.keystore_uri,
88 data_dir: config.data_dir,
89 blueprint_id: 0,
90 service_id: 0,
91 protocol: Protocol::Eigenlayer,
92 chain: Some(chain),
93 bootnodes: String::new(),
94 registration_mode: false,
95 bridge_socket_path: None,
96 };
97
98 command.envs(env.encode());
99
100 let args = BlueprintArgs {
101 test_mode: false,
102 pretty: false,
103 verbose: 0,
104 };
105
106 command.args(args.encode());
107
108 command
116 .arg("--registry-coordinator")
117 .arg(contract_addresses.registry_coordinator_address.to_string())
118 .arg("--operator-state-retriever")
119 .arg(
120 contract_addresses
121 .operator_state_retriever_address
122 .to_string(),
123 )
124 .arg("--delegation-manager")
125 .arg(contract_addresses.delegation_manager_address.to_string())
126 .arg("--strategy-manager")
127 .arg(contract_addresses.strategy_manager_address.to_string())
128 .arg("--service-manager")
129 .arg(contract_addresses.service_manager_address.to_string())
130 .arg("--stake-registry")
131 .arg(contract_addresses.stake_registry_address.to_string())
132 .arg("--avs-directory")
133 .arg(contract_addresses.avs_directory_address.to_string())
134 .arg("--rewards-coordinator")
135 .arg(contract_addresses.rewards_coordinator_address.to_string())
136 .arg("--allocation-manager")
137 .arg(contract_addresses.allocation_manager_address.to_string())
138 .arg("--permission-controller")
139 .arg(contract_addresses.permission_controller_address.to_string())
140 .arg("--strategy")
141 .arg(contract_addresses.strategy_address.to_string());
142
143 assert!(binary_path.exists(), "Binary path does not exist");
144
145 let mut child = command
146 .stdout(std::process::Stdio::piped())
147 .stderr(std::process::Stdio::piped())
148 .spawn()?;
149
150 let stdout = child.stdout.take().expect("Failed to capture stdout");
152 let mut stdout_reader = BufReader::new(stdout).lines();
153
154 let stderr = child.stderr.take().expect("Failed to capture stderr");
156 let mut stderr_reader = BufReader::new(stderr).lines();
157
158 let stdout_task = tokio::spawn(async move {
160 while let Some(line) = stdout_reader
161 .next_line()
162 .await
163 .expect("Failed to read stdout")
164 {
165 println!("{}", line);
166 }
167 });
168
169 let stderr_task = tokio::spawn(async move {
170 while let Some(line) = stderr_reader
171 .next_line()
172 .await
173 .expect("Failed to read stderr")
174 {
175 eprintln!("{}", line);
176 }
177 });
178
179 let _ = tokio::join!(stdout_task, stderr_task);
181
182 println!(
183 "AVS is running with PID: {}",
184 child.id().unwrap_or_default()
185 );
186 Ok(child)
187}