newton_cli/commands/
policy_data.rs1use alloy::primitives::{Address, FixedBytes};
2use clap::{Parser, Subcommand};
3use eyre::{Context, Result};
4use newton_prover_bindings::newton_policy_data::INewtonPolicyData;
5use newton_prover_chainio::policy_data::PolicyDataController;
6use newton_prover_config::NewtonAvsConfig;
7use newton_prover_core::io::chain::{get_block_time_ms, get_chain_id};
8use serde_json::Value;
9use std::path::PathBuf;
10use tracing;
11
12use crate::config::NewtonCliConfig;
13
14#[derive(Debug, Parser)]
16#[command(name = "policy-data")]
17pub struct PolicyDataCommand {
18 #[command(subcommand)]
19 pub subcommand: PolicyDataSubcommand,
20}
21
22#[derive(Debug, Subcommand)]
23pub enum PolicyDataSubcommand {
24 Deploy(DeployCommand),
26}
27
28#[derive(Debug, Parser)]
30pub struct DeployCommand {
31 #[arg(long, env = "PRIVATE_KEY")]
32 private_key: Option<String>,
33
34 #[arg(long, env = "RPC_URL")]
35 rpc_url: Option<String>,
36
37 #[arg(long, default_value = "policy-files/policy_cids.json")]
38 policy_cids: PathBuf,
39}
40
41impl DeployCommand {
42 async fn seconds_to_blocks(rpc_url: &str, seconds: u32) -> Result<u32> {
44 let block_time_ms = get_block_time_ms(rpc_url).await?;
45 let block_time_seconds = block_time_ms / 1000;
46
47 if block_time_seconds == 0 {
48 return Err(eyre::eyre!("Block time is zero, cannot convert seconds to blocks"));
49 }
50
51 let blocks = (seconds as u64 / block_time_seconds) as u32;
52 tracing::info!(
53 "Converting {} seconds to blocks: block_time={}ms ({}s), result={} blocks",
54 seconds,
55 block_time_ms,
56 block_time_seconds,
57 blocks
58 );
59
60 Ok(blocks)
61 }
62
63 async fn get_task_generator_address(rpc_url: &str) -> Result<Address> {
70 let chain_id = get_chain_id(rpc_url).await;
71 let task_generator_address = match chain_id {
72 31337 | 1 => "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
73 _ => "0xD45062003a4626a532F30A4596aB253c45AE0647", };
75 task_generator_address
76 .parse()
77 .map_err(|e| eyre::eyre!("Failed to parse task generator address: {}", e))
78 }
79
80 async fn deploy_policy_data(
86 private_key: &str,
87 rpc_url: &str,
88 wasm_cid: &str,
89 wasm_args_cid: &str,
90 policy_data_metadata_cid: &str,
91 expire_after_blocks: u32,
92 ) -> Result<Address> {
93 let controller = PolicyDataController::new(private_key.to_string(), rpc_url.to_string());
94
95 tracing::info!(
96 "Deploying policy data with wasmCid: {}, wasmArgs: {}, metadataCid: {}, expireAfter: {} blocks",
97 wasm_cid,
98 wasm_args_cid,
99 policy_data_metadata_cid,
100 expire_after_blocks
101 );
102
103 let (_receipt, policy_data_address) = controller
104 .deploy_policy_data(
105 wasm_cid.to_string(),
106 wasm_args_cid.to_string(),
107 expire_after_blocks,
108 policy_data_metadata_cid.to_string(),
109 )
110 .await
111 .map_err(|e| eyre::eyre!("Failed to deploy policy data: {}", e))?;
112
113 tracing::info!("Policy data deployed successfully at address: {}", policy_data_address);
114
115 Ok(policy_data_address)
116 }
117
118 async fn set_attestation_info(
127 private_key: &str,
128 rpc_url: &str,
129 policy_data_address: Address,
130 attester_address: Address,
131 ) -> Result<()> {
132 let controller = PolicyDataController::new(private_key.to_string(), rpc_url.to_string());
133
134 let task_generator_address = Self::get_task_generator_address(rpc_url).await?;
136
137 let attesters = vec![attester_address, task_generator_address];
139
140 let attestation_info = INewtonPolicyData::AttestationInfo {
142 attesters,
143 attestationType: 0u8, verifier: Address::ZERO,
145 verificationKey: FixedBytes::ZERO,
146 };
147
148 tracing::info!(
149 "Setting attestation info on policy data {} with attesters: {:?}",
150 policy_data_address,
151 attestation_info.attesters
152 );
153
154 controller
155 .set_attestation_info(policy_data_address, attestation_info)
156 .await
157 .map_err(|e| eyre::eyre!("Failed to set attestation info: {}", e))?;
158
159 tracing::info!(
160 "Attestation info set successfully on policy data: {}",
161 policy_data_address
162 );
163
164 Ok(())
165 }
166
167 pub async fn execute(self: Box<Self>, _config: NewtonAvsConfig<NewtonCliConfig>) -> eyre::Result<()> {
169 let private_key = self
171 .private_key
172 .ok_or_else(|| eyre::eyre!("private_key is required (use --private-key or PRIVATE_KEY env var)"))?;
173
174 let rpc_url = self
175 .rpc_url
176 .ok_or_else(|| eyre::eyre!("rpc_url is required (use --rpc-url or RPC_URL env var)"))?;
177
178 let json_content = std::fs::read_to_string(&self.policy_cids)
180 .with_context(|| format!("Failed to read policy_cids.json: {:?}", self.policy_cids))?;
181 let json: Value = serde_json::from_str(&json_content)
182 .with_context(|| format!("Failed to parse policy_cids.json: {:?}", self.policy_cids))?;
183
184 let wasm_cid = json.get("wasmCid").and_then(|v| v.as_str()).unwrap_or("");
186 let wasm_args_cid = json.get("wasmArgs").and_then(|v| v.as_str()).unwrap_or("");
187 let policy_data_metadata_cid = json.get("policyDataMetadataCid").and_then(|v| v.as_str()).unwrap_or("");
188 let attester = json.get("attester").and_then(|v| v.as_str()).unwrap_or("");
189 let attester_address: Address = attester.parse().unwrap_or(Address::ZERO);
190
191 let expire_after_blocks = Self::seconds_to_blocks(&rpc_url, 300).await?;
194
195 let policy_data_address = Self::deploy_policy_data(
197 &private_key,
198 &rpc_url,
199 wasm_cid,
200 wasm_args_cid,
201 policy_data_metadata_cid,
202 expire_after_blocks,
203 )
204 .await?;
205
206 tracing::info!("Policy data deployment completed!");
207 Self::set_attestation_info(&private_key, &rpc_url, policy_data_address, attester_address).await?;
209
210 tracing::info!("Successfully deployed policy data and set attestation");
211 tracing::info!("Policy Data Address: {}", policy_data_address);
212
213 Ok(())
214 }
215}
216
217impl PolicyDataCommand {
218 pub async fn execute(self: Box<Self>, config: NewtonAvsConfig<NewtonCliConfig>) -> eyre::Result<()> {
220 match self.subcommand {
221 PolicyDataSubcommand::Deploy(command) => {
222 Box::new(command).execute(config).await?;
223 }
224 }
225 Ok(())
226 }
227}