1use alloy::primitives::{Address, FixedBytes};
2use clap::{Parser, Subcommand};
3use eyre::{Context, Result};
4use newton_prover_chainio::policy_data::PolicyDataController;
5use newton_prover_core::{
6 config::NewtonAvsConfig,
7 newton_policy_data::INewtonPolicyData,
8 utils::chain::{get_block_time_ms, get_chain_id},
9};
10use serde_json::Value;
11use std::path::PathBuf;
12use tracing::{self, info};
13
14use crate::{commands::utils, config::NewtonCliConfig};
15
16#[derive(Debug, Parser)]
18#[command(name = "policy-data")]
19pub struct PolicyDataCommand {
20 #[command(subcommand)]
21 pub subcommand: PolicyDataSubcommand,
22}
23
24#[derive(Debug, Subcommand)]
25pub enum PolicyDataSubcommand {
26 Deploy(DeployCommand),
28 Simulate(SimulateCommand),
30}
31
32#[derive(Debug, Parser)]
34pub struct SimulateCommand {
35 #[arg(long)]
37 wasm_file: PathBuf,
38
39 #[arg(long)]
41 input_json: String,
42}
43
44#[derive(Debug, Parser)]
46pub struct DeployCommand {
47 #[arg(long, env = "PRIVATE_KEY")]
48 private_key: Option<String>,
49
50 #[arg(long, env = "RPC_URL")]
51 rpc_url: Option<String>,
52
53 #[arg(long, default_value = "policy-files/policy_cids.json")]
54 policy_cids: PathBuf,
55}
56
57impl DeployCommand {
58 async fn seconds_to_blocks(rpc_url: &str, seconds: u32) -> Result<u32> {
60 let block_time_ms = get_block_time_ms(rpc_url).await?;
61 let block_time_seconds = block_time_ms / 1000;
62
63 if block_time_seconds == 0 {
64 return Err(eyre::eyre!("Block time is zero, cannot convert seconds to blocks"));
65 }
66
67 let blocks = (seconds as u64 / block_time_seconds) as u32;
68 tracing::info!(
69 "Converting {} seconds to blocks: block_time={}ms ({}s), result={} blocks",
70 seconds,
71 block_time_ms,
72 block_time_seconds,
73 blocks
74 );
75
76 Ok(blocks)
77 }
78
79 async fn get_task_generator_address(rpc_url: &str) -> Result<Address> {
86 let chain_id = get_chain_id(rpc_url).await;
87 let task_generator_address = match chain_id {
88 31337 | 1 => "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
89 _ => "0xD45062003a4626a532F30A4596aB253c45AE0647", };
91 task_generator_address
92 .parse()
93 .map_err(|e| eyre::eyre!("Failed to parse task generator address: {}", e))
94 }
95
96 async fn deploy_policy_data(
102 private_key: &str,
103 rpc_url: &str,
104 wasm_cid: &str,
105 wasm_args_cid: &str,
106 policy_data_metadata_cid: &str,
107 expire_after_blocks: u32,
108 ) -> Result<Address> {
109 let controller = PolicyDataController::new(private_key.to_string(), rpc_url.to_string());
110
111 tracing::info!(
112 "Deploying policy data:\n wasmCid: {}\n wasmArgs: {}\n metadataCid: {}\n expireAfter: {} blocks \n",
113 wasm_cid,
114 wasm_args_cid,
115 policy_data_metadata_cid,
116 expire_after_blocks
117 );
118
119 let (_receipt, policy_data_address) = controller
120 .deploy_policy_data(
121 wasm_cid.to_string(),
122 wasm_args_cid.to_string(),
123 expire_after_blocks,
124 policy_data_metadata_cid.to_string(),
125 )
126 .await
127 .map_err(|e| eyre::eyre!("Failed to deploy policy data: {}", e))?;
128
129 tracing::info!("Policy data deployed successfully at address: {}", policy_data_address);
130
131 Ok(policy_data_address)
132 }
133
134 async fn set_attestation_info(
143 private_key: &str,
144 rpc_url: &str,
145 policy_data_address: Address,
146 attester_address: Address,
147 ) -> Result<()> {
148 let controller = PolicyDataController::new(private_key.to_string(), rpc_url.to_string());
149
150 let task_generator_address = Self::get_task_generator_address(rpc_url).await?;
152
153 let attesters = vec![attester_address, task_generator_address];
155
156 let attestation_info = INewtonPolicyData::AttestationInfo {
158 attesters,
159 attestationType: 0u8, verifier: Address::ZERO,
161 verificationKey: FixedBytes::ZERO,
162 };
163
164 tracing::info!(
165 "Setting attestation info on policy data {} with attesters: {:?}",
166 policy_data_address,
167 attestation_info.attesters
168 );
169
170 controller
171 .set_attestation_info(policy_data_address, attestation_info)
172 .await
173 .map_err(|e| eyre::eyre!("Failed to set attestation info: {}", e))?;
174
175 tracing::info!(
176 "Attestation info set successfully on policy data: {}",
177 policy_data_address
178 );
179
180 Ok(())
181 }
182
183 pub async fn execute(self: Box<Self>, _config: NewtonAvsConfig<NewtonCliConfig>) -> eyre::Result<()> {
185 let private_key = self
187 .private_key
188 .ok_or_else(|| eyre::eyre!("private_key is required (use --private-key or PRIVATE_KEY env var)"))?;
189
190 let rpc_url = self
191 .rpc_url
192 .ok_or_else(|| eyre::eyre!("rpc_url is required (use --rpc-url or RPC_URL env var)"))?;
193
194 let json_content = std::fs::read_to_string(&self.policy_cids)
196 .with_context(|| format!("Failed to read policy_cids.json: {:?}", self.policy_cids))?;
197 let json: Value = serde_json::from_str(&json_content)
198 .with_context(|| format!("Failed to parse policy_cids.json: {:?}", self.policy_cids))?;
199
200 let wasm_cid = json.get("wasmCid").and_then(|v| v.as_str()).unwrap_or("");
202 let wasm_args_cid = json.get("wasmArgs").and_then(|v| v.as_str()).unwrap_or("");
203 let policy_data_metadata_cid = json.get("policyDataMetadataCid").and_then(|v| v.as_str()).unwrap_or("");
204 let attester = json.get("attester").and_then(|v| v.as_str()).unwrap_or("");
205 let attester_address: Address = attester.parse().unwrap_or(Address::ZERO);
206
207 let expire_after_blocks = Self::seconds_to_blocks(&rpc_url, 300).await?;
210
211 let policy_data_address = Self::deploy_policy_data(
213 &private_key,
214 &rpc_url,
215 wasm_cid,
216 wasm_args_cid,
217 policy_data_metadata_cid,
218 expire_after_blocks,
219 )
220 .await?;
221
222 tracing::info!("Policy data deployment completed! Setting attestation info...");
223 Self::set_attestation_info(&private_key, &rpc_url, policy_data_address, attester_address).await?;
225
226 tracing::info!("Successfully deployed policy data and set attestation");
227 tracing::info!("Policy Data Address: {}", policy_data_address);
228
229 Ok(())
230 }
231}
232
233impl SimulateCommand {
234 pub async fn execute(self: Box<Self>, config: NewtonAvsConfig<NewtonCliConfig>) -> eyre::Result<()> {
236 info!("Executing WASM simulation...");
237 let output = utils::execute_wasm(self.wasm_file, self.input_json, config).await?;
238 info!("WASM simulation output: {}", output);
239 Ok(())
240 }
241}
242
243impl PolicyDataCommand {
244 pub async fn execute(self: Box<Self>, config: NewtonAvsConfig<NewtonCliConfig>) -> eyre::Result<()> {
246 match self.subcommand {
247 PolicyDataSubcommand::Deploy(command) => {
248 Box::new(command).execute(config).await?;
249 }
250 PolicyDataSubcommand::Simulate(command) => {
251 Box::new(command).execute(config).await?;
252 }
253 }
254 Ok(())
255 }
256}