use sp1_prover::{HashableKey, SP1VerifyingKey};
use crate::SP1VerificationError;
pub mod api;
pub mod client;
pub const SP1_TEE_VERSION: u32 = 2;
pub async fn get_tee_signers() -> Result<Vec<alloy_primitives::Address>, client::ClientError> {
let client = client::Client::default();
client.get_signers().await
}
pub fn verify_tee_proof(
signers: &[alloy_primitives::Address],
tee_proof: &[u8],
vkey: &SP1VerifyingKey,
public_values: &[u8],
) -> Result<(), SP1VerificationError> {
if signers.is_empty() {
return Err(crate::SP1VerificationError::Other(anyhow::anyhow!(
"TEE integrity proof verification is enabled, but no TEE signers are provided"
)));
}
let mut bytes = Vec::new();
let version_hash =
alloy_primitives::keccak256(crate::network::tee::SP1_TEE_VERSION.to_le_bytes());
bytes.extend_from_slice(version_hash.as_ref());
bytes.extend_from_slice(&vkey.bytes32_raw());
let public_values_hash = alloy_primitives::keccak256(public_values);
bytes.extend_from_slice(public_values_hash.as_ref());
let message_digest = alloy_primitives::keccak256(&bytes);
let signature =
k256::ecdsa::Signature::from_bytes(tee_proof[5..69].into()).expect("Invalid signature");
let recovery_id =
k256::ecdsa::RecoveryId::from_byte(tee_proof[4] - 27).expect("Invalid recovery id");
let signer = k256::ecdsa::VerifyingKey::recover_from_prehash(
message_digest.as_ref(),
&signature,
recovery_id,
)
.unwrap();
let address = alloy_primitives::Address::from_public_key(&signer);
if signers.contains(&address) {
Ok(())
} else {
Err(crate::SP1VerificationError::Other(anyhow::anyhow!(
"Invalid TEE proof, signed by unknown address {address}",
)))
}
}