@@ -12,11 +12,9 @@ use primitives::{
12
12
config:: Config ,
13
13
Address , BigNum , Channel , ToETHChecksum , ValidatorId ,
14
14
} ;
15
- use reqwest:: Client ;
16
15
use serde:: { Deserialize , Serialize } ;
17
16
use serde_json:: Value ;
18
17
use std:: { fs, str:: FromStr } ;
19
- use thiserror:: Error ;
20
18
use tiny_keccak:: Keccak ;
21
19
use web3:: {
22
20
contract:: { Contract , Options } ,
@@ -39,6 +37,9 @@ pub static ERC20_ABI: Lazy<&'static [u8]> = Lazy::new(|| {
39
37
} ) ;
40
38
pub static SWEEPER_ABI : Lazy < & ' static [ u8 ] > =
41
39
Lazy :: new ( || include_bytes ! ( "../../lib/protocol-eth/abi/Sweeper.json" ) ) ;
40
+ pub static IDENTITY_ABI : Lazy < & ' static [ u8 ] > =
41
+ Lazy :: new ( || include_bytes ! ( "../../lib/protocol-eth/abi/Identity5.2.json" ) ) ;
42
+
42
43
/// Ready to use init code (i.e. decoded) for calculating the create2 address
43
44
pub static DEPOSITOR_BYTECODE_DECODED : Lazy < Vec < u8 > > = Lazy :: new ( || {
44
45
let bytecode = include_str ! ( "../../lib/protocol-eth/resources/bytecode/Depositor.bin" ) ;
@@ -92,7 +93,6 @@ pub struct EthereumAdapter {
92
93
config : Config ,
93
94
wallet : Option < SafeAccount > ,
94
95
web3 : Web3 < Http > ,
95
- relayer : RelayerClient ,
96
96
}
97
97
98
98
impl EthereumAdapter {
@@ -113,7 +113,6 @@ impl EthereumAdapter {
113
113
let transport =
114
114
web3:: transports:: Http :: new ( & config. ethereum_network ) . map_err ( Error :: Web3 ) ?;
115
115
let web3 = web3:: Web3 :: new ( transport) ;
116
- let relayer = RelayerClient :: new ( & config. ethereum_adapter_relayer ) ?;
117
116
118
117
Ok ( Self {
119
118
address,
@@ -122,9 +121,45 @@ impl EthereumAdapter {
122
121
wallet : None ,
123
122
config : config. to_owned ( ) ,
124
123
web3,
125
- relayer,
126
124
} )
127
125
}
126
+
127
+ /// Checks if the `from` address has privilages,
128
+ /// by using the Identity contract with a create2 address created with the `from` address
129
+ pub async fn has_privilages (
130
+ & self ,
131
+ identity : Address ,
132
+ check_for : Address ,
133
+ hash : [ u8 ; 32 ] ,
134
+ signature : & [ u8 ] ,
135
+ ) -> Result < bool , Error > {
136
+ // see https://eips.ethereum.org/EIPS/eip-1271
137
+ let magic_value: u32 = 0x1626ba7e ;
138
+ // 0x4e487b710000000000000000000000000000000000000000000000000000000000000021
139
+
140
+ let identity_contract =
141
+ Contract :: from_json ( self . web3 . eth ( ) , H160 ( identity. to_bytes ( ) ) , & IDENTITY_ABI )
142
+ . map_err ( Error :: ContractInitialization ) ?;
143
+
144
+ let status: u32 = identity_contract
145
+ . query (
146
+ "isValidSignature" ,
147
+ (
148
+ // bytes32
149
+ Token :: FixedBytes ( hash. to_vec ( ) ) ,
150
+ // bytes
151
+ Token :: Bytes ( signature. to_vec ( ) ) ,
152
+ ) ,
153
+ Some ( H160 ( check_for. to_bytes ( ) ) ) ,
154
+ Options :: default ( ) ,
155
+ None ,
156
+ )
157
+ . await
158
+ . map_err ( Error :: ContractQuerying ) ?;
159
+
160
+ // if it is the magical value then the address has privileges.
161
+ Ok ( status == magic_value)
162
+ }
128
163
}
129
164
130
165
#[ async_trait]
@@ -222,9 +257,19 @@ impl Adapter for EthereumAdapter {
222
257
223
258
let sess = match & verified. payload . identity {
224
259
Some ( identity) => {
260
+ let decoded_signature =
261
+ base64:: decode_config ( token_encoded, base64:: URL_SAFE_NO_PAD ) . unwrap ( ) ;
262
+
263
+ let hash =
264
+ hash_message ( format ! ( "{}.{}" , header_encoded, payload_encoded) . as_bytes ( ) ) ;
265
+
225
266
if self
226
- . relayer
227
- . has_privileges ( & verified. from , identity)
267
+ . has_privilages (
268
+ identity. to_address ( ) ,
269
+ self . whoami ( ) . to_address ( ) ,
270
+ hash,
271
+ & decoded_signature,
272
+ )
228
273
. await ?
229
274
{
230
275
Session {
@@ -348,49 +393,6 @@ impl Adapter for EthereumAdapter {
348
393
}
349
394
}
350
395
351
- #[ derive( Debug , Clone ) ]
352
- struct RelayerClient {
353
- client : Client ,
354
- relayer_url : String ,
355
- }
356
-
357
- #[ derive( Debug , Error ) ]
358
- #[ error( transparent) ]
359
- pub struct RelayerError ( #[ from] pub reqwest:: Error ) ;
360
-
361
- impl RelayerClient {
362
- pub fn new ( relayer_url : & str ) -> Result < Self , RelayerError > {
363
- let client = Client :: builder ( ) . build ( ) ?;
364
-
365
- Ok ( Self {
366
- relayer_url : relayer_url. to_string ( ) ,
367
- client,
368
- } )
369
- }
370
-
371
- /// Checks whether there are any privileges (i.e. > 0)
372
- pub async fn has_privileges (
373
- & self ,
374
- from : & ValidatorId ,
375
- identity : & ValidatorId ,
376
- ) -> Result < bool , RelayerError > {
377
- use std:: collections:: HashMap ;
378
- let relay_url = format ! (
379
- "{}/identity/by-owner/{}" ,
380
- self . relayer_url,
381
- from. to_checksum( )
382
- ) ;
383
-
384
- let identities_owned: HashMap < ValidatorId , u8 > =
385
- self . client . get ( & relay_url) . send ( ) . await ?. json ( ) . await ?;
386
-
387
- let has_privileges = identities_owned
388
- . get ( identity)
389
- . map_or ( false , |privileges| * privileges > 0 ) ;
390
- Ok ( has_privileges)
391
- }
392
- }
393
-
394
396
fn hash_message ( message : & [ u8 ] ) -> [ u8 ; 32 ] {
395
397
let eth = "\x19 Ethereum Signed Message:\n " ;
396
398
let message_length = message. len ( ) ;
@@ -476,6 +478,10 @@ pub fn ewt_verify(
476
478
let decoded_signature = base64:: decode_config ( & token, base64:: URL_SAFE_NO_PAD )
477
479
. map_err ( EwtVerifyError :: SignatureDecoding ) ?;
478
480
let signature = Signature :: from_electrum ( & decoded_signature) ;
481
+ // signature is empty, so it is invalid, see `Signature::from_electrum`
482
+ if * signature == [ 0 ; 65 ] {
483
+ return Err ( EwtVerifyError :: InvalidSignature ) ;
484
+ }
479
485
480
486
let address =
481
487
public_to_address ( & recover ( & signature, & message) . map_err ( EwtVerifyError :: AddressRecovery ) ?) ;
@@ -485,6 +491,7 @@ pub fn ewt_verify(
485
491
. map_err ( EwtVerifyError :: PayloadDecoding ) ?,
486
492
)
487
493
. map_err ( EwtVerifyError :: PayloadUtf8 ) ?;
494
+
488
495
let payload: Payload =
489
496
serde_json:: from_str ( & payload_string) . map_err ( EwtVerifyError :: PayloadDeserialization ) ?;
490
497
@@ -502,14 +509,10 @@ mod test {
502
509
use super :: * ;
503
510
use chrono:: Utc ;
504
511
use primitives:: {
505
- config:: DEVELOPMENT_CONFIG ,
512
+ config:: { DEVELOPMENT_CONFIG , GANACHE_CONFIG } ,
506
513
test_util:: { CREATOR , IDS , LEADER } ,
507
514
} ;
508
515
use web3:: { transports:: Http , Web3 } ;
509
- use wiremock:: {
510
- matchers:: { method, path} ,
511
- Mock , MockServer , ResponseTemplate ,
512
- } ;
513
516
514
517
#[ test]
515
518
fn should_init_and_unlock_ethereum_adapter ( ) {
@@ -590,6 +593,7 @@ mod test {
590
593
} ;
591
594
592
595
let parts: Vec < & str > = expected. split ( '.' ) . collect ( ) ;
596
+
593
597
let verification =
594
598
ewt_verify ( parts[ 0 ] , parts[ 1 ] , parts[ 2 ] ) . expect ( "Failed to verify ewt token" ) ;
595
599
@@ -602,37 +606,44 @@ mod test {
602
606
#[ tokio:: test]
603
607
async fn test_session_from_token ( ) {
604
608
use primitives:: ToETHChecksum ;
605
- use std:: collections:: HashMap ;
606
609
607
- let identity = ValidatorId :: try_from ( "0x5B04DBc513F90CaAFAa09307Ad5e3C65EB4b26F0" ) . unwrap ( ) ;
608
- let server = MockServer :: start ( ) . await ;
609
- let mut identities_owned: HashMap < ValidatorId , u8 > = HashMap :: new ( ) ;
610
- identities_owned. insert ( identity, 2 ) ;
610
+ // let identity = ValidatorId::try_from("0x5B04DBc513F90CaAFAa09307Ad5e3C65EB4b26F0").unwrap();
611
611
612
- let mut eth_adapter = setup_eth_adapter ( DEVELOPMENT_CONFIG . clone ( ) ) ;
612
+ // let mut eth_adapter = setup_eth_adapter(GANACHE_CONFIG.clone());
613
+ let mut adapter = EthereumAdapter :: init ( KEYSTORES [ & CREATOR ] . clone ( ) , & GANACHE_CONFIG )
614
+ . expect ( "should init ethereum adapter" ) ;
613
615
614
- Mock :: given ( method ( "GET" ) )
615
- . and ( path ( format ! ( "/identity/by-owner/{}" , eth_adapter. whoami( ) ) ) )
616
- . respond_with ( ResponseTemplate :: new ( 200 ) . set_body_json ( & identities_owned) )
617
- . mount ( & server)
618
- . await ;
616
+ adapter. unlock ( ) . expect ( "should unlock eth adapter" ) ;
619
617
620
- eth_adapter. unlock ( ) . expect ( "should unlock eth adapter" ) ;
621
- let wallet = eth_adapter. wallet . clone ( ) ;
618
+ let whoami = adapter. whoami ( ) . to_address ( ) ;
619
+
620
+ // todo: Deploy Identity
621
+ let ( identity_address, _contract) =
622
+ deploy_identity_contract ( & adapter. web3 , adapter. whoami ( ) . to_address ( ) , & [ whoami] )
623
+ . await
624
+ . expect ( "Should deploy identity" ) ;
625
+ let identity_id = ValidatorId :: from ( identity_address) ;
626
+
627
+ let wallet = adapter. wallet . clone ( ) . expect ( "Should have unlocked wallet" ) ;
622
628
623
629
let era = Utc :: now ( ) . timestamp_millis ( ) as f64 / 60000.0 ;
624
630
let payload = Payload {
625
- id : eth_adapter . whoami ( ) . to_checksum ( ) ,
631
+ id : adapter . whoami ( ) . to_checksum ( ) ,
626
632
era : era. floor ( ) as i64 ,
627
- identity : Some ( identity ) ,
628
- address : eth_adapter . whoami ( ) . to_checksum ( ) ,
633
+ identity : Some ( identity_id ) ,
634
+ address : adapter . whoami ( ) . to_checksum ( ) ,
629
635
} ;
630
636
631
- let token = ewt_sign ( & wallet. unwrap ( ) , & eth_adapter. keystore_pwd , & payload) . unwrap ( ) ;
637
+ let token = ewt_sign ( & wallet, & adapter. keystore_pwd , & payload)
638
+ . expect ( "Sould successfully sign the Paypload" ) ;
639
+ // let parts = token.split('.').collect::<Vec<_>>();
640
+
641
+ // double check that we have access for _Who Am I_
642
+ // eth_adapter.has_privilages(identity_address, whoami, ).await.expect("Ok");
632
643
633
- let session: Session = eth_adapter . session_from_token ( & token) . await . unwrap ( ) ;
644
+ let session: Session = adapter . session_from_token ( & token) . await . unwrap ( ) ;
634
645
635
- assert_eq ! ( session. uid, identity ) ;
646
+ assert_eq ! ( session. uid, identity_id ) ;
636
647
}
637
648
638
649
#[ tokio:: test]
0 commit comments