diff --git a/pallets/identity-management-mock/Cargo.toml b/pallets/identity-management-mock/Cargo.toml index 9e4c76ea57..0569cd4927 100644 --- a/pallets/identity-management-mock/Cargo.toml +++ b/pallets/identity-management-mock/Cargo.toml @@ -50,6 +50,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", ] std = [ + "log/std", "codec/std", "sp-std/std", "sp-runtime/std", diff --git a/pallets/identity-management-mock/src/identity_context.rs b/pallets/identity-management-mock/src/identity_context.rs index 2de7c50a2c..91352883fe 100644 --- a/pallets/identity-management-mock/src/identity_context.rs +++ b/pallets/identity-management-mock/src/identity_context.rs @@ -27,8 +27,8 @@ use crate::{BlockNumberOf, Config, Metadata}; pub struct IdentityContext { // the metadata pub metadata: Option, - // the block number (of parent chain) where the linking was intially requested - pub linking_request_block: Option>, + // the block number (of parent chain) where the creation was intially requested + pub creation_request_block: Option>, // the block number (of parent chain) where the verification was intially requested pub verification_request_block: Option>, // if this did is verified @@ -41,7 +41,7 @@ impl Default for IdentityContext { fn default() -> Self { Self { metadata: None, - linking_request_block: None, + creation_request_block: None, verification_request_block: None, is_verified: false, } @@ -50,12 +50,12 @@ impl Default for IdentityContext { impl IdentityContext { pub fn new( - linking_request_block: BlockNumberOf, + creation_request_block: BlockNumberOf, verification_request_block: BlockNumberOf, ) -> Self { Self { metadata: None, - linking_request_block: Some(linking_request_block), + creation_request_block: Some(creation_request_block), verification_request_block: Some(verification_request_block), is_verified: false, } diff --git a/pallets/identity-management-mock/src/lib.rs b/pallets/identity-management-mock/src/lib.rs index 359dd37003..56f1df8bd3 100644 --- a/pallets/identity-management-mock/src/lib.rs +++ b/pallets/identity-management-mock/src/lib.rs @@ -81,7 +81,7 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// origin to manage caller whitelist type ManageWhitelistOrigin: EnsureOrigin; - // maximum delay in block numbers between linking an identity and verifying an identity + // maximum delay in block numbers between creating an identity and verifying an identity #[pallet::constant] type MaxVerificationDelay: Get>; // some extrinsics should only be called by origins from TEE @@ -171,9 +171,9 @@ pub mod pallet { ShieldingKeyDecryptionFailed, /// unexpected decoded type WrongDecodedType, - /// identity already exists when linking an identity - IdentityAlreadyExist, - /// identity not exist when unlinking an identity + /// identity already verified when creating an identity + IdentityAlreadyVerified, + /// identity not exist when removing an identity IdentityNotExist, /// no shielding key for a given AccountId ShieldingKeyNotExist, @@ -187,8 +187,8 @@ pub mod pallet { RecoverSubstratePubkeyFailed, /// verify evm signature failed VerifyEvmSignatureFailed, - /// the linking request block is zero - LinkingRequestBlockZero, + /// the creation request block is zero + CreationRequestBlockZero, /// the challenge code doesn't exist ChallengeCodeNotExist, /// wrong signature type @@ -310,14 +310,17 @@ pub mod pallet { }, }; - ensure!( - !IDGraphs::::contains_key(&who, &identity), - Error::::IdentityAlreadyExist - ); + if let Some(c) = IDGraphs::::get(&who, &identity) { + ensure!(!c.is_verified, Error::::IdentityAlreadyVerified); + } + let key = UserShieldingKeys::::get(&who).ok_or(Error::::ShieldingKeyNotExist)?; // emit the challenge code event, TODO: use randomness pallet - let code = Self::get_mock_challenge_code(); + let code = Self::get_mock_challenge_code( + >::block_number(), + ChallengeCodes::::get(&who, &identity), + ); ChallengeCodes::::insert(&who, &identity, &code); Self::deposit_event(Event::::ChallengeCodeGeneratedPlain { account: who.clone(), @@ -333,7 +336,7 @@ pub mod pallet { // emit the IdentityCreated event let context = IdentityContext { metadata, - linking_request_block: Some(>::block_number()), + creation_request_block: Some(>::block_number()), verification_request_block: None, is_verified: false, }; @@ -381,7 +384,7 @@ pub mod pallet { Ok(()) } - /// Verify a linked identity + /// Verify a created identity #[pallet::weight(195_000_000)] pub fn verify_identity( origin: OriginFor, @@ -424,11 +427,11 @@ pub mod pallet { IDGraphs::::try_mutate(&who, &identity, |context| -> DispatchResult { let mut c = context.take().ok_or(Error::::IdentityNotExist)?; - let linking_request_block = - c.linking_request_block.ok_or(Error::::LinkingRequestBlockZero)?; - ensure!(linking_request_block <= now, Error::::VerificationRequestTooEarly); + let creation_request_block = + c.creation_request_block.ok_or(Error::::CreationRequestBlockZero)?; + ensure!(creation_request_block <= now, Error::::VerificationRequestTooEarly); ensure!( - now - linking_request_block <= T::MaxVerificationDelay::get(), + now - creation_request_block <= T::MaxVerificationDelay::get(), Error::::VerificationRequestTooLate ); c.is_verified = true; @@ -534,9 +537,13 @@ pub mod pallet { } // TODO: maybe use randomness pallet - fn get_mock_challenge_code() -> ChallengeCode { - let now = >::block_number(); - blake2_128(&now.encode()) + pub fn get_mock_challenge_code( + bn: BlockNumberOf, + maybe_code: Option, + ) -> ChallengeCode { + let mut code = bn.encode(); + code.append(&mut maybe_code.encode()); + blake2_128(&code) } fn verify_substrate_signature( diff --git a/pallets/identity-management-mock/src/mock.rs b/pallets/identity-management-mock/src/mock.rs index 7436544999..fe29e12494 100644 --- a/pallets/identity-management-mock/src/mock.rs +++ b/pallets/identity-management-mock/src/mock.rs @@ -39,7 +39,7 @@ pub use mock_tee_primitives::{ }; pub use parity_crypto::publickey::{sign, Generator, KeyPair as EvmPair, Message, Random}; use sp_core::sr25519::Pair as SubstratePair; // TODO: maybe use more generic struct -use sp_core::{blake2_128, Pair, H256}; +use sp_core::{Pair, H256}; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, @@ -239,6 +239,10 @@ pub fn setup_create_identity( ) { let key = setup_user_shieding_key(who); let encrypted_identity = tee_encrypt(identity.encode().as_slice()); + let code = IdentityManagementMock::get_mock_challenge_code( + bn, + IdentityManagementMock::challenge_codes(&who, &identity), + ); assert_ok!(IdentityManagementMock::create_identity( Origin::signed(who), H256::random(), @@ -256,12 +260,10 @@ pub fn setup_create_identity( account: aes_encrypted_account.clone(), })); - // double check the challenge code - let code = blake2_128(bn.encode().as_slice()); System::assert_has_event(Event::IdentityManagementMock( crate::Event::ChallengeCodeGeneratedPlain { account: who, identity, code }, )); - let aes_encrypted_code = aes_encrypt_default(&key, code.encode().as_slice()); + let aes_encrypted_code = aes_encrypt_default(&key, code.as_slice()); System::assert_has_event(Event::IdentityManagementMock(crate::Event::ChallengeCodeGenerated { account: aes_encrypted_account, identity: aes_encrypted_identity, diff --git a/pallets/identity-management-mock/src/tests.rs b/pallets/identity-management-mock/src/tests.rs index c651367ec2..cf07d299a2 100644 --- a/pallets/identity-management-mock/src/tests.rs +++ b/pallets/identity-management-mock/src/tests.rs @@ -73,6 +73,59 @@ fn create_eth_identity_works() { }); } +#[test] +fn create_two_distinct_twitter_identities_works() { + new_test_ext().execute_with(|| { + // create and verify the first twitter handle + System::set_block_number(3); + setup_verify_twitter_identity(2, create_mock_twitter_identity(b"alice"), 3); + // create second twitter handle works + System::set_block_number(4); + setup_create_identity(2, create_mock_twitter_identity(b"bob"), 4); + }); +} + +#[test] +fn create_twitter_identity_twice_works() { + new_test_ext().execute_with(|| { + let who = 2; + let identity = create_mock_twitter_identity(b"alice"); + // create a twitter identity + System::set_block_number(3); + setup_create_identity(who, identity.clone(), 3); + let old_code = IdentityManagementMock::challenge_codes(who, &identity).unwrap(); + // create the same twitter identity for the second time + // it should succeed and generate a new challenge code + System::set_block_number(5); + setup_create_identity(who, identity.clone(), 5); + let new_code = IdentityManagementMock::challenge_codes(who, &identity).unwrap(); + assert!(old_code != new_code); + let c = IdentityManagementMock::id_graphs(who, &identity).unwrap(); + assert!(c.creation_request_block == Some(5)); + }); +} + +#[test] +fn create_twitter_identity_after_verification_fails() { + new_test_ext().execute_with(|| { + let who = 2; + let identity = create_mock_twitter_identity(b"alice"); + System::set_block_number(3); + setup_verify_twitter_identity(who, identity.clone(), 3); + System::set_block_number(4); + let encrypted_identity = tee_encrypt(identity.encode().as_slice()); + assert_noop!( + IdentityManagementMock::create_identity( + Origin::signed(who), + H256::random(), + encrypted_identity.to_vec(), + None + ), + Error::::IdentityAlreadyVerified + ); + }); +} + // actually it should always be successful, as we don't have on-chain web2 verification // for the mock pallet #[test] @@ -101,18 +154,6 @@ fn verify_eth_identity_works() { }); } -#[test] -fn double_create_twitter_identity_works() { - new_test_ext().execute_with(|| { - // create and verify the first twitter handle - System::set_block_number(3); - setup_verify_twitter_identity(2, create_mock_twitter_identity(b"alice"), 3); - // create second twitter handle works - System::set_block_number(4); - setup_create_identity(2, create_mock_twitter_identity(b"bob"), 4); - }); -} - #[test] fn wrong_polkadot_verification_message_fails() { new_test_ext().execute_with(|| { diff --git a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs index 80ee5084b0..63cb0efde8 100644 --- a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs +++ b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs @@ -81,7 +81,7 @@ impl TrustedCallSigned { who: who.clone(), identity: identity.clone(), metadata, - linking_request_block: bn, + creation_request_block: bn, } .dispatch_bypass_filter(ita_sgx_runtime::Origin::root()) .map_err(|e| StfError::Dispatch(format!("{:?}", e.error)))?; diff --git a/tee-worker/litentry/pallets/identity-management/src/identity_context.rs b/tee-worker/litentry/pallets/identity-management/src/identity_context.rs index 96ac0e3f46..7285d7503b 100644 --- a/tee-worker/litentry/pallets/identity-management/src/identity_context.rs +++ b/tee-worker/litentry/pallets/identity-management/src/identity_context.rs @@ -28,8 +28,8 @@ use litentry_primitives::ParentchainBlockNumber; pub struct IdentityContext { // the metadata pub metadata: Option>, - // the block number (of parent chain) where the linking was intially requested - pub linking_request_block: Option, + // the block number (of parent chain) where the creation was intially requested + pub creation_request_block: Option, // the block number (of parent chain) where the verification was intially requested pub verification_request_block: Option, // if this did is verified @@ -42,7 +42,7 @@ impl Default for IdentityContext { fn default() -> Self { Self { metadata: None, - linking_request_block: None, + creation_request_block: None, verification_request_block: None, is_verified: false, } @@ -51,12 +51,12 @@ impl Default for IdentityContext { impl IdentityContext { pub fn new( - linking_request_block: ParentchainBlockNumber, + creation_request_block: ParentchainBlockNumber, verification_request_block: ParentchainBlockNumber, ) -> Self { Self { metadata: None, - linking_request_block: Some(linking_request_block), + creation_request_block: Some(creation_request_block), verification_request_block: Some(verification_request_block), is_verified: false, } diff --git a/tee-worker/litentry/pallets/identity-management/src/lib.rs b/tee-worker/litentry/pallets/identity-management/src/lib.rs index 600df608a9..299e4d0f1b 100644 --- a/tee-worker/litentry/pallets/identity-management/src/lib.rs +++ b/tee-worker/litentry/pallets/identity-management/src/lib.rs @@ -67,7 +67,7 @@ pub mod pallet { /// maximum metadata length #[pallet::constant] type MaxMetadataLength: Get; - /// maximum delay in block numbers between linking an identity and verifying an identity + /// maximum delay in block numbers between creating an identity and verifying an identity #[pallet::constant] type MaxVerificationDelay: Get; } @@ -91,8 +91,8 @@ pub mod pallet { pub enum Error { /// challenge code doesn't exist ChallengeCodeNotExist, - /// the pair (litentry-account, identity) already exists - IdentityAlreadyExist, + /// the pair (litentry-account, identity) already verified when creating an identity + IdentityAlreadyVerified, /// the pair (litentry-account, identity) doesn't exist IdentityNotExist, /// the identity was not created before verification @@ -186,16 +186,15 @@ pub mod pallet { who: T::AccountId, identity: Identity, metadata: Option>, - linking_request_block: ParentchainBlockNumber, + creation_request_block: ParentchainBlockNumber, ) -> DispatchResult { T::ManageOrigin::ensure_origin(origin)?; - ensure!( - !IDGraphs::::contains_key(&who, &identity), - Error::::IdentityAlreadyExist - ); + if let Some(c) = IDGraphs::::get(&who, &identity) { + ensure!(!c.is_verified, Error::::IdentityAlreadyVerified); + } let context = IdentityContext { metadata, - linking_request_block: Some(linking_request_block), + creation_request_block: Some(creation_request_block), ..Default::default() }; IDGraphs::::insert(&who, &identity, context); @@ -227,7 +226,7 @@ pub mod pallet { IDGraphs::::try_mutate(&who, &identity, |context| -> DispatchResult { let mut c = context.take().ok_or(Error::::IdentityNotExist)?; - if let Some(b) = c.linking_request_block { + if let Some(b) = c.creation_request_block { ensure!( b <= verification_request_block, Error::::VerificationRequestTooEarly diff --git a/tee-worker/litentry/pallets/identity-management/src/tests.rs b/tee-worker/litentry/pallets/identity-management/src/tests.rs index 4afb1c80a4..0d92aff97b 100644 --- a/tee-worker/litentry/pallets/identity-management/src/tests.rs +++ b/tee-worker/litentry/pallets/identity-management/src/tests.rs @@ -51,7 +51,7 @@ fn create_identity_works() { IMT::id_graphs(2, ALICE_WEB3_IDENTITY).unwrap(), IdentityContext { metadata: Some(metadata), - linking_request_block: Some(1), + creation_request_block: Some(1), verification_request_block: None, is_verified: false, } @@ -78,7 +78,7 @@ fn remove_identity_works() { IMT::id_graphs(2, ALICE_WEB3_IDENTITY.clone()).unwrap(), IdentityContext { metadata: Some(metadata), - linking_request_block: Some(1), + creation_request_block: Some(1), verification_request_block: None, is_verified: false, } @@ -104,7 +104,7 @@ fn verify_identity_works() { IMT::id_graphs(2, ALICE_WEB3_IDENTITY).unwrap(), IdentityContext { metadata: Some(metadata), - linking_request_block: Some(1), + creation_request_block: Some(1), verification_request_block: Some(1), is_verified: true, } @@ -149,7 +149,7 @@ fn get_identity_and_identity_context_works() { #[test] fn verify_identity_fails_when_too_early() { new_test_ext().execute_with(|| { - const LINKNIG_REQUEST_BLOCK: ParentchainBlockNumber = 2; + const CREATION_REQUEST_BLOCK: ParentchainBlockNumber = 2; const VERIFICATION_REQUEST_BLOCK: ParentchainBlockNumber = 1; let metadata: MetadataOf = vec![0u8; 16].try_into().unwrap(); @@ -158,7 +158,7 @@ fn verify_identity_fails_when_too_early() { 2, ALICE_WEB3_IDENTITY.clone(), Some(metadata.clone()), - LINKNIG_REQUEST_BLOCK + CREATION_REQUEST_BLOCK )); assert_noop!( IMT::verify_identity( @@ -173,7 +173,7 @@ fn verify_identity_fails_when_too_early() { IMT::id_graphs(2, ALICE_WEB3_IDENTITY).unwrap(), IdentityContext { metadata: Some(metadata), - linking_request_block: Some(LINKNIG_REQUEST_BLOCK), + creation_request_block: Some(CREATION_REQUEST_BLOCK), verification_request_block: None, is_verified: false, } @@ -184,7 +184,7 @@ fn verify_identity_fails_when_too_early() { #[test] fn verify_identity_fails_when_too_late() { new_test_ext().execute_with(|| { - const LINKNIG_REQUEST_BLOCK: ParentchainBlockNumber = 1; + const CREATION_REQUEST_BLOCK: ParentchainBlockNumber = 1; const VERIFICATION_REQUEST_BLOCK: ParentchainBlockNumber = 5; let metadata: MetadataOf = vec![0u8; 16].try_into().unwrap(); @@ -193,7 +193,7 @@ fn verify_identity_fails_when_too_late() { 2, ALICE_WEB3_IDENTITY.clone(), Some(metadata.clone()), - LINKNIG_REQUEST_BLOCK + CREATION_REQUEST_BLOCK )); assert_noop!( IMT::verify_identity( @@ -208,7 +208,7 @@ fn verify_identity_fails_when_too_late() { IMT::id_graphs(2, ALICE_WEB3_IDENTITY).unwrap(), IdentityContext { metadata: Some(metadata), - linking_request_block: Some(LINKNIG_REQUEST_BLOCK), + creation_request_block: Some(CREATION_REQUEST_BLOCK), verification_request_block: None, is_verified: false, }