mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 15:13:56 +02:00

This PR introduces TEE Prover continuous mode with attestation policies. Attestation policies are a set of criteria that determine whether an SGX attestation should be considered valid or invalid. In practice, this means checking against a specified set of mrsigners, mrenclaves, and TCB levels. If the attestation’s mrenclave/mrsigner/TCB levels matches those in the provided --sgx-mrenclaves/--sgx-mrsigners/--sgx-allowed-tcb-levels, we treat the attestation as successfully verified. Otherwise, the attestation is considered invalid. The --continuous mode for the TEE Prover allows it to run continuously, verifying new batches exposed by the node's RPC API in real-time. To try it out, run the following commands: $ nix build -L .#container-verify-era-proof-attestation-sgx $ export IMAGE_TAG=$(docker load -i result | grep -Po 'Loaded image.*: \K.*') $ docker run -i --init --rm $IMAGE_TAG --continuous 11505 --rpc https://sepolia.era.zksync.dev --sgx-allowed-tcb-levels Ok,SwHardeningNeeded --log-level debug $ docker run -i --init --rm $IMAGE_TAG --batch 11509 --rpc https://sepolia.era.zksync.dev --sgx-allowed-tcb-levels Ok,SwHardeningNeeded --log-level debug
123 lines
4.5 KiB
Rust
123 lines
4.5 KiB
Rust
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright (c) 2023-2024 Matter Labs
|
|
|
|
use anyhow::{anyhow, Result};
|
|
use clap::{ArgGroup, Args, Parser};
|
|
use std::time::Duration;
|
|
use teepot::sgx::{parse_tcb_levels, EnumSet, TcbLevel};
|
|
use tracing_subscriber::filter::LevelFilter;
|
|
use url::Url;
|
|
use zksync_basic_types::L1BatchNumber;
|
|
use zksync_types::L2ChainId;
|
|
|
|
#[derive(Parser, Debug, Clone)]
|
|
#[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)]
|
|
#[clap(group(
|
|
ArgGroup::new("mode")
|
|
.required(true)
|
|
.args(&["batch_range", "continuous"]),
|
|
))]
|
|
pub struct Arguments {
|
|
#[clap(long, default_value_t = LevelFilter::WARN, value_parser = LogLevelParser)]
|
|
pub log_level: LevelFilter,
|
|
/// The batch number or range of batch numbers to verify the attestation and signature (e.g.,
|
|
/// "42" or "42-45"). This option is mutually exclusive with the `--continuous` mode.
|
|
#[clap(short = 'n', long = "batch", value_parser = parse_batch_range)]
|
|
pub batch_range: Option<(L1BatchNumber, L1BatchNumber)>,
|
|
/// Continuous mode: keep verifying new batches until interrupted. This option is mutually
|
|
/// exclusive with the `--batch` option.
|
|
#[clap(long, value_name = "FIRST_BATCH")]
|
|
pub continuous: Option<L1BatchNumber>,
|
|
/// URL of the RPC server to query for the batch attestation and signature.
|
|
#[clap(long = "rpc")]
|
|
pub rpc_url: Url,
|
|
/// Chain ID of the network to query.
|
|
#[clap(long = "chain", default_value_t = L2ChainId::default().as_u64())]
|
|
pub chain_id: u64,
|
|
/// Rate limit between requests in milliseconds.
|
|
#[clap(long, default_value = "0", value_parser = parse_duration)]
|
|
pub rate_limit: Duration,
|
|
/// Criteria for valid attestation policy. Invalid proofs will be rejected.
|
|
#[clap(flatten)]
|
|
pub attestation_policy: AttestationPolicyArgs,
|
|
}
|
|
|
|
/// Attestation policy implemented as a set of criteria that must be met by SGX attestation.
|
|
#[derive(Args, Debug, Clone)]
|
|
pub struct AttestationPolicyArgs {
|
|
/// Comma-separated list of allowed hex-encoded SGX mrsigners. Batch attestation must consist of
|
|
/// one of these mrsigners. If the list is empty, the mrsigner check is skipped.
|
|
#[arg(long = "mrsigners")]
|
|
pub sgx_mrsigners: Option<String>,
|
|
/// Comma-separated list of allowed hex-encoded SGX mrenclaves. Batch attestation must consist
|
|
/// of one of these mrenclaves. If the list is empty, the mrenclave check is skipped.
|
|
#[arg(long = "mrenclaves")]
|
|
pub sgx_mrenclaves: Option<String>,
|
|
/// Comma-separated list of allowed TCB levels. If the list is empty, the TCB level check is
|
|
/// skipped. Allowed values: Ok, ConfigNeeded, ConfigAndSwHardeningNeeded, SwHardeningNeeded,
|
|
/// OutOfDate, OutOfDateConfigNeeded.
|
|
#[arg(long, value_parser = parse_tcb_levels, default_value = "Ok")]
|
|
pub sgx_allowed_tcb_levels: EnumSet<TcbLevel>,
|
|
}
|
|
|
|
fn parse_batch_range(s: &str) -> Result<(L1BatchNumber, L1BatchNumber)> {
|
|
let parse = |s: &str| {
|
|
s.parse::<u32>()
|
|
.map(L1BatchNumber::from)
|
|
.map_err(|e| anyhow!(e))
|
|
};
|
|
match s.split_once('-') {
|
|
Some((start, end)) => {
|
|
let (start, end) = (parse(start)?, parse(end)?);
|
|
if start > end {
|
|
Err(anyhow!(
|
|
"Start batch number ({}) must be less than or equal to end batch number ({})",
|
|
start,
|
|
end
|
|
))
|
|
} else {
|
|
Ok((start, end))
|
|
}
|
|
}
|
|
None => {
|
|
let batch_number = parse(s)?;
|
|
Ok((batch_number, batch_number))
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parse_duration(s: &str) -> Result<Duration> {
|
|
let millis = s.parse()?;
|
|
Ok(Duration::from_millis(millis))
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct LogLevelParser;
|
|
|
|
impl clap::builder::TypedValueParser for LogLevelParser {
|
|
type Value = LevelFilter;
|
|
|
|
fn parse_ref(
|
|
&self,
|
|
cmd: &clap::Command,
|
|
arg: Option<&clap::Arg>,
|
|
value: &std::ffi::OsStr,
|
|
) -> Result<Self::Value, clap::Error> {
|
|
clap::builder::TypedValueParser::parse(self, cmd, arg, value.to_owned())
|
|
}
|
|
|
|
fn parse(
|
|
&self,
|
|
cmd: &clap::Command,
|
|
arg: Option<&clap::Arg>,
|
|
value: std::ffi::OsString,
|
|
) -> std::result::Result<Self::Value, clap::Error> {
|
|
use std::str::FromStr;
|
|
let p = clap::builder::PossibleValuesParser::new([
|
|
"off", "error", "warn", "info", "debug", "trace",
|
|
]);
|
|
let v = p.parse(cmd, arg, value)?;
|
|
|
|
Ok(LevelFilter::from_str(&v).unwrap())
|
|
}
|
|
}
|