44
55use 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
1010pub 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 ) ]
2929pub 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
6859impl 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,
0 commit comments