1414// You should have received a copy of the GNU Affero General Public License
1515// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616
17- use ccrypto:: Blake ;
18- use ckey:: { recover, Address , Signature } ;
17+ use std:: sync:: Arc ;
18+
19+ use ccrypto:: { blake256, Blake } ;
20+ use ckey:: { recover, verify_schnorr, Address , Public , Signature } ;
21+ use client:: ConsensusClient ;
22+ use consensus:: stake:: get_validators;
23+ use consensus:: vote_collector:: Message ;
1924use ctypes:: errors:: SyntaxError ;
2025use ctypes:: CommonParams ;
2126use primitives:: { Bytes , H256 } ;
@@ -25,10 +30,11 @@ const ACTION_TAG_TRANSFER_CCS: u8 = 1;
2530const ACTION_TAG_DELEGATE_CCS : u8 = 2 ;
2631const ACTION_TAG_REVOKE : u8 = 3 ;
2732const ACTION_TAG_SELF_NOMINATE : u8 = 4 ;
33+ const ACTION_TAG_REPORT_DOUBLE_VOTE : u8 = 5 ;
2834const ACTION_TAG_CHANGE_PARAMS : u8 = 0xFF ;
2935
3036#[ derive( Debug , PartialEq ) ]
31- pub enum Action {
37+ pub enum Action < M : Message > {
3238 TransferCCS {
3339 address : Address ,
3440 quantity : u64 ,
@@ -50,10 +56,18 @@ pub enum Action {
5056 params : Box < CommonParams > ,
5157 signatures : Vec < Signature > ,
5258 } ,
59+ ReportDoubleVote {
60+ message1 : M ,
61+ message2 : M ,
62+ } ,
5363}
5464
55- impl Action {
56- pub fn verify ( & self , current_params : & CommonParams ) -> Result < ( ) , SyntaxError > {
65+ impl < M : Message > Action < M > {
66+ pub fn verify (
67+ & self ,
68+ current_params : & CommonParams ,
69+ client : Option < Arc < ConsensusClient > > ,
70+ ) -> Result < ( ) , SyntaxError > {
5771 match self {
5872 Action :: TransferCCS {
5973 ..
@@ -89,7 +103,7 @@ impl Action {
89103 ) ) )
90104 }
91105 params. verify ( ) . map_err ( SyntaxError :: InvalidCustomAction ) ?;
92- let action = Action :: ChangeParams {
106+ let action = Action :: < M > :: ChangeParams {
93107 metadata_seq : * metadata_seq,
94108 params : params. clone ( ) ,
95109 signatures : vec ! [ ] ,
@@ -102,12 +116,59 @@ impl Action {
102116 } ) ?;
103117 }
104118 }
119+ Action :: ReportDoubleVote {
120+ message1,
121+ message2,
122+ } => {
123+ // what is the general verifying for general message?
124+ let message_for_signature = message1. message_for_signature ( ) ;
125+ let message_hash = blake256 ( & message_for_signature) ;
126+
127+ let signature1 = message1. signature ( ) ;
128+ let signature2 = message2. signature ( ) ;
129+
130+ let signer_idx1 = message1. signer_index ( ) ;
131+ let signer_idx2 = message2. signer_index ( ) ;
132+
133+ let signed_block_hash = message1. block_hash ( ) ;
134+ let client = client. expect ( "Client should be initialized" ) ;
135+ let parent_block_hash = signed_block_hash
136+ . and_then ( |hash| client. block_header ( & hash. into ( ) ) )
137+ . ok_or_else ( || {
138+ SyntaxError :: InvalidCustomAction ( String :: from (
139+ "Cannot get parent header from message's block_hash" ,
140+ ) )
141+ } ) ?
142+ . parent_hash ( ) ;
143+
144+ let parent_state = client. state_at ( parent_block_hash. into ( ) ) . ok_or_else ( || {
145+ SyntaxError :: InvalidCustomAction ( String :: from (
146+ "Cannot read state from the given message's parent hash" ,
147+ ) )
148+ } ) ?;
149+ let signers_vec: Vec < Public > = get_validators ( & parent_state)
150+ . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
151+ . map_err ( |_| {
152+ SyntaxError :: InvalidCustomAction ( String :: from ( "Cannot get validators from parent_state" ) )
153+ } ) ?;
154+
155+ let signer1 = signers_vec. get ( signer_idx1) . ok_or_else ( || {
156+ SyntaxError :: InvalidCustomAction ( String :: from ( "Invalid signer index in message1" ) )
157+ } ) ?;
158+ let signer2 = signers_vec. get ( signer_idx2) . ok_or_else ( || {
159+ SyntaxError :: InvalidCustomAction ( String :: from ( "Invalid signer index in message2" ) )
160+ } ) ?;
161+
162+ verify_schnorr ( signer1, & signature1, & message_hash)
163+ . and ( verify_schnorr ( signer2, & signature2, & message_hash) )
164+ . map_err ( |err| SyntaxError :: InvalidCustomAction ( format ! ( "{}" , err) ) ) ?;
165+ }
105166 }
106167 Ok ( ( ) )
107168 }
108169}
109170
110- impl Encodable for Action {
171+ impl < M : Message > Encodable for Action < M > {
111172 fn rlp_append ( & self , s : & mut RlpStream ) {
112173 match self {
113174 Action :: TransferCCS {
@@ -147,11 +208,17 @@ impl Encodable for Action {
147208 s. append ( signature) ;
148209 }
149210 }
211+ Action :: ReportDoubleVote {
212+ message1,
213+ message2,
214+ } => {
215+ s. begin_list ( 3 ) . append ( & ACTION_TAG_REPORT_DOUBLE_VOTE ) . append ( message1) . append ( message2) ;
216+ }
150217 } ;
151218 }
152219}
153220
154- impl Decodable for Action {
221+ impl < M : Message > Decodable for Action < M > {
155222 fn decode ( rlp : & UntrustedRlp ) -> Result < Self , DecoderError > {
156223 let tag = rlp. val_at ( 0 ) ?;
157224 match tag {
@@ -224,6 +291,21 @@ impl Decodable for Action {
224291 signatures,
225292 } )
226293 }
294+ ACTION_TAG_REPORT_DOUBLE_VOTE => {
295+ let item_count = rlp. item_count ( ) ?;
296+ if item_count != 3 {
297+ return Err ( DecoderError :: RlpIncorrectListLen {
298+ expected : 3 ,
299+ got : item_count,
300+ } )
301+ }
302+ let message1 = rlp. val_at ( 1 ) ?;
303+ let message2 = rlp. val_at ( 2 ) ?;
304+ Ok ( Action :: ReportDoubleVote {
305+ message1,
306+ message2,
307+ } )
308+ }
227309 _ => Err ( DecoderError :: Custom ( "Unexpected Tendermint Stake Action Type" ) ) ,
228310 }
229311 }
@@ -247,7 +329,7 @@ mod tests {
247329 expected: 4 ,
248330 got: 3 ,
249331 } ) ,
250- UntrustedRlp :: new( & rlp:: encode( & action) ) . as_val:: <Action >( )
332+ UntrustedRlp :: new( & rlp:: encode( & action) ) . as_val:: <Action >:: <_> ( )
251333 ) ;
252334 }
253335
0 commit comments