Skip to content

Commit 5b35061

Browse files
committed
wip
1 parent f37999a commit 5b35061

File tree

2 files changed

+90
-58
lines changed

2 files changed

+90
-58
lines changed

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

Lines changed: 56 additions & 53 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::EncryptedVote;
7+
use crate::vote_protocol::voter::{proof::VoterProof, EncryptedVote};
88

99
/// A v1 (Jörmungandr) transaction struct
1010
pub struct Tx {
@@ -21,112 +21,115 @@ pub enum Vote {
2121
/// Public voting choice
2222
Public(u8),
2323
/// Private (encrypted) voting choice
24-
Private(EncryptedVote),
24+
Private(EncryptedVote, VoterProof),
2525
}
2626

2727
/// `Tx` decoding error
2828
#[derive(thiserror::Error, Debug)]
2929
pub enum DecodingError {
30-
/// Cannot decode tx size
31-
#[error("Cannot decode `u32` tx size field.")]
32-
CannotDecodeTxSize,
33-
/// Cannot decode padding tag
34-
#[error("Cannot decode `u8` padding tag field.")]
35-
CannotDecodePaddingTag,
30+
/// `std::io::Error`
31+
#[error(transparent)]
32+
IoRead(#[from] std::io::Error),
3633
/// Invalid padding tag
3734
#[error("Invalid padding tag field value, must be equals to `0`, provided: {0}.")]
3835
InvalidPaddingTag(u8),
39-
/// Cannot decode fragment tag
40-
#[error("Cannot decode `u8` fragment tag field.")]
41-
CannotDecodeFragmentTag,
4236
/// Invalid fragment tag
4337
#[error("Invalid fragment tag field value, must be equals to `11`, provided: {0}.")]
4438
InvalidFragmentTag(u8),
45-
/// Cannot decode vote plan id
46-
#[error("Cannot decode vote plan id field.")]
47-
CannotDecodeVotePlanId,
48-
/// Cannot decode proposal index
49-
#[error("Cannot decode proposal index field.")]
50-
CannotDecodeProposalIndex,
51-
/// Cannot decode vote tag
52-
#[error("Cannot decode vote tag field.")]
53-
CannotDecodeVoteTag,
5439
/// Cannot decode vote tag
5540
#[error("Invalid vote tag value, must be equals to `0` or `1`, provided: {0}")]
5641
InvalidVoteTag(u8),
57-
/// Cannot decode public vote
58-
#[error("Cannot decode public vote field.")]
59-
CannotDecodePublicVote,
60-
/// Cannot decode ciphertexts array size
61-
#[error("Cannot decode encrypted vote size field.")]
62-
CannotDecodeEncryptedVoteSize,
6342
/// Cannot decode encrypted vote
6443
#[error("Cannot decode ecnrypted vote field.")]
6544
CannotDecodeEncryptedVote,
45+
/// Cannot decode voter proof field
46+
#[error("Cannot decode voter proof field.")]
47+
CannotDecodeVoterProof,
48+
/// Invalid number of inputs
49+
#[error("Invalid number of inputs, expected: `1`, provided: {0}")]
50+
InvalidNumberOfInputs(u8),
51+
/// Invalid number of outputs
52+
#[error("Invalid number of outputs, expected: `0`, provided: {0}")]
53+
InvalidNumberOfOutputs(u8),
54+
/// Invalid input tag
55+
#[error("Invalid input tag, expected: `255`, provided: {0}")]
56+
InvalidInputTag(u8),
6657
}
6758

6859
impl Tx {
6960
/// Decode `Tx` from bytes.
7061
///
7162
/// # Errors
7263
/// - `DecodingError`
64+
#[allow(clippy::indexing_slicing)]
7365
pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, DecodingError> {
74-
let mut u32_buf = [0u8; 4];
7566
let mut u8_buf = [0u8; 1];
67+
let mut u32_buf = [0u8; 4];
68+
let mut u64_buf = [0u8; 8];
7669
let mut u256_buf = [0u8; 32];
7770
// let mut u512_buf = [0u8; 64];
7871

79-
bytes
80-
.read_exact(&mut u32_buf)
81-
.map_err(|_| DecodingError::CannotDecodeTxSize)?;
72+
bytes.read_exact(&mut u32_buf)?;
8273
let tx_size = u32::from_be_bytes(u32_buf);
8374

84-
bytes
85-
.read_exact(&mut u8_buf)
86-
.map_err(|_| DecodingError::CannotDecodePaddingTag)?;
75+
bytes.read_exact(&mut u8_buf)?;
8776
if u8_buf[0] != 0 {
8877
return Err(DecodingError::InvalidPaddingTag(u8_buf[0]));
8978
}
9079

91-
bytes
92-
.read_exact(&mut u8_buf)
93-
.map_err(|_| DecodingError::CannotDecodeFragmentTag)?;
80+
bytes.read_exact(&mut u8_buf)?;
9481
if u8_buf[0] != 11 {
9582
return Err(DecodingError::InvalidFragmentTag(u8_buf[0]));
9683
}
9784

98-
bytes
99-
.read_exact(&mut u256_buf)
100-
.map_err(|_| DecodingError::CannotDecodeVotePlanId)?;
85+
bytes.read_exact(&mut u256_buf)?;
10186
let vote_plan_id = u256_buf;
10287

103-
bytes
104-
.read_exact(&mut u8_buf)
105-
.map_err(|_| DecodingError::CannotDecodeProposalIndex)?;
88+
bytes.read_exact(&mut u8_buf)?;
10689
let proposal_index = u8_buf[0];
10790

108-
bytes
109-
.read_exact(&mut u8_buf)
110-
.map_err(|_| DecodingError::CannotDecodeVoteTag)?;
91+
bytes.read_exact(&mut u8_buf)?;
11192
let vote = match u8_buf[0] {
11293
1 => {
113-
bytes
114-
.read_exact(&mut u8_buf)
115-
.map_err(|_| DecodingError::CannotDecodePublicVote)?;
94+
bytes.read_exact(&mut u8_buf)?;
11695
Vote::Public(u8_buf[0])
11796
},
11897
2 => {
119-
bytes
120-
.read_exact(&mut u8_buf)
121-
.map_err(|_| DecodingError::CannotDecodeEncryptedVoteSize)?;
122-
let encrypted_vote = EncryptedVote::from_bytes(bytes, u8_buf[0].into())
98+
bytes.read_exact(&mut u8_buf)?;
99+
let vote = EncryptedVote::from_bytes(bytes, u8_buf[0].into())
123100
.ok_or(DecodingError::CannotDecodeEncryptedVote)?;
101+
bytes = &bytes[vote.bytes_size()..];
124102

125-
Vote::Private(encrypted_vote)
103+
bytes.read_exact(&mut u8_buf)?;
104+
let proof = VoterProof::from_bytes(bytes, u8_buf[0].into())
105+
.ok_or(DecodingError::CannotDecodeVoterProof)?;
106+
bytes = &bytes[vote.bytes_size()..];
107+
108+
Vote::Private(vote, proof)
126109
},
127110
tag => return Err(DecodingError::InvalidVoteTag(tag)),
128111
};
129112

113+
// skip block date (epoch and slot)
114+
bytes.read_exact(&mut u64_buf)?;
115+
116+
bytes.read_exact(&mut u8_buf)?;
117+
if u8_buf[0] != 1 {
118+
return Err(DecodingError::InvalidNumberOfInputs(u8_buf[0]));
119+
}
120+
bytes.read_exact(&mut u8_buf)?;
121+
if u8_buf[0] != 0 {
122+
return Err(DecodingError::InvalidNumberOfOutputs(u8_buf[0]));
123+
}
124+
125+
bytes.read_exact(&mut u8_buf)?;
126+
if u8_buf[0] != 0xFF {
127+
return Err(DecodingError::InvalidInputTag(u8_buf[0]));
128+
}
129+
130+
// skip value
131+
bytes.read_exact(&mut u64_buf)?;
132+
130133
Ok(Self {
131134
vote_plan_id,
132135
proposal_index,

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

Lines changed: 34 additions & 5 deletions
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::{Deref, Mul};
4+
use std::ops::Mul;
55

66
use rand_core::CryptoRngCore;
77

@@ -16,13 +16,26 @@ use crate::{
1616

1717
/// Tally proof struct.
1818
#[allow(clippy::module_name_repetitions)]
19+
#[derive(Debug, Clone, PartialEq, Eq)]
1920
pub struct VoterProof(UnitVectorProof);
2021

21-
impl Deref for VoterProof {
22-
type Target = UnitVectorProof;
22+
impl VoterProof {
23+
/// Decode `VoterProof` from bytes.
24+
#[must_use]
25+
pub fn from_bytes(bytes: &[u8], size: usize) -> Option<Self> {
26+
UnitVectorProof::from_bytes(bytes, size).map(Self)
27+
}
28+
29+
/// Get a deserialized bytes size
30+
#[must_use]
31+
pub fn bytes_size(&self) -> usize {
32+
self.0.bytes_size()
33+
}
2334

24-
fn deref(&self) -> &Self::Target {
25-
&self.0
35+
/// Encode `EncryptedVote` tos bytes.
36+
#[must_use]
37+
pub fn to_bytes(&self) -> Vec<u8> {
38+
self.0.to_bytes()
2639
}
2740
}
2841

@@ -83,3 +96,19 @@ pub fn verify_voter_proof(
8396
) -> bool {
8497
verify_unit_vector_proof(&proof.0, encrypted_vote.0, public_key, &commitment.0)
8598
}
99+
100+
#[cfg(test)]
101+
mod tests {
102+
use proptest::prelude::{any_with, Arbitrary, BoxedStrategy, Strategy};
103+
104+
use super::*;
105+
106+
impl Arbitrary for VoterProof {
107+
type Parameters = usize;
108+
type Strategy = BoxedStrategy<Self>;
109+
110+
fn arbitrary_with(size: Self::Parameters) -> Self::Strategy {
111+
any_with::<UnitVectorProof>(size).prop_map(Self).boxed()
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)