diff --git a/.github/workflows/tee-worker-ci.yml b/.github/workflows/tee-worker-ci.yml index a34d494af8..881973ab3a 100644 --- a/.github/workflows/tee-worker-ci.yml +++ b/.github/workflows/tee-worker-ci.yml @@ -163,7 +163,7 @@ jobs: runs-on: ubuntu-latest needs: check-file-change if: needs.check-file-change.outputs.src == 'true' - container: "integritee/integritee-dev:0.1.9" + container: "integritee/integritee-dev:0.1.10" steps: - uses: actions/checkout@v3 - name: init rust diff --git a/pallets/identity-management-mock/src/lib.rs b/pallets/identity-management-mock/src/lib.rs index fae167c3cd..4974be5ba0 100644 --- a/pallets/identity-management-mock/src/lib.rs +++ b/pallets/identity-management-mock/src/lib.rs @@ -79,19 +79,25 @@ pub mod pallet { pub trait Config: frame_system::Config { /// Event type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// origin to manage caller whitelist - type ManageWhitelistOrigin: EnsureOrigin; // 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 type TEECallOrigin: EnsureOrigin; + /// origin to manage authorised delegatee list + type DelegateeAdminOrigin: EnsureOrigin; } #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { // Events from this pallet + DelegateeAdded { + account: T::AccountId, + }, + DelegateeRemoved { + account: T::AccountId, + }, CreateIdentityRequested { shard: ShardIdentifier, }, @@ -171,8 +177,10 @@ pub mod pallet { /// These are the errors that are immediately emitted from this mock pallet #[pallet::error] pub enum Error { - /// caller is not in whitelist (therefore disallowed to call some extrinsics) - CallerNotWhitelisted, + /// a delegatee doesn't exist + DelegateeNotExist, + /// a `create_identity` request from unauthorised user + UnauthorisedUser, /// Error when decrypting using TEE'shielding key ShieldingKeyDecryptionFailed, /// unexpected decoded type @@ -209,10 +217,11 @@ pub mod pallet { UnexpectedMessage, } + /// delegatees who are authorised to send extrinsics(currently only `create_identity`) + /// on behalf of the users #[pallet::storage] - #[pallet::getter(fn whitelisted_callers)] - pub type WhitelistedCallers = - StorageMap<_, Twox64Concat, T::AccountId, (), OptionQuery>; + #[pallet::getter(fn delegatee)] + pub type Delegatee = StorageMap<_, Blake2_128Concat, T::AccountId, (), OptionQuery>; /// user shielding key is per Litentry account #[pallet::storage] @@ -248,22 +257,23 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// add an account to the whitelist + /// add an account to the delegatees #[pallet::weight(195_000_000)] - pub fn add_to_whitelist(origin: OriginFor, account: T::AccountId) -> DispatchResult { - let _ = T::ManageWhitelistOrigin::ensure_origin(origin)?; - WhitelistedCallers::::insert(account, ()); + pub fn add_delegatee(origin: OriginFor, account: T::AccountId) -> DispatchResult { + let _ = T::DelegateeAdminOrigin::ensure_origin(origin)?; + // we don't care if `account` already exists + Delegatee::::insert(account.clone(), ()); + Self::deposit_event(Event::DelegateeAdded { account }); Ok(()) } - /// remove an account from the whitelist + /// remove an account from the delegatees #[pallet::weight(195_000_000)] - pub fn remove_from_whitelist( - origin: OriginFor, - account: T::AccountId, - ) -> DispatchResult { - let _ = T::ManageWhitelistOrigin::ensure_origin(origin)?; - WhitelistedCallers::::remove(account); + pub fn remove_delegatee(origin: OriginFor, account: T::AccountId) -> DispatchResult { + let _ = T::DelegateeAdminOrigin::ensure_origin(origin)?; + ensure!(Delegatee::::contains_key(&account), Error::::DelegateeNotExist); + Delegatee::::remove(account.clone()); + Self::deposit_event(Event::DelegateeRemoved { account }); Ok(()) } @@ -275,7 +285,6 @@ pub mod pallet { encrypted_key: Vec, ) -> DispatchResult { let who = ensure_signed(origin)?; - ensure!(WhitelistedCallers::::contains_key(&who), Error::::CallerNotWhitelisted); Self::deposit_event(Event::SetUserShieldingKeyRequested { shard }); let decrypted_key = Self::decrypt_with_tee_shielding_key(&encrypted_key)?; @@ -294,11 +303,15 @@ pub mod pallet { pub fn create_identity( origin: OriginFor, shard: ShardIdentifier, + user: T::AccountId, encrypted_identity: Vec, encrypted_metadata: Option>, ) -> DispatchResult { let who = ensure_signed(origin)?; - ensure!(WhitelistedCallers::::contains_key(&who), Error::::CallerNotWhitelisted); + ensure!( + who == user || Delegatee::::contains_key(&who), + Error::::UnauthorisedUser + ); Self::deposit_event(Event::CreateIdentityRequested { shard }); let decrypted_identitty = Self::decrypt_with_tee_shielding_key(&encrypted_identity)?; @@ -368,7 +381,6 @@ pub mod pallet { encrypted_identity: Vec, ) -> DispatchResult { let who = ensure_signed(origin)?; - ensure!(WhitelistedCallers::::contains_key(&who), Error::::CallerNotWhitelisted); Self::deposit_event(Event::RemoveIdentityRequested { shard }); let decrypted_identitty = Self::decrypt_with_tee_shielding_key(&encrypted_identity)?; @@ -403,7 +415,6 @@ pub mod pallet { encrypted_validation_data: Vec, ) -> DispatchResult { let who = ensure_signed(origin)?; - ensure!(WhitelistedCallers::::contains_key(&who), Error::::CallerNotWhitelisted); Self::deposit_event(Event::VerifyIdentityRequested { shard }); let now = >::block_number(); diff --git a/pallets/identity-management-mock/src/mock.rs b/pallets/identity-management-mock/src/mock.rs index 20f6f67fd8..5a8834ab34 100644 --- a/pallets/identity-management-mock/src/mock.rs +++ b/pallets/identity-management-mock/src/mock.rs @@ -121,9 +121,9 @@ ord_parameter_types! { impl pallet_identity_management_mock::Config for Test { type RuntimeEvent = RuntimeEvent; - type ManageWhitelistOrigin = EnsureRoot; type MaxVerificationDelay = ConstU64<10>; type TEECallOrigin = EnsureSignedBy; + type DelegateeAdminOrigin = EnsureRoot; } pub fn new_test_ext() -> sp_io::TestExternalities { @@ -135,8 +135,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| { - // add to `One` to whitelist - let _ = IdentityManagementMock::add_to_whitelist(RuntimeOrigin::root(), 1u64); System::set_block_number(1); }); ext @@ -214,7 +212,6 @@ pub fn setup_user_shieding_key( let shielding_key = Aes256Gcm::generate_key(&mut OsRng); let encrpted_shielding_key = tee_encrypt(&shielding_key); // whitelist caller - assert_ok!(IdentityManagementMock::add_to_whitelist(RuntimeOrigin::root(), who)); assert_ok!(IdentityManagementMock::set_user_shielding_key( RuntimeOrigin::signed(who), H256::random(), @@ -246,6 +243,7 @@ pub fn setup_create_identity( assert_ok!(IdentityManagementMock::create_identity( RuntimeOrigin::signed(who), H256::random(), + who, encrypted_identity.to_vec(), None )); diff --git a/pallets/identity-management-mock/src/tests.rs b/pallets/identity-management-mock/src/tests.rs index b108a43aea..72b322e6f3 100644 --- a/pallets/identity-management-mock/src/tests.rs +++ b/pallets/identity-management-mock/src/tests.rs @@ -20,20 +20,6 @@ use codec::Encode; use frame_support::assert_noop; use sp_core::{blake2_256, Pair, H256}; -#[test] -fn unpriveledged_origin_call_fails() { - new_test_ext().execute_with(|| { - assert_noop!( - IdentityManagementMock::set_user_shielding_key( - RuntimeOrigin::signed(2), - H256::random(), - vec![] - ), - Error::::CallerNotWhitelisted - ); - }); -} - #[test] fn set_user_shielding_key_works() { new_test_ext().execute_with(|| { @@ -118,6 +104,7 @@ fn create_twitter_identity_after_verification_fails() { IdentityManagementMock::create_identity( RuntimeOrigin::signed(who), H256::random(), + who, encrypted_identity.to_vec(), None ), diff --git a/pallets/identity-management/src/benchmarking.rs b/pallets/identity-management/src/benchmarking.rs index 5adeb56b09..bdc1adfe0f 100644 --- a/pallets/identity-management/src/benchmarking.rs +++ b/pallets/identity-management/src/benchmarking.rs @@ -32,15 +32,14 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { } benchmarks! { - // Benchmark `create_identity`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. create_identity { - let caller = whitelisted_caller(); + let caller = whitelisted_caller::(); let shard = H256::from_slice(&TEST_MRENCLAVE); let encrypted_did = vec![1u8; 2048]; let encrypted_metadata = Some(vec![1u8; 2048]); - }: _(RawOrigin::Signed(caller), shard, encrypted_did, encrypted_metadata) + }: _(RawOrigin::Signed(caller.clone()), shard, caller.clone(), encrypted_did, encrypted_metadata) verify { assert_last_event::(Event::CreateIdentityRequested{ shard }.into()); } diff --git a/pallets/identity-management/src/lib.rs b/pallets/identity-management/src/lib.rs index 836bad2511..7f1943fcd1 100644 --- a/pallets/identity-management/src/lib.rs +++ b/pallets/identity-management/src/lib.rs @@ -47,12 +47,6 @@ pub use pallet::*; pub use primitives::{AesOutput, ShardIdentifier}; use sp_std::vec::Vec; -// fn types for handling inside tee-worker -pub type SetUserShieldingKeyFn = ([u8; 2], ShardIdentifier, Vec); -pub type CreateIdentityFn = ([u8; 2], ShardIdentifier, Vec, Option>); -pub type RemoveIdentityFn = ([u8; 2], ShardIdentifier, Vec); -pub type VerifyIdentityFn = ([u8; 2], ShardIdentifier, Vec, Vec); - #[frame_support::pallet] pub mod pallet { use super::{AesOutput, ShardIdentifier, Vec, WeightInfo}; @@ -69,11 +63,15 @@ pub mod pallet { type WeightInfo: WeightInfo; // some extrinsics should only be called by origins from TEE type TEECallOrigin: EnsureOrigin; + /// origin to manage authorised delegatee list + type DelegateeAdminOrigin: EnsureOrigin; } #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { + DelegateeAdded { account: T::AccountId }, + DelegateeRemoved { account: T::AccountId }, // TODO: do we need account as event parameter? This needs to be decided by F/E CreateIdentityRequested { shard: ShardIdentifier }, RemoveIdentityRequested { shard: ShardIdentifier }, @@ -92,11 +90,42 @@ pub mod pallet { SomeError { func: Vec, error: Vec }, } + /// delegatees who are authorised to send extrinsics(currently only `create_identity`) + /// on behalf of the users + #[pallet::storage] + #[pallet::getter(fn delegatee)] + pub type Delegatee = StorageMap<_, Blake2_128Concat, T::AccountId, (), OptionQuery>; + #[pallet::error] - pub enum Error {} + pub enum Error { + /// a delegatee doesn't exist + DelegateeNotExist, + /// a `create_identity` request from unauthorised user + UnauthorisedUser, + } #[pallet::call] impl Pallet { + /// add an account to the delegatees + #[pallet::weight(195_000_000)] + pub fn add_delegatee(origin: OriginFor, account: T::AccountId) -> DispatchResult { + let _ = T::DelegateeAdminOrigin::ensure_origin(origin)?; + // we don't care if `account` already exists + Delegatee::::insert(account.clone(), ()); + Self::deposit_event(Event::DelegateeAdded { account }); + Ok(()) + } + + /// remove an account from the delegatees + #[pallet::weight(195_000_000)] + pub fn remove_delegatee(origin: OriginFor, account: T::AccountId) -> DispatchResult { + let _ = T::DelegateeAdminOrigin::ensure_origin(origin)?; + ensure!(Delegatee::::contains_key(&account), Error::::DelegateeNotExist); + Delegatee::::remove(account.clone()); + Self::deposit_event(Event::DelegateeRemoved { account }); + Ok(()) + } + /// Set or update user's shielding key #[pallet::weight(::WeightInfo::set_user_shielding_key())] pub fn set_user_shielding_key( @@ -110,14 +139,22 @@ pub mod pallet { } /// Create an identity + /// We do the origin check for this extrinsic, it has to be + /// - either the caller him/herself, i.e. ensure_signed(origin)? == who + /// - or from a delegatee in the list #[pallet::weight(::WeightInfo::create_identity())] pub fn create_identity( origin: OriginFor, shard: ShardIdentifier, + user: T::AccountId, encrypted_identity: Vec, encrypted_metadata: Option>, ) -> DispatchResultWithPostInfo { - let _ = ensure_signed(origin)?; + let who = ensure_signed(origin)?; + ensure!( + who == user || Delegatee::::contains_key(&who), + Error::::UnauthorisedUser + ); Self::deposit_event(Event::CreateIdentityRequested { shard }); Ok(().into()) } diff --git a/pallets/identity-management/src/mock.rs b/pallets/identity-management/src/mock.rs index 2562ce6c60..a2b134bc26 100644 --- a/pallets/identity-management/src/mock.rs +++ b/pallets/identity-management/src/mock.rs @@ -28,6 +28,7 @@ use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; +use system::EnsureRoot; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -135,6 +136,7 @@ impl pallet_identity_management::Config for Test { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type TEECallOrigin = EnsureEnclaveSigner; + type DelegateeAdminOrigin = EnsureRoot; } pub fn new_test_ext() -> sp_io::TestExternalities { @@ -142,6 +144,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| { + // add `5` to delegatee + let _ = IdentityManagement::add_delegatee(RuntimeOrigin::root(), 5u64); System::set_block_number(1); }); ext diff --git a/pallets/identity-management/src/tests.rs b/pallets/identity-management/src/tests.rs index 803d000a0e..5d66c58aff 100644 --- a/pallets/identity-management/src/tests.rs +++ b/pallets/identity-management/src/tests.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::{mock::*, ShardIdentifier}; +use crate::{mock::*, Error, ShardIdentifier}; use frame_support::{assert_noop, assert_ok}; use sp_core::H256; @@ -38,12 +38,13 @@ fn set_user_shielding_key_works() { } #[test] -fn create_identity_works() { +fn create_identity_without_delegatee_works() { new_test_ext().execute_with(|| { let shard: ShardIdentifier = H256::from_slice(&TEST_MRENCLAVE); assert_ok!(IdentityManagement::create_identity( RuntimeOrigin::signed(1), shard, + 1, vec![1u8; 2048], Some(vec![1u8; 2048]) )); @@ -53,6 +54,40 @@ fn create_identity_works() { }); } +#[test] +fn create_identity_with_authorised_delegatee_works() { + new_test_ext().execute_with(|| { + let shard: ShardIdentifier = H256::from_slice(&TEST_MRENCLAVE); + assert_ok!(IdentityManagement::create_identity( + RuntimeOrigin::signed(5), // authorised delegatee set in initialisation + shard, + 1, + vec![1u8; 2048], + Some(vec![1u8; 2048]) + )); + System::assert_last_event(RuntimeEvent::IdentityManagement( + crate::Event::CreateIdentityRequested { shard }, + )); + }); +} + +#[test] +fn create_identity_with_unauthorised_delegatee_fails() { + new_test_ext().execute_with(|| { + let shard: ShardIdentifier = H256::from_slice(&TEST_MRENCLAVE); + assert_noop!( + IdentityManagement::create_identity( + RuntimeOrigin::signed(3), + shard, + 1, + vec![1u8; 2048], + Some(vec![1u8; 2048]) + ), + Error::::UnauthorisedUser + ); + }); +} + #[test] fn remove_identity_works() { new_test_ext().execute_with(|| { diff --git a/runtime/litmus/src/lib.rs b/runtime/litmus/src/lib.rs index 1b48ec63e6..08941fb02e 100644 --- a/runtime/litmus/src/lib.rs +++ b/runtime/litmus/src/lib.rs @@ -798,6 +798,7 @@ impl pallet_identity_management::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type TEECallOrigin = EnsureEnclaveSigner; + type DelegateeAdminOrigin = EnsureRootOrAllCouncil; } ord_parameter_types! { @@ -806,10 +807,10 @@ ord_parameter_types! { impl pallet_identity_management_mock::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type ManageWhitelistOrigin = EnsureRootOrAllCouncil; - type MaxVerificationDelay = ConstU32<10>; + type MaxVerificationDelay = ConstU32<{ 30 * MINUTES }>; // intentionally use ALICE for the IMP mock type TEECallOrigin = EnsureSignedBy; + type DelegateeAdminOrigin = EnsureRootOrAllCouncil; } impl pallet_vc_management::Config for Runtime { diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index f6fd32b935..557b25f8dd 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -873,6 +873,7 @@ impl pallet_identity_management::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type TEECallOrigin = EnsureEnclaveSigner; + type DelegateeAdminOrigin = EnsureRootOrAllCouncil; } ord_parameter_types! { @@ -881,10 +882,10 @@ ord_parameter_types! { impl pallet_identity_management_mock::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type ManageWhitelistOrigin = EnsureRoot; - type MaxVerificationDelay = ConstU32<10>; + type MaxVerificationDelay = ConstU32<{ 30 * MINUTES }>; // intentionally use ALICE for the IMP mock type TEECallOrigin = EnsureSignedBy; + type DelegateeAdminOrigin = EnsureRootOrAllCouncil; } impl pallet_vc_management::Config for Runtime { diff --git a/scripts/launch-local-binary.sh b/scripts/launch-local-binary.sh index 1123343bdb..ad26ec3d1e 100755 --- a/scripts/launch-local-binary.sh +++ b/scripts/launch-local-binary.sh @@ -40,8 +40,10 @@ print_divider if [ -z "$POLKADOT_BIN" ]; then echo "no polkadot binary provided, download now ..." # TODO: find a way to get stable download link - # https://api.github.com/repos/paritytech/polkadot/releases/latest is not reliable as + # https://api.github.com/repos/paritytech/polkadot/releases/latest is not reliable as # polkadot could publish release which has no binary + # + # TODO: v0.9.33 isn't working, see issue #1097 url="https://github.com/paritytech/polkadot/releases/download/v0.9.32/polkadot" POLKADOT_BIN="$TMPDIR/polkadot" wget -O "$POLKADOT_BIN" -q "$url" @@ -111,4 +113,4 @@ print_divider echo "done. please check $TMPDIR for generated files if need" -print_divider +print_divider \ No newline at end of file diff --git a/tee-worker/core-primitives/types/src/lib.rs b/tee-worker/core-primitives/types/src/lib.rs index 14b50b726e..469a4c33d8 100644 --- a/tee-worker/core-primitives/types/src/lib.rs +++ b/tee-worker/core-primitives/types/src/lib.rs @@ -42,10 +42,17 @@ pub use itp_sgx_runtime_primitives::types::*; pub type IpfsHash = [u8; 46]; pub type MrEnclave = [u8; 32]; +// pallet teerex pub type ConfirmCallFn = ([u8; 2], ShardIdentifier, H256, Vec); pub type ShieldFundsFn = ([u8; 2], Vec, Balance, ShardIdentifier); pub type CallWorkerFn = ([u8; 2], Request); +// pallet IMP +pub type SetUserShieldingKeyFn = ([u8; 2], ShardIdentifier, Vec); +pub type CreateIdentityFn = ([u8; 2], ShardIdentifier, AccountId, Vec, Option>); +pub type RemoveIdentityFn = ([u8; 2], ShardIdentifier, Vec); +pub type VerifyIdentityFn = ([u8; 2], ShardIdentifier, Vec, Vec); + pub type Enclave = EnclaveGen; /// Simple blob to hold an encoded call diff --git a/tee-worker/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs b/tee-worker/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs index 92904e9704..b40c59921a 100644 --- a/tee-worker/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs +++ b/tee-worker/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs @@ -36,10 +36,12 @@ use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, Shieldin use itp_stf_executor::traits::StfEnclaveSigning; use itp_stf_primitives::types::AccountId; use itp_top_pool_author::traits::AuthorApi; -use itp_types::{CallWorkerFn, OpaqueCall, ShardIdentifier, ShieldFundsFn, H256}; +use itp_types::{ + CallWorkerFn, CreateIdentityFn, OpaqueCall, RemoveIdentityFn, SetUserShieldingKeyFn, + ShardIdentifier, ShieldFundsFn, VerifyIdentityFn, H256, +}; use litentry_primitives::{Identity, UserShieldingKeyType, ValidationData}; use log::*; -use pallet_imp::{CreateIdentityFn, RemoveIdentityFn, SetUserShieldingKeyFn, VerifyIdentityFn}; use sp_core::blake2_256; use sp_runtime::traits::{AccountIdLookup, Block as ParentchainBlockTrait, Header, StaticLookup}; use std::{sync::Arc, vec::Vec}; @@ -280,7 +282,7 @@ impl" -} -[ $# -ne 1 ] && (usage; exit 1) +ROOTDIR=$(git rev-parse --show-toplevel) +cd "$ROOTDIR" -CHAIN=$1 - -# TODO: remove later -if [ "${CHAIN}" != 'rococo' ]; then - echo "only support 'rococo' for the moment" - usage; exit 1 -fi - -PARACHAIN_DIR=/tmp/litentry-parachain -[ -d "$PARACHAIN_DIR" ] && rm -rf "$PARACHAIN_DIR" -git clone https://github.com/litentry/litentry-parachain "$PARACHAIN_DIR" -cd "$PARACHAIN_DIR" -git checkout tee-dev - -cp -f docker/${CHAIN}-parachain-launch-config.tee-dev.yml docker/${CHAIN}-parachain-launch-config.yml - -make launch-docker-${CHAIN} +sed -i.bak "s;litentry-parachain:latest;litentry-parachain:tee-dev;" docker/rococo-parachain-launch-config.yml +make launch-docker-rococo diff --git a/tee-worker/scripts/litentry/stop_parachain.sh b/tee-worker/scripts/litentry/stop_parachain.sh index 8f0058118d..759083e8e5 100755 --- a/tee-worker/scripts/litentry/stop_parachain.sh +++ b/tee-worker/scripts/litentry/stop_parachain.sh @@ -1,8 +1,6 @@ #!/bin/bash set -euo pipefail -PARACHAIN_DIR=/tmp/litentry-parachain - -cd "$PARACHAIN_DIR" +ROOTDIR=$(git rev-parse --show-toplevel) +cd "$ROOTDIR" make clean-docker-rococo || true -rm -rf "$PARACHAIN_DIR" \ No newline at end of file diff --git a/tee-worker/ts-tests/.env.local b/tee-worker/ts-tests/.env.local index d7602455ee..fd0eec07c6 100644 --- a/tee-worker/ts-tests/.env.local +++ b/tee-worker/ts-tests/.env.local @@ -1,11 +1,5 @@ NODE_ENV = local - - WORKER_END_POINT = wss://localhost:2000 - -SUBSTRATE_END_POINT = "ws://localhost:9946" - +SUBSTRATE_END_POINT = "ws://localhost:9944" ETH_END_POINT = "http://localhost:8545" - - ID_HUB_URL='http://localhost:3000' diff --git a/tee-worker/ts-tests/.env.staging b/tee-worker/ts-tests/.env.staging index 61b290ddc9..56183b08a5 100644 --- a/tee-worker/ts-tests/.env.staging +++ b/tee-worker/ts-tests/.env.staging @@ -1,7 +1,4 @@ NODE_ENV = staging - WORKER_END_POINT = wss://integritee-worker-1:2011 - SUBSTRATE_END_POINT = "ws://integritee-node:9912" - -ID_HUB_URL='http://staging:3000' +ID_HUB_URL='http://staging:3000' \ No newline at end of file diff --git a/tee-worker/ts-tests/.prettierrc b/tee-worker/ts-tests/.prettierrc new file mode 100644 index 0000000000..b65f49a91b --- /dev/null +++ b/tee-worker/ts-tests/.prettierrc @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 120, + "tabWidth": 4, + "semi": true +} diff --git a/tee-worker/ts-tests/config.js b/tee-worker/ts-tests/config.js index fbb7ea4420..d0e1cab26e 100644 --- a/tee-worker/ts-tests/config.js +++ b/tee-worker/ts-tests/config.js @@ -1 +1 @@ -require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` }); +require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` }); diff --git a/tee-worker/ts-tests/identity.test.ts b/tee-worker/ts-tests/identity.test.ts index d2abb07da1..0e970e68b8 100644 --- a/tee-worker/ts-tests/identity.test.ts +++ b/tee-worker/ts-tests/identity.test.ts @@ -1,30 +1,20 @@ -import { - describeLitentry, - generateVerificationMessage, - getMessage, - listenEncryptedEvents, -} from "./utils"; -import { hexToU8a, u8aToHex, stringToU8a } from "@polkadot/util"; -import { - createIdentity, - setUserShieldingKey, - removeIdentity, - verifyIdentity, -} from "./indirect_calls"; -import { step } from "mocha-steps"; -import { assert } from "chai"; -import {IdentityGenericEvent, LitentryIdentity, LitentryValidationData} from "./type-definitions"; -import { Sign } from "./web3/functions"; -import { generateTestKeys } from "./web3/functions"; -import { ethers } from "ethers"; -import { HexString } from "@polkadot/util/types"; -import {KeyringPair} from "@polkadot/keyring/types"; +import { describeLitentry, generateVerificationMessage, getMessage, listenEncryptedEvents } from './utils'; +import { hexToU8a, u8aToHex, stringToU8a } from '@polkadot/util'; +import { createIdentity, setUserShieldingKey, removeIdentity, verifyIdentity } from './indirect_calls'; +import { step } from 'mocha-steps'; +import { assert } from 'chai'; +import { IdentityGenericEvent, LitentryIdentity, LitentryValidationData } from './type-definitions'; +import { Sign } from './web3/functions'; +import { generateTestKeys } from './web3/functions'; +import { ethers } from 'ethers'; +import { HexString } from '@polkadot/util/types'; +import { KeyringPair } from '@polkadot/keyring/types'; const twitterIdentity = { handle: { - PlainString: `0x${Buffer.from("mock_user", "utf8").toString("hex")}`, + PlainString: `0x${Buffer.from('mock_user', 'utf8').toString('hex')}`, }, web_type: { - Web2Identity: "Twitter", + Web2Identity: 'Twitter', }, }; @@ -34,7 +24,7 @@ const ethereumIdentity = { }, web_type: { Web3Identity: { - Evm: "Ethereum", + Evm: 'Ethereum', }, }, }; @@ -45,14 +35,14 @@ const substrateIdentity = { }, web_type: { Web3Identity: { - Substrate: "Litentry", + Substrate: 'Litentry', }, }, }; const twitterValidationData = { Web2Validation: { Twitter: { - tweet_id: `0x${Buffer.from("100", "utf8").toString("hex")}`, + tweet_id: `0x${Buffer.from('100', 'utf8').toString('hex')}`, }, }, }; @@ -60,12 +50,12 @@ const twitterValidationData = { const ethereumValidationData = { Web3Validation: { Evm: { - message: `0x${Buffer.from("mock_message", "utf8").toString("hex")}`, + message: `0x${Buffer.from('mock_message', 'utf8').toString('hex')}`, signature: { Ethereum: `0x${Buffer.from( - "10ee76e356d944d17bce552a4fd0d4554ccc97dc81213f470367bd3b99c441c51", - "utf8" - ).toString("hex")}`, + '10ee76e356d944d17bce552a4fd0d4554ccc97dc81213f470367bd3b99c441c51', + 'utf8' + ).toString('hex')}`, }, }, }, @@ -73,101 +63,83 @@ const ethereumValidationData = { const substrateValidationData = { Web3Validation: { Substrate: { - message: `0x${Buffer.from("mock_message", "utf8").toString("hex")}`, + message: `0x${Buffer.from('mock_message', 'utf8').toString('hex')}`, signature: { Sr25519: `0x${Buffer.from( - "10ee76e356d944d17bce552a4fd0d4554ccc97dc81213f470367bd3b99c441c51", - "utf8" - ).toString("hex")}`, + '10ee76e356d944d17bce552a4fd0d4554ccc97dc81213f470367bd3b99c441c51', + 'utf8' + ).toString('hex')}`, }, }, }, }; const discordIdentity = { handle: { - PlainString: `0x${Buffer.from("859641379851337798", "utf8").toString("hex")}`, + PlainString: `0x${Buffer.from('859641379851337798', 'utf8').toString('hex')}`, }, web_type: { - Web2Identity: "Discord", + Web2Identity: 'Discord', }, }; const discordValidationData = { Web2Validation: { Discord: { - channel_id: `0x${Buffer.from("919848392035794945", "utf8").toString("hex")}`, - guild_id: `0x${Buffer.from("919848390156767232", "utf8").toString("hex")}`, - message_id: `0x${Buffer.from("859641379851337798", "utf8").toString("hex")}`, + channel_id: `0x${Buffer.from('919848392035794945', 'utf8').toString('hex')}`, + guild_id: `0x${Buffer.from('919848390156767232', 'utf8').toString('hex')}`, + message_id: `0x${Buffer.from('859641379851337798', 'utf8').toString('hex')}`, }, }, }; -describeLitentry("Test Identity", (context) => { - const aesKey = "0x22fc82db5b606998ad45099b7978b5b4f9dd4ea6017e57370ac56141caaabd12"; +describeLitentry('Test Identity', (context) => { + const aesKey = '0x22fc82db5b606998ad45099b7978b5b4f9dd4ea6017e57370ac56141caaabd12'; var signature_ethereum; var signature_substrate; - step("set user shielding key", async function () { + step('set user shielding key', async function () { const who = await setUserShieldingKey(context, context.defaultSigner, aesKey, true); - assert.equal(who, u8aToHex(context.defaultSigner.addressRaw), "check caller error"); + assert.equal(who, u8aToHex(context.defaultSigner.addressRaw), 'check caller error'); }); - step("create identity", async function () { + step('create identity', async function () { //create twitter identity - const resp_twitter = await createIdentity( - context, - context.defaultSigner, - aesKey, - true, - twitterIdentity - ); + const resp_twitter = await createIdentity(context, context.defaultSigner, aesKey, true, twitterIdentity); if (resp_twitter) { const [_who, challengeCode] = resp_twitter; - console.log("twitterIdentity challengeCode: ", challengeCode); + console.log('twitterIdentity challengeCode: ', challengeCode); const msg = generateVerificationMessage( context, hexToU8a(challengeCode), context.defaultSigner.addressRaw, twitterIdentity ); - console.log("post verification msg to twitter: ", msg); - assert.isNotEmpty(challengeCode, "challengeCode empty"); + console.log('post verification msg to twitter: ', msg); + assert.isNotEmpty(challengeCode, 'challengeCode empty'); } //create ethereum identity - const resp_ethereum = await createIdentity( - context, - context.defaultSigner, - aesKey, - true, - ethereumIdentity - ); + const resp_ethereum = await createIdentity(context, context.defaultSigner, aesKey, true, ethereumIdentity); if (resp_ethereum) { const [_who, challengeCode] = resp_ethereum; - console.log("ethereumIdentity challengeCode: ", challengeCode); + console.log('ethereumIdentity challengeCode: ', challengeCode); const msg = generateVerificationMessage( context, hexToU8a(challengeCode), context.defaultSigner.addressRaw, ethereumIdentity ); - console.log("post verification msg to ethereum: ", msg); + console.log('post verification msg to ethereum: ', msg); ethereumValidationData!.Web3Validation!.Evm!.message = msg; const msgHash = ethers.utils.arrayify(msg); signature_ethereum = await context.ethersWallet.alice.signMessage(msgHash); ethereumValidationData!.Web3Validation!.Evm!.signature!.Ethereum = signature_ethereum; - assert.isNotEmpty(challengeCode, "challengeCode empty"); + assert.isNotEmpty(challengeCode, 'challengeCode empty'); } // create substrate identity - const resp_substrate = await createIdentity( - context, - context.defaultSigner, - aesKey, - true, - substrateIdentity - ); + const resp_substrate = await createIdentity(context, context.defaultSigner, aesKey, true, substrateIdentity); if (resp_substrate) { const [_who, challengeCode] = resp_substrate; - console.log("substrateIdentity challengeCode: ", challengeCode); + console.log('substrateIdentity challengeCode: ', challengeCode); const msg = generateVerificationMessage( context, hexToU8a(challengeCode), @@ -175,16 +147,15 @@ describeLitentry("Test Identity", (context) => { substrateIdentity ); - console.log("post verification msg to substrate: ", msg); + console.log('post verification msg to substrate: ', msg); substrateValidationData!.Web3Validation!.Substrate!.message = msg; signature_substrate = context.defaultSigner.sign(msg); - substrateValidationData!.Web3Validation!.Substrate!.signature!.Sr25519 = - u8aToHex(signature_substrate); - assert.isNotEmpty(challengeCode, "challengeCode empty"); + substrateValidationData!.Web3Validation!.Substrate!.signature!.Sr25519 = u8aToHex(signature_substrate); + assert.isNotEmpty(challengeCode, 'challengeCode empty'); } }); - step("verify identity", async function () { + step('verify identity', async function () { //verify twitter identity const twitter_identity_verified = await verifyIdentity( context, @@ -219,7 +190,7 @@ describeLitentry("Test Identity", (context) => { assertIdentityVerified(context.defaultSigner, substrate_identity_verified); }); - step("remove identity", async function () { + step('remove identity', async function () { //remove twitter identity const twitter_identity_removed = await removeIdentity( context, @@ -228,7 +199,7 @@ describeLitentry("Test Identity", (context) => { true, twitterIdentity ); - assertIdentityRemoved(context.defaultSigner, twitter_identity_removed) + assertIdentityRemoved(context.defaultSigner, twitter_identity_removed); // remove ethereum identity const ethereum_identity_removed = await removeIdentity( @@ -238,7 +209,7 @@ describeLitentry("Test Identity", (context) => { true, ethereumIdentity ); - assertIdentityRemoved(context.defaultSigner, ethereum_identity_removed) + assertIdentityRemoved(context.defaultSigner, ethereum_identity_removed); // remove substrate identity const substrate_identity_removed = await removeIdentity( @@ -248,34 +219,33 @@ describeLitentry("Test Identity", (context) => { true, substrateIdentity ); - assertIdentityRemoved(context.defaultSigner, substrate_identity_removed) + assertIdentityRemoved(context.defaultSigner, substrate_identity_removed); }); }); - function assertIdentityVerified(signer: KeyringPair, identityEvent: IdentityGenericEvent | undefined) { - let idGraphExist = false + let idGraphExist = false; if (identityEvent) { for (let i = 0; i < identityEvent.idGraph.length; i++) { if (JSON.stringify(identityEvent.idGraph[i][0]) == JSON.stringify(identityEvent.identity)) { idGraphExist = true; - assert.isTrue(identityEvent.idGraph[i][1].is_verified, "identity should be verified"); + assert.isTrue(identityEvent.idGraph[i][1].is_verified, 'identity should be verified'); } } } - assert.isTrue(idGraphExist, "id_graph should exist") - assert.equal(identityEvent?.who, u8aToHex(signer.addressRaw), "check caller error"); + assert.isTrue(idGraphExist, 'id_graph should exist'); + assert.equal(identityEvent?.who, u8aToHex(signer.addressRaw), 'check caller error'); } function assertIdentityRemoved(signer: KeyringPair, identityEvent: IdentityGenericEvent | undefined) { - let idGraphExist = false + let idGraphExist = false; if (identityEvent) { for (let i = 0; i < identityEvent.idGraph.length; i++) { if (JSON.stringify(identityEvent.idGraph[i][0]) == JSON.stringify(identityEvent.identity)) { - idGraphExist = true + idGraphExist = true; } } } - assert.isFalse(idGraphExist, "id_graph should be empty") - assert.equal(identityEvent?.who, u8aToHex(signer.addressRaw), "check caller error"); + assert.isFalse(idGraphExist, 'id_graph should be empty'); + assert.equal(identityEvent?.who, u8aToHex(signer.addressRaw), 'check caller error'); } diff --git a/tee-worker/ts-tests/indirect_calls.ts b/tee-worker/ts-tests/indirect_calls.ts index 5b5b4d99bf..548aaa581d 100644 --- a/tee-worker/ts-tests/indirect_calls.ts +++ b/tee-worker/ts-tests/indirect_calls.ts @@ -3,27 +3,28 @@ import { IntegrationTestContext, LitentryIdentity, LitentryValidationData, -} from "./type-definitions"; -import {encryptWithTeeShieldingKey, listenEncryptedEvents, sendTxUntilInBlock} from "./utils"; -import { KeyringPair } from "@polkadot/keyring/types"; -import { HexString } from "@polkadot/util/types"; -import { generateChallengeCode } from "./web3/setup"; -import {ApiPromise} from "@polkadot/api"; +} from './type-definitions'; +import { encryptWithTeeShieldingKey, listenEncryptedEvents, sendTxUntilInBlock } from './utils'; +import { KeyringPair } from '@polkadot/keyring/types'; +import { HexString } from '@polkadot/util/types'; +import { generateChallengeCode } from './web3/setup'; +import { ApiPromise } from '@polkadot/api'; + export async function setUserShieldingKey( context: IntegrationTestContext, signer: KeyringPair, aesKey: HexString, listening: boolean ): Promise { - const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, aesKey).toString("hex"); + const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, aesKey).toString('hex'); await context.substrate.tx.identityManagement .setUserShieldingKey(context.shard, `0x${ciphertext}`) .signAndSend(signer); if (listening) { const event = await listenEncryptedEvents(context, aesKey, { - module: "identityManagement", - method: "userShieldingKeySet", - event: "UserShieldingKeySet", + module: 'identityManagement', + method: 'userShieldingKeySet', + event: 'UserShieldingKeySet', }); const [who] = event.eventData; return who; @@ -38,17 +39,17 @@ export async function createIdentity( listening: boolean, identity: LitentryIdentity ): Promise { - const encode = context.substrate.createType("LitentryIdentity", identity).toHex(); - const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, encode).toString("hex"); + const encode = context.substrate.createType('LitentryIdentity', identity).toHex(); + const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, encode).toString('hex'); const nonce = await context.substrate.rpc.system.accountNextIndex(signer.address); await context.substrate.tx.identityManagement - .createIdentity(context.shard, `0x${ciphertext}`, null) + .createIdentity(context.shard, signer.address, `0x${ciphertext}`, null) .signAndSend(signer, { nonce }); if (listening) { const event = await listenEncryptedEvents(context, aesKey, { - module: "identityManagement", - method: "challengeCodeGenerated", - event: "ChallengeCodeGenerated", + module: 'identityManagement', + method: 'challengeCodeGenerated', + event: 'ChallengeCodeGenerated', }); const [who, _identity, challengeCode] = event.eventData; return [who, challengeCode]; @@ -56,7 +57,6 @@ export async function createIdentity( return undefined; } - export async function removeIdentity( context: IntegrationTestContext, signer: KeyringPair, @@ -64,20 +64,20 @@ export async function removeIdentity( listening: boolean, identity: LitentryIdentity ): Promise { - const encode = context.substrate.createType("LitentryIdentity", identity).toHex(); - const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, encode).toString("hex"); + const encode = context.substrate.createType('LitentryIdentity', identity).toHex(); + const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, encode).toString('hex'); - const tx = context.substrate.tx.identityManagement.removeIdentity(context.shard, `0x${ciphertext}`) - await sendTxUntilInBlock(context.substrate, tx, signer) + const tx = context.substrate.tx.identityManagement.removeIdentity(context.shard, `0x${ciphertext}`); + await sendTxUntilInBlock(context.substrate, tx, signer); if (listening) { const event = await listenEncryptedEvents(context, aesKey, { - module: "identityManagement", - method: "identityRemoved", - event: "IdentityRemoved", + module: 'identityManagement', + method: 'identityRemoved', + event: 'IdentityRemoved', }); const [who, identity, idGraph] = event.eventData; - return decodeIdentityEvent(context.substrate, who, identity, idGraph) + return decodeIdentityEvent(context.substrate, who, identity, idGraph); } return undefined; } @@ -90,39 +90,43 @@ export async function verifyIdentity( identity: LitentryIdentity, data: LitentryValidationData ): Promise { - const identity_encode = context.substrate.createType("LitentryIdentity", identity).toHex(); - const validation_encode = context.substrate.createType("LitentryValidationData", data).toHex(); - const identity_ciphertext = encryptWithTeeShieldingKey( - context.teeShieldingKey, - identity_encode - ).toString("hex"); - const validation_ciphertext = encryptWithTeeShieldingKey( - context.teeShieldingKey, - validation_encode - ).toString("hex"); + const identity_encode = context.substrate.createType('LitentryIdentity', identity).toHex(); + const validation_encode = context.substrate.createType('LitentryValidationData', data).toHex(); + const identity_ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, identity_encode).toString('hex'); + const validation_ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, validation_encode).toString( + 'hex' + ); - const tx = context.substrate.tx.identityManagement - .verifyIdentity(context.shard, `0x${identity_ciphertext}`, `0x${validation_ciphertext}`) - await sendTxUntilInBlock(context.substrate, tx, signer) + const tx = context.substrate.tx.identityManagement.verifyIdentity( + context.shard, + `0x${identity_ciphertext}`, + `0x${validation_ciphertext}` + ); + await sendTxUntilInBlock(context.substrate, tx, signer); if (listening) { const event = await listenEncryptedEvents(context, aesKey, { - module: "identityManagement", - method: "identityVerified", - event: "IdentityVerified", + module: 'identityManagement', + method: 'identityVerified', + event: 'IdentityVerified', }); const [who, identity, idGraph] = event.eventData; - return decodeIdentityEvent(context.substrate, who, identity, idGraph) + return decodeIdentityEvent(context.substrate, who, identity, idGraph); } return undefined; } -function decodeIdentityEvent(api: ApiPromise, who: HexString, identityString: HexString, idGraphString: HexString): IdentityGenericEvent { - let identity = api.createType("LitentryIdentity", identityString).toJSON(); - let idGraph = api.createType("Vec<(LitentryIdentity, IdentityContext)>", idGraphString).toJSON(); +function decodeIdentityEvent( + api: ApiPromise, + who: HexString, + identityString: HexString, + idGraphString: HexString +): IdentityGenericEvent { + let identity = api.createType('LitentryIdentity', identityString).toJSON(); + let idGraph = api.createType('Vec<(LitentryIdentity, IdentityContext)>', idGraphString).toJSON(); return { who, identity, idGraph, }; -} \ No newline at end of file +} diff --git a/tee-worker/ts-tests/package.json b/tee-worker/ts-tests/package.json index b11b75c71a..11b1576346 100644 --- a/tee-worker/ts-tests/package.json +++ b/tee-worker/ts-tests/package.json @@ -22,6 +22,7 @@ "cross-env": "^7.0.3", "dotenv": "^16.0.3", "ethers": "^5.7.2", + "prettier": "2.8.1", "ts-node": "^10.8.1", "typescript": "^4.7.3" }, diff --git a/tee-worker/ts-tests/type-definitions.ts b/tee-worker/ts-tests/type-definitions.ts index de922e9b72..65d5087474 100644 --- a/tee-worker/ts-tests/type-definitions.ts +++ b/tee-worker/ts-tests/type-definitions.ts @@ -1,155 +1,155 @@ -import { ApiPromise, Keyring } from "@polkadot/api"; -import { KeyObject } from "crypto"; -import { HexString } from "@polkadot/util/types"; -import WebSocketAsPromised = require("websocket-as-promised"); -import { KeyringPair } from "@polkadot/keyring/types"; -import { Web3Provider } from "@ethersproject/providers"; -import { ethers, Wallet } from "ethers"; +import { ApiPromise, Keyring } from '@polkadot/api'; +import { KeyObject } from 'crypto'; +import { HexString } from '@polkadot/util/types'; +import WebSocketAsPromised = require('websocket-as-promised'); +import { KeyringPair } from '@polkadot/keyring/types'; +import { Web3Provider } from '@ethersproject/providers'; +import { ethers, Wallet } from 'ethers'; export const teeTypes = { WorkerRpcReturnString: { - vec: "Bytes", + vec: 'Bytes', }, WorkerRpcReturnValue: { - value: "Bytes", - do_watch: "bool", - status: "DirectRequestStatus", + value: 'Bytes', + do_watch: 'bool', + status: 'DirectRequestStatus', }, TrustedOperation: { _enum: { - indirect_call: "(TrustedCallSigned)", - direct_call: "(TrustedCallSigned)", - get: "(Getter)", + indirect_call: '(TrustedCallSigned)', + direct_call: '(TrustedCallSigned)', + get: '(Getter)', }, }, TrustedCallSigned: { - call: "TrustedCall", - index: "u32", - signature: "MultiSignature", + call: 'TrustedCall', + index: 'u32', + signature: 'MultiSignature', }, Getter: { _enum: { - public: "(PublicGetter)", - trusted: "(TrustedGetterSigned)", + public: '(PublicGetter)', + trusted: '(TrustedGetterSigned)', }, }, PublicGetter: { - _enum: ["some_value"], + _enum: ['some_value'], }, TrustedGetterSigned: { - getter: "TrustedGetter", - signature: "MultiSignature", + getter: 'TrustedGetter', + signature: 'MultiSignature', }, /// important TrustedGetter: { _enum: { - free_balance: "(AccountId)", + free_balance: '(AccountId)', }, }, /// important TrustedCall: { _enum: { - balance_set_balance: "(AccountId, AccountId, Balance, Balance)", - balance_transfer: "(AccountId, AccountId, Balance)", - balance_unshield: "(AccountId, AccountId, Balance, ShardIdentifier)", + balance_set_balance: '(AccountId, AccountId, Balance, Balance)', + balance_transfer: '(AccountId, AccountId, Balance)', + balance_unshield: '(AccountId, AccountId, Balance, ShardIdentifier)', }, }, DirectRequestStatus: { _enum: [ //TODO support TrustedOperationStatus(TrustedOperationStatus) - "Ok", - "TrustedOperationStatus", - "Error", + 'Ok', + 'TrustedOperationStatus', + 'Error', ], }, /// identity LitentryIdentity: { - web_type: "IdentityWebType", - handle: "IdentityHandle", + web_type: 'IdentityWebType', + handle: 'IdentityHandle', }, IdentityWebType: { _enum: { - Web2Identity: "Web2Network", - Web3Identity: "Web3Network", + Web2Identity: 'Web2Network', + Web3Identity: 'Web3Network', }, }, Web2Network: { - _enum: ["Twitter", "Discord", "Github"], + _enum: ['Twitter', 'Discord', 'Github'], }, Web3Network: { _enum: { - Substrate: "SubstrateNetwork", - Evm: "EvmNetwork", + Substrate: 'SubstrateNetwork', + Evm: 'EvmNetwork', }, }, SubstrateNetwork: { - _enum: ["Polkadot", "Kusama", "Litentry", "Litmus"], + _enum: ['Polkadot', 'Kusama', 'Litentry', 'Litmus'], }, EvmNetwork: { - _enum: ["Ethereum", "BSC"], + _enum: ['Ethereum', 'BSC'], }, IdentityHandle: { _enum: { - Address32: "[u8;32]", - Address20: "[u8;20]", - PlainString: "Vec", + Address32: '[u8;32]', + Address20: '[u8;20]', + PlainString: 'Vec', }, }, /// Validation Data LitentryValidationData: { _enum: { - Web2Validation: "Web2ValidationData", - Web3Validation: "Web3ValidationData", + Web2Validation: 'Web2ValidationData', + Web3Validation: 'Web3ValidationData', }, }, Web2ValidationData: { _enum: { - Twitter: "TwitterValidationData", - Discord: "DiscordValidationData", + Twitter: 'TwitterValidationData', + Discord: 'DiscordValidationData', }, }, TwitterValidationData: { - tweet_id: "Vec", + tweet_id: 'Vec', }, DiscordValidationData: { - channel_id: "Vec", - message_id: "Vec", - guild_id: "Vec", + channel_id: 'Vec', + message_id: 'Vec', + guild_id: 'Vec', }, Web3ValidationData: { _enum: { - Substrate: "Web3CommonValidationData", - Evm: "Web3CommonValidationData", + Substrate: 'Web3CommonValidationData', + Evm: 'Web3CommonValidationData', }, }, Web3CommonValidationData: { - message: "Vec", - signature: "IdentityMultiSignature", + message: 'Vec', + signature: 'IdentityMultiSignature', }, IdentityMultiSignature: { _enum: { - Ed25519: "ed25519::Signature", - Sr25519: "sr25519::Signature", - Ecdsa: "ecdsa::Signature", - Ethereum: "EthereumSignature", + Ed25519: 'ed25519::Signature', + Sr25519: 'sr25519::Signature', + Ecdsa: 'ecdsa::Signature', + Ethereum: 'EthereumSignature', }, }, - EthereumSignature: "([u8; 65])", + EthereumSignature: '([u8; 65])', IdentityGenericEvent: { - who: "AccountId", - identity: "LitentryIdentity", - id_graph: "Vec<(LitentryIdentity, IdentityContext)>", + who: 'AccountId', + identity: 'LitentryIdentity', + id_graph: 'Vec<(LitentryIdentity, IdentityContext)>', }, IdentityContext: { - metadata: "Option>", - linking_request_block: "Option", - verification_request_block: "Option", - is_verified: "bool", - } + metadata: 'Option>', + linking_request_block: 'Option', + verification_request_block: 'Option', + is_verified: 'bool', + }, }; export type WorkerRpcReturnValue = { @@ -252,19 +252,19 @@ export type Web3Network = { Evm?: EvmNetwork; }; -export type Web2Network = "Twitter" | "Discord" | "Github"; -export type SubstrateNetwork = "Polkadot" | "Kusama" | "Litentry" | "Litmus"; -export type EvmNetwork = "Ethereum" | "BSC"; +export type Web2Network = 'Twitter' | 'Discord' | 'Github'; +export type SubstrateNetwork = 'Polkadot' | 'Kusama' | 'Litentry' | 'Litmus'; +export type EvmNetwork = 'Ethereum' | 'BSC'; export type IdentityGenericEvent = { - who: HexString, - identity: LitentryIdentity, - idGraph: [LitentryIdentity, IdentityContext][] -} + who: HexString; + identity: LitentryIdentity; + idGraph: [LitentryIdentity, IdentityContext][]; +}; export type IdentityContext = { - metadata?: HexString - linking_request_block?: number, - verification_request_block?: number, - is_verified: boolean, -} + metadata?: HexString; + linking_request_block?: number; + verification_request_block?: number; + is_verified: boolean; +}; diff --git a/tee-worker/ts-tests/utils.ts b/tee-worker/ts-tests/utils.ts index 95dd0d2b4c..43cea9ba53 100644 --- a/tee-worker/ts-tests/utils.ts +++ b/tee-worker/ts-tests/utils.ts @@ -1,9 +1,9 @@ -import "./config"; -import WebSocketAsPromised = require("websocket-as-promised"); -import WebSocket = require("ws"); -import Options from "websocket-as-promised/types/options"; -import { ApiPromise, Keyring, WsProvider } from "@polkadot/api"; -import { StorageKey, Vec } from "@polkadot/types"; +import './config'; +import WebSocketAsPromised = require('websocket-as-promised'); +import WebSocket = require('ws'); +import Options from 'websocket-as-promised/types/options'; +import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; +import { StorageKey, Vec } from '@polkadot/types'; import { AESOutput, IntegrationTestContext, @@ -12,27 +12,27 @@ import { teeTypes, WorkerRpcReturnString, WorkerRpcReturnValue, -} from "./type-definitions"; -import { blake2AsHex, cryptoWaitReady } from "@polkadot/util-crypto"; -import { KeyringPair } from "@polkadot/keyring/types"; -import { Codec } from "@polkadot/types/types"; +} from './type-definitions'; +import { blake2AsHex, cryptoWaitReady } from '@polkadot/util-crypto'; +import { KeyringPair } from '@polkadot/keyring/types'; +import { Codec } from '@polkadot/types/types'; import { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; -import { HexString } from "@polkadot/util/types"; -import { hexToU8a, u8aToHex } from "@polkadot/util"; -import { KeyObject } from "crypto"; -import { EventRecord } from "@polkadot/types/interfaces"; -import { after, before, describe } from "mocha"; -import { randomAsHex } from "@polkadot/util-crypto"; -import { generateChallengeCode, getSigner } from "./web3/setup"; -import { ethers } from "ethers"; -import { Web3Provider } from "@ethersproject/providers"; -import { generateTestKeys } from "./web3/functions"; +import { HexString } from '@polkadot/util/types'; +import { hexToU8a, u8aToHex } from '@polkadot/util'; +import { KeyObject } from 'crypto'; +import { EventRecord } from '@polkadot/types/interfaces'; +import { after, before, describe } from 'mocha'; +import { randomAsHex } from '@polkadot/util-crypto'; +import { generateChallengeCode, getSigner } from './web3/setup'; +import { ethers } from 'ethers'; +import { Web3Provider } from '@ethersproject/providers'; +import { generateTestKeys } from './web3/functions'; -const base58 = require("micro-base58"); -const crypto = require("crypto"); +const base58 = require('micro-base58'); +const crypto = require('crypto'); // in order to handle self-signed certificates we need to turn off the validation // TODO add self signed certificate ?? -process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; export function sleep(secs: number) { return new Promise((resolve) => { @@ -46,34 +46,27 @@ export async function sendRequest( api: ApiPromise ): Promise { const resp = await wsClient.sendRequest(request, { requestId: 1, timeout: 6000 }); - const resp_json = api - .createType("WorkerRpcReturnValue", resp.result) - .toJSON() as WorkerRpcReturnValue; + const resp_json = api.createType('WorkerRpcReturnValue', resp.result).toJSON() as WorkerRpcReturnValue; return resp_json; } -export async function getTEEShieldingKey( - wsClient: WebSocketAsPromised, - api: ApiPromise -): Promise { - let request = { jsonrpc: "2.0", method: "author_getShieldingKey", params: [], id: 1 }; +export async function getTEEShieldingKey(wsClient: WebSocketAsPromised, api: ApiPromise): Promise { + let request = { jsonrpc: '2.0', method: 'author_getShieldingKey', params: [], id: 1 }; let respJSON = await sendRequest(wsClient, request, api); - const pubKeyHex = api - .createType("WorkerRpcReturnString", respJSON.value) - .toJSON() as WorkerRpcReturnString; - let chunk = Buffer.from(pubKeyHex.vec.slice(2), "hex"); - let pubKeyJSON = JSON.parse(chunk.toString("utf-8")) as PubicKeyJson; + const pubKeyHex = api.createType('WorkerRpcReturnString', respJSON.value).toJSON() as WorkerRpcReturnString; + let chunk = Buffer.from(pubKeyHex.vec.slice(2), 'hex'); + let pubKeyJSON = JSON.parse(chunk.toString('utf-8')) as PubicKeyJson; return crypto.createPublicKey({ key: { - alg: "RSA-OAEP-256", - kty: "RSA", - use: "enc", - n: Buffer.from(pubKeyJSON.n.reverse()).toString("base64url"), - e: Buffer.from(pubKeyJSON.e.reverse()).toString("base64url"), + alg: 'RSA-OAEP-256', + kty: 'RSA', + use: 'enc', + n: Buffer.from(pubKeyJSON.n.reverse()).toString('base64url'), + e: Buffer.from(pubKeyJSON.e.reverse()).toString('base64url'), }, - format: "jwk", + format: 'jwk', }); } @@ -98,27 +91,23 @@ export async function initIntegrationTestContext( }); await cryptoWaitReady(); const keys = (await api.query.sidechain.workerForShard.entries()) as [StorageKey, Codec][]; - let shard = ""; + let shard = ''; for (let i = 0; i < keys.length; i++) { //TODO shard may be different from mr_enclave. The default value of shard is mr_enclave shard = keys[i][0].args[0].toHex(); - console.log("query worker shard: ", shard); + console.log('query worker shard: ', shard); break; } - if (shard == "") { - throw new Error("shard not found"); + if (shard == '') { + throw new Error('shard not found'); } - // random shard for testing - // let shard = randomAsHex(32); - // const endpoint = "wss://localhost:2000" const wsp = new WebSocketAsPromised(workerEndpoint, ({ createWebSocket: (url: any) => new WebSocket(url), extractMessageData: (event: any) => event, packMessage: (data: any) => JSON.stringify(data), unpackMessage: (data: string | ArrayBuffer | Blob) => JSON.parse(data.toString()), - attachRequestId: (data: any, requestId: string | number) => - Object.assign({ id: requestId }, data), + attachRequestId: (data: any, requestId: string | number) => Object.assign({ id: requestId }, data), extractRequestId: (data: any) => data && data.id, // read requestId from message `id` field })); await wsp.open(); @@ -138,7 +127,7 @@ export async function initIntegrationTestContext( export async function sendTxUntilInBlock(api: ApiPromise, tx: SubmittableExtrinsic, signer: KeyringPair) { return new Promise<{ block: string }>(async (resolve, reject) => { const nonce = await api.rpc.system.accountNextIndex(signer.address); - await tx.signAndSend(signer, {nonce}, (result) => { + await tx.signAndSend(signer, { nonce }, (result) => { if (result.status.isInBlock) { console.log(`Transaction included at blockHash ${result.status.asInBlock}`); resolve({ @@ -163,22 +152,15 @@ export async function listenEncryptedEvents( const currentBlockNumber = header.number.toNumber(); if (startBlock == 0) startBlock = currentBlockNumber; if (currentBlockNumber > startBlock + timeout) { - reject("timeout"); + reject('timeout'); return; } console.log(`Chain is at block: #${header.number}`); const signedBlock = await context.substrate.rpc.chain.getBlock(header.hash); - const allEvents = (await context.substrate.query.system.events.at( - header.hash - )) as Vec; + const allEvents = (await context.substrate.query.system.events.at(header.hash)) as Vec; signedBlock.block.extrinsics.forEach((ex, index) => { - if ( - !( - ex.method.section === filterObj.module && - ex.method.method === filterObj.method - ) - ) { + if (!(ex.method.section === filterObj.module && ex.method.method === filterObj.method)) { return; } allEvents @@ -191,7 +173,6 @@ export async function listenEncryptedEvents( ); }) .forEach(({ event }) => { - // const eventData = event.data as AESOutput; const data = event.data as AESOutput[]; const eventData: HexString[] = []; for (let i = 0; i < data.length; i++) { @@ -206,45 +187,22 @@ export async function listenEncryptedEvents( }); } -// export function encryptWithAES(key: HexString, plaintext: HexString): [Buffer, Buffer, Buffer] { -// console.log("plaintext: ", plaintext) -// const iv = new Buffer(crypto.randomBytes(12), 'utf8'); -// const secretKey = crypto.createSecretKey(hexToU8a(key)) -// console.log(secretKey) -// const cipher = crypto.createCipheriv('aes-256-gcm', secretKey, iv); -// cipher.setAAD(Buffer.from('', 'hex')) -// let enc1 = cipher.update(hexToU8a(plaintext)); -// let enc2 = cipher.final(); -// console.log('111', enc1.toString('hex'), enc2.toString('hex')) -// -// const decipher = crypto.createDecipheriv('aes-256-gcm', secretKey, iv); -// decipher.setAuthTag(cipher.getAuthTag()) -// console.log(decipher.update(enc1).toString('hex')) -// console.log(decipher.final().toString('hex')) -// console.log(`0x${iv.toString('hex')}`) -// return [Buffer.concat([enc1, enc2]), iv, cipher.getAuthTag()]; -// } - export function decryptWithAES(key: HexString, aesOutput: AESOutput): HexString { const secretKey = crypto.createSecretKey(hexToU8a(key)); const tagSize = 16; - const ciphertext = aesOutput.ciphertext ? aesOutput.ciphertext : hexToU8a("0x"); - const initialization_vector = aesOutput.nonce ? aesOutput.nonce : hexToU8a("0x"); - const aad = aesOutput.aad ? aesOutput.aad : hexToU8a("0x"); + const ciphertext = aesOutput.ciphertext ? aesOutput.ciphertext : hexToU8a('0x'); + const initialization_vector = aesOutput.nonce ? aesOutput.nonce : hexToU8a('0x'); + const aad = aesOutput.aad ? aesOutput.aad : hexToU8a('0x'); // notice!!! extract author_tag from ciphertext // maybe this code only works with rust aes encryption const authorTag = ciphertext.subarray(ciphertext.length - tagSize); - const decipher = crypto.createDecipheriv("aes-256-gcm", secretKey, initialization_vector); + const decipher = crypto.createDecipheriv('aes-256-gcm', secretKey, initialization_vector); decipher.setAAD(aad); decipher.setAuthTag(authorTag); - let part1 = decipher.update( - ciphertext.subarray(0, ciphertext.length - tagSize), - undefined, - "hex" - ); - let part2 = decipher.final("hex"); + let part1 = decipher.update(ciphertext.subarray(0, ciphertext.length - tagSize), undefined, 'hex'); + let part2 = decipher.final('hex'); return `0x${part1 + part2}`; } @@ -258,7 +216,7 @@ export async function createTrustedCallSigned( params: Array ) { const [variant, argType] = trustedCall; - const call = api.createType("TrustedCall", { + const call = api.createType('TrustedCall', { [variant]: api.createType(argType, params), }); const payload = Uint8Array.from([ @@ -267,41 +225,36 @@ export async function createTrustedCallSigned( ...base58.decode(mrenclave), ...hexToU8a(shard), ]); - const signature = api.createType("MultiSignature", { + const signature = api.createType('MultiSignature', { Sr25519: u8aToHex(account.sign(payload)), }); - return api.createType("TrustedCallSigned", { + return api.createType('TrustedCallSigned', { call: call, index: nonce, signature: signature, }); } -export function encryptWithTeeShieldingKey( - teeShieldingKey: KeyObject, - plaintext: HexString -): Buffer { +export function encryptWithTeeShieldingKey(teeShieldingKey: KeyObject, plaintext: HexString): Buffer { return crypto.publicEncrypt( { key: teeShieldingKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, - oaepHash: "sha256", + oaepHash: 'sha256', }, hexToU8a(plaintext) ); } // + + - export function generateVerificationMessage( context: IntegrationTestContext, challengeCode: Uint8Array, signerAddress: Uint8Array, identity: LitentryIdentity ): HexString { - const encode = context.substrate.createType("LitentryIdentity", identity).toU8a(); + const encode = context.substrate.createType('LitentryIdentity', identity).toU8a(); const msg = Buffer.concat([challengeCode, signerAddress, encode]); - // return encryptWithTeeShieldingKey(context.teeShieldingKey, `0x${msg.toString('hex')}`) return blake2AsHex(msg, 256); } @@ -311,7 +264,7 @@ export function describeLitentry(title: string, cb: (context: IntegrationTestCon this.timeout(6000000); let context: IntegrationTestContext = { defaultSigner: {} as KeyringPair, - shard: "0x11" as HexString, + shard: '0x11' as HexString, substrate: {} as ApiPromise, tee: {} as WebSocketAsPromised, teeShieldingKey: {} as KeyObject, @@ -319,7 +272,7 @@ export function describeLitentry(title: string, cb: (context: IntegrationTestCon ethersWallet: {}, }; - before("Starting Litentry(parachain&tee)", async function () { + before('Starting Litentry(parachain&tee)', async function () { //env url const tmp = await initIntegrationTestContext( process.env.WORKER_END_POINT!, diff --git a/tee-worker/ts-tests/web3/functions.ts b/tee-worker/ts-tests/web3/functions.ts index 5d496354ac..3e89b6c34d 100644 --- a/tee-worker/ts-tests/web3/functions.ts +++ b/tee-worker/ts-tests/web3/functions.ts @@ -1,6 +1,6 @@ -import { Signer } from "@polkadot/types/types"; -import { isString, u8aToHex, u8aToU8a, stringToU8a } from "@polkadot/util"; -import type { KeyringPair } from "@polkadot/keyring/types"; +import { Signer } from '@polkadot/types/types'; +import { isString, u8aToHex, u8aToU8a, stringToU8a } from '@polkadot/util'; +import type { KeyringPair } from '@polkadot/keyring/types'; export async function Sign(data: string, options?: KeyringPair): Promise { let signer = options; @@ -16,12 +16,12 @@ export function generateTestKeys(): { eve: string; } { const secp256k1PrivateKeyLength = 32; - const names = ["alice", "bob", "charlie", "dave", "eve"]; + const names = ['alice', 'bob', 'charlie', 'dave', 'eve']; let keys = new Array(); for (const name of names) { const result = Buffer.alloc(secp256k1PrivateKeyLength); - result.fill(name, secp256k1PrivateKeyLength - Buffer.from(name, "utf8").length); - keys.push(result.toString("hex")); + result.fill(name, secp256k1PrivateKeyLength - Buffer.from(name, 'utf8').length); + keys.push(result.toString('hex')); } return { alice: keys[0], bob: keys[1], charlie: keys[2], dave: keys[3], eve: keys[4] }; diff --git a/tee-worker/ts-tests/web3/setup.ts b/tee-worker/ts-tests/web3/setup.ts index 234bc85493..3cb823d1c0 100644 --- a/tee-worker/ts-tests/web3/setup.ts +++ b/tee-worker/ts-tests/web3/setup.ts @@ -1,16 +1,16 @@ -import { Keyring } from "@polkadot/api"; -import type { KeyringPair } from "@polkadot/keyring/types"; -const keyring = new Keyring({ type: "sr25519" }); -const crypto = require("crypto"); +import { Keyring } from '@polkadot/api'; +import type { KeyringPair } from '@polkadot/keyring/types'; +const keyring = new Keyring({ type: 'sr25519' }); +const crypto = require('crypto'); export function getSigner(index: number): KeyringPair { - let Alice = keyring.addFromUri("//Alice", { name: "Alice" }); - let Bob = keyring.addFromUri("//Bob", { name: "Bob" }); - let Charlie = keyring.addFromUri("//Charlie", { name: "Charlie" }); - let Eve = keyring.addFromUri("//Eve", { name: "Eve" }); + let Alice = keyring.addFromUri('//Alice', { name: 'Alice' }); + let Bob = keyring.addFromUri('//Bob', { name: 'Bob' }); + let Charlie = keyring.addFromUri('//Charlie', { name: 'Charlie' }); + let Eve = keyring.addFromUri('//Eve', { name: 'Eve' }); const signers = [Alice, Bob, Charlie, Eve]; return signers[index]; } export function generateChallengeCode(): String { - return crypto.randomBytes(16).toString("hex"); + return crypto.randomBytes(16).toString('hex'); } diff --git a/tee-worker/ts-tests/yarn.lock b/tee-worker/ts-tests/yarn.lock index 562c61257b..bbddaa6ca1 100644 --- a/tee-worker/ts-tests/yarn.lock +++ b/tee-worker/ts-tests/yarn.lock @@ -1847,6 +1847,11 @@ picomatch@^2.0.4, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +prettier@2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" + integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== + promise-controller@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-controller/-/promise-controller-1.0.0.tgz#81ebea71271aa40ac8f3bebccab3d4158dc4cc02" diff --git a/ts-tests/tests/bridge.test.ts b/ts-tests/tests/bridge.test.ts index b40e03e71c..d1af5472e3 100644 --- a/ts-tests/tests/bridge.test.ts +++ b/ts-tests/tests/bridge.test.ts @@ -72,7 +72,8 @@ describeCrossChainTransfer('Test Cross-chain Transfer', ``, (context) => { handlerBalance .div(BigNumber.from(1000000)) .add(BigNumber.from(100)) - .add(BigNumber.from(fee.toString())).toString(), + .add(BigNumber.from(fee.toString())) + .toString(), receipt, 0 ), diff --git a/ts-tests/yarn.lock b/ts-tests/yarn.lock index e153c47fa9..2e6339367c 100644 --- a/ts-tests/yarn.lock +++ b/ts-tests/yarn.lock @@ -901,20 +901,6 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/bn.js@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - -"@types/bn.js@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - "@types/chai@^4.3.1": version "4.3.4" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" @@ -1341,20 +1327,6 @@ body-parser@1.20.1, body-parser@^1.16.0: type-is "~1.6.18" unpipe "1.0.0" -boxen@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1487,6 +1459,11 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + cacheable-lookup@^6.0.4: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz#0330a543471c61faa4e9035db583aad753b36385" @@ -1721,11 +1698,6 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2665,7 +2637,7 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== -get-intrinsic@^1.0.2: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== @@ -2674,15 +2646,6 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.3" -get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -2857,12 +2820,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.1, has-symbols@^1.0.2: +has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== @@ -2872,13 +2830,6 @@ has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -3463,24 +3414,12 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== dependencies: - mime-db "1.52.0" - -mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" + mime-db "1.51.0" mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" @@ -3745,6 +3684,13 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.0.tgz#37e71db4ecc257057af828d523a7243d651d91e4" @@ -3814,21 +3760,6 @@ object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-inspect@^1.11.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - -object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" @@ -3927,16 +3858,6 @@ pako@^2.0.4: resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== -pako@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" - integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== - -pako@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" - integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -4111,13 +4032,6 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - escape-goat "^2.0.0" - qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -4882,26 +4796,6 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-notifier@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" - integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== - dependencies: - boxen "^5.0.0" - chalk "^4.1.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.4.0" - is-npm "^5.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.1.0" - pupa "^2.1.1" - semver "^7.3.4" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4947,11 +4841,6 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" @@ -5331,11 +5220,6 @@ ws@^8.8.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - xhr-request-promise@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c"