diff --git a/tig-protocol/src/context.rs b/tig-protocol/src/context.rs index 0d6a4e29..579f8c5f 100644 --- a/tig-protocol/src/context.rs +++ b/tig-protocol/src/context.rs @@ -16,7 +16,7 @@ pub trait Context { &self, benchmark_id: String, details: BenchmarkDetails, - solution_quality: Vec, + solution_quality: Option>, ) -> Result<()>; async fn get_binary_details(&self, code_id: &String) -> Option; async fn add_binary_to_mempool(&self, code_id: String, details: BinaryDetails) -> Result<()>; diff --git a/tig-protocol/src/contracts/benchmarks.rs b/tig-protocol/src/contracts/benchmarks.rs index 14df0743..2a068899 100644 --- a/tig-protocol/src/contracts/benchmarks.rs +++ b/tig-protocol/src/contracts/benchmarks.rs @@ -97,6 +97,44 @@ pub async fn submit_precommit( Ok(benchmark_id) } +#[time] +pub async fn stop_benchmark( + ctx: &T, + player_id: String, + benchmark_id: String, +) -> Result<()> { + // check benchmark is not duplicate + if ctx.get_benchmark_details(&benchmark_id).await.is_some() { + return Err(anyhow!("Duplicate benchmark: {}", benchmark_id)); + } + + // check player owns benchmark + let settings = ctx + .get_precommit_settings(&benchmark_id) + .await + .ok_or_else(|| anyhow!("Precommit does not exist: {}", benchmark_id))?; + if player_id != settings.player_id { + return Err(anyhow!( + "Invalid submitting player: {}. Expected: {}", + player_id, + settings.player_id + )); + } + + ctx.add_benchmark_to_mempool( + benchmark_id, + BenchmarkDetails { + stopped: true, + average_solution_quality: None, + merkle_root: None, + sampled_nonces: None, + }, + None, + ) + .await?; + Ok(()) +} + #[time] pub async fn submit_benchmark( ctx: &T, @@ -151,11 +189,12 @@ pub async fn submit_benchmark( ctx.add_benchmark_to_mempool( benchmark_id, BenchmarkDetails { - average_solution_quality, - merkle_root, - sampled_nonces, + stopped: false, + average_solution_quality: Some(average_solution_quality), + merkle_root: Some(merkle_root), + sampled_nonces: Some(sampled_nonces), }, - solution_quality, + Some(solution_quality), ) .await?; Ok(()) @@ -179,6 +218,11 @@ pub async fn submit_proof( .await .ok_or_else(|| anyhow!("Benchmark needs to be submitted first."))?; + // check benchmark is not stopped + if benchmark_details.stopped { + return Err(anyhow!("Cannot submit proof for stopped benchmark.")); + } + // check player owns benchmark let settings = ctx.get_precommit_settings(&benchmark_id).await.unwrap(); if player_id != settings.player_id { @@ -192,7 +236,7 @@ pub async fn submit_proof( // verify let precommit_details = ctx.get_precommit_details(&benchmark_id).await.unwrap(); let proof_nonces: HashSet = merkle_proofs.iter().map(|p| p.leaf.nonce).collect(); - let sampled_nonces = benchmark_details.sampled_nonces; + let sampled_nonces = benchmark_details.sampled_nonces.unwrap(); let num_nonces = precommit_details.num_nonces; if sampled_nonces != proof_nonces || sampled_nonces.len() != merkle_proofs.len() { return Err(anyhow!( @@ -203,6 +247,7 @@ pub async fn submit_proof( // verify merkle_proofs let mut verification_result = Ok(()); let max_branch_len = (64 - (num_nonces - 1).leading_zeros()) as usize; + let merkle_root = benchmark_details.merkle_root.unwrap(); for merkle_proof in merkle_proofs.iter() { if merkle_proof.branch.0.len() > max_branch_len || merkle_proof @@ -222,9 +267,7 @@ pub async fn submit_proof( let result = merkle_proof .branch .calc_merkle_root(&hash, merkle_proof.leaf.nonce as usize); - if !result - .is_ok_and(|actual_merkle_root| actual_merkle_root == benchmark_details.merkle_root) - { + if !result.is_ok_and(|actual_merkle_root| actual_merkle_root == merkle_root) { verification_result = Err(anyhow!( "Invalid merkle proof for nonce {}. Merkle root does not match", merkle_proof.leaf.nonce diff --git a/tig-structs/src/core.rs b/tig-structs/src/core.rs index d648613f..f8fff5aa 100644 --- a/tig-structs/src/core.rs +++ b/tig-structs/src/core.rs @@ -158,9 +158,10 @@ impl BenchmarkSettings { } serializable_struct_with_getters! { BenchmarkDetails { - average_solution_quality: i32, - merkle_root: MerkleHash, - sampled_nonces: HashSet, + stopped: bool, + average_solution_quality: Option, + merkle_root: Option, + sampled_nonces: Option>, } } serializable_struct_with_getters! {