diff --git a/hotshot-state-prover/src/mock_ledger.rs b/hotshot-state-prover/src/mock_ledger.rs index 0b59ceeef1..0e9ec11904 100644 --- a/hotshot-state-prover/src/mock_ledger.rs +++ b/hotshot-state-prover/src/mock_ledger.rs @@ -16,7 +16,9 @@ use hotshot_contract_adapter::jellyfish::{field_to_u256, open_key, u256_to_field use hotshot_contract_adapter::light_client::ParsedLightClientState; use hotshot_stake_table::vec_based::StakeTable; -use crate::{generate_state_update_proof, preprocess, Proof, VerifyingKey}; +use crate::{ + generate_state_update_proof, preprocess, service::one_honest_threshold, Proof, VerifyingKey, +}; use hotshot_types::traits::stake_table::StakeTableScheme; use hotshot_types::{ light_client::{GenericLightClientState, GenericPublicInput, LightClientState}, @@ -86,7 +88,8 @@ impl MockLedger { key_archive.insert(qc_keys[i], state_keys[i].0.clone()); } let st = stake_table_for_testing(&qc_keys, &state_keys); - let threshold = st.total_stake(SnapshotVersion::LastEpochStart).unwrap() * 2 / 3; + let threshold = + one_honest_threshold(st.total_stake(SnapshotVersion::LastEpochStart).unwrap()); // arbitrary commitment values as they don't affect logic being tested let block_comm_root = F::from(1234); @@ -120,12 +123,11 @@ impl MockLedger { { self.epoch += 1; self.st.advance(); - self.threshold = self - .st - .total_stake(SnapshotVersion::LastEpochStart) - .unwrap() - * 2 - / 3; + self.threshold = one_honest_threshold( + self.st + .total_stake(SnapshotVersion::LastEpochStart) + .unwrap(), + ); } let new_root = self.new_dummy_comm(); diff --git a/hotshot-state-prover/src/service.rs b/hotshot-state-prover/src/service.rs index afaff42f8b..5b609b17a6 100644 --- a/hotshot-state-prover/src/service.rs +++ b/hotshot-state-prover/src/service.rs @@ -79,6 +79,12 @@ pub struct StateProverConfig { pub stake_table_capacity: usize, } +#[inline] +/// A helper function to compute the quorum threshold given a total amount of stake. +pub fn one_honest_threshold(total_stake: U256) -> U256 { + total_stake / 3 + 1 +} + pub fn init_stake_table( bls_keys: &[BLSPubKey], state_keys: &[StateVerKey], @@ -156,7 +162,7 @@ pub async fn light_client_genesis( let (bls_comm, schnorr_comm, stake_comm) = st .commitment(SnapshotVersion::LastEpochStart) .expect("Commitment computation shouldn't fail."); - let threshold = st.total_stake(SnapshotVersion::LastEpochStart)? * 2 / 3; + let threshold = one_honest_threshold(st.total_stake(SnapshotVersion::LastEpochStart)?); let pi = vec![ u256_to_field(threshold), @@ -297,7 +303,7 @@ pub async fn sync_state( tracing::debug!("Old state: {old_state:?}"); tracing::debug!("New state: {:?}", bundle.state); - let threshold = st.total_stake(SnapshotVersion::LastEpochStart)? * 2 / 3; + let threshold = one_honest_threshold(st.total_stake(SnapshotVersion::LastEpochStart)?); tracing::info!("Threshold before syncing state: {}", threshold); let entries = st .try_iter(SnapshotVersion::LastEpochStart) diff --git a/sequencer/src/bin/deploy.rs b/sequencer/src/bin/deploy.rs index 6f76168b10..2935c0f244 100644 --- a/sequencer/src/bin/deploy.rs +++ b/sequencer/src/bin/deploy.rs @@ -95,7 +95,7 @@ struct Options { #[clap(flatten)] contracts: DeployedContracts, - /// If toggled, launch a mock prover contract that does not do any proof verification. + /// If toggled, launch a mock prover contract with a smaller verification key. #[clap(short, long)] pub use_mock_contract: bool, diff --git a/sequencer/src/bin/nasty-client.rs b/sequencer/src/bin/nasty-client.rs index 069b28d869..75f205aa21 100644 --- a/sequencer/src/bin/nasty-client.rs +++ b/sequencer/src/bin/nasty-client.rs @@ -149,7 +149,7 @@ struct ClientConfig { #[derive(Clone, Debug, Parser)] struct ActionDistribution { /// The weight of query actions in the random distribution. - #[clap(long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_QUERY", default_value = "5")] + #[clap(long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_QUERY", default_value = "20")] weight_query: u8, /// The weight of "open stream" actions in the random distribution. @@ -172,7 +172,7 @@ struct ActionDistribution { #[clap( long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_POLL_STREAM", - default_value = "5" + default_value = "10" )] weight_poll_stream: u8, @@ -180,7 +180,7 @@ struct ActionDistribution { #[clap( long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_QUERY_WINDOW", - default_value = "3" + default_value = "15" )] weight_query_window: u8, @@ -188,7 +188,7 @@ struct ActionDistribution { #[clap( long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_QUERY_NAMESPACE", - default_value = "3" + default_value = "15" )] weight_query_namespace: u8, @@ -196,7 +196,7 @@ struct ActionDistribution { #[clap( long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_QUERY_BLOCK_STATE", - default_value = "3" + default_value = "15" )] weight_query_block_state: u8, @@ -204,7 +204,7 @@ struct ActionDistribution { #[clap( long, env = "ESPRESSO_NASTY_CLIENT_WEIGHT_QUERY_FEE_STATE", - default_value = "3" + default_value = "15" )] weight_query_fee_state: u8, } diff --git a/sequencer/src/bin/state-relay-server.rs b/sequencer/src/bin/state-relay-server.rs index 2aef99c31a..5b77ec4905 100644 --- a/sequencer/src/bin/state-relay-server.rs +++ b/sequencer/src/bin/state-relay-server.rs @@ -1,6 +1,8 @@ use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; use es_version::SEQUENCER_VERSION; +use ethers::types::U256; +use hotshot_state_prover::service::one_honest_threshold; use sequencer::state_signature::relay_server::run_relay_server; #[derive(Parser)] @@ -31,9 +33,12 @@ async fn main() { setup_backtrace(); let args = Args::parse(); - let threshold = ((2 * args.total_stake) / 3) + 1; + let threshold = one_honest_threshold(U256::from(args.total_stake)); - tracing::info!(port = args.port, threshold, "starting state relay server"); + tracing::info!( + port = args.port, + "starting state relay server, quorum threshold: {threshold}" + ); run_relay_server( None, threshold, diff --git a/sequencer/src/l1_client.rs b/sequencer/src/l1_client.rs index d305c963a2..d64de7f3c9 100644 --- a/sequencer/src/l1_client.rs +++ b/sequencer/src/l1_client.rs @@ -121,26 +121,32 @@ impl L1Client { /// Get information about the given block. /// - /// If the desired block number is not available yet, this function will block until it becomes - /// available. - pub async fn wait_for_block(&self, number: u64) -> L1BlockInfo { + /// If the desired block number is not finalized yet, this function will block until it becomes + /// finalized. + pub async fn wait_for_finalized_block(&self, number: u64) -> L1BlockInfo { let interval = self.provider.get_interval(); - // Wait for the block to become available. - loop { - match self.provider.get_block_number().await { - Ok(height) if height > number.into() => break, - Ok(height) => { - tracing::warn!(number, %height, "waiting for L1 block"); - } - Err(err) => { - tracing::error!(%err, "failed to get L1 block height"); - } + // Wait for the block to finalize. + let finalized = loop { + let Some(block) = self.get_finalized_block().await else { + tracing::info!("waiting for finalized block"); + sleep(interval).await; + continue; + }; + if block.number >= number { + break block; } + tracing::info!(current_finalized = %block.number, "waiting for finalized block"); sleep(interval).await; + continue; + }; + + if finalized.number == number { + return finalized; } - // Get the block, retrying until we succeed. + // The finalized block may have skipped over the block of interest. In this case, our block + // is still finalized, since it is before the finalized block. We just need to fetch it. loop { let block = match self.provider.get_block(number).await { Ok(Some(block)) => block, @@ -477,7 +483,7 @@ mod test { } #[async_std::test] - async fn test_wait_for_block() { + async fn test_wait_for_finalized_block() { setup_logging(); setup_backtrace(); @@ -487,7 +493,7 @@ mod test { // Wait for a block 10 blocks in the future. let block_height = provider.get_block_number().await.unwrap().as_u64(); - let block = l1_client.wait_for_block(block_height + 10).await; + let block = l1_client.wait_for_finalized_block(block_height + 10).await; assert_eq!(block.number, block_height + 10); // Compare against underlying provider. diff --git a/sequencer/src/lib.rs b/sequencer/src/lib.rs index 6bdc69bdc7..dd947ef769 100644 --- a/sequencer/src/lib.rs +++ b/sequencer/src/lib.rs @@ -460,7 +460,7 @@ pub async fn init_node( let l1_client = L1Client::new(l1_params.url, l1_params.events_max_block_range); let l1_genesis = match l1_params.finalized_block { - Some(block) => Some(l1_client.wait_for_block(block).await), + Some(block) => Some(l1_client.wait_for_finalized_block(block).await), None => None, }; diff --git a/sequencer/src/state_signature/relay_server.rs b/sequencer/src/state_signature/relay_server.rs index d61d3c417b..4dd0263f89 100644 --- a/sequencer/src/state_signature/relay_server.rs +++ b/sequencer/src/state_signature/relay_server.rs @@ -224,7 +224,7 @@ where pub async fn run_relay_server( shutdown_listener: Option>, - threshold: u64, + threshold: U256, url: Url, bind_version: Ver, ) -> std::io::Result<()> { @@ -234,7 +234,6 @@ pub async fn run_relay_server( // We don't have a stake table yet, putting some temporary value here. // Related issue: [https://github.com/EspressoSystems/espresso-sequencer/issues/1022] - let threshold = U256::from(threshold); let state = State::new(StateRelayServerState::new(threshold).with_shutdown_signal(shutdown_listener)); let mut app = App::::with_state(state);