tempo_dkg_onchain_artifacts/
lib.rs1use std::num::NonZeroU32;
4
5use bytes::{Buf, BufMut};
6use commonware_codec::{EncodeSize, RangeCfg, Read, ReadExt, Write};
7use commonware_consensus::types::Epoch;
8use commonware_cryptography::{
9 bls12381::{
10 dkg::Output,
11 primitives::{
12 sharing::{ModeVersion, Sharing},
13 variant::{MinSig, Variant},
14 },
15 },
16 ed25519::PublicKey,
17};
18use commonware_utils::{NZU32, ordered};
19
20const MAX_VALIDATORS: NonZeroU32 = NZU32!(u16::MAX as u32);
21
22#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct OnchainDkgOutcome {
29 pub epoch: Epoch,
31
32 pub output: Output<MinSig, PublicKey>,
36
37 pub next_players: ordered::Set<PublicKey>,
40
41 pub is_next_full_dkg: bool,
44}
45
46impl OnchainDkgOutcome {
47 pub fn dealers(&self) -> &ordered::Set<PublicKey> {
48 self.output.dealers()
49 }
50
51 pub fn players(&self) -> &ordered::Set<PublicKey> {
52 self.output.players()
53 }
54
55 pub fn next_players(&self) -> &ordered::Set<PublicKey> {
56 &self.next_players
57 }
58
59 pub fn sharing(&self) -> &Sharing<MinSig> {
60 self.output.public()
61 }
62
63 pub fn network_identity(&self) -> &<MinSig as Variant>::Public {
64 self.sharing().public()
65 }
66}
67
68impl Write for OnchainDkgOutcome {
69 fn write(&self, buf: &mut impl BufMut) {
70 self.epoch.write(buf);
71 self.output.write(buf);
72 self.next_players.write(buf);
73 self.is_next_full_dkg.write(buf);
74 }
75}
76
77impl Read for OnchainDkgOutcome {
78 type Cfg = ();
79
80 fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result<Self, commonware_codec::Error> {
81 let epoch = ReadExt::read(buf)?;
82 let output = Read::read_cfg(buf, &(MAX_VALIDATORS, ModeVersion::v0()))?;
83 let next_players = Read::read_cfg(
84 buf,
85 &(RangeCfg::from(1..=(MAX_VALIDATORS.get() as usize)), ()),
86 )?;
87 let is_next_full_dkg = ReadExt::read(buf)?;
88 Ok(Self {
89 epoch,
90 output,
91 next_players,
92 is_next_full_dkg,
93 })
94 }
95}
96
97impl EncodeSize for OnchainDkgOutcome {
98 fn encode_size(&self) -> usize {
99 self.epoch.encode_size()
100 + self.output.encode_size()
101 + self.next_players.encode_size()
102 + self.is_next_full_dkg.encode_size()
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use std::iter::repeat_with;
109
110 use commonware_codec::{Encode as _, ReadExt as _};
111 use commonware_consensus::types::Epoch;
112 use commonware_cryptography::{Signer as _, bls12381::dkg, ed25519::PrivateKey};
113 use commonware_math::algebra::Random as _;
114 use commonware_utils::{N3f1, TryFromIterator as _, ordered};
115 use rand_08::SeedableRng as _;
116
117 use super::OnchainDkgOutcome;
118
119 #[test]
120 fn onchain_dkg_outcome_roundtrip() {
121 let mut rng = rand_08::rngs::StdRng::seed_from_u64(42);
122
123 let mut player_keys = repeat_with(|| PrivateKey::random(&mut rng))
124 .take(10)
125 .collect::<Vec<_>>();
126 player_keys.sort_by_key(|key| key.public_key());
127 let (output, _shares) = dkg::deal::<_, _, N3f1>(
128 &mut rng,
129 Default::default(),
130 ordered::Set::try_from_iter(player_keys.iter().map(|key| key.public_key())).unwrap(),
131 )
132 .unwrap();
133
134 let on_chain = OnchainDkgOutcome {
135 epoch: Epoch::new(42),
136 output,
137 next_players: ordered::Set::try_from_iter(
138 player_keys.iter().map(|key| key.public_key()),
139 )
140 .unwrap(),
141 is_next_full_dkg: false,
142 };
143 let bytes = on_chain.encode();
144 assert_eq!(
145 OnchainDkgOutcome::read(&mut bytes.as_ref()).unwrap(),
146 on_chain,
147 );
148 }
149}