coconut_crypto/proof/
mod.rs1use alloc::vec::Vec;
4
5pub mod messages_pok;
6pub mod signature_pok;
7
8use ark_ff::PrimeField;
9
10use ark_std::rand::RngCore;
11
12use itertools::process_results;
13use serde::{Deserialize, Serialize};
14use serde_with::serde_as;
15use utils::serde_utils::ArkObjectBytes;
16
17pub use messages_pok::*;
18pub use signature_pok::*;
19
20use crate::helpers::{pair_with_slice, rand, IndexIsOutOfBounds};
21
22#[serde_as]
25#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
26#[serde(bound = "")]
27pub enum CommitMessage<F: PrimeField> {
28 BlindMessageRandomly(#[serde_as(as = "ArkObjectBytes")] F),
30 RevealMessage,
32 BlindMessageWithConcreteBlinding {
34 #[serde_as(as = "ArkObjectBytes")]
35 message: F,
36 #[serde_as(as = "ArkObjectBytes")]
37 blinding: F,
38 },
39}
40
41impl<F: PrimeField> CommitMessage<F> {
42 pub fn split<R: RngCore>(self, rng: &mut R) -> Option<(F, F)> {
44 match self {
45 Self::BlindMessageRandomly(message) => Some((message, rand(rng))),
46 Self::BlindMessageWithConcreteBlinding { message, blinding } => {
47 Some((message, blinding))
48 }
49 Self::RevealMessage => None,
50 }
51 }
52
53 pub fn blind_message_with(message: F, blinding: F) -> Self {
55 Self::BlindMessageWithConcreteBlinding { message, blinding }
56 }
57}
58
59impl<F: PrimeField> From<F> for CommitMessage<F> {
60 fn from(message: F) -> Self {
61 Self::BlindMessageRandomly(message)
62 }
63}
64
65impl<F: PrimeField> From<&'_ F> for CommitMessage<F> {
66 fn from(&message: &'_ F) -> Self {
67 Self::BlindMessageRandomly(message)
68 }
69}
70
71impl<F: PrimeField> From<(F, F)> for CommitMessage<F> {
72 fn from((message, blinding): (F, F)) -> Self {
73 Self::BlindMessageWithConcreteBlinding { message, blinding }
74 }
75}
76
77impl<F: PrimeField> From<(F, Option<F>)> for CommitMessage<F> {
78 fn from((message, blinding): (F, Option<F>)) -> Self {
79 if let Some(blinding) = blinding {
80 Self::BlindMessageWithConcreteBlinding { message, blinding }
81 } else {
82 Self::BlindMessageRandomly(message)
83 }
84 }
85}
86
87impl<F: PrimeField> From<Option<F>> for CommitMessage<F> {
88 fn from(opt: Option<F>) -> Self {
89 match opt {
90 Some(msg) => Self::BlindMessageRandomly(msg),
91 None => Self::RevealMessage,
92 }
93 }
94}
95
96impl<F: PrimeField> From<Option<&'_ F>> for CommitMessage<F> {
97 fn from(opt: Option<&'_ F>) -> Self {
98 match opt {
99 Some(&msg) => Self::BlindMessageRandomly(msg),
100 None => Self::RevealMessage,
101 }
102 }
103}
104
105impl<F: PrimeField> From<(&'_ F, F)> for CommitMessage<F> {
106 fn from((&message, blinding): (&'_ F, F)) -> Self {
107 Self::BlindMessageWithConcreteBlinding { message, blinding }
108 }
109}
110
111impl<F: PrimeField> From<(&'_ F, &'_ F)> for CommitMessage<F> {
112 fn from((&message, &blinding): (&'_ F, &'_ F)) -> Self {
113 Self::BlindMessageWithConcreteBlinding { message, blinding }
114 }
115}
116
117impl<F: PrimeField> From<(&'_ F, Option<F>)> for CommitMessage<F> {
118 fn from((&message, blinding): (&'_ F, Option<F>)) -> Self {
119 if let Some(blinding) = blinding {
120 Self::BlindMessageWithConcreteBlinding { message, blinding }
121 } else {
122 Self::BlindMessageRandomly(message)
123 }
124 }
125}
126
127impl<F: PrimeField> From<(&'_ F, Option<&'_ F>)> for CommitMessage<F> {
128 fn from((&message, blinding): (&'_ F, Option<&'_ F>)) -> Self {
129 if let Some(blinding) = blinding.copied() {
130 Self::BlindMessageWithConcreteBlinding { message, blinding }
131 } else {
132 Self::BlindMessageRandomly(message)
133 }
134 }
135}
136
137#[derive(Debug, PartialEq, Eq, Clone)]
140struct UnpackedBlindedMessages<'pair, Pair, F>(pub Vec<&'pair Pair>, pub Vec<F>, pub Vec<F>);
141
142#[derive(Clone, Debug, PartialEq, Eq)]
143pub enum MessageUnpackingError {
144 MessageIndexIsOutOfBounds(IndexIsOutOfBounds),
145 NoMessagesProvided,
146 LessMessagesThanExpected { provided: usize, expected: usize },
147}
148
149impl From<IndexIsOutOfBounds> for MessageUnpackingError {
150 fn from(err: IndexIsOutOfBounds) -> Self {
151 Self::MessageIndexIsOutOfBounds(err)
152 }
153}
154
155impl<'pair, Pair, F: PrimeField> UnpackedBlindedMessages<'pair, Pair, F> {
156 pub fn new(
161 rng: &mut impl RngCore,
162 messages: impl IntoIterator<Item = impl Into<CommitMessage<F>>>,
163 pair_with: &'pair [Pair],
164 ) -> Result<Self, MessageUnpackingError> {
165 let mut total_count = 0;
166 let indexed_blinded_msgs = messages
167 .into_iter()
168 .map(Into::into)
169 .enumerate()
170 .inspect(|_| total_count += 1)
171 .filter_map(|(idx, msg_with_blinding)| {
172 msg_with_blinding.split(rng).map(|split| (idx, split))
173 });
174
175 let paired = pair_with_slice(indexed_blinded_msgs, pair_with);
177
178 let (paired, (msgs, blindings)): (Vec<_>, _) =
179 process_results(paired, |iter| iter.unzip())?;
180 if pair_with.len() != total_count {
181 Err(MessageUnpackingError::LessMessagesThanExpected {
182 provided: total_count,
183 expected: pair_with.len(),
184 })
185 } else {
186 Ok(Self(paired, msgs, blindings))
187 }
188 }
189}