Skip to content

Commit f37999a

Browse files
committed
wip
1 parent c3e3213 commit f37999a

File tree

6 files changed

+129
-70
lines changed

6 files changed

+129
-70
lines changed
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Crypto primitives which are used by voting protocol.
22
3-
pub(crate) mod babystep_giantstep;
4-
pub(crate) mod elgamal;
5-
pub(crate) mod group;
6-
pub(crate) mod hash;
7-
pub(crate) mod zk_dl_equality;
8-
pub(crate) mod zk_unit_vector;
3+
pub mod babystep_giantstep;
4+
pub mod elgamal;
5+
pub mod group;
6+
pub mod hash;
7+
pub mod zk_dl_equality;
8+
pub mod zk_unit_vector;

rust/catalyst-voting/src/crypto/zk_unit_vector/mod.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod polynomial;
1111
mod randomness_announcements;
1212
mod utils;
1313

14-
use std::ops::Mul;
14+
use std::{io::Read, ops::Mul};
1515

1616
use challenges::{calculate_first_challenge_hash, calculate_second_challenge_hash};
1717
use polynomial::{calculate_polynomial_val, generate_polynomial, Polynomial};
@@ -25,13 +25,72 @@ use crate::crypto::{
2525
};
2626

2727
/// Unit vector proof struct
28+
#[derive(Debug, Clone, PartialEq, Eq)]
2829
pub struct UnitVectorProof(
2930
Vec<Announcement>,
3031
Vec<Ciphertext>,
3132
Vec<ResponseRandomness>,
3233
Scalar,
3334
);
3435

