Skip to content

Commit 9452c83

Browse files
[cryptography/bls12381] Support Both MinPk and MinSig Variants (#906)
1 parent b906d70 commit 9452c83

55 files changed

Lines changed: 3110 additions & 1837 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

consensus/src/ordered_broadcast/ack_manager.rs

Lines changed: 186 additions & 88 deletions
Large diffs are not rendered by default.

consensus/src/ordered_broadcast/config.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
use super::types::{Activity, Context, Epoch};
22
use crate::{Automaton, Monitor, Relay, Reporter, Supervisor, ThresholdSupervisor};
3-
use commonware_cryptography::{Digest, Scheme};
3+
use commonware_cryptography::{bls12381::primitives::variant::Variant, Digest, Scheme};
44
use std::time::Duration;
55

66
/// Configuration for the [`Engine`](super::Engine).
77
pub struct Config<
88
C: Scheme,
9+
V: Variant,
910
D: Digest,
1011
A: Automaton<Context = Context<C::PublicKey>, Digest = D>,
1112
R: Relay<Digest = D>,
12-
Z: Reporter<Activity = Activity<C, D>>,
13+
Z: Reporter<Activity = Activity<C, V, D>>,
1314
M: Monitor<Index = Epoch>,
1415
Su: Supervisor<Index = Epoch, PublicKey = C::PublicKey>,
1516
TSu: ThresholdSupervisor<Index = Epoch, PublicKey = C::PublicKey>,

consensus/src/ordered_broadcast/engine.rs

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use super::{
1414
};
1515
use crate::{Automaton, Monitor, Relay, Reporter, Supervisor, ThresholdSupervisor};
1616
use commonware_cryptography::{
17-
bls12381::primitives::{group, poly},
17+
bls12381::primitives::{group, poly, variant::Variant},
1818
Digest, Scheme,
1919
};
2020
use commonware_macros::select;
@@ -55,17 +55,18 @@ struct Verify<C: Scheme, D: Digest, E: Clock> {
5555
pub struct Engine<
5656
E: Clock + Spawner + Storage + Metrics,
5757
C: Scheme,
58+
V: Variant,
5859
D: Digest,
5960
A: Automaton<Context = Context<C::PublicKey>, Digest = D> + Clone,
6061
R: Relay<Digest = D>,
61-
Z: Reporter<Activity = Activity<C, D>>,
62+
Z: Reporter<Activity = Activity<C, V, D>>,
6263
M: Monitor<Index = Epoch>,
6364
Su: Supervisor<Index = Epoch, PublicKey = C::PublicKey>,
6465
TSu: ThresholdSupervisor<
6566
Index = Epoch,
6667
PublicKey = C::PublicKey,
6768
Share = group::Share,
68-
Identity = poly::Public,
69+
Identity = poly::Public<V>,
6970
>,
7071
NetS: Sender<PublicKey = C::PublicKey>,
7172
NetR: Receiver<PublicKey = C::PublicKey>,
@@ -151,7 +152,8 @@ pub struct Engine<
151152
journal_compression: Option<u8>,
152153

153154
// A map of sequencer public keys to their journals.
154-
journals: BTreeMap<C::PublicKey, Journal<E, Node<C, D>>>,
155+
#[allow(clippy::type_complexity)]
156+
journals: BTreeMap<C::PublicKey, Journal<E, Node<C, V, D>>>,
155157

156158
////////////////////////////////////////
157159
// State
@@ -161,11 +163,11 @@ pub struct Engine<
161163
// The tip is a `Node` which is comprised of a `Chunk` and,
162164
// if not the genesis chunk for that sequencer,
163165
// a threshold signature over the parent chunk.
164-
tip_manager: TipManager<C, D>,
166+
tip_manager: TipManager<C, V, D>,
165167

166168
// Tracks the acknowledgements for chunks.
167169
// This is comprised of partial signatures or threshold signatures.
168-
ack_manager: AckManager<C::PublicKey, D>,
170+
ack_manager: AckManager<C::PublicKey, V, D>,
169171

170172
// The current epoch.
171173
epoch: Epoch,
@@ -197,24 +199,25 @@ pub struct Engine<
197199
impl<
198200
E: Clock + Spawner + Storage + Metrics,
199201
C: Scheme,
202+
V: Variant,
200203
D: Digest,
201204
A: Automaton<Context = Context<C::PublicKey>, Digest = D> + Clone,
202205
R: Relay<Digest = D>,
203-
Z: Reporter<Activity = Activity<C, D>>,
206+
Z: Reporter<Activity = Activity<C, V, D>>,
204207
M: Monitor<Index = Epoch>,
205208
Su: Supervisor<Index = Epoch, PublicKey = C::PublicKey>,
206209
TSu: ThresholdSupervisor<
207210
Index = Epoch,
208211
PublicKey = C::PublicKey,
209212
Share = group::Share,
210-
Identity = poly::Public,
213+
Identity = poly::Public<V>,
211214
>,
212215
NetS: Sender<PublicKey = C::PublicKey>,
213216
NetR: Receiver<PublicKey = C::PublicKey>,
214-
> Engine<E, C, D, A, R, Z, M, Su, TSu, NetS, NetR>
217+
> Engine<E, C, V, D, A, R, Z, M, Su, TSu, NetS, NetR>
215218
{
216219
/// Creates a new engine with the given context and configuration.
217-
pub fn new(context: E, cfg: Config<C, D, A, R, Z, M, Su, TSu>) -> Self {
220+
pub fn new(context: E, cfg: Config<C, V, D, A, R, Z, M, Su, TSu>) -> Self {
218221
let metrics = metrics::Metrics::init(context.clone());
219222

220223
Self {
@@ -238,8 +241,8 @@ impl<
238241
journal_name_prefix: cfg.journal_name_prefix,
239242
journal_compression: cfg.journal_compression,
240243
journals: BTreeMap::new(),
241-
tip_manager: TipManager::<C, D>::new(),
242-
ack_manager: AckManager::<C::PublicKey, D>::new(),
244+
tip_manager: TipManager::<C, V, D>::new(),
245+
ack_manager: AckManager::<C::PublicKey, V, D>::new(),
243246
epoch: 0,
244247
priority_proposals: cfg.priority_proposals,
245248
priority_acks: cfg.priority_acks,
@@ -475,7 +478,7 @@ impl<
475478
&mut self,
476479
context: &Context<C::PublicKey>,
477480
payload: &D,
478-
ack_sender: &mut WrappedSender<NetS, Ack<C::PublicKey, D>>,
481+
ack_sender: &mut WrappedSender<NetS, Ack<C::PublicKey, V, D>>,
479482
) -> Result<(), Error> {
480483
// Get the tip
481484
let Some(tip) = self.tip_manager.get(&context.sequencer) else {
@@ -548,7 +551,7 @@ impl<
548551
&mut self,
549552
chunk: &Chunk<C::PublicKey, D>,
550553
epoch: Epoch,
551-
threshold: group::Signature,
554+
threshold: V::Signature,
552555
) {
553556
// Set the threshold signature, returning early if it already exists
554557
if !self
@@ -573,7 +576,7 @@ impl<
573576
///
574577
/// Returns an error if the ack is invalid, or can be ignored
575578
/// (e.g. already exists, threshold already exists, is outside the epoch bounds, etc.).
576-
async fn handle_ack(&mut self, ack: &Ack<C::PublicKey, D>) -> Result<(), Error> {
579+
async fn handle_ack(&mut self, ack: &Ack<C::PublicKey, V, D>) -> Result<(), Error> {
577580
// Get the quorum
578581
let Some(identity) = self.validators.identity(ack.epoch) else {
579582
return Err(Error::UnknownIdentity(ack.epoch));
@@ -594,7 +597,7 @@ impl<
594597
/// Handles a valid `Node` message, storing it as the tip.
595598
/// Alerts the automaton of the new node.
596599
/// Also appends the `Node` to the journal if it's new.
597-
async fn handle_node(&mut self, node: &Node<C, D>) {
600+
async fn handle_node(&mut self, node: &Node<C, V, D>) {
598601
// Store the tip
599602
let is_new = self.tip_manager.put(node);
600603

@@ -671,7 +674,7 @@ impl<
671674
&mut self,
672675
context: Context<C::PublicKey>,
673676
payload: D,
674-
node_sender: &mut WrappedSender<NetS, Node<C, D>>,
677+
node_sender: &mut WrappedSender<NetS, Node<C, V, D>>,
675678
) -> Result<(), Error> {
676679
let mut guard = self.metrics.propose.guard(Status::Dropped);
677680
let me = self.crypto.public_key();
@@ -738,7 +741,7 @@ impl<
738741
/// - this instance has not yet collected the threshold signature for the chunk.
739742
async fn rebroadcast(
740743
&mut self,
741-
node_sender: &mut WrappedSender<NetS, Node<C, D>>,
744+
node_sender: &mut WrappedSender<NetS, Node<C, V, D>>,
742745
) -> Result<(), Error> {
743746
let mut guard = self.metrics.rebroadcast.guard(Status::Dropped);
744747

@@ -775,8 +778,8 @@ impl<
775778
/// Send a `Node` message to all validators in the given epoch.
776779
async fn broadcast(
777780
&mut self,
778-
node: Node<C, D>,
779-
node_sender: &mut WrappedSender<NetS, Node<C, D>>,
781+
node: Node<C, V, D>,
782+
node_sender: &mut WrappedSender<NetS, Node<C, V, D>>,
780783
epoch: Epoch,
781784
) -> Result<(), Error> {
782785
// Get the validators for the epoch
@@ -814,7 +817,7 @@ impl<
814817
/// Else returns an error if the `Node` is invalid.
815818
fn validate_node(
816819
&mut self,
817-
node: &Node<C, D>,
820+
node: &Node<C, V, D>,
818821
sender: &C::PublicKey,
819822
) -> Result<Option<Chunk<C::PublicKey, D>>, Error> {
820823
// Verify the sender
@@ -838,7 +841,7 @@ impl<
838841
let Some(identity) = self.validators.identity(parent.epoch) else {
839842
return Err(Error::UnknownIdentity(parent.epoch));
840843
};
841-
Some(poly::public(identity))
844+
Some(poly::public::<V>(identity))
842845
} else {
843846
None
844847
};
@@ -852,7 +855,11 @@ impl<
852855
///
853856
/// Returns the chunk, epoch, and partial signature if the ack is valid.
854857
/// Returns an error if the ack is invalid.
855-
fn validate_ack(&self, ack: &Ack<C::PublicKey, D>, sender: &C::PublicKey) -> Result<(), Error> {
858+
fn validate_ack(
859+
&self,
860+
ack: &Ack<C::PublicKey, V, D>,
861+
sender: &C::PublicKey,
862+
) -> Result<(), Error> {
856863
// Validate chunk
857864
self.validate_chunk(&ack.chunk, ack.epoch)?;
858865

@@ -964,7 +971,7 @@ impl<
964971
compression: self.journal_compression,
965972
codec_config: (),
966973
};
967-
let journal = Journal::<_, Node<C, D>>::init(self.context.with_label("journal"), cfg)
974+
let journal = Journal::<_, Node<C, V, D>>::init(self.context.with_label("journal"), cfg)
968975
.await
969976
.expect("unable to init journal");
970977

@@ -981,7 +988,7 @@ impl<
981988

982989
// Read from the stream, which may be in arbitrary order.
983990
// Remember the highest node height
984-
let mut tip: Option<Node<C, D>> = None;
991+
let mut tip: Option<Node<C, V, D>> = None;
985992
let mut num_items = 0;
986993
while let Some(msg) = stream.next().await {
987994
let (_, _, _, node) = msg.expect("unable to read from journal");
@@ -1017,7 +1024,7 @@ impl<
10171024
///
10181025
/// To prevent ever writing two conflicting `Chunk`s at the same height,
10191026
/// the journal must already be open and replayed.
1020-
async fn journal_append(&mut self, node: Node<C, D>) {
1027+
async fn journal_append(&mut self, node: Node<C, V, D>) {
10211028
let section = self.get_journal_section(node.chunk.height);
10221029
self.journals
10231030
.get_mut(&node.chunk.sequencer)

consensus/src/ordered_broadcast/mocks/reporter.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,30 @@ use crate::{
33
Reporter as Z,
44
};
55
use commonware_codec::{DecodeExt, Encode};
6-
use commonware_cryptography::{bls12381::primitives::group, Digest, Verifier};
6+
use commonware_cryptography::{bls12381::primitives::variant::Variant, Digest, Verifier};
77
use futures::{
88
channel::{mpsc, oneshot},
99
SinkExt, StreamExt,
1010
};
1111
use std::collections::{btree_map::Entry, BTreeMap, HashMap, HashSet};
1212

1313
#[allow(clippy::large_enum_variant)]
14-
enum Message<C: Verifier, D: Digest> {
14+
enum Message<C: Verifier, V: Variant, D: Digest> {
1515
Proposal(Proposal<C, D>),
16-
Locked(Lock<C::PublicKey, D>),
16+
Locked(Lock<C::PublicKey, V, D>),
1717
GetTip(C::PublicKey, oneshot::Sender<Option<(u64, Epoch)>>),
1818
GetContiguousTip(C::PublicKey, oneshot::Sender<Option<u64>>),
1919
Get(C::PublicKey, u64, oneshot::Sender<Option<(D, Epoch)>>),
2020
}
2121

22-
pub struct Reporter<C: Verifier, D: Digest> {
23-
mailbox: mpsc::Receiver<Message<C, D>>,
22+
pub struct Reporter<C: Verifier, V: Variant, D: Digest> {
23+
mailbox: mpsc::Receiver<Message<C, V, D>>,
2424

2525
// Application namespace
2626
namespace: Vec<u8>,
2727

2828
// Public key of the group
29-
public: group::Public,
29+
public: V::Public,
3030

3131
// Notified proposals
3232
proposals: HashSet<Chunk<C::PublicKey, D>>,
@@ -42,12 +42,12 @@ pub struct Reporter<C: Verifier, D: Digest> {
4242
highest: HashMap<C::PublicKey, (u64, Epoch)>,
4343
}
4444

45-
impl<C: Verifier, D: Digest> Reporter<C, D> {
45+
impl<C: Verifier, V: Variant, D: Digest> Reporter<C, V, D> {
4646
pub fn new(
4747
namespace: &[u8],
48-
public: group::Public,
48+
public: V::Public,
4949
limit_misses: Option<usize>,
50-
) -> (Self, Mailbox<C, D>) {
50+
) -> (Self, Mailbox<C, V, D>) {
5151
let (sender, receiver) = mpsc::channel(1024);
5252
(
5353
Reporter {
@@ -89,7 +89,7 @@ impl<C: Verifier, D: Digest> Reporter<C, D> {
8989

9090
// Test encoding/decoding
9191
let encoded = lock.encode();
92-
Lock::<C::PublicKey, D>::decode(encoded).unwrap();
92+
Lock::<C::PublicKey, V, D>::decode(encoded).unwrap();
9393

9494
// Check if the proposal is known
9595
if let Some(misses_allowed) = self.limit_misses {
@@ -166,12 +166,12 @@ impl<C: Verifier, D: Digest> Reporter<C, D> {
166166
}
167167

168168
#[derive(Clone)]
169-
pub struct Mailbox<C: Verifier, D: Digest> {
170-
sender: mpsc::Sender<Message<C, D>>,
169+
pub struct Mailbox<C: Verifier, V: Variant, D: Digest> {
170+
sender: mpsc::Sender<Message<C, V, D>>,
171171
}
172172

173-
impl<C: Verifier, D: Digest> Z for Mailbox<C, D> {
174-
type Activity = Activity<C, D>;
173+
impl<C: Verifier, V: Variant, D: Digest> Z for Mailbox<C, V, D> {
174+
type Activity = Activity<C, V, D>;
175175

176176
async fn report(&mut self, activity: Self::Activity) {
177177
match activity {
@@ -191,7 +191,7 @@ impl<C: Verifier, D: Digest> Z for Mailbox<C, D> {
191191
}
192192
}
193193

194-
impl<C: Verifier, D: Digest> Mailbox<C, D> {
194+
impl<C: Verifier, V: Variant, D: Digest> Mailbox<C, V, D> {
195195
pub async fn get_tip(&mut self, sequencer: C::PublicKey) -> Option<(u64, Epoch)> {
196196
let (sender, receiver) = oneshot::channel();
197197
self.sender

consensus/src/ordered_broadcast/mocks/validators.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
use crate::{ordered_broadcast::types::Epoch, Supervisor, ThresholdSupervisor};
2-
use commonware_cryptography::bls12381::primitives::{
3-
group::{self, Public, Share},
4-
poly::Poly,
5-
};
2+
use commonware_cryptography::bls12381::primitives::{group::Share, poly::Public, variant::Variant};
63
use commonware_utils::Array;
7-
use std::collections::HashMap;
4+
use std::{collections::HashMap, marker::PhantomData};
85

96
#[derive(Clone)]
10-
pub struct Validators<P: Array> {
11-
identity: Poly<Public>,
7+
pub struct Validators<P: Array, V: Variant> {
8+
identity: Public<V>,
129
validators: Vec<P>,
1310
validators_map: HashMap<P, u32>,
1411
share: Option<Share>,
12+
13+
_phantom: PhantomData<V>,
1514
}
1615

17-
impl<P: Array> Validators<P> {
18-
pub fn new(identity: Poly<Public>, mut validators: Vec<P>, share: Option<Share>) -> Self {
16+
impl<P: Array, V: Variant> Validators<P, V> {
17+
pub fn new(identity: Public<V>, mut validators: Vec<P>, share: Option<Share>) -> Self {
1918
// Setup validators
2019
validators.sort();
2120
let mut validators_map = HashMap::new();
@@ -28,11 +27,13 @@ impl<P: Array> Validators<P> {
2827
validators,
2928
validators_map,
3029
share,
30+
31+
_phantom: PhantomData,
3132
}
3233
}
3334
}
3435

35-
impl<P: Array> Supervisor for Validators<P> {
36+
impl<P: Array, V: Variant> Supervisor for Validators<P, V> {
3637
type Index = Epoch;
3738
type PublicKey = P;
3839

@@ -49,10 +50,10 @@ impl<P: Array> Supervisor for Validators<P> {
4950
}
5051
}
5152

52-
impl<P: Array> ThresholdSupervisor for Validators<P> {
53-
type Identity = Poly<Public>;
53+
impl<P: Array, V: Variant> ThresholdSupervisor for Validators<P, V> {
54+
type Identity = Public<V>;
5455
type Share = Share;
55-
type Seed = group::Signature;
56+
type Seed = V::Signature;
5657

5758
fn leader(&self, _: Self::Index, _: Self::Seed) -> Option<Self::PublicKey> {
5859
unimplemented!()

0 commit comments

Comments
 (0)