diff --git a/Cargo.lock b/Cargo.lock index 8bd5f7c..45b39a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -835,7 +835,7 @@ dependencies = [ [[package]] name = "cw-tee-mtcs" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git?branch=hu55a1n1/11-use-quartz#48508d739427bd3f2a983c8e8d4c6eb2e677aff2" +source = "git+ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git?branch=hu55a1n1/11-use-quartz#e2ce14cb275e9668739b63659535ea721f95b0ff" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2455,7 +2455,7 @@ dependencies = [ [[package]] name = "quartz-cw" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git?branch=hu55a1n1/11-use-quartz#48508d739427bd3f2a983c8e8d4c6eb2e677aff2" +source = "git+ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git?branch=hu55a1n1/11-use-quartz#e2ce14cb275e9668739b63659535ea721f95b0ff" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2475,6 +2475,7 @@ dependencies = [ "clap", "color-eyre", "cosmwasm-std", + "cw-proof", "cw-tee-mtcs", "ecies", "k256 0.13.3", @@ -2489,6 +2490,7 @@ dependencies = [ "serde_json", "tendermint 0.34.0", "tendermint-light-client", + "tm-stateless-verifier", "tokio", "tonic 0.11.0", "tonic-build", @@ -2530,7 +2532,7 @@ dependencies = [ [[package]] name = "quartz-tee-ra" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git?branch=hu55a1n1/11-use-quartz#48508d739427bd3f2a983c8e8d4c6eb2e677aff2" +source = "git+ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git?branch=hu55a1n1/11-use-quartz#e2ce14cb275e9668739b63659535ea721f95b0ff" dependencies = [ "cosmwasm-schema", "cosmwasm-std", diff --git a/enclaves/quartz/Cargo.toml b/enclaves/quartz/Cargo.toml index 4d88333..95df3d8 100644 --- a/enclaves/quartz/Cargo.toml +++ b/enclaves/quartz/Cargo.toml @@ -18,12 +18,14 @@ tendermint-light-client = "0.34.0" tonic = "0.11" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +cw-proof = { path = "../../utils/cw-proof" } cw-tee-mtcs = { git = "ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git", branch = "hu55a1n1/11-use-quartz" } mtcs = { git = "ssh://git@github.com/informalsystems/mtcs.git" } quartz-cw = { git = "ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git", branch = "hu55a1n1/11-use-quartz" } quartz-proto = { path = "../../utils/quartz-proto" } quartz-relayer = { path = "../../utils/quartz-relayer" } quartz-tee-ra = { git = "ssh://git@github.com/informalsystems/bisenzone-cw-mvp.git", branch = "hu55a1n1/11-use-quartz" } +tm-stateless-verifier = { path = "../../utils/tm-stateless-verifier" } [build-dependencies] tonic-build = "0.11" diff --git a/enclaves/quartz/src/server.rs b/enclaves/quartz/src/server.rs index 967393b..ba4c5de 100644 --- a/enclaves/quartz/src/server.rs +++ b/enclaves/quartz/src/server.rs @@ -1,5 +1,15 @@ -use std::sync::{Arc, Mutex}; +use std::{ + sync::{Arc, Mutex}, + time::Duration, +}; +use cw_proof::{ + error::ProofError, + proof::{ + cw::{CwProof, RawCwProof}, + Proof, + }, +}; use k256::ecdsa::SigningKey; use quartz_cw::{ msg::{ @@ -17,6 +27,12 @@ use quartz_proto::quartz::{ }; use quartz_relayer::types::{InstantiateResponse, SessionCreateResponse, SessionSetPubKeyResponse}; use rand::Rng; +use serde::{Deserialize, Serialize}; +use tendermint_light_client::{ + light_client::Options, + types::{LightBlock, TrustThreshold}, +}; +use tm_stateless_verifier::make_provider; use tonic::{Request, Response, Result as TonicResult, Status}; use crate::attestor::Attestor; @@ -83,11 +99,67 @@ where async fn session_set_pub_key( &self, - _request: Request, + request: Request, ) -> TonicResult> { // FIXME(hu55a1n1) - disallow calling more than once + let proof: ProofOfPublication = serde_json::from_str(&request.into_inner().message) + .map_err(|e| Status::invalid_argument(e.to_string()))?; + + let config_trust_threshold = self.config.light_client_opts().trust_threshold(); + let trust_threshold = + TrustThreshold::new(config_trust_threshold.0, config_trust_threshold.1).unwrap(); + + let config_trusting_period = self.config.light_client_opts().trusting_period(); + let trusting_period = Duration::from_secs(config_trusting_period); + + let config_clock_drift = self.config.light_client_opts().max_clock_drift(); + let clock_drift = Duration::from_secs(config_clock_drift); + let options = Options { + trust_threshold, + trusting_period, + clock_drift, + }; + + let target_height = proof.light_client_proof.last().unwrap().height(); + + let primary_block = make_provider( + self.config.light_client_opts().chain_id(), + self.config + .light_client_opts() + .trusted_height() + .try_into() + .unwrap(), + self.config + .light_client_opts() + .trusted_hash() + .to_vec() + .try_into() + .unwrap(), + proof.light_client_proof, + options, + ) + .and_then(|mut primary| primary.verify_to_height(target_height)) + .map_err(|e| Status::internal(e.to_string()))?; + + let proof = CwProof::from(proof.merkle_proof); + proof + .verify( + primary_block + .signed_header + .header + .app_hash + .as_bytes() + .to_vec(), + ) + .map_err(|e: ProofError| Status::internal(e.to_string()))?; + + let nonce_onchain: Nonce = serde_json::from_slice(&proof.value).unwrap(); let nonce = self.nonce.lock().unwrap(); + if nonce_onchain != *nonce { + return Err(Status::unauthenticated("nonce mismatch")); + } + let sk = SigningKey::random(&mut rand::thread_rng()); *self.sk.lock().unwrap() = Some(sk.clone()); let pk = sk.verifying_key(); @@ -103,3 +175,9 @@ where Ok(Response::new(response.into())) } } + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ProofOfPublication { + light_client_proof: Vec, + merkle_proof: RawCwProof, +} diff --git a/utils/quartz-proto/proto/quartz.proto b/utils/quartz-proto/proto/quartz.proto index 7312b86..53c7d81 100644 --- a/utils/quartz-proto/proto/quartz.proto +++ b/utils/quartz-proto/proto/quartz.proto @@ -20,7 +20,9 @@ message SessionCreateResponse { string message = 1; } -message SessionSetPubKeyRequest {} +message SessionSetPubKeyRequest { + string message = 1; +} message SessionSetPubKeyResponse { string message = 1; diff --git a/utils/quartz-proto/src/prost/quartz.rs b/utils/quartz-proto/src/prost/quartz.rs index a55c500..2814449 100644 --- a/utils/quartz-proto/src/prost/quartz.rs +++ b/utils/quartz-proto/src/prost/quartz.rs @@ -18,7 +18,10 @@ pub struct SessionCreateResponse { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct SessionSetPubKeyRequest {} +pub struct SessionSetPubKeyRequest { + #[prost(string, tag = "1")] + pub message: ::prost::alloc::string::String, +} #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SessionSetPubKeyResponse {