tempo_commonware_node/dkg/ceremony/
payload.rs1use bytes::{Buf, BufMut};
4use commonware_codec::{EncodeSize, FixedSize as _, Read, ReadExt as _, Write, varint::UInt};
5use commonware_consensus::types::Epoch;
6use commonware_cryptography::bls12381::primitives::{group, poly::Public, variant::MinSig};
7use commonware_utils::quorum;
8use tempo_dkg_onchain_artifacts::Ack;
9
10#[derive(Clone, Debug, PartialEq)]
12pub(super) struct Message {
13 pub(super) epoch: Epoch,
14 pub(super) payload: Payload,
15}
16
17impl Write for Message {
18 fn write(&self, buf: &mut impl BufMut) {
19 UInt(self.epoch).write(buf);
20 self.payload.write(buf);
21 }
22}
23
24impl Read for Message {
25 type Cfg = u32;
26
27 fn read_cfg(buf: &mut impl Buf, num_players: &u32) -> Result<Self, commonware_codec::Error> {
28 let epoch = UInt::read(buf)?.into();
29 let payload = Payload::read_cfg(buf, num_players)?;
30 Ok(Self { epoch, payload })
31 }
32}
33
34impl EncodeSize for Message {
35 fn encode_size(&self) -> usize {
36 UInt(self.epoch).encode_size() + self.payload.encode_size()
37 }
38}
39
40#[derive(Clone, Debug, PartialEq)]
42pub(super) enum Payload {
43 Share(Share),
49
50 Ack(Box<Ack>),
57}
58
59impl From<Ack> for Payload {
60 fn from(value: Ack) -> Self {
61 Self::Ack(value.into())
62 }
63}
64
65impl From<Share> for Payload {
66 fn from(value: Share) -> Self {
67 Self::Share(value)
68 }
69}
70
71impl Write for Payload {
72 fn write(&self, buf: &mut impl BufMut) {
73 match self {
74 Self::Share(inner) => {
75 buf.put_u8(SHARE_TAG);
76 inner.write(buf);
77 }
78 Self::Ack(inner) => {
79 buf.put_u8(ACK_TAG);
80 inner.write(buf);
81 }
82 }
83 }
84}
85
86const SHARE_TAG: u8 = 0;
87const ACK_TAG: u8 = 1;
88
89impl Read for Payload {
90 type Cfg = u32;
91
92 fn read_cfg(buf: &mut impl Buf, p: &u32) -> Result<Self, commonware_codec::Error> {
93 let tag = u8::read(buf)?;
94 let result = match tag {
95 SHARE_TAG => Self::Share(Share::read_cfg(buf, p)?),
96 ACK_TAG => Self::Ack(Ack::read(buf)?.into()),
97 _ => return Err(commonware_codec::Error::InvalidEnum(tag)),
98 };
99 Ok(result)
100 }
101}
102
103impl EncodeSize for Payload {
104 fn encode_size(&self) -> usize {
105 u8::SIZE
106 + match self {
107 Self::Share(inner) => inner.encode_size(),
108 Self::Ack(inner) => inner.encode_size(),
109 }
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
121pub(super) struct Share {
122 pub(super) commitment: Public<MinSig>,
124 pub(super) share: group::Share,
126}
127
128impl Write for Share {
129 fn write(&self, buf: &mut impl BufMut) {
130 self.commitment.write(buf);
131 self.share.write(buf);
132 }
133}
134
135impl EncodeSize for Share {
136 fn encode_size(&self) -> usize {
137 self.commitment.encode_size() + self.share.encode_size()
138 }
139}
140
141impl Read for Share {
142 type Cfg = u32;
143
144 fn read_cfg(buf: &mut impl Buf, t: &u32) -> Result<Self, commonware_codec::Error> {
145 let q = quorum(*t);
146 Ok(Self {
147 commitment: Public::<MinSig>::read_cfg(buf, &(q as usize))?,
148 share: group::Share::read(buf)?,
149 })
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use commonware_codec::{Encode as _, Read as _};
156 use commonware_cryptography::{
157 PrivateKeyExt as _, Signer as _,
158 bls12381::{dkg, primitives::variant::MinSig},
159 ed25519::{PrivateKey, PublicKey},
160 };
161 use commonware_utils::{set::Ordered, union};
162 use rand::{SeedableRng as _, rngs::StdRng};
163
164 use crate::dkg::ceremony::ACK_NAMESPACE;
165
166 use super::Ack;
167
168 fn three_public_keys() -> Ordered<PublicKey> {
169 vec![
170 PrivateKey::from_seed(0).public_key(),
171 PrivateKey::from_seed(1).public_key(),
172 PrivateKey::from_seed(2).public_key(),
173 ]
174 .into()
175 }
176
177 #[test]
178 fn roundtrip_ack() {
179 let (_, commitment, _) = dkg::Dealer::<_, MinSig>::new(
180 &mut StdRng::from_seed([0; 32]),
181 None,
182 three_public_keys(),
183 );
184 let player = PrivateKey::from_seed(0);
185 let dealer = PrivateKey::from_seed(1).public_key();
186 let ack = Ack::new(
187 &union(b"test", ACK_NAMESPACE),
188 player.clone(),
189 player.public_key(),
190 42,
191 &dealer,
192 &commitment,
193 );
194
195 let bytes = ack.encode();
196
197 assert_eq!(Ack::read_cfg(&mut bytes.as_ref(), &()).unwrap(), ack);
198 }
199}