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 ccrypto:: { blake256 , Blake } ;
18+ use ckey:: { recover, verify_schnorr , Address , Public , Signature } ;
1919use ctypes:: errors:: SyntaxError ;
2020use ctypes:: CommonParams ;
2121use primitives:: { Bytes , H256 } ;
2222use rlp:: { Decodable , DecoderError , Encodable , RlpStream , UntrustedRlp } ;
2323
24+ use consensus:: vote_collector:: Message ;
25+
2426const ACTION_TAG_TRANSFER_CCS : u8 = 1 ;
2527const ACTION_TAG_DELEGATE_CCS : u8 = 2 ;
2628const ACTION_TAG_REVOKE : u8 = 3 ;
2729const ACTION_TAG_SELF_NOMINATE : u8 = 4 ;
30+ const ACTION_TAG_REPORT_DOUBLE_VOTE : u8 = 5 ;
2831const ACTION_TAG_CHANGE_PARAMS : u8 = 0xFF ;
2932
3033#[ derive( Debug , PartialEq ) ]
31- pub enum Action {
34+ pub enum Action < M : Message > {
3235 TransferCCS {
3336 address : Address ,
3437 quantity : u64 ,
@@ -50,10 +53,14 @@ pub enum Action {
5053 params : Box < CommonParams > ,
5154 signatures : Vec < Signature > ,
5255 } ,
56+ ReportDoubleVote {
57+ message1 : M ,
58+ message2 : M ,
59+ } ,
5360}
5461
55- impl Action {
56- pub fn verify ( & self , current_params : & CommonParams ) -> Result < ( ) , SyntaxError > {
62+ impl < M : Message > Action < M > {
63+ pub fn verify ( & self , current_params : & CommonParams , signers : Option < Vec < Public > > ) -> Result < ( ) , SyntaxError > {
5764 match self {
5865 Action :: TransferCCS {
5966 ..
@@ -89,7 +96,7 @@ impl Action {
8996 ) ) )
9097 }
9198 params. verify ( ) . map_err ( SyntaxError :: InvalidCustomAction ) ?;
92- let action = Action :: ChangeParams {
99+ let action = Action :: < M > :: ChangeParams {
93100 metadata_seq : * metadata_seq,
94101 params : params. clone ( ) ,
95102 signatures : vec ! [ ] ,
@@ -102,12 +109,42 @@ impl Action {
102109 } ) ?;
103110 }
104111 }
112+ Action :: ReportDoubleVote {
113+ message1,
114+ message2,
115+ } => {
116+ // what is the general verifying for general message?
117+ let message_for_signature = message1. message_for_signature ( ) ;
118+ let message_hash = blake256 ( & message_for_signature) ;
119+
120+ let signature1 = message1. signature ( ) ;
121+ let signature2 = message2. signature ( ) ;
122+
123+ let signer_idx1 = message1. signer_index ( ) ;
124+ let signer_idx2 = message2. signer_index ( ) ;
125+
126+ let signers = signers. ok_or_else ( || {
127+ SyntaxError :: InvalidCustomAction ( String :: from (
128+ "ReportDoubleVote Custom action is invalid for consensus engines without validators" ,
129+ ) )
130+ } ) ?;
131+ let signer1 = signers
132+ . get ( signer_idx1)
133+ . ok_or_else ( || SyntaxError :: InvalidCustomAction ( String :: from ( "Invalid signer index" ) ) ) ?;
134+ let signer2 = signers
135+ . get ( signer_idx2)
136+ . ok_or_else ( || SyntaxError :: InvalidCustomAction ( String :: from ( "Invalid signer index" ) ) ) ?;
137+
138+ verify_schnorr ( signer1, & signature1, & message_hash)
139+ . and ( verify_schnorr ( signer2, & signature2, & message_hash) )
140+ . map_err ( |err| SyntaxError :: InvalidCustomAction ( format ! ( "{}" , err) ) ) ?;
141+ }
105142 }
106143 Ok ( ( ) )
107144 }
108145}
109146
110- impl Encodable for Action {
147+ impl < M : Message > Encodable for Action < M > {
111148 fn rlp_append ( & self , s : & mut RlpStream ) {
112149 match self {
113150 Action :: TransferCCS {
@@ -147,11 +184,17 @@ impl Encodable for Action {
147184 s. append ( signature) ;
148185 }
149186 }
187+ Action :: ReportDoubleVote {
188+ message1,
189+ message2,
190+ } => {
191+ s. begin_list ( 3 ) . append ( & ACTION_TAG_REPORT_DOUBLE_VOTE ) . append ( message1) . append ( message2) ;
192+ }
150193 } ;
151194 }
152195}
153196
154- impl Decodable for Action {
197+ impl < M : Message > Decodable for Action < M > {
155198 fn decode ( rlp : & UntrustedRlp ) -> Result < Self , DecoderError > {
156199 let tag = rlp. val_at ( 0 ) ?;
157200 match tag {
@@ -224,6 +267,21 @@ impl Decodable for Action {
224267 signatures,
225268 } )
226269 }
270+ ACTION_TAG_REPORT_DOUBLE_VOTE => {
271+ let item_count = rlp. item_count ( ) ?;
272+ if item_count != 3 {
273+ return Err ( DecoderError :: RlpIncorrectListLen {
274+ expected : 3 ,
275+ got : item_count,
276+ } )
277+ }
278+ let message1 = rlp. val_at ( 1 ) ?;
279+ let message2 = rlp. val_at ( 2 ) ?;
280+ Ok ( Action :: ReportDoubleVote {
281+ message1,
282+ message2,
283+ } )
284+ }
227285 _ => Err ( DecoderError :: Custom ( "Unexpected Tendermint Stake Action Type" ) ) ,
228286 }
229287 }
@@ -247,7 +305,7 @@ mod tests {
247305 expected: 4 ,
248306 got: 3 ,
249307 } ) ,
250- UntrustedRlp :: new( & rlp:: encode( & action) ) . as_val:: <Action >( )
308+ UntrustedRlp :: new( & rlp:: encode( & action) ) . as_val:: <Action >:: <_> ( )
251309 ) ;
252310 }
253311
0 commit comments