Skip to content

Commit

Permalink
new options kalypso-cli
Browse files Browse the repository at this point in the history
  • Loading branch information
akshay111meher committed Nov 4, 2024
1 parent b347f1c commit 1d1f5b2
Show file tree
Hide file tree
Showing 7 changed files with 493 additions and 0 deletions.
4 changes: 4 additions & 0 deletions kalypso-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ edition = "2021"

[dependencies]
async-trait = "0.1.64"
bytes = "1.0"
bindings = { path = "../bindings", package = "foundry-contracts" }
dotenv = "0.15.0"
dialoguer = "0.10.3"
env_logger = "0.11"
futures = "0.3"
ethers = { version = "2", features = ["rustls"] }
hex = "0.4.3"
log = "0.4"
reqwest = { version = "0.11", features = ["stream"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sha3 = "0.10"
tokio = { version = "1.15.0", features = ["full"] }
url = "2.3.1"
86 changes: 86 additions & 0 deletions kalypso-cli/src/common_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,89 @@ impl CommonDeps {
})
}
}

pub struct MarketCreateInfo {
pub private_key_signer: LocalWallet,
pub proof_marketplace: bindings::proof_marketplace::ProofMarketplace<
SignerMiddleware<Provider<Http>, LocalWallet>,
>,
pub prover_pcrs: Vec<u8>,
pub ivs_pcrs: Vec<u8>,
pub payment_token: bindings::ierc20::IERC20<SignerMiddleware<Provider<Http>, LocalWallet>>,
pub verifier_wrapper: Address,
}

impl CommonDeps {
pub fn market_create_info(
config: &std::collections::HashMap<String, String>,
) -> Result<MarketCreateInfo, String> {
get_config_ref!(config, "private_key", private_key);
get_config_ref!(config, "rpc_url", rpc_url);
get_config_ref!(config, "proof_marketplace", proof_marketplace_address);
get_config_ref!(config, "chain_id", chain_id);
get_config_ref!(config, "prover_image_id", prover_pcrs);
get_config_ref!(config, "verification_image_id", ivs_pcrs);
get_config_ref!(config, "verifier_wrapper", verifier_wrapper);
get_config_ref!(config, "payment_token", payment_token);

let (proof_marketplace, private_key_signer) = get_proof_marketplace_instance(
private_key,
chain_id,
proof_marketplace_address,
rpc_url,
)?;

let prover_pcrs = {
let trimmed_key = if prover_pcrs.starts_with("0x") || prover_pcrs.starts_with("0X") {
&prover_pcrs[2..]
} else {
prover_pcrs
};
hex::decode(trimmed_key).map_err(|e| format!("Invalid Prover PCRs: {}", e))?
};

let ivs_pcrs = {
let trimmed_key = if ivs_pcrs.starts_with("0x") || ivs_pcrs.starts_with("0X") {
&ivs_pcrs[2..]
} else {
ivs_pcrs
};
hex::decode(trimmed_key).map_err(|e| format!("Invalid IVS PCRs: {}", e))?
};

let (payment_token, _) =
get_token_instance(private_key, chain_id, &payment_token, rpc_url)?;

let verifier_wrapper = verifier_wrapper
.parse::<Address>()
.map_err(|e| format!("Invalid Verifier Wrapper Address: {}", e))?;

Ok(MarketCreateInfo {
private_key_signer,
proof_marketplace,
prover_pcrs,
ivs_pcrs,
verifier_wrapper,
payment_token,
})
}
}

pub struct ComputePcrsInfo {
pub attestation_utility: String,
pub attestation_verifier: String,
}

impl CommonDeps {
pub fn compute_pcrs_info(
config: &std::collections::HashMap<String, String>,
) -> Result<ComputePcrsInfo, String> {
get_config_ref!(config, "attestation_server_url", attestation_server_url);
get_config_ref!(config, "attestion_verifier_url", attestion_verifier_url);

Ok(ComputePcrsInfo {
attestation_utility: attestation_server_url.to_string(),
attestation_verifier: attestion_verifier_url.to_string(),
})
}
}
58 changes: 58 additions & 0 deletions kalypso-cli/src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,42 @@
"prompt": "Enter the staking token address",
"secret": false,
"env_var": "STAKING_TOKEN"
},
{
"field": "payment_token",
"prompt": "Enter the payment token address",
"secret": false,
"env_var": "PAYMENT_TOKEN"
},
{
"field": "prover_image_id",
"prompt": "Enter the prover image pcrs",
"secret": false,
"env_var": "PROVER_IMAGE_PCRS"
},
{
"field": "verification_image_id",
"prompt": "Enter the input_verification image pcrs",
"secret": false,
"env_var": "IVS_IMAGE_PCRS"
},
{
"field": "verifier_wrapper",
"prompt": "Enter Proof Verifier Contract Address (refer to Kalypso Standard Wrapper Contract)",
"secret": false,
"env_var": "VERIFIER_WRAPPER_ADDRESS"
},
{
"field": "attestation_server_url",
"prompt": "Enter Attestation Server URL",
"secret": false,
"env_var": "ATTESTATION_UTILITY_URL"
},
{
"field": "attestion_verifier_url",
"prompt": "Enter Attestation VERIFIER URL",
"secret": false,
"env_var": "ATTESTATION_VERIFIER_URL"
}
],
"operations": [
Expand Down Expand Up @@ -147,6 +183,28 @@
"staking_address",
"stake"
]
},
{
"name": "Create Marketplace",
"description": "Create a new market place in kalypso",
"required_prompts": [
"private_key",
"rpc_url",
"chain_id",
"proof_marketplace",
"prover_image_id",
"verification_image_id",
"verifier_wrapper",
"payment_token"
]
},
{
"name": "Compute PCRs",
"description": "Compute PCRs of a given enclave from it's attestation server",
"required_prompts": [
"attestation_server_url",
"attestion_verifier_url"
]
}
]
}
169 changes: 169 additions & 0 deletions kalypso-cli/src/operations/compute_pcrs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
use crate::common_deps::CommonDeps;
use crate::operations::Operation;
use async_trait::async_trait;
use ethers::types::U256;
use serde::Deserialize;
use std::collections::HashMap;

pub struct ComputePcrs;

#[async_trait]
impl Operation for ComputePcrs {
async fn execute(&self, config: HashMap<String, String>) -> Result<(), String> {
let compute_pcrs_info = CommonDeps::compute_pcrs_info(&config)?;
let attestation_stream = build_attestation(&compute_pcrs_info.attestation_utility, false)
.await
.map_err(|_| "Failed Building Attestations.".to_string())?;

let attestation_data: Vec<u8> = attestation_stream
.fold(Vec::new(), |mut acc, item| async {
match item {
Ok(bytes) => {
acc.extend_from_slice(&bytes);
acc
}
Err(e) => {
println!("Error while receiving data: {}", e);
acc
}
}
})
.await;

println!("Attestation Data Length: {}", attestation_data.len());

let image_id = get_image_id(
&compute_pcrs_info.attestation_verifier,
attestation_data,
false,
)
.await
.map_err(|_| "Failed Computing Image ID".to_string())?;

print!("Image ID: \n{}", image_id);

println!("\n\nSave Image For Further");

Ok(())
}
}

use bytes::Bytes;
use futures::{Stream, StreamExt};
use hex::decode;
use reqwest::Client;
use std::error::Error;

pub async fn build_attestation(
base_url: &str,
print_logs: bool,
) -> Result<impl Stream<Item = Result<Bytes, reqwest::Error>>, Box<dyn Error>> {
let attestation_end_point = utility_url(base_url, "/attestation/raw");

if print_logs {
println!("build attestation {}", attestation_end_point);
}

let client = Client::new();
let response = client.get(&attestation_end_point).send().await?;

// Check if the response status is successful (2xx)
if !response.status().is_success() {
println!("status code: {}", response.status());
return Err("failed building the attestation".into());
}

// Get the response body as a stream of bytes
let stream = response.bytes_stream();

Ok(stream)
}

fn utility_url(base_url: &str, path: &str) -> String {
format!("{}{}", base_url, path)
}

#[derive(Debug, Deserialize)]
struct AttestationVerifierResponse {
#[allow(unused)]
secp256k1_public: String,
#[allow(unused)]
signature: String,
#[allow(unused)]
pcr0: String,
#[allow(unused)]
pcr1: String,
#[allow(unused)]
pcr2: String,
#[allow(unused)]
timestamp: u64,
}

use ethers::abi::{encode, Token};

// Function to get attestation by sending attestation_data to the verifier
pub async fn get_image_id(
base_url: &str,
attestation_data: Vec<u8>,
print_logs: bool,
) -> Result<String, Box<dyn Error>> {
// Construct the verify endpoint URL
let verify_endpoint = utility_url(base_url, "/verify/raw");

if print_logs {
println!("Sending attestation data to {}", verify_endpoint);
}

let client = Client::new();
let response = client
.post(&verify_endpoint)
.header("Content-Type", "application/octet-stream")
.body(attestation_data)
.send()
.await?;

if !response.status().is_success() {
if print_logs {
println!(
"Attestation verifier responded with status: {}",
response.status()
);
}
return Err("Failed to verify attestation".into());
}

let verifier_response: AttestationVerifierResponse = response.json().await?;

if print_logs {
println!("Fetched attestation successfully");
println!("Verifier response: {:?}", verifier_response);
}

// Extract and process secp256k1_public
let ecies_pubkey = format!("0x{}", verifier_response.secp256k1_public);
if ecies_pubkey.len() != 130 {
return Err("secp pub key length incorrect".into());
}

// Decode hex strings to bytes
let signature_bytes = decode(&verifier_response.signature.trim_start_matches("0x"))?;
let pcr0_bytes = decode(&verifier_response.pcr0.trim_start_matches("0x"))?;
let pcr1_bytes = decode(&verifier_response.pcr1.trim_start_matches("0x"))?;
let pcr2_bytes = decode(&verifier_response.pcr2.trim_start_matches("0x"))?;

let _timestamp_u256 = U256::from(verifier_response.timestamp);
let _signature_vec = signature_bytes;
let _ecies_pubkey_vec = decode(&verifier_response.secp256k1_public.trim_start_matches("0x"))?;

let pcr0_vec = pcr0_bytes;
let pcr1_vec = pcr1_bytes;
let pcr2_vec = pcr2_bytes;

let encoded = encode(&[
Token::Bytes(pcr0_vec),
Token::Bytes(pcr1_vec),
Token::Bytes(pcr2_vec),
]);

Ok(format!("0x{}", hex::encode(encoded)))
}
Loading

0 comments on commit 1d1f5b2

Please sign in to comment.