@@ -5,16 +5,20 @@ use alloc::Vec;
55#[ cfg( feature = "std" ) ] use std:: rc:: Rc ;
66
77use bigint:: Gas ;
8- #[ cfg( feature = "std" ) ] use std:: cmp:: min;
8+ #[ cfg( all( feature = "std" , any( feature = "rust-secp256k1" , feature = "c-secp256k1" ) ) ) ] use std:: cmp:: min;
9+ #[ cfg( all( not( feature = "std" ) , any( feature = "rust-secp256k1" , feature = "c-secp256k1" ) ) ) ] use core:: cmp:: min;
910
1011use errors:: { RuntimeError , OnChainError } ;
1112use sha2:: Sha256 ;
12- #[ cfg( feature = "std" ) ] use sha3:: Keccak256 ;
13+ #[ cfg( any( feature = "rust-secp256k1" , feature = "c-secp256k1" ) ) ]
14+ use sha3:: Keccak256 ;
1315use ripemd160:: Ripemd160 ;
1416use digest:: { Digest , FixedOutput } ;
1517
16- #[ cfg( feature = "std " ) ]
18+ #[ cfg( feature = "c-secp256k1 " ) ]
1719use secp256k1:: { SECP256K1 , RecoverableSignature , Message , RecoveryId , Error } ;
20+ #[ cfg( feature = "rust-secp256k1" ) ]
21+ use secp256k1:: { recover, Message , RecoveryId , Signature , Error } ;
1822
1923/// Represent a precompiled contract.
2024pub trait Precompiled : Sync {
@@ -96,7 +100,7 @@ pub static SHA256_PRECOMPILED: SHA256Precompiled = SHA256Precompiled;
96100
97101/// ECREC precompiled contract.
98102pub struct ECRECPrecompiled ;
99- #[ cfg( feature = "std" ) ]
103+ #[ cfg( any ( feature = "c-secp256k1" , feature = "rust-secp256k1" ) ) ]
100104impl Precompiled for ECRECPrecompiled {
101105 fn gas ( & self , _: & [ u8 ] ) -> Gas {
102106 Gas :: from ( 3000u64 )
@@ -118,7 +122,7 @@ impl Precompiled for ECRECPrecompiled {
118122 }
119123 }
120124}
121- #[ cfg( not( feature = "std" ) ) ]
125+ #[ cfg( all ( not( feature = "c-secp256k1" ) , not ( feature = "rust-secp256k1" ) ) ) ]
122126impl Precompiled for ECRECPrecompiled {
123127 fn gas_and_step ( & self , _: & [ u8 ] , _: Gas ) -> Result < ( Gas , Rc < Vec < u8 > > ) , RuntimeError > {
124128 use errors:: NotSupportedError ;
@@ -136,7 +140,7 @@ fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
136140 }
137141}
138142
139- #[ cfg( feature = "std " ) ]
143+ #[ cfg( feature = "c-secp256k1 " ) ]
140144fn kececrec ( data : & [ u8 ] ) -> Result < [ u8 ; 32 ] , Error > {
141145 let message = Message :: from_slice ( & data[ 0 ..32 ] ) ?;
142146 let recid_raw = match data[ 63 ] {
@@ -157,3 +161,33 @@ fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
157161
158162 Ok ( ret)
159163}
164+
165+ #[ cfg( feature = "rust-secp256k1" ) ]
166+ fn kececrec ( data : & [ u8 ] ) -> Result < [ u8 ; 32 ] , Error > {
167+ let mut message_raw = [ 0u8 ; 32 ] ;
168+ for i in 0 ..32 {
169+ message_raw[ i] = data[ i] ;
170+ }
171+ let message = Message :: parse ( & message_raw) ;
172+ let recid_raw = match data[ 63 ] {
173+ 27 | 28 if data[ 32 ..63 ] == [ 0 ; 31 ] => data[ 63 ] - 27 ,
174+ _ => return Err ( Error :: InvalidRecoveryId ) ,
175+ } ;
176+ let recid = RecoveryId :: parse ( recid_raw) ?;
177+ let mut sig_raw = [ 0u8 ; 64 ] ;
178+ for i in 0 ..64 {
179+ sig_raw[ i] = data[ 64 + i] ;
180+ }
181+ let sig = Signature :: parse ( & sig_raw) ;
182+ let recovered = recover ( & message, & sig, & recid) ?;
183+ let key = recovered. serialize ( ) ;
184+
185+ let ret_generic = Keccak256 :: digest ( & key[ 1 ..65 ] ) ;
186+ let mut ret = [ 0u8 ; 32 ] ;
187+
188+ for i in 0 ..32 {
189+ ret[ i] = ret_generic[ i] ;
190+ }
191+
192+ Ok ( ret)
193+ }
0 commit comments