use cw_client::{GrpcClient, CwClient}; use quartz_tcbinfo_msgs::{QueryMsg, ExecuteMsg}; use quoted_string::strip_dquotes; use anyhow::{anyhow, Result}; use quoted_string::test_utils::TestSpec; use quoted_string::to_content; use reqwest::Url; use serde_json::{json, Value}; use std::env; use tendermint::chain::id::Id; type Fmspc = String; type Update = String; const TCB_SIGNER: &str = include_str!("../tcb_signer.pem"); async fn get_tcbinfo(fmspc: Fmspc, update: Update) -> String { let url = format!("https://api.trustedservices.intel.com/sgx/certification/v4/tcb?fmspc={fmspc}&update={update}"); let body: String = reqwest::get(url) .await .expect("url retrieval failed") .text() .await .expect("could not read https response"); body } async fn get_fmspc_list() -> Vec { let body: String = reqwest::get("https://api.trustedservices.intel.com/sgx/certification/v4/fmspcs") .await .expect("url retrieval failed") .text() .await .expect("could not read https response"); let fmspc_data: Vec = serde_json::from_str(&body).expect("could not convert to JSON"); let mut fmspc_list: Vec = Vec::new(); for item in fmspc_data.iter() { let fmspc: String = format!("{}", item["fmspc"]); fmspc_list.push(strip_dquotes(&fmspc).unwrap().to_string()); } fmspc_list } async fn upsert_tcbinfo(url: &str, contract_addr: &str, chain_id : Id, sender: &str, gas: u64, fees: &str) -> Result<(), &'static str> { let network = Url::parse(url).expect("couldn't parse network URL"); let skey = hex::decode(sk).expect("couldn't read signing key") .as_slice() .try_into() .map_err(|e| anyhow!("failed to read/parse sk: {}", e)).expect("couldn't extract result value"); let client = CliClient::new(network); let fmspc_list = get_fmspc_list().await; for fmspc in fmspc_list { let tcbinfo_from_api = get_tcbinfo(fmspc.clone(), "standard".to_string()).await; // assert!(verify_signature(tcbinfo.clone(), key)); let contract_address = contract_addr .parse() .expect("failed to parse contract address"); let query_msg = QueryMsg::GetTcbInfo { fmspc: fmspc.clone() }; let tcbinfo_on_chain = { if let Ok(res) = client.query_smart::(&contract_address, json!(query_msg)).await { to_content::(&res["data"]["tcb_info"].to_string()).unwrap().to_string() } else { "".to_string() } }; if tcbinfo_on_chain != tcbinfo_from_api { println!("updating on-chain TCBInfo for FMSPC: {fmspc}"); let execute_msg = ExecuteMsg { tcb_info: tcbinfo_from_api.to_string(), certificate: TCB_SIGNER.to_string(), time: None, }; let res = client .tx_execute( &contract_address, &chain_id, gas, sender, json!(execute_msg), fees ) .await; println!("{res:?}"); std::thread::sleep(std::time::Duration::from_secs(5)); } else { println!("TCBInfo for FMSPC: {fmspc} up to date") } } Ok(()) } #[tokio::main] pub async fn main() { let args: Vec = env::args().collect(); let url = &args[1]; let chain_id = &args[2]; let contract_address : &str = &args[3]; let sender: &str = &args[4]; let gas: &u64 = &args[5].parse().expect("gas must be a u64 value"); let fees: &str = &args[6]; let sk: &str = &args[7]; upsert_tcbinfo(url, contract_address, Id::try_from(chain_id.clone()).expect("invalid chain id"), sender, *gas, fees).await.expect("TCBInfo update failed"); } /*let url =; let chain_id = tendermint::chain::id::Id::try_from("pion-1").expect("invalid chain id"); contract_address = ; let sender = ; gas = 1000000, fees = , */