Skip to content

Commit

Permalink
Better tracing and logging
Browse files Browse the repository at this point in the history
  • Loading branch information
pbeza committed Sep 9, 2024
1 parent bbe0d83 commit 1f5b731
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 62 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions bin/verify-era-proof-attestation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ secp256k1.workspace = true
serde.workspace = true
teepot.workspace = true
tokio.workspace = true
tracing-log.workspace = true
tracing-subscriber.workspace = true
tracing.workspace = true
url.workspace = true
zksync_basic_types.workspace = true
zksync_types.workspace = true
Expand Down
19 changes: 17 additions & 2 deletions bin/verify-era-proof-attestation/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,28 @@ mod client;
mod proof;
mod verification;

use anyhow::Result;
use anyhow::{Context, Result};
use args::Arguments;
use clap::Parser;
use client::MainNodeClient;
use proof::{GetProofsRequest, GetProofsResponse};
use reqwest::Client;
use tokio::time::sleep;
use verification::verify_proof;
use tracing::info;
use tracing_log::LogTracer;
use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};

use crate::verification::verify_proof;

#[tokio::main]
async fn main() -> Result<()> {
LogTracer::init().context("Failed to set logger")?;

let subscriber = Registry::default()
.with(EnvFilter::from_default_env())
.with(fmt::layer().with_writer(std::io::stderr));
tracing::subscriber::set_global_default(subscriber)?;

let args = Arguments::parse();
let node_client = MainNodeClient::new(args.rpc_url.clone(), args.chain_id)?;
let http_client = Client::new();
Expand All @@ -40,6 +51,10 @@ async fn main() -> Result<()> {
.into_iter()
.filter(|proof| proof.tee_type.to_lowercase() == "sgx")
{
info!(
"Verifying batch #{} proved at {}",
proof.l1_batch_number, proof.proved_at
);
verify_proof(&args.attestation_criteria, &node_client, &proof).await?;
}

Expand Down
116 changes: 56 additions & 60 deletions bin/verify-era-proof-attestation/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use teepot::{
client::TcbLevel,
sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
};
use tracing::{debug, info, warn};
use zksync_basic_types::{L1BatchNumber, H256};

use crate::client::JsonRpcClient;
Expand All @@ -18,10 +19,6 @@ pub async fn verify_proof(
node_client: &impl JsonRpcClient,
proof: &Proof,
) -> Result<()> {
println!(
"Verifying batch #{} proved at {}",
proof.l1_batch_number, proof.proved_at
);
let quote_verification_result = verify_attestation_quote(&proof.attestation)?;
print_quote_verification_summary(&quote_verification_result);
if check_if_quote_is_matching_acceptance_criteria(
Expand All @@ -31,45 +28,63 @@ pub async fn verify_proof(
let public_key = PublicKey::from_slice(
&quote_verification_result.quote.report_body.reportdata[..PUBLIC_KEY_SIZE],
)?;
println!("Public key from attestation quote: {}", public_key);
debug!("Public key from attestation quote: {}", public_key);
let root_hash = node_client
.get_root_hash(L1BatchNumber(proof.l1_batch_number))
.await?;
println!("Root hash: {}", root_hash);
debug!("Root hash: {}", root_hash);
verify_signature(&proof.signature, public_key, root_hash)?;
}
println!();
Ok(())
}

pub fn verify_signature(signature: &[u8], public_key: PublicKey, root_hash: H256) -> Result<()> {
fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result<QuoteVerificationResult> {
debug!(
"Verifying quote ({} bytes)...",
attestation_quote_bytes.len()
);
let collateral =
tee_qv_get_collateral(attestation_quote_bytes).context("Failed to get collateral")?;
let unix_time: i64 = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_secs() as _;
verify_quote_with_collateral(attestation_quote_bytes, Some(&collateral), unix_time)
.context("Failed to verify quote with collateral")
}

fn print_quote_verification_summary(quote_verification_result: &QuoteVerificationResult) {
let QuoteVerificationResult {
collateral_expired,
result,
quote,
advisories,
..
} = quote_verification_result;
if *collateral_expired {
warn!("Freshly fetched collateral expired");
}
let tcblevel = TcbLevel::from(*result);
for advisory in advisories {
info!("\tInfo: Advisory ID: {advisory}");
}
info!("Quote verification result: {}", tcblevel);
info!("mrsigner: {}", hex::encode(quote.report_body.mrsigner));
info!("mrenclave: {}", hex::encode(quote.report_body.mrenclave));
info!("reportdata: {}", hex::encode(quote.report_body.reportdata));
}

fn verify_signature(signature: &[u8], public_key: PublicKey, root_hash: H256) -> Result<()> {
let signature = Signature::from_compact(signature)?;
let root_hash_msg = Message::from_digest_slice(&root_hash.0)?;
if signature.verify(&root_hash_msg, &public_key).is_ok() {
println!("Signature verified successfully");
info!("Signature verified successfully");
} else {
println!("Failed to verify signature");
warn!("Failed to verify signature");
}
Ok(())
}

pub fn check_criteria(criteria: Option<&str>, actual_value: &[u8], field_name: &str) -> bool {
if let Some(valid_values) = criteria {
let valid_values: Vec<&str> = valid_values.split(',').collect();
let actual_value = hex::encode(actual_value);
if !valid_values.contains(&actual_value.as_str()) {
println!(
"Quote verification failed: {} mismatch (expected one of: {:?}, actual: {})",
field_name, valid_values, actual_value
);
return false;
}
println!("{}: {}", field_name, actual_value);
}
true
}

pub fn check_if_quote_is_matching_acceptance_criteria(
fn check_if_quote_is_matching_acceptance_criteria(
attestation_criteria: &AttestationArgs,
quote_verification_result: &QuoteVerificationResult<'_>,
) -> bool {
Expand All @@ -78,7 +93,7 @@ pub fn check_if_quote_is_matching_acceptance_criteria(

if let Some(sgx_allowed_tcb_levels) = attestation_criteria.sgx_allowed_tcb_levels.as_ref() {
if !sgx_allowed_tcb_levels.contains(tcblevel) {
println!(
warn!(
"Quote verification failed: TCB level mismatch (expected one of: {:?}, actual: {})",
sgx_allowed_tcb_levels, tcblevel
);
Expand All @@ -97,37 +112,18 @@ pub fn check_if_quote_is_matching_acceptance_criteria(
)
}

fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result<QuoteVerificationResult> {
println!(
"Verifying quote ({} bytes)...",
attestation_quote_bytes.len()
);
let collateral =
tee_qv_get_collateral(attestation_quote_bytes).context("Failed to get collateral")?;
let unix_time: i64 = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_secs() as _;
verify_quote_with_collateral(attestation_quote_bytes, Some(&collateral), unix_time)
.context("Failed to verify quote with collateral")
}

fn print_quote_verification_summary(quote_verification_result: &QuoteVerificationResult) {
let QuoteVerificationResult {
collateral_expired,
result,
quote,
advisories,
..
} = quote_verification_result;
if *collateral_expired {
println!("Freshly fetched collateral expired");
}
let tcblevel = TcbLevel::from(*result);
for advisory in advisories {
println!("\tInfo: Advisory ID: {advisory}");
fn check_criteria(criteria: Option<&str>, actual_value: &[u8], field_name: &str) -> bool {
if let Some(valid_values) = criteria {
let valid_values: Vec<&str> = valid_values.split(',').collect();
let actual_value = hex::encode(actual_value);
if !valid_values.contains(&actual_value.as_str()) {
warn!(
"Quote verification failed: {} mismatch (expected one of: {:?}, actual: {})",
field_name, valid_values, actual_value
);
return false;
}
warn!("{}: {}", field_name, actual_value);
}
println!("Quote verification result: {}", tcblevel);
println!("mrsigner: {}", hex::encode(quote.report_body.mrsigner));
println!("mrenclave: {}", hex::encode(quote.report_body.mrenclave));
println!("reportdata: {}", hex::encode(quote.report_body.reportdata));
true
}

0 comments on commit 1f5b731

Please sign in to comment.