36+
impl UnitVectorProof {
37+
/// Decode `UnitVectorProof` from bytes.
38+
pub fn from_bytes(mut bytes: &[u8], size: usize) -> Option<Self> {
39+
let mut ann_buf = [0u8; Announcement::BYTES_SIZE];
40+
let mut dl_buf = [0u8; Ciphertext::BYTES_SIZE];
41+
let mut rr_buf = [0u8; ResponseRandomness::BYTES_SIZE];
42+
43+
let ann = (0..size)
44+
.map(|_| {
45+
bytes.read_exact(&mut ann_buf).ok()?;
46+
Announcement::from_bytes(&ann_buf)
47+
})
48+
.collect::<Option<_>>()?;
49+
let dl = (0..size)
50+
.map(|_| {
51+
bytes.read_exact(&mut dl_buf).ok()?;
52+
Ciphertext::from_bytes(&dl_buf)
53+
})
54+
.collect::<Option<_>>()?;
55+
let rr = (0..size)
56+
.map(|_| {
57+
bytes.read_exact(&mut rr_buf).ok()?;
58+
ResponseRandomness::from_bytes(&rr_buf)
59+
})
60+
.collect::<Option<_>>()?;
61+
62+
let mut scalar_buf = [0u8; Scalar::BYTES_SIZE];
63+
bytes.read_exact(&mut scalar_buf).ok()?;
64+
let scalar = Scalar::from_bytes(scalar_buf)?;
65+
Some(Self(ann, dl, rr, scalar))
66+
}
67+
68+
/// Get a deserialized bytes size
69+
#[must_use]
70+
pub fn bytes_size(&self) -> usize {
71+
self.0.len() * Announcement::BYTES_SIZE
72+
+ self.0.len() * Ciphertext::BYTES_SIZE
73+
+ self.0.len() * ResponseRandomness::BYTES_SIZE
74+
}
75+
76+
/// Encode `EncryptedVote` tos bytes.
77+
#[must_use]
78+
pub fn to_bytes(&self) -> Vec<u8> {
79+
let mut res = Vec::with_capacity(self.bytes_size());
80+
self.0
81+
.iter()
82+
.for_each(|c| res.extend_from_slice(&c.to_bytes()));
83+
self.1
84+
.iter()
85+
.for_each(|c| res.extend_from_slice(&c.to_bytes()));
86+
self.2
87+
.iter()
88+
.for_each(|c| res.extend_from_slice(&c.to_bytes()));
89+
res.extend_from_slice(&self.3.to_bytes());
90+
res
91+
}
92+
}
93+
3594
/// Generates a unit vector proof.
3695
///
3796
/// `unit_vector` must be a collection of `Scalar` where only one element is equal to
@@ -232,12 +291,40 @@ fn check_2(
232291

233292
#[cfg(test)]
234293
mod tests {
235-
use proptest::sample::size_range;
294+
use proptest::{
295+
prelude::{any_with, Arbitrary, BoxedStrategy, Strategy},
296+
sample::size_range,
297+
};
236298
use rand_core::OsRng;
237299
use test_strategy::proptest;
238300

239301
use super::{super::elgamal::SecretKey, *};
240302

303+
impl Arbitrary for UnitVectorProof {
304+
type Parameters = usize;
305+
type Strategy = BoxedStrategy<Self>;
306+
307+
fn arbitrary_with(size: Self::Parameters) -> Self::Strategy {
308+
any_with::<(
309+
Vec<((Announcement, Ciphertext), ResponseRandomness)>,
310+
Scalar,
311+
)>(((size_range(size), (((), ()), ())), ()))
312+
.prop_map(|(val, scalar)| {
313+
let (vec, rr): (Vec<_>, Vec<_>) = val.into_iter().unzip();
314+
let (an, ciph) = vec.into_iter().unzip();
315+
Self(an, ciph, rr, scalar)
316+
})
317+
.boxed()
318+
}
319+
}
320+
321+
#[proptest]
322+
fn proof_to_bytes_from_bytes_test(p1: UnitVectorProof) {
323+
let bytes = p1.to_bytes();
324+
let p2 = UnitVectorProof::from_bytes(&bytes, p1.0.len()).unwrap();
325+
assert_eq!(p1, p2);
326+
}
327+
241328
fn is_unit_vector(vector: &[Scalar]) -> bool {
242329
let ones = vector.iter().filter(|s| s == &&Scalar::one()).count();
243330
let zeros = vector.iter().filter(|s| s == &&Scalar::zero()).count();

rust/catalyst-voting/src/crypto/zk_unit_vector/randomness_announcements.rs

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Randomness and announcements structs for the ZK unit vector algorithm
22
3-
#![allow(clippy::missing_docs_in_private_items, dead_code)]
3+
#![allow(clippy::missing_docs_in_private_items)]
44

55
use std::ops::Mul;
66

@@ -37,14 +37,6 @@ pub struct Announcement {
3737
pub(crate) a: GroupElement,
3838
}
3939

40-
/// `EncryptedVote` decoding error
41-
#[derive(thiserror::Error, Debug)]
42-
pub enum AnnouncementDecodingError {
43-
/// Cannot decode ciphertext
44-
#[error("Cannot decode group element {0} field.")]
45-
CannotDecodeGroupElement(char),
46-
}
47-
4840
impl Announcement {
4941
/// `Announcement` bytes size
5042
pub const BYTES_SIZE: usize = GroupElement::BYTES_SIZE * 3;
@@ -71,14 +63,11 @@ impl Announcement {
7163
/// # Errors
7264
/// - `AnnouncementDecodingError`
7365
#[allow(clippy::unwrap_used)]
74-
pub fn from_bytes(bytes: &[u8; Self::BYTES_SIZE]) -> Result<Self, AnnouncementDecodingError> {
75-
let i = GroupElement::from_bytes(bytes[0..32].try_into().unwrap())
76-
.ok_or(AnnouncementDecodingError::CannotDecodeGroupElement('i'))?;
77-
let b = GroupElement::from_bytes(bytes[32..64].try_into().unwrap())
78-
.ok_or(AnnouncementDecodingError::CannotDecodeGroupElement('b'))?;
79-
let a = GroupElement::from_bytes(bytes[64..96].try_into().unwrap())
80-
.ok_or(AnnouncementDecodingError::CannotDecodeGroupElement('a'))?;
81-
Ok(Self { i, b, a })
66+
pub fn from_bytes(bytes: &[u8; Self::BYTES_SIZE]) -> Option<Self> {
67+
let i = GroupElement::from_bytes(bytes[0..32].try_into().unwrap())?;
68+
let b = GroupElement::from_bytes(bytes[32..64].try_into().unwrap())?;
69+
let a = GroupElement::from_bytes(bytes[64..96].try_into().unwrap())?;
70+
Some(Self { i, b, a })
8271
}
8372

8473
/// Encode `Announcement` tos bytes.
@@ -101,14 +90,6 @@ pub struct ResponseRandomness {
10190
pub(crate) v: Scalar,
10291
}
10392

104-
/// `EncryptedVote` decoding error
105-
#[derive(thiserror::Error, Debug)]
106-
pub enum ResponseRandomnessDecodingError {
107-
/// Cannot decode ciphertext
108-
#[error("Cannot decode scalar {0} field.")]
109-
CannotDecodeScalar(char),
110-
}
111-
11293
impl ResponseRandomness {
11394
/// `ResponseRandomness` bytes size
11495
pub const BYTES_SIZE: usize = Scalar::BYTES_SIZE * 3;
@@ -129,16 +110,11 @@ impl ResponseRandomness {
129110
/// # Errors
130111
/// - `ResponseRandomnessDecodingError`
131112
#[allow(clippy::unwrap_used)]
132-
pub fn from_bytes(
133-
bytes: &[u8; Self::BYTES_SIZE],
134-
) -> Result<Self, ResponseRandomnessDecodingError> {
135-
let z = Scalar::from_bytes(bytes[0..32].try_into().unwrap())
136-
.ok_or(ResponseRandomnessDecodingError::CannotDecodeScalar('z'))?;
137-
let w = Scalar::from_bytes(bytes[32..64].try_into().unwrap())
138-
.ok_or(ResponseRandomnessDecodingError::CannotDecodeScalar('w'))?;
139-
let v = Scalar::from_bytes(bytes[64..96].try_into().unwrap())
140-
.ok_or(ResponseRandomnessDecodingError::CannotDecodeScalar('v'))?;
141-
Ok(Self { z, w, v })
113+
pub fn from_bytes(bytes: &[u8; Self::BYTES_SIZE]) -> Option<Self> {
114+
let z = Scalar::from_bytes(bytes[0..32].try_into().unwrap())?;
115+
let w = Scalar::from_bytes(bytes[32..64].try_into().unwrap())?;
116+
let v = Scalar::from_bytes(bytes[64..96].try_into().unwrap())?;
117+
Some(Self { z, w, v })
142118
}
143119

144120
/// Encode `ResponseRandomness` tos bytes.

rust/catalyst-voting/src/txs/v1.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use std::io::Read;
66

7-
use crate::vote_protocol::voter::{DecodingError as EncryptedVoteDecodingError, EncryptedVote};
7+
use crate::vote_protocol::voter::EncryptedVote;
88

99
/// A v1 (Jörmungandr) transaction struct
1010
pub struct Tx {
@@ -61,8 +61,8 @@ pub enum DecodingError {
6161
#[error("Cannot decode encrypted vote size field.")]
6262
CannotDecodeEncryptedVoteSize,
6363
/// Cannot decode encrypted vote
64-
#[error(transparent)]
65-
CannotDecodeEncryptedVote(#[from] EncryptedVoteDecodingError),
64+
#[error("Cannot decode ecnrypted vote field.")]
65+
CannotDecodeEncryptedVote,
6666
}
6767

6868
impl Tx {
@@ -119,7 +119,8 @@ impl Tx {
119119
bytes
120120
.read_exact(&mut u8_buf)
121121
.map_err(|_| DecodingError::CannotDecodeEncryptedVoteSize)?;
122-
let encrypted_vote = EncryptedVote::from_bytes(bytes, u8_buf[0].into())?;
122+
let encrypted_vote = EncryptedVote::from_bytes(bytes, u8_buf[0].into())
123+
.ok_or(DecodingError::CannotDecodeEncryptedVote)?;
123124

124125
Vote::Private(encrypted_vote)
125126
},

rust/catalyst-voting/src/vote_protocol/voter/mod.rs

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,20 @@ impl EncryptionRandomness {
3838
}
3939
}
4040

41-
/// `EncryptedVote` decoding error
42-
#[derive(thiserror::Error, Debug)]
43-
pub enum DecodingError {
44-
/// Cannot decode ciphertext
45-
#[error("Cannot decode ciphertext {0} field.")]
46-
CannotDecodeCiphertext(usize),
47-
}
48-
4941
impl EncryptedVote {
5042
/// Decode `EncryptedVote` from bytes.
51-
///
52-
/// # Errors
53-
/// - `DecodingError`
54-
pub fn from_bytes(mut bytes: &[u8], size: usize) -> Result<Self, DecodingError> {
43+
#[must_use]
44+
pub fn from_bytes(mut bytes: &[u8], size: usize) -> Option<Self> {
5545
let mut ciph_buf = [0u8; Ciphertext::BYTES_SIZE];
5646

57-
let mut ciphertexts = Vec::with_capacity(size);
58-
for i in 0..size {
59-
bytes
60-
.read_exact(&mut ciph_buf)
61-
.map_err(|_| DecodingError::CannotDecodeCiphertext(i))?;
62-
ciphertexts.push(
47+
let ciphertexts = (0..size)
48+
.map(|_| {
49+
bytes.read_exact(&mut ciph_buf).ok()?;
6350
Ciphertext::from_bytes(&ciph_buf)
64-
.ok_or(DecodingError::CannotDecodeCiphertext(i))?,
65-
);
66-
}
67-
Ok(Self(ciphertexts))
51+
})
52+
.collect::<Option<_>>()?;
53+
54+
Some(Self(ciphertexts))
6855
}
6956

7057
/// Get a deserialized bytes size

rust/catalyst-voting/src/vote_protocol/voter/proof.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Voter proof generation and verification procedures.
22
//! It allows to transparently verify the correctness voter generation and encryption.
33
4-
use std::ops::Mul;
4+
use std::ops::{Deref, Mul};
55

66
use rand_core::CryptoRngCore;
77

@@ -18,6 +18,14 @@ use crate::{
1818
#[allow(clippy::module_name_repetitions)]
1919
pub struct VoterProof(UnitVectorProof);
2020

21+
impl Deref for VoterProof {
22+
type Target = UnitVectorProof;
23+
24+
fn deref(&self) -> &Self::Target {
25+
&self.0
26+
}
27+
}
28+
2129
/// Voter proof commitment struct.
2230
pub struct VoterProofCommitment(GroupElement);
2331

0 commit comments

Comments
 (0)