commonware_broadcast/linked/
prover.rs1use super::{namespace, parsed, serializer, Context, Epoch};
6use crate::Proof;
7use bytes::{Buf, BufMut};
8use commonware_cryptography::{
9 bls12381::primitives::{
10 group::{self, Element},
11 ops,
12 },
13 Array, Scheme,
14};
15use commonware_utils::SizedSerialize;
16use std::marker::PhantomData;
17
18#[derive(Clone)]
23pub struct Prover<C: Scheme, D: Array> {
24 _crypto: PhantomData<C>,
25 _digest: PhantomData<D>,
26 namespace: Vec<u8>,
27 public: group::Public,
28}
29
30impl<C: Scheme, D: Array> Prover<C, D> {
31 const PROOF_LEN: usize = C::PublicKey::SERIALIZED_LEN
33 + u64::SERIALIZED_LEN
34 + D::SERIALIZED_LEN
35 + u64::SERIALIZED_LEN
36 + group::SIGNATURE_LENGTH;
37
38 pub fn new(namespace: &[u8], public: group::Public) -> Self {
40 Self {
41 _crypto: PhantomData,
42 _digest: PhantomData,
43 namespace: namespace::ack(namespace),
44 public,
45 }
46 }
47
48 pub fn serialize_threshold(
50 context: &Context<C::PublicKey>,
51 payload: &D,
52 epoch: Epoch,
53 threshold: &group::Signature,
54 ) -> Proof {
55 let mut proof = Vec::with_capacity(Self::PROOF_LEN);
56
57 proof.extend_from_slice(&context.sequencer);
59 proof.put_u64(context.height);
60 proof.extend_from_slice(payload);
61 proof.put_u64(epoch);
62 proof.extend_from_slice(&threshold.serialize());
63 let result: Proof = proof.into();
64
65 assert!(result.len() == Self::PROOF_LEN);
67 result
68 }
69
70 pub fn deserialize_threshold(
73 &self,
74 mut proof: Proof,
75 ) -> Option<(Context<C::PublicKey>, D, Epoch, group::Signature)> {
76 if proof.len() != Self::PROOF_LEN {
78 return None;
79 }
80
81 let sequencer = C::PublicKey::read_from(&mut proof).ok()?;
83 let height = proof.get_u64();
84 let Ok(payload) = D::read_from(&mut proof) else {
85 return None;
86 };
87 let epoch = proof.get_u64();
88 let threshold = proof.copy_to_bytes(group::SIGNATURE_LENGTH);
89 let threshold = group::Signature::deserialize(&threshold)?;
90
91 let chunk = parsed::Chunk {
93 sequencer: sequencer.clone(),
94 height,
95 payload: payload.clone(),
96 };
97 let msg = serializer::ack(&chunk, epoch);
98 if ops::verify_message(&self.public, Some(&self.namespace), &msg, &threshold).is_err() {
99 return None;
100 }
101
102 Some((Context { sequencer, height }, payload, epoch, threshold))
103 }
104}