mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 23:23:57 +02:00
feat(verify-era-proof-attestation): continuous mode with attestation policies
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
This commit is contained in:
parent
dd2a0304be
commit
4fcaaa7398
8 changed files with 702 additions and 202 deletions
123
bin/verify-era-proof-attestation/src/args.rs
Normal file
123
bin/verify-era-proof-attestation/src/args.rs
Normal file
|
@ -0,0 +1,123 @@
|
|||
// 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())
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue