//! Marshal storage conformance tests. use super::mocks::{ application::Application, harness::{ self, CodingHarness, StandardHarness, TestHarness, ValidatorHandle, ValidatorSetup, BLOCKS_PER_EPOCH, NAMESPACE, NUM_VALIDATORS, QUORUM, V, }, }; use crate::{ simplex::{scheme::bls12381_threshold::vrf as bls12381_threshold_vrf, types::Proposal}, types::{Epoch, Height, Round, View}, }; use commonware_conformance::{conformance_tests, Conformance}; use commonware_cryptography::certificate::{mocks::Fixture, ConstantProvider}; use commonware_runtime::{deterministic, Clock, Runner, Supervisor as _}; use commonware_utils::NZUsize; use rand::Rng; use std::time::Duration; const CASES: usize = 32; struct StandardStorageConformance; struct CodingStorageConformance; impl Conformance for StandardStorageConformance { async fn commit(seed: u64) -> Vec { marshal_commit::(seed) } } impl Conformance for CodingStorageConformance { async fn commit(seed: u64) -> Vec { marshal_commit::(seed) } } fn marshal_commit(seed: u64) -> Vec { let runner = deterministic::Runner::new( deterministic::Config::default() .with_seed(seed) .with_timeout(Some(Duration::from_secs(30))), ); runner.start(|mut context| async move { let Fixture { participants, schemes, .. } = bls12381_threshold_vrf::fixture::(&mut context, NAMESPACE, NUM_VALIDATORS); let mut oracle = harness::setup_network_with_participants( context.child("network"), NZUsize!(1), participants.clone(), ) .await; let validator = participants[0].clone(); let provider = ConstantProvider::new(schemes[0].clone()); let application = Application::::manual_ack(); let setup = H::setup_validator_with( context.child("validator"), &mut oracle, validator, provider, NZUsize!(1), application, ) .await; assert_eq!(setup.application.acknowledged().await, Height::zero()); wait_processed(&mut context, &setup, Height::zero()).await; let mut handle = ValidatorHandle:: { mailbox: setup.mailbox.clone(), extra: setup.extra.clone(), }; let mut peers = Vec::>::new(); let mut parent = H::genesis_block(NUM_VALIDATORS as u16); let count = context.gen_range(1..=BLOCKS_PER_EPOCH.get().min(4)); for height in 1..=count { let height = Height::new(height); let round = Round::new(Epoch::zero(), View::new(height.get())); let parent_view = height .previous() .map_or(View::zero(), |h| View::new(h.get())); let block = H::make_test_block( H::digest(&parent), H::commitment(&parent), height, context.gen(), NUM_VALIDATORS as u16, ); H::verify(&mut handle, round, &block, &mut peers).await; let proposal = Proposal::new(round, parent_view, H::commitment(&block)); let finalization = H::make_finalization(proposal, &schemes, QUORUM); let mut mailbox = setup.mailbox.clone(); H::report_finalization(&mut mailbox, finalization).await; assert_eq!(setup.application.acknowledged().await, height); wait_processed(&mut context, &setup, height).await; parent = block; } setup.actor_handle.abort(); let _ = setup.actor_handle.await; context.storage_audit().to_vec() }) } async fn wait_processed( context: &mut deterministic::Context, setup: &ValidatorSetup, height: Height, ) { loop { if setup.mailbox.get_processed_height().await == Some(height) { break; } context.sleep(Duration::from_millis(1)).await; } } conformance_tests! { StandardStorageConformance => CASES, CodingStorageConformance => CASES, }