//! Core reshare [Application] implementation. use crate::{ application::{genesis_block, Block}, dkg, }; use commonware_consensus::{ marshal::ingress::mailbox::AncestorStream, simplex::types::Context, Block as _, VerifyingApplication, }; use commonware_cryptography::{ bls12381::primitives::variant::Variant, certificate::Scheme, Committable, Hasher, Signer, }; use commonware_runtime::{Clock, Metrics, Spawner}; use futures::StreamExt; use rand::Rng; use std::marker::PhantomData; #[derive(Clone)] pub struct Application where E: Rng + Spawner + Metrics + Clock, S: Scheme, H: Hasher, C: Signer, V: Variant, { dkg: dkg::Mailbox, _marker: PhantomData<(E, S)>, } impl Application where E: Rng + Spawner + Metrics + Clock, S: Scheme, H: Hasher, C: Signer, V: Variant, { pub const fn new(dkg: dkg::Mailbox) -> Self { Self { dkg, _marker: PhantomData, } } } impl commonware_consensus::Application for Application where E: Rng + Spawner + Metrics + Clock, S: Scheme, H: Hasher, C: Signer, V: Variant, { type Context = Context; type SigningScheme = S; type Block = Block; async fn genesis(&mut self) -> Self::Block { genesis_block::() } async fn propose( &mut self, _context: (E, Self::Context), mut ancestry: AncestorStream, ) -> Option { // Fetch the parent block from the ancestry stream. let parent_block = ancestry.next().await?; let parent_commitment = parent_block.commitment(); // Ask the DKG actor for a result to include // // This approach does allow duplicate commitments to be proposed, but // the arbiter handles this by choosing the first commitment it sees // from any given dealer. let reshare = self.dkg.act().await; // Create a new block Some(Block::new( parent_commitment, parent_block.height() + 1, reshare, )) } } impl VerifyingApplication for Application where E: Rng + Spawner + Metrics + Clock, S: Scheme, H: Hasher, C: Signer, V: Variant, { async fn verify( &mut self, _: (E, Self::Context), _: AncestorStream, ) -> bool { // We wrap this application with `Marshaled`, which handles ancestry // verification (parent commitment and height contiguity). // // You could opt to verify the deal_outcome in the block here (both that it is valid // and that the dealer is the proposer) but we opt to only process deal data after the // block has been finalized to keep verification as fast as possible. The downside // of this approach is that invalid data can be included in the canonical chain (which // makes certificates over finalized blocks less useful because the verifier must still // check the block contents). true } }