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 , Weak } ;
18+
19+ use ccrypto:: { blake256, Blake } ;
20+ use ckey:: { recover, verify_schnorr, Address , Public , Signature } ;
21+ use client:: ConsensusClient ;
22+ use consensus:: vote_collector:: Message ;
1923use ctypes:: errors:: SyntaxError ;
2024use ctypes:: CommonParams ;
2125use primitives:: { Bytes , H256 } ;
2226use rlp:: { Decodable , DecoderError , Encodable , RlpStream , UntrustedRlp } ;
2327
28+ use consensus:: stake:: get_validators;
29+
2430const ACTION_TAG_TRANSFER_CCS : u8 = 1 ;
2531const ACTION_TAG_DELEGATE_CCS : u8 = 2 ;
2632const ACTION_TAG_REVOKE : u8 = 3 ;
2733const ACTION_TAG_SELF_NOMINATE : u8 = 4 ;
34+ const ACTION_TAG_REPORT_DOUBLE_VOTE : u8 = 5 ;
2835const ACTION_TAG_CHANGE_PARAMS : u8 = 0xFF ;
2936
3037#[ derive( Debug , PartialEq ) ]
31- pub enum Action {
38+ pub enum Action < M : Message > {
3239 TransferCCS {
3340 address : Address ,
3441 quantity : u64 ,
@@ -50,10 +57,18 @@ pub enum Action {
5057 params : Box < CommonParams > ,
5158 signatures : Vec < Signature > ,
5259 } ,
60+ ReportDoubleVote {
61+ message1 : M ,
62+ message2 : M ,
63+ } ,
5364}
5465
55- impl Action {
56- pub fn verify ( & self , current_params : & CommonParams ) -> Result < ( ) , SyntaxError > {
66+ impl < M : Message > Action < M > {
67+ pub fn verify (
68+ & self ,
69+ current_params : & CommonParams ,
70+ client : Option < Weak < ConsensusClient > > ,
71+ ) -> Result < ( ) , SyntaxError > {
5772 match self {
5873 Action :: TransferCCS {
5974 ..
@@ -89,7 +104,7 @@ impl Action {
89104 ) ) )
90105 }
91106 params. verify ( ) . map_err ( SyntaxError :: InvalidCustomAction ) ?;
92- let action = Action :: ChangeParams {
107+ let action = Action :: < M > :: ChangeParams {
93108 metadata_seq : * metadata_seq,
94109 params : params. clone ( ) ,
95110 signatures : vec ! [ ] ,
@@ -102,12 +117,60 @@ impl Action {
102117 } ) ?;
103118 }
104119 }
120+ Action :: ReportDoubleVote {
121+ message1,
122+ message2,
123+ } => {
124+ // what is the general verifying for general message?
125+ let message_for_signature = message1. message_for_signature ( ) ;
126+ let message_hash = blake256 ( & message_for_signature) ;
127+
128+ let signature1 = message1. signature ( ) ;
129+ let signature2 = message2. signature ( ) ;
130+
131+ let signer_idx1 = message1. signer_index ( ) ;
132+ let signer_idx2 = message2. signer_index ( ) ;
133+
134+ let signed_block_hash = message1. block_hash ( ) ;
135+ let client: Arc < ConsensusClient > =
136+ client. as_ref ( ) . and_then ( Weak :: upgrade) . expect ( "Client must be initialized" ) ;
137+ let parent_block_hash = signed_block_hash
138+ . and_then ( |hash| client. block_header ( & hash. into ( ) ) )
139+ . ok_or_else ( || {
140+ SyntaxError :: InvalidCustomAction ( String :: from (
141+ "Cannot get parent header from message's block_hash" ,
142+ ) )
143+ } ) ?
144+ . parent_hash ( ) ;
145+
146+ let parent_state = client. state_at ( parent_block_hash. into ( ) ) . ok_or_else ( || {
147+ SyntaxError :: InvalidCustomAction ( String :: from (
148+ "Cannot read state from the given message's parent hash" ,
149+ ) )
150+ } ) ?;
151+ let signers_vec: Vec < Public > = get_validators ( & parent_state)
152+ . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
153+ . map_err ( |_| {
154+ SyntaxError :: InvalidCustomAction ( String :: from ( "Cannot get validators from parent_state" ) )
155+ } ) ?;
156+
157+ let signer1 = signers_vec. get ( signer_idx1) . ok_or_else ( || {
158+ SyntaxError :: InvalidCustomAction ( String :: from ( "Invalid signer index in message1" ) )
159+ } ) ?;
160+ let signer2 = signers_vec. get ( signer_idx2) . ok_or_else ( || {
161+ SyntaxError :: InvalidCustomAction ( String :: from ( "Invalid signer index in message2" ) )
162+ } ) ?;
163+
164+ verify_schnorr ( signer1, & signature1, & message_hash)
165+ . and ( verify_schnorr ( signer2, & signature2, & message_hash) )
166+ . map_err ( |err| SyntaxError :: InvalidCustomAction ( format ! ( "{}" , err) ) ) ?;
167+ }
105168 }
106169 Ok ( ( ) )
107170 }
108171}
109172
110- impl Encodable for Action {
173+ impl < M : Message > Encodable for Action < M > {
111174 fn rlp_append ( & self , s : & mut RlpStream ) {
112175 match self {
113176 Action :: TransferCCS {
@@ -147,11 +210,17 @@ impl Encodable for Action {
147210 s. append ( signature) ;
148211 }
149212 }
213+ Action :: ReportDoubleVote {
214+ message1,
215+ message2,
216+ } => {
217+ s. begin_list ( 3 ) . append ( & ACTION_TAG_REPORT_DOUBLE_VOTE ) . append ( message1) . append ( message2) ;
218+ }
150219 } ;
151220 }
152221}
153222
154- impl Decodable for Action {
223+ impl < M : Message > Decodable for Action < M > {
155224 fn decode ( rlp : & UntrustedRlp ) -> Result < Self , DecoderError > {
156225 let tag = rlp. val_at ( 0 ) ?;
157226 match tag {
@@ -224,6 +293,21 @@ impl Decodable for Action {
224293 signatures,
225294 } )
226295 }
296+ ACTION_TAG_REPORT_DOUBLE_VOTE => {
297+ let item_count = rlp. item_count ( ) ?;
298+ if item_count != 3 {
299+ return Err ( DecoderError :: RlpIncorrectListLen {
300+ expected : 3 ,
301+ got : item_count,
302+ } )
303+ }
304+ let message1 = rlp. val_at ( 1 ) ?;
305+ let message2 = rlp. val_at ( 2 ) ?;
306+ Ok ( Action :: ReportDoubleVote {
307+ message1,
308+ message2,
309+ } )
310+ }
227311 _ => Err ( DecoderError :: Custom ( "Unexpected Tendermint Stake Action Type" ) ) ,
228312 }
229313 }
@@ -247,7 +331,7 @@ mod tests {
247331 expected: 4 ,
248332 got: 3 ,
249333 } ) ,
250- UntrustedRlp :: new( & rlp:: encode( & action) ) . as_val:: <Action >( )
334+ UntrustedRlp :: new( & rlp:: encode( & action) ) . as_val:: <Action >:: <_> ( )
251335 ) ;
252336 }
253337
0 commit comments