From 9b9f865575aee1e6a96f9aee99921e271e885b65 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:06:07 +0800 Subject: [PATCH 01/43] P-314 add lit holding amount (#2324) * Add LIT HOLDING AMOUNT * make fmt * small Update --- primitives/core/src/assertion.rs | 37 +++++---- .../commands/litentry/request_vc.rs | 32 ++++---- .../commands/litentry/request_vc_direct.rs | 6 +- .../src/achainable/amount_token.rs | 69 ++++++++++++----- .../assertion-build/src/achainable/mod.rs | 66 +++++++++++++++- .../src/achainable/lit_holding_amount.rs | 75 +++++++++++++++++++ .../core/credentials/src/achainable/mod.rs | 1 + .../core/data-providers/src/achainable.rs | 10 ++- .../data-providers/src/achainable_names.rs | 37 +++++++++ 9 files changed, 272 insertions(+), 61 deletions(-) create mode 100644 tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 85e4eac057..37ef6b2ab7 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -40,7 +40,14 @@ pub struct AchainableAmountHolding { #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct AchainableAmountToken { pub name: ParameterString, - pub chain: Web3Network, + + // Considering the uniformity of the structure, all relevant chain structures should be changed + // to BoundedWeb3Network. However, this would be a significant modification for the previous + // VC. Considering the tight timeline for this New Year compain, we will temporarily only + // change this AchainableAmountToken' chain field to BoundedWeb3Network. Afterwards, it needs + // to be modified to be consistent. + pub chain: BoundedWeb3Network, + pub amount: ParameterString, pub token: Option, } @@ -163,20 +170,20 @@ impl AchainableParams { } } - pub fn chain(&self) -> Web3Network { + pub fn chains(&self) -> Vec { match self { - AchainableParams::AmountHolding(p) => p.chain, - AchainableParams::AmountToken(p) => p.chain, - AchainableParams::Amount(p) => p.chain, - AchainableParams::Amounts(p) => p.chain, - AchainableParams::Basic(p) => p.chain, - AchainableParams::BetweenPercents(p) => p.chain, - AchainableParams::ClassOfYear(p) => p.chain, - AchainableParams::DateInterval(p) => p.chain, - AchainableParams::DatePercent(p) => p.chain, - AchainableParams::Date(p) => p.chain, - AchainableParams::Token(p) => p.chain, - AchainableParams::Mirror(p) => p.chain, + AchainableParams::AmountHolding(arg) => vec![arg.chain], + AchainableParams::AmountToken(arg) => arg.chain.to_vec(), + AchainableParams::Amount(arg) => vec![arg.chain], + AchainableParams::Amounts(arg) => vec![arg.chain], + AchainableParams::Basic(arg) => vec![arg.chain], + AchainableParams::BetweenPercents(arg) => vec![arg.chain], + AchainableParams::ClassOfYear(arg) => vec![arg.chain], + AchainableParams::DateInterval(arg) => vec![arg.chain], + AchainableParams::DatePercent(arg) => vec![arg.chain], + AchainableParams::Date(arg) => vec![arg.chain], + AchainableParams::Token(arg) => vec![arg.chain], + AchainableParams::Mirror(arg) => vec![arg.chain], } } } @@ -263,7 +270,7 @@ impl Assertion { // polkadot paticipation Self::A14 => vec![Web3Network::Polkadot], // Achainable Assertions - Self::Achainable(a) => vec![a.chain()], + Self::Achainable(arg) => arg.chains(), // Oneblock Assertion Self::Oneblock(..) => vec![Web3Network::Polkadot, Web3Network::Kusama], Self::WeirdoGhostGangHolder => vec![Web3Network::Ethereum], diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index 400066ec6e..58cbad30de 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -29,9 +29,9 @@ use litentry_primitives::{ aes_decrypt, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams, - AchainableToken, Assertion, ContestType, GenericDiscordRoleType, Identity, OneBlockCourseType, - ParameterString, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network, - REQUEST_AES_KEY_LEN, + AchainableToken, Assertion, BoundedWeb3Network, ContestType, GenericDiscordRoleType, Identity, + OneBlockCourseType, ParameterString, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, + Web3Network, REQUEST_AES_KEY_LEN, }; use sp_core::Pair; @@ -56,6 +56,15 @@ pub fn to_para_str(s: &str) -> ParameterString { ParameterString::truncate_from(s.as_bytes().to_vec()) } +pub fn to_chains(networks: &[String]) -> BoundedWeb3Network { + let networks: Vec = networks + .iter() + .map(|n| n.as_str().try_into().expect("cannot convert to Web3Network")) + .collect(); + + networks.try_into().unwrap() +} + #[derive(Parser)] pub struct RequestVcCommand { /// did account to whom the vc will be issued @@ -182,7 +191,7 @@ pub struct AmountHoldingArg { #[derive(Args)] pub struct AmountTokenArg { pub name: String, - pub chain: String, + pub chain: Vec, pub amount: String, pub token: Option, } @@ -274,14 +283,7 @@ impl RequestVcCommand { Command::A4(arg) => Assertion::A4(to_para_str(&arg.minimum_amount)), Command::A6 => Assertion::A6, Command::A7(arg) => Assertion::A7(to_para_str(&arg.minimum_amount)), - Command::A8(arg) => { - let networks: Vec = arg - .networks - .iter() - .map(|n| n.as_str().try_into().expect("cannot convert to Web3Network")) - .collect(); - Assertion::A8(networks.try_into().unwrap()) - }, + Command::A8(arg) => Assertion::A8(to_chains(&arg.networks)), Command::A10(arg) => Assertion::A10(to_para_str(&arg.minimum_amount)), Command::A11(arg) => Assertion::A11(to_para_str(&arg.minimum_amount)), Command::A13(arg) => { @@ -315,11 +317,7 @@ impl RequestVcCommand { AchainableCommand::AmountToken(arg) => Assertion::Achainable(AchainableParams::AmountToken(AchainableAmountToken { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), amount: to_para_str(&arg.amount), token: arg.token.as_ref().map(|s| to_para_str(s)), })), diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs index 7550a12ea2..0d6449053a 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs @@ -122,11 +122,7 @@ impl RequestVcDirectCommand { AchainableCommand::AmountToken(arg) => Assertion::Achainable(AchainableParams::AmountToken(AchainableAmountToken { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), amount: to_para_str(&arg.amount), token: arg.token.as_ref().map(|s| to_para_str(s)), })), diff --git a/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs b/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs index c3933e6fd7..02b2b03e30 100644 --- a/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs +++ b/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs @@ -20,32 +20,32 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; -use crate::{achainable::request_achainable_balance, *}; -use lc_credentials::litentry_profile::token_balance::TokenBalanceInfo; -use lc_data_providers::{ETokenAddress, TokenFromString}; +use crate::{ + achainable::{query_lit_holding_amount, request_achainable_balance}, + *, +}; +use lc_credentials::{ + achainable::lit_holding_amount::AchainableLitHoldingAmountUpdate, + litentry_profile::token_balance::TokenBalanceInfo, +}; +use lc_data_providers::{ + achainable_names::{AchainableNameAmountToken, GetAchainableName}, + ETokenAddress, TokenFromString, +}; -// Input params: -// { -// "name": "ERC20 balance over {amount}", -// "address": "0xb59490ab09a0f526cc7305822ac65f2ab12f9723", -// "params": { -// "chain": "ethereum", -// "amount": "0", -// "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" -// } -// } +const LIT_HOLDING_AMOUNT_NAME: &str = "LIT Holding Amount"; -/// LIT / USDC / USDT Holder +/// USDC / USDT Holder /// assertions:[ /// { /// and:[ /// { -/// src:$lit_holding_amount, +/// src:$usdc_holding_amount, /// op: >=, /// dst:100 /// }, /// { -/// src:$lit_holding_amount, +/// src:$usdc_holding_amount, /// op: <, /// dst:200 /// }, @@ -57,16 +57,37 @@ pub fn build_amount_token( req: &AssertionBuildRequest, param: AchainableAmountToken, ) -> Result { - debug!("Assertion Achainable build_amount_token, who: {:?}", account_id_to_string(&req.who)); + debug!("Assertion Building AchainableAmountToken"); let identities = transpose_identity(&req.identities); + let achainable_param = AchainableParams::AmountToken(param.clone()); + + // LIT Holding Amount + // Since "LIT Holding Amount" is a custom name in this context, we need to differentiate it by identifying which VC it refers to. + if is_lit_holding_amount(&achainable_param)? { + let lit_holding_amount = query_lit_holding_amount(&achainable_param, &identities)?; + + return match Credential::new(&req.who, &req.shard) { + Ok(mut credential_unsigned) => { + credential_unsigned.update_lit_holding_amount(lit_holding_amount); + Ok(credential_unsigned) + }, + Err(e) => { + error!("Generate unsigned credential failed {:?}", e); + Err(Error::RequestVCFailed( + Assertion::Achainable(achainable_param), + e.into_error_detail(), + )) + }, + } + } + + // USDC / USDT Holder let addresses = identities .into_iter() .flat_map(|(_, addresses)| addresses) .collect::>(); - - let token = ETokenAddress::from_vec(param.clone().token.unwrap_or_default()); - let achainable_param = AchainableParams::AmountToken(param); + let token = ETokenAddress::from_vec(param.token.unwrap_or_default()); let balance = request_achainable_balance(addresses, achainable_param.clone())? .parse::() .map_err(|_| { @@ -89,3 +110,11 @@ pub fn build_amount_token( }, } } + +fn is_lit_holding_amount(param: &AchainableParams) -> Result { + let name_amount_token = AchainableNameAmountToken::from(param.name()).map_err(|e| { + Error::RequestVCFailed(Assertion::Achainable(param.clone()), e.into_error_detail()) + })?; + + Ok(name_amount_token.name() == LIT_HOLDING_AMOUNT_NAME) +} diff --git a/tee-worker/litentry/core/assertion-build/src/achainable/mod.rs b/tee-worker/litentry/core/assertion-build/src/achainable/mod.rs index c5f9af7830..4d765c556a 100644 --- a/tee-worker/litentry/core/assertion-build/src/achainable/mod.rs +++ b/tee-worker/litentry/core/assertion-build/src/achainable/mod.rs @@ -28,11 +28,15 @@ use self::{ }; use crate::*; use lc_data_providers::{ - achainable::{AchainableClient, AchainableTagDeFi, HoldingAmount, Params}, - DataProviderConfigReader, ReadDataProviderConfig, + achainable::{ + AchainableClient, AchainableTagDeFi, HoldingAmount, Params, ParamsBasicTypeWithAmountToken, + }, + achainable_names::{AchainableNameAmountToken, GetAchainableName}, + DataProviderConfigReader, ReadDataProviderConfig, LIT_TOKEN_ADDRESS, }; use lc_stf_task_sender::AssertionBuildRequest; use litentry_primitives::AchainableParams; +use std::string::ToString; pub mod amount; pub mod amount_holding; @@ -156,3 +160,61 @@ pub fn request_achainable_balance( Ok(balance) } + +pub fn query_lit_holding_amount( + aparam: &AchainableParams, + identities: &Vec<(Web3Network, Vec)>, +) -> Result { + let mut total_lit_balance = 0_f64; + + let data_provider_config = DataProviderConfigReader::read() + .map_err(|e| Error::RequestVCFailed(Assertion::Achainable(aparam.clone()), e))?; + let mut client: AchainableClient = AchainableClient::new(&data_provider_config); + + for (network, addresses) in identities { + let (q_name, q_network, q_token) = if *network == Web3Network::Ethereum { + ( + AchainableNameAmountToken::ERC20BalanceOverAmount, + Web3Network::Ethereum, + Some(LIT_TOKEN_ADDRESS.to_string()), + ) + } else if *network == Web3Network::Bsc { + ( + AchainableNameAmountToken::BEP20BalanceOverAmount, + Web3Network::Bsc, + Some(LIT_TOKEN_ADDRESS.to_string()), + ) + } else if *network == Web3Network::Litentry { + (AchainableNameAmountToken::BalanceOverAmount, Web3Network::Litentry, None) + } else if *network == Web3Network::Litmus { + (AchainableNameAmountToken::BalanceOverAmount, Web3Network::Litmus, None) + } else { + continue + }; + + let q_param = ParamsBasicTypeWithAmountToken::new( + q_name.name().to_string(), + &q_network, + "0".to_string(), + q_token, + ); + + let params = Params::ParamsBasicTypeWithAmountToken(q_param); + let balance = client + .holding_amount(addresses.clone(), params) + .map_err(|e| { + Error::RequestVCFailed(Assertion::Achainable(aparam.clone()), e.into_error_detail()) + })? + .parse::() + .map_err(|_| { + Error::RequestVCFailed( + Assertion::Achainable(aparam.clone()), + ErrorDetail::ParseError, + ) + })?; + + total_lit_balance += balance; + } + + Ok(total_lit_balance as usize) +} diff --git a/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs b/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs new file mode 100644 index 0000000000..60e8434f74 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs @@ -0,0 +1,75 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + assertion_logic::AssertionLogic, nodereal::bnb_domain::RangeCredentialDetail, Credential, +}; +use std::vec::Vec; + +// Type / Info +const LIT_HOLDING_AMOUNT_INFO: (&str, &str) = + ("Token holding amount", "The amount of a particular token you are holding"); +const LIT_HOLDING_AMOUNT_BREAKDOWN: &str = "lit_holding_amount"; +const LIT_BALANCE_RANGE: [usize; 10] = [0, 1, 50, 100, 200, 500, 800, 1200, 1600, 3000]; + +pub struct LitHoldingAmount { + pub amount: usize, +} + +impl LitHoldingAmount { + pub fn new(amount: usize) -> Self { + Self { amount } + } +} + +impl RangeCredentialDetail for LitHoldingAmount { + fn get_info(&self) -> (&'static str, &'static str) { + LIT_HOLDING_AMOUNT_INFO + } + + fn get_range(&self) -> Vec { + LIT_BALANCE_RANGE.to_vec() + } + + fn get_last_value(&self) -> usize { + 3000 + } + + fn get_breakdown(&self) -> &'static str { + LIT_HOLDING_AMOUNT_BREAKDOWN + } +} + +pub trait AchainableLitHoldingAmountUpdate { + fn update_lit_holding_amount(&mut self, balance: usize); +} + +impl AchainableLitHoldingAmountUpdate for Credential { + fn update_lit_holding_amount(&mut self, amount: usize) { + let lit_holding_amount = LitHoldingAmount::new(amount); + let items = lit_holding_amount.get_assertion_items(amount); + let mut assertion = AssertionLogic::new_and(); + for item in items { + assertion = assertion.add_item(item); + } + + self.credential_subject.assertions.push(assertion); + self.credential_subject.values.push(true); + + let info = lit_holding_amount.get_info(); + self.add_subject_info(info.1, info.0); + } +} diff --git a/tee-worker/litentry/core/credentials/src/achainable/mod.rs b/tee-worker/litentry/core/credentials/src/achainable/mod.rs index 23e93ac365..f813fdb1fc 100644 --- a/tee-worker/litentry/core/credentials/src/achainable/mod.rs +++ b/tee-worker/litentry/core/credentials/src/achainable/mod.rs @@ -15,3 +15,4 @@ // along with Litentry. If not, see . pub mod amount_holding_time; +pub mod lit_holding_amount; diff --git a/tee-worker/litentry/core/data-providers/src/achainable.rs b/tee-worker/litentry/core/data-providers/src/achainable.rs index 9e6f51bd9b..558079aa43 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable.rs @@ -158,6 +158,10 @@ impl ReqBody { pub fn new(address: String, params: Params) -> Self { ReqBody { name: params.name(), address, params, include_metadata: true } } + + pub fn new_with_false_metadata(address: String, params: Params) -> Self { + ReqBody { name: params.name(), address, params, include_metadata: false } + } } pub trait AchainableSystemLabelName { @@ -236,7 +240,9 @@ impl TryFrom for Params { let token = if p.token.is_some() { Some(ap.to_string(&p.token.unwrap())?) } else { None }; - let p = ParamsBasicTypeWithAmountToken::new(name, network, amount, token); + // At this step, we do not care about the content inside the chains and instead use real chain data to fill in the request + // so use network[0] as a placehold. + let p = ParamsBasicTypeWithAmountToken::new(name, &network[0], amount, token); Ok(Params::ParamsBasicTypeWithAmountToken(p)) }, AchainableParams::Amount(p) => { @@ -837,7 +843,7 @@ impl HoldingAmount for AchainableClient { fn holding_amount(&mut self, addresses: Vec, param: Params) -> Result { let mut total_balance = 0_f64; for address in addresses.iter() { - let body = ReqBody::new(address.into(), param.clone()); + let body = ReqBody::new_with_false_metadata(address.into(), param.clone()); let balance = self.post(SystemLabelReqPath::default(), &body).and_then(Self::get_balance)?; total_balance += balance; diff --git a/tee-worker/litentry/core/data-providers/src/achainable_names.rs b/tee-worker/litentry/core/data-providers/src/achainable_names.rs index 21e8b41f10..d9a6fe4cbf 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable_names.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable_names.rs @@ -88,3 +88,40 @@ impl AchainableNameAmount { Err(Error::AchainableError("Invalid Achainable Name".to_string())) } } + +#[derive(Debug, PartialEq)] +pub enum AchainableNameAmountToken { + BEP20BalanceOverAmount, + ERC20BalanceOverAmount, + BalanceOverAmount, + LITHoldingAmount, // Custom Name +} + +impl GetAchainableName for AchainableNameAmountToken { + fn name(&self) -> &'static str { + match self { + AchainableNameAmountToken::BEP20BalanceOverAmount => "BEP20 balance over {amount}", + AchainableNameAmountToken::ERC20BalanceOverAmount => "ERC20 balance over {amount}", + AchainableNameAmountToken::BalanceOverAmount => "Balance over {amount}", + AchainableNameAmountToken::LITHoldingAmount => "LIT Holding Amount", + } + } +} + +impl AchainableNameAmountToken { + pub fn from(param: ParameterString) -> Result { + let name_str = vec_to_string(param.to_vec())?; + + if name_str == AchainableNameAmountToken::BEP20BalanceOverAmount.name() { + return Ok(AchainableNameAmountToken::BEP20BalanceOverAmount) + } else if name_str == AchainableNameAmountToken::ERC20BalanceOverAmount.name() { + return Ok(AchainableNameAmountToken::ERC20BalanceOverAmount) + } else if name_str == AchainableNameAmountToken::BalanceOverAmount.name() { + return Ok(AchainableNameAmountToken::BalanceOverAmount) + } else if name_str == AchainableNameAmountToken::LITHoldingAmount.name() { + return Ok(AchainableNameAmountToken::LITHoldingAmount) + } + + Err(Error::AchainableError("Unsupported name in this Type".to_string())) + } +} From d0da1268bfd373f4499349080505d39ccb5ea85c Mon Sep 17 00:00:00 2001 From: BillyWooo Date: Fri, 15 Dec 2023 09:50:52 +0100 Subject: [PATCH 02/43] extend token list (#2329) * extend token list * copy/paste error; renaming --------- Co-authored-by: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Co-authored-by: BillyWooo --- .../src/litentry_profile/token_balance.rs | 103 ++++++++++++++++-- .../litentry/core/data-providers/src/lib.rs | 70 ++++++++++-- ts-tests/tests/evm-contract.test.ts | 4 +- ts-tests/tests/evm-transfer.test.ts | 4 +- 4 files changed, 156 insertions(+), 25 deletions(-) diff --git a/tee-worker/litentry/core/credentials/src/litentry_profile/token_balance.rs b/tee-worker/litentry/core/credentials/src/litentry_profile/token_balance.rs index 613411308b..21f9da8744 100644 --- a/tee-worker/litentry/core/credentials/src/litentry_profile/token_balance.rs +++ b/tee-worker/litentry/core/credentials/src/litentry_profile/token_balance.rs @@ -32,6 +32,31 @@ const USDT_C_TOKEN_BALANCE_RANGE: [f64; 10] = const LIT_TOKEN_BALANCE_RANGE: [f64; 8] = [0.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1600.0, 3000.0]; const WBTC_TOKEN_BALANCE_RANGE: [f64; 10] = [0.0, 0.001, 0.05, 0.1, 0.5, 10.0, 50.0, 100.0, 500.0, 1000.0]; +const CRV_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1800.0]; +const MATIC_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1800.0]; +const DYDX_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0]; +const AMP_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 2000.0, 5000.0, 10000.0, 18000.0, 30000.0, 50000.0, 80000.0, 120000.0]; +const CVX_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0]; +const TUSD_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0]; +const USDD_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0]; +const GUSD_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0]; +const LINK_TOKEN_BALANCE_RANGE: [f64; 9] = [0.0, 1.0, 5.0, 20.0, 40.0, 80.0, 150.0, 240.0, 400.0]; +const GRT_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1800.0]; +const COMP_TOKEN_BALANCE_RANGE: [f64; 11] = + [0.0, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 80.0, 150.0, 250.0, 400.0]; +const PEOPLE_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 200.0, 500.0, 1000.0, 1800.0, 3000.0, 5000.0, 8000.0, 12000.0]; +const GTC_TOKEN_BALANCE_RANGE: [f64; 9] = + [0.0, 1.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0]; pub trait TokenBalanceInfo { fn update_token_balance(&mut self, token: ETokenAddress, balance: f64); @@ -81,27 +106,68 @@ fn update_assertion(token: ETokenAddress, balance: f64, credential: &mut Credent fn get_token_info(token: &ETokenAddress) -> (&'static str, &'static str) { match token { - ETokenAddress::Lit | ETokenAddress::Usdc | ETokenAddress::Usdt | ETokenAddress::Wbtc => - VC_TOKEN_BALANCE_INFOS[0], + ETokenAddress::WBTC + | ETokenAddress::LIT + | ETokenAddress::USDC + | ETokenAddress::USDT + | ETokenAddress::CRV + | ETokenAddress::MATIC + | ETokenAddress::DYDX + | ETokenAddress::AMP + | ETokenAddress::CVX + | ETokenAddress::TUSD + | ETokenAddress::USDD + | ETokenAddress::GUSD + | ETokenAddress::LINK + | ETokenAddress::GRT + | ETokenAddress::COMP + | ETokenAddress::PEOPLE + | ETokenAddress::GTC => VC_TOKEN_BALANCE_INFOS[0], _ => ("UnknownType", ("UnkonwDescription")), } } fn get_assertion_content(token: &ETokenAddress) -> &'static str { match token { - ETokenAddress::Lit => "$lit_holding_amount", - ETokenAddress::Usdc => "$usdc_holding_amount", - ETokenAddress::Usdt => "$usdt_holding_amount", - ETokenAddress::Wbtc => "$wbtc_holding_amount", + ETokenAddress::WBTC => "$wbtc_holding_amount", + ETokenAddress::LIT => "$lit_holding_amount", + ETokenAddress::USDC => "$usdc_holding_amount", + ETokenAddress::USDT => "$usdt_holding_amount", + ETokenAddress::CRV => "$crv_holding_amount", + ETokenAddress::MATIC => "$matic_holding_amount", + ETokenAddress::DYDX => "$dydx_holding_amount", + ETokenAddress::AMP => "$amp_holding_amount", + ETokenAddress::CVX => "$cvx_holding_amount", + ETokenAddress::TUSD => "$tusd_holding_amount", + ETokenAddress::USDD => "$usdd_holding_amount", + ETokenAddress::GUSD => "$gusd_holding_amount", + ETokenAddress::LINK => "$link_holding_amount", + ETokenAddress::GRT => "$grt_holding_amount", + ETokenAddress::COMP => "$comp_holding_amount", + ETokenAddress::PEOPLE => "$people_holding_amount", + ETokenAddress::GTC => "$gtc_holding_amount", _ => "Unknown", } } fn get_balance_range(token: &ETokenAddress) -> Vec { match token { - ETokenAddress::Lit => LIT_TOKEN_BALANCE_RANGE.to_vec(), - ETokenAddress::Usdc | ETokenAddress::Usdt => USDT_C_TOKEN_BALANCE_RANGE.to_vec(), - ETokenAddress::Wbtc => WBTC_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::WBTC => WBTC_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::LIT => LIT_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::USDC | ETokenAddress::USDT => USDT_C_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::CRV => CRV_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::MATIC => MATIC_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::DYDX => DYDX_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::AMP => AMP_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::CVX => CVX_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::TUSD => TUSD_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::USDD => USDD_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::GUSD => GUSD_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::LINK => LINK_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::GRT => GRT_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::COMP => COMP_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::PEOPLE => PEOPLE_TOKEN_BALANCE_RANGE.to_vec(), + ETokenAddress::GTC => GTC_TOKEN_BALANCE_RANGE.to_vec(), _ => { vec![] }, @@ -110,10 +176,23 @@ fn get_balance_range(token: &ETokenAddress) -> Vec { fn get_token_range_last(token: &ETokenAddress) -> f64 { match token { - ETokenAddress::Lit => *LIT_TOKEN_BALANCE_RANGE.last().unwrap_or(&3000.0), - ETokenAddress::Usdc | ETokenAddress::Usdt => + ETokenAddress::WBTC => *WBTC_TOKEN_BALANCE_RANGE.last().unwrap_or(&1000.0), + ETokenAddress::LIT => *LIT_TOKEN_BALANCE_RANGE.last().unwrap_or(&3000.0), + ETokenAddress::USDC | ETokenAddress::USDT => *USDT_C_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), - ETokenAddress::Wbtc => *WBTC_TOKEN_BALANCE_RANGE.last().unwrap_or(&1000.0), + ETokenAddress::CRV => *CRV_TOKEN_BALANCE_RANGE.last().unwrap_or(&1800.0), + ETokenAddress::MATIC => *MATIC_TOKEN_BALANCE_RANGE.last().unwrap_or(&1800.0), + ETokenAddress::DYDX => *DYDX_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), + ETokenAddress::AMP => *AMP_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), + ETokenAddress::CVX => *CVX_TOKEN_BALANCE_RANGE.last().unwrap_or(&12000.0), + ETokenAddress::TUSD => *TUSD_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), + ETokenAddress::USDD => *USDD_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), + ETokenAddress::GUSD => *GUSD_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), + ETokenAddress::LINK => *LINK_TOKEN_BALANCE_RANGE.last().unwrap_or(&400.0), + ETokenAddress::GRT => *GRT_TOKEN_BALANCE_RANGE.last().unwrap_or(&1800.0), + ETokenAddress::COMP => *COMP_TOKEN_BALANCE_RANGE.last().unwrap_or(&400.0), + ETokenAddress::PEOPLE => *PEOPLE_TOKEN_BALANCE_RANGE.last().unwrap_or(&12000.0), + ETokenAddress::GTC => *GTC_TOKEN_BALANCE_RANGE.last().unwrap_or(&1200.0), _ => 0.0, } } diff --git a/tee-worker/litentry/core/data-providers/src/lib.rs b/tee-worker/litentry/core/data-providers/src/lib.rs index 25e03c500f..676a8780cd 100644 --- a/tee-worker/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/litentry/core/data-providers/src/lib.rs @@ -85,13 +85,39 @@ pub const WETH_TOKEN_ADDRESS: &str = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 pub const USDT_TOKEN_ADDRESS: &str = "0xdac17f958d2ee523a2206206994597c13d831ec7"; pub const USDC_TOKEN_ADDRESS: &str = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; pub const LIT_TOKEN_ADDRESS: &str = "0xb59490ab09a0f526cc7305822ac65f2ab12f9723"; +pub const CRV_TOKEN_ADDRESS: &str = "0xd533a949740bb3306d119cc777fa900ba034cd52"; +pub const MATIC_TOKEN_ADDRESS: &str = "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0"; +pub const DYDX_TOKEN_ADDRESS: &str = "0x92d6c1e31e14520e676a687f0a93788b716beff5"; +pub const AMP_TOKEN_ADDRESS: &str = "0xff20817765cb7f73d4bde2e66e067e58d11095c2"; +pub const CVX_TOKEN_ADDRESS: &str = "0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b"; +pub const TUSD_TOKEN_ADDRESS: &str = "0x0000000000085d4780b73119b644ae5ecd22b376"; +pub const USDD_TOKEN_ADDRESS: &str = "0x0c10bf8fcb7bf5412187a595ab97a3609160b5c6"; +pub const GUSD_TOKEN_ADDRESS: &str = "0x056fd409e1d7a124bd7017459dfea2f387b6d5cd"; +pub const LINK_TOKEN_ADDRESS: &str = "0x514910771af9ca656af840dff83e8264ecf986ca"; +pub const GRT_TOKEN_ADDRESS: &str = "0xc944e90c64b2c07662a292be6244bdf05cda44a7"; +pub const COMP_TOKEN_ADDRESS: &str = "0xc00e94cb662c3520282e6f5717214004a7f26888"; +pub const PEOPLE_TOKEN_ADDRESS: &str = "0x7a58c0be72be218b41c608b7fe7c5bb630736c71"; +pub const GTC_TOKEN_ADDRESS: &str = "0xde30da39c46104798bb5aa3fe8b9e0e1f348163f"; #[derive(Debug, PartialEq, PartialOrd)] pub enum ETokenAddress { - Wbtc, - Lit, - Usdc, - Usdt, + WBTC, + LIT, + USDC, + USDT, + CRV, + MATIC, + DYDX, + AMP, + CVX, + TUSD, + USDD, + GUSD, + LINK, + GRT, + COMP, + PEOPLE, + GTC, Unknown, } @@ -102,13 +128,39 @@ impl TokenFromString for ETokenAddress { fn from_vec(vec: ParameterString) -> ETokenAddress { let address = vec_to_string(vec.to_vec()).unwrap_or_default(); if address == WBTC_TOKEN_ADDRESS { - ETokenAddress::Wbtc + ETokenAddress::WBTC } else if address == LIT_TOKEN_ADDRESS { - ETokenAddress::Lit - } else if address == USDT_TOKEN_ADDRESS { - ETokenAddress::Usdt + ETokenAddress::LIT } else if address == USDC_TOKEN_ADDRESS { - ETokenAddress::Usdc + ETokenAddress::USDC + } else if address == USDT_TOKEN_ADDRESS { + ETokenAddress::USDT + } else if address == CRV_TOKEN_ADDRESS { + ETokenAddress::CRV + } else if address == MATIC_TOKEN_ADDRESS { + ETokenAddress::MATIC + } else if address == DYDX_TOKEN_ADDRESS { + ETokenAddress::DYDX + } else if address == AMP_TOKEN_ADDRESS { + ETokenAddress::AMP + } else if address == CVX_TOKEN_ADDRESS { + ETokenAddress::CVX + } else if address == TUSD_TOKEN_ADDRESS { + ETokenAddress::TUSD + } else if address == USDD_TOKEN_ADDRESS { + ETokenAddress::USDD + } else if address == GUSD_TOKEN_ADDRESS { + ETokenAddress::GUSD + } else if address == LINK_TOKEN_ADDRESS { + ETokenAddress::LINK + } else if address == GRT_TOKEN_ADDRESS { + ETokenAddress::GRT + } else if address == COMP_TOKEN_ADDRESS { + ETokenAddress::COMP + } else if address == PEOPLE_TOKEN_ADDRESS { + ETokenAddress::PEOPLE + } else if address == GTC_TOKEN_ADDRESS { + ETokenAddress::GTC } else { ETokenAddress::Unknown } diff --git a/ts-tests/tests/evm-contract.test.ts b/ts-tests/tests/evm-contract.test.ts index 9242688678..618d68b35e 100644 --- a/ts-tests/tests/evm-contract.test.ts +++ b/ts-tests/tests/evm-contract.test.ts @@ -2,7 +2,7 @@ import { assert, expect } from 'chai'; import { step } from 'mocha-steps'; import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; -import { evmToAddress } from '@polkadot/util-crypto' +import { evmToAddress } from '@polkadot/util-crypto'; import Web3 from 'web3'; import { compiled } from './compile'; @@ -63,7 +63,7 @@ describeLitentry('Test EVM Module Contract', ``, (context) => { // If a substrate account using pallet_evm to trigger evm transaction, // it will bump 2 for nonce (one for substrate extrinsic, one for evm). - // +1 nonce for original substrate account, plus another 1 nonce for original substrate account's truncated evm address's mapped susbtrate account. + // +1 nonce for original substrate account, plus another 1 nonce for original substrate account's truncated evm address's mapped susbtrate account. expect(eveCurrentNonce.toNumber()).to.equal(eveInitNonce.toNumber() + 1); expect(evmAccountCurrentBalance.free.toBigInt()).to.equal( evmAccountInitBalance.free.toBigInt() + BigInt(value) diff --git a/ts-tests/tests/evm-transfer.test.ts b/ts-tests/tests/evm-transfer.test.ts index d464a5db33..a804ad073a 100644 --- a/ts-tests/tests/evm-transfer.test.ts +++ b/ts-tests/tests/evm-transfer.test.ts @@ -4,7 +4,7 @@ import { step } from 'mocha-steps'; import { signAndSend, describeLitentry } from './utils'; import { hexToU8a, u8aToHex } from '@polkadot/util'; import { createPair, encodeAddress } from '@polkadot/keyring'; -import { evmToAddress } from '@polkadot/util-crypto' +import { evmToAddress } from '@polkadot/util-crypto'; import Web3 from 'web3'; describeLitentry('Test EVM Module Transfer', ``, (context) => { @@ -75,7 +75,7 @@ describeLitentry('Test EVM Module Transfer', ``, (context) => { // If a substrate account using pallet_evm to trigger evm transaction, // it will bump 2 for nonce (one for substrate extrinsic, one for evm). - // +1 nonce for original substrate account, plus another 1 nonce for original substrate account's truncated evm address's mapped susbtrate account. + // +1 nonce for original substrate account, plus another 1 nonce for original substrate account's truncated evm address's mapped susbtrate account. expect(eveCurrentNonce.toNumber()).to.equal(eveInitNonce.toNumber() + 1); expect(evmAccountCurrentBalance.free.toBigInt()).to.equal( evmAccountInitBalance.free.toBigInt() + BigInt(value) From b5a555c355d4deb8eb7c7940d682ac0980a40869 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:03:43 +0100 Subject: [PATCH 03/43] Add support for BTC account linking (#2331) * add bitcoin identity * add bitcoin sig verification * some update * add bitoin prime identity test * small clippy fix * fix service name --------- Co-authored-by: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> --- .github/workflows/ci.yml | 1 + primitives/core/src/network.rs | 35 ++ scripts/launch-standalone.sh | 2 + .../commands/litentry/link_identity.rs | 17 +- .../interfaces/identity/definitions.ts | 25 +- .../substrate-sgx/sp-io/src/lib.rs | 9 +- .../docker/lit-di-bitcoin-identity-test.yml | 24 ++ .../core/data-providers/src/achainable.rs | 1 + .../litentry/primitives/src/identity.rs | 147 ++++++- tee-worker/litentry/primitives/src/lib.rs | 24 +- .../primitives/src/validation_data.rs | 4 + tee-worker/service/src/prometheus_metrics.rs | 1 + .../rpc-handler/src/direct_top_pool_api.rs | 6 +- .../integration-tests/common/common-types.ts | 7 +- .../integration-tests/common/utils/context.ts | 16 +- .../integration-tests/common/utils/crypto.ts | 37 +- .../common/utils/identity-helper.ts | 38 +- .../common/utils/integration-setup.ts | 14 +- .../di_bitcoin_identity.test.ts | 359 ++++++++++++++++++ .../integration-tests/di_evm_identity.test.ts | 3 +- .../di_substrate_identity.test.ts | 64 +++- .../ts-tests/integration-tests/di_vc.test.ts | 7 +- .../integration-tests/ii_batch.test.ts | 2 +- .../integration-tests/ii_identity.test.ts | 2 +- .../ts-tests/integration-tests/ii_vc.test.ts | 2 +- .../ts-tests/integration-tests/package.json | 4 + tee-worker/ts-tests/pnpm-lock.yaml | 125 ++++++ ts-tests/tests/base-filter.test.ts | 1 - 28 files changed, 898 insertions(+), 79 deletions(-) create mode 100644 tee-worker/docker/lit-di-bitcoin-identity-test.yml create mode 100644 tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 838fbd9f06..0a79308407 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -620,6 +620,7 @@ jobs: - test_name: lit-ii-identity-test - test_name: lit-di-substrate-identity-test - test_name: lit-di-evm-identity-test + - test_name: lit-di-bitcoin-identity-test - test_name: lit-di-vc-test - test_name: lit-parentchain-nonce - test_name: lit-ii-batch-test diff --git a/primitives/core/src/network.rs b/primitives/core/src/network.rs index 45ed984446..171aec5fb8 100644 --- a/primitives/core/src/network.rs +++ b/primitives/core/src/network.rs @@ -69,6 +69,10 @@ pub enum Web3Network { Ethereum, #[codec(index = 8)] Bsc, + + // btc + #[codec(index = 9)] + Bitcoin, } // mainly used in CLI @@ -95,6 +99,10 @@ impl Web3Network { pub fn is_evm(&self) -> bool { matches!(self, Self::Ethereum | Self::Bsc) } + + pub fn is_bitcoin(&self) -> bool { + matches!(self, Self::Bitcoin) + } } pub fn all_web3networks() -> Vec { @@ -109,6 +117,10 @@ pub fn all_evm_web3networks() -> Vec { Web3Network::iter().filter(|n| n.is_evm()).collect() } +pub fn all_bitcoin_web3networks() -> Vec { + Web3Network::iter().filter(|n| n.is_bitcoin()).collect() +} + #[cfg(test)] mod tests { use super::*; @@ -134,6 +146,7 @@ mod tests { Web3Network::SubstrateTestnet => false, Web3Network::Ethereum => true, Web3Network::Bsc => true, + Web3Network::Bitcoin => false, } ) }) @@ -154,6 +167,28 @@ mod tests { Web3Network::SubstrateTestnet => true, Web3Network::Ethereum => false, Web3Network::Bsc => false, + Web3Network::Bitcoin => false, + } + ) + }) + } + + #[test] + fn is_bitcoin_works() { + Web3Network::iter().for_each(|network| { + assert_eq!( + network.is_bitcoin(), + match network { + Web3Network::Polkadot => false, + Web3Network::Kusama => false, + Web3Network::Litentry => false, + Web3Network::Litmus => false, + Web3Network::LitentryRococo => false, + Web3Network::Khala => false, + Web3Network::SubstrateTestnet => false, + Web3Network::Ethereum => false, + Web3Network::Bsc => false, + Web3Network::Bitcoin => true, } ) }) diff --git a/scripts/launch-standalone.sh b/scripts/launch-standalone.sh index a6e159c6a1..0c78c2ecdf 100755 --- a/scripts/launch-standalone.sh +++ b/scripts/launch-standalone.sh @@ -27,3 +27,5 @@ echo "Starting litentry-collator in standalone mode ..." $PARACHAIN_BIN --dev --unsafe-ws-external --unsafe-rpc-external \ --port "${CollatorPort:-30333}" --ws-port "${CollatorWSPort:-9944}" --rpc-port "${CollatorRPCPort:-9933}" \ &> "$LITENTRY_PARACHAIN_DIR/para.alice.log" & + +sleep 10 diff --git a/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs b/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs index 28544ab0d8..e79b7aaf02 100644 --- a/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs +++ b/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs @@ -17,7 +17,7 @@ use super::IMP; use crate::{ command_utils::{get_chain_api, *}, - Cli, CliError, CliResult, CliResultOk, + Cli, CliResult, CliResultOk, }; use base58::FromBase58; use codec::{Decode, Encode}; @@ -33,8 +33,8 @@ use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, pub struct LinkIdentityCommand { /// AccountId in ss58check format account: String, - /// Identity to be created - identity: String, + /// Identity to be created, in did form + did: String, /// Shard identifier shard: String, } @@ -56,16 +56,9 @@ impl LinkIdentityCommand { let who = sr25519_core::Pair::from_string(&self.account, None).unwrap(); chain_api.set_signer(who.clone().into()); - let identity: Result = serde_json::from_str(self.identity.as_str()); - if let Err(e) = identity { - warn!("Deserialize Identity error: {:?}", e.to_string()); - return Err(CliError::Extrinsic { - msg: format!("Deserialize Identity error: {:?}", e.to_string()), - }) - } - + let identity = Identity::from_did(self.did.as_str()).unwrap(); let tee_shielding_key = get_shielding_key(cli).unwrap(); - let encrypted_identity = tee_shielding_key.encrypt(&identity.unwrap().encode()).unwrap(); + let encrypted_identity = tee_shielding_key.encrypt(&identity.encode()).unwrap(); // TODO: the params are incorrect - and need to be reworked too let vdata: Option> = None; diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts index e8c09d3380..a9d3a6d5e0 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts @@ -26,13 +26,26 @@ export default { Github: "IdentityString", Substrate: "Address32", Evm: "Address20", + Bitcoin: "Address33", }, }, Address32: "[u8;32]", Address20: "[u8;20]", + Address33: "[u8;33]", IdentityString: "Vec", Web3Network: { - _enum: ["Polkadot", "Kusama", "Litentry", "Litmus", "LitentryRococo", "Khala", "SubstrateTestnet", "Ethereum", "Bsc"], + _enum: [ + "Polkadot", + "Kusama", + "Litentry", + "Litmus", + "LitentryRococo", + "Khala", + "SubstrateTestnet", + "Ethereum", + "Bsc", + "Bitcoin", + ], }, LitentryValidationData: { _enum: { @@ -58,6 +71,7 @@ export default { _enum: { Substrate: "Web3CommonValidationData", Evm: "Web3CommonValidationData", + Bitcoin: "Web3CommonValidationData", }, }, Web3CommonValidationData: { @@ -67,13 +81,16 @@ export default { LitentryMultiSignature: { _enum: { - Ed25519: "ed25519::Signature", - Sr25519: "sr25519::Signature", - Ecdsa: "ecdsa::Signature", + Ed25519: "Ed25519Signature", + Sr25519: "Sr25519Signature", + Ecdsa: "EcdsaSignature", Ethereum: "EthereumSignature", EthereumPrettified: "EthereumSignature", }, }, + Ed25519Signature: "([u8; 64])", + Sr25519Signature: "([u8; 64])", + EcdsaSignature: "([u8; 65])", EthereumSignature: "([u8; 65])", IdentityGenericEvent: { diff --git a/tee-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs b/tee-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs index 9e39143376..6962f6c164 100644 --- a/tee-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs +++ b/tee-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs @@ -668,8 +668,13 @@ pub mod crypto { sig: &[u8; 65], msg: &[u8; 32], ) -> Result<[u8; 33], EcdsaVerifyError> { - warn!("crypto::secp256k1_ecdsa_recover unimplemented"); - Ok([0; 33]) + let rs = libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] }) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + Ok(pubkey.serialize_compressed()) } } diff --git a/tee-worker/docker/lit-di-bitcoin-identity-test.yml b/tee-worker/docker/lit-di-bitcoin-identity-test.yml new file mode 100644 index 0000000000..8a4b5a2c59 --- /dev/null +++ b/tee-worker/docker/lit-di-bitcoin-identity-test.yml @@ -0,0 +1,24 @@ +services: + lit-di-bitcoin-identity-test: + image: litentry/litentry-cli:latest + container_name: litentry-di-bitcoin-identity-test + volumes: + - ../ts-tests:/ts-tests + - ../client-api:/client-api + - ../cli:/usr/local/worker-cli + build: + context: .. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + litentry-worker-1: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_test.sh test-di-bitcoin-identity 2>&1' " + restart: "no" +networks: + litentry-test-network: + driver: bridge diff --git a/tee-worker/litentry/core/data-providers/src/achainable.rs b/tee-worker/litentry/core/data-providers/src/achainable.rs index 558079aa43..7ee3405117 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable.rs @@ -179,6 +179,7 @@ pub fn web3_network_to_chain(network: &Web3Network) -> String { Web3Network::SubstrateTestnet => "substrate_testnet".into(), Web3Network::Ethereum => "ethereum".into(), Web3Network::Bsc => "bsc".into(), + Web3Network::Bitcoin => "bitcoin".into(), } } diff --git a/tee-worker/litentry/primitives/src/identity.rs b/tee-worker/litentry/primitives/src/identity.rs index 0d4d7fe740..781d107387 100644 --- a/tee-worker/litentry/primitives/src/identity.rs +++ b/tee-worker/litentry/primitives/src/identity.rs @@ -29,7 +29,8 @@ use itp_utils::{ use pallet_evm::{AddressMapping, HashedAddressMapping as GenericHashedAddressMapping}; use parentchain_primitives::{AccountId, Web3Network}; use scale_info::{meta_type, Type, TypeDefSequence, TypeInfo}; -use sp_core::{crypto::AccountId32, ed25519, sr25519, ByteArray, H160}; +use sp_core::{crypto::AccountId32, ecdsa, ed25519, sr25519, ByteArray, H160}; +use sp_io::hashing::blake2_256; use sp_runtime::{ traits::{BlakeTwo256, ConstU32}, BoundedVec, @@ -92,7 +93,6 @@ impl Debug for IdentityString { } #[derive(Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Address20([u8; 20]); impl AsRef<[u8; 20]> for Address20 { @@ -130,7 +130,6 @@ impl Debug for Address20 { } #[derive(Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Address32([u8; 32]); impl AsRef<[u8; 32]> for Address32 { fn as_ref(&self) -> &[u8; 32] { @@ -198,11 +197,72 @@ impl Debug for Address32 { } } +// TODO: maybe use macros to reduce verbosity +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct Address33([u8; 33]); +impl AsRef<[u8; 33]> for Address33 { + fn as_ref(&self) -> &[u8; 33] { + &self.0 + } +} + +impl Default for Address33 { + fn default() -> Self { + Address33([0u8; 33]) + } +} + +impl From<[u8; 33]> for Address33 { + fn from(value: [u8; 33]) -> Self { + Self(value) + } +} + +impl<'a> TryFrom<&'a [u8]> for Address33 { + type Error = (); + fn try_from(x: &'a [u8]) -> Result { + if x.len() == 33 { + let mut data = [0; 33]; + data.copy_from_slice(x); + Ok(Address33(data)) + } else { + Err(()) + } + } +} + +impl From for ecdsa::Public { + fn from(value: Address33) -> Self { + let raw: [u8; 33] = *value.as_ref(); + ecdsa::Public::from_raw(raw) + } +} + +impl From<&Address33> for ecdsa::Public { + fn from(value: &Address33) -> Self { + (*value).into() + } +} + +impl From for Address33 { + fn from(k: ecdsa::Public) -> Self { + k.0.into() + } +} + +impl Debug for Address33 { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + if_production_or!( + f.debug_tuple("Address33").finish(), + f.debug_tuple("Address33").field(&self.0).finish() + ) + } +} + /// Web2 and Web3 Identity based on handle/public key /// We only include the network categories (substrate/evm) without concrete types /// see https://github.com/litentry/litentry-parachain/issues/1841 #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, EnumIter)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Identity { // web2 #[codec(index = 0)] @@ -217,6 +277,12 @@ pub enum Identity { Substrate(Address32), #[codec(index = 4)] Evm(Address20), + // bitcoin addresses are derived (one-way hash) from the pubkey + // by using `Address33` as the Identity handle, it requires that pubkey + // is retrievable by the wallet API when verifying the bitcoin account. + // e.g. unisat-wallet: https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#getpublickey + #[codec(index = 5)] + Bitcoin(Address33), } impl Identity { @@ -225,7 +291,7 @@ impl Identity { } pub fn is_web3(&self) -> bool { - matches!(self, Self::Substrate(..) | Self::Evm(..)) + matches!(self, Self::Substrate(..) | Self::Evm(..) | Self::Bitcoin(..)) } pub fn is_substrate(&self) -> bool { @@ -236,26 +302,27 @@ impl Identity { matches!(self, Self::Evm(..)) } + pub fn is_bitcoin(&self) -> bool { + matches!(self, Self::Bitcoin(..)) + } + // check if the given web3networks match the identity pub fn matches_web3networks(&self, networks: &Vec) -> bool { (self.is_substrate() && !networks.is_empty() && networks.iter().all(|n| n.is_substrate())) || (self.is_evm() && !networks.is_empty() && networks.iter().all(|n| n.is_evm())) + || (self.is_bitcoin() + && !networks.is_empty() + && networks.iter().all(|n| n.is_bitcoin())) || (self.is_web2() && networks.is_empty()) } /// Currently we only support mapping from Address32/Address20 to AccountId, not opposite. pub fn to_account_id(&self) -> Option { match self { - Identity::Substrate(address) => { - let mut data = [0u8; 32]; - data.copy_from_slice(address.as_ref()); - Some(AccountId32::from(data)) - }, - Identity::Evm(address) => { - let substrate_version = - HashedAddressMapping::into_account_id(H160::from_slice(address.as_ref())); - Some(AccountId32::from(Into::<[u8; 32]>::into(substrate_version))) - }, + Identity::Substrate(address) => Some(address.into()), + Identity::Evm(address) => + Some(HashedAddressMapping::into_account_id(H160::from_slice(address.as_ref()))), + Identity::Bitcoin(address) => Some(blake2_256(address.as_ref()).into()), _ => None, } } @@ -281,6 +348,13 @@ impl Identity { .try_into() .map_err(|_| "Address20 conversion error")?; return Ok(Identity::Evm(handle)) + } else if v[0] == "bitcoin" { + let handle = decode_hex(v[1]) + .unwrap() + .as_slice() + .try_into() + .map_err(|_| "Address33 conversion error")?; + return Ok(Identity::Bitcoin(handle)) } else if v[0] == "github" { return Ok(Identity::Github(IdentityString::new(v[1].as_bytes().to_vec()))) } else if v[0] == "discord" { @@ -308,6 +382,8 @@ impl Identity { Identity::Evm(address) => std::format!("evm:{}", &hex_encode(address.as_ref())), Identity::Substrate(address) => std::format!("substrate:{}", &hex_encode(address.as_ref())), + Identity::Bitcoin(address) => + std::format!("bitcoin:{}", &hex_encode(address.as_ref())), Identity::Twitter(handle) => std::format!( "twitter:{}", std::str::from_utf8(handle.inner_ref()) @@ -358,6 +434,12 @@ impl From for Identity { } } +impl From for Identity { + fn from(value: Address33) -> Self { + Identity::Bitcoin(value) + } +} + impl From<[u8; 32]> for Identity { fn from(value: [u8; 32]) -> Self { Identity::Substrate(value.into()) @@ -370,6 +452,12 @@ impl From<[u8; 20]> for Identity { } } +impl From<[u8; 33]> for Identity { + fn from(value: [u8; 33]) -> Self { + Identity::Bitcoin(value.into()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -388,6 +476,7 @@ mod tests { Identity::Github(..) => true, Identity::Substrate(..) => false, Identity::Evm(..) => false, + Identity::Bitcoin(..) => false, } ) }) @@ -404,6 +493,7 @@ mod tests { Identity::Github(..) => false, Identity::Substrate(..) => true, Identity::Evm(..) => true, + Identity::Bitcoin(..) => true, } ) }) @@ -420,6 +510,7 @@ mod tests { Identity::Github(..) => false, Identity::Substrate(..) => true, Identity::Evm(..) => false, + Identity::Bitcoin(..) => false, } ) }) @@ -436,6 +527,24 @@ mod tests { Identity::Github(..) => false, Identity::Substrate(..) => false, Identity::Evm(..) => true, + Identity::Bitcoin(..) => false, + } + ) + }) + } + + #[test] + fn is_bitcoin_works() { + Identity::iter().for_each(|identity| { + assert_eq!( + identity.is_bitcoin(), + match identity { + Identity::Twitter(..) => false, + Identity::Discord(..) => false, + Identity::Github(..) => false, + Identity::Substrate(..) => false, + Identity::Evm(..) => false, + Identity::Bitcoin(..) => true, } ) }) @@ -501,6 +610,14 @@ mod tests { assert_eq!(Identity::from_did(did_str).unwrap(), identity); } + #[test] + fn test_bitcoin_did() { + let identity = Identity::Bitcoin([0; 33].into()); + let did_str = "did:litentry:bitcoin:0x000000000000000000000000000000000000000000000000000000000000000000"; + assert_eq!(identity.to_did().unwrap(), did_str); + assert_eq!(Identity::from_did(did_str).unwrap(), identity); + } + #[test] fn test_discord_did() { let identity = Identity::Discord(IdentityString::new("discord_handle".as_bytes().to_vec())); diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index f3a8f1b3af..508ac2634c 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -55,7 +55,10 @@ pub use parentchain_primitives::{ }; use scale_info::TypeInfo; use sp_core::{ecdsa, ed25519, sr25519, ByteArray}; -use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256}; +use sp_io::{ + crypto::secp256k1_ecdsa_recover, + hashing::{blake2_256, keccak_256}, +}; use sp_runtime::traits::Verify; use std::string::{String, ToString}; pub use teerex_primitives::{decl_rsa_request, ShardIdentifier}; @@ -90,6 +93,7 @@ impl LitentryMultiSignature { self.verify_substrate(substrate_wrap(msg).as_slice(), address) || self.verify_substrate(msg, address), Identity::Evm(address) => self.verify_evm(msg, address), + Identity::Bitcoin(address) => self.verify_bitcoin(msg, address), _ => false, } } @@ -105,11 +109,10 @@ impl LitentryMultiSignature { Err(()) => false, }, (Self::Ecdsa(ref sig), who) => { - let m = sp_io::hashing::blake2_256(msg); + let m = blake2_256(msg); match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { Ok(pubkey) => - &sp_io::hashing::blake2_256(pubkey.as_ref()) - == >::as_ref(who), + &blake2_256(pubkey.as_ref()) == >::as_ref(who), _ => false, } }, @@ -134,6 +137,19 @@ impl LitentryMultiSignature { _ => false, } } + + fn verify_bitcoin(&self, msg: &[u8], signer: &Address33) -> bool { + match self { + Self::Ecdsa(ref sig) => { + let m = blake2_256(msg); + match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { + Ok(pubkey) => pubkey.as_ref() == signer.as_ref(), + _ => false, + } + }, + _ => false, + } + } } fn verify_evm_signature(data: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { diff --git a/tee-worker/litentry/primitives/src/validation_data.rs b/tee-worker/litentry/primitives/src/validation_data.rs index be0da9e31d..aac3427799 100644 --- a/tee-worker/litentry/primitives/src/validation_data.rs +++ b/tee-worker/litentry/primitives/src/validation_data.rs @@ -64,6 +64,8 @@ pub enum Web3ValidationData { Substrate(Web3CommonValidationData), #[codec(index = 1)] Evm(Web3CommonValidationData), + #[codec(index = 2)] + Bitcoin(Web3CommonValidationData), } impl Web3ValidationData { @@ -71,6 +73,7 @@ impl Web3ValidationData { match self { Self::Substrate(data) => &data.message, Self::Evm(data) => &data.message, + Self::Bitcoin(data) => &data.message, } } @@ -78,6 +81,7 @@ impl Web3ValidationData { match self { Self::Substrate(data) => &data.signature, Self::Evm(data) => &data.signature, + Self::Bitcoin(data) => &data.signature, } } } diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index 1bb7e1e20f..6515037758 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -265,6 +265,7 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Identity::Github(_) => "Github", Identity::Substrate(_) => "Substrate", Identity::Evm(_) => "Evm", + Identity::Bitcoin(_) => "Bitcoin", }, RequestType::AssertionVerification(request) => match request.assertion { Assertion::A1 => "A1", diff --git a/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs b/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs index dc461aace3..c4c7a00220 100644 --- a/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs +++ b/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs @@ -330,12 +330,8 @@ where TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, { - debug!("Author submit and watch AesRequest.."); - let hex_encoded_params = params.parse::>().map_err(|e| format!("{:?}", e))?; - - info!("Got request hex: {:?}", &hex_encoded_params[0]); - std::println!("Got request hex: {:?}", &hex_encoded_params[0]); + info!("author_submitAndWatchAesRequest, request hex: {:?}", &hex_encoded_params[0]); let request = AesRequest::from_hex(&hex_encoded_params[0].clone()).map_err(|e| format!("{:?}", e))?; diff --git a/tee-worker/ts-tests/integration-tests/common/common-types.ts b/tee-worker/ts-tests/integration-tests/common/common-types.ts index 67fadfbcf8..b128a2d1a8 100644 --- a/tee-worker/ts-tests/integration-tests/common/common-types.ts +++ b/tee-worker/ts-tests/integration-tests/common/common-types.ts @@ -5,6 +5,7 @@ import { Metadata, TypeRegistry } from '@polkadot/types'; import { Wallet } from 'ethers'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; +import { ECPairInterface } from 'ecpair'; // If there are types already defined in the client-api, please avoid redefining these types. // Instead, make every effort to use the types that have been generated within the client-api. @@ -14,6 +15,9 @@ interface EthersWalletItem { interface SubstrateWalletItem { [key: string]: KeyringPair; } +interface BitcoinWalletItem { + [key: string]: ECPairInterface; +} export type IntegrationTestContext = { tee: WebSocketAsPromised; api: ApiPromise; @@ -21,9 +25,9 @@ export type IntegrationTestContext = { mrEnclave: HexString; ethersWallet: EthersWalletItem; substrateWallet: SubstrateWalletItem; + bitcoinWallet: BitcoinWalletItem; sidechainMetaData: Metadata; sidechainRegistry: TypeRegistry; - web3Signers: Web3Wallets[]; chainIdentifier: number; requestId: number; }; @@ -31,6 +35,7 @@ export type IntegrationTestContext = { export type Web3Wallets = { substrateWallet: KeyringPair; evmWallet: Wallet; + bitcoinWallet: ECPairInterface; }; export type JsonRpcRequest = { diff --git a/tee-worker/ts-tests/integration-tests/common/utils/context.ts b/tee-worker/ts-tests/integration-tests/common/utils/context.ts index b7c190a22f..b6a70dad02 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/context.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/context.ts @@ -2,6 +2,8 @@ import { WsProvider, ApiPromise, TeerexPrimitivesEnclave } from 'parachain-api'; import { Keyring } from '@polkadot/api'; import { cryptoWaitReady } from '@polkadot/util-crypto'; import { ethers } from 'ethers'; +import { ECPairFactory } from 'ecpair'; +import * as ecc from 'tiny-secp256k1'; import WebSocketAsPromised from 'websocket-as-promised'; import WebSocket from 'ws'; import Options from 'websocket-as-promised/types/options'; @@ -32,11 +34,11 @@ export async function initWorkerConnection(endpoint: string): Promise { const provider = new WsProvider(substrateEndpoint); await cryptoWaitReady(); + const ecPair = ECPairFactory(ecc); const ethersWallet = { alice: new ethers.Wallet(getEvmSigner().alice), @@ -48,6 +50,10 @@ export async function initIntegrationTestContext( const substrateWallet = getSubstrateSigner(); + const bitcoinWallet = { + alice: ecPair.makeRandom(), + }; + const types = { ...identity.types, ...vc.types, ...trusted_operations.types, ...sidechain.types }; const api = await ApiPromise.create({ @@ -61,7 +67,6 @@ export async function initIntegrationTestContext( const requestId = 1; const { sidechainMetaData, sidechainRegistry } = await getSidechainMetadata(wsp, api, requestId); - const web3Signers = await generateWeb3Wallets(walletsNumber); const { mrEnclave, teeShieldingKey } = await getEnclave(api); return { tee: wsp, @@ -70,9 +75,9 @@ export async function initIntegrationTestContext( mrEnclave, ethersWallet, substrateWallet, + bitcoinWallet, sidechainMetaData, sidechainRegistry, - web3Signers, chainIdentifier, requestId, }; @@ -114,13 +119,16 @@ export async function generateWeb3Wallets(count: number): Promise const seed = 'litentry seed'; const addresses: Web3Wallets[] = []; const keyring = new Keyring({ type: 'sr25519' }); + const ecPair = ECPairFactory(ecc); for (let i = 0; i < count; i++) { const substratePair = keyring.addFromUri(`${seed}//${i}`); const evmWallet = ethers.Wallet.createRandom(); + const bitcoinPair = ecPair.makeRandom(); addresses.push({ substrateWallet: substratePair, evmWallet: evmWallet, + bitcoinWallet: bitcoinPair, }); } return addresses; diff --git a/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts b/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts index a40fc5d03c..36c199a2dd 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts @@ -1,12 +1,18 @@ import type { HexString } from '@polkadot/util/types'; -import { hexToU8a, stringToU8a } from '@polkadot/util'; +import { bufferToU8a, hexToU8a, stringToU8a, numberToU8a } from '@polkadot/util'; import { KeyObject } from 'crypto'; import { AesOutput } from 'parachain-api'; import crypto from 'crypto'; import { KeyringPair } from '@polkadot/keyring/types'; import { ethers } from 'ethers'; import { blake2AsU8a } from '@polkadot/util-crypto'; -import type { KeypairType } from '@polkadot/util-crypto/types'; +import { ECPairInterface } from 'ecpair'; +import * as ecc from 'tiny-secp256k1'; + +// TODO: `ecdsa` type could actually be used by both substrate and bitcoin +// do we need to differentiate them? +export type KeypairType = 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum'; + export function encryptWithTeeShieldingKey(teeShieldingKey: KeyObject, plaintext: Uint8Array): Buffer { return crypto.publicEncrypt( { @@ -115,3 +121,30 @@ export class EthersSigner implements Signer { return blake2AsU8a(merged, 256); } } + +export class BitcoinSigner implements Signer { + keypair: ECPairInterface; + + constructor(keypair: ECPairInterface) { + this.keypair = keypair; + } + + getAddressRaw(): Uint8Array { + return bufferToU8a(this.keypair.publicKey); + } + + sign(message: HexString | string | Uint8Array): Promise { + const rawSignature = ecc.signRecoverable(blake2AsU8a(message), bufferToU8a(this.keypair.privateKey)); + return new Promise((resolve) => + resolve(bufferToU8a(Buffer.concat([rawSignature.signature, numberToU8a(rawSignature.recoveryId)]))) + ); + } + + type(): KeypairType { + return 'ecdsa'; + } + + getAddressInSubstrateFormat(): Uint8Array { + return blake2AsU8a(this.keypair.publicKey, 256); + } +} diff --git a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts index aec1241df6..02b1b84977 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts @@ -1,15 +1,18 @@ -import { u8aToHex } from '@polkadot/util'; -import { blake2AsHex } from '@polkadot/util-crypto'; +import { numberToU8a, u8aToHex } from '@polkadot/util'; +import { blake2AsHex, blake2AsU8a } from '@polkadot/util-crypto'; import type { IntegrationTestContext } from '../common-types'; import { AesOutput } from 'parachain-api'; import { decryptWithAes, encryptWithTeeShieldingKey, Signer } from './crypto'; import { ethers } from 'ethers'; +import { ECPairInterface } from 'ecpair'; +import * as ecc from 'tiny-secp256k1'; import type { TypeRegistry } from '@polkadot/types'; import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import type { LitentryValidationData, Web3Network } from 'parachain-api'; import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; +import { bufferToU8a } from '@polkadot/util'; // blake2_256( + + ) export function generateVerificationMessage( @@ -163,12 +166,14 @@ export async function buildValidations( signerIdentities: LitentryPrimitivesIdentity[], identities: LitentryPrimitivesIdentity[], startingSidechainNonce: number, - network: 'ethereum' | 'substrate' | 'twitter', + network: 'ethereum' | 'substrate' | 'twitter' | 'bitcoin', substrateSigners?: KeyringPair[] | KeyringPair, - evmSigners?: ethers.Wallet[] + evmSigners?: ethers.Wallet[], + bitcoinSigners?: ECPairInterface[] | ECPairInterface ): Promise { let evmSignature: HexString; let substrateSignature: Uint8Array; + let bitcoinSignature: Uint8Array; const validations: LitentryValidationData[] = []; for (let index = 0; index < identities.length; index++) { @@ -222,6 +227,31 @@ export async function buildValidations( substrateValidationData ) as unknown as LitentryValidationData; validations.push(encodedVerifyIdentityValidation); + } else if (network === 'bitcoin') { + const bitcoinValidationData = { + Web3Validation: { + Bitcoin: { + message: '' as HexString, + signature: { + Ecdsa: '' as HexString, + }, + }, + }, + }; + console.log('post verification msg to bitcoin: ', msg); + bitcoinValidationData.Web3Validation.Bitcoin.message = msg; + const bitcoinSigner = Array.isArray(bitcoinSigners!) ? bitcoinSigners![index] : bitcoinSigners!; + const rawSignature = ecc.signRecoverable(blake2AsU8a(msg, 256), bufferToU8a(bitcoinSigner.privateKey)); + bitcoinSignature = bufferToU8a( + Buffer.concat([rawSignature.signature, numberToU8a(rawSignature.recoveryId)]) + ); + bitcoinValidationData!.Web3Validation.Bitcoin.signature.Ecdsa = u8aToHex(bitcoinSignature); + console.log('bitcoinSignature', u8aToHex(bitcoinSignature)); + const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType( + 'LitentryValidationData', + bitcoinValidationData + ) as unknown as LitentryValidationData; + validations.push(encodedVerifyIdentityValidation); } else if (network === 'twitter') { console.log('post verification msg to twitter: ', msg); const twitterValidationData = { diff --git a/tee-worker/ts-tests/integration-tests/common/utils/integration-setup.ts b/tee-worker/ts-tests/integration-tests/common/utils/integration-setup.ts index afa6e98d1f..38aae874b0 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/integration-setup.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/integration-setup.ts @@ -1,12 +1,12 @@ import { ApiPromise } from 'parachain-api'; import { KeyObject } from 'crypto'; import WebSocketAsPromised from 'websocket-as-promised'; -import type { IntegrationTestContext, Web3Wallets } from '../common-types'; +import type { IntegrationTestContext } from '../common-types'; import type { Metadata, TypeRegistry } from '@polkadot/types'; import type { HexString } from '@polkadot/util/types'; import { initIntegrationTestContext } from './context'; -export function describeLitentry(title: string, walletsNumber: number, cb: (context: IntegrationTestContext) => void) { +export function describeLitentry(title: string, cb: (context: IntegrationTestContext) => void) { describe(title, function () { // Set timeout to 6000 seconds this.timeout(6000000); @@ -18,9 +18,9 @@ export function describeLitentry(title: string, walletsNumber: number, cb: (cont teeShieldingKey: {} as KeyObject, ethersWallet: {}, substrateWallet: {}, + bitcoinWallet: {}, sidechainMetaData: {} as Metadata, sidechainRegistry: {} as TypeRegistry, - web3Signers: [] as Web3Wallets[], // default LitentryRococo chainIdentifier: 42, requestId: 0, @@ -29,20 +29,16 @@ export function describeLitentry(title: string, walletsNumber: number, cb: (cont before('Starting Litentry(parachain&tee)', async function () { //env url - const tmp = await initIntegrationTestContext( - process.env.WORKER_ENDPOINT!, - process.env.NODE_ENDPOINT!, - walletsNumber - ); + const tmp = await initIntegrationTestContext(process.env.WORKER_ENDPOINT!, process.env.NODE_ENDPOINT!); context.mrEnclave = tmp.mrEnclave; context.api = tmp.api; context.tee = tmp.tee; context.teeShieldingKey = tmp.teeShieldingKey; context.ethersWallet = tmp.ethersWallet; context.substrateWallet = tmp.substrateWallet; + context.bitcoinWallet = tmp.bitcoinWallet; context.sidechainMetaData = tmp.sidechainMetaData; context.sidechainRegistry = tmp.sidechainRegistry; - context.web3Signers = tmp.web3Signers; context.chainIdentifier = tmp.chainIdentifier; }); diff --git a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts new file mode 100644 index 0000000000..3aff1d02cc --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts @@ -0,0 +1,359 @@ +import { randomBytes, KeyObject } from 'crypto'; +import { step } from 'mocha-steps'; +import { assert } from 'chai'; +import { u8aToHex, bufferToU8a } from '@polkadot/util'; +import { + buildIdentityFromKeypair, + buildIdentityHelper, + buildValidations, + initIntegrationTestContext, + EthersSigner, + BitcoinSigner, + assertIdGraphMutationResult, + assertIdGraphHash, +} from './common/utils'; +import { assertIsInSidechainBlock, assertIdGraphMutation } from './common/utils/assertion'; +import { + createSignedTrustedCallLinkIdentity, + createSignedTrustedGetterIdGraph, + createSignedTrustedCallDeactivateIdentity, + createSignedTrustedCallActivateIdentity, + decodeIdGraph, + getSidechainNonce, + getTeeShieldingKey, + sendRequestFromGetter, + sendRequestFromTrustedCall, +} from './common/di-utils'; // @fixme move to a better place +import type { IntegrationTestContext } from './common/common-types'; +import { aesKey } from './common/call'; +import { LitentryValidationData, Web3Network } from 'parachain-api'; +import { LitentryPrimitivesIdentity } from 'sidechain-api'; +import { Vec } from '@polkadot/types'; +import { subscribeToEventsWithExtHash } from './common/transactions'; + +describe('Test Identity (bitcoin direct invocation)', function () { + let context: IntegrationTestContext = undefined as any; + let teeShieldingKey: KeyObject = undefined as any; + let aliceBitcoinIdentity: LitentryPrimitivesIdentity = undefined as any; + let aliceEvmIdentity: LitentryPrimitivesIdentity; + + // Alice links: + // - alice's evm identity + const linkIdentityRequestParams: { + nonce: number; + identity: LitentryPrimitivesIdentity; + validation: LitentryValidationData; + networks: Vec; + }[] = []; + this.timeout(6000000); + + before(async () => { + context = await initIntegrationTestContext( + process.env.WORKER_ENDPOINT!, // @fixme evil assertion; centralize env access + process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access + ); + teeShieldingKey = await getTeeShieldingKey(context); + aliceBitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + 'Bitcoin', + context + ); + aliceEvmIdentity = await buildIdentityFromKeypair(new EthersSigner(context.ethersWallet.alice), context); + }); + + step('check idGraph from sidechain storage before linking', async function () { + const idGraphGetter = await createSignedTrustedGetterIdGraph( + context.api, + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity + ); + const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); + const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); + assert.lengthOf(idGraph, 0); + }); + + step('linking identities (alice bitcoin account)', async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + + const aliceNonce = getNextNonce(); + const [aliceEvmValidation] = await buildValidations( + context, + [aliceBitcoinIdentity], + [aliceEvmIdentity], + aliceNonce, + 'ethereum', + undefined, + [context.ethersWallet.alice] + ); + const aliceEvmNetworks = context.api.createType('Vec', [ + 'Ethereum', + 'Bsc', + ]) as unknown as Vec; // @fixme #1878 + linkIdentityRequestParams.push({ + nonce: aliceNonce, + identity: aliceEvmIdentity, + validation: aliceEvmValidation, + networks: aliceEvmNetworks, + }); + + const identityLinkedEvents: any[] = []; + const idGraphHashResults: any[] = []; + let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + [ + [aliceBitcoinIdentity, true], + [aliceEvmIdentity, true], + ], + ]; + + for (const { nonce, identity, validation, networks } of linkIdentityRequestParams) { + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); + const linkIdentityCall = await createSignedTrustedCallLinkIdentity( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity, + identity.toHex(), + validation.toHex(), + networks.toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall); + idGraphHashResults.push( + assertIdGraphMutationResult(context, res, 'LinkIdentityResult', expectedIdGraphs[0]) + ); + expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); + await assertIsInSidechainBlock('linkIdentityCall', res); + + const events = (await eventsPromise).map(({ event }) => event); + events.forEach((event) => { + if (context.api.events.identityManagement.LinkIdentityFailed.is(event)) { + assert.fail(JSON.stringify(event.toHuman(), null, 4)); + } + if (context.api.events.identityManagement.IdentityLinked.is(event)) { + identityLinkedEvents.push(event); + } + }); + } + + await assertIdGraphMutation( + new BitcoinSigner(context.bitcoinWallet.alice), + identityLinkedEvents, + idGraphHashResults, + 1 + ); + }); + + step('check user sidechain storage after linking', async function () { + const idGraphGetter = await createSignedTrustedGetterIdGraph( + context.api, + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity + ); + const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); + + const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); + + // according to the order of linkIdentityRequestParams + const expectedWeb3Networks = [['Ethereum', 'Bsc']]; + let currentIndex = 0; + + for (const { identity } of linkIdentityRequestParams) { + const identityDump = JSON.stringify(identity.toHuman(), null, 4); + console.debug(`checking identity: ${identityDump}`); + const idGraphNode = idGraph.find(([idGraphNodeIdentity]) => idGraphNodeIdentity.eq(identity)); + assert.isDefined(idGraphNode, `identity not found in idGraph: ${identityDump}`); + const [, idGraphNodeContext] = idGraphNode!; + + const web3networks = idGraphNode![1].web3networks.toHuman(); + assert.deepEqual(web3networks, expectedWeb3Networks[currentIndex]); + + assert.equal( + idGraphNodeContext.status.toString(), + 'Active', + `status should be active for identity: ${identityDump}` + ); + console.debug('active ✅'); + + currentIndex++; + } + + await assertIdGraphHash(context, new BitcoinSigner(context.bitcoinWallet.alice), idGraph); + }); + step('deactivating identity(alice bitcoin account)', async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + + const deactivateIdentityRequestParams: { + nonce: number; + identity: LitentryPrimitivesIdentity; + }[] = []; + + const aliceEvmNonce = getNextNonce(); + + deactivateIdentityRequestParams.push({ + nonce: aliceEvmNonce, + identity: aliceEvmIdentity, + }); + + const identityDeactivatedEvents: any[] = []; + const idGraphHashResults: any[] = []; + let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [[[aliceEvmIdentity, false]]]; + + for (const { nonce, identity } of deactivateIdentityRequestParams) { + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); + const deactivateIdentityCall = await createSignedTrustedCallDeactivateIdentity( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity, + identity.toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); + idGraphHashResults.push( + assertIdGraphMutationResult(context, res, 'DeactivateIdentityResult', expectedIdGraphs[0]) + ); + expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); + await assertIsInSidechainBlock('deactivateIdentityCall', res); + + const events = (await eventsPromise).map(({ event }) => event); + events.forEach((event) => { + if (context.api.events.identityManagement.DeactivateIdentityFailed.is(event)) { + assert.fail(JSON.stringify(event.toHuman(), null, 4)); + } + if (context.api.events.identityManagement.IdentityDeactivated.is(event)) { + identityDeactivatedEvents.push(event); + } + }); + } + + await assertIdGraphMutation( + new BitcoinSigner(context.bitcoinWallet.alice), + identityDeactivatedEvents, + idGraphHashResults, + 1 + ); + }); + + step('check idGraph from sidechain storage after deactivating', async function () { + const idGraphGetter = await createSignedTrustedGetterIdGraph( + context.api, + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity + ); + const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); + const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); + + for (const { identity } of linkIdentityRequestParams) { + const identityDump = JSON.stringify(identity.toHuman(), null, 4); + console.debug(`checking identity: ${identityDump}`); + const idGraphNode = idGraph.find(([idGraphNodeIdentity]) => idGraphNodeIdentity.eq(identity)); + assert.isDefined(idGraphNode, `identity not found in idGraph: ${identityDump}`); + const [, idGraphNodeContext] = idGraphNode!; + + assert.equal( + idGraphNodeContext.status.toString(), + 'Inactive', + `status should be Inactive for identity: ${identityDump}` + ); + console.debug('inactive ✅'); + } + + await assertIdGraphHash(context, new BitcoinSigner(context.bitcoinWallet.alice), idGraph); + }); + step('activating identity(alice bitcoin account)', async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + + const activateIdentityRequestParams: { + nonce: number; + identity: LitentryPrimitivesIdentity; + }[] = []; + + const aliceEvmNonce = getNextNonce(); + + activateIdentityRequestParams.push({ + nonce: aliceEvmNonce, + identity: aliceEvmIdentity, + }); + + const identityActivatedEvents: any[] = []; + const idGraphHashResults: any[] = []; + let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [[[aliceEvmIdentity, true]]]; + + for (const { nonce, identity } of activateIdentityRequestParams) { + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); + const activateIdentityCall = await createSignedTrustedCallActivateIdentity( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity, + identity.toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, activateIdentityCall); + idGraphHashResults.push( + assertIdGraphMutationResult(context, res, 'ActivateIdentityResult', expectedIdGraphs[0]) + ); + expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); + await assertIsInSidechainBlock('activateIdentityCall', res); + + const events = (await eventsPromise).map(({ event }) => event); + events.forEach((event) => { + if (context.api.events.identityManagement.ActivateIdentityFailed.is(event)) { + assert.fail(JSON.stringify(event.toHuman(), null, 4)); + } + if (context.api.events.identityManagement.IdentityActivated.is(event)) { + identityActivatedEvents.push(event); + } + }); + } + + await assertIdGraphMutation( + new BitcoinSigner(context.bitcoinWallet.alice), + identityActivatedEvents, + idGraphHashResults, + 1 + ); + }); + + step('check idGraph from sidechain storage after activating', async function () { + const idGraphGetter = await createSignedTrustedGetterIdGraph( + context.api, + new BitcoinSigner(context.bitcoinWallet.alice), + aliceBitcoinIdentity + ); + const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); + const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); + + for (const { identity } of linkIdentityRequestParams) { + const identityDump = JSON.stringify(identity.toHuman(), null, 4); + console.debug(`checking identity: ${identityDump}`); + const idGraphNode = idGraph.find(([idGraphNodeIdentity]) => idGraphNodeIdentity.eq(identity)); + assert.isDefined(idGraphNode, `identity not found in idGraph: ${identityDump}`); + const [, idGraphNodeContext] = idGraphNode!; + + assert.equal( + idGraphNodeContext.status.toString(), + 'Active', + `status should be active for identity: ${identityDump}` + ); + console.debug('active ✅'); + } + + await assertIdGraphHash(context, new BitcoinSigner(context.bitcoinWallet.alice), idGraph); + }); +}); diff --git a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts index b7d2c5cde3..58e18bbd3f 100644 --- a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts @@ -52,8 +52,7 @@ describe('Test Identity (evm direct invocation)', function () { before(async () => { context = await initIntegrationTestContext( process.env.WORKER_ENDPOINT!, // @fixme evil assertion; centralize env access - process.env.NODE_ENDPOINT!, // @fixme evil assertion; centralize env access - 0 + process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access ); teeShieldingKey = await getTeeShieldingKey(context); diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index f685bcb033..2a03f53f68 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -1,7 +1,7 @@ import { randomBytes, KeyObject } from 'crypto'; import { step } from 'mocha-steps'; import { assert } from 'chai'; -import { u8aToHex, u8aToString } from '@polkadot/util'; +import { u8aToHex, u8aToString, bufferToU8a } from '@polkadot/util'; import { assertIdGraphMutationResult, assertIdGraphHash, @@ -43,6 +43,7 @@ describe('Test Identity (direct invocation)', function () { // - a `mock_user` twitter // - alice's evm identity // - eve's substrate identity (as alice can't link her own substrate again) + // - alice's bitcoin identity const linkIdentityRequestParams: { nonce: number; identity: LitentryPrimitivesIdentity; @@ -54,8 +55,7 @@ describe('Test Identity (direct invocation)', function () { before(async () => { context = await initIntegrationTestContext( process.env.WORKER_ENDPOINT!, // @fixme evil assertion; centralize env access - process.env.NODE_ENDPOINT!, // @fixme evil assertion; centralize env access - 0 + process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access ); teeShieldingKey = await getTeeShieldingKey(context); aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); @@ -142,6 +142,31 @@ describe('Test Identity (direct invocation)', function () { networks: eveSubstrateNetworks, }); + const bitcoinNonce = getNextNonce(); + const bitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + 'Bitcoin', + context + ); + console.log('bitcoin id: ', bitcoinIdentity.toHuman()); + const [bitcoinValidation] = await buildValidations( + context, + [aliceSubject], + [bitcoinIdentity], + bitcoinNonce, + 'bitcoin', + undefined, + undefined, + context.bitcoinWallet.alice + ); + const bitcoinNetworks = context.api.createType('Vec', ['Bitcoin']) as unknown as Vec; // @fixme #1878 + linkIdentityRequestParams.push({ + nonce: bitcoinNonce, + identity: bitcoinIdentity, + validation: bitcoinValidation, + networks: bitcoinNetworks, + }); + const identityLinkedEvents: any[] = []; const idGraphHashResults: any[] = []; let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ @@ -151,6 +176,7 @@ describe('Test Identity (direct invocation)', function () { ], [[evmIdentity, true]], [[eveSubstrateIdentity, true]], + [[bitcoinIdentity, true]], ]; for (const { nonce, identity, validation, networks } of linkIdentityRequestParams) { @@ -191,7 +217,7 @@ describe('Test Identity (direct invocation)', function () { new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, idGraphHashResults, - 3 + 4 ); }); @@ -206,7 +232,7 @@ describe('Test Identity (direct invocation)', function () { const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); // according to the order of linkIdentityRequestParams - const expectedWeb3Networks = [[], ['Ethereum', 'Bsc'], ['Polkadot', 'Litentry']]; + const expectedWeb3Networks = [[], ['Ethereum', 'Bsc'], ['Polkadot', 'Litentry'], ['Bitcoin']]; let currentIndex = 0; for (const { identity } of linkIdentityRequestParams) { @@ -432,12 +458,24 @@ describe('Test Identity (direct invocation)', function () { identity: eveSubstrateIdentity, }); + const bitcoinNonce = getNextNonce(); + const bitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + 'Bitcoin', + context + ); + deactivateIdentityRequestParams.push({ + nonce: bitcoinNonce, + identity: bitcoinIdentity, + }); + const identityDeactivatedEvents: any[] = []; const idGraphHashResults: any[] = []; let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ [[twitterIdentity, false]], [[evmIdentity, false]], [[eveSubstrateIdentity, false]], + [[bitcoinIdentity, false]], ]; for (const { nonce, identity } of deactivateIdentityRequestParams) { @@ -475,7 +513,7 @@ describe('Test Identity (direct invocation)', function () { new PolkadotSigner(context.substrateWallet.alice), identityDeactivatedEvents, idGraphHashResults, - 3 + 4 ); }); @@ -541,12 +579,24 @@ describe('Test Identity (direct invocation)', function () { identity: eveSubstrateIdentity, }); + const bitcoinNonce = getNextNonce(); + const bitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + 'Bitcoin', + context + ); + activateIdentityRequestParams.push({ + nonce: bitcoinNonce, + identity: bitcoinIdentity, + }); + const identityActivatedEvents: any[] = []; const idGraphHashResults: any[] = []; let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ [[twitterIdentity, true]], [[evmIdentity, true]], [[eveSubstrateIdentity, true]], + [[bitcoinIdentity, true]], ]; for (const { nonce, identity } of activateIdentityRequestParams) { @@ -584,7 +634,7 @@ describe('Test Identity (direct invocation)', function () { new PolkadotSigner(context.substrateWallet.alice), identityActivatedEvents, idGraphHashResults, - 3 + 4 ); }); diff --git a/tee-worker/ts-tests/integration-tests/di_vc.test.ts b/tee-worker/ts-tests/integration-tests/di_vc.test.ts index 8c61b055ed..3c3aa6304a 100644 --- a/tee-worker/ts-tests/integration-tests/di_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_vc.test.ts @@ -25,8 +25,7 @@ describe('Test Vc (direct invocation)', function () { before(async () => { context = await initIntegrationTestContext( process.env.WORKER_ENDPOINT!, // @fixme evil assertion; centralize env access - process.env.NODE_ENDPOINT!, // @fixme evil assertion; centralize env access - 0 + process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access ); teeShieldingKey = await getTeeShieldingKey(context); aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); @@ -74,7 +73,7 @@ describe('Test Vc (direct invocation)', function () { const nonce = getNextNonce(); const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; console.log(`request vc ${Object.keys(assertion)[0]} for Alice ... Assertion description: ${description}`); - const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); + subscribeToEventsWithExtHash(requestIdentifier, context); const requestVcCall = await createSignedTrustedCallRequestVc( context.api, @@ -87,7 +86,7 @@ describe('Test Vc (direct invocation)', function () { requestIdentifier ); - const res = await sendRequestFromTrustedCall(context, teeShieldingKey, requestVcCall); + await sendRequestFromTrustedCall(context, teeShieldingKey, requestVcCall); // pending test this.skip(); }); diff --git a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts index c39cd08cf0..9bac42ea88 100644 --- a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts @@ -15,7 +15,7 @@ import type { LitentryPrimitivesIdentity } from 'sidechain-api'; import type { LitentryValidationData, Web3Network } from 'parachain-api'; import { Vec } from '@polkadot/types'; -describeLitentry('Test Batch Utility', 0, (context) => { +describeLitentry('Test Batch Utility', (context) => { let identities: LitentryPrimitivesIdentity[] = []; let validations: LitentryValidationData[] = []; let evmSigners: ethers.Wallet[] = []; diff --git a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts index 4cf1c05cc3..a4f7e55af0 100644 --- a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts @@ -51,7 +51,7 @@ async function getNonce(base58mrEnclave: string, workerAddr: string, context: In return nonce; } -describeLitentry('Test Identity', 0, (context) => { +describeLitentry('Test Identity', (context) => { // random wrong msg const wrongMsg = '0x693d9131808e7a8574c7ea5eb7813bdf356223263e61fa8fe2ee8e434508bc75'; let signatureSubstrate; diff --git a/tee-worker/ts-tests/integration-tests/ii_vc.test.ts b/tee-worker/ts-tests/integration-tests/ii_vc.test.ts index 7114565fd6..28263e688b 100644 --- a/tee-worker/ts-tests/integration-tests/ii_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_vc.test.ts @@ -26,7 +26,7 @@ const allAssertions = [ // It doesn't make much difference test A1 only vs test A1 - A11, one VC type is enough. // So only use A1 to trigger the wrong event -describeLitentry('VC ii test', 0, async (context) => { +describeLitentry('VC ii test', async (context) => { const indexList: HexString[] = []; step('Request VC', async () => { // request all vc diff --git a/tee-worker/ts-tests/integration-tests/package.json b/tee-worker/ts-tests/integration-tests/package.json index a4fd1b74c1..d7b7944e20 100644 --- a/tee-worker/ts-tests/integration-tests/package.json +++ b/tee-worker/ts-tests/integration-tests/package.json @@ -11,6 +11,8 @@ "test-di-substrate-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_substrate_identity.test.ts'", "test-di-evm-identity:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_evm_identity.test.ts'", "test-di-evm-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_evm_identity.test.ts'", + "test-di-bitcoin-identity:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_bitcoin_identity.test.ts'", + "test-di-bitcoin-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_bitcoin_identity.test.ts'", "test-di-vc:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_vc.test.ts'", "test-di-vc:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_vc.test.ts'", "test-resuming-worker:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'resuming_worker.test.ts'", @@ -60,9 +62,11 @@ "@typescript-eslint/parser": "^5.60.0", "cross-env": "^7.0.3", "dotenv": "^16.0.3", + "ecpair": "^2.0.1", "eslint": "^8.43.0", "ethers": "^5.7.2", "prettier": "2.8.1", + "tiny-secp256k1": "^2.2.0", "ts-node": "^10.9.1", "typescript": "5.0.4" }, diff --git a/tee-worker/ts-tests/pnpm-lock.yaml b/tee-worker/ts-tests/pnpm-lock.yaml index 53a61d3a2b..67bbfc7e08 100644 --- a/tee-worker/ts-tests/pnpm-lock.yaml +++ b/tee-worker/ts-tests/pnpm-lock.yaml @@ -122,6 +122,9 @@ importers: dotenv: specifier: ^16.0.3 version: 16.3.1 + ecpair: + specifier: ^2.0.1 + version: 2.1.0 eslint: specifier: ^8.43.0 version: 8.50.0 @@ -131,6 +134,9 @@ importers: prettier: specifier: 2.8.1 version: 2.8.1 + tiny-secp256k1: + specifier: ^2.2.0 + version: 2.2.3 ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@20.7.1)(typescript@5.0.4) @@ -1405,6 +1411,12 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} dev: true @@ -1444,6 +1456,20 @@ packages: /browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + /bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + dependencies: + base-x: 3.0.9 + dev: true + + /bs58check@2.1.2: + resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + dependencies: + bs58: 4.0.1 + create-hash: 1.2.0 + safe-buffer: 5.2.1 + dev: true + /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: @@ -1502,6 +1528,13 @@ packages: optionalDependencies: fsevents: 2.3.3 + /cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + /cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: @@ -1535,6 +1568,16 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: true + /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true @@ -1633,6 +1676,15 @@ packages: engines: {node: '>=12'} dev: true + /ecpair@2.1.0: + resolution: {integrity: sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==} + engines: {node: '>=8.0.0'} + dependencies: + randombytes: 2.1.0 + typeforce: 1.18.0 + wif: 2.0.6 + dev: true + /elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} dependencies: @@ -2131,6 +2183,15 @@ packages: function-bind: 1.1.1 dev: false + /hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + dev: true + /hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} dependencies: @@ -2403,6 +2464,14 @@ packages: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true + /md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2668,6 +2737,15 @@ packages: dependencies: safe-buffer: 5.2.1 + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2709,6 +2787,13 @@ packages: glob: 7.2.3 dev: true + /ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: true + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -2772,6 +2857,14 @@ packages: has-property-descriptors: 1.0.0 dev: false + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2847,6 +2940,12 @@ packages: es-abstract: 1.22.2 dev: false + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2873,6 +2972,13 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true + /tiny-secp256k1@2.2.3: + resolution: {integrity: sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==} + engines: {node: '>=14.0.0'} + dependencies: + uint8array-tools: 0.0.7 + dev: true + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2982,6 +3088,10 @@ packages: is-typed-array: 1.1.12 dev: false + /typeforce@1.18.0: + resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==} + dev: true + /typescript@5.0.4: resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} @@ -2996,6 +3106,11 @@ packages: dev: false optional: true + /uint8array-tools@0.0.7: + resolution: {integrity: sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==} + engines: {node: '>=14.0.0'} + dev: true + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -3010,6 +3125,10 @@ packages: dependencies: punycode: 2.3.0 + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -3058,6 +3177,12 @@ packages: isexe: 2.0.0 dev: true + /wif@2.0.6: + resolution: {integrity: sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==} + dependencies: + bs58check: 2.1.2 + dev: true + /wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} dev: false diff --git a/ts-tests/tests/base-filter.test.ts b/ts-tests/tests/base-filter.test.ts index e3bcba7b0b..e5b43f7077 100644 --- a/ts-tests/tests/base-filter.test.ts +++ b/ts-tests/tests/base-filter.test.ts @@ -1,6 +1,5 @@ import { expect } from 'chai'; import { step } from 'mocha-steps'; -import { assert } from 'chai'; import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; describeLitentry('Test Base Filter', ``, (context) => { From 00e803b6e7288d55f4d806e602ca92ce571282c1 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Fri, 15 Dec 2023 12:43:42 +0100 Subject: [PATCH 04/43] Update rococo rpc endpoint (#2333) --- .github/workflows/create-release-draft.yml | 2 +- scripts/fork-parachain-and-launch.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release-draft.yml b/.github/workflows/create-release-draft.yml index a9e621f000..fa619fa504 100644 --- a/.github/workflows/create-release-draft.yml +++ b/.github/workflows/create-release-draft.yml @@ -266,7 +266,7 @@ jobs: chain: [rococo, litmus, litentry] include: - chain: rococo - ref_url: wss://rpc.rococo-parachain-sg.litentry.io + ref_url: wss://rpc.rococo-parachain.litentry.io - chain: litmus ref_url: wss://rpc.litmus-parachain.litentry.io - chain: litentry diff --git a/scripts/fork-parachain-and-launch.sh b/scripts/fork-parachain-and-launch.sh index abe5bc91e4..3fb61b76ba 100755 --- a/scripts/fork-parachain-and-launch.sh +++ b/scripts/fork-parachain-and-launch.sh @@ -52,7 +52,7 @@ FORK_CHAIN=${ORIG_CHAIN}-dev case "$ORIG_CHAIN" in rococo) - ENDPOINT="${2:-wss://rpc.rococo-parachain-sg.litentry.io}" + ENDPOINT="${2:-wss://rpc.rococo-parachain.litentry.io}" ;; litmus) ENDPOINT="${2:-wss://rpc.litmus-parachain.litentry.io}" From 4d5b3e5d9c3be273ec6cb3c14038ae9abe2d9e13 Mon Sep 17 00:00:00 2001 From: Jonathan Alvarez Date: Fri, 15 Dec 2023 10:49:47 -0500 Subject: [PATCH 05/43] chore(cli): request_vc print valid json string (#2330) * chore(cli): request_vc print valid json string Signed-off-by: Jonathan Alvarez * fix(request_vc_direct): print json string Signed-off-by: Jonathan Alvarez --------- Signed-off-by: Jonathan Alvarez --- .../cli/src/trusted_base_cli/commands/litentry/request_vc.rs | 5 ++--- .../trusted_base_cli/commands/litentry/request_vc_direct.rs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index 58cbad30de..702770f344 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -24,7 +24,6 @@ use crate::{ use ita_stf::{trusted_call_result::RequestVCResult, Index, TrustedCall, TrustedCallSigning}; use itp_stf_primitives::types::KeyPair; use itp_utils::hex::decode_hex; -use lc_credentials::Credential; use litentry_primitives::{ aes_decrypt, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, @@ -461,9 +460,9 @@ impl RequestVcCommand { match perform_trusted_operation::(cli, trusted_cli, &top) { Ok(mut vc) => { let decrypted = aes_decrypt(&key, &mut vc.vc_payload).unwrap(); - let credential: Credential = serde_json::from_slice(&decrypted).unwrap(); + let credential_str = String::from_utf8(decrypted).expect("Found invalid UTF-8"); println!("----Generated VC-----"); - println!("{:?}", credential); + println!("{}", credential_str); }, Err(e) => { println!("{:?}", e); diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs index 0d6449053a..4b7eacfb3d 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs @@ -25,7 +25,6 @@ use crate::{ use ita_stf::{trusted_call_result::RequestVCResult, Index, TrustedCall, TrustedCallSigning}; use itp_stf_primitives::types::KeyPair; use itp_utils::hex::decode_hex; -use lc_credentials::Credential; use litentry_primitives::{ aes_decrypt, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, @@ -272,9 +271,9 @@ impl RequestVcDirectCommand { match perform_direct_operation::(cli, trusted_cli, &top, key) { Ok(mut vc) => { let decrypted = aes_decrypt(&key, &mut vc.vc_payload).unwrap(); - let credential: Credential = serde_json::from_slice(&decrypted).unwrap(); + let credential_str = String::from_utf8(decrypted).expect("Found invalid UTF-8"); println!("----Generated VC-----"); - println!("{:?}", credential); + println!("{}", credential_str); }, Err(e) => { println!("{:?}", e); From c852d5c36e5c05fbbda6d95a0a6a76ff11f7bf1d Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Sun, 17 Dec 2023 14:37:50 +0100 Subject: [PATCH 06/43] Use bitcoin crate for signature verification (#2336) * use bitcoin crate * adjust tests * fix ts-test --- tee-worker/Cargo.lock | 105 +++++++++- .../interfaces/identity/definitions.ts | 2 + tee-worker/enclave-runtime/Cargo.lock | 88 ++++++++- tee-worker/litentry/primitives/Cargo.toml | 10 +- .../primitives/src/bitcoin_signature.rs | 72 +++++++ tee-worker/litentry/primitives/src/lib.rs | 59 +++++- .../integration-tests/common/common-types.ts | 6 +- .../integration-tests/common/di-utils.ts | 33 +++- .../integration-tests/common/utils/context.ts | 10 +- .../integration-tests/common/utils/crypto.ts | 31 +-- .../common/utils/identity-helper.ts | 26 +-- .../di_bitcoin_identity.test.ts | 2 +- .../di_substrate_identity.test.ts | 6 +- .../ts-tests/integration-tests/package.json | 16 +- tee-worker/ts-tests/pnpm-lock.yaml | 185 +++++++----------- 15 files changed, 456 insertions(+), 195 deletions(-) create mode 100644 tee-worker/litentry/primitives/src/bitcoin_signature.rs diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 508e2b5845..9b5a7a3349 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -580,9 +580,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -590,6 +590,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + [[package]] name = "beef" version = "0.5.2" @@ -643,6 +649,38 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitcoin" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5973a027b341b462105675962214dfe3c938ad9afd395d84b28602608bdcec7b" +dependencies = [ + "bech32", + "bitcoin-internals", + "bitcoin_hashes", + "core2 0.3.3", + "hex-conservative", + "hex_lit", + "secp256k1 0.28.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "core2 0.3.3", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1051,7 +1089,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ed9c8b2d17acb8110c46f1da5bf4a696d745e1474a16db0cd2b49cd0249bf2" dependencies = [ - "core2", + "core2 0.4.0", "multibase", "multihash 0.16.3", "serde 1.0.193", @@ -1278,6 +1316,15 @@ dependencies = [ "strum_macros 0.25.3", ] +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr 2.6.3", +] + [[package]] name = "core2" version = "0.4.0" @@ -3882,12 +3929,27 @@ dependencies = [ "serde 1.0.193", ] +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +dependencies = [ + "core2 0.3.3", +] + [[package]] name = "hex-literal" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "hkdf" version = "0.12.3" @@ -7010,6 +7072,9 @@ dependencies = [ name = "litentry-primitives" version = "0.1.0" dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3)", + "base64 0.13.1", + "bitcoin", "core-primitives", "hex 0.4.3", "itp-sgx-crypto", @@ -7021,6 +7086,7 @@ dependencies = [ "rand 0.7.3 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", "ring 0.16.20", "scale-info", + "secp256k1 0.28.0", "serde 1.0.193", "sgx_tstd", "sp-core", @@ -7628,7 +7694,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "blake3", - "core2", + "core2 0.4.0", "digest 0.10.7", "multihash-derive 0.8.0", "sha2 0.10.7", @@ -7642,7 +7708,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" dependencies = [ - "core2", + "core2 0.4.0", "multihash-derive 0.8.0", "unsigned-varint 0.7.1", ] @@ -10827,7 +10893,7 @@ version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "bytes 1.4.0", "encoding_rs", "futures-core 0.3.28", @@ -11403,7 +11469,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", ] [[package]] @@ -12564,7 +12630,17 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys 0.9.1", ] [[package]] @@ -12576,6 +12652,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -13415,7 +13500,7 @@ dependencies = [ "regex 1.9.5", "scale-info", "schnorrkel", - "secp256k1", + "secp256k1 0.24.3", "secrecy", "serde 1.0.193", "sp-core-hashing 5.0.0", @@ -13541,7 +13626,7 @@ dependencies = [ "log 0.4.20", "parity-scale-codec", "rustversion", - "secp256k1", + "secp256k1 0.24.3", "sp-core", "sp-externalities", "sp-keystore", diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts index a9d3a6d5e0..30536b32d2 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts @@ -86,12 +86,14 @@ export default { Ecdsa: "EcdsaSignature", Ethereum: "EthereumSignature", EthereumPrettified: "EthereumSignature", + Bitcoin: "BitcoinSignature", }, }, Ed25519Signature: "([u8; 64])", Sr25519Signature: "([u8; 64])", EcdsaSignature: "([u8; 65])", EthereumSignature: "([u8; 65])", + BitcoinSignature: "([u8; 65])", IdentityGenericEvent: { who: "AccountId", diff --git a/tee-worker/enclave-runtime/Cargo.lock b/tee-worker/enclave-runtime/Cargo.lock index 93d7440815..7273cea73d 100644 --- a/tee-worker/enclave-runtime/Cargo.lock +++ b/tee-worker/enclave-runtime/Cargo.lock @@ -257,6 +257,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + [[package]] name = "binary-merkle-tree" version = "4.0.0-dev" @@ -271,6 +277,38 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitcoin" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5973a027b341b462105675962214dfe3c938ad9afd395d84b28602608bdcec7b" +dependencies = [ + "bech32", + "bitcoin-internals", + "bitcoin_hashes", + "core2", + "hex-conservative", + "hex_lit", + "secp256k1 0.28.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "core2", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -581,6 +619,15 @@ dependencies = [ "strum_macros", ] +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr 2.6.3", +] + [[package]] name = "cpufeatures" version = "0.2.9" @@ -1532,12 +1579,27 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +dependencies = [ + "core2", +] + [[package]] name = "hex-literal" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "hmac" version = "0.12.1" @@ -3038,7 +3100,9 @@ dependencies = [ name = "litentry-primitives" version = "0.1.0" dependencies = [ + "bitcoin", "core-primitives", + "hex 0.4.3", "itp-sgx-crypto", "itp-utils", "log", @@ -3047,6 +3111,7 @@ dependencies = [ "rand 0.7.3", "ring 0.16.20", "scale-info", + "secp256k1 0.28.0", "serde 1.0.188", "sgx_tstd", "sp-core", @@ -4024,7 +4089,17 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys 0.9.1", ] [[package]] @@ -4036,6 +4111,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -4537,7 +4621,7 @@ dependencies = [ "primitive-types", "scale-info", "schnorrkel", - "secp256k1", + "secp256k1 0.24.3", "secrecy", "sp-core-hashing", "sp-debug-derive", diff --git a/tee-worker/litentry/primitives/Cargo.toml b/tee-worker/litentry/primitives/Cargo.toml index 421dd12823..2ad014ae67 100644 --- a/tee-worker/litentry/primitives/Cargo.toml +++ b/tee-worker/litentry/primitives/Cargo.toml @@ -5,14 +5,16 @@ name = "litentry-primitives" version = "0.1.0" [dependencies] +bitcoin = { version = "0.31.0", default-features = false, features = ["secp-recovery", "no-std"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -hex = { version = "0.4.3", default-features = false, optional = true } +hex = { version = "0.4.3", default-features = false } log = { version = "0.4", default-features = false } pallet-evm = { default-features = false, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } rand = { version = "0.7", optional = true } rand-sgx = { package = "rand", git = "https://github.com/mesalock-linux/rand-sgx", tag = "sgx_1.1.3", features = ["sgx_tstd"], optional = true } ring = { version = "0.16.20", default-features = false } scale-info = { version = "2.4.0", default-features = false, features = ["derive"] } +secp256k1 = { version = "0.28.0", default-features = false } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } @@ -22,6 +24,7 @@ strum = { version = "0.25.0", default-features = false } strum_macros = { version = "0.25.0", default-features = false } # sgx dependencies +base64_sgx = { package = "base64", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base64-sgx", optional = true } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master", optional = true, features = ["net", "thread"] } # internal dependencies @@ -30,6 +33,9 @@ itp-utils = { path = "../../core-primitives/utils", default-features = false } parentchain-primitives = { package = "core-primitives", path = "../../../primitives/core", default-features = false } teerex-primitives = { path = "../../../primitives/teerex", default-features = false } +[dev-dependencies] +base64 = { version = "0.13", features = ["alloc"] } + [features] default = ["std"] production = [] @@ -53,4 +59,6 @@ std = [ "teerex-primitives/std", "rand", "log/std", + "bitcoin/std", + "secp256k1/std", ] diff --git a/tee-worker/litentry/primitives/src/bitcoin_signature.rs b/tee-worker/litentry/primitives/src/bitcoin_signature.rs new file mode 100644 index 0000000000..cb6db71a23 --- /dev/null +++ b/tee-worker/litentry/primitives/src/bitcoin_signature.rs @@ -0,0 +1,72 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct BitcoinSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for BitcoinSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(BitcoinSignature(inner)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "std")] +impl Serialize for BitcoinSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for BitcoinSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + BitcoinSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for BitcoinSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for BitcoinSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index 508ac2634c..5bd2fcf0c8 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -25,17 +25,20 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam mod aes; mod aes_request; +mod bitcoin_signature; mod ethereum_signature; mod identity; mod validation_data; pub use aes::*; pub use aes_request::*; +pub use bitcoin_signature::*; pub use ethereum_signature::*; pub use identity::*; use sp_std::{boxed::Box, fmt::Debug, vec::Vec}; pub use validation_data::*; +use bitcoin::sign_message::{signed_msg_hash, MessageSignature}; use codec::{Decode, Encode, MaxEncodedLen}; use itp_sgx_crypto::ShieldingCryptoDecrypt; use itp_utils::hex::hex_encode; @@ -84,6 +87,9 @@ pub enum LitentryMultiSignature { /// Same as the above, but the payload bytes are hex-encoded and prepended with a readable prefix #[codec(index = 4)] EthereumPrettified(EthereumSignature), + /// Bitcoin signed message + #[codec(index = 5)] + Bitcoin(BitcoinSignature), } impl LitentryMultiSignature { @@ -140,19 +146,13 @@ impl LitentryMultiSignature { fn verify_bitcoin(&self, msg: &[u8], signer: &Address33) -> bool { match self { - Self::Ecdsa(ref sig) => { - let m = blake2_256(msg); - match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { - Ok(pubkey) => pubkey.as_ref() == signer.as_ref(), - _ => false, - } - }, + Self::Bitcoin(ref sig) => verify_bitcoin_signature(msg, sig, signer), _ => false, } } } -fn verify_evm_signature(data: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { +pub fn verify_evm_signature(data: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { let digest = keccak_256(data); return match recover_evm_address(&digest, sig.as_ref()) { Ok(recovered_evm_address) => recovered_evm_address == who.as_ref().as_slice(), @@ -163,6 +163,22 @@ fn verify_evm_signature(data: &[u8], sig: &EthereumSignature, who: &Address20) - } } +pub fn verify_bitcoin_signature(msg: &[u8], sig: &BitcoinSignature, who: &Address33) -> bool { + if let Ok(msg_sig) = MessageSignature::from_slice(sig.as_ref()) { + let msg_hash = signed_msg_hash(hex::encode(msg).as_str()); + let secp = secp256k1::Secp256k1::new(); + return match msg_sig.recover_pubkey(&secp, msg_hash) { + Ok(recovered_pub_key) => &recovered_pub_key.inner.serialize() == who.as_ref(), + Err(_) => { + error!("Could not verify bitcoin signature msg: {:?}, signer {:?}", msg, who); + false + }, + } + } + + false +} + impl From for LitentryMultiSignature { fn from(x: ed25519::Signature) -> Self { Self::Ed25519(x) @@ -225,3 +241,30 @@ pub struct BroadcastedRequest { pub payload: String, pub rpc_method: String, } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn verify_bitcoin_signature_works() { + // generated by unisat-wallet API: https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet + let msg: Vec = vec![ + 3, 93, 250, 112, 216, 101, 89, 57, 83, 88, 100, 252, 203, 15, 64, 127, 138, 37, 2, 40, + 147, 95, 245, 27, 97, 202, 62, 205, 151, 0, 175, 177, + ]; + let pubkey: Vec = vec![ + 3, 93, 250, 112, 216, 101, 89, 57, 83, 88, 100, 252, 203, 15, 64, 127, 138, 37, 2, 40, + 147, 95, 245, 27, 97, 202, 62, 205, 151, 0, 175, 177, 216, + ]; + let sig: Vec = base64::decode("G2LhyYzWT2o8UoBsuhJsqFgwm3tlE0cW4aseCXKqVuNATk6K/uEHlPzDFmtlMADywDHl5vLCWcNpwmQLD7n/yvc=").unwrap(); + + let pubkey_ref: &[u8] = pubkey.as_ref(); + let sig_ref: &[u8] = sig.as_ref(); + assert!(verify_bitcoin_signature( + &msg, + &sig_ref.try_into().unwrap(), + &pubkey_ref.try_into().unwrap() + )); + } +} diff --git a/tee-worker/ts-tests/integration-tests/common/common-types.ts b/tee-worker/ts-tests/integration-tests/common/common-types.ts index b128a2d1a8..84fa7a930e 100644 --- a/tee-worker/ts-tests/integration-tests/common/common-types.ts +++ b/tee-worker/ts-tests/integration-tests/common/common-types.ts @@ -5,7 +5,7 @@ import { Metadata, TypeRegistry } from '@polkadot/types'; import { Wallet } from 'ethers'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; -import { ECPairInterface } from 'ecpair'; +import bitcore from 'bitcore-lib'; // If there are types already defined in the client-api, please avoid redefining these types. // Instead, make every effort to use the types that have been generated within the client-api. @@ -16,7 +16,7 @@ interface SubstrateWalletItem { [key: string]: KeyringPair; } interface BitcoinWalletItem { - [key: string]: ECPairInterface; + [key: string]: bitcore.PrivateKey; } export type IntegrationTestContext = { tee: WebSocketAsPromised; @@ -35,7 +35,7 @@ export type IntegrationTestContext = { export type Web3Wallets = { substrateWallet: KeyringPair; evmWallet: Wallet; - bitcoinWallet: ECPairInterface; + bitcoinWallet: bitcore.PrivateKey; }; export type JsonRpcRequest = { diff --git a/tee-worker/ts-tests/integration-tests/common/di-utils.ts b/tee-worker/ts-tests/integration-tests/common/di-utils.ts index 4d786c75e0..1f4185498f 100644 --- a/tee-worker/ts-tests/integration-tests/common/di-utils.ts +++ b/tee-worker/ts-tests/integration-tests/common/di-utils.ts @@ -94,9 +94,21 @@ export const createSignedTrustedCall = async ( if (withWrappedBytes) { payload = u8aConcat(stringToU8a(''), payload, stringToU8a('')); } - const signature = parachainApi.createType('LitentryMultiSignature', { - [signer.type()]: u8aToHex(await signer.sign(payload)), - }); + + let signature; + + // for bitcoin signature, we expect a hex-encoded `string` without `0x` prefix + // TODO: any better idiomatic way? + if (signer.type() === 'bitcoin') { + const payloadStr = u8aToHex(payload).substring(2); + signature = parachainApi.createType('LitentryMultiSignature', { + [signer.type()]: u8aToHex(await signer.sign(payloadStr)), + }); + } else { + signature = parachainApi.createType('LitentryMultiSignature', { + [signer.type()]: u8aToHex(await signer.sign(payload)), + }); + } return parachainApi.createType('TrustedCallSigned', { call: call, index: nonce, @@ -115,9 +127,18 @@ export const createSignedTrustedGetter = async ( [variant]: parachainApi.createType(argType, params), }); const payload = getter.toU8a(); - const signature = parachainApi.createType('LitentryMultiSignature', { - [signer.type()]: u8aToHex(await signer.sign(payload)), - }); + + let signature; + if (signer.type() === 'bitcoin') { + const payloadStr = u8aToHex(payload).substring(2); + signature = parachainApi.createType('LitentryMultiSignature', { + [signer.type()]: u8aToHex(await signer.sign(payloadStr)), + }); + } else { + signature = parachainApi.createType('LitentryMultiSignature', { + [signer.type()]: u8aToHex(await signer.sign(payload)), + }); + } return parachainApi.createType('TrustedGetterSigned', { getter: getter, signature: signature, diff --git a/tee-worker/ts-tests/integration-tests/common/utils/context.ts b/tee-worker/ts-tests/integration-tests/common/utils/context.ts index b6a70dad02..529b3ff6aa 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/context.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/context.ts @@ -2,8 +2,6 @@ import { WsProvider, ApiPromise, TeerexPrimitivesEnclave } from 'parachain-api'; import { Keyring } from '@polkadot/api'; import { cryptoWaitReady } from '@polkadot/util-crypto'; import { ethers } from 'ethers'; -import { ECPairFactory } from 'ecpair'; -import * as ecc from 'tiny-secp256k1'; import WebSocketAsPromised from 'websocket-as-promised'; import WebSocket from 'ws'; import Options from 'websocket-as-promised/types/options'; @@ -11,10 +9,10 @@ import { KeyObject } from 'crypto'; import { getSidechainMetadata } from '../call'; import { getEvmSigner, getSubstrateSigner } from '../helpers'; import type { IntegrationTestContext, Web3Wallets } from '../common-types'; - import { identity, vc, trusted_operations, sidechain } from 'parachain-api'; import crypto from 'crypto'; import type { HexString } from '@polkadot/util/types'; +import bitcore from 'bitcore-lib'; // maximum block number that we wait in listening events before we timeout export const defaultListenTimeoutInBlockNumber = 15; @@ -38,7 +36,6 @@ export async function initIntegrationTestContext( ): Promise { const provider = new WsProvider(substrateEndpoint); await cryptoWaitReady(); - const ecPair = ECPairFactory(ecc); const ethersWallet = { alice: new ethers.Wallet(getEvmSigner().alice), @@ -51,7 +48,7 @@ export async function initIntegrationTestContext( const substrateWallet = getSubstrateSigner(); const bitcoinWallet = { - alice: ecPair.makeRandom(), + alice: new bitcore.PrivateKey(), }; const types = { ...identity.types, ...vc.types, ...trusted_operations.types, ...sidechain.types }; @@ -119,12 +116,11 @@ export async function generateWeb3Wallets(count: number): Promise const seed = 'litentry seed'; const addresses: Web3Wallets[] = []; const keyring = new Keyring({ type: 'sr25519' }); - const ecPair = ECPairFactory(ecc); for (let i = 0; i < count; i++) { const substratePair = keyring.addFromUri(`${seed}//${i}`); const evmWallet = ethers.Wallet.createRandom(); - const bitcoinPair = ecPair.makeRandom(); + const bitcoinPair = new bitcore.PrivateKey(); addresses.push({ substrateWallet: substratePair, evmWallet: evmWallet, diff --git a/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts b/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts index 36c199a2dd..129a4a0dbc 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts @@ -1,17 +1,14 @@ import type { HexString } from '@polkadot/util/types'; -import { bufferToU8a, hexToU8a, stringToU8a, numberToU8a } from '@polkadot/util'; +import { bufferToU8a, hexToU8a, isString, stringToU8a } from '@polkadot/util'; import { KeyObject } from 'crypto'; import { AesOutput } from 'parachain-api'; import crypto from 'crypto'; import { KeyringPair } from '@polkadot/keyring/types'; import { ethers } from 'ethers'; import { blake2AsU8a } from '@polkadot/util-crypto'; -import { ECPairInterface } from 'ecpair'; -import * as ecc from 'tiny-secp256k1'; +import bitcore from 'bitcore-lib'; -// TODO: `ecdsa` type could actually be used by both substrate and bitcoin -// do we need to differentiate them? -export type KeypairType = 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum'; +export type KeypairType = 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum' | 'bitcoin'; export function encryptWithTeeShieldingKey(teeShieldingKey: KeyObject, plaintext: Uint8Array): Buffer { return crypto.publicEncrypt( @@ -123,28 +120,32 @@ export class EthersSigner implements Signer { } export class BitcoinSigner implements Signer { - keypair: ECPairInterface; + keypair: bitcore.PrivateKey; - constructor(keypair: ECPairInterface) { + constructor(keypair: bitcore.PrivateKey) { this.keypair = keypair; } getAddressRaw(): Uint8Array { - return bufferToU8a(this.keypair.publicKey); + return bufferToU8a(this.keypair.toPublicKey().toBuffer()); } sign(message: HexString | string | Uint8Array): Promise { - const rawSignature = ecc.signRecoverable(blake2AsU8a(message), bufferToU8a(this.keypair.privateKey)); - return new Promise((resolve) => - resolve(bufferToU8a(Buffer.concat([rawSignature.signature, numberToU8a(rawSignature.recoveryId)]))) - ); + return new Promise((resolve, reject) => { + if (isString(message)) { + const sig = new bitcore.Message(message).sign(this.keypair); + resolve(bufferToU8a(Buffer.from(sig, 'base64'))); + } else { + reject('wrong message type'); + } + }); } type(): KeypairType { - return 'ecdsa'; + return 'bitcoin'; } getAddressInSubstrateFormat(): Uint8Array { - return blake2AsU8a(this.keypair.publicKey, 256); + return blake2AsU8a(this.getAddressRaw(), 256); } } diff --git a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts index 02b1b84977..247f0d8812 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts @@ -1,11 +1,9 @@ -import { numberToU8a, u8aToHex } from '@polkadot/util'; -import { blake2AsHex, blake2AsU8a } from '@polkadot/util-crypto'; +import { u8aToHex } from '@polkadot/util'; +import { blake2AsHex } from '@polkadot/util-crypto'; import type { IntegrationTestContext } from '../common-types'; import { AesOutput } from 'parachain-api'; import { decryptWithAes, encryptWithTeeShieldingKey, Signer } from './crypto'; import { ethers } from 'ethers'; -import { ECPairInterface } from 'ecpair'; -import * as ecc from 'tiny-secp256k1'; import type { TypeRegistry } from '@polkadot/types'; import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import type { LitentryValidationData, Web3Network } from 'parachain-api'; @@ -13,6 +11,7 @@ import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; import { bufferToU8a } from '@polkadot/util'; +import bitcore from 'bitcore-lib'; // blake2_256( + + ) export function generateVerificationMessage( @@ -56,6 +55,8 @@ export async function buildIdentityFromKeypair( return 'Substrate'; case 'ecdsa': return 'Substrate'; + case 'bitcoin': + return 'Bitcoin'; default: return 'Substrate'; } @@ -169,7 +170,7 @@ export async function buildValidations( network: 'ethereum' | 'substrate' | 'twitter' | 'bitcoin', substrateSigners?: KeyringPair[] | KeyringPair, evmSigners?: ethers.Wallet[], - bitcoinSigners?: ECPairInterface[] | ECPairInterface + bitcoinSigners?: bitcore.PrivateKey[] | bitcore.PrivateKey ): Promise { let evmSignature: HexString; let substrateSignature: Uint8Array; @@ -233,7 +234,7 @@ export async function buildValidations( Bitcoin: { message: '' as HexString, signature: { - Ecdsa: '' as HexString, + Bitcoin: '' as HexString, }, }, }, @@ -241,12 +242,13 @@ export async function buildValidations( console.log('post verification msg to bitcoin: ', msg); bitcoinValidationData.Web3Validation.Bitcoin.message = msg; const bitcoinSigner = Array.isArray(bitcoinSigners!) ? bitcoinSigners![index] : bitcoinSigners!; - const rawSignature = ecc.signRecoverable(blake2AsU8a(msg, 256), bufferToU8a(bitcoinSigner.privateKey)); - bitcoinSignature = bufferToU8a( - Buffer.concat([rawSignature.signature, numberToU8a(rawSignature.recoveryId)]) - ); - bitcoinValidationData!.Web3Validation.Bitcoin.signature.Ecdsa = u8aToHex(bitcoinSignature); - console.log('bitcoinSignature', u8aToHex(bitcoinSignature)); + // we need to sign the hex string without `0x` prefix, the signature is base64-encoded string + const sig = new bitcore.Message(msg.substring(2)).sign(bitcoinSigner); + bitcoinSignature = bufferToU8a(Buffer.from(sig, 'base64')); + bitcoinValidationData!.Web3Validation.Bitcoin.signature.Bitcoin = u8aToHex(bitcoinSignature); + console.log('bitcoin pubkey: ', u8aToHex(bufferToU8a(bitcoinSigner.toPublicKey().toBuffer()))); + console.log('bitcoin sig (base64): ', sig); + console.log('bitcoin sig (hex): ', u8aToHex(bitcoinSignature)); const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType( 'LitentryValidationData', bitcoinValidationData diff --git a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts index 3aff1d02cc..f6530ee4d3 100644 --- a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts @@ -54,7 +54,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { ); teeShieldingKey = await getTeeShieldingKey(context); aliceBitcoinIdentity = await buildIdentityHelper( - u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())), 'Bitcoin', context ); diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index 2a03f53f68..d3956e67b2 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -144,7 +144,7 @@ describe('Test Identity (direct invocation)', function () { const bitcoinNonce = getNextNonce(); const bitcoinIdentity = await buildIdentityHelper( - u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())), 'Bitcoin', context ); @@ -460,7 +460,7 @@ describe('Test Identity (direct invocation)', function () { const bitcoinNonce = getNextNonce(); const bitcoinIdentity = await buildIdentityHelper( - u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())), 'Bitcoin', context ); @@ -581,7 +581,7 @@ describe('Test Identity (direct invocation)', function () { const bitcoinNonce = getNextNonce(); const bitcoinIdentity = await buildIdentityHelper( - u8aToHex(bufferToU8a(context.bitcoinWallet.alice.publicKey)), + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())), 'Bitcoin', context ); diff --git a/tee-worker/ts-tests/integration-tests/package.json b/tee-worker/ts-tests/integration-tests/package.json index d7b7944e20..40ecbaaf8f 100644 --- a/tee-worker/ts-tests/integration-tests/package.json +++ b/tee-worker/ts-tests/integration-tests/package.json @@ -26,34 +26,36 @@ "@noble/ed25519": "^1.7.3", "@polkadot/api": "^10.9.1", "@polkadot/api-augment": "^10.9.1", - "@polkadot/api-derive": "^10.9.1", "@polkadot/api-base": "^10.9.1", + "@polkadot/api-derive": "^10.9.1", "@polkadot/keyring": "^12.2.1", + "@polkadot/rpc-core": "^10.9.1", "@polkadot/types": "^10.9.1", "@polkadot/types-augment": "^10.9.1", + "@polkadot/types-codec": "^10.9.1", "@polkadot/types-create": "^10.9.1", "@polkadot/types-known": "^10.9.1", "@polkadot/types-support": "^10.9.1", "@polkadot/util": "^12.5.1", "@polkadot/util-crypto": "^12.5.1", - "@polkadot/types-codec": "^10.9.1", - "@polkadot/rpc-core": "^10.9.1", "add": "^2.0.6", "ajv": "^8.12.0", + "bitcore-lib": "^10.0.21", "chai": "^4.3.6", "colors": "^1.4.0", "js-base64": "^3.7.5", "micro-base58": "^0.5.1", "mocha": "^10.1.0", "mocha-steps": "^1.3.0", + "parachain-api": "file:../../client-api/parachain-api", "scale-ts": "^0.2.11", + "sidechain-api": "file:../../client-api/sidechain-api", "websocket-as-promised": "^2.0.1", - "ws": "^8.8.1", - "parachain-api": "file:../../client-api/parachain-api", - "sidechain-api": "file:../../client-api/sidechain-api" + "ws": "^8.8.1" }, "devDependencies": { "@ethersproject/providers": "^5.7.2", + "@types/bitcore-lib": "^0.15.1", "@types/chai": "^4.3.3", "@types/mocha": "^10.0.0", "@types/node": "^20.4.4", @@ -62,11 +64,9 @@ "@typescript-eslint/parser": "^5.60.0", "cross-env": "^7.0.3", "dotenv": "^16.0.3", - "ecpair": "^2.0.1", "eslint": "^8.43.0", "ethers": "^5.7.2", "prettier": "2.8.1", - "tiny-secp256k1": "^2.2.0", "ts-node": "^10.9.1", "typescript": "5.0.4" }, diff --git a/tee-worker/ts-tests/pnpm-lock.yaml b/tee-worker/ts-tests/pnpm-lock.yaml index 67bbfc7e08..f6605b0ca5 100644 --- a/tee-worker/ts-tests/pnpm-lock.yaml +++ b/tee-worker/ts-tests/pnpm-lock.yaml @@ -61,6 +61,9 @@ importers: ajv: specifier: ^8.12.0 version: 8.12.0 + bitcore-lib: + specifier: ^10.0.21 + version: 10.0.21 chai: specifier: ^4.3.6 version: 4.3.10 @@ -98,6 +101,9 @@ importers: '@ethersproject/providers': specifier: ^5.7.2 version: 5.7.2 + '@types/bitcore-lib': + specifier: ^0.15.1 + version: 0.15.6 '@types/chai': specifier: ^4.3.3 version: 4.3.6 @@ -122,9 +128,6 @@ importers: dotenv: specifier: ^16.0.3 version: 16.3.1 - ecpair: - specifier: ^2.0.1 - version: 2.1.0 eslint: specifier: ^8.43.0 version: 8.50.0 @@ -134,9 +137,6 @@ importers: prettier: specifier: 2.8.1 version: 2.8.1 - tiny-secp256k1: - specifier: ^2.2.0 - version: 2.2.3 ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@20.7.1)(typescript@5.0.4) @@ -1141,6 +1141,12 @@ packages: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} dev: true + /@types/bitcore-lib@0.15.6: + resolution: {integrity: sha512-CtKDBgSBubPXZ0wFeCiUCSdzH+cuy6nFya3FboOqf44evi+OmkQPqEg3ASMpmPDYE8vkcxV302Iu8lZqCjYieg==} + dependencies: + '@types/node': 20.7.1 + dev: true + /@types/bn.js@5.1.2: resolution: {integrity: sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==} dependencies: @@ -1415,19 +1421,54 @@ packages: resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} dependencies: safe-buffer: 5.2.1 - dev: true + dev: false /bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} dev: true + /bech32@2.0.0: + resolution: {integrity: sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==} + dev: false + + /bigi@1.4.2: + resolution: {integrity: sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==} + dev: false + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} + /bip-schnorr@0.6.4: + resolution: {integrity: sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==} + engines: {node: '>=8.0.0'} + dependencies: + bigi: 1.4.2 + ecurve: 1.0.6 + js-sha256: 0.9.0 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /bitcore-lib@10.0.21: + resolution: {integrity: sha512-oYB1BrHjeRHqdrZ+j/cVm+M0XGxRDDjDiX4wP9QWQGAZkvS6DQGeNIndwS7m7BA18H76PJRhBM+DrSV2medpXg==} + dependencies: + bech32: 2.0.0 + bip-schnorr: 0.6.4 + bn.js: 4.11.8 + bs58: 4.0.1 + buffer-compare: 1.1.1 + elliptic: 6.5.4 + inherits: 2.0.1 + lodash: 4.17.21 + dev: false + + /bn.js@4.11.8: + resolution: {integrity: sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==} + dev: false + /bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: true /bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} @@ -1451,7 +1492,6 @@ packages: /brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - dev: true /browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} @@ -1460,15 +1500,11 @@ packages: resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} dependencies: base-x: 3.0.9 - dev: true + dev: false - /bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} - dependencies: - bs58: 4.0.1 - create-hash: 1.2.0 - safe-buffer: 5.2.1 - dev: true + /buffer-compare@1.1.1: + resolution: {integrity: sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==} + dev: false /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} @@ -1528,13 +1564,6 @@ packages: optionalDependencies: fsevents: 2.3.3 - /cipher-base@1.0.4: - resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - /cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: @@ -1568,16 +1597,6 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - /create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - dependencies: - cipher-base: 1.0.4 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.2 - sha.js: 2.4.11 - dev: true - /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true @@ -1676,14 +1695,12 @@ packages: engines: {node: '>=12'} dev: true - /ecpair@2.1.0: - resolution: {integrity: sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==} - engines: {node: '>=8.0.0'} + /ecurve@1.0.6: + resolution: {integrity: sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==} dependencies: - randombytes: 2.1.0 - typeforce: 1.18.0 - wif: 2.0.6 - dev: true + bigi: 1.4.2 + safe-buffer: 5.2.1 + dev: false /elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} @@ -1695,7 +1712,6 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2183,21 +2199,11 @@ packages: function-bind: 1.1.1 dev: false - /hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - safe-buffer: 5.2.1 - dev: true - /hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} dependencies: inherits: 2.0.4 minimalistic-assert: 1.0.1 - dev: true /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -2209,7 +2215,6 @@ packages: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} @@ -2235,6 +2240,10 @@ packages: once: 1.4.0 wrappy: 1.0.2 + /inherits@2.0.1: + resolution: {integrity: sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==} + dev: false + /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -2383,6 +2392,10 @@ packages: resolution: {integrity: sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==} dev: false + /js-sha256@0.9.0: + resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} + dev: false + /js-sha3@0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} dev: true @@ -2464,14 +2477,6 @@ packages: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true - /md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2491,11 +2496,9 @@ packages: /minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true /minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - dev: true /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2737,15 +2740,6 @@ packages: dependencies: safe-buffer: 5.2.1 - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2787,13 +2781,6 @@ packages: glob: 7.2.3 dev: true - /ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - dev: true - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -2857,14 +2844,6 @@ packages: has-property-descriptors: 1.0.0 dev: false - /sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2940,12 +2919,6 @@ packages: es-abstract: 1.22.2 dev: false - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2972,13 +2945,6 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true - /tiny-secp256k1@2.2.3: - resolution: {integrity: sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==} - engines: {node: '>=14.0.0'} - dependencies: - uint8array-tools: 0.0.7 - dev: true - /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3088,10 +3054,6 @@ packages: is-typed-array: 1.1.12 dev: false - /typeforce@1.18.0: - resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==} - dev: true - /typescript@5.0.4: resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} @@ -3106,11 +3068,6 @@ packages: dev: false optional: true - /uint8array-tools@0.0.7: - resolution: {integrity: sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==} - engines: {node: '>=14.0.0'} - dev: true - /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -3125,10 +3082,6 @@ packages: dependencies: punycode: 2.3.0 - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -3177,12 +3130,6 @@ packages: isexe: 2.0.0 dev: true - /wif@2.0.6: - resolution: {integrity: sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==} - dependencies: - bs58check: 2.1.2 - dev: true - /wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} dev: false From 873003b902a1e55bcc4c906beb50e5441c85cade Mon Sep 17 00:00:00 2001 From: "will.li" <120463031+higherordertech@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:00:52 +1100 Subject: [PATCH 07/43] P 317 tron ton holding amount (#2328) * P-317: remove testnet & use mainnet instead * P-317: add ton&trx token amount holding vc * fix PR * fix PR comments --------- Co-authored-by: higherordertech --- primitives/core/src/assertion.rs | 12 +- primitives/core/src/evm_amount_holding.rs | 26 ++ primitives/core/src/lib.rs | 3 + .../commands/litentry/request_vc.rs | 18 +- .../commands/litentry/request_vc_direct.rs | 8 +- .../interfaces/vc/definitions.ts | 5 + .../amount_holding/evm_amount_holding.rs | 324 ++++++++++++++++++ .../src/nodereal/amount_holding/mod.rs | 23 ++ .../core/assertion-build/src/nodereal/mod.rs | 1 + .../nft_holder/weirdo_ghost_gang_holder.rs | 4 +- .../amount_holding/evm_amount_holding.rs | 157 +++++++++ .../src/nodereal/amount_holding/mod.rs | 23 ++ .../core/credentials/src/nodereal/mod.rs | 1 + .../litentry/core/data-providers/src/lib.rs | 14 + .../data-providers/src/nodereal_jsonrpc.rs | 106 ++++-- .../core/mock-server/src/nodereal_jsonrpc.rs | 23 ++ .../receiver/src/handler/assertion.rs | 5 + .../lc-vc-task-receiver/src/vc_handling.rs | 5 + tee-worker/litentry/primitives/src/lib.rs | 10 +- tee-worker/service/src/prometheus_metrics.rs | 1 + .../service/src/running-mode-config.json | 8 +- 21 files changed, 729 insertions(+), 48 deletions(-) create mode 100644 primitives/core/src/evm_amount_holding.rs create mode 100644 tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs create mode 100644 tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/mod.rs create mode 100644 tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs create mode 100644 tee-worker/litentry/core/credentials/src/nodereal/amount_holding/mod.rs diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 37ef6b2ab7..1277360368 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -18,8 +18,8 @@ // when requesting VCs. use crate::{ - AccountId, BnbDigitDomainType, BoundedWeb3Network, GenericDiscordRoleType, OneBlockCourseType, - VIP3MembershipCardLevel, Web3Network, + AccountId, BnbDigitDomainType, BoundedWeb3Network, EVMTokenType, GenericDiscordRoleType, + OneBlockCourseType, VIP3MembershipCardLevel, Web3Network, }; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -245,6 +245,9 @@ pub enum Assertion { #[codec(index = 19)] WeirdoGhostGangHolder, + + #[codec(index = 22)] + EVMAmountHolding(EVMTokenType), // (evm_token_type) } impl Assertion { @@ -273,11 +276,14 @@ impl Assertion { Self::Achainable(arg) => arg.chains(), // Oneblock Assertion Self::Oneblock(..) => vec![Web3Network::Polkadot, Web3Network::Kusama], - Self::WeirdoGhostGangHolder => vec![Web3Network::Ethereum], // SPACEID Assertions Self::BnbDomainHolding | Self::BnbDigitDomainClub(..) => vec![Web3Network::Bsc], // VIP3 Member Card Self::VIP3MembershipCard(..) => vec![Web3Network::Ethereum], + // Weirdo Ghost Gang + Self::WeirdoGhostGangHolder => vec![Web3Network::Ethereum], + // EVM Amount Holding + Self::EVMAmountHolding(_) => vec![Web3Network::Ethereum, Web3Network::Bsc], // we don't care about any specific web3 network _ => vec![], } diff --git a/primitives/core/src/evm_amount_holding.rs b/primitives/core/src/evm_amount_holding.rs new file mode 100644 index 0000000000..d4afdd495d --- /dev/null +++ b/primitives/core/src/evm_amount_holding.rs @@ -0,0 +1,26 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +pub enum EVMTokenType { + #[codec(index = 0)] + Ton, + #[codec(index = 1)] + Trx, +} diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 76a0831052..49f992e4f6 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -52,6 +52,9 @@ pub use bnb_domain::*; mod generic_discord_role; pub use generic_discord_role::*; + +mod evm_amount_holding; +pub use evm_amount_holding::*; /// Common types of parachains. mod types { use sp_runtime::{ diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index 702770f344..8336030771 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -28,9 +28,9 @@ use litentry_primitives::{ aes_decrypt, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams, - AchainableToken, Assertion, BoundedWeb3Network, ContestType, GenericDiscordRoleType, Identity, - OneBlockCourseType, ParameterString, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, - Web3Network, REQUEST_AES_KEY_LEN, + AchainableToken, Assertion, BoundedWeb3Network, ContestType, EVMTokenType, + GenericDiscordRoleType, Identity, OneBlockCourseType, ParameterString, RequestAesKey, + SoraQuizType, VIP3MembershipCardLevel, Web3Network, REQUEST_AES_KEY_LEN, }; use sp_core::Pair; @@ -97,6 +97,8 @@ pub enum Command { #[clap(subcommand)] VIP3MembershipCard(VIP3MembershipCardLevelCommand), WeirdoGhostGangHolder, + #[clap(subcommand)] + EVMAmountHolding(EVMAmountHoldingCommand), } #[derive(Args)] @@ -177,6 +179,12 @@ pub enum SoraQuizCommand { Master, } +#[derive(Subcommand)] +pub enum EVMAmountHoldingCommand { + Ton, + Trx, +} + // I haven't found a good way to use common args for subcommands #[derive(Args)] pub struct AmountHoldingArg { @@ -443,6 +451,10 @@ impl RequestVcCommand { Assertion::VIP3MembershipCard(VIP3MembershipCardLevel::Silver), }, Command::WeirdoGhostGangHolder => Assertion::WeirdoGhostGangHolder, + Command::EVMAmountHolding(c) => match c { + EVMAmountHoldingCommand::Ton => Assertion::EVMAmountHolding(EVMTokenType::Ton), + EVMAmountHoldingCommand::Trx => Assertion::EVMAmountHolding(EVMTokenType::Trx), + }, }; let key = Self::random_aes_key(); diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs index 4b7eacfb3d..39513c673e 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs @@ -29,8 +29,8 @@ use litentry_primitives::{ aes_decrypt, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams, - AchainableToken, Assertion, ContestType, GenericDiscordRoleType, Identity, OneBlockCourseType, - RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network, + AchainableToken, Assertion, ContestType, EVMTokenType, GenericDiscordRoleType, Identity, + OneBlockCourseType, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network, }; use sp_core::Pair; @@ -248,6 +248,10 @@ impl RequestVcDirectCommand { Assertion::VIP3MembershipCard(VIP3MembershipCardLevel::Silver), }, Command::WeirdoGhostGangHolder => Assertion::WeirdoGhostGangHolder, + Command::EVMAmountHolding(c) => match c { + EVMAmountHoldingCommand::Ton => Assertion::EVMAmountHolding(EVMTokenType::Ton), + EVMAmountHoldingCommand::Trx => Assertion::EVMAmountHolding(EVMTokenType::Trx), + }, }; let mut key: RequestAesKey = RequestAesKey::default(); diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts index d698d1b165..77b1c66422 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts @@ -27,6 +27,7 @@ export default { BnbDigitDomainClub: "BnbDigitDomainType", VIP3MembershipCard: "VIP3MembershipCardLevel", WeirdoGhostGangHolder: "Null", + EVMAmountHolding: "EVMTokenType", }, }, AssertionSupportedNetwork: { @@ -139,5 +140,9 @@ export default { VIP3MembershipCardLevel: { _enum: ["Gold", "Silver"], }, + // EVMAmountHolding + EVMTokenType: { + _enum: ["Ton", "Trx"], + }, }, }; diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs new file mode 100644 index 0000000000..d60b921f01 --- /dev/null +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs @@ -0,0 +1,324 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use core::result; + +use crate::*; +use lc_credentials::{ + nodereal::amount_holding::evm_amount_holding::{ + EVMAmountHoldingAssertionUpdate, EVMTokenAddress, + }, + Credential, +}; +use lc_data_providers::{ + nodereal_jsonrpc::{ + FungibleApiList, GetTokenBalance20Param, NoderealChain, NoderealJsonrpcClient, + }, + Error as DataProviderError, +}; +use litentry_primitives::EVMTokenType; + +fn get_holding_balance( + token_type: EVMTokenType, + addresses: Vec<(Web3Network, String)>, +) -> result::Result { + let mut eth_client = NoderealJsonrpcClient::new(NoderealChain::Eth); + let mut bsc_client = NoderealJsonrpcClient::new(NoderealChain::Bsc); + let mut total_balance = 0_f64; + + for address in addresses.iter() { + let param = GetTokenBalance20Param { + contract_address: token_type.get_address(address.0).unwrap_or_default().into(), + address: address.1.clone(), + block_number: "latest".into(), + }; + match address.0 { + Web3Network::Bsc => match bsc_client.get_token_balance_20(¶m) { + Ok(balance) => { + total_balance += balance; + }, + Err(err) => return Err(err), + }, + Web3Network::Ethereum => match eth_client.get_token_balance_20(¶m) { + Ok(balance) => { + total_balance += balance; + }, + Err(err) => return Err(err), + }, + _ => {}, + } + } + + Ok(total_balance) +} + +pub fn build(req: &AssertionBuildRequest, token_type: EVMTokenType) -> Result { + debug!("evm amount holding: {:?}", token_type); + + let identities: Vec<(Web3Network, Vec)> = transpose_identity(&req.identities); + let addresses = identities + .into_iter() + .filter(|(newtwork_type, _)| newtwork_type.is_evm()) + .flat_map(|(newtwork_type, addresses)| { + addresses.into_iter().map(move |address| (newtwork_type, address)) + }) + .collect::>(); + + let result = get_holding_balance(token_type.clone(), addresses).map_err(|e| { + Error::RequestVCFailed( + Assertion::EVMAmountHolding(token_type.clone()), + ErrorDetail::DataProviderError(ErrorString::truncate_from( + format!("{e:?}").as_bytes().to_vec(), + )), + ) + }); + + match result { + Ok(value) => match Credential::new(&req.who, &req.shard) { + Ok(mut credential_unsigned) => { + credential_unsigned.update_evm_amount_holding_assertion(token_type, value); + Ok(credential_unsigned) + }, + Err(e) => { + error!("Generate unsigned credential failed {:?}", e); + Err(Error::RequestVCFailed( + Assertion::EVMAmountHolding(token_type), + e.into_error_detail(), + )) + }, + }, + Err(e) => Err(e), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itp_stf_primitives::types::ShardIdentifier; + use itp_utils::hex::decode_hex; + use lc_credentials::assertion_logic::{AssertionLogic, Op}; + use lc_data_providers::GLOBAL_DATA_PROVIDER_CONFIG; + use lc_mock_server::run; + + fn create_ton_token_assertion_logic() -> Box { + Box::new(AssertionLogic::Item { src: "$token".into(), op: Op::Equal, dst: "TON".into() }) + } + + fn create_ton_network_assertion_logic() -> Box { + Box::new(AssertionLogic::Or { + items: vec![ + Box::new(AssertionLogic::And { + items: vec![ + Box::new(AssertionLogic::Item { + src: "$network".into(), + op: Op::Equal, + dst: "ethereum".into(), + }), + Box::new(AssertionLogic::Item { + src: "$address".into(), + op: Op::Equal, + dst: "0x582d872a1b094fc48f5de31d3b73f2d9be47def1".into(), + }), + ], + }), + Box::new(AssertionLogic::And { + items: vec![ + Box::new(AssertionLogic::Item { + src: "$network".into(), + op: Op::Equal, + dst: "bsc".into(), + }), + Box::new(AssertionLogic::Item { + src: "$address".into(), + op: Op::Equal, + dst: "0x76a797a59ba2c17726896976b7b3747bfd1d220f".into(), + }), + ], + }), + ], + }) + } + + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + let url = run(0).unwrap() + "/nodereal_jsonrpc/"; + GLOBAL_DATA_PROVIDER_CONFIG + .write() + .unwrap() + .set_nodereal_api_key("d416f55179dbd0e45b1a8ed030e3".into()); + GLOBAL_DATA_PROVIDER_CONFIG + .write() + .unwrap() + .set_nodereal_api_chain_network_url(url); + } + + #[test] + fn build_evm_amount_holding_works() { + init(); + let identities: Vec = vec![ + (Identity::Evm([0; 20].into()), vec![Web3Network::Ethereum]), + (Identity::Evm([0; 20].into()), vec![Web3Network::Ethereum, Web3Network::Bsc]), + ]; + + let req: AssertionBuildRequest = AssertionBuildRequest { + shard: ShardIdentifier::default(), + signer: AccountId::from([0; 32]), + enclave_account: AccountId::from([0; 32]), + who: AccountId::from([0; 32]).into(), + assertion: Assertion::EVMAmountHolding(EVMTokenType::Ton), + identities, + top_hash: Default::default(), + maybe_key: None, + req_ext_hash: Default::default(), + }; + + match build(&req, EVMTokenType::Ton) { + Ok(credential) => { + log::info!("build EVMAmount holding done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![ + create_ton_token_assertion_logic(), + create_ton_network_assertion_logic(), + Box::new(AssertionLogic::Item { + src: "$holding_amount".into(), + op: Op::GreaterEq, + dst: "1600".into() + }), + Box::new(AssertionLogic::Item { + src: "$holding_amount".into(), + op: Op::LessThan, + dst: "3000".into() + }) + ] + } + ); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); + }, + Err(e) => { + panic!("build EVMAmount holding failed with error {:?}", e); + }, + } + } + + #[test] + fn build_evm_amount_holding_lt_min_works() { + init(); + let address = decode_hex("0x85be4e2ccc9c85be8783798b6e8a101bdac6467f".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + let identities: Vec = + vec![(Identity::Evm(address), vec![Web3Network::Ethereum])]; + + let req: AssertionBuildRequest = AssertionBuildRequest { + shard: ShardIdentifier::default(), + signer: AccountId::from([0; 32]), + enclave_account: AccountId::from([0; 32]), + who: AccountId::from([0; 32]).into(), + assertion: Assertion::EVMAmountHolding(EVMTokenType::Ton), + identities, + top_hash: Default::default(), + maybe_key: None, + req_ext_hash: Default::default(), + }; + + match build(&req, EVMTokenType::Ton) { + Ok(credential) => { + log::info!("build EVMAmount holding done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![ + create_ton_token_assertion_logic(), + create_ton_network_assertion_logic(), + Box::new(AssertionLogic::Item { + src: "$holding_amount".into(), + op: Op::GreaterEq, + dst: "0".into() + }), + Box::new(AssertionLogic::Item { + src: "$holding_amount".into(), + op: Op::LessThan, + dst: "100".into() + }) + ] + } + ); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), false); + }, + Err(e) => { + panic!("build EVMAmount holding failed with error {:?}", e); + }, + } + } + + #[test] + fn build_evm_amount_holding_gte_max_works() { + init(); + let address = decode_hex("0x90d53026a47ac20609accc3f2ddc9fb9b29bb310".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + let identities: Vec = + vec![(Identity::Evm(address), vec![Web3Network::Ethereum])]; + + let req: AssertionBuildRequest = AssertionBuildRequest { + shard: ShardIdentifier::default(), + signer: AccountId::from([0; 32]), + enclave_account: AccountId::from([0; 32]), + who: AccountId::from([0; 32]).into(), + assertion: Assertion::EVMAmountHolding(EVMTokenType::Ton), + identities, + top_hash: Default::default(), + maybe_key: None, + req_ext_hash: Default::default(), + }; + + match build(&req, EVMTokenType::Ton) { + Ok(credential) => { + log::info!("build EVMAmount holding done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![ + create_ton_token_assertion_logic(), + create_ton_network_assertion_logic(), + Box::new(AssertionLogic::Item { + src: "$holding_amount".into(), + op: Op::GreaterEq, + dst: "3000".into() + }) + ] + } + ); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); + }, + Err(e) => { + panic!("build EVMAmount holding failed with error {:?}", e); + }, + } + } +} diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/mod.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/mod.rs new file mode 100644 index 0000000000..09c8ec0fdf --- /dev/null +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub mod evm_amount_holding; diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs index 41346f95d0..bd8b22015c 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs @@ -20,5 +20,6 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; +pub mod amount_holding; pub mod bnb_domain; pub mod nft_holder; diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs index f5838e1c4d..af9b98e756 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs @@ -24,7 +24,7 @@ use core::result; use lc_credentials::nodereal::nft_holder::weirdo_ghost_gang_holder::WeirdoGhostGangHolderAssertionUpdate; use lc_data_providers::nodereal_jsonrpc::{ - GetTokenBalance721Param, NftApiList, NoderealChain, NoderealJsonrpcClient, NoderealNetwork, + GetTokenBalance721Param, NftApiList, NoderealChain, NoderealJsonrpcClient, }; use crate::*; @@ -58,7 +58,7 @@ pub fn build(req: &AssertionBuildRequest) -> Result { debug!("WeirdoGhostGang holder"); let mut has_nft = false; - let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth, NoderealNetwork::Mainnet); + let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth); let identities: Vec<(Web3Network, Vec)> = transpose_identity(&req.identities); let addresses = identities diff --git a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs new file mode 100644 index 0000000000..b03d9fe399 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs @@ -0,0 +1,157 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use lc_data_providers::achainable::web3_network_to_chain; +use litentry_primitives::{all_evm_web3networks, EVMTokenType, Web3Network}; + +use crate::{ + assertion_logic::{AssertionLogic, Op}, + litentry_profile::{BalanceRange, BalanceRangeIndex}, + Credential, +}; +pub trait EVMTokenAddress { + fn get_address(&self, network: Web3Network) -> Option<&'static str>; +} + +impl EVMTokenAddress for EVMTokenType { + fn get_address(&self, network: Web3Network) -> Option<&'static str> { + match (self, network) { + (EVMTokenType::Ton, Web3Network::Bsc) => + Some("0x76a797a59ba2c17726896976b7b3747bfd1d220f"), + (EVMTokenType::Ton, Web3Network::Ethereum) => + Some("0x582d872a1b094fc48f5de31d3b73f2d9be47def1"), + (EVMTokenType::Trx, Web3Network::Bsc) => + Some("0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3"), + (EVMTokenType::Trx, Web3Network::Ethereum) => + Some("0x50327c6c5a14dcade707abad2e27eb517df87ab5"), + _ => None, + } + } +} + +const EVM_HOLDING_AMOUNT_RANGE: [f64; 8] = + [0.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1600.0, 3000.0]; + +const TYPE: &str = "Token Holding Amount"; +const DESCRIPTION: &str = "The amount of a particular token you are holding"; + +struct AssertionKeys { + token: &'static str, + network: &'static str, + address: &'static str, + holding_amount: &'static str, +} + +const ASSERTION_KEYS: AssertionKeys = AssertionKeys { + token: "$token", + network: "$network", + address: "$address", + holding_amount: "$holding_amount", +}; + +trait AssertionTokenName { + fn get_name(&self) -> &'static str; +} + +impl AssertionTokenName for EVMTokenType { + fn get_name(&self) -> &'static str { + match self { + EVMTokenType::Ton => "TON", + EVMTokenType::Trx => "TRX", + } + } +} + +pub trait EVMAmountHoldingAssertionUpdate { + fn update_evm_amount_holding_assertion(&mut self, token_type: EVMTokenType, amount: f64); +} + +impl EVMAmountHoldingAssertionUpdate for Credential { + fn update_evm_amount_holding_assertion(&mut self, token_type: EVMTokenType, amount: f64) { + self.add_subject_info(DESCRIPTION, TYPE); + + update_assertion(token_type, amount, self); + } +} + +fn update_assertion(token_type: EVMTokenType, balance: f64, credential: &mut Credential) { + let mut assertion = AssertionLogic::new_and(); + + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.token, + Op::Equal, + token_type.get_name(), + )); + + let mut network_assertion = AssertionLogic::new_or(); + for newtork in all_evm_web3networks() { + match create_network_assertion_logic(newtork, token_type.clone()) { + Some(network_assertion_item) => { + network_assertion = network_assertion.add_item(network_assertion_item); + }, + None => continue, + } + } + + assertion = assertion.add_item(network_assertion); + + let index = BalanceRange::index(&EVM_HOLDING_AMOUNT_RANGE, balance); + match index { + Some(index) => { + let min = format!("{}", &EVM_HOLDING_AMOUNT_RANGE[index]); + let max = format!("{}", &EVM_HOLDING_AMOUNT_RANGE[index + 1]); + let min_item = + AssertionLogic::new_item(ASSERTION_KEYS.holding_amount, Op::GreaterEq, &min); + let max_item = + AssertionLogic::new_item(ASSERTION_KEYS.holding_amount, Op::LessThan, &max); + + assertion = assertion.add_item(min_item); + assertion = assertion.add_item(max_item); + + credential.credential_subject.values.push(index != 0); + }, + None => { + let min_item = AssertionLogic::new_item( + ASSERTION_KEYS.holding_amount, + Op::GreaterEq, + &format!("{}", &EVM_HOLDING_AMOUNT_RANGE.last().unwrap()), + ); + assertion = assertion.add_item(min_item); + + credential.credential_subject.values.push(true); + }, + } + + credential.credential_subject.assertions.push(assertion); +} + +fn create_network_assertion_logic( + network: Web3Network, + token_type: EVMTokenType, +) -> Option { + let mut assertion = AssertionLogic::new_and(); + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.network, + Op::Equal, + web3_network_to_chain(&network).as_str(), + )); + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.address, + Op::Equal, + token_type.get_address(network)?, + )); + Some(assertion) +} diff --git a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/mod.rs b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/mod.rs new file mode 100644 index 0000000000..09c8ec0fdf --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub mod evm_amount_holding; diff --git a/tee-worker/litentry/core/credentials/src/nodereal/mod.rs b/tee-worker/litentry/core/credentials/src/nodereal/mod.rs index 41346f95d0..bd8b22015c 100644 --- a/tee-worker/litentry/core/credentials/src/nodereal/mod.rs +++ b/tee-worker/litentry/core/credentials/src/nodereal/mod.rs @@ -20,5 +20,6 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; +pub mod amount_holding; pub mod bnb_domain; pub mod nft_holder; diff --git a/tee-worker/litentry/core/data-providers/src/lib.rs b/tee-worker/litentry/core/data-providers/src/lib.rs index 676a8780cd..3dba91f5e9 100644 --- a/tee-worker/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/litentry/core/data-providers/src/lib.rs @@ -407,3 +407,17 @@ impl ConvertParameterString for AchainableParams { }) } } + +fn hex_to_decimal(hex_string: &str) -> f64 { + let parts: Vec<&str> = hex_string.split('.').collect(); + + let integer_part = u64::from_str_radix(parts[0], 16).unwrap_or_default(); + + if parts.len() > 1 { + let decimal_part = u64::from_str_radix(parts[1], 16).unwrap(); + let decimal_str = format!("{}.{}", integer_part, decimal_part); + decimal_str.parse::().unwrap_or_default() + } else { + integer_part as f64 + } +} diff --git a/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs b/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs index 15131d5283..346f5a5041 100644 --- a/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs +++ b/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs @@ -17,7 +17,7 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::*; -use crate::{build_client, Error, HttpError, GLOBAL_DATA_PROVIDER_CONFIG}; +use crate::{build_client, hex_to_decimal, Error, HttpError, GLOBAL_DATA_PROVIDER_CONFIG}; use http::header::CONNECTION; use http_req::response::Headers; use itc_rest_client::{ @@ -67,22 +67,6 @@ impl NoderealChain { } } -pub enum NoderealNetwork { - Mainnet, - Testnet, - Goerli, -} - -impl NoderealNetwork { - pub fn to_string(&self) -> &'static str { - match self { - NoderealNetwork::Mainnet => "mainnet", - NoderealNetwork::Testnet => "testnet", - NoderealNetwork::Goerli => "goerli", - } - } -} - #[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct ReqPath { @@ -116,7 +100,7 @@ pub struct NoderealJsonrpcClient { } impl NoderealJsonrpcClient { - pub fn new(chain: NoderealChain, network: NoderealNetwork) -> Self { + pub fn new(chain: NoderealChain) -> Self { let api_key = GLOBAL_DATA_PROVIDER_CONFIG.write().unwrap().nodereal_api_key.clone(); let api_retry_delay = GLOBAL_DATA_PROVIDER_CONFIG.write().unwrap().nodereal_api_retry_delay; let api_retry_times = GLOBAL_DATA_PROVIDER_CONFIG.write().unwrap().nodereal_api_retry_times; @@ -125,9 +109,7 @@ impl NoderealJsonrpcClient { .unwrap() .nodereal_api_chain_network_url .clone(); - let base_url = api_url - .replace("{chain}", chain.to_string()) - .replace("{network}", network.to_string()); + let base_url = api_url.replace("{chain}", chain.to_string()); let mut headers = Headers::new(); headers.insert(CONNECTION.as_str(), "close"); @@ -244,6 +226,7 @@ pub trait NftApiList { fn get_token_balance_721(&mut self, param: &GetTokenBalance721Param) -> Result; } +// NFT API impl NftApiList for NoderealJsonrpcClient { // https://docs.nodereal.io/reference/nr_getnftholdings fn get_nft_holdings( @@ -285,14 +268,66 @@ impl NftApiList for NoderealJsonrpcClient { params, id: Id::Number(1), }; - self.post(&req_body) - .map_err(|e| Error::RequestError(format!("{:?}", e))) - .map(|resp| { + + match self.post(&req_body) { + Ok(resp) => { // result example: '0x', '0x8' debug!("get_token_balance_721, response: {:?}", resp); - let result = resp.result.as_str().unwrap(); - usize::from_str_radix(&result[2..], 16).unwrap_or_default() - }) + match resp.result.as_str() { + Some(result) => Ok(usize::from_str_radix(&result[2..], 16).unwrap_or_default()), + None => Err(Error::RequestError(format!( + "Cannot tansform response result {:?} to &str", + resp.result + ))), + } + }, + Err(e) => Err(Error::RequestError(format!("{:?}", e))), + } + } +} + +#[derive(Serialize, Debug)] +pub struct GetTokenBalance20Param { + // The address of the contract + pub contract_address: String, + // Target address + pub address: String, + // The block number in hex format or the string 'latest' or 'earliest' on which the balance will be checked + pub block_number: String, +} + +// Fungible Tokens API +pub trait FungibleApiList { + fn get_token_balance_20(&mut self, param: &GetTokenBalance20Param) -> Result; +} + +impl FungibleApiList for NoderealJsonrpcClient { + // https://docs.nodereal.io/reference/nr_gettokenbalance20 + fn get_token_balance_20(&mut self, param: &GetTokenBalance20Param) -> Result { + let params: Vec = + vec![param.contract_address.clone(), param.address.clone(), param.block_number.clone()]; + debug!("get_token_balance_20: {:?}", param); + let req_body = RpcRequest { + jsonrpc: "2.0".to_string(), + method: "nr_getTokenBalance20".to_string(), + params, + id: Id::Number(1), + }; + + match self.post(&req_body) { + Ok(resp) => { + // result example: '0x', '0x8' + debug!("get_token_balance_20, response: {:?}", resp); + match resp.result.as_str() { + Some(result) => Ok(hex_to_decimal(&result[2..])), + None => Err(Error::RequestError(format!( + "Cannot tansform response result {:?} to &str", + resp.result + ))), + } + }, + Err(e) => Err(Error::RequestError(format!("{:?}", e))), + } } } @@ -317,7 +352,7 @@ mod tests { #[test] fn does_get_nft_holdings_works() { init(); - let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth, NoderealNetwork::Mainnet); + let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth); let param = GetNFTHoldingsParam { account_address: "0x49AD262C49C7aA708Cc2DF262eD53B64A17Dd5EE".into(), token_type: "ERC721".into(), @@ -336,7 +371,7 @@ mod tests { #[test] fn does_get_token_balance_721_works() { init(); - let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth, NoderealNetwork::Mainnet); + let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth); let param = GetTokenBalance721Param { token_address: "0x07D971C03553011a48E951a53F48632D37652Ba1".into(), account_address: "0x49AD262C49C7aA708Cc2DF262eD53B64A17Dd5EE".into(), @@ -345,4 +380,17 @@ mod tests { let result = client.get_token_balance_721(¶m).unwrap(); assert_eq!(result, 1); } + + #[test] + fn does_get_token_balance_20_works() { + init(); + let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth); + let param = GetTokenBalance20Param { + contract_address: "0x76A797A59Ba2C17726896976B7B3747BfD1d220f".into(), + address: "0x85Be4e2ccc9c85BE8783798B6e8A101BDaC6467F".into(), + block_number: "latest".into(), + }; + let result = client.get_token_balance_20(¶m).unwrap(); + assert_eq!(result, 800.1); + } } diff --git a/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs b/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs index c72d5fa4eb..3a0f64fb56 100644 --- a/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs +++ b/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs @@ -28,6 +28,14 @@ pub(crate) fn query() -> impl Filter = json + .get("params") + .unwrap() + .as_array() + .unwrap() + .iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect(); match method { "nr_getNFTHoldings" => { let result = GetNFTHoldingsResult { @@ -54,6 +62,21 @@ pub(crate) fn query() -> impl Filter { + let value = match params[1].as_str() { + "0x85be4e2ccc9c85be8783798b6e8a101bdac6467f" => "0x1", + // 3000 + "0x90d53026a47ac20609accc3f2ddc9fb9b29bb310" => "0xBB8", + // 800.1 + _ => "0x320.1", + }; + let body = RpcResponse { + jsonrpc: "2.0".into(), + id: Id::Number(1), + result: serde_json::to_value(value).unwrap(), + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + }, _ => Response::builder().status(404).body(String::from("Error query")), } }) diff --git a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs index 7c3f7e08cb..1e7d8a9265 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs @@ -122,6 +122,11 @@ where Assertion::WeirdoGhostGangHolder => lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build(&self.req), + + Assertion::EVMAmountHolding(token_type) => + lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( + &self.req, token_type, + ), }?; // post-process the credential diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs index 9a526c2b99..8d84d430b3 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs @@ -98,6 +98,11 @@ where Assertion::WeirdoGhostGangHolder => lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build(&self.req), + + Assertion::EVMAmountHolding(token_type) => + lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( + &self.req, token_type, + ), }?; // post-process the credential diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index 5bd2fcf0c8..8f2436bd19 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -50,11 +50,11 @@ pub use parentchain_primitives::{ AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableMirror, AchainableParams, AchainableToken, AmountHoldingTimeType, Assertion, Balance as ParentchainBalance, BlockNumber as ParentchainBlockNumber, BnbDigitDomainType, - BoundedWeb3Network, ContestType, ErrorDetail, ErrorString, GenericDiscordRoleType, - Hash as ParentchainHash, Header as ParentchainHeader, IMPError, Index as ParentchainIndex, - IntoErrorDetail, OneBlockCourseType, ParameterString, SchemaContentString, SchemaIdString, - Signature as ParentchainSignature, SoraQuizType, VCMPError, VIP3MembershipCardLevel, - Web3Network, ASSERTION_FROM_DATE, MINUTES, + BoundedWeb3Network, ContestType, EVMTokenType, ErrorDetail, ErrorString, + GenericDiscordRoleType, Hash as ParentchainHash, Header as ParentchainHeader, IMPError, + Index as ParentchainIndex, IntoErrorDetail, OneBlockCourseType, ParameterString, + SchemaContentString, SchemaIdString, Signature as ParentchainSignature, SoraQuizType, + VCMPError, VIP3MembershipCardLevel, Web3Network, ASSERTION_FROM_DATE, MINUTES, }; use scale_info::TypeInfo; use sp_core::{ecdsa, ed25519, sr25519, ByteArray}; diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index 6515037758..db68fb6a9a 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -287,6 +287,7 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::GenericDiscordRole(_) => "GenericDiscordRole", Assertion::VIP3MembershipCard(..) => "VIP3MembershipCard", Assertion::WeirdoGhostGangHolder => "WeirdoGhostGangHolder", + Assertion::EVMAmountHolding(_) => "EVMAmountHolding", }, }; inc_stf_calls(category, label); diff --git a/tee-worker/service/src/running-mode-config.json b/tee-worker/service/src/running-mode-config.json index 5fa6212dc2..b1b226af75 100644 --- a/tee-worker/service/src/running-mode-config.json +++ b/tee-worker/service/src/running-mode-config.json @@ -17,7 +17,7 @@ "nodereal_api_retry_delay": 5000, "nodereal_api_retry_times": 2, "nodereal_api_url": "https://open-platform.nodereal.io/", - "nodereal_api_chain_network_url": "https://{chain}-{network}.nodereal.io/", + "nodereal_api_chain_network_url": "https://{chain}-mainnet.nodereal.io/", "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", @@ -41,7 +41,7 @@ "nodereal_api_retry_delay": 5000, "nodereal_api_retry_times": 2, "nodereal_api_url": "https://open-platform.nodereal.io/", - "nodereal_api_chain_network_url": "https://{chain}-{network}.nodereal.io/", + "nodereal_api_chain_network_url": "https://{chain}-mainnet.nodereal.io/", "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", @@ -65,7 +65,7 @@ "nodereal_api_retry_delay": 5000, "nodereal_api_retry_times": 2, "nodereal_api_url": "https://open-platform.nodereal.io/", - "nodereal_api_chain_network_url": "https://{chain}-{network}.nodereal.io/", + "nodereal_api_chain_network_url": "https://{chain}-mainnet.nodereal.io/", "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", @@ -89,7 +89,7 @@ "nodereal_api_retry_delay": 5000, "nodereal_api_retry_times": 2, "nodereal_api_url": "https://open-platform.nodereal.io/", - "nodereal_api_chain_network_url": "https://{chain}-{network}.nodereal.io/", + "nodereal_api_chain_network_url": "https://{chain}-mainnet.nodereal.io/", "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", From 6f13ad4eb50a22a29f6c45cff84109cf98f2fed5 Mon Sep 17 00:00:00 2001 From: Igor Trofimov Date: Mon, 18 Dec 2023 12:40:48 +0200 Subject: [PATCH 08/43] P 345 precompile contract tests (#2325) * init contract * add initial scenarios for testing functions * include readme and add tests to CI --------- Co-authored-by: Verin1005 Co-authored-by: WMQ <46511820+wangminqi@users.noreply.github.com> Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com> --- scripts/run-ts-test.sh | 1 + ts-tests/package.json | 1 + ts-tests/precompile/contracts/README.md | 12 ++ ts-tests/precompile/contracts/bridge.json | 25 +++ ts-tests/precompile/contracts/staking.json | 165 +++++++++++++++ ts-tests/tests/evm-contract.test.ts | 3 +- ts-tests/tests/evm-transfer.test.ts | 6 +- ts-tests/tests/precompile-contract.test.ts | 233 +++++++++++++++++++++ ts-tests/tsconfig.json | 1 + 9 files changed, 443 insertions(+), 4 deletions(-) create mode 100644 ts-tests/precompile/contracts/README.md create mode 100644 ts-tests/precompile/contracts/bridge.json create mode 100644 ts-tests/precompile/contracts/staking.json create mode 100644 ts-tests/tests/precompile-contract.test.ts diff --git a/scripts/run-ts-test.sh b/scripts/run-ts-test.sh index 11d9702907..9f227e6253 100755 --- a/scripts/run-ts-test.sh +++ b/scripts/run-ts-test.sh @@ -34,4 +34,5 @@ fi if $evm; then pnpm run test-evm-transfer 2>&1 | tee "$LITENTRY_PARACHAIN_DIR/parachain_ci_test.log" pnpm run test-evm-contract 2>&1 | tee "$LITENTRY_PARACHAIN_DIR/parachain_ci_test.log" + pnpm run test-precompile-contract 2>&1 | tee "$LITENTRY_PARACHAIN_DIR/parachain_ci_test.log" fi diff --git a/ts-tests/package.json b/ts-tests/package.json index 3af0758c10..5ac5afd6d7 100644 --- a/ts-tests/package.json +++ b/ts-tests/package.json @@ -16,6 +16,7 @@ "test-evm-contract": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/evm-contract.test.ts'", "test-runtime-upgrade": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/runtime-upgrade.test.ts'", "test-all": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/**/*.test.ts'", + "test-precompile-contract": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/precompile-contract.test.ts'", "format": "pnpm exec prettier --write 'tests/**/*.test.ts'" }, "author": "Litentry Dev", diff --git a/ts-tests/precompile/contracts/README.md b/ts-tests/precompile/contracts/README.md new file mode 100644 index 0000000000..3f0b65430a --- /dev/null +++ b/ts-tests/precompile/contracts/README.md @@ -0,0 +1,12 @@ +# EVM Contracts JSON + +This folder contains Ethereum Virtual Machine (EVM) contracts converted to JSON format using Remix. + +## What is Remix? + +[Remix](https://remix.ethereum.org/) is an open-source web and desktop application that helps developers write, test, and deploy smart contracts on the Ethereum blockchain. It provides a user-friendly interface for Solidity development and offers features such as a built-in code editor, debugger, and compiler. + +## Included Contracts + +- [ParachainStaking](https://www.notion.so/web3builders/Parachain-Precompile-Contract-0c34929e5f16408084446dcf3dd36006?pvs=4#53cff6e661e84c4fb300bbb5e9f68033) +- [BridgeTransfer](https://www.notion.so/web3builders/Parachain-Precompile-Contract-0c34929e5f16408084446dcf3dd36006?pvs=4#1f82e990425345b59b7cdbba50bb2c49) diff --git a/ts-tests/precompile/contracts/bridge.json b/ts-tests/precompile/contracts/bridge.json new file mode 100644 index 0000000000..d5ab21c488 --- /dev/null +++ b/ts-tests/precompile/contracts/bridge.json @@ -0,0 +1,25 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "receipt", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "dest_id", + "type": "uint8" + } + ], + "name": "transferNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/ts-tests/precompile/contracts/staking.json b/ts-tests/precompile/contracts/staking.json new file mode 100644 index 0000000000..488464b8e5 --- /dev/null +++ b/ts-tests/precompile/contracts/staking.json @@ -0,0 +1,165 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + } + ], + "name": "cancelDelegationRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "autoCompound", + "type": "uint8" + } + ], + "name": "delegateWithAutoCompound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegator", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + } + ], + "name": "delegationRequestIsPending", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "more", + "type": "uint256" + } + ], + "name": "delegatorBondMore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegator", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + } + ], + "name": "executeDelegationRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "less", + "type": "uint256" + } + ], + "name": "scheduleDelegatorBondLess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + } + ], + "name": "scheduleRevokeDelegation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "candidate", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "value", + "type": "uint8" + } + ], + "name": "setAutoCompound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/ts-tests/tests/evm-contract.test.ts b/ts-tests/tests/evm-contract.test.ts index 618d68b35e..b94771c1e7 100644 --- a/ts-tests/tests/evm-contract.test.ts +++ b/ts-tests/tests/evm-contract.test.ts @@ -9,6 +9,7 @@ import { compiled } from './compile'; describeLitentry('Test EVM Module Contract', ``, (context) => { console.log(`Test EVM Module Contract`); + const config = loadConfig(); step('Transfer Value from Eve to EVM external account', async function () { // In case evm is not enabled in Normal Mode, switch back to filterMode, after test. @@ -96,7 +97,7 @@ describeLitentry('Test EVM Module Contract', ``, (context) => { const bytecode = compiled.evm.bytecode.object; const abi = compiled.abi; // Create Web3 instance - const web3 = new Web3('http://localhost:9944'); + const web3 = new Web3(config.parachain_ws); // Create deploy function const deploy = async (accountFrom: any) => { diff --git a/ts-tests/tests/evm-transfer.test.ts b/ts-tests/tests/evm-transfer.test.ts index a804ad073a..82b6904c03 100644 --- a/ts-tests/tests/evm-transfer.test.ts +++ b/ts-tests/tests/evm-transfer.test.ts @@ -1,7 +1,7 @@ import { assert, expect } from 'chai'; import { step } from 'mocha-steps'; -import { signAndSend, describeLitentry } from './utils'; +import { signAndSend, describeLitentry, loadConfig } from './utils'; import { hexToU8a, u8aToHex } from '@polkadot/util'; import { createPair, encodeAddress } from '@polkadot/keyring'; import { evmToAddress } from '@polkadot/util-crypto'; @@ -9,7 +9,7 @@ import Web3 from 'web3'; describeLitentry('Test EVM Module Transfer', ``, (context) => { console.log(`Test EVM Module Transfer`); - + const config = loadConfig(); step('Transfer Value from Eve to EVM external account', async function () { // In case evm is not enabled in Normal Mode, switch back to filterMode, after test. // We do not test mode in initialization since ts-test concerns filter function too. @@ -116,7 +116,7 @@ describeLitentry('Test EVM Module Transfer', ``, (context) => { console.log(`evmAccount Balance: ${evmAccountInitBalance}`); // Create Web3 instance - const web3 = new Web3('http://localhost:9944'); + const web3 = new Web3(config.parachain_ws); let value = 100000000000; // ExistentialDeposit = 100 000 000 000 (0x174876E800) diff --git a/ts-tests/tests/precompile-contract.test.ts b/ts-tests/tests/precompile-contract.test.ts new file mode 100644 index 0000000000..b668715913 --- /dev/null +++ b/ts-tests/tests/precompile-contract.test.ts @@ -0,0 +1,233 @@ +import { assert, expect } from 'chai'; +import { step } from 'mocha-steps'; +import { AbiItem } from 'web3-utils'; +import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; +import Web3 from 'web3'; +import precompileContractAbi from '../precompile/contracts/staking.json'; +import { mnemonicGenerate, mnemonicToMiniSecret, decodeAddress, evmToAddress } from '@polkadot/util-crypto'; +import { KeyringPair } from '@polkadot/keyring/types'; + +const toBigNumber = (int: number) => int * 1e12; + +describeLitentry('Test Parachain Precompile Contract', ``, (context) => { + const config = loadConfig(); + + const precompileContractAddress = '0x000000000000000000000000000000000000502d'; + const evmAccountRaw = { + privateKey: '0x01ab6e801c06e59ca97a14fc0a1978b27fa366fc87450e0b65459dd3515b7391', + address: '0xaaafB3972B05630fCceE866eC69CdADd9baC2771', + mappedAddress: evmToAddress('0xaaafB3972B05630fCceE866eC69CdADd9baC2771', 31), + publicKey: '0x93eac2793cb6d9e837b0f8da1a63dbc0db2ca848c05cbe66db139157922f78f9', + }; + + // candidate: collator address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY + // transform to bytes32(public key) reference:https://polkadot.subscan.io/tools/format_transform?input=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY&type=All + const collatorPublicKey = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; + + const web3 = new Web3(config.parachain_ws); + const precompileContract = new web3.eth.Contract(precompileContractAbi as AbiItem[], precompileContractAddress); + + const executeTransaction = async (delegateTransaction: any, label = '') => { + console.log(`=== Executing ${label} ===`); + + // estimate gas doesn't work + // const gas = await delegateTransaction.estimateGas(); + // console.log("gas", gas); + + const transaction = await web3.eth.accounts.signTransaction( + { + to: precompileContractAddress, + data: delegateTransaction.encodeABI(), + gas: 1000000, + }, + evmAccountRaw.privateKey + ); + + return await web3.eth.sendSignedTransaction(transaction.rawTransaction!); + }; + + const printBalance = (label: string, bl: any) => { + console.log(label, 'free', bl.free.toNumber() / 1e12, 'reserved', bl.reserved.toNumber() / 1e12); + }; + + // this function makes two transactions first one from token owner substrate account to owner evm mapped account + // and then it transfers to recepient + const transferTokens = async (from: KeyringPair, to: any) => { + const aliceEVMMappedAccount = from.publicKey.slice(0, 20); // pretend to be evm + console.log(`alice address: ${from.publicKey}`); + console.log(`aliceEVMMappedAccount: ${aliceEVMMappedAccount}`); + + let aliceMappedSustrateAccount = evmToAddress(aliceEVMMappedAccount, 31); + + console.log('transfer from Alice to alice EMV'); + + // Deposit money into substrate account's truncated EVM address's mapping substrate account + const tx_init = context.api.tx.balances.transfer(aliceMappedSustrateAccount, 70 * 1e12); + await signAndSend(tx_init, context.alice); + + // 25000 is min_gas_price setup + const tx = context.api.tx.evm.call( + aliceEVMMappedAccount, // evm like + to.address, // evm like + '0x', + toBigNumber(65), + 1000000, + 25000, + null, + null, + [] + ); + let block = await context.api.rpc.chain.getBlock(); + console.log(`evm call await before: ${block.block.header.number}`); + await signAndSend(tx, from); + let temp = await context.api.rpc.chain.getBlock(); + console.log(`evm call await end: ${temp.block.header.number}`); + }; + + const isPendingRequest = async () => + await precompileContract.methods.delegationRequestIsPending(evmAccountRaw.publicKey, collatorPublicKey).call(); + + const collatorDetails = async () => { + const response = await context.api.query.parachainStaking.autoCompoundingDelegations(collatorPublicKey); + const collators = response.toJSON() as { address: string; value: number }[]; + return collators[0]; + }; + + step('Address with not sufficient amount of tokens', async function () { + // Create valid Substrate-compatible seed from mnemonic + const randomSeed = mnemonicToMiniSecret(mnemonicGenerate()); + const secretKey = Buffer.from(randomSeed).toString('hex'); + + const delegateWithAutoCompound = precompileContract.methods.delegateWithAutoCompound( + collatorPublicKey, + toBigNumber(60), + 1 + ); + + try { + await web3.eth.accounts.signTransaction( + { + to: precompileContractAddress, + data: delegateWithAutoCompound.encodeABI(), + gas: await delegateWithAutoCompound.estimateGas(), + }, + secretKey + ); + expect(true).to.eq(false); // test should fail here + } catch (e) { + expect(e).to.be.instanceof(Error); + } + }); + + // To see full params types for the interfaces, check notion page: https://web3builders.notion.site/Parachain-Precompile-Contract-0c34929e5f16408084446dcf3dd36006 + step('Test precompile contract', async function () { + const filterMode = (await context.api.query.extrinsicFilter.mode()).toHuman(); + if ('Test' !== filterMode) { + let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode('Test')); + let temp = await context.api.rpc.chain.getBlock(); + console.log(`setMode await Before: ${temp.block.header.number}`); + await signAndSend(extrinsic, context.alice); + temp = await context.api.rpc.chain.getBlock(); + console.log(`setMode await end: ${temp.block.header.number}`); + } + + let balance = (await context.api.query.system.account(evmAccountRaw.mappedAddress)).data; + printBalance('initial balance', balance); + + // top up LITs if not sufficient amount for staking or they are not reserved (require: 50 LITs minimum) + if (balance.free.toNumber() < toBigNumber(60) && balance.reserved.toNumber() === 0) { + console.log('transferring more tokens'); + + await transferTokens(context.alice, evmAccountRaw); + + balance = (await context.api.query.system.account(evmAccountRaw.mappedAddress)).data; + printBalance('balance after transferring', balance); + } + + //// TESTS + const autoCompoundPercent = 20; + + // delegateWithAutoCompound(collator, amount, percent) + const delegateWithAutoCompound = precompileContract.methods.delegateWithAutoCompound( + collatorPublicKey, + toBigNumber(60), + autoCompoundPercent + ); + + // skip test if already delegated + if (balance.reserved.toNumber() === 0) { + await executeTransaction(delegateWithAutoCompound, 'delegateWithAutoCompound'); + const { data: afterDelegateBalance } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + + expect(balance.free.toNumber() - toBigNumber(60)).to.closeTo( + afterDelegateBalance.free.toNumber(), + toBigNumber(1) + ); + expect(afterDelegateBalance.reserved.toNumber()).to.eq(toBigNumber(60)); + const collator = await collatorDetails(); + expect(collator.value).to.eq(autoCompoundPercent); + + balance = afterDelegateBalance; + } + + // delegatorBondMore(collator, amount) + const delegatorBondMore = precompileContract.methods.delegatorBondMore(collatorPublicKey, toBigNumber(1)); + await executeTransaction(delegatorBondMore, 'delegatorBondMore'); + + const { data: balanceAfterBondMore } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + expect(balanceAfterBondMore.free.toNumber()).to.closeTo( + balanceAfterBondMore.free.toNumber() - toBigNumber(1), + toBigNumber(1) + ); + expect(balanceAfterBondMore.reserved.toNumber()).to.eq(balance.reserved.toNumber() + toBigNumber(1)); + + // setAutoCompound(collator, percent); + const setAutoCompound = precompileContract.methods.setAutoCompound(collatorPublicKey, autoCompoundPercent + 5); + await executeTransaction(setAutoCompound, 'setAutoCompound'); + const collatorAfterCompound = await collatorDetails(); + expect(collatorAfterCompound.value).to.eq(autoCompoundPercent + 5); + + // scheduleDelegatorBondLess(collator, amount) + expect(await isPendingRequest()).to.be.false; + const scheduleDelegatorBondLess = precompileContract.methods.scheduleDelegatorBondLess( + collatorPublicKey, + toBigNumber(5) + ); + await executeTransaction(scheduleDelegatorBondLess, 'scheduleDelegatorBondLess'); + expect(await isPendingRequest()).to.be.true; + + // cancelDelegationRequest(collator) + const cancelDelegationRequest = precompileContract.methods.cancelDelegationRequest(collatorPublicKey); + expect(await isPendingRequest()).to.be.true; + await executeTransaction(cancelDelegationRequest, 'cancelDelegationRequest'); + expect(await isPendingRequest()).to.be.false; + + // In case evm is not enabled in Normal Mode, switch back to filterMode, after test. + let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode(filterMode)); + await signAndSend(extrinsic, context.alice); + }); + + // once we add ability to customise minimum waiting time for `executeDelegationRequest` implement tests for the rest functions + // step('test time sensitive functions', async () => { + // delegate(collator, amount); + // const delegate = precompileContract.methods.delegate(collatorPublicKey, toBigNumber(55)); + // await executeTransaction(delegate, 'delegate'); + // const { data: balanceAfterDelegate } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + // printBalance('balanceAfterDelegate', balanceAfterDelegate); + // scheduleRevokeDelegation(collator); + // const scheduleRevokeDelegation = precompileContract.methods.scheduleRevokeDelegation(collatorPublicKey); + // await executeTransaction(scheduleRevokeDelegation, 'scheduleRevokeDelegation'); + // const { data: balanceAfterRevoke } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + // printBalance('balanceAfterRevoke', balanceAfterRevoke); + // executeDelegationRequest(delegator, collator); + // const executeDelegationRequest = precompileContract.methods.executeDelegationRequest( + // evmAccountRaw.mappedAddress, + // collatorPublicKey + // ); + // await executeTransaction(executeDelegationRequest, 'executeDelegationRequest'); + // const { data: balanceAfterExecuteDelegation } = await context.api.query.system.account( + // evmAccountRaw.mappedAddress + // ); + // printBalance('balanceAfterExecuteDelegation', balanceAfterExecuteDelegation); + // }); +}); diff --git a/ts-tests/tsconfig.json b/ts-tests/tsconfig.json index f6ba8eb1e7..edce41abe9 100644 --- a/ts-tests/tsconfig.json +++ b/ts-tests/tsconfig.json @@ -2,6 +2,7 @@ "extends": "./node_modules/gts/tsconfig-google.json", "compilerOptions": { "esModuleInterop": true, + "resolveJsonModule": true, "target": "es5", "lib": ["es2019"], "rootDir": ".", From a6cf8c3fedca67ca1a9439cd3fb631b470e6e69e Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Mon, 18 Dec 2023 15:42:35 +0100 Subject: [PATCH 09/43] Fix upgrade simulation parameter (#2335) * Add missing authorizeUpgrade param * adjust timeout --- .github/workflows/simulate-runtime-upgrade.yml | 4 ++-- ts-tests/tests/runtime-upgrade.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/simulate-runtime-upgrade.yml b/.github/workflows/simulate-runtime-upgrade.yml index 556090c1cb..af9e760d01 100644 --- a/.github/workflows/simulate-runtime-upgrade.yml +++ b/.github/workflows/simulate-runtime-upgrade.yml @@ -17,7 +17,7 @@ env: jobs: simulate-runtime-upgrade: runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -36,7 +36,7 @@ jobs: run: corepack enable && corepack enable pnpm - name: Fork ${{ matrix.chain }} and launch parachain - timeout-minutes: 10 + timeout-minutes: 20 run: | ./scripts/fork-parachain-and-launch.sh ${{ matrix.chain }} diff --git a/ts-tests/tests/runtime-upgrade.test.ts b/ts-tests/tests/runtime-upgrade.test.ts index 252a66cf36..00611d9a98 100644 --- a/ts-tests/tests/runtime-upgrade.test.ts +++ b/ts-tests/tests/runtime-upgrade.test.ts @@ -21,7 +21,7 @@ async function runtimeUpgrade(api: ApiPromise, wasm: string) { // authorize and enact the upgrade await api.tx.sudo - .sudo(api.tx.parachainSystem.authorizeUpgrade(blake2AsHex(wasm))) + .sudo(api.tx.parachainSystem.authorizeUpgrade(blake2AsHex(wasm), true)) .signAndSend(alice, { nonce: -1 }); console.log('Submitted authorizeUpgrade'); await api.tx.parachainSystem.enactAuthorizedUpgrade(wasm).signAndSend(alice, { nonce: -1 }); From 5d45746a8634c2d89e5fc2da3ebcd751529148ce Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Mon, 18 Dec 2023 20:48:25 +0100 Subject: [PATCH 10/43] Add missing bitcoin match arm (#2338) * add missing bitcoin match arm * fix clippy * add comment --- tee-worker/litentry/core/assertion-build/src/a20.rs | 5 +++++ tee-worker/litentry/core/assertion-build/src/lib.rs | 5 +++++ tee-worker/litentry/pallets/identity-management/src/lib.rs | 4 +++- tee-worker/litentry/primitives/src/lib.rs | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tee-worker/litentry/core/assertion-build/src/a20.rs b/tee-worker/litentry/core/assertion-build/src/a20.rs index d062403248..08e22d4ffa 100644 --- a/tee-worker/litentry/core/assertion-build/src/a20.rs +++ b/tee-worker/litentry/core/assertion-build/src/a20.rs @@ -48,9 +48,14 @@ impl RestPath for EarlyBirdResponse { } pub fn build(req: &AssertionBuildRequest) -> Result { + // Note: it's not perfectly implemented here + // it only attests if the main address meets the criteria, but we should have implemented + // the supported web3networks and attested the linked identities. + // However, this VC is probably too old to change let who = match req.who { Identity::Substrate(account) => account_id_to_string(&account), Identity::Evm(account) => account_id_to_string(&account), + Identity::Bitcoin(account) => account_id_to_string(&account), _ => unreachable!(), }; debug!("Assertion A20 build, who: {:?}", who); diff --git a/tee-worker/litentry/core/assertion-build/src/lib.rs b/tee-worker/litentry/core/assertion-build/src/lib.rs index 63fb2bb6ea..4e90e3839b 100644 --- a/tee-worker/litentry/core/assertion-build/src/lib.rs +++ b/tee-worker/litentry/core/assertion-build/src/lib.rs @@ -97,6 +97,11 @@ pub fn transpose_identity( addresses.push((address, n)); networks_set.insert(n); }, + Identity::Bitcoin(address) => { + let address = account_id_to_string(address.as_ref()); + addresses.push((address, n)); + networks_set.insert(n); + }, _ => {}, }; }); diff --git a/tee-worker/litentry/pallets/identity-management/src/lib.rs b/tee-worker/litentry/pallets/identity-management/src/lib.rs index 68e5c43d84..a20a200e15 100644 --- a/tee-worker/litentry/pallets/identity-management/src/lib.rs +++ b/tee-worker/litentry/pallets/identity-management/src/lib.rs @@ -42,7 +42,8 @@ use frame_support::{pallet_prelude::*, sp_runtime::traits::One, traits::StorageV use frame_system::pallet_prelude::*; pub use litentry_primitives::{ - all_evm_web3networks, all_substrate_web3networks, Identity, ParentchainBlockNumber, Web3Network, + all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, Identity, + ParentchainBlockNumber, Web3Network, }; use sp_core::{blake2_256, H256}; use sp_std::{vec, vec::Vec}; @@ -158,6 +159,7 @@ pub mod pallet { let prime_identity_web3networks = match who { Identity::Substrate(_) => all_substrate_web3networks(), Identity::Evm(_) => all_evm_web3networks(), + Identity::Bitcoin(_) => all_bitcoin_web3networks(), _ => vec![], }; let context = >::new( diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index 8f2436bd19..35d019fb64 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -44,7 +44,7 @@ use itp_sgx_crypto::ShieldingCryptoDecrypt; use itp_utils::hex::hex_encode; use log::error; pub use parentchain_primitives::{ - all_evm_web3networks, all_substrate_web3networks, all_web3networks, + all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, all_web3networks, AccountId as ParentchainAccountId, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, From b8638ffbef05cee323844ba3981ed88d447a133c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 00:06:05 +0100 Subject: [PATCH 11/43] Bump num_enum from 0.5.11 to 0.6.1 (#2343) Bumps [num_enum](https://github.com/illicitonion/num_enum) from 0.5.11 to 0.6.1. - [Commits](https://github.com/illicitonion/num_enum/compare/0.5.11...0.6.1) --- updated-dependencies: - dependency-name: num_enum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 6 +++--- precompiles/bridge-transfer/Cargo.toml | 2 +- precompiles/parachain-staking/Cargo.toml | 2 +- precompiles/utils/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc3184d833..c52c84a425 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7207,7 +7207,7 @@ dependencies = [ "frame-system", "hex-literal 0.4.1", "log", - "num_enum 0.5.11", + "num_enum 0.6.1", "pallet-balances", "pallet-bridge", "pallet-bridge-transfer", @@ -7262,7 +7262,7 @@ dependencies = [ "frame-support", "frame-system", "log", - "num_enum 0.5.11", + "num_enum 0.6.1", "pallet-balances", "pallet-evm", "pallet-parachain-staking", @@ -9713,7 +9713,7 @@ dependencies = [ "hex-literal 0.4.1", "impl-trait-for-tuples", "log", - "num_enum 0.5.11", + "num_enum 0.6.1", "pallet-evm", "parity-scale-codec", "precompile-utils-macro", diff --git a/precompiles/bridge-transfer/Cargo.toml b/precompiles/bridge-transfer/Cargo.toml index 320a558546..3dc81a73b9 100644 --- a/precompiles/bridge-transfer/Cargo.toml +++ b/precompiles/bridge-transfer/Cargo.toml @@ -6,7 +6,7 @@ version = '0.9.17' [dependencies] log = { version = "0.4", default-features = false } -num_enum = { version = "0.5.3", default-features = false } +num_enum = { version = "0.6.1", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } rustc-hex = { version = "2.0.1", default-features = false } diff --git a/precompiles/parachain-staking/Cargo.toml b/precompiles/parachain-staking/Cargo.toml index df5627ee6e..ec296475e8 100644 --- a/precompiles/parachain-staking/Cargo.toml +++ b/precompiles/parachain-staking/Cargo.toml @@ -6,7 +6,7 @@ version = '0.9.17' [dependencies] log = { version = "0.4", default-features = false } -num_enum = { version = "0.5.3", default-features = false } +num_enum = { version = "0.6.1", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } rustc-hex = { version = "2.0.1", default-features = false } diff --git a/precompiles/utils/Cargo.toml b/precompiles/utils/Cargo.toml index f5f107e445..309b7030d5 100644 --- a/precompiles/utils/Cargo.toml +++ b/precompiles/utils/Cargo.toml @@ -9,7 +9,7 @@ version = '0.9.17' evm = { git = "https://github.com/rust-blockchain/evm", rev = "b7b82c7e1fc57b7449d6dfa6826600de37cc1e65", default-features = false, optional = true } impl-trait-for-tuples = "0.2.2" log = { version = "0.4", default-features = false } -num_enum = { version = "0.5.3", default-features = false } +num_enum = { version = "0.6.1", default-features = false } sha3 = { version = "0.10", default-features = false } similar-asserts = { version = "1.1.0", optional = true } From 7131a10207bb9e7b105fc387936f8a2afd3c99f0 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Tue, 19 Dec 2023 09:23:17 +0800 Subject: [PATCH 12/43] P-319 add BAB holder (#2337) * refactor uniswap user base on basic type * add bab holder --------- Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com> --- tee-worker/Cargo.lock | 8 +- .../assertion-build/src/achainable/basic.rs | 88 ++++++------------- .../credentials/src/achainable/bab_holder.rs | 40 +++++++++ .../core/credentials/src/achainable/mod.rs | 2 + .../src/achainable/uniswap_user.rs | 48 ++++++++++ .../litentry/core/credentials/src/lib.rs | 13 --- .../data-providers/src/achainable_names.rs | 29 ++++++ 7 files changed, 150 insertions(+), 78 deletions(-) create mode 100644 tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs create mode 100644 tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 9b5a7a3349..ffbae888bb 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -580,9 +580,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64ct" @@ -10893,7 +10893,7 @@ version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ - "base64 0.21.5", + "base64 0.21.2", "bytes 1.4.0", "encoding_rs", "futures-core 0.3.28", @@ -11469,7 +11469,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.5", + "base64 0.21.2", ] [[package]] diff --git a/tee-worker/litentry/core/assertion-build/src/achainable/basic.rs b/tee-worker/litentry/core/assertion-build/src/achainable/basic.rs index 050edcbe64..cc305089e1 100644 --- a/tee-worker/litentry/core/assertion-build/src/achainable/basic.rs +++ b/tee-worker/litentry/core/assertion-build/src/achainable/basic.rs @@ -20,31 +20,15 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; -use crate::{achainable::request_uniswap_v2_or_v3_user, *}; -use lc_data_providers::ConvertParameterString; -use std::string::ToString; +use crate::{ + achainable::{request_achainable, request_uniswap_v2_or_v3_user}, + *, +}; +use lc_credentials::achainable::{bab_holder::UpdateBABHolder, uniswap_user::UpdateUniswapUser}; +use lc_data_providers::achainable_names::AchainableNameBasic; -/// NOTE: -/// Build is uniswap v2/v3 user -/// name: Because it is necessary to request the interface four times to determine whether the uniswapv2/v3 user requires it, we can agree on the name here as IsUniswapV23User. -/// chain: ethereum -/// -/// assertions":[ -/// { -/// { -/// src:$is_uniswap_v2_user, -/// op:==, -/// dst:true -/// }, -/// { -/// src: is_uniswap_v3_user, -/// op: ==, -/// dst: true -/// } -/// } -/// pub fn build_basic(req: &AssertionBuildRequest, param: AchainableBasic) -> Result { - debug!("Assertion Achainable build_basic, who: {:?}", account_id_to_string(&req.who)); + debug!("Assertion Achainable building Basic"); let identities = transpose_identity(&req.identities); let addresses = identities @@ -53,47 +37,29 @@ pub fn build_basic(req: &AssertionBuildRequest, param: AchainableBasic) -> Resul .collect::>(); let achainable_param = AchainableParams::Basic(param.clone()); - check_uniswap_v23_user_inputs(&achainable_param, ¶m)?; - - let (v2_user, v3_user) = request_uniswap_v2_or_v3_user(addresses, achainable_param.clone())?; - match Credential::new(&req.who, &req.shard) { - Ok(mut credential_unsigned) => { - let (desc, subtype) = get_uniswap_v23_info(); - credential_unsigned.add_subject_info(desc, subtype); - credential_unsigned.update_uniswap_v23_info(v2_user, v3_user); + let mut credential = Credential::new(&req.who, &req.shard).map_err(|e| { + Error::RequestVCFailed( + Assertion::Achainable(achainable_param.clone()), + e.into_error_detail(), + ) + })?; - Ok(credential_unsigned) + let basic_name = AchainableNameBasic::from(param.name).map_err(|e| { + Error::RequestVCFailed( + Assertion::Achainable(achainable_param.clone()), + e.into_error_detail(), + ) + })?; + match basic_name { + AchainableNameBasic::UniswapV23User => { + let (v2_user, v3_user) = request_uniswap_v2_or_v3_user(addresses, achainable_param)?; + credential.update_uniswap_user(v2_user, v3_user); }, - Err(e) => { - error!("Generate unsigned credential failed {:?}", e); - Err(Error::RequestVCFailed( - Assertion::Achainable(achainable_param), - e.into_error_detail(), - )) + AchainableNameBasic::BABHolder => { + let is_bab_holder = request_achainable(addresses, achainable_param)?; + credential.update_bab_holder(is_bab_holder); }, } -} - -fn get_uniswap_v23_info() -> (&'static str, &'static str) { - ( - "You are a trader or liquidity provider of Uniswap V2 or V3. - Uniswap V2 Factory Contract: 0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f. - Uniswap V3 Factory Contract: 0x1f98431c8ad98523631ae4a59f267346ea31f984.", - "Uniswap V2/V3 User", - ) -} - -fn check_uniswap_v23_user_inputs( - achainable_param: &AchainableParams, - param: &AchainableBasic, -) -> Result { - let name = achainable_param.to_string(¶m.name)?; - if name != "Uniswap V2/V3 user" { - return Err(Error::RequestVCFailed( - Assertion::Achainable(achainable_param.clone()), - ErrorDetail::StfError(ErrorString::truncate_from("Invalid name".to_string().into())), - )) - } - Ok(true) + Ok(credential) } diff --git a/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs b/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs new file mode 100644 index 0000000000..2fdf6c5ab9 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs @@ -0,0 +1,40 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + assertion_logic::{AssertionLogic, Op}, + Credential, +}; + +const BAB_HOLDER_DESCRIPTIONS: &str = "You are a holder of a certain kind of NFT"; +const BAB_HOLDER_TYPE: &str = "NFT Holder"; +const BAB_HOLDER_BREAKDOWN: &str = "is_bab_holder"; + +pub trait UpdateBABHolder { + fn update_bab_holder(&mut self, is_bab_holder: bool); +} + +impl UpdateBABHolder for Credential { + fn update_bab_holder(&mut self, is_bab_holder: bool) { + let bab_holder = AssertionLogic::new_item(BAB_HOLDER_BREAKDOWN, Op::Equal, "true"); + + let assertion = AssertionLogic::new_and().add_item(bab_holder); + self.credential_subject.assertions.push(assertion); + self.credential_subject.values.push(is_bab_holder); + + self.add_subject_info(BAB_HOLDER_DESCRIPTIONS, BAB_HOLDER_TYPE); + } +} diff --git a/tee-worker/litentry/core/credentials/src/achainable/mod.rs b/tee-worker/litentry/core/credentials/src/achainable/mod.rs index f813fdb1fc..a795bf7892 100644 --- a/tee-worker/litentry/core/credentials/src/achainable/mod.rs +++ b/tee-worker/litentry/core/credentials/src/achainable/mod.rs @@ -15,4 +15,6 @@ // along with Litentry. If not, see . pub mod amount_holding_time; +pub mod bab_holder; pub mod lit_holding_amount; +pub mod uniswap_user; diff --git a/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs b/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs new file mode 100644 index 0000000000..18f7855687 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs @@ -0,0 +1,48 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + assertion_logic::{AssertionLogic, Op}, + Credential, +}; +use std::string::ToString; + +const UNISWAP_USER_DESCRIPTIONS: &str = + "You are a trader or liquidity provider of Uniswap V2 or V3. +Uniswap V2 Factory Contract: 0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f. +Uniswap V3 Factory Contract: 0x1f98431c8ad98523631ae4a59f267346ea31f984."; +const UNISWAP_USER_TYPE: &str = "Uniswap V2/V3 User"; + +pub trait UpdateUniswapUser { + fn update_uniswap_user(&mut self, is_v2_holder: bool, is_v3_holder: bool); +} + +impl UpdateUniswapUser for Credential { + fn update_uniswap_user(&mut self, is_v2_holder: bool, is_v3_holder: bool) { + let uniswap_v2 = + AssertionLogic::new_item("$is_uniswap_v2_user", Op::Equal, &is_v2_holder.to_string()); + let uniswap_v3 = + AssertionLogic::new_item("$is_uniswap_v3_user", Op::Equal, &is_v3_holder.to_string()); + + let assertion = AssertionLogic::new_and().add_item(uniswap_v2).add_item(uniswap_v3); + self.credential_subject.assertions.push(assertion); + + // Always true + self.credential_subject.values.push(true); + + self.add_subject_info(UNISWAP_USER_DESCRIPTIONS, UNISWAP_USER_TYPE); + } +} diff --git a/tee-worker/litentry/core/credentials/src/lib.rs b/tee-worker/litentry/core/credentials/src/lib.rs index cd5ff9cd19..9eb4e65108 100644 --- a/tee-worker/litentry/core/credentials/src/lib.rs +++ b/tee-worker/litentry/core/credentials/src/lib.rs @@ -513,19 +513,6 @@ impl Credential { self.credential_subject.values.push(value); } - pub fn update_uniswap_v23_info(&mut self, v2_user: bool, v3_user: bool) { - let uniswap_v2 = - AssertionLogic::new_item("$is_uniswap_v2_user", Op::Equal, &v2_user.to_string()); - let uniswap_v3 = - AssertionLogic::new_item("$is_uniswap_v3_user", Op::Equal, &v3_user.to_string()); - - let assertion = AssertionLogic::new_and().add_item(uniswap_v2).add_item(uniswap_v3); - self.credential_subject.assertions.push(assertion); - - // Always true - self.credential_subject.values.push(true); - } - pub fn update_class_of_year(&mut self, ret: bool, date: String) { let mut and_logic = AssertionLogic::new_and(); diff --git a/tee-worker/litentry/core/data-providers/src/achainable_names.rs b/tee-worker/litentry/core/data-providers/src/achainable_names.rs index d9a6fe4cbf..d3b6f09921 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable_names.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable_names.rs @@ -25,6 +25,35 @@ pub trait GetAchainableName { fn name(&self) -> &'static str; } +#[derive(Debug)] +pub enum AchainableNameBasic { + BABHolder, + UniswapV23User, // custom name +} + +impl GetAchainableName for AchainableNameBasic { + fn name(&self) -> &'static str { + match self { + AchainableNameBasic::BABHolder => "BAB token holder", + AchainableNameBasic::UniswapV23User => "Uniswap V2/V3 user", + } + } +} + +impl AchainableNameBasic { + pub fn from(param: ParameterString) -> Result { + let name_str = vec_to_string(param.to_vec())?; + + if name_str == AchainableNameBasic::BABHolder.name() { + return Ok(AchainableNameBasic::BABHolder) + } else if name_str == AchainableNameBasic::UniswapV23User.name() { + return Ok(AchainableNameBasic::UniswapV23User) + } + + Err(Error::AchainableError("Invalid Achainable Name in Basic Type".to_string())) + } +} + #[derive(Debug)] pub enum AchainableNameMirror { IsAPublicationOnMirror, From 8a2376aae5f9f13692318261d40e20c3918efb0c Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Tue, 19 Dec 2023 21:12:50 +0800 Subject: [PATCH 13/43] P-315 add lit staking vc (#2332) * Add lit staking * add staking client * decode delegator * small update * add LITStaking * using pallet-parachain-staking directly * fix NULL * using ParentchainBalance * refactor decode_delegator --- primitives/core/src/assertion.rs | 5 + tee-worker/Cargo.lock | 9 +- .../interfaces/vc/definitions.ts | 1 + tee-worker/enclave-runtime/Cargo.lock | 95 +++++++- .../litentry/core/assertion-build/Cargo.toml | 4 + .../litentry/core/assertion-build/src/lib.rs | 1 + .../core/assertion-build/src/lit_staking.rs | 224 ++++++++++++++++++ .../src/litentry_profile/lit_staking.rs | 75 ++++++ .../credentials/src/litentry_profile/mod.rs | 1 + .../receiver/src/handler/assertion.rs | 1 + .../lc-vc-task-receiver/src/vc_handling.rs | 2 + tee-worker/service/src/prometheus_metrics.rs | 1 + 12 files changed, 413 insertions(+), 6 deletions(-) create mode 100644 tee-worker/litentry/core/assertion-build/src/lit_staking.rs create mode 100644 tee-worker/litentry/core/credentials/src/litentry_profile/lit_staking.rs diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 1277360368..cb118e65d3 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -246,6 +246,9 @@ pub enum Assertion { #[codec(index = 19)] WeirdoGhostGangHolder, + #[codec(index = 20)] + LITStaking, + #[codec(index = 22)] EVMAmountHolding(EVMTokenType), // (evm_token_type) } @@ -280,6 +283,8 @@ impl Assertion { Self::BnbDomainHolding | Self::BnbDigitDomainClub(..) => vec![Web3Network::Bsc], // VIP3 Member Card Self::VIP3MembershipCard(..) => vec![Web3Network::Ethereum], + // LITStaking + Self::LITStaking => vec![Web3Network::Litentry], // Weirdo Ghost Gang Self::WeirdoGhostGangHolder => vec![Web3Network::Ethereum], // EVM Amount Holding diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index ffbae888bb..0b3c40a4f1 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -6123,6 +6123,7 @@ dependencies = [ "frame-support", "hex 0.4.0", "hex 0.4.3", + "hex-literal", "http 0.2.1", "http 0.2.9", "http_req 0.8.1 (git+https://github.com/integritee-network/http_req?branch=master)", @@ -6138,12 +6139,14 @@ dependencies = [ "lc-stf-task-sender", "litentry-primitives", "log 0.4.20", + "pallet-parachain-staking", "parity-scale-codec", "rust-base58 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rust-base58 0.0.4 (git+https://github.com/mesalock-linux/rust-base58-sgx)", "serde 1.0.193", "serde_json 1.0.103", "sgx_tstd", + "sp-core", "ss58-registry", "thiserror 1.0.9", "url 2.1.1", @@ -8861,7 +8864,7 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.20", - "num_enum 0.5.11", + "num_enum 0.6.1", "pallet-bridge", "pallet-bridge-transfer", "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", @@ -8910,7 +8913,7 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.20", - "num_enum 0.5.11", + "num_enum 0.6.1", "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "pallet-parachain-staking", "parity-scale-codec", @@ -10184,7 +10187,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log 0.4.20", - "num_enum 0.5.11", + "num_enum 0.6.1", "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "parity-scale-codec", "precompile-utils-macro", diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts index 77b1c66422..7b71f9a901 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts @@ -27,6 +27,7 @@ export default { BnbDigitDomainClub: "BnbDigitDomainType", VIP3MembershipCard: "VIP3MembershipCardLevel", WeirdoGhostGangHolder: "Null", + LITStaking: "Null", EVMAmountHolding: "EVMTokenType", }, }, diff --git a/tee-worker/enclave-runtime/Cargo.lock b/tee-worker/enclave-runtime/Cargo.lock index 7273cea73d..5fb183c9e3 100644 --- a/tee-worker/enclave-runtime/Cargo.lock +++ b/tee-worker/enclave-runtime/Cargo.lock @@ -1766,7 +1766,7 @@ dependencies = [ "parity-scale-codec", "serde 1.0.188", "sgx_tstd", - "substrate-fixed", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", "thiserror", "url", ] @@ -2150,7 +2150,7 @@ dependencies = [ "lc-stf-task-sender", "parity-scale-codec", "sgx_tstd", - "substrate-fixed", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", ] [[package]] @@ -2808,6 +2808,7 @@ dependencies = [ "blake2-rfc", "frame-support", "hex 0.4.0", + "hex-literal", "http", "http_req", "itc-rest-client", @@ -2820,11 +2821,13 @@ dependencies = [ "lc-stf-task-sender", "litentry-primitives", "log", + "pallet-parachain-staking", "parity-scale-codec", "rust-base58 0.0.4 (git+https://github.com/mesalock-linux/rust-base58-sgx)", "serde 1.0.188", "serde_json 1.0.107", "sgx_tstd", + "sp-core", "ss58-registry", "thiserror", "url", @@ -3371,6 +3374,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "pallet-authorship" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-balances" version = "4.0.0-dev" @@ -3424,6 +3441,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-parachain-staking" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-balances", + "pallet-session", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-staking", + "sp-std", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed)", +] + [[package]] name = "pallet-parentchain" version = "0.9.0" @@ -3437,6 +3473,26 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-session" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-sudo" version = "4.0.0-dev" @@ -4763,6 +4819,19 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "sp-session" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-staking", + "sp-std", +] + [[package]] name = "sp-staking" version = "4.0.0-dev" @@ -4959,6 +5028,26 @@ dependencies = [ "typenum 1.16.0", ] +[[package]] +name = "substrate-fixed" +version = "0.5.9" +source = "git+https://github.com/encointer/substrate-fixed#a75f3ba3f7c7893fb420500639cc055f964b1b88" +dependencies = [ + "parity-scale-codec", + "scale-info", + "substrate-typenum", +] + +[[package]] +name = "substrate-typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f0091e93c2c75b233ae39424c52cb8a662c0811fb68add149e20e5d7e8a788" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + [[package]] name = "subtle" version = "2.5.0" @@ -5219,7 +5308,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.7", "static_assertions", ] diff --git a/tee-worker/litentry/core/assertion-build/Cargo.toml b/tee-worker/litentry/core/assertion-build/Cargo.toml index 30393c2404..f23f8835bf 100644 --- a/tee-worker/litentry/core/assertion-build/Cargo.toml +++ b/tee-worker/litentry/core/assertion-build/Cargo.toml @@ -39,11 +39,15 @@ itp-utils = { path = "../../../core-primitives/utils", default-features = false frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +hex-literal = { version = "0.4" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + # litentry lc-credentials = { path = "../credentials", default-features = false } lc-data-providers = { path = "../data-providers", default-features = false } lc-stf-task-sender = { path = "../stf-task/sender", default-features = false } litentry-primitives = { path = "../../primitives", default-features = false } +pallet-parachain-staking = { path = "../../../../pallets/parachain-staking", default-features = false } [dev-dependencies] env_logger = "0.10.0" diff --git a/tee-worker/litentry/core/assertion-build/src/lib.rs b/tee-worker/litentry/core/assertion-build/src/lib.rs index 4e90e3839b..ef90c5f8da 100644 --- a/tee-worker/litentry/core/assertion-build/src/lib.rs +++ b/tee-worker/litentry/core/assertion-build/src/lib.rs @@ -48,6 +48,7 @@ pub mod a8; pub mod achainable; pub mod generic_discord_role; pub mod holding_time; +pub mod lit_staking; pub mod nodereal; pub mod oneblock; pub mod vip3; diff --git a/tee-worker/litentry/core/assertion-build/src/lit_staking.rs b/tee-worker/litentry/core/assertion-build/src/lit_staking.rs new file mode 100644 index 0000000000..32d98bc92c --- /dev/null +++ b/tee-worker/litentry/core/assertion-build/src/lit_staking.rs @@ -0,0 +1,224 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::*; +use codec::Decode; +use frame_support::{StorageHasher, Twox64Concat}; +use http::header::CONNECTION; +use itc_rest_client::{ + error::Error as RestClientError, + http_client::{DefaultSend, HttpClient}, + rest_client::{Headers, RestClient}, + RestPath, RestPost, +}; +use itp_stf_primitives::types::AccountId; +use itp_utils::hex_display::AsBytesRef; +use lc_credentials::litentry_profile::lit_staking::UpdateLITStakingAmountCredential; +use lc_data_providers::build_client; +use litentry_primitives::ParentchainBalance; +use pallet_parachain_staking::types::Delegator; +use serde::{Deserialize, Serialize}; +use std::string::ToString; + +const LIT_TOKEN_DECIMALS: u128 = 1_000_000_000_000; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct JsonRPCRequest { + id: usize, + jsonrpc: String, + method: String, + params: Vec, +} + +impl JsonRPCRequest { + pub fn state_getstorage(params: &str) -> Self { + Self { + id: 1, + jsonrpc: "2.0".to_string(), + method: "state_getStorage".to_string(), + params: vec![params.to_string()], + } + } +} + +impl RestPath for JsonRPCRequest { + fn get_path(path: String) -> core::result::Result { + Ok(path) + } +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct JsonRPCResponse { + pub id: usize, + pub jsonrpc: String, + pub result: String, +} + +pub struct LitentryStakingClient { + client: RestClient>, +} + +impl Default for LitentryStakingClient { + fn default() -> Self { + Self::new() + } +} + +impl LitentryStakingClient { + pub fn new() -> Self { + let mut headers = Headers::new(); + headers.insert(CONNECTION.as_str(), "close"); + let client = build_client("https://litentry-rpc.dwellir.com:443", headers); + LitentryStakingClient { client } + } + + pub fn send_request(&mut self, data: &JsonRPCRequest) -> Result { + self.client + .post_capture::(String::default(), data) + .map_err(|e| { + Error::RequestVCFailed( + Assertion::LITStaking, + ErrorDetail::DataProviderError(ErrorString::truncate_from( + format!("{e:?}").as_bytes().to_vec(), + )), + ) + }) + } +} + +pub trait QueryParachainStaking { + fn query_delegator_state(&mut self, key: &str) -> Result; +} + +impl QueryParachainStaking for LitentryStakingClient { + fn query_delegator_state(&mut self, key: &str) -> Result { + let data = JsonRPCRequest::state_getstorage(key); + let res = self.send_request(&data)?; + Ok(res.result) + } +} + +pub struct DelegatorState; +impl DelegatorState { + pub fn query_lit_staking( + &mut self, + client: &mut LitentryStakingClient, + identities: &[Identity], + ) -> Result { + let mut total_staking_amount = 0_u128; + + for identity in identities { + let storage_key = DelegatorState::delegator_state_storage_key(identity)?; + let storage_in_hex = client.query_delegator_state(&storage_key)?; + + let delegator = DelegatorState::decode_delegator(&storage_in_hex)?; + let total = delegator.total; + + total_staking_amount += total; + } + + Ok(total_staking_amount / LIT_TOKEN_DECIMALS) + } + + fn delegator_state_storage_key(identity: &Identity) -> Result { + // encoded partial key: ParachainStaking DelegatorState + // 0xa686a3043d0adcf2fa655e57bc595a78131da8bc800de21b19b3ba9ed33cfacc + let params = "0xa686a3043d0adcf2fa655e57bc595a78131da8bc800de21b19b3ba9ed33cfacc"; + let acc = identity + .to_account_id() + .ok_or(Error::RequestVCFailed(Assertion::LITStaking, ErrorDetail::ParseError))?; + let cocat = Twox64Concat::hash(acc.as_ref()); + + Ok(params.to_string() + &hex::encode(&cocat)) + } + + fn decode_delegator(storage_in_hex: &str) -> Result> { + // Remove 0x + if let Some(storage_in_hex_without_prefix) = storage_in_hex.strip_prefix("0x") { + if let Ok(decoded) = hex::decode(storage_in_hex_without_prefix) { + if let Ok(delegator) = + Delegator::::decode(&mut decoded.as_bytes_ref()) + { + return Ok(delegator) + } + } + } + + Err(Error::RequestVCFailed( + Assertion::LITStaking, + ErrorDetail::DataProviderError(ErrorString::truncate_from( + "Invalid ParachainStaking DelegatorState".as_bytes().to_vec(), + )), + )) + } +} + +pub fn build(req: &AssertionBuildRequest) -> Result { + debug!("Assertion building LIT staking amount"); + + let mut identities = vec![]; + req.identities.iter().for_each(|identity| { + identities.push(identity.0.clone()); + }); + + let mut client = LitentryStakingClient::new(); + let staking_amount = DelegatorState.query_lit_staking(&mut client, &identities)?; + match Credential::new(&req.who, &req.shard) { + Ok(mut credential_unsigned) => { + credential_unsigned.update_lit_staking_amount(staking_amount); + Ok(credential_unsigned) + }, + Err(e) => { + error!("Generate unsigned credential failed {:?}", e); + Err(Error::RequestVCFailed(Assertion::LITStaking, e.into_error_detail())) + }, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::{crypto::Ss58Codec, ed25519}; + + #[test] + fn decode_delegator_works() { + let delegator_in_hex = "0xa06c6b3f286fc8fe59cfe3d85ea8df043ddc08742ff9cfe2ed3d6ba1da1f4b4a18149ccce9d526a65ba54fccc24f5d1dee62f9b87915d4004eb932959d468a9e6200f008d0236e040000000000000000001acba651394c1b8d65d06702662921077e58b09d0fc15f3126a427144f83c95f00b0b522399003000000000000000000223188d5f28ee27f7e9067e89bc52fca8f1da20c6a7548a21cef18d8934f820f006048774c3a0400000000000000000024f07a3858f8d4dece9806b6c7e4ee165ba8c98e6ff4d066dd0284d46aee967d00e046350eb003000000000000000000e0d0031d0a450dfc4bb16333fe575dfb8452bb0f79c768181478190a5d9a653f00b064d8ab8103000000000000000000fc7a9dd32be14db4695555aa9a2abd240a8c2160f84ccb403a985701dd13fe5000409dde18410300000000000000000000d04f567cab160000000000000000000000000000000000000000000000000000"; + let d = DelegatorState::decode_delegator(delegator_in_hex); + assert!(d.is_ok()); + } + + #[test] + fn decode_delegator_should_fail_works() { + let delegator_in_hex = "0xa0"; + let d = DelegatorState::decode_delegator(delegator_in_hex); + assert!(d.is_err()); + } + + #[test] + fn delegator_state_storage_key_works() { + let address = "4A2nt96tH4ej9B3S9sagrKdJubYvu8No4hE9kjjrXMWvGLYW"; + + let pubkey = ed25519::Public::from_ss58check(address).unwrap(); + let acc = AccountId::new(pubkey.0); + let identity = Identity::from(acc); + + let storage_key = DelegatorState::delegator_state_storage_key(&identity).unwrap(); + let target_key = "0xa686a3043d0adcf2fa655e57bc595a78131da8bc800de21b19b3ba9ed33cfacc01e6a2b4eb558329a06c6b3f286fc8fe59cfe3d85ea8df043ddc08742ff9cfe2ed3d6ba1da1f4b4a".to_string(); + assert_eq!(storage_key, target_key); + } +} diff --git a/tee-worker/litentry/core/credentials/src/litentry_profile/lit_staking.rs b/tee-worker/litentry/core/credentials/src/litentry_profile/lit_staking.rs new file mode 100644 index 0000000000..cd5ac65ed1 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/litentry_profile/lit_staking.rs @@ -0,0 +1,75 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + assertion_logic::AssertionLogic, nodereal::bnb_domain::RangeCredentialDetail, Credential, +}; +use std::vec::Vec; + +// VC type / info +const LIT_STAKING_INFOS: (&str, &str) = ("LIT staking amount", "The amount of LIT you are staking"); + +// [x-y) +pub const LIT_STAKING_AMOUNT_RANGE: [usize; 10] = [0, 1, 50, 100, 200, 500, 800, 1200, 1600, 3000]; + +pub struct LITStakingAmount { + pub amount: u128, +} + +impl LITStakingAmount { + pub fn new(amount: u128) -> Self { + Self { amount } + } +} + +impl RangeCredentialDetail for LITStakingAmount { + fn get_info(&self) -> (&'static str, &'static str) { + LIT_STAKING_INFOS + } + + fn get_range(&self) -> Vec { + LIT_STAKING_AMOUNT_RANGE.to_vec() + } + + fn get_last_value(&self) -> usize { + 3000 + } + + fn get_breakdown(&self) -> &'static str { + "$lit_staking_amount" + } +} + +pub trait UpdateLITStakingAmountCredential { + fn update_lit_staking_amount(&mut self, amount: u128); +} + +impl UpdateLITStakingAmountCredential for Credential { + fn update_lit_staking_amount(&mut self, amount: u128) { + let lit_staking = LITStakingAmount::new(amount); + let items = lit_staking.get_assertion_items(amount as usize); + let mut assertion = AssertionLogic::new_and(); + for item in items { + assertion = assertion.add_item(item); + } + + self.credential_subject.assertions.push(assertion); + self.credential_subject.values.push(true); + + let info = lit_staking.get_info(); + self.add_subject_info(info.1, info.0); + } +} diff --git a/tee-worker/litentry/core/credentials/src/litentry_profile/mod.rs b/tee-worker/litentry/core/credentials/src/litentry_profile/mod.rs index 2c73b0aa7b..630660173d 100644 --- a/tee-worker/litentry/core/credentials/src/litentry_profile/mod.rs +++ b/tee-worker/litentry/core/credentials/src/litentry_profile/mod.rs @@ -15,6 +15,7 @@ // along with Litentry. If not, see . pub mod holding_amount; +pub mod lit_staking; pub mod mirror; pub mod token_balance; diff --git a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs index 1e7d8a9265..8f2e89991b 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs @@ -123,6 +123,7 @@ where Assertion::WeirdoGhostGangHolder => lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build(&self.req), + Assertion::LITStaking => lc_assertion_build::lit_staking::build(&self.req), Assertion::EVMAmountHolding(token_type) => lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( &self.req, token_type, diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs index 8d84d430b3..8b2129526a 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs @@ -99,6 +99,8 @@ where Assertion::WeirdoGhostGangHolder => lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build(&self.req), + Assertion::LITStaking => lc_assertion_build::lit_staking::build(&self.req), + Assertion::EVMAmountHolding(token_type) => lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( &self.req, token_type, diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index db68fb6a9a..d6da902c89 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -287,6 +287,7 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::GenericDiscordRole(_) => "GenericDiscordRole", Assertion::VIP3MembershipCard(..) => "VIP3MembershipCard", Assertion::WeirdoGhostGangHolder => "WeirdoGhostGangHolder", + Assertion::LITStaking => "LITStaking", Assertion::EVMAmountHolding(_) => "EVMAmountHolding", }, }; From ef09e0f4ea6a3093db02e0d88ae08a67008b5116 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Wed, 20 Dec 2023 01:46:44 +0100 Subject: [PATCH 14/43] Use public getter for IDGraphHash (#2345) * initial impl * add specific error * fix ts-tests * more refactoring * fix clippy * update cargo lock * update some crates * bring back hashes in events --- Cargo.lock | 153 ++++++++++-------- .../identity-management/src/benchmarking.rs | 18 +-- pallets/identity-management/src/lib.rs | 36 ----- pallets/identity-management/src/mock.rs | 1 - pallets/identity-management/src/weights.rs | 27 ---- precompiles/utils/Cargo.toml | 2 +- runtime/rococo/src/lib.rs | 6 +- .../src/weights/pallet_identity_management.rs | 14 -- tee-worker/app-libs/stf/src/getter.rs | 8 +- tee-worker/app-libs/stf/src/trusted_call.rs | 33 +--- .../app-libs/stf/src/trusted_call_litentry.rs | 10 +- ...dump_id_graph_hash.rs => id_graph_hash.rs} | 28 ++-- .../cli/src/base_cli/commands/litentry/mod.rs | 2 +- tee-worker/cli/src/base_cli/mod.rs | 8 +- .../interfaces/sidechain/definitions.ts | 3 + .../stf-primitives/src/error.rs | 2 + .../core/rpc-client/src/direct_client.rs | 8 +- tee-worker/core/rpc-client/src/mock.rs | 2 +- .../pallets/identity-management/src/lib.rs | 17 +- .../pallets/identity-management/src/tests.rs | 26 +-- .../integration-tests/common/di-utils.ts | 60 ++++--- .../common/utils/assertion.ts | 32 ++-- .../di_bitcoin_identity.test.ts | 43 +++-- .../integration-tests/di_evm_identity.test.ts | 41 +++-- .../di_substrate_identity.test.ts | 130 +++++++++------ .../ts-tests/integration-tests/di_vc.test.ts | 17 +- .../integration-tests/ii_batch.test.ts | 11 +- .../integration-tests/ii_identity.test.ts | 44 +++-- 28 files changed, 406 insertions(+), 376 deletions(-) rename tee-worker/cli/src/base_cli/commands/litentry/{dump_id_graph_hash.rs => id_graph_hash.rs} (53%) diff --git a/Cargo.lock b/Cargo.lock index c52c84a425..3e6817f4d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,7 +445,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -456,7 +456,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -1058,7 +1058,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -1729,10 +1729,10 @@ name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2045,7 +2045,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2062,7 +2062,7 @@ checksum = "b8fcfa71f66c8563c4fa9dd2bb68368d50267856f831ac5d85367e0805f9606c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2340,7 +2340,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2533,7 +2533,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2544,7 +2544,7 @@ checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2844,7 +2844,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -2892,7 +2892,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -3358,10 +3358,10 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -3476,7 +3476,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -3485,10 +3485,10 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -3498,7 +3498,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -3665,7 +3665,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -4493,7 +4493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" dependencies = [ "heck", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -5421,7 +5421,7 @@ version = "0.9.12" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -6179,7 +6179,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", @@ -6497,10 +6497,10 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -6598,7 +6598,7 @@ dependencies = [ "expander 0.0.6", "itertools", "petgraph", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -7848,10 +7848,10 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -8194,9 +8194,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.4" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -8209,11 +8209,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.4" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.1", "proc-macro2", "quote", "syn 1.0.109", @@ -8369,7 +8369,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -8410,7 +8410,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -9734,7 +9734,7 @@ dependencies = [ "proc-macro2", "quote", "sha3", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -9814,7 +9814,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.14", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -9849,7 +9859,7 @@ checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -10245,7 +10255,7 @@ checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -11020,10 +11030,10 @@ name = "sc-chain-spec-derive" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -11996,10 +12006,10 @@ name = "sc-tracing-proc-macro" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -12078,7 +12088,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -12285,7 +12295,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -12479,9 +12489,9 @@ dependencies = [ [[package]] name = "similar-asserts" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18" +checksum = "e041bb827d1bfca18f213411d51b665309f1afb37a04a5d1464530e13779fc0f" dependencies = [ "console", "similar", @@ -12623,10 +12633,10 @@ dependencies = [ "Inflector", "blake2", "expander 1.0.0", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -12868,7 +12878,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -12887,7 +12897,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -13095,10 +13105,10 @@ version = "6.0.0" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -13266,7 +13276,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -13459,7 +13469,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -13644,9 +13654,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -13770,7 +13780,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -13939,7 +13949,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -13998,7 +14008,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.14", ] [[package]] @@ -14023,6 +14033,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -14085,7 +14106,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -14125,10 +14146,10 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "expander 2.0.0", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -14575,7 +14596,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", "wasm-bindgen-shared", ] @@ -14609,7 +14630,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -15683,7 +15704,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] @@ -15791,7 +15812,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.41", ] [[package]] diff --git a/pallets/identity-management/src/benchmarking.rs b/pallets/identity-management/src/benchmarking.rs index d57bc5ed1a..5f62296215 100644 --- a/pallets/identity-management/src/benchmarking.rs +++ b/pallets/identity-management/src/benchmarking.rs @@ -93,21 +93,11 @@ benchmarks! { assert_last_event::(Event::ActivateIdentityRequested{ shard }.into()); } - update_id_graph_hash { - let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); - let new_hash = H256::default(); - let req_ext_hash = H256::default(); - }: _(call_origin, account.clone(), new_hash, req_ext_hash) - verify { - assert_last_event::(Event::IDGraphHashUpdated { account, new_hash, req_ext_hash }.into()) - } - // Benchmark `identity_linked`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. identity_linked { - let req_ext_hash = H256::default(); let id_graph_hash = H256::default(); + let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) @@ -118,8 +108,8 @@ benchmarks! { // Benchmark `identity_deactivated`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. identity_deactivated { - let req_ext_hash = H256::default(); let id_graph_hash = H256::default(); + let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) @@ -130,8 +120,8 @@ benchmarks! { // Benchmark `identity_activated`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. identity_activated { - let req_ext_hash = H256::default(); let id_graph_hash = H256::default(); + let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) @@ -142,8 +132,8 @@ benchmarks! { // Benchmark `identity_networks_set`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. identity_networks_set { - let req_ext_hash = H256::default(); let id_graph_hash = H256::default(); + let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) diff --git a/pallets/identity-management/src/lib.rs b/pallets/identity-management/src/lib.rs index d136f462bb..634941d924 100644 --- a/pallets/identity-management/src/lib.rs +++ b/pallets/identity-management/src/lib.rs @@ -67,8 +67,6 @@ pub mod pallet { type DelegateeAdminOrigin: EnsureOrigin; // origin that is allowed to call extrinsics type ExtrinsicWhitelistOrigin: EnsureOrigin; - // dedicated origin to update the IDGraph hash - type UpdateIDGraphHashOrigin: EnsureOrigin; } #[pallet::event] @@ -141,11 +139,6 @@ pub mod pallet { detail: ErrorDetail, req_ext_hash: H256, }, - IDGraphHashUpdated { - account: T::AccountId, - new_hash: H256, - req_ext_hash: H256, - }, } // delegatees who can send extrinsics(currently only `link_identity`) on users' behalf @@ -153,12 +146,6 @@ pub mod pallet { #[pallet::getter(fn delegatee)] pub type Delegatee = StorageMap<_, Blake2_128Concat, T::AccountId, (), OptionQuery>; - // idgraph hashes so that the client can detect out-of-sync local IDGraph - #[pallet::storage] - #[pallet::getter(fn id_graph_hash)] - pub type IDGraphHash = - StorageMap<_, Blake2_128Concat, T::AccountId, H256, OptionQuery>; - #[pallet::error] pub enum Error { /// a delegatee doesn't exist @@ -253,25 +240,6 @@ pub mod pallet { Ok(().into()) } - /// Update the id_graph hash explicitly - /// Each IDGraph mutation event includes the `id_graph_hash` already, however, - /// there might still be situations where we need to call this fn explicitly, - /// e.g. when populating the hashes for the existing IDGraphs for the first time. - #[pallet::call_index(6)] - #[pallet::weight(::WeightInfo::update_id_graph_hash())] - pub fn update_id_graph_hash( - origin: OriginFor, - account: T::AccountId, - new_hash: H256, - req_ext_hash: H256, - ) -> DispatchResultWithPostInfo { - let _ = T::UpdateIDGraphHashOrigin::ensure_origin(origin)?; - // we don't care if `account` already exists - IDGraphHash::::insert(account.clone(), new_hash); - Self::deposit_event(Event::IDGraphHashUpdated { account, new_hash, req_ext_hash }); - Ok(Pays::No.into()) - } - /// --------------------------------------------------- /// The following extrinsics are supposed to be called by TEE only /// --------------------------------------------------- @@ -284,7 +252,6 @@ pub mod pallet { req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - IDGraphHash::::insert(account.clone(), id_graph_hash); Self::deposit_event(Event::IdentityLinked { account, id_graph_hash, req_ext_hash }); Ok(Pays::No.into()) } @@ -298,7 +265,6 @@ pub mod pallet { req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - IDGraphHash::::insert(account.clone(), id_graph_hash); Self::deposit_event(Event::IdentityDeactivated { account, id_graph_hash, @@ -316,7 +282,6 @@ pub mod pallet { req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - IDGraphHash::::insert(account.clone(), id_graph_hash); Self::deposit_event(Event::IdentityActivated { account, id_graph_hash, req_ext_hash }); Ok(Pays::No.into()) } @@ -330,7 +295,6 @@ pub mod pallet { req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - IDGraphHash::::insert(account.clone(), id_graph_hash); Self::deposit_event(Event::IdentityNetworksSet { account, id_graph_hash, diff --git a/pallets/identity-management/src/mock.rs b/pallets/identity-management/src/mock.rs index 49caeb75ec..ba1f914b68 100644 --- a/pallets/identity-management/src/mock.rs +++ b/pallets/identity-management/src/mock.rs @@ -168,7 +168,6 @@ impl pallet_identity_management::Config for Test { type TEECallOrigin = EnsureEnclaveSigner; type DelegateeAdminOrigin = EnsureRoot; type ExtrinsicWhitelistOrigin = IMPExtrinsicWhitelist; - type UpdateIDGraphHashOrigin = EnsureEnclaveSigner; } impl pallet_group::Config for Test { diff --git a/pallets/identity-management/src/weights.rs b/pallets/identity-management/src/weights.rs index a6567a164e..706ae3e421 100644 --- a/pallets/identity-management/src/weights.rs +++ b/pallets/identity-management/src/weights.rs @@ -55,7 +55,6 @@ pub trait WeightInfo { fn link_identity() -> Weight; fn deactivate_identity() -> Weight; fn activate_identity() -> Weight; - fn update_id_graph_hash() -> Weight; fn identity_linked() -> Weight; fn identity_deactivated() -> Weight; fn identity_activated() -> Weight; @@ -121,19 +120,6 @@ impl WeightInfo for LitentryWeight { /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) /// Storage: IdentityManagement IDGraphHash (r:0 w:1) /// Proof: IdentityManagement IDGraphHash (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) - fn update_id_graph_hash() -> Weight { - // Proof Size summary in bytes: - // Measured: `255` - // Estimated: `3720` - // Minimum execution time: 22_016_000 picoseconds. - Weight::from_parts(22_404_000, 3720) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: IdentityManagement IDGraphHash (r:0 w:1) - /// Proof: IdentityManagement IDGraphHash (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn identity_linked() -> Weight { // Proof Size summary in bytes: // Measured: `255` @@ -251,19 +237,6 @@ impl WeightInfo for () { /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) /// Storage: IdentityManagement IDGraphHash (r:0 w:1) /// Proof: IdentityManagement IDGraphHash (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) - fn update_id_graph_hash() -> Weight { - // Proof Size summary in bytes: - // Measured: `255` - // Estimated: `3720` - // Minimum execution time: 22_016_000 picoseconds. - Weight::from_parts(22_404_000, 3720) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: IdentityManagement IDGraphHash (r:0 w:1) - /// Proof: IdentityManagement IDGraphHash (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn identity_linked() -> Weight { // Proof Size summary in bytes: // Measured: `255` diff --git a/precompiles/utils/Cargo.toml b/precompiles/utils/Cargo.toml index 309b7030d5..c2dba34af5 100644 --- a/precompiles/utils/Cargo.toml +++ b/precompiles/utils/Cargo.toml @@ -11,7 +11,7 @@ impl-trait-for-tuples = "0.2.2" log = { version = "0.4", default-features = false } num_enum = { version = "0.6.1", default-features = false } sha3 = { version = "0.10", default-features = false } -similar-asserts = { version = "1.1.0", optional = true } +similar-asserts = { version = "1.5.0", optional = true } precompile-utils-macro = { path = "macro" } diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index efedaf29de..45749675a2 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -28,9 +28,8 @@ use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ construct_runtime, ord_parameter_types, parameter_types, traits::{ - ConstU128, ConstU32, ConstU64, ConstU8, Contains, ContainsLengthBound, EitherOfDiverse, - EnsureOrigin, Everything, FindAuthor, InstanceFilter, OnFinalize, SortedMembers, - WithdrawReasons, + ConstU128, ConstU32, ConstU64, ConstU8, Contains, ContainsLengthBound, EnsureOrigin, + Everything, FindAuthor, InstanceFilter, OnFinalize, SortedMembers, WithdrawReasons, }, weights::{constants::RocksDbWeight, ConstantMultiplier, IdentityFee, Weight}, ConsensusEngineId, PalletId, RuntimeDebug, @@ -1027,7 +1026,6 @@ impl pallet_identity_management::Config for Runtime { type TEECallOrigin = EnsureEnclaveSigner; type DelegateeAdminOrigin = EnsureRootOrAllCouncil; type ExtrinsicWhitelistOrigin = IMPExtrinsicWhitelist; - type UpdateIDGraphHashOrigin = EitherOfDiverse; } impl pallet_group::Config for Runtime { diff --git a/runtime/rococo/src/weights/pallet_identity_management.rs b/runtime/rococo/src/weights/pallet_identity_management.rs index ea1cb3f73b..bbe38fdeb7 100644 --- a/runtime/rococo/src/weights/pallet_identity_management.rs +++ b/runtime/rococo/src/weights/pallet_identity_management.rs @@ -160,18 +160,4 @@ impl pallet_identity_management::WeightInfo for WeightI .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(1)) } - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: IdentityManagement IDGraphHash (r:0 w:1) - /// Proof: IdentityManagement IDGraphHash (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) - fn update_id_graph_hash() -> Weight { - // Proof Size summary in bytes: - // Measured: `255` - // Estimated: `3720` - // Minimum execution time: 22_335_000 picoseconds. - Weight::from_parts(22_875_000, 0) - .saturating_add(Weight::from_parts(0, 3720)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } } diff --git a/tee-worker/app-libs/stf/src/getter.rs b/tee-worker/app-libs/stf/src/getter.rs index eb8680e6a3..d2ccec900a 100644 --- a/tee-worker/app-libs/stf/src/getter.rs +++ b/tee-worker/app-libs/stf/src/getter.rs @@ -100,7 +100,7 @@ pub enum PublicGetter { #[codec(index = 1)] nonce(Identity), #[codec(index = 2)] - all_id_graph_hash, + id_graph_hash(Identity), } #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] @@ -250,7 +250,7 @@ impl ExecuteGetter for TrustedGetterSigned { None }, // litentry - TrustedGetter::id_graph(who) => Some(IdentityManagement::get_id_graph(&who).encode()), + TrustedGetter::id_graph(who) => Some(IdentityManagement::id_graph(&who).encode()), // TODO: we need to re-think it // currently, _who is ignored meaning it's actually not a "trusted" getter. @@ -280,8 +280,8 @@ impl ExecuteGetter for PublicGetter { } else { None }, - PublicGetter::all_id_graph_hash => - Some(IdentityManagement::all_id_graph_hash().encode()), + PublicGetter::id_graph_hash(identity) => + IdentityManagement::id_graph_hash(&identity).map(|h| h.encode()), } } diff --git a/tee-worker/app-libs/stf/src/trusted_call.rs b/tee-worker/app-libs/stf/src/trusted_call.rs index 12a579dbd5..30e8522608 100644 --- a/tee-worker/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/app-libs/stf/src/trusted_call.rs @@ -759,9 +759,9 @@ where e })?; - debug!("pushing identity_deactivated event ..."); - let id_graph_hash: H256 = blake2_256(&IMT::get_id_graph(&who).encode()).into(); + let id_graph_hash: H256 = IMT::id_graph_hash(&who).ok_or(StfError::EmptyIDGraph)?; + debug!("pushing identity_deactivated event ..."); calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, account, @@ -810,8 +810,9 @@ where e })?; + let id_graph_hash: H256 = IMT::id_graph_hash(&who).ok_or(StfError::EmptyIDGraph)?; + debug!("pushing identity_activated event ..."); - let id_graph_hash: H256 = blake2_256(&IMT::get_id_graph(&who).encode()).into(); calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, account, @@ -970,8 +971,9 @@ where .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) .map_err(|e| Self::Error::Dispatch(format!(" error: {:?}", e.error)))?; + let id_graph_hash: H256 = IMT::id_graph_hash(&who).ok_or(StfError::EmptyIDGraph)?; + debug!("pushing identity_networks_set event ..."); - let id_graph_hash: H256 = blake2_256(&IMT::get_id_graph(&who).encode()).into(); calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, account, @@ -1162,29 +1164,6 @@ pub fn push_call_vcmp_some_error( } } -pub fn push_call_imp_update_id_graph_hash( - calls: &mut Vec, - node_metadata_repo: Arc, - account: ParentchainAccountId, - id_graph_hash: H256, - req_ext_hash: H256, -) where - NodeMetadataRepository: AccessNodeMetadata, - NodeMetadataRepository::MetadataType: NodeMetadataTrait, -{ - debug!("pushing IMP::update_id_graph_hash call ..."); - match node_metadata_repo.get_from_metadata(|m| m.update_id_graph_hash_call_indexes()) { - Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( - call_index, - account, - id_graph_hash, - req_ext_hash, - )))), - Ok(e) => warn!("error getting IMP::update_id_graph_hash call indexes: {:?}", e), - Err(e) => warn!("error getting IMP::update_id_graph_hash call indexes: {:?}", e), - } -} - #[cfg(test)] mod tests { use super::*; 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 1798062957..a265cc00b2 100644 --- a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs +++ b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs @@ -44,7 +44,6 @@ use litentry_primitives::{ Web3Network, }; use log::*; -use sp_core::blake2_256; use std::{sync::Arc, vec::Vec}; #[cfg(not(feature = "production"))] @@ -169,7 +168,7 @@ impl TrustedCallSigned { ), } - let id_graph = IMT::get_id_graph(&who); + let id_graph = IMT::id_graph(&who); let assertion_networks = assertion.get_supported_web3networks(); let identities: Vec = id_graph .into_iter() @@ -283,10 +282,9 @@ impl TrustedCallSigned { e })?; - debug!("pushing identity_linked event ..."); - let id_graph = IMT::get_id_graph(&who); - let id_graph_hash: H256 = blake2_256(&id_graph.encode()).into(); + let id_graph_hash: H256 = IMT::id_graph_hash(&who).ok_or(StfError::EmptyIDGraph)?; + debug!("pushing identity_linked event ..."); // push `identity_linked` call let call_index = node_metadata_repo.get_from_metadata(|m| m.identity_linked_call_indexes())??; @@ -298,7 +296,7 @@ impl TrustedCallSigned { )))); if old_id_graph_len == 0 { - mutated_id_graph = id_graph; + mutated_id_graph = IMT::id_graph(&who); } else if let Some(identity_context) = IMT::id_graphs(&who, &identity) { mutated_id_graph.push((identity, identity_context)) } else { diff --git a/tee-worker/cli/src/base_cli/commands/litentry/dump_id_graph_hash.rs b/tee-worker/cli/src/base_cli/commands/litentry/id_graph_hash.rs similarity index 53% rename from tee-worker/cli/src/base_cli/commands/litentry/dump_id_graph_hash.rs rename to tee-worker/cli/src/base_cli/commands/litentry/id_graph_hash.rs index d4e25c9119..9abf282b20 100644 --- a/tee-worker/cli/src/base_cli/commands/litentry/dump_id_graph_hash.rs +++ b/tee-worker/cli/src/base_cli/commands/litentry/id_graph_hash.rs @@ -18,32 +18,26 @@ use crate::{command_utils::get_worker_api_direct, Cli, CliResult, CliResultOk}; use codec::Decode; use itc_rpc_client::direct_client::DirectApi; use itp_types::ShardIdentifier; -use itp_utils::ToHexPrefixed; +use litentry_primitives::Identity; -// usage: ./bin/litentry-cli dump-id-graph-hash +// usage: ./bin/litentry-cli id-graph-hash did-identity // -// this command prints a list of (AccountId32, H256) collections which represent the IDGraph owner and hash, respectively -// example result: -// ``` -// 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d, 0xd47cd39a19bc0094a4ec6ebf147cd1bde820e8d07574df02505607ec53c39ceb -// 0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48, 0x6fd466064ab4aa8eeae19e0ddc25a99fefd3bf326caef98cf0c24b6467805f9d -// ``` -// please note the evm address is converted to substrate account to faciliate the population of on-chain storage, -// as the parachain extrinsic `update_id_graph_hash` expects a T::AccountId, same as other extrinsic callbacks +// this command prints the id graph hash of the given identity in did form #[derive(Parser)] -pub struct DumpIDGraphHashCommand {} +pub struct IDGraphHashCommand { + /// identity to query, in did form + did: String, +} -impl DumpIDGraphHashCommand { +impl IDGraphHashCommand { pub(crate) fn run(&self, cli: &Cli) -> CliResult { let direct_api = get_worker_api_direct(cli); let mrenclave = direct_api.get_state_mrenclave().unwrap(); let shard = ShardIdentifier::decode(&mut &mrenclave[..]).unwrap(); - let id_graph_hash = direct_api.get_all_id_graph_hash(&shard).unwrap(); - - id_graph_hash.iter().for_each(|(identity, hash)| { - println!("{}, {:?}", identity.to_account_id().unwrap().to_hex(), hash) - }); + let identity = Identity::from_did(self.did.as_str()).unwrap(); + let id_graph_hash = direct_api.get_id_graph_hash(&shard, &identity).unwrap(); + println!("{:?}", id_graph_hash); Ok(CliResultOk::None) } diff --git a/tee-worker/cli/src/base_cli/commands/litentry/mod.rs b/tee-worker/cli/src/base_cli/commands/litentry/mod.rs index 26e784e28e..820e551764 100644 --- a/tee-worker/cli/src/base_cli/commands/litentry/mod.rs +++ b/tee-worker/cli/src/base_cli/commands/litentry/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -pub mod dump_id_graph_hash; +pub mod id_graph_hash; pub mod link_identity; pub mod set_heartbeat_timeout; diff --git a/tee-worker/cli/src/base_cli/mod.rs b/tee-worker/cli/src/base_cli/mod.rs index c825c74bca..7270dd8dbb 100644 --- a/tee-worker/cli/src/base_cli/mod.rs +++ b/tee-worker/cli/src/base_cli/mod.rs @@ -21,7 +21,7 @@ use crate::{ faucet::FaucetCommand, listen::ListenCommand, litentry::{ - dump_id_graph_hash::DumpIDGraphHashCommand, link_identity::LinkIdentityCommand, + id_graph_hash::IDGraphHashCommand, link_identity::LinkIdentityCommand, set_heartbeat_timeout::SetHeartbeatTimeoutCommand, }, register_tcb_info::RegisterTcbInfoCommand, @@ -93,8 +93,8 @@ pub enum BaseCommand { /// set heartbeat timeout storage SetHeartbeatTimeout(SetHeartbeatTimeoutCommand), - /// dump all IDGraph hashes stored in sidechain - DumpIDGraphHash(DumpIDGraphHashCommand), + /// get the IDGraph hash of the given identity + IDGraphHash(IDGraphHashCommand), } impl BaseCommand { @@ -115,7 +115,7 @@ impl BaseCommand { BaseCommand::PrintSgxMetadataRaw => print_sgx_metadata_raw(cli), BaseCommand::LinkIdentity(cmd) => cmd.run(cli), BaseCommand::SetHeartbeatTimeout(cmd) => cmd.run(cli), - BaseCommand::DumpIDGraphHash(cmd) => cmd.run(cli), + BaseCommand::IDGraphHash(cmd) => cmd.run(cli), } } } diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts index ccd7f115f4..51f11ae57f 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts @@ -37,6 +37,7 @@ export default { _enum: { some_value: "u32", nonce: "(LitentryIdentity)", + id_graph_hash: "(LitentryIdentity)", }, }, @@ -58,6 +59,8 @@ export default { SetIdentityNetworksFailed: "(ErrorDetail)", InvalidAccount: "Null", UnclassifiedError: "Null", + RemoveIdentityFailed: "(ErrorDetail)", + EmptyIDGraph: "Null", }, }, ErrorDetail: { diff --git a/tee-worker/core-primitives/stf-primitives/src/error.rs b/tee-worker/core-primitives/stf-primitives/src/error.rs index c222ea0a1b..c69514f109 100644 --- a/tee-worker/core-primitives/stf-primitives/src/error.rs +++ b/tee-worker/core-primitives/stf-primitives/src/error.rs @@ -70,6 +70,8 @@ pub enum StfError { #[codec(index = 16)] #[display(fmt = "RemovingIdentityFailed: {:?}", _0)] RemoveIdentityFailed(ErrorDetail), + #[codec(index = 17)] + EmptyIDGraph, } impl From for StfError { diff --git a/tee-worker/core/rpc-client/src/direct_client.rs b/tee-worker/core/rpc-client/src/direct_client.rs index 274e9d1061..7814b0e7e3 100644 --- a/tee-worker/core/rpc-client/src/direct_client.rs +++ b/tee-worker/core/rpc-client/src/direct_client.rs @@ -65,7 +65,7 @@ pub trait DirectApi { fn get_state_metadata_raw(&self) -> Result; fn get_next_nonce(&self, shard: &ShardIdentifier, account: &AccountId) -> Result; fn get_state_mrenclave(&self) -> Result; - fn get_all_id_graph_hash(&self, shard: &ShardIdentifier) -> Result>; + fn get_id_graph_hash(&self, shard: &ShardIdentifier, identity: &Identity) -> Result; } impl DirectClient { @@ -264,11 +264,11 @@ impl DirectApi for DirectClient { Ok(mrenclave) } - fn get_all_id_graph_hash(&self, shard: &ShardIdentifier) -> Result> { - let getter = Getter::public(PublicGetter::all_id_graph_hash); + fn get_id_graph_hash(&self, shard: &ShardIdentifier, identity: &Identity) -> Result { + let getter = Getter::public(PublicGetter::id_graph_hash(identity.clone())); self.get_state(*shard, &getter) .ok_or_else(|| Error::Status("failed to get state".to_string())) - .and_then(|v| Vec::<(Identity, H256)>::decode(&mut v.as_slice()).map_err(Error::Codec)) + .and_then(|v| H256::decode(&mut v.as_slice()).map_err(Error::Codec)) } } diff --git a/tee-worker/core/rpc-client/src/mock.rs b/tee-worker/core/rpc-client/src/mock.rs index f0e09625ac..a76851931a 100644 --- a/tee-worker/core/rpc-client/src/mock.rs +++ b/tee-worker/core/rpc-client/src/mock.rs @@ -120,7 +120,7 @@ impl DirectApi for DirectClientMock { unimplemented!() } - fn get_all_id_graph_hash(&self, _shard: &ShardIdentifier) -> Result> { + fn get_id_graph_hash(&self, shard: &ShardIdentifier, identity: &Identity) -> Result { unimplemented!() } } diff --git a/tee-worker/litentry/pallets/identity-management/src/lib.rs b/tee-worker/litentry/pallets/identity-management/src/lib.rs index a20a200e15..256781f5c3 100644 --- a/tee-worker/litentry/pallets/identity-management/src/lib.rs +++ b/tee-worker/litentry/pallets/identity-management/src/lib.rs @@ -295,7 +295,10 @@ pub mod pallet { } // get the whole IDGraph, sorted by `link_block` (earliest -> latest) - pub fn get_id_graph(who: &Identity) -> IDGraph { + // + // TODO: shall we change the return type to Option> and return + // `None` if the IDGraph doesn't exist? + pub fn id_graph(who: &Identity) -> IDGraph { let mut id_graph = IDGraphs::iter_prefix(who).collect::>(); // Initial sort to ensure a deterministic order @@ -304,10 +307,14 @@ pub mod pallet { id_graph } - pub fn all_id_graph_hash() -> Vec<(Identity, H256)> { - IDGraphLens::::iter_keys() - .map(|k| (k.clone(), H256::from(blake2_256(&Self::get_id_graph(&k).encode())))) - .collect() + // get the IDGraph hash of the given `who` + pub fn id_graph_hash(who: &Identity) -> Option { + let id_graph = Self::id_graph(who); + if id_graph.is_empty() { + None + } else { + Some(H256::from(blake2_256(&id_graph.encode()))) + } } // get count of all keys account + identity in the IDGraphs diff --git a/tee-worker/litentry/pallets/identity-management/src/tests.rs b/tee-worker/litentry/pallets/identity-management/src/tests.rs index 717fdf05af..63dfca243c 100644 --- a/tee-worker/litentry/pallets/identity-management/src/tests.rs +++ b/tee-worker/litentry/pallets/identity-management/src/tests.rs @@ -238,7 +238,7 @@ fn deactivate_identity_works() { } ); - let id_graph = IMT::get_id_graph(&who.clone()); + let id_graph = IMT::id_graph(&who.clone()); assert_eq!(id_graph.len(), 2); assert_eq!(crate::IDGraphLens::::get(&who.clone()), 2); @@ -256,13 +256,13 @@ fn deactivate_identity_works() { } ); - let id_graph = IMT::get_id_graph(&who.clone()) + let id_graph = IMT::id_graph(&who.clone()) .into_iter() .filter(|(_, c)| c.is_active()) .collect::>(); // "1": because of the main id is added by default when first calling link_identity. assert_eq!(id_graph.len(), 1); - assert_eq!(IMT::get_id_graph(&who.clone()).len(), 2); + assert_eq!(IMT::id_graph(&who.clone()).len(), 2); // identity is only deactivated, so it still exists assert_eq!(crate::IDGraphLens::::get(&who.clone()), 2); @@ -296,7 +296,7 @@ fn activate_identity_works() { status: IdentityStatus::Active } ); - let id_graph = IMT::get_id_graph(&who.clone()); + let id_graph = IMT::id_graph(&who.clone()); assert_eq!(id_graph.len(), 2); assert_eq!(crate::IDGraphLens::::get(&who.clone()), 2); @@ -313,7 +313,7 @@ fn activate_identity_works() { status: IdentityStatus::Inactive } ); - let id_graph = IMT::get_id_graph(&who.clone()) + let id_graph = IMT::id_graph(&who.clone()) .into_iter() .filter(|(_, c)| c.is_active()) .collect::>(); @@ -328,7 +328,7 @@ fn activate_identity_works() { alice_substrate_identity(), )); - let id_graph = IMT::get_id_graph(&who.clone()); + let id_graph = IMT::id_graph(&who.clone()); assert_eq!(id_graph.len(), 2); assert_eq!(crate::IDGraphLens::::get(&who.clone()), 2); }); @@ -418,7 +418,7 @@ fn get_id_graph_works() { )); } // the full id_graph should have 22 elements, including the prime_id - let id_graph = IMT::get_id_graph(&who); + let id_graph = IMT::id_graph(&who); assert_eq!(id_graph.len(), 22); assert_eq!(id_graph.get(0).unwrap().0, who); @@ -450,7 +450,7 @@ fn get_id_graph_identities_within_same_block() { )); } - let id_graph = IMT::get_id_graph(&who); + let id_graph = IMT::id_graph(&who); let sorted_identities = [ alice_evm_identity(), who.clone(), @@ -483,7 +483,7 @@ fn get_id_graph_identities_within_same_block() { )); } - let id_graph = IMT::get_id_graph(&who); + let id_graph = IMT::id_graph(&who); for (i, identity) in sorted_identities.iter().enumerate() { assert_eq!(&id_graph.get(i).unwrap().0, identity); @@ -535,7 +535,7 @@ fn remove_one_identity_works() { // alice's IDGraph should have 3 entries: // alice's identity itself, bob_substrate_identity, alice_twitter_identity - assert_eq!(IMT::get_id_graph(&alice).len(), 3); + assert_eq!(IMT::id_graph(&alice).len(), 3); assert_ok!(IMT::remove_identity( RuntimeOrigin::signed(ALICE), @@ -543,7 +543,7 @@ fn remove_one_identity_works() { vec![bob_substrate_identity()], )); - assert_eq!(IMT::get_id_graph(&alice).len(), 2); + assert_eq!(IMT::id_graph(&alice).len(), 2); }); } @@ -566,11 +566,11 @@ fn remove_whole_identity_graph_works() { // alice's IDGraph should have 3 entries: // alice's identity itself, bob_substrate_identity, alice_twitter_identity - assert_eq!(IMT::get_id_graph(&alice).len(), 3); + assert_eq!(IMT::id_graph(&alice).len(), 3); assert_ok!(IMT::remove_identity(RuntimeOrigin::signed(ALICE), alice.clone(), vec![],)); - assert_eq!(IMT::get_id_graph(&alice).len(), 0); + assert_eq!(IMT::id_graph(&alice).len(), 0); }); } diff --git a/tee-worker/ts-tests/integration-tests/common/di-utils.ts b/tee-worker/ts-tests/integration-tests/common/di-utils.ts index 1f4185498f..69e959a750 100644 --- a/tee-worker/ts-tests/integration-tests/common/di-utils.ts +++ b/tee-worker/ts-tests/integration-tests/common/di-utils.ts @@ -9,8 +9,7 @@ import { encryptWithTeeShieldingKey, Signer, encryptWithAes } from './utils'; import { aesKey, decodeRpcBytesAsString, keyNonce } from './call'; import { createPublicKey, KeyObject } from 'crypto'; import WebSocketAsPromised from 'websocket-as-promised'; -import { u32, Option, u8, Vector } from 'scale-ts'; -import { Index } from '@polkadot/types/interfaces'; +import { H256, Index } from '@polkadot/types/interfaces'; import { blake2AsHex } from '@polkadot/util-crypto'; import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import { createJsonRpcRequest, nextRequestId } from './helpers'; @@ -159,7 +158,7 @@ export async function createSignedTrustedCallLinkIdentity( mrenclave: string, nonce: Codec, signer: Signer, - subject: LitentryPrimitivesIdentity, + primeIdentity: LitentryPrimitivesIdentity, identity: string, validationData: string, web3networks: string, @@ -175,7 +174,7 @@ export async function createSignedTrustedCallLinkIdentity( signer, mrenclave, nonce, - [subject.toHuman(), subject.toHuman(), identity, validationData, web3networks, aesKey, hash] + [primeIdentity.toHuman(), primeIdentity.toHuman(), identity, validationData, web3networks, aesKey, hash] ); } @@ -184,7 +183,7 @@ export async function createSignedTrustedCallSetIdentityNetworks( mrenclave: string, nonce: Codec, signer: Signer, - subject: LitentryPrimitivesIdentity, + primeIdentity: LitentryPrimitivesIdentity, identity: string, web3networks: string, aesKey: string, @@ -199,7 +198,7 @@ export async function createSignedTrustedCallSetIdentityNetworks( signer, mrenclave, nonce, - [subject.toHuman(), subject.toHuman(), identity, web3networks, aesKey, hash] + [primeIdentity.toHuman(), primeIdentity.toHuman(), identity, web3networks, aesKey, hash] ); } @@ -208,7 +207,7 @@ export async function createSignedTrustedCallRequestVc( mrenclave: string, nonce: Codec, signer: Signer, - subject: LitentryPrimitivesIdentity, + primeIdentity: LitentryPrimitivesIdentity, assertion: string, aesKey: string, hash: string @@ -219,7 +218,7 @@ export async function createSignedTrustedCallRequestVc( signer, mrenclave, nonce, - [subject.toHuman(), subject.toHuman(), assertion, aesKey, hash] + [primeIdentity.toHuman(), primeIdentity.toHuman(), assertion, aesKey, hash] ); } export async function createSignedTrustedCallDeactivateIdentity( @@ -227,7 +226,7 @@ export async function createSignedTrustedCallDeactivateIdentity( mrenclave: string, nonce: Codec, signer: Signer, - subject: LitentryPrimitivesIdentity, + primeIdentity: LitentryPrimitivesIdentity, identity: string, aesKey: string, hash: string @@ -238,7 +237,7 @@ export async function createSignedTrustedCallDeactivateIdentity( signer, mrenclave, nonce, - [subject.toHuman(), subject.toHuman(), identity, aesKey, hash] + [primeIdentity.toHuman(), primeIdentity.toHuman(), identity, aesKey, hash] ); } export async function createSignedTrustedCallActivateIdentity( @@ -246,7 +245,7 @@ export async function createSignedTrustedCallActivateIdentity( mrenclave: string, nonce: Codec, signer: Signer, - subject: LitentryPrimitivesIdentity, + primeIdentity: LitentryPrimitivesIdentity, identity: string, aesKey: string, hash: string @@ -257,20 +256,20 @@ export async function createSignedTrustedCallActivateIdentity( signer, mrenclave, nonce, - [subject.toHuman(), subject.toHuman(), identity, aesKey, hash] + [primeIdentity.toHuman(), primeIdentity.toHuman(), identity, aesKey, hash] ); } export async function createSignedTrustedGetterIdGraph( parachainApi: ApiPromise, signer: Signer, - subject: LitentryPrimitivesIdentity + primeIdentity: LitentryPrimitivesIdentity ): Promise { const getterSigned = await createSignedTrustedGetter( parachainApi, ['id_graph', '(LitentryIdentity)'], signer, - subject.toHuman() + primeIdentity.toHuman() ); return parachainApi.createType('Getter', { trusted: getterSigned }) as unknown as Getter; // @fixme 1878; } @@ -278,13 +277,29 @@ export async function createSignedTrustedGetterIdGraph( export const getSidechainNonce = async ( context: IntegrationTestContext, teeShieldingKey: KeyObject, - subject: LitentryPrimitivesIdentity + primeIdentity: LitentryPrimitivesIdentity ): Promise => { - const getterPublic = createPublicGetter(context.api, ['nonce', '(LitentryIdentity)'], subject.toHuman()); + const getterPublic = createPublicGetter(context.api, ['nonce', '(LitentryIdentity)'], primeIdentity.toHuman()); const getter = context.api.createType('Getter', { public: getterPublic }) as unknown as Getter; // @fixme 1878 - const nonce = await sendRequestFromGetter(context, teeShieldingKey, getter); - const nonceValue = decodeNonce(nonce.value.toHex()); - return context.api.createType('Index', nonceValue) as Index; + const res = await sendRequestFromGetter(context, teeShieldingKey, getter); + const nonce = context.api.createType('Option', hexToU8a(res.value.toHex())).unwrap(); + return context.api.createType('Index', nonce); +}; + +export const getIdGraphHash = async ( + context: IntegrationTestContext, + teeShieldingKey: KeyObject, + primeIdentity: LitentryPrimitivesIdentity +): Promise => { + const getterPublic = createPublicGetter( + context.api, + ['id_graph_hash', '(LitentryIdentity)'], + primeIdentity.toHuman() + ); + const getter = context.api.createType('Getter', { public: getterPublic }) as unknown as Getter; // @fixme 1878 + const res = await sendRequestFromGetter(context, teeShieldingKey, getter); + const hash = context.api.createType('Option', hexToU8a(res.value.toHex())).unwrap(); + return context.api.createType('H256', hash); }; export const sendRequestFromTrustedCall = async ( @@ -389,13 +404,6 @@ export const createAesRequest = async ( .toU8a(); }; -export function decodeNonce(nonceInHex: string) { - const optionalType = Option(Vector(u8)); - const encodedNonce = optionalType.dec(nonceInHex) as number[]; - const nonce = u32.dec(new Uint8Array(encodedNonce)); - return nonce; -} - export function decodeIdGraph(sidechainRegistry: TypeRegistry, value: Bytes) { const idgraphBytes = sidechainRegistry.createType('Option', hexToU8a(value.toHex())); return sidechainRegistry.createType( diff --git a/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts b/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts index 318ef4725d..cd9aad1cee 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts @@ -8,6 +8,7 @@ import { parseIdGraph, parseIdentity } from './identity-helper'; import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeError } from 'sidechain-api'; import { TeerexPrimitivesEnclave } from 'parachain-api'; import type { IntegrationTestContext } from '../common-types'; +import { getIdGraphHash } from '../di-utils'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; import { jsonSchema } from './vc-helper'; @@ -25,6 +26,7 @@ import { Bytes } from '@polkadot/types-codec'; import { Signer, decryptWithAes } from './crypto'; import { blake2AsHex } from '@polkadot/util-crypto'; import { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; +import { KeyObject } from 'crypto'; export async function assertFailedEvent( context: IntegrationTestContext, @@ -210,7 +212,7 @@ export async function checkJson(vc: any, proofJson: any): Promise { } // for IdGraph mutation, assert the corresponding event is emitted for the given signer and the id_graph_hash matches -export async function assertIdGraphMutation( +export async function assertIdGraphMutationEvent( signer: Signer, events: any[], idGraphHashResults: any[] | undefined, @@ -220,6 +222,7 @@ export async function assertIdGraphMutation( if (idGraphHashResults != undefined) { assert.equal(idGraphHashResults!.length, expectedLength); } + const signerAddress = u8aToHex(signer.getAddressInSubstrateFormat()); events.forEach((e, i) => { assert.equal(signerAddress, e.data.account.toHex()); @@ -227,7 +230,7 @@ export async function assertIdGraphMutation( assert.equal(idGraphHashResults![i], e.data.idGraphHash.toHex()); } }); - console.log(colors.green('assertIdGraphMutation passed')); + console.log(colors.green('assertIdGraphMutationEvent passed')); } export async function assertIdentity( @@ -254,8 +257,10 @@ export function assertWorkerError( // a common assertion for all DI requests that might mutate the IdGraph // returns the `id_graph_hash` in the `returnValue` -export function assertIdGraphMutationResult( +export async function assertIdGraphMutationResult( context: IntegrationTestContext, + teeShieldingKey: KeyObject, + identity: LitentryPrimitivesIdentity, returnValue: WorkerRpcReturnValue, resultType: | 'LinkIdentityResult' @@ -263,12 +268,15 @@ export function assertIdGraphMutationResult( | 'ActivateIdentityResult' | 'SetIdentityNetworksResult', expectedIdGraph: [LitentryPrimitivesIdentity, boolean][] -): HexString { +): Promise { const decodedResult = context.api.createType(resultType, returnValue.value) as any; - assert.isNotNull(decodedResult.mutated_id_graph); const idGraph = parseIdGraph(context.sidechainRegistry, decodedResult.mutated_id_graph, aesKey); assertIdGraph(idGraph, expectedIdGraph); + const queriedIdGraphHash = (await getIdGraphHash(context, teeShieldingKey, identity)).toHex(); + assert.equal(u8aToHex(decodedResult.id_graph_hash), queriedIdGraphHash); + + console.log(colors.green('assertIdGraphMutationResult passed')); return u8aToHex(decodedResult.id_graph_hash); } @@ -366,18 +374,18 @@ export async function assertVc(context: IntegrationTestContext, subject: Litentr export async function assertIdGraphHash( context: IntegrationTestContext, - signer: Signer, + teeShieldingKey: KeyObject, + identity: LitentryPrimitivesIdentity, idGraph: [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] ) { const idGraphType = context.sidechainRegistry.createType( 'Vec<(LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', idGraph ); - const localIdGraphHash = blake2AsHex(idGraphType.toU8a()); - console.log('local id graph hash: ', localIdGraphHash); + const computedIdGraphHash = blake2AsHex(idGraphType.toU8a()); + console.log('computed id graph hash: ', computedIdGraphHash); - const account = u8aToHex(signer.getAddressInSubstrateFormat()); - const onChainIdGraphHash = (await context.api.query.identityManagement.idGraphHash(account)).toHuman(); - console.log('on-chain id graph hash: ', onChainIdGraphHash); - assert.equal(localIdGraphHash, onChainIdGraphHash); + const queriedIdGraphHash = (await getIdGraphHash(context, teeShieldingKey, identity)).toHex(); + console.log('queried id graph hash: ', queriedIdGraphHash); + assert.equal(computedIdGraphHash, queriedIdGraphHash); } diff --git a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts index f6530ee4d3..fe6c5df292 100644 --- a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts @@ -12,7 +12,7 @@ import { assertIdGraphMutationResult, assertIdGraphHash, } from './common/utils'; -import { assertIsInSidechainBlock, assertIdGraphMutation } from './common/utils/assertion'; +import { assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; import { createSignedTrustedCallLinkIdentity, createSignedTrustedGetterIdGraph, @@ -124,7 +124,14 @@ describe('Test Identity (bitcoin direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'LinkIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceBitcoinIdentity, + res, + 'LinkIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('linkIdentityCall', res); @@ -140,7 +147,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new BitcoinSigner(context.bitcoinWallet.alice), identityLinkedEvents, idGraphHashResults, @@ -155,7 +162,6 @@ describe('Test Identity (bitcoin direct invocation)', function () { aliceBitcoinIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); - const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); // according to the order of linkIdentityRequestParams @@ -182,7 +188,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { currentIndex++; } - await assertIdGraphHash(context, new BitcoinSigner(context.bitcoinWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceBitcoinIdentity, idGraph); }); step('deactivating identity(alice bitcoin account)', async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); @@ -220,7 +226,14 @@ describe('Test Identity (bitcoin direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'DeactivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceBitcoinIdentity, + res, + 'DeactivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('deactivateIdentityCall', res); @@ -236,7 +249,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new BitcoinSigner(context.bitcoinWallet.alice), identityDeactivatedEvents, idGraphHashResults, @@ -268,8 +281,9 @@ describe('Test Identity (bitcoin direct invocation)', function () { console.debug('inactive ✅'); } - await assertIdGraphHash(context, new BitcoinSigner(context.bitcoinWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceBitcoinIdentity, idGraph); }); + step('activating identity(alice bitcoin account)', async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); const getNextNonce = () => currentNonce++; @@ -306,7 +320,14 @@ describe('Test Identity (bitcoin direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, activateIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'ActivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceBitcoinIdentity, + res, + 'ActivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('activateIdentityCall', res); @@ -322,7 +343,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new BitcoinSigner(context.bitcoinWallet.alice), identityActivatedEvents, idGraphHashResults, @@ -354,6 +375,6 @@ describe('Test Identity (bitcoin direct invocation)', function () { console.debug('active ✅'); } - await assertIdGraphHash(context, new BitcoinSigner(context.bitcoinWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceBitcoinIdentity, idGraph); }); }); diff --git a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts index 58e18bbd3f..5de294b890 100644 --- a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts @@ -12,7 +12,7 @@ import { assertWorkerError, assertIdGraphHash, } from './common/utils'; -import { assertFailedEvent, assertIsInSidechainBlock, assertIdGraphMutation } from './common/utils/assertion'; +import { assertFailedEvent, assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; import { createSignedTrustedCallLinkIdentity, createSignedTrustedGetterIdGraph, @@ -151,7 +151,14 @@ describe('Test Identity (evm direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'LinkIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceEvmIdentity, + res, + 'LinkIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('linkIdentityCall', res); @@ -167,7 +174,7 @@ describe('Test Identity (evm direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new EthersSigner(context.ethersWallet.alice), identityLinkedEvents, idGraphHashResults, @@ -212,7 +219,7 @@ describe('Test Identity (evm direct invocation)', function () { currentIndex++; } - await assertIdGraphHash(context, new EthersSigner(context.ethersWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceEvmIdentity, idGraph); }); step('deactivating identity(alice evm account)', async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceEvmIdentity)).toNumber(); @@ -264,7 +271,14 @@ describe('Test Identity (evm direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'DeactivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceEvmIdentity, + res, + 'DeactivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('deactivateIdentityCall', res); @@ -280,7 +294,7 @@ describe('Test Identity (evm direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new EthersSigner(context.ethersWallet.alice), identityDeactivatedEvents, idGraphHashResults, @@ -312,7 +326,7 @@ describe('Test Identity (evm direct invocation)', function () { console.debug('inactive ✅'); } - await assertIdGraphHash(context, new EthersSigner(context.ethersWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceEvmIdentity, idGraph); }); step('activating identity(alice evm account)', async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceEvmIdentity)).toNumber(); @@ -364,7 +378,14 @@ describe('Test Identity (evm direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, activateIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'ActivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceEvmIdentity, + res, + 'ActivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('activateIdentityCall', res); @@ -380,7 +401,7 @@ describe('Test Identity (evm direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new EthersSigner(context.ethersWallet.alice), identityActivatedEvents, idGraphHashResults, @@ -412,7 +433,7 @@ describe('Test Identity (evm direct invocation)', function () { console.debug('active ✅'); } - await assertIdGraphHash(context, new EthersSigner(context.ethersWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceEvmIdentity, idGraph); }); step('deactivating prime identity is disallowed', async function () { diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index d3956e67b2..2c6247b710 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -12,7 +12,7 @@ import { initIntegrationTestContext, PolkadotSigner, } from './common/utils'; -import { assertFailedEvent, assertIsInSidechainBlock, assertIdGraphMutation } from './common/utils/assertion'; +import { assertFailedEvent, assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; import { createSignedTrustedCallLinkIdentity, createSignedTrustedGetterIdGraph, @@ -37,7 +37,7 @@ import { subscribeToEventsWithExtHash } from './common/transactions'; describe('Test Identity (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; - let aliceSubject: LitentryPrimitivesIdentity = undefined as any; + let aliceSubstrateIdentity: LitentryPrimitivesIdentity = undefined as any; // Alice links: // - a `mock_user` twitter @@ -58,14 +58,17 @@ describe('Test Identity (direct invocation)', function () { process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access ); teeShieldingKey = await getTeeShieldingKey(context); - aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); + aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); }); step('check idgraph from sidechain storage before linking', async function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); @@ -75,14 +78,14 @@ describe('Test Identity (direct invocation)', function () { }); step('linking identities (alice)', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const twitterNonce = getNextNonce(); const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); const [twitterValidation] = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [twitterIdentity], twitterNonce, 'twitter' @@ -99,7 +102,7 @@ describe('Test Identity (direct invocation)', function () { const evmIdentity = await buildIdentityHelper(context.ethersWallet.alice.address, 'Evm', context); const [evmValidation] = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [evmIdentity], evmNonce, 'ethereum', @@ -125,7 +128,7 @@ describe('Test Identity (direct invocation)', function () { ); const [eveSubstrateValidation] = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [eveSubstrateIdentity], eveSubstrateNonce, 'substrate', @@ -151,7 +154,7 @@ describe('Test Identity (direct invocation)', function () { console.log('bitcoin id: ', bitcoinIdentity.toHuman()); const [bitcoinValidation] = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [bitcoinIdentity], bitcoinNonce, 'bitcoin', @@ -171,7 +174,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphHashResults: any[] = []; let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ [ - [aliceSubject, true], + [aliceSubstrateIdentity, true], [twitterIdentity, true], ], [[evmIdentity, true]], @@ -187,7 +190,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, identity.toHex(), validation.toHex(), networks.toHex(), @@ -197,7 +200,14 @@ describe('Test Identity (direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'LinkIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceSubstrateIdentity, + res, + 'LinkIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('linkIdentityCall', res); @@ -213,7 +223,7 @@ describe('Test Identity (direct invocation)', function () { }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, idGraphHashResults, @@ -225,7 +235,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); @@ -255,13 +265,16 @@ describe('Test Identity (direct invocation)', function () { currentIndex++; } - await assertIdGraphHash(context, new PolkadotSigner(context.substrateWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceSubstrateIdentity, idGraph); }); step('linking invalid identity', async function () { - const aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.bob), context); + const aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.bob), + context + ); - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; @@ -271,7 +284,7 @@ describe('Test Identity (direct invocation)', function () { const evmIdentity = await buildIdentityHelper(context.ethersWallet.alice.address, 'Evm', context); const [evmValidation] = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [evmIdentity], evmNonce, 'ethereum', @@ -287,7 +300,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', twitterNonce), new PolkadotSigner(context.substrateWallet.bob), - aliceSubject, + aliceSubstrateIdentity, twitterIdentity.toHex(), evmValidation.toHex(), evmNetworks.toHex(), @@ -315,7 +328,7 @@ describe('Test Identity (direct invocation)', function () { }); step('linking identity with wrong signature', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const evmIdentity = await buildIdentityHelper(context.ethersWallet.alice.address, 'Evm', context); const evmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); @@ -346,7 +359,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', evmNonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, evmIdentity.toHex(), encodedVerifyIdentityValidation.toHex(), evmNetworks.toHex(), @@ -374,14 +387,14 @@ describe('Test Identity (direct invocation)', function () { }); step('linking already linked identity', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const twitterNonce = getNextNonce(); const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); const [twitterValidation] = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [twitterIdentity], twitterNonce, 'twitter' @@ -395,7 +408,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', twitterNonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, twitterIdentity.toHex(), twitterValidation.toHex(), twitterNetworks.toHex(), @@ -423,7 +436,7 @@ describe('Test Identity (direct invocation)', function () { }); step('deactivating identity', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const deactivateIdentityRequestParams: { @@ -486,7 +499,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, identity.toHex(), context.api.createType('Option', aesKey).toHex(), requestIdentifier @@ -494,7 +507,14 @@ describe('Test Identity (direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'DeactivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceSubstrateIdentity, + res, + 'DeactivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('deactivateIdentityCall', res); @@ -509,7 +529,7 @@ describe('Test Identity (direct invocation)', function () { } }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.alice), identityDeactivatedEvents, idGraphHashResults, @@ -521,7 +541,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); @@ -541,10 +561,10 @@ describe('Test Identity (direct invocation)', function () { console.debug('inactive ✅'); } - await assertIdGraphHash(context, new PolkadotSigner(context.substrateWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceSubstrateIdentity, idGraph); }); step('activating identity', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const activateIdentityRequestParams: { @@ -607,7 +627,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, identity.toHex(), context.api.createType('Option', aesKey).toHex(), requestIdentifier @@ -615,7 +635,14 @@ describe('Test Identity (direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, activateIdentityCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'ActivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceSubstrateIdentity, + res, + 'ActivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('activateIdentityCall', res); @@ -630,7 +657,7 @@ describe('Test Identity (direct invocation)', function () { } }); } - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.alice), identityActivatedEvents, idGraphHashResults, @@ -642,7 +669,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); @@ -662,7 +689,7 @@ describe('Test Identity (direct invocation)', function () { console.debug('active ✅'); } - await assertIdGraphHash(context, new PolkadotSigner(context.substrateWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceSubstrateIdentity, idGraph); }); step('check idgraph from sidechain storage before setting identity network', async function () { @@ -670,7 +697,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); @@ -680,7 +707,7 @@ describe('Test Identity (direct invocation)', function () { }); step('setting identity network(alice)', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const eveSubstrateIdentity = await buildIdentityHelper( u8aToHex(context.substrateWallet.eve.addressRaw), @@ -701,7 +728,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, eveSubstrateIdentity.toHex(), context.api.createType('Vec', ['Litentry', 'Kusama']).toHex(), context.api.createType('Option', aesKey).toHex(), @@ -710,7 +737,14 @@ describe('Test Identity (direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, setIdentityNetworksCall); idGraphHashResults.push( - assertIdGraphMutationResult(context, res, 'ActivateIdentityResult', expectedIdGraphs[0]) + await assertIdGraphMutationResult( + context, + teeShieldingKey, + aliceSubstrateIdentity, + res, + 'ActivateIdentityResult', + expectedIdGraphs[0] + ) ); expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); await assertIsInSidechainBlock('setIdentityNetworksCall', res); @@ -721,7 +755,7 @@ describe('Test Identity (direct invocation)', function () { identityNetworksSetEvents.push(event); } }); - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.alice), identityNetworksSetEvents, idGraphHashResults, @@ -734,7 +768,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); @@ -745,11 +779,11 @@ describe('Test Identity (direct invocation)', function () { 'idGraph should be changed after setting network' ); - await assertIdGraphHash(context, new PolkadotSigner(context.substrateWallet.alice), idGraph); + await assertIdGraphHash(context, teeShieldingKey, aliceSubstrateIdentity, idGraph); }); step('setting incompatible identity network(alice)', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const eveSubstrateIdentity = await buildIdentityHelper( u8aToHex(context.substrateWallet.eve.addressRaw), @@ -766,7 +800,7 @@ describe('Test Identity (direct invocation)', function () { context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, eveSubstrateIdentity.toHex(), context.api.createType('Vec', ['BSC', 'Ethereum']).toHex(), context.api.createType('Option', aesKey).toHex(), @@ -793,7 +827,7 @@ describe('Test Identity (direct invocation)', function () { const idGraphGetter = await createSignedTrustedGetterIdGraph( context.api, new PolkadotSigner(context.substrateWallet.alice), - aliceSubject + aliceSubstrateIdentity ); const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); @@ -805,7 +839,7 @@ describe('Test Identity (direct invocation)', function () { ); }); step('deactivating prime identity is disallowed', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; // nonce should be plus 1 why? @@ -825,7 +859,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, substratePrimeIdentity.toHex(), context.api.createType('Option', aesKey).toHex(), requestIdentifier diff --git a/tee-worker/ts-tests/integration-tests/di_vc.test.ts b/tee-worker/ts-tests/integration-tests/di_vc.test.ts index 3c3aa6304a..0e17e4f750 100644 --- a/tee-worker/ts-tests/integration-tests/di_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_vc.test.ts @@ -18,7 +18,7 @@ import { defaultAssertions, unconfiguredAssertions } from './common/utils/vc-hel describe('Test Vc (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; - let aliceSubject: LitentryPrimitivesIdentity = undefined as any; + let aliceSubstrateIdentity: LitentryPrimitivesIdentity = undefined as any; this.timeout(6000000); @@ -28,12 +28,15 @@ describe('Test Vc (direct invocation)', function () { process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access ); teeShieldingKey = await getTeeShieldingKey(context); - aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); + aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); }); defaultAssertions.forEach(({ description, assertion }) => { step(`request vc ${Object.keys(assertion)[0]} (alice)`, async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const nonce = getNextNonce(); const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -45,7 +48,7 @@ describe('Test Vc (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, context.api.createType('Assertion', assertion).toHex(), context.api.createType('Option', aesKey).toHex(), requestIdentifier @@ -63,12 +66,12 @@ describe('Test Vc (direct invocation)', function () { 1, `vcIssuedEvents.length != 1, please check the ${Object.keys(assertion)[0]} call` ); - await assertVc(context, aliceSubject, res.value); + await assertVc(context, aliceSubstrateIdentity, res.value); }); }); unconfiguredAssertions.forEach(({ description, assertion }) => { it(`request vc ${Object.keys(assertion)[0]} (alice)`, async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubject)).toNumber(); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const nonce = getNextNonce(); const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -80,7 +83,7 @@ describe('Test Vc (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', nonce), new PolkadotSigner(context.substrateWallet.alice), - aliceSubject, + aliceSubstrateIdentity, context.api.createType('Assertion', assertion).toHex(), context.api.createType('Option', aesKey).toHex(), requestIdentifier diff --git a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts index 9bac42ea88..01bd32114c 100644 --- a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts @@ -9,7 +9,7 @@ import { } from './common/utils'; import { step } from 'mocha-steps'; import { sendTxsWithUtility } from './common/transactions'; -import { generateWeb3Wallets, assertIdGraphMutation, assertIdentityDeactivated } from './common/utils'; +import { generateWeb3Wallets, assertIdGraphMutationEvent, assertIdentityDeactivated } from './common/utils'; import { ethers } from 'ethers'; import type { LitentryPrimitivesIdentity } from 'sidechain-api'; import type { LitentryValidationData, Web3Network } from 'parachain-api'; @@ -31,14 +31,17 @@ describeLitentry('Test Batch Utility', (context) => { step('batch test: link identities', async function () { const defaultNetworks = context.api.createType('Vec', ['Ethereum']); - const aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); + const aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); for (let index = 0; index < evmSigners.length; index++) { const signer = evmSigners[index]; const evmIdentity = await buildIdentityHelper(signer.address, 'Evm', context); identities.push(evmIdentity); we3networks.push(defaultNetworks as unknown as Vec); // @fixme #1878 - signerIdentities.push(aliceSubject); + signerIdentities.push(aliceSubstrateIdentity); } const evmValidations = await buildValidations( @@ -65,7 +68,7 @@ describeLitentry('Test Batch Utility', (context) => { ]); const identityLinkedEvents = events.filter((e) => context.api.events.identityManagement.IdentityLinked.is(e)); - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, undefined, diff --git a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts index a4f7e55af0..cf71f5c401 100644 --- a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts @@ -9,7 +9,7 @@ import { assertIdentityDeactivated, buildIdentityFromKeypair, assertIdentityActivated, - assertIdGraphMutation, + assertIdGraphMutationEvent, PolkadotSigner, } from './common/utils'; import { u8aConcat, u8aToHex, u8aToU8a, stringToU8a } from '@polkadot/util'; @@ -94,11 +94,14 @@ describeLitentry('Test Identity', (context) => { eveIdentities = [evmIdentity, eveSubstrateIdentity, twitterIdentity]; charlieIdentities = [charlieSubstrateIdentity]; - const aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); + const aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); const evmValidations = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [evmIdentity], nonce, 'ethereum', @@ -108,7 +111,7 @@ describeLitentry('Test Identity', (context) => { const eveSubstrateValidations = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [eveSubstrateIdentity], nonce + 1, 'substrate', @@ -117,7 +120,7 @@ describeLitentry('Test Identity', (context) => { const twitterValidations = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [twitterIdentity], nonce + 2, 'twitter' @@ -155,7 +158,7 @@ describeLitentry('Test Identity', (context) => { context.api.events.identityManagement.IdentityLinked.is(e) ); - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, undefined, @@ -174,10 +177,13 @@ describeLitentry('Test Identity', (context) => { }, }, }; - const bobSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.bob), context); + const bobSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.bob), + context + ); nonce = await getNonce(base58mrEnclave, workerAddress, context); console.log('nonce for step link identities', nonce); - const msg = generateVerificationMessage(context, bobSubject, charlieSubstrateIdentity, nonce); + const msg = generateVerificationMessage(context, bobSubstrateIdentity, charlieSubstrateIdentity, nonce); console.log('post verification msg to substrate: ', msg); substrateExtensionValidationData.Web3Validation.Substrate.message = msg; // sign the wrapped version as in polkadot-extension @@ -214,7 +220,7 @@ describeLitentry('Test Identity', (context) => { ); identityLinkedEvents = bobRespEvents.filter((e) => context.api.events.identityManagement.IdentityLinked.is(e)); - await assertIdGraphMutation( + await assertIdGraphMutationEvent( new PolkadotSigner(context.substrateWallet.bob), identityLinkedEvents, undefined, @@ -225,9 +231,18 @@ describeLitentry('Test Identity', (context) => { step('check IDGraph after LinkIdentity', async function () { const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); const identityHex = context.sidechainRegistry.createType('LitentryPrimitivesIdentity', twitterIdentity).toHex(); - const aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); + const aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); - const respIdGraph = await checkIdGraph(context, 'IdentityManagement', 'IDGraphs', aliceSubject, identityHex); + const respIdGraph = await checkIdGraph( + context, + 'IdentityManagement', + 'IDGraphs', + aliceSubstrateIdentity, + identityHex + ); assert.isTrue(respIdGraph.linkBlock.toNumber() > 0, 'linkBlock should be greater than 0'); assert.isTrue(respIdGraph.status.isActive, 'status should be active'); }); @@ -299,7 +314,10 @@ describeLitentry('Test Identity', (context) => { step('link already linked identity', async function () { const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); - const aliceSubject = await buildIdentityFromKeypair(new PolkadotSigner(context.substrateWallet.alice), context); + const aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); const aliceIdentities = [twitterIdentity]; @@ -307,7 +325,7 @@ describeLitentry('Test Identity', (context) => { console.log('nonce for step link already linked identity', nonce); const aliceTwitterValidations = await buildValidations( context, - [aliceSubject], + [aliceSubstrateIdentity], [twitterIdentity], nonce, 'twitter', From e215b5b960d42b21a09da0e211db6436ca890fa0 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Wed, 20 Dec 2023 16:51:57 +0800 Subject: [PATCH 15/43] hotfix Achainable response (#2346) --- .../src/achainable/amount_token.rs | 84 ++++++++----------- .../core/data-providers/src/achainable.rs | 6 ++ 2 files changed, 39 insertions(+), 51 deletions(-) diff --git a/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs b/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs index 02b2b03e30..77c2615edd 100644 --- a/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs +++ b/tee-worker/litentry/core/assertion-build/src/achainable/amount_token.rs @@ -29,13 +29,10 @@ use lc_credentials::{ litentry_profile::token_balance::TokenBalanceInfo, }; use lc_data_providers::{ - achainable_names::{AchainableNameAmountToken, GetAchainableName}, - ETokenAddress, TokenFromString, + achainable_names::AchainableNameAmountToken, ETokenAddress, TokenFromString, }; -const LIT_HOLDING_AMOUNT_NAME: &str = "LIT Holding Amount"; - -/// USDC / USDT Holder +/// ERC20 Holder: USDC and others /// assertions:[ /// { /// and:[ @@ -62,59 +59,44 @@ pub fn build_amount_token( let identities = transpose_identity(&req.identities); let achainable_param = AchainableParams::AmountToken(param.clone()); - // LIT Holding Amount - // Since "LIT Holding Amount" is a custom name in this context, we need to differentiate it by identifying which VC it refers to. - if is_lit_holding_amount(&achainable_param)? { - let lit_holding_amount = query_lit_holding_amount(&achainable_param, &identities)?; - - return match Credential::new(&req.who, &req.shard) { - Ok(mut credential_unsigned) => { - credential_unsigned.update_lit_holding_amount(lit_holding_amount); - Ok(credential_unsigned) - }, - Err(e) => { - error!("Generate unsigned credential failed {:?}", e); - Err(Error::RequestVCFailed( - Assertion::Achainable(achainable_param), - e.into_error_detail(), - )) - }, - } - } + let mut credential = Credential::new(&req.who, &req.shard).map_err(|e| { + Error::RequestVCFailed( + Assertion::Achainable(achainable_param.clone()), + e.into_error_detail(), + ) + })?; - // USDC / USDT Holder - let addresses = identities - .into_iter() - .flat_map(|(_, addresses)| addresses) - .collect::>(); - let token = ETokenAddress::from_vec(param.token.unwrap_or_default()); - let balance = request_achainable_balance(addresses, achainable_param.clone())? - .parse::() - .map_err(|_| { + let amount_token_name = + AchainableNameAmountToken::from(achainable_param.name()).map_err(|e| { Error::RequestVCFailed( Assertion::Achainable(achainable_param.clone()), - ErrorDetail::ParseError, + e.into_error_detail(), ) })?; - match Credential::new(&req.who, &req.shard) { - Ok(mut credential_unsigned) => { - credential_unsigned.update_token_balance(token, balance); - Ok(credential_unsigned) + match amount_token_name { + AchainableNameAmountToken::LITHoldingAmount => { + let lit_holding_amount = query_lit_holding_amount(&achainable_param, &identities)?; + credential.update_lit_holding_amount(lit_holding_amount); }, - Err(e) => { - error!("Generate unsigned credential failed {:?}", e); - Err(Error::RequestVCFailed( - Assertion::Achainable(achainable_param), - e.into_error_detail(), - )) + _ => { + // Token Holder + let addresses = identities + .into_iter() + .flat_map(|(_, addresses)| addresses) + .collect::>(); + let token = ETokenAddress::from_vec(param.token.unwrap_or_default()); + let balance = request_achainable_balance(addresses, achainable_param.clone())? + .parse::() + .map_err(|_| { + Error::RequestVCFailed( + Assertion::Achainable(achainable_param.clone()), + ErrorDetail::ParseError, + ) + })?; + + credential.update_token_balance(token, balance); }, } -} - -fn is_lit_holding_amount(param: &AchainableParams) -> Result { - let name_amount_token = AchainableNameAmountToken::from(param.name()).map_err(|e| { - Error::RequestVCFailed(Assertion::Achainable(param.clone()), e.into_error_detail()) - })?; - Ok(name_amount_token.name() == LIT_HOLDING_AMOUNT_NAME) + Ok(credential) } diff --git a/tee-worker/litentry/core/data-providers/src/achainable.rs b/tee-worker/litentry/core/data-providers/src/achainable.rs index 7ee3405117..fef7e594d6 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable.rs @@ -814,6 +814,12 @@ impl AchainableUtils for AchainableClient { }) .flatten(); if let Some(display_text) = display_text { + // If it is a newly created brand new account, Achainable returns `Address has no [token] balance`, + // so it will not be parsed and will directly return 0 + if display_text.contains("Address has no") { + return Ok(0_f64) + } + // TODO: // text field format: Balance over 0 (Balance is 588.504602529) let split_text = display_text.split("Balance is ").collect::>(); From ecd18d2e50c0cd8a1b87612b97012a6078ae99e7 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Fri, 22 Dec 2023 16:17:17 +0800 Subject: [PATCH 16/43] Unfold _ expression in Assertion type (#2350) --- primitives/core/src/assertion.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index cb118e65d3..880c0cfcae 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -270,7 +270,10 @@ impl Assertion { // DOT holder Self::A7(..) => vec![Web3Network::Polkadot], // WBTC/ETH holder - Self::A10(..) | Self::A11(..) => vec![Web3Network::Ethereum], + Self::A10(..) | + Self::A11(..) | + Self::VIP3MembershipCard(..) | + Self::WeirdoGhostGangHolder => vec![Web3Network::Ethereum], // total tx over `networks` Self::A8(network) => network.to_vec(), // polkadot paticipation @@ -281,16 +284,18 @@ impl Assertion { Self::Oneblock(..) => vec![Web3Network::Polkadot, Web3Network::Kusama], // SPACEID Assertions Self::BnbDomainHolding | Self::BnbDigitDomainClub(..) => vec![Web3Network::Bsc], - // VIP3 Member Card - Self::VIP3MembershipCard(..) => vec![Web3Network::Ethereum], // LITStaking Self::LITStaking => vec![Web3Network::Litentry], - // Weirdo Ghost Gang - Self::WeirdoGhostGangHolder => vec![Web3Network::Ethereum], // EVM Amount Holding Self::EVMAmountHolding(_) => vec![Web3Network::Ethereum, Web3Network::Bsc], // we don't care about any specific web3 network - _ => vec![], + Self::A1 | + Self::A2(..) | + Self::A3(..) | + Self::A6 | + Self::A13(..) | + Self::A20 | + Self::GenericDiscordRole(..) => vec![], } } } From 62039f45b79c396a32009204a89c0c8a159e399d Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:59:11 +0100 Subject: [PATCH 17/43] Extend bitcoin networks to all address types (#2349) * Extend bitcoin networks * update definitions * try to fix ts-test --- primitives/core/src/network.rs | 39 ++++++++++++++++--- .../interfaces/identity/definitions.ts | 6 ++- .../core/data-providers/src/achainable.rs | 6 ++- .../di_substrate_identity.test.ts | 6 ++- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/primitives/core/src/network.rs b/primitives/core/src/network.rs index 171aec5fb8..90561648ab 100644 --- a/primitives/core/src/network.rs +++ b/primitives/core/src/network.rs @@ -70,9 +70,17 @@ pub enum Web3Network { #[codec(index = 8)] Bsc, - // btc + // btc, see https://github.com/rust-bitcoin/rust-bitcoin/blob/9ea3e29d61569479b7b4618c8ae1992612f3d01a/bitcoin/src/address/mod.rs#L64-L75 #[codec(index = 9)] - Bitcoin, + BitcoinP2tr, + #[codec(index = 10)] + BitcoinP2pkh, + #[codec(index = 11)] + BitcoinP2sh, + #[codec(index = 12)] + BitcoinP2wpkh, + #[codec(index = 13)] + BitcoinP2wsh, } // mainly used in CLI @@ -101,7 +109,14 @@ impl Web3Network { } pub fn is_bitcoin(&self) -> bool { - matches!(self, Self::Bitcoin) + matches!( + self, + Self::BitcoinP2tr | + Self::BitcoinP2pkh | + Self::BitcoinP2sh | + Self::BitcoinP2wpkh | + Self::BitcoinP2wsh + ) } } @@ -146,7 +161,11 @@ mod tests { Web3Network::SubstrateTestnet => false, Web3Network::Ethereum => true, Web3Network::Bsc => true, - Web3Network::Bitcoin => false, + Web3Network::BitcoinP2tr => false, + Web3Network::BitcoinP2pkh => false, + Web3Network::BitcoinP2sh => false, + Web3Network::BitcoinP2wpkh => false, + Web3Network::BitcoinP2wsh => false, } ) }) @@ -167,7 +186,11 @@ mod tests { Web3Network::SubstrateTestnet => true, Web3Network::Ethereum => false, Web3Network::Bsc => false, - Web3Network::Bitcoin => false, + Web3Network::BitcoinP2tr => false, + Web3Network::BitcoinP2pkh => false, + Web3Network::BitcoinP2sh => false, + Web3Network::BitcoinP2wpkh => false, + Web3Network::BitcoinP2wsh => false, } ) }) @@ -188,7 +211,11 @@ mod tests { Web3Network::SubstrateTestnet => false, Web3Network::Ethereum => false, Web3Network::Bsc => false, - Web3Network::Bitcoin => true, + Web3Network::BitcoinP2tr => true, + Web3Network::BitcoinP2pkh => true, + Web3Network::BitcoinP2sh => true, + Web3Network::BitcoinP2wpkh => true, + Web3Network::BitcoinP2wsh => true, } ) }) diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts index 30536b32d2..4abe41e2b9 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts @@ -44,7 +44,11 @@ export default { "SubstrateTestnet", "Ethereum", "Bsc", - "Bitcoin", + "BitcoinP2tr", + "BitcoinP2pkh", + "BitcoinP2sh", + "BitcoinP2wpkh", + "BitcoinP2wsh", ], }, LitentryValidationData: { diff --git a/tee-worker/litentry/core/data-providers/src/achainable.rs b/tee-worker/litentry/core/data-providers/src/achainable.rs index fef7e594d6..2fa0939be9 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable.rs @@ -179,7 +179,11 @@ pub fn web3_network_to_chain(network: &Web3Network) -> String { Web3Network::SubstrateTestnet => "substrate_testnet".into(), Web3Network::Ethereum => "ethereum".into(), Web3Network::Bsc => "bsc".into(), - Web3Network::Bitcoin => "bitcoin".into(), + Web3Network::BitcoinP2tr => "bitcoin_p2tr".into(), + Web3Network::BitcoinP2pkh => "bitcoin_p2pkh".into(), + Web3Network::BitcoinP2sh => "bitcoin_p2sh".into(), + Web3Network::BitcoinP2wpkh => "bitcoin_p2wpkh".into(), + Web3Network::BitcoinP2wsh => "bitcoin_p2wsh".into(), } } diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index 2c6247b710..68f594c410 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -162,7 +162,9 @@ describe('Test Identity (direct invocation)', function () { undefined, context.bitcoinWallet.alice ); - const bitcoinNetworks = context.api.createType('Vec', ['Bitcoin']) as unknown as Vec; // @fixme #1878 + const bitcoinNetworks = context.api.createType('Vec', [ + 'BitcoinP2tr', + ]) as unknown as Vec; // @fixme #1878 linkIdentityRequestParams.push({ nonce: bitcoinNonce, identity: bitcoinIdentity, @@ -242,7 +244,7 @@ describe('Test Identity (direct invocation)', function () { const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); // according to the order of linkIdentityRequestParams - const expectedWeb3Networks = [[], ['Ethereum', 'Bsc'], ['Polkadot', 'Litentry'], ['Bitcoin']]; + const expectedWeb3Networks = [[], ['Ethereum', 'Bsc'], ['Polkadot', 'Litentry'], ['BitcoinP2tr']]; let currentIndex = 0; for (const { identity } of linkIdentityRequestParams) { From ac0fad8b408cf7bed27e1b3649aef50c1f48f832 Mon Sep 17 00:00:00 2001 From: Igor Trofimov Date: Fri, 22 Dec 2023 15:31:59 +0200 Subject: [PATCH 18/43] Parachain staking: reduce awaiting time (#2339) * Parachain stacking: reduce awaiting time * cover rest functions with tests * include feature to CI build --- Makefile | 4 +- .../src/delegation_requests.rs | 1 - runtime/rococo/src/lib.rs | 14 ++-- ts-tests/tests/precompile-contract.test.ts | 76 ++++++++++++------- 4 files changed, 57 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index b959abca5c..2572c54712 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ build-all: .PHONY: build-node ## Build release node with `tee-dev` feature build-node: - cargo build --locked -p $(call pkgid, $(NODE_BIN)) --release --features=tee-dev + cargo build --locked -p $(call pkgid, $(NODE_BIN)) --release --features=tee-dev,fast-runtime .PHONY: build-runtime-litentry ## Build litentry release runtime build-runtime-litentry: @@ -61,7 +61,7 @@ srtool-build-wasm-rococo: .PHONY: build-docker-release ## Build docker image using cargo profile `release` # with `tee-dev` feature as we use release profile in dev build-docker-release: - @./scripts/build-docker.sh release latest --features=tee-dev + @./scripts/build-docker.sh release latest --features=tee-dev,fast-runtime .PHONY: build-docker-production ## Build docker image using cargo profile `production` build-docker-production: diff --git a/pallets/parachain-staking/src/delegation_requests.rs b/pallets/parachain-staking/src/delegation_requests.rs index eb8fddef30..e01b7edf34 100644 --- a/pallets/parachain-staking/src/delegation_requests.rs +++ b/pallets/parachain-staking/src/delegation_requests.rs @@ -214,7 +214,6 @@ impl Pallet { let now = >::get().current; ensure!(request.when_executable <= now, >::PendingDelegationRequestNotDueYet); - match request.action { DelegationAction::Revoke(amount) => { // revoking last delegation => leaving set of delegators diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 45749675a2..c54f9b5d04 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -855,19 +855,19 @@ impl pallet_parachain_staking::Config for Runtime { type Currency = Balances; type MonetaryGovernanceOrigin = EnsureRootOrAllCouncil; /// Minimum round length is 2 minutes (10 * 12 second block times) - type MinBlocksPerRound = ConstU32<{ 2 * MINUTES }>; + type MinBlocksPerRound = ConstU32<{ prod_or_fast!(2 * MINUTES, 2) }>; /// Blocks per round - type DefaultBlocksPerRound = ConstU32<{ 2 * MINUTES }>; + type DefaultBlocksPerRound = ConstU32<{ prod_or_fast!(2 * MINUTES, 2) }>; /// Rounds before the collator leaving the candidates request can be executed - type LeaveCandidatesDelay = ConstU32<28>; + type LeaveCandidatesDelay = ConstU32<{ prod_or_fast!(28, 1) }>; /// Rounds before the candidate bond increase/decrease can be executed - type CandidateBondLessDelay = ConstU32<28>; + type CandidateBondLessDelay = ConstU32<{ prod_or_fast!(28, 1) }>; /// Rounds before the delegator exit can be executed - type LeaveDelegatorsDelay = ConstU32<28>; + type LeaveDelegatorsDelay = ConstU32<{ prod_or_fast!(28, 1) }>; /// Rounds before the delegator revocation can be executed - type RevokeDelegationDelay = ConstU32<28>; + type RevokeDelegationDelay = ConstU32<{ prod_or_fast!(28, 1) }>; /// Rounds before the delegator bond increase/decrease can be executed - type DelegationBondLessDelay = ConstU32<28>; + type DelegationBondLessDelay = ConstU32<{ prod_or_fast!(28, 1) }>; /// Rounds before the reward is paid type RewardPaymentDelay = ConstU32<2>; /// Minimum collators selected per round, default at genesis and minimum forever after diff --git a/ts-tests/tests/precompile-contract.test.ts b/ts-tests/tests/precompile-contract.test.ts index b668715913..19d15053db 100644 --- a/ts-tests/tests/precompile-contract.test.ts +++ b/ts-tests/tests/precompile-contract.test.ts @@ -154,10 +154,11 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { autoCompoundPercent ); + let afterDelegateBalance = balance; // skip test if already delegated if (balance.reserved.toNumber() === 0) { await executeTransaction(delegateWithAutoCompound, 'delegateWithAutoCompound'); - const { data: afterDelegateBalance } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + afterDelegateBalance = (await context.api.query.system.account(evmAccountRaw.mappedAddress)).data; expect(balance.free.toNumber() - toBigNumber(60)).to.closeTo( afterDelegateBalance.free.toNumber(), @@ -166,8 +167,6 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { expect(afterDelegateBalance.reserved.toNumber()).to.eq(toBigNumber(60)); const collator = await collatorDetails(); expect(collator.value).to.eq(autoCompoundPercent); - - balance = afterDelegateBalance; } // delegatorBondMore(collator, amount) @@ -179,7 +178,9 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { balanceAfterBondMore.free.toNumber() - toBigNumber(1), toBigNumber(1) ); - expect(balanceAfterBondMore.reserved.toNumber()).to.eq(balance.reserved.toNumber() + toBigNumber(1)); + expect(balanceAfterBondMore.reserved.toNumber()).to.eq( + afterDelegateBalance.reserved.toNumber() + toBigNumber(1) + ); // setAutoCompound(collator, percent); const setAutoCompound = precompileContract.methods.setAutoCompound(collatorPublicKey, autoCompoundPercent + 5); @@ -202,32 +203,51 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { await executeTransaction(cancelDelegationRequest, 'cancelDelegationRequest'); expect(await isPendingRequest()).to.be.false; + // testing bond less + execution + await executeTransaction(scheduleDelegatorBondLess, 'scheduleDelegatorBondLess again to test execution'); + expect(await isPendingRequest()).to.be.true; + + console.log('Waiting 2 blocks before execute delegation request'); + await context.api.rpc.chain.getBlock(); + await context.api.rpc.chain.getBlock(); + + // executeDelegationRequest(delegator, collator); + const executeDelegationRequest = precompileContract.methods.executeDelegationRequest( + evmAccountRaw.publicKey, + collatorPublicKey + ); + await executeTransaction(executeDelegationRequest, 'executeDelegationRequest'); + const { data: balanceAfterBondLess } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + expect(balanceAfterBondLess.free.toNumber()).to.closeTo( + balanceAfterBondMore.free.toNumber() + toBigNumber(5), + toBigNumber(1) + ); + expect(balanceAfterBondLess.reserved.toNumber()).to.eq( + balanceAfterBondMore.reserved.toNumber() - toBigNumber(5) + ); + + // testing revoke delegation + execute + // scheduleRevokeDelegation(collator); + const scheduleRevokeDelegation = precompileContract.methods.scheduleRevokeDelegation(collatorPublicKey); + await executeTransaction(scheduleRevokeDelegation, 'scheduleRevokeDelegation'); + + console.log('Waiting 2 blocks before execute delegation request'); + await context.api.rpc.chain.getBlock(); + await context.api.rpc.chain.getBlock(); + + await executeTransaction(executeDelegationRequest, 'executeDelegationRequest'); + const { data: balanceAfterRevoke } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + expect(balanceAfterRevoke.free.toNumber()).to.closeTo(balance.free.toNumber(), toBigNumber(1)); + expect(balanceAfterRevoke.reserved.toNumber()).to.eq(0); + + // delegate(collator, amount); + const delegate = precompileContract.methods.delegate(collatorPublicKey, toBigNumber(57)); + await executeTransaction(delegate, 'delegate'); + const { data: balanceAfterDelegate } = await context.api.query.system.account(evmAccountRaw.mappedAddress); + expect(balanceAfterDelegate.reserved.toNumber()).to.eq(toBigNumber(57)); + // In case evm is not enabled in Normal Mode, switch back to filterMode, after test. let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode(filterMode)); await signAndSend(extrinsic, context.alice); }); - - // once we add ability to customise minimum waiting time for `executeDelegationRequest` implement tests for the rest functions - // step('test time sensitive functions', async () => { - // delegate(collator, amount); - // const delegate = precompileContract.methods.delegate(collatorPublicKey, toBigNumber(55)); - // await executeTransaction(delegate, 'delegate'); - // const { data: balanceAfterDelegate } = await context.api.query.system.account(evmAccountRaw.mappedAddress); - // printBalance('balanceAfterDelegate', balanceAfterDelegate); - // scheduleRevokeDelegation(collator); - // const scheduleRevokeDelegation = precompileContract.methods.scheduleRevokeDelegation(collatorPublicKey); - // await executeTransaction(scheduleRevokeDelegation, 'scheduleRevokeDelegation'); - // const { data: balanceAfterRevoke } = await context.api.query.system.account(evmAccountRaw.mappedAddress); - // printBalance('balanceAfterRevoke', balanceAfterRevoke); - // executeDelegationRequest(delegator, collator); - // const executeDelegationRequest = precompileContract.methods.executeDelegationRequest( - // evmAccountRaw.mappedAddress, - // collatorPublicKey - // ); - // await executeTransaction(executeDelegationRequest, 'executeDelegationRequest'); - // const { data: balanceAfterExecuteDelegation } = await context.api.query.system.account( - // evmAccountRaw.mappedAddress - // ); - // printBalance('balanceAfterExecuteDelegation', balanceAfterExecuteDelegation); - // }); }); From 423918410b7670fa932813f223468cb88709f487 Mon Sep 17 00:00:00 2001 From: BillyWooo Date: Fri, 22 Dec 2023 15:40:01 +0100 Subject: [PATCH 19/43] BRC20 token amount holding (#2344) * BRC20 token amount holding: first implementation * update index * Add definition * make fmt * remove unused code * remove lazy_static * refine code * update balance range * rm used code; add "token" as separate assertion entry; * add pubkey to address convertor for bitcoin --------- Co-authored-by: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Co-authored-by: zhouhuitian --- Cargo.lock | 1 + primitives/core/src/assertion.rs | 13 +- .../interfaces/vc/definitions.ts | 1 + .../core-primitives/utils/src/stringify.rs | 4 + .../enclave-runtime/src/stf_task_handler.rs | 2 + .../enclave-runtime/src/vc_issuance_task.rs | 2 + .../src/brc20/amount_holder.rs | 51 +++++ .../core/assertion-build/src/brc20/mod.rs | 23 +++ .../litentry/core/assertion-build/src/lib.rs | 83 +++++++- .../credentials/src/brc20/amount_holder.rs | 183 ++++++++++++++++++ .../core/credentials/src/brc20/mod.rs | 17 ++ .../litentry/core/credentials/src/lib.rs | 1 + .../core/data-providers/src/geniidata.rs | 113 +++++++++++ .../litentry/core/data-providers/src/lib.rs | 16 ++ .../receiver/src/handler/assertion.rs | 4 + .../lc-vc-task-receiver/src/vc_handling.rs | 3 + .../primitives/src/bitcoin_address.rs | 57 ++++++ tee-worker/litentry/primitives/src/lib.rs | 2 + tee-worker/service/src/main_impl.rs | 6 + tee-worker/service/src/prometheus_metrics.rs | 1 + .../service/src/running-mode-config.json | 16 +- 21 files changed, 586 insertions(+), 13 deletions(-) create mode 100644 tee-worker/litentry/core/assertion-build/src/brc20/amount_holder.rs create mode 100644 tee-worker/litentry/core/assertion-build/src/brc20/mod.rs create mode 100644 tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs create mode 100644 tee-worker/litentry/core/credentials/src/brc20/mod.rs create mode 100644 tee-worker/litentry/core/data-providers/src/geniidata.rs create mode 100644 tee-worker/litentry/primitives/src/bitcoin_address.rs diff --git a/Cargo.lock b/Cargo.lock index 3e6817f4d5..d05e283dd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8013,6 +8013,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", + "log", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "sp-api", diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 880c0cfcae..df639eb4dc 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -248,9 +248,12 @@ pub enum Assertion { #[codec(index = 20)] LITStaking, - + #[codec(index = 22)] EVMAmountHolding(EVMTokenType), // (evm_token_type) + + #[codec(index = 23)] + BRC20AmountHolder, } impl Assertion { @@ -288,6 +291,14 @@ impl Assertion { Self::LITStaking => vec![Web3Network::Litentry], // EVM Amount Holding Self::EVMAmountHolding(_) => vec![Web3Network::Ethereum, Web3Network::Bsc], + // BRC20 Holder + Self::BRC20AmountHolder => vec![ + Web3Network::BitcoinP2tr, + Web3Network::BitcoinP2pkh, + Web3Network::BitcoinP2sh, + Web3Network::BitcoinP2wpkh, + Web3Network::BitcoinP2wsh, + ], // we don't care about any specific web3 network Self::A1 | Self::A2(..) | diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts index 7b71f9a901..0b48610e21 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts @@ -29,6 +29,7 @@ export default { WeirdoGhostGangHolder: "Null", LITStaking: "Null", EVMAmountHolding: "EVMTokenType", + BRC20AmountHolder: "Null", }, }, AssertionSupportedNetwork: { diff --git a/tee-worker/core-primitives/utils/src/stringify.rs b/tee-worker/core-primitives/utils/src/stringify.rs index 7018038ad8..e514fdbecb 100644 --- a/tee-worker/core-primitives/utils/src/stringify.rs +++ b/tee-worker/core-primitives/utils/src/stringify.rs @@ -30,3 +30,7 @@ pub fn public_to_string(t: &T) -> String { pub fn account_id_to_string(account: &AccountId) -> String { format!("0x{}", HexDisplay::from(&account.encode())) } + +pub fn account_id_to_string_without_prefix(account: &AccountId) -> String { + format!("{}", HexDisplay::from(&account.encode())) +} diff --git a/tee-worker/enclave-runtime/src/stf_task_handler.rs b/tee-worker/enclave-runtime/src/stf_task_handler.rs index da62a05a08..11876a4418 100644 --- a/tee-worker/enclave-runtime/src/stf_task_handler.rs +++ b/tee-worker/enclave-runtime/src/stf_task_handler.rs @@ -72,6 +72,8 @@ pub unsafe extern "C" fn run_stf_task_handler(dpc: *const u8, dpc_size: usize) - data_provider_config.contest_participant_discord_role_id, ); dpc.set_vip3_url(data_provider_config.vip3_url); + dpc.set_geniidata_url(data_provider_config.geniidata_url); + dpc.set_geniidata_api_key(data_provider_config.geniidata_api_key); }, Err(e) => { error!("Error while setting data provider config: {:?}", e); diff --git a/tee-worker/enclave-runtime/src/vc_issuance_task.rs b/tee-worker/enclave-runtime/src/vc_issuance_task.rs index 425c1cca7f..bdbce0ecc7 100644 --- a/tee-worker/enclave-runtime/src/vc_issuance_task.rs +++ b/tee-worker/enclave-runtime/src/vc_issuance_task.rs @@ -77,6 +77,8 @@ pub unsafe extern "C" fn run_vc_issuance(dpc: *const u8, dpc_size: usize) -> sgx data_provider_config.contest_participant_discord_role_id, ); dpc.set_vip3_url(data_provider_config.vip3_url); + dpc.set_geniidata_url(data_provider_config.geniidata_url); + dpc.set_geniidata_api_key(data_provider_config.geniidata_api_key); }, Err(e) => { error!("Error while setting data provider config: {:?}", e); diff --git a/tee-worker/litentry/core/assertion-build/src/brc20/amount_holder.rs b/tee-worker/litentry/core/assertion-build/src/brc20/amount_holder.rs new file mode 100644 index 0000000000..09be442d97 --- /dev/null +++ b/tee-worker/litentry/core/assertion-build/src/brc20/amount_holder.rs @@ -0,0 +1,51 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use crate::*; +use lc_credentials::brc20::amount_holder::BRC20AmountHolderCredential; +use lc_data_providers::geniidata::GeniidataClient; + +pub fn build(req: &AssertionBuildRequest) -> Result { + let identities = transpose_identity(&req.identities); + let addresses = identities + .into_iter() + .flat_map(|(_, addresses)| addresses) + .collect::>(); + + let mut credential_unsigned = Credential::new(&req.who, &req.shard).map_err(|e| { + error!("Generate unsigned credential failed {:?}", e); + Error::RequestVCFailed(Assertion::BRC20AmountHolder, e.into_error_detail()) + })?; + let mut client = GeniidataClient::new() + .map_err(|e| Error::RequestVCFailed(Assertion::BRC20AmountHolder, e))?; + let response = client.create_brc20_amount_holder_sum(addresses).map_err(|e| { + Error::RequestVCFailed( + Assertion::BRC20AmountHolder, + ErrorDetail::DataProviderError(ErrorString::truncate_from( + format!("{e:?}").as_bytes().to_vec(), + )), + ) + })?; + credential_unsigned.update_brc20_amount_holder_credential(&response); + + Ok(credential_unsigned) +} diff --git a/tee-worker/litentry/core/assertion-build/src/brc20/mod.rs b/tee-worker/litentry/core/assertion-build/src/brc20/mod.rs new file mode 100644 index 0000000000..028dceb3dc --- /dev/null +++ b/tee-worker/litentry/core/assertion-build/src/brc20/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub mod amount_holder; diff --git a/tee-worker/litentry/core/assertion-build/src/lib.rs b/tee-worker/litentry/core/assertion-build/src/lib.rs index ef90c5f8da..297333b264 100644 --- a/tee-worker/litentry/core/assertion-build/src/lib.rs +++ b/tee-worker/litentry/core/assertion-build/src/lib.rs @@ -46,6 +46,7 @@ pub mod a3; pub mod a6; pub mod a8; pub mod achainable; +pub mod brc20; pub mod generic_discord_role; pub mod holding_time; pub mod lit_staking; @@ -55,21 +56,29 @@ pub mod vip3; use blake2_rfc::blake2b::Blake2b; use itp_types::AccountId; -use itp_utils::stringify::account_id_to_string; +use itp_utils::stringify::{account_id_to_string, account_id_to_string_without_prefix}; use lc_credentials::Credential; use lc_data_providers::achainable::web3_network_to_chain; use lc_stf_task_sender::AssertionBuildRequest; use litentry_primitives::{ - AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, - AchainableBasic, AchainableBetweenPercents, AchainableDate, AchainableDateInterval, - AchainableDatePercent, AchainableParams, AchainableToken, Assertion, ErrorDetail, ErrorString, - Identity, IdentityNetworkTuple, IntoErrorDetail, OneBlockCourseType, ParameterString, - VCMPError as Error, Web3Network, ASSERTION_FROM_DATE, + p2pkh_address, p2sh_address, p2tr_address, p2wpkh_address, AchainableAmount, + AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, + AchainableBetweenPercents, AchainableDate, AchainableDateInterval, AchainableDatePercent, + AchainableParams, AchainableToken, Assertion, ErrorDetail, ErrorString, Identity, + IdentityNetworkTuple, IntoErrorDetail, OneBlockCourseType, ParameterString, VCMPError as Error, + Web3Network, ASSERTION_FROM_DATE, }; use log::*; use rust_base58::ToBase58; use ss58_registry::Ss58AddressFormat; -use std::{collections::HashSet, format, string::String, sync::Arc, vec, vec::Vec}; +use std::{ + collections::HashSet, + format, + string::{String, ToString}, + sync::Arc, + vec, + vec::Vec, +}; pub type Result = core::result::Result; @@ -99,7 +108,8 @@ pub fn transpose_identity( networks_set.insert(n); }, Identity::Bitcoin(address) => { - let address = account_id_to_string(address.as_ref()); + let address = account_id_to_string_without_prefix(address.as_ref()); + let address = pubkey_to_address(&n, &address); addresses.push((address, n)); networks_set.insert(n); }, @@ -154,6 +164,25 @@ pub fn ss58_address_of( Ok(bytes.to_base58()) } +fn pubkey_to_address(network: &Web3Network, pubkey: &str) -> String { + match network { + Web3Network::BitcoinP2tr => p2tr_address(pubkey), + Web3Network::BitcoinP2pkh => p2pkh_address(pubkey), + Web3Network::BitcoinP2sh => p2sh_address(pubkey), + Web3Network::BitcoinP2wpkh => p2wpkh_address(pubkey), + Web3Network::BitcoinP2wsh => "".to_string(), + Web3Network::Polkadot + | Web3Network::Kusama + | Web3Network::Litentry + | Web3Network::Litmus + | Web3Network::LitentryRococo + | Web3Network::Khala + | Web3Network::SubstrateTestnet + | Web3Network::Ethereum + | Web3Network::Bsc => "".to_string(), + } +} + #[cfg(test)] mod tests { use super::*; @@ -220,4 +249,42 @@ mod tests { ); assert_eq!(result.get(4).unwrap(), &(Web3Network::Bsc, vec![[4u8; 20].to_hex()])); } + + #[test] + fn pubkey_to_address_works() { + // p2wpkh + let addr = "bc1qlht0muueu6wln5qqwtvczjepnfeerpaw480067"; + let pubkey = "0272cbf3e56e238897ca9ee9ca9594a82803cfdf19121bd939cbe3f2e1bcaffc7b"; + let network = Web3Network::BitcoinP2wpkh; + let gen_addr = pubkey_to_address(&network, &pubkey); + assert_eq!(addr, gen_addr); + + // p2sh + let addr = "35KQSeZpaABvNWmKAMXo7mAAtXZBqCd4sw"; + let pubkey = "02e46883d2101f09e875dd4a67ee5c2dce9d821b9a610a7e12ab0de7494b19b7d0"; + let network = Web3Network::BitcoinP2sh; + let gen_addr = pubkey_to_address(&network, &pubkey); + assert_eq!(addr, gen_addr); + + // p2tr + let addr = "bc1pwgqves622fs5s42h4sr8hu9y6ej232hga8uxal7xgkcsy8a3ryqqvgku7t"; + let pubkey = "031d867537093a8eaace96717ba0aa226a5bf368c6c84ca5dfb214d380bc91afbe"; + let network = Web3Network::BitcoinP2tr; + let gen_addr = pubkey_to_address(&network, &pubkey); + assert_eq!(addr, gen_addr); + + // p2pkh + let addr = "1CY8nArJbvLSHQmKp3SiG8T5WSBfnMJpJx"; + let pubkey = "02784a686e5ffc74d713f66cb8885d6b75c062c61df5f6de8f86f07c340ebc183c"; + let network = Web3Network::BitcoinP2pkh; + let gen_addr = pubkey_to_address(&network, &pubkey); + assert_eq!(addr, gen_addr); + + // p2wsh + let addr = ""; + let pubkey = "02e46883d2101f09e875dd4a67ee5c2dce9d821b9a610a7e12ab0de7494b19b7d0"; + let network = Web3Network::BitcoinP2wsh; + let gen_addr = pubkey_to_address(&network, &pubkey); + assert_eq!(addr, gen_addr); + } } diff --git a/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs b/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs new file mode 100644 index 0000000000..21d54c2264 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs @@ -0,0 +1,183 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + assertion_logic::{AssertionLogic, Op}, + litentry_profile::{BalanceRange, BalanceRangeIndex}, + Credential, +}; +use lc_data_providers::geniidata::ResponseItem; +use std::vec::Vec; + +const VC_BRC20_AMOUNT_HOLDER_DESCRIPTIONS: &str = + "The amount of a particular token you are holding"; +const VC_BRC20_AMOUNT_HOLDER_TYPE: &str = "Token holding amount"; + +const BRC20_TOKENS: [&str; 7] = ["ordi", "sats", "rats", "Mmss", "long", "cats", "BTCs"]; +const ORDI_TOKEN_BALANCE_RANGE: [f64; 8] = [0.0, 1.0, 5.0, 20.0, 50.0, 100.0, 200.0, 500.0]; +const SATS_TOKEN_BALANCE_RANGE: [f64; 8] = [ + 0.0, + 40_000_000.0, + 200_000_000.0, + 500_000_000.0, + 1_000_000_000.0, + 2_000_000_000.0, + 4_000_000_000.0, + 6_000_000_000.0, +]; +const RATS_TOKEN_BALANCE_RANGE: [f64; 8] = + [0.0, 40_000.0, 200_000.0, 1_000_000.0, 2_000_000.0, 4_000_000.0, 10_000_000.0, 20_000_000.0]; +const MMSS_TOKEN_BALANCE_RANGE: [f64; 8] = [0.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0]; +const LONG_TOKEN_BALANCE_RANGE: [f64; 8] = [0.0, 20.0, 50.0, 200.0, 500.0, 1000.0, 2000.0, 3000.0]; +const CATS_TOKEN_BALANCE_RANGE: [f64; 7] = + [0.0, 10_000.0, 50_000.0, 100_000.0, 200_000.0, 500_000.0, 800_000.0]; +const BTCS_TOKEN_BALANCE_RANGE: [f64; 8] = [0.0, 5.0, 20.0, 50.0, 100.0, 200.0, 500.0, 800.0]; + +enum BRC20Token { + Ordi, + Sats, + Rats, + Mmss, + Long, + Cats, + Btcs, + Unknown, +} + +struct AssertionKeys { + token: &'static str, + holding_amount: &'static str, +} + +const ASSERTION_KEYS: AssertionKeys = + AssertionKeys { token: "$token", holding_amount: "$holding_amount" }; + +pub trait BRC20AmountHolderCredential { + fn update_brc20_amount_holder_credential(&mut self, response_items: &[ResponseItem]); +} + +impl BRC20AmountHolderCredential for Credential { + fn update_brc20_amount_holder_credential(&mut self, response_items: &[ResponseItem]) { + for item in response_items { + if BRC20_TOKENS.contains(&item.tick.as_str()) { + let token = tick_to_brctoken(&item.tick); + let balance: f64 = item.overall_balance.parse().unwrap_or(0.0); + update_assertion(token, balance, self); + } + } + + self.add_subject_info(VC_BRC20_AMOUNT_HOLDER_DESCRIPTIONS, VC_BRC20_AMOUNT_HOLDER_TYPE); + } +} + +// TODO: the following part is exactly the same structure from 'token_balance.rs'. +// Anyway the refactor is planned later. So continue using the same mechanism. +fn update_assertion(token: BRC20Token, balance: f64, credential: &mut Credential) { + let mut assertion = AssertionLogic::new_and(); + + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.token, + Op::Equal, + brctoken_to_tick(&token), + )); + + let range = get_balance_range(&token); + let index = BalanceRange::index(&range, balance); + match index { + Some(index) => { + let min = format!("{}", range[index]); + let max = format!("{}", range[index + 1]); + let min_item = + AssertionLogic::new_item(ASSERTION_KEYS.holding_amount, Op::GreaterEq, &min); + let max_item = + AssertionLogic::new_item(ASSERTION_KEYS.holding_amount, Op::LessThan, &max); + + assertion = assertion.add_item(min_item); + assertion = assertion.add_item(max_item); + + credential.credential_subject.values.push(index != 0); + }, + None => { + let min_item = AssertionLogic::new_item( + ASSERTION_KEYS.holding_amount, + Op::GreaterEq, + &format!("{}", get_token_range_last(&token)), + ); + assertion = assertion.add_item(min_item); + + credential.credential_subject.values.push(true); + }, + } + + credential.credential_subject.assertions.push(assertion); +} + +fn tick_to_brctoken(tick: &str) -> BRC20Token { + match tick { + "ordi" => BRC20Token::Ordi, + "sats" => BRC20Token::Sats, + "rats" => BRC20Token::Rats, + "MMSS" => BRC20Token::Mmss, + "long" => BRC20Token::Long, + "cats" => BRC20Token::Cats, + "BTCs" => BRC20Token::Btcs, + _ => BRC20Token::Unknown, + } +} + +fn brctoken_to_tick(token: &BRC20Token) -> &'static str { + match token { + BRC20Token::Ordi => "$ordi", + BRC20Token::Sats => "$sats", + BRC20Token::Rats => "$rats", + BRC20Token::Mmss => "$MMSS", + BRC20Token::Long => "$long", + BRC20Token::Cats => "$cats", + BRC20Token::Btcs => "$BTCs", + _ => "Unknown", + } +} + +fn get_balance_range(token: &BRC20Token) -> Vec { + match token { + BRC20Token::Ordi => ORDI_TOKEN_BALANCE_RANGE.to_vec(), + BRC20Token::Sats => SATS_TOKEN_BALANCE_RANGE.to_vec(), + BRC20Token::Rats => RATS_TOKEN_BALANCE_RANGE.to_vec(), + BRC20Token::Mmss => MMSS_TOKEN_BALANCE_RANGE.to_vec(), + BRC20Token::Long => LONG_TOKEN_BALANCE_RANGE.to_vec(), + BRC20Token::Cats => CATS_TOKEN_BALANCE_RANGE.to_vec(), + BRC20Token::Btcs => BTCS_TOKEN_BALANCE_RANGE.to_vec(), + _ => { + vec![] + }, + } +} + +fn get_token_range_last(token: &BRC20Token) -> f64 { + match token { + BRC20Token::Ordi => *ORDI_TOKEN_BALANCE_RANGE.last().unwrap_or(&500.0), + BRC20Token::Sats => *SATS_TOKEN_BALANCE_RANGE.last().unwrap_or(&6_000_000_000.0), + BRC20Token::Rats => *RATS_TOKEN_BALANCE_RANGE.last().unwrap_or(&20_000_000.0), + BRC20Token::Mmss => *MMSS_TOKEN_BALANCE_RANGE.last().unwrap_or(&2000.0), + BRC20Token::Long => *LONG_TOKEN_BALANCE_RANGE.last().unwrap_or(&3000.0), + BRC20Token::Cats => *CATS_TOKEN_BALANCE_RANGE.last().unwrap_or(&800_000.0), + BRC20Token::Btcs => *BTCS_TOKEN_BALANCE_RANGE.last().unwrap_or(&800.0), + _ => 0.0, + } +} + +#[cfg(test)] +mod tests {} diff --git a/tee-worker/litentry/core/credentials/src/brc20/mod.rs b/tee-worker/litentry/core/credentials/src/brc20/mod.rs new file mode 100644 index 0000000000..40eee4424d --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/brc20/mod.rs @@ -0,0 +1,17 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +pub mod amount_holder; diff --git a/tee-worker/litentry/core/credentials/src/lib.rs b/tee-worker/litentry/core/credentials/src/lib.rs index 9eb4e65108..32e05d96fe 100644 --- a/tee-worker/litentry/core/credentials/src/lib.rs +++ b/tee-worker/litentry/core/credentials/src/lib.rs @@ -81,6 +81,7 @@ pub mod litentry_profile; pub mod oneblock; pub mod schema; use assertion_logic::{AssertionLogic, Op}; +pub mod brc20; pub mod generic_discord_role; pub mod nodereal; pub mod vip3; diff --git a/tee-worker/litentry/core/data-providers/src/geniidata.rs b/tee-worker/litentry/core/data-providers/src/geniidata.rs new file mode 100644 index 0000000000..7f7e27059b --- /dev/null +++ b/tee-worker/litentry/core/data-providers/src/geniidata.rs @@ -0,0 +1,113 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use crate::{ + build_client_with_cert, DataProviderConfigReader, Error as DataProviderError, + ReadDataProviderConfig, +}; +use http::header::ACCEPT; +use http_req::response::Headers; +use itc_rest_client::{ + error::Error as RestClientError, + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, + RestGet, RestPath, +}; +use litentry_primitives::ErrorDetail; +use serde::{Deserialize, Serialize}; +use std::{ + format, str, + string::{String, ToString}, + vec, + vec::Vec, +}; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ResponseItem { + pub tick: String, + pub address: String, + pub overall_balance: String, + pub transferable_balance: String, + pub available_balance: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct ReponseData { + pub count: u64, + pub limit: String, + pub offset: String, + pub list: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct GeniidataResponse { + pub code: u64, + pub message: String, + pub data: ReponseData, +} + +impl RestPath for GeniidataResponse { + fn get_path(path: String) -> core::result::Result { + Ok(path) + } +} + +pub struct GeniidataClient { + client: RestClient>, +} + +impl GeniidataClient { + pub fn new() -> core::result::Result { + let data_provider_config = DataProviderConfigReader::read()?; + + let mut headers = Headers::new(); + headers.insert(ACCEPT.as_str(), "application/json"); + headers.insert("api-key", data_provider_config.geniidata_api_key.as_str()); + + let client = build_client_with_cert(data_provider_config.geniidata_url.as_str(), headers); + + Ok(GeniidataClient { client }) + } + + pub fn create_brc20_amount_holder_sum( + &mut self, + addresses: Vec, + ) -> Result, DataProviderError> { + let mut all_items: Vec = Vec::new(); + for address in addresses { + let query = vec![("limit", "20"), ("offset", "0"), ("address", &address)]; + let response = self + .client + .get_with::("".to_string(), query.as_slice()) + .map_err(|e| { + DataProviderError::GeniiDataError(format!("GeniiData response error: {}", e)) + })?; + + all_items.extend(response.data.list); + } + + Ok(all_items) + } +} diff --git a/tee-worker/litentry/core/data-providers/src/lib.rs b/tee-worker/litentry/core/data-providers/src/lib.rs index 3dba91f5e9..0489aba446 100644 --- a/tee-worker/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/litentry/core/data-providers/src/lib.rs @@ -73,6 +73,7 @@ pub mod achainable; pub mod achainable_names; pub mod discord_litentry; pub mod discord_official; +pub mod geniidata; pub mod nodereal; pub mod nodereal_jsonrpc; pub mod twitter_official; @@ -191,6 +192,8 @@ pub struct DataProviderConfig { pub contest_popularity_discord_role_id: String, pub contest_participant_discord_role_id: String, pub vip3_url: String, + pub geniidata_url: String, + pub geniidata_api_key: String, } impl Default for DataProviderConfig { @@ -224,6 +227,8 @@ impl DataProviderConfig { contest_popularity_discord_role_id: "".to_string(), contest_participant_discord_role_id: "".to_string(), vip3_url: "".to_string(), + geniidata_url: "".to_string(), + geniidata_api_key: "".to_string(), } } pub fn set_twitter_official_url(&mut self, v: String) { @@ -314,6 +319,14 @@ impl DataProviderConfig { debug!("set_vip3_url: {:?}", v); self.vip3_url = v; } + pub fn set_geniidata_url(&mut self, v: String) { + debug!("set_geniidata_url: {:?}", v); + self.geniidata_url = v; + } + pub fn set_geniidata_api_key(&mut self, v: String) { + debug!("set_geniidata_api_key: {:?}", v); + self.geniidata_api_key = v; + } } lazy_static! { @@ -350,6 +363,9 @@ pub enum Error { #[error("Nodereal error: {0}")] NoderealError(String), + + #[error("GeniiData error: {0}")] + GeniiDataError(String), } impl IntoErrorDetail for Error { diff --git a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs index 8f2e89991b..45c419d20f 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs @@ -124,10 +124,14 @@ where lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build(&self.req), Assertion::LITStaking => lc_assertion_build::lit_staking::build(&self.req), + Assertion::EVMAmountHolding(token_type) => lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( &self.req, token_type, ), + + Assertion::BRC20AmountHolder => + lc_assertion_build::brc20::amount_holder::build(&self.req), }?; // post-process the credential diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs index 8b2129526a..85928d84e3 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs @@ -105,6 +105,9 @@ where lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( &self.req, token_type, ), + + Assertion::BRC20AmountHolder => + lc_assertion_build::brc20::amount_holder::build(&self.req), }?; // post-process the credential diff --git a/tee-worker/litentry/primitives/src/bitcoin_address.rs b/tee-worker/litentry/primitives/src/bitcoin_address.rs new file mode 100644 index 0000000000..32dcdcafcb --- /dev/null +++ b/tee-worker/litentry/primitives/src/bitcoin_address.rs @@ -0,0 +1,57 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use bitcoin::{ + address::Address, key::PublicKey, network::Network, secp256k1::Secp256k1, XOnlyPublicKey, +}; +use core::str::FromStr; +use std::string::{String, ToString}; + +// Some dependency conflict of bitcoin crate with enclave building +// when putting these functions into core-premitives/utils. +pub fn p2wpkh_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let address = Address::p2wpkh(&pubkey, Network::Bitcoin); + if let Ok(address) = address { + return address.to_string() + } + "".to_string() +} + +pub fn p2sh_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let address = Address::p2shwpkh(&pubkey, Network::Bitcoin); + if let Ok(address) = address { + return address.to_string() + } + "".to_string() +} + +pub fn p2tr_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); + // unisat wallet uses is this way + let secp = Secp256k1::verification_only(); + let address = Address::p2tr(&secp, xonly_pubkey, None, Network::Bitcoin); + address.to_string() +} + +pub fn p2pkh_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let address = Address::p2pkh(&pubkey, Network::Bitcoin); + address.to_string() +} diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index 35d019fb64..b27059e878 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -25,6 +25,7 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam mod aes; mod aes_request; +mod bitcoin_address; mod bitcoin_signature; mod ethereum_signature; mod identity; @@ -32,6 +33,7 @@ mod validation_data; pub use aes::*; pub use aes_request::*; +pub use bitcoin_address::*; pub use bitcoin_signature::*; pub use ethereum_signature::*; pub use identity::*; diff --git a/tee-worker/service/src/main_impl.rs b/tee-worker/service/src/main_impl.rs index f399835609..0d1b53eda0 100644 --- a/tee-worker/service/src/main_impl.rs +++ b/tee-worker/service/src/main_impl.rs @@ -1168,5 +1168,11 @@ fn get_data_provider_config(config: &Config) -> DataProviderConfig { if let Ok(v) = env::var("VIP3_URL") { data_provider_config.set_vip3_url(v); } + if let Ok(v) = env::var("GENIIDATA_URL") { + data_provider_config.set_geniidata_url(v); + } + if let Ok(v) = env::var("GENIIDATA_API_KEY") { + data_provider_config.set_geniidata_api_key(v); + } data_provider_config } diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index d6da902c89..ec23e2d96d 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -287,6 +287,7 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::GenericDiscordRole(_) => "GenericDiscordRole", Assertion::VIP3MembershipCard(..) => "VIP3MembershipCard", Assertion::WeirdoGhostGangHolder => "WeirdoGhostGangHolder", + Assertion::BRC20AmountHolder => "BRC20AmountHolder", Assertion::LITStaking => "LITStaking", Assertion::EVMAmountHolding(_) => "EVMAmountHolding", }, diff --git a/tee-worker/service/src/running-mode-config.json b/tee-worker/service/src/running-mode-config.json index b1b226af75..117cd7e55c 100644 --- a/tee-worker/service/src/running-mode-config.json +++ b/tee-worker/service/src/running-mode-config.json @@ -21,7 +21,9 @@ "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", - "vip3_url": "https://dappapi.vip3.io/" + "vip3_url": "https://dappapi.vip3.io/", + "geniidata_url": "https://api.geniidata.com/api/1/brc20/balance?", + "geniidata_api_key": "142cf1b0-1ca7-11ee-bb5e-9d74c2e854ac" }, "mock": { "twitter_official_url": "http://localhost:19527", @@ -45,7 +47,9 @@ "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", - "vip3_url": "https://dappapi.vip3.io/" + "vip3_url": "https://dappapi.vip3.io/", + "geniidata_url": "https://api.geniidata.com/api/1/brc20/balance?", + "geniidata_api_key": "142cf1b0-1ca7-11ee-bb5e-9d74c2e854ac" }, "prod": { "twitter_official_url": "https://api.twitter.com", @@ -69,7 +73,9 @@ "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", - "vip3_url": "https://dappapi.vip3.io/" + "vip3_url": "https://dappapi.vip3.io/", + "geniidata_url": "https://api.geniidata.com/api/1/brc20/balance?", + "geniidata_api_key": "142cf1b0-1ca7-11ee-bb5e-9d74c2e854ac" }, "staging": { "twitter_official_url": "https://api.twitter.com", @@ -93,6 +99,8 @@ "contest_legend_discord_role_id": "CONTEST_LEGEND_DISCORD_ROLE_ID", "contest_popularity_discord_role_id": "CONTEST_POPULARITY_DISCORD_ROLE_ID", "contest_participant_discord_role_id": "CONTEST_PARTICIPANT_DISCORD_ROLE_ID", - "vip3_url": "https://dappapi.vip3.io/" + "vip3_url": "https://dappapi.vip3.io/", + "geniidata_url": "https://api.geniidata.com/api/1/brc20/balance?", + "geniidata_api_key": "142cf1b0-1ca7-11ee-bb5e-9d74c2e854ac" } } \ No newline at end of file From 6b676c6737bb49541a17f9aae3f2fd44e4d98fd2 Mon Sep 17 00:00:00 2001 From: Igor Trofimov Date: Sat, 23 Dec 2023 19:46:08 +0200 Subject: [PATCH 20/43] increase time for CI tests (#2353) --- .github/workflows/ci.yml | 8 ++++---- ts-tests/tests/precompile-contract.test.ts | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a79308407..2ab68e47e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,8 +33,8 @@ on: branches: - dev paths-ignore: - - '**/dependabot.yml' - - '**/README.md' + - "**/dependabot.yml" + - "**/README.md" pull_request: branches: - dev @@ -225,7 +225,7 @@ jobs: - set-condition - sequentialise if: needs.set-condition.outputs.rebuild_tee == 'true' - container: 'litentry/litentry-tee-dev:latest' + container: "litentry/litentry-tee-dev:latest" steps: - uses: actions/checkout@v4 @@ -500,7 +500,7 @@ jobs: - name: Run ts tests for ${{ matrix.chain }} if: needs.set-condition.outputs.run_parachain_test == 'true' - timeout-minutes: 30 + timeout-minutes: 35 run: | make test-ts-docker-${{ matrix.chain }} diff --git a/ts-tests/tests/precompile-contract.test.ts b/ts-tests/tests/precompile-contract.test.ts index 19d15053db..efc9cec007 100644 --- a/ts-tests/tests/precompile-contract.test.ts +++ b/ts-tests/tests/precompile-contract.test.ts @@ -121,6 +121,7 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { // To see full params types for the interfaces, check notion page: https://web3builders.notion.site/Parachain-Precompile-Contract-0c34929e5f16408084446dcf3dd36006 step('Test precompile contract', async function () { + console.time('Test precompile contract'); const filterMode = (await context.api.query.extrinsicFilter.mode()).toHuman(); if ('Test' !== filterMode) { let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode('Test')); @@ -249,5 +250,7 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { // In case evm is not enabled in Normal Mode, switch back to filterMode, after test. let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode(filterMode)); await signAndSend(extrinsic, context.alice); + + console.timeEnd('Test precompile contract'); }); }); From 03d6ba3ed8b4778dde20db67a7dae1a395767715 Mon Sep 17 00:00:00 2001 From: BillyWooo Date: Sun, 24 Dec 2023 15:07:22 +0100 Subject: [PATCH 21/43] bug fix (#2354) --- Cargo.lock | 1 - primitives/core/src/assertion.rs | 8 +------- .../litentry/core/credentials/src/brc20/amount_holder.rs | 5 +++-- tee-worker/litentry/core/data-providers/src/geniidata.rs | 6 ++---- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d05e283dd6..3e6817f4d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8013,7 +8013,6 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", - "log", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "sp-api", diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index df639eb4dc..b61879ba81 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -292,13 +292,7 @@ impl Assertion { // EVM Amount Holding Self::EVMAmountHolding(_) => vec![Web3Network::Ethereum, Web3Network::Bsc], // BRC20 Holder - Self::BRC20AmountHolder => vec![ - Web3Network::BitcoinP2tr, - Web3Network::BitcoinP2pkh, - Web3Network::BitcoinP2sh, - Web3Network::BitcoinP2wpkh, - Web3Network::BitcoinP2wsh, - ], + Self::BRC20AmountHolder => vec![Web3Network::BitcoinP2tr], // we don't care about any specific web3 network Self::A1 | Self::A2(..) | diff --git a/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs b/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs index 21d54c2264..ddd3d4659c 100644 --- a/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs +++ b/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs @@ -26,7 +26,8 @@ const VC_BRC20_AMOUNT_HOLDER_DESCRIPTIONS: &str = "The amount of a particular token you are holding"; const VC_BRC20_AMOUNT_HOLDER_TYPE: &str = "Token holding amount"; -const BRC20_TOKENS: [&str; 7] = ["ordi", "sats", "rats", "Mmss", "long", "cats", "BTCs"]; +// Keep all name in lowercase here by purpose +const BRC20_TOKENS: [&str; 7] = ["ordi", "sats", "rats", "mmss", "long", "cats", "btcs"]; const ORDI_TOKEN_BALANCE_RANGE: [f64; 8] = [0.0, 1.0, 5.0, 20.0, 50.0, 100.0, 200.0, 500.0]; const SATS_TOKEN_BALANCE_RANGE: [f64; 8] = [ 0.0, @@ -72,7 +73,7 @@ pub trait BRC20AmountHolderCredential { impl BRC20AmountHolderCredential for Credential { fn update_brc20_amount_holder_credential(&mut self, response_items: &[ResponseItem]) { for item in response_items { - if BRC20_TOKENS.contains(&item.tick.as_str()) { + if BRC20_TOKENS.contains(&item.tick.to_lowercase().as_str()) { let token = tick_to_brctoken(&item.tick); let balance: f64 = item.overall_balance.parse().unwrap_or(0.0); update_assertion(token, balance, self); diff --git a/tee-worker/litentry/core/data-providers/src/geniidata.rs b/tee-worker/litentry/core/data-providers/src/geniidata.rs index 7f7e27059b..e733f1df6c 100644 --- a/tee-worker/litentry/core/data-providers/src/geniidata.rs +++ b/tee-worker/litentry/core/data-providers/src/geniidata.rs @@ -24,7 +24,7 @@ use crate::{ build_client_with_cert, DataProviderConfigReader, Error as DataProviderError, ReadDataProviderConfig, }; -use http::header::ACCEPT; +use http::header::{ACCEPT, CONNECTION}; use http_req::response::Headers; use itc_rest_client::{ error::Error as RestClientError, @@ -42,7 +42,6 @@ use std::{ }; #[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] pub struct ResponseItem { pub tick: String, pub address: String, @@ -52,7 +51,6 @@ pub struct ResponseItem { } #[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] struct ReponseData { pub count: u64, pub limit: String, @@ -61,7 +59,6 @@ struct ReponseData { } #[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] struct GeniidataResponse { pub code: u64, pub message: String, @@ -83,6 +80,7 @@ impl GeniidataClient { let data_provider_config = DataProviderConfigReader::read()?; let mut headers = Headers::new(); + headers.insert(CONNECTION.as_str(), "close"); headers.insert(ACCEPT.as_str(), "application/json"); headers.insert("api-key", data_provider_config.geniidata_api_key.as_str()); From b61adbcda0862a3346e52f475b7a4d2a5c230b54 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Mon, 25 Dec 2023 04:49:59 +0800 Subject: [PATCH 22/43] add list (#2355) --- tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs b/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs index ddd3d4659c..b70173ac3b 100644 --- a/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs +++ b/tee-worker/litentry/core/credentials/src/brc20/amount_holder.rs @@ -24,7 +24,7 @@ use std::vec::Vec; const VC_BRC20_AMOUNT_HOLDER_DESCRIPTIONS: &str = "The amount of a particular token you are holding"; -const VC_BRC20_AMOUNT_HOLDER_TYPE: &str = "Token holding amount"; +const VC_BRC20_AMOUNT_HOLDER_TYPE: &str = "Token holding amount list"; // Keep all name in lowercase here by purpose const BRC20_TOKENS: [&str; 7] = ["ordi", "sats", "rats", "mmss", "long", "cats", "btcs"]; From f0ec132d81c70f2e667b3330fc574d09c57996af Mon Sep 17 00:00:00 2001 From: BillyWooo Date: Tue, 26 Dec 2023 22:32:11 +0100 Subject: [PATCH 23/43] force set the order and index before widely usage. (#2351) Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com> --- primitives/core/src/assertion.rs | 4 ++-- tee-worker/service/src/prometheus_metrics.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index b61879ba81..3f36328022 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -249,10 +249,10 @@ pub enum Assertion { #[codec(index = 20)] LITStaking, - #[codec(index = 22)] + #[codec(index = 21)] EVMAmountHolding(EVMTokenType), // (evm_token_type) - #[codec(index = 23)] + #[codec(index = 22)] BRC20AmountHolder, } diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index ec23e2d96d..d345a4bf2b 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -287,9 +287,9 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::GenericDiscordRole(_) => "GenericDiscordRole", Assertion::VIP3MembershipCard(..) => "VIP3MembershipCard", Assertion::WeirdoGhostGangHolder => "WeirdoGhostGangHolder", - Assertion::BRC20AmountHolder => "BRC20AmountHolder", Assertion::LITStaking => "LITStaking", Assertion::EVMAmountHolding(_) => "EVMAmountHolding", + Assertion::BRC20AmountHolder => "BRC20AmountHolder", }, }; inc_stf_calls(category, label); From bce29ac6e0d91398b4901a783afcc5dd23c371c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:12:20 +0000 Subject: [PATCH 24/43] Bump tokio from 1.35.0 to 1.35.1 (#2360) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.35.0 to 1.35.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.35.0...tokio-1.35.1) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- node/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e6817f4d5..31abf9e548 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13924,9 +13924,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", diff --git a/node/Cargo.toml b/node/Cargo.toml index fb75e823d1..9899f02c85 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -22,7 +22,7 @@ futures = { version = "0.3.29", features = ["compat"] } log = "0.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.35.0", features = ["macros", "sync"] } +tokio = { version = "1.35.1", features = ["macros", "sync"] } # Substrate dependencies sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } From 3c7053a7dc23f07be9b14bc15d9c53d3070c23ba Mon Sep 17 00:00:00 2001 From: Verin1005 <104152026+Verin1005@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:40:34 +0800 Subject: [PATCH 25/43] Adjust the directory structure of litentry-parachain/ts-tests. (#2365) * Restructuring of folder * fix path issue * rename && fix requires * fix keys path * debug with ganache * test path * modify path * fix require issue * debug clean-local-docker.sh * format * tsconfig.json * Rename bridge.json to Bridge.json * Rename staking.json to Staking.json --------- Co-authored-by: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> --- scripts/clean-local-docker.sh | 5 +- .../abi/bridge}/Bridge.json | 0 .../abi/bridge}/ERC20Handler.json | 0 .../abi/bridge}/ERC721Handler.json | 0 .../abi/bridge}/GenericHandler.json | 0 .../abi/bridge}/MintableERC20.json | 0 .../contracts => common/abi/bridge}/README.md | 0 .../abi/precompile/Bridge.json} | 0 .../abi/precompile}/README.md | 0 .../abi/precompile/Staking.json} | 0 ...8FfB2074A9e59eD58142822b3eB3fcBffb0cd7.key | 0 ...962717f8fA5BA3b931bACaF9ac03924EB475a0.key | 0 ...EEf6139f00F9F4535Ad19640Ff7A0137708485.key | 0 ...0a907331554AF72563Bd8D43051C2E64Be5d35.key | 0 ...93B45308FD417dF303D6515aB04D9e89a750Ca.key | 0 ...Tznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy.key | 0 ...Xgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty.key | 0 ...RKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y.key | 0 ...Xb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.key | 0 ...FCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw.key | 0 .../setup}/register-parathread.ts | 2 +- .../{tests => common/setup}/setup-bridge.ts | 21 ++++--- .../{tests => common/setup}/setup-enclave.ts | 16 ++--- .../setup}/upgrade-parathread.ts | 2 +- ts-tests/{tests => common/utils}/compile.ts | 25 ++++---- ts-tests/common/utils/config.ts | 14 +++++ ts-tests/common/utils/function.ts | 42 +++++++++++++ ts-tests/common/utils/index.ts | 3 + .../utils/integration-setup.ts} | 59 +------------------ ts-tests/global.d.ts | 1 + .../base-filter.test.ts | 2 +- .../bridge.test.ts | 9 ++- .../evm-contract.test.ts | 4 +- .../evm-transfer.test.ts | 2 +- .../precompile-contract.test.ts | 6 +- .../runtime-upgrade.test.ts | 2 +- .../transaction-fee.test.ts | 2 +- .../transfer.test.ts | 2 +- ts-tests/package.json | 24 ++++---- ts-tests/tests/global.d.ts | 1 - ts-tests/tsconfig.json | 2 +- 41 files changed, 124 insertions(+), 122 deletions(-) rename ts-tests/{bridge/contracts => common/abi/bridge}/Bridge.json (100%) rename ts-tests/{bridge/contracts => common/abi/bridge}/ERC20Handler.json (100%) rename ts-tests/{bridge/contracts => common/abi/bridge}/ERC721Handler.json (100%) rename ts-tests/{bridge/contracts => common/abi/bridge}/GenericHandler.json (100%) rename ts-tests/{bridge/contracts => common/abi/bridge}/MintableERC20.json (100%) rename ts-tests/{bridge/contracts => common/abi/bridge}/README.md (100%) rename ts-tests/{precompile/contracts/bridge.json => common/abi/precompile/Bridge.json} (100%) rename ts-tests/{precompile/contracts => common/abi/precompile}/README.md (100%) rename ts-tests/{precompile/contracts/staking.json => common/abi/precompile/Staking.json} (100%) rename ts-tests/{bridge => common}/keys/0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7.key (100%) rename ts-tests/{bridge => common}/keys/0x24962717f8fA5BA3b931bACaF9ac03924EB475a0.key (100%) rename ts-tests/{bridge => common}/keys/0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485.key (100%) rename ts-tests/{bridge => common}/keys/0x8e0a907331554AF72563Bd8D43051C2E64Be5d35.key (100%) rename ts-tests/{bridge => common}/keys/0xff93B45308FD417dF303D6515aB04D9e89a750Ca.key (100%) rename ts-tests/{bridge => common}/keys/5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy.key (100%) rename ts-tests/{bridge => common}/keys/5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty.key (100%) rename ts-tests/{bridge => common}/keys/5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y.key (100%) rename ts-tests/{bridge => common}/keys/5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.key (100%) rename ts-tests/{bridge => common}/keys/5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw.key (100%) rename ts-tests/{tests => common/setup}/register-parathread.ts (96%) rename ts-tests/{tests => common/setup}/setup-bridge.ts (96%) rename ts-tests/{tests => common/setup}/setup-enclave.ts (81%) rename ts-tests/{tests => common/setup}/upgrade-parathread.ts (97%) rename ts-tests/{tests => common/utils}/compile.ts (74%) create mode 100644 ts-tests/common/utils/config.ts create mode 100644 ts-tests/common/utils/function.ts create mode 100644 ts-tests/common/utils/index.ts rename ts-tests/{tests/utils.ts => common/utils/integration-setup.ts} (59%) create mode 100644 ts-tests/global.d.ts rename ts-tests/{tests => integration-tests}/base-filter.test.ts (97%) rename ts-tests/{tests => integration-tests}/bridge.test.ts (98%) rename ts-tests/{tests => integration-tests}/evm-contract.test.ts (99%) rename ts-tests/{tests => integration-tests}/evm-transfer.test.ts (99%) rename ts-tests/{tests => integration-tests}/precompile-contract.test.ts (97%) rename ts-tests/{tests => integration-tests}/runtime-upgrade.test.ts (97%) rename ts-tests/{tests => integration-tests}/transaction-fee.test.ts (99%) rename ts-tests/{tests => integration-tests}/transfer.test.ts (96%) delete mode 100644 ts-tests/tests/global.d.ts diff --git a/scripts/clean-local-docker.sh b/scripts/clean-local-docker.sh index 09f9bd3d47..b8ae7bcf79 100755 --- a/scripts/clean-local-docker.sh +++ b/scripts/clean-local-docker.sh @@ -40,7 +40,6 @@ IMG=$(docker images --filter=reference="generated-$CHAIN*" --format "{{.Reposito [ -z "$IMG" ] || docker rmi -f $IMG rm -rf "$LITENTRY_PARACHAIN_DIR" -rm -rf "$ROOTDIR/ts-tests/bridge/bob.json" -rm -rf "$ROOTDIR/ts-tests/bridge/data/" - +rm -rf "$ROOTDIR/ts-tests/common/bob.json" +rm -rf "$ROOTDIR/ts-tests/common/data/" echo "cleaned up." diff --git a/ts-tests/bridge/contracts/Bridge.json b/ts-tests/common/abi/bridge/Bridge.json similarity index 100% rename from ts-tests/bridge/contracts/Bridge.json rename to ts-tests/common/abi/bridge/Bridge.json diff --git a/ts-tests/bridge/contracts/ERC20Handler.json b/ts-tests/common/abi/bridge/ERC20Handler.json similarity index 100% rename from ts-tests/bridge/contracts/ERC20Handler.json rename to ts-tests/common/abi/bridge/ERC20Handler.json diff --git a/ts-tests/bridge/contracts/ERC721Handler.json b/ts-tests/common/abi/bridge/ERC721Handler.json similarity index 100% rename from ts-tests/bridge/contracts/ERC721Handler.json rename to ts-tests/common/abi/bridge/ERC721Handler.json diff --git a/ts-tests/bridge/contracts/GenericHandler.json b/ts-tests/common/abi/bridge/GenericHandler.json similarity index 100% rename from ts-tests/bridge/contracts/GenericHandler.json rename to ts-tests/common/abi/bridge/GenericHandler.json diff --git a/ts-tests/bridge/contracts/MintableERC20.json b/ts-tests/common/abi/bridge/MintableERC20.json similarity index 100% rename from ts-tests/bridge/contracts/MintableERC20.json rename to ts-tests/common/abi/bridge/MintableERC20.json diff --git a/ts-tests/bridge/contracts/README.md b/ts-tests/common/abi/bridge/README.md similarity index 100% rename from ts-tests/bridge/contracts/README.md rename to ts-tests/common/abi/bridge/README.md diff --git a/ts-tests/precompile/contracts/bridge.json b/ts-tests/common/abi/precompile/Bridge.json similarity index 100% rename from ts-tests/precompile/contracts/bridge.json rename to ts-tests/common/abi/precompile/Bridge.json diff --git a/ts-tests/precompile/contracts/README.md b/ts-tests/common/abi/precompile/README.md similarity index 100% rename from ts-tests/precompile/contracts/README.md rename to ts-tests/common/abi/precompile/README.md diff --git a/ts-tests/precompile/contracts/staking.json b/ts-tests/common/abi/precompile/Staking.json similarity index 100% rename from ts-tests/precompile/contracts/staking.json rename to ts-tests/common/abi/precompile/Staking.json diff --git a/ts-tests/bridge/keys/0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7.key b/ts-tests/common/keys/0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7.key similarity index 100% rename from ts-tests/bridge/keys/0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7.key rename to ts-tests/common/keys/0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7.key diff --git a/ts-tests/bridge/keys/0x24962717f8fA5BA3b931bACaF9ac03924EB475a0.key b/ts-tests/common/keys/0x24962717f8fA5BA3b931bACaF9ac03924EB475a0.key similarity index 100% rename from ts-tests/bridge/keys/0x24962717f8fA5BA3b931bACaF9ac03924EB475a0.key rename to ts-tests/common/keys/0x24962717f8fA5BA3b931bACaF9ac03924EB475a0.key diff --git a/ts-tests/bridge/keys/0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485.key b/ts-tests/common/keys/0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485.key similarity index 100% rename from ts-tests/bridge/keys/0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485.key rename to ts-tests/common/keys/0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485.key diff --git a/ts-tests/bridge/keys/0x8e0a907331554AF72563Bd8D43051C2E64Be5d35.key b/ts-tests/common/keys/0x8e0a907331554AF72563Bd8D43051C2E64Be5d35.key similarity index 100% rename from ts-tests/bridge/keys/0x8e0a907331554AF72563Bd8D43051C2E64Be5d35.key rename to ts-tests/common/keys/0x8e0a907331554AF72563Bd8D43051C2E64Be5d35.key diff --git a/ts-tests/bridge/keys/0xff93B45308FD417dF303D6515aB04D9e89a750Ca.key b/ts-tests/common/keys/0xff93B45308FD417dF303D6515aB04D9e89a750Ca.key similarity index 100% rename from ts-tests/bridge/keys/0xff93B45308FD417dF303D6515aB04D9e89a750Ca.key rename to ts-tests/common/keys/0xff93B45308FD417dF303D6515aB04D9e89a750Ca.key diff --git a/ts-tests/bridge/keys/5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy.key b/ts-tests/common/keys/5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy.key similarity index 100% rename from ts-tests/bridge/keys/5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy.key rename to ts-tests/common/keys/5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy.key diff --git a/ts-tests/bridge/keys/5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty.key b/ts-tests/common/keys/5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty.key similarity index 100% rename from ts-tests/bridge/keys/5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty.key rename to ts-tests/common/keys/5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty.key diff --git a/ts-tests/bridge/keys/5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y.key b/ts-tests/common/keys/5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y.key similarity index 100% rename from ts-tests/bridge/keys/5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y.key rename to ts-tests/common/keys/5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y.key diff --git a/ts-tests/bridge/keys/5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.key b/ts-tests/common/keys/5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.key similarity index 100% rename from ts-tests/bridge/keys/5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.key rename to ts-tests/common/keys/5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.key diff --git a/ts-tests/bridge/keys/5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw.key b/ts-tests/common/keys/5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw.key similarity index 100% rename from ts-tests/bridge/keys/5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw.key rename to ts-tests/common/keys/5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw.key diff --git a/ts-tests/tests/register-parathread.ts b/ts-tests/common/setup/register-parathread.ts similarity index 96% rename from ts-tests/tests/register-parathread.ts rename to ts-tests/common/setup/register-parathread.ts index 81d1b2f86f..01de1dc613 100644 --- a/ts-tests/tests/register-parathread.ts +++ b/ts-tests/common/setup/register-parathread.ts @@ -3,7 +3,7 @@ import '@polkadot/api-augment'; import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; import { TypeRegistry } from '@polkadot/types/create'; import { Bytes } from '@polkadot/types'; -import { loadConfig, signAndSend } from './utils'; +import { loadConfig, signAndSend } from '../utils'; async function registerParathread(api: ApiPromise, config: any) { // Get keyring of Alice, who is also the sudo in dev chain spec diff --git a/ts-tests/tests/setup-bridge.ts b/ts-tests/common/setup/setup-bridge.ts similarity index 96% rename from ts-tests/tests/setup-bridge.ts rename to ts-tests/common/setup/setup-bridge.ts index 1978d9fd3a..75fbded4b6 100644 --- a/ts-tests/tests/setup-bridge.ts +++ b/ts-tests/common/setup/setup-bridge.ts @@ -5,15 +5,15 @@ import { Contract, ethers, Wallet } from 'ethers'; import { BN } from '@polkadot/util'; import fs from 'fs'; import { spawn } from 'child_process'; -import { initApiPromise, loadConfig, ParachainConfig, signAndSend, sleep, sudoWrapper } from './utils'; +import { initApiPromise, loadConfig, ParachainConfig, signAndSend, sleep, sudoWrapper } from '../utils'; import { toWei } from 'web3-utils'; const path = require('path'); -const BridgeContract = require('../bridge/contracts/Bridge.json'); -const ERC20HandlerContract = require('../bridge/contracts/ERC20Handler.json'); -const ERC721HandlerContract = require('../bridge/contracts/ERC721Handler.json'); -const GenericHandlerContract = require('../bridge/contracts/GenericHandler.json'); -const ERC20Contract = require('../bridge/contracts/MintableERC20.json'); +const BridgeContract = require('../abi/bridge/Bridge.json'); +const ERC20HandlerContract = require('../abi/bridge/ERC20Handler.json'); +const ERC721HandlerContract = require('../abi/bridge/ERC721Handler.json'); +const GenericHandlerContract = require('../abi/bridge/GenericHandler.json'); +const ERC20Contract = require('../abi/bridge/MintableERC20.json'); class EthConfig { wallets!: { alice: Wallet; bob: Wallet; charlie: Wallet; dave: Wallet; eve: Wallet }; @@ -236,7 +236,7 @@ async function startChainBridge( log: string ) { require('dotenv').config(); - const dataDir = './bridge/data'; + const dataDir = './common/data'; if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }); } @@ -255,10 +255,11 @@ async function startChainBridge( config ); const logging = fs.createWriteStream(log, { flags: 'w+' }); + const lsProcess = spawn( // `${process.env.GOPATH}/bin/chainbridge`, bridgePath, - ['--verbosity', 'trace', '--blockstore', dataDir, '--config', config, '--keystore', './bridge/keys'], + ['--verbosity', 'trace', '--blockstore', dataDir, '--config', config, '--keystore', './common/keys'], { env: { STAGE: 'dev' } } ); lsProcess.stdout.pipe(logging); @@ -300,6 +301,7 @@ export function describeCrossChainTransfer( const parachainConfig = await initApiPromise(config); const provider = new ethers.providers.JsonRpcProvider(config.eth_endpoint); + const wallets = { alice: new ethers.Wallet(generateTestKeys().alice, provider), bob: new ethers.Wallet(generateTestKeys().bob, provider), @@ -307,6 +309,7 @@ export function describeCrossChainTransfer( dave: new ethers.Wallet(generateTestKeys().dave, provider), eve: new ethers.Wallet(generateTestKeys().eve, provider), }; + const { bridge, erc20Handler, erc721Handler, genericHandler, erc20 } = await deployBridgeContracts( wallets.alice ); @@ -336,7 +339,7 @@ export function describeCrossChainTransfer( ethConfig.wallets.bob.address, parachainConfig.bob.address, config.bridge_path, - './bridge/bob.json', + './common/bob.json', '/tmp/parachain_dev/bob.log' ); await sleep(5); diff --git a/ts-tests/tests/setup-enclave.ts b/ts-tests/common/setup/setup-enclave.ts similarity index 81% rename from ts-tests/tests/setup-enclave.ts rename to ts-tests/common/setup/setup-enclave.ts index ae1d2203f3..36faf3db7b 100644 --- a/ts-tests/tests/setup-enclave.ts +++ b/ts-tests/common/setup/setup-enclave.ts @@ -1,9 +1,6 @@ -import fs from 'fs'; import '@polkadot/api-augment'; import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; -import { TypeRegistry } from '@polkadot/types/create'; -import { Bytes } from '@polkadot/types'; -import { loadConfig, signAndSend } from './utils'; +import { loadConfig, signAndSend } from '../utils'; import { hexToU8a } from '@polkadot/util'; const mrenclave = process.argv[2]; @@ -14,7 +11,7 @@ async function setAliceAsAdmin(api: ApiPromise, config: any) { const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - const tx = api.tx.sudo.sudo(api.tx.teerex.setAdmin('esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5')); + const tx = api.tx.sudo.sudo(api.tx.teerex.setAdmin('esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5')); console.log(`Setting Alice as Admin for Teerex`); return signAndSend(tx, alice); @@ -23,11 +20,11 @@ async function setAliceAsAdmin(api: ApiPromise, config: any) { async function updateScheduledEnclave(api: ApiPromise, config: any) { const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - + const tx = api.tx.teerex.updateScheduledEnclave(block, hexToU8a(`0x${mrenclave}`)); - console.log("Schedule Enclave Extrinsic sent"); - return signAndSend(tx, alice) + console.log('Schedule Enclave Extrinsic sent'); + return signAndSend(tx, alice); } (async () => { @@ -41,11 +38,10 @@ async function updateScheduledEnclave(api: ApiPromise, config: any) { await setAliceAsAdmin(api, config); await updateScheduledEnclave(api, config); - + await api.disconnect(); provider.on('disconnected', () => { console.log('Disconnect from relaychain'); process.exit(0); }); })(); - diff --git a/ts-tests/tests/upgrade-parathread.ts b/ts-tests/common/setup/upgrade-parathread.ts similarity index 97% rename from ts-tests/tests/upgrade-parathread.ts rename to ts-tests/common/setup/upgrade-parathread.ts index 2e9b6d1122..a794c0656d 100644 --- a/ts-tests/tests/upgrade-parathread.ts +++ b/ts-tests/common/setup/upgrade-parathread.ts @@ -1,7 +1,7 @@ import '@polkadot/api-augment'; import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; import type { ISubmittableResult } from '@polkadot/types/types'; -import { loadConfig } from './utils'; +import { loadConfig } from '../utils'; // upgrade the parathread to parachain by forcibly leasing a certain period // can be used to extend the leasing period if it's already in onboarding process diff --git a/ts-tests/tests/compile.ts b/ts-tests/common/utils/compile.ts similarity index 74% rename from ts-tests/tests/compile.ts rename to ts-tests/common/utils/compile.ts index ac6f42ad67..e1fdeede77 100644 --- a/ts-tests/tests/compile.ts +++ b/ts-tests/common/utils/compile.ts @@ -25,22 +25,21 @@ contract Hello { const input = { language: 'Solidity', sources: { - 'hello.sol': { - content: source - } + 'hello.sol': { + content: source, + }, }, settings: { - outputSelection: { - '*': { - '*': ['*'] - } - }, - // evmVersion: "byzantium", - } - }; + outputSelection: { + '*': { + '*': ['*'], + }, + }, + // evmVersion: "byzantium", + }, +}; const result = JSON.parse(solcWrapper.compile(JSON.stringify(input))); if (!result.contracts) { - console.log(result.errors); + console.log(result.errors); } export const compiled: any = result.contracts['hello.sol']['Hello']; - diff --git a/ts-tests/common/utils/config.ts b/ts-tests/common/utils/config.ts new file mode 100644 index 0000000000..256f9152de --- /dev/null +++ b/ts-tests/common/utils/config.ts @@ -0,0 +1,14 @@ +export function loadConfig() { + require('dotenv').config(); + switch (process.env.NODE_ENV) { + case 'local': + return require('../../config.local.json'); + case 'test': + case 'ci': + return require('../../config.ci.json'); + case 'staging': + return require('../../config.staging.json'); + default: + throw new Error(`Invalid NODE_ENV: ${process.env.NODE_ENV}`); + } +} diff --git a/ts-tests/common/utils/function.ts b/ts-tests/common/utils/function.ts new file mode 100644 index 0000000000..5da60e9104 --- /dev/null +++ b/ts-tests/common/utils/function.ts @@ -0,0 +1,42 @@ +import { AddressOrPair, ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; +import { ApiPromise } from '@polkadot/api'; + +export function sleep(secs: number) { + return new Promise((resolve) => { + setTimeout(resolve, secs * 1000); + }); +} + +export function signAndSend(tx: SubmittableExtrinsic, account: AddressOrPair) { + return new Promise<{ block: string }>(async (resolve, reject) => { + await tx.signAndSend(account, (result) => { + console.log(`Current status is ${result.status}`); + if (result.status.isInBlock) { + console.log(`Transaction included at blockHash ${result.status.asInBlock}`); + } else if (result.status.isFinalized) { + console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`); + resolve({ + block: result.status.asFinalized.toString(), + }); + } else if (result.status.isInvalid) { + reject(`Transaction is ${result.status}`); + } + }); + }); +} + +// After removing the sudo module, we use `EnsureRootOrHalfCouncil` instead of `Sudo`, +// and there are only two council members in litmus-dev/rococo-dev/litentry-dev. +// So only `propose` is required, no vote. +// +// TODO: support to send the `vote extrinsic`, if the number of council members is greater than 2. +export async function sudoWrapper(api: ApiPromise, tx: SubmittableExtrinsic) { + const chain = (await api.rpc.system.chain()).toString().toLowerCase(); + if (chain == 'litmus-dev') { + const threshold = api.createType('Compact', 1); + const call = api.createType('Call', tx); + return api.tx.council.propose(threshold, call, api.createType('Compact', tx.length)); + } else { + return api.tx.sudo.sudo(tx); + } +} diff --git a/ts-tests/common/utils/index.ts b/ts-tests/common/utils/index.ts new file mode 100644 index 0000000000..537f5e77e5 --- /dev/null +++ b/ts-tests/common/utils/index.ts @@ -0,0 +1,3 @@ +export * from './config'; +export * from './integration-setup'; +export * from './function'; diff --git a/ts-tests/tests/utils.ts b/ts-tests/common/utils/integration-setup.ts similarity index 59% rename from ts-tests/tests/utils.ts rename to ts-tests/common/utils/integration-setup.ts index 52cc919c51..099dc6cd37 100644 --- a/ts-tests/tests/utils.ts +++ b/ts-tests/common/utils/integration-setup.ts @@ -1,10 +1,8 @@ import 'mocha'; - import '@polkadot/api-augment'; import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; -import { AddressOrPair, ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; import { KeyringPair } from '@polkadot/keyring/types'; -import { BN } from '@polkadot/util'; +import { loadConfig } from './config'; export class ParachainConfig { api!: ApiPromise; @@ -15,27 +13,6 @@ export class ParachainConfig { ferdie!: KeyringPair; } -export function loadConfig() { - require('dotenv').config(); - switch (process.env.NODE_ENV) { - case 'local': - return require('../config.local.json') - case 'test': - case 'ci': - return require('../config.ci.json'); - case 'staging': - return require('../config.staging.json'); - default: - throw new Error(`Invalid NODE_ENV: ${process.env.NODE_ENV}`); - } -} - -export function sleep(secs: number) { - return new Promise((resolve) => { - setTimeout(resolve, secs * 1000); - }); -} - export async function initApiPromise(config: any): Promise { console.log(`Initiating the API (ignore message "Unable to resolve type B..." and "Unknown types found...")`); // Provider is set for parachain node @@ -76,40 +53,6 @@ export async function initApiPromise(config: any): Promise { return { api, parachain, alice, bob, eve, ferdie }; } -export function signAndSend(tx: SubmittableExtrinsic, account: AddressOrPair) { - return new Promise<{ block: string }>(async (resolve, reject) => { - await tx.signAndSend(account, (result) => { - console.log(`Current status is ${result.status}`); - if (result.status.isInBlock) { - console.log(`Transaction included at blockHash ${result.status.asInBlock}`); - } else if (result.status.isFinalized) { - console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`); - resolve({ - block: result.status.asFinalized.toString(), - }); - } else if (result.status.isInvalid) { - reject(`Transaction is ${result.status}`); - } - }); - }); -} - -// After removing the sudo module, we use `EnsureRootOrHalfCouncil` instead of `Sudo`, -// and there are only two council members in litmus-dev/rococo-dev/litentry-dev. -// So only `propose` is required, no vote. -// -// TODO: support to send the `vote extrinsic`, if the number of council members is greater than 2. -export async function sudoWrapper(api: ApiPromise, tx: SubmittableExtrinsic) { - const chain = (await api.rpc.system.chain()).toString().toLowerCase(); - if (chain == 'litmus-dev') { - const threshold = api.createType('Compact', 1); - const call = api.createType('Call', tx); - return api.tx.council.propose(threshold, call, api.createType('Compact', tx.length)); - } else { - return api.tx.sudo.sudo(tx); - } -} - export function describeLitentry(title: string, specFilename: string, cb: (context: ParachainConfig) => void) { describe(title, function () { // Set timeout to 6000 seconds (Because of 50-blocks delay of rococo, so called "training wheels") diff --git a/ts-tests/global.d.ts b/ts-tests/global.d.ts new file mode 100644 index 0000000000..905f98a29b --- /dev/null +++ b/ts-tests/global.d.ts @@ -0,0 +1 @@ +declare module 'solc'; diff --git a/ts-tests/tests/base-filter.test.ts b/ts-tests/integration-tests/base-filter.test.ts similarity index 97% rename from ts-tests/tests/base-filter.test.ts rename to ts-tests/integration-tests/base-filter.test.ts index e5b43f7077..5bc277d386 100644 --- a/ts-tests/tests/base-filter.test.ts +++ b/ts-tests/integration-tests/base-filter.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { step } from 'mocha-steps'; -import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; +import { signAndSend, describeLitentry } from '../common/utils'; describeLitentry('Test Base Filter', ``, (context) => { console.log(`Test Base Filter`); diff --git a/ts-tests/tests/bridge.test.ts b/ts-tests/integration-tests/bridge.test.ts similarity index 98% rename from ts-tests/tests/bridge.test.ts rename to ts-tests/integration-tests/bridge.test.ts index ff803199f8..2a0844ef6b 100644 --- a/ts-tests/tests/bridge.test.ts +++ b/ts-tests/integration-tests/bridge.test.ts @@ -1,7 +1,7 @@ -import { createERCDepositData, describeCrossChainTransfer } from './setup-bridge'; +import { createERCDepositData, describeCrossChainTransfer } from '../common/setup/setup-bridge'; import { step } from 'mocha-steps'; import { toHex } from 'web3-utils'; -import { signAndSend, sleep } from './utils'; +import { signAndSend, sleep } from '../common/utils'; import { assert } from 'chai'; import { BigNumber, ethers } from 'ethers'; @@ -15,8 +15,11 @@ describeCrossChainTransfer('Test Cross-chain Transfer', ``, (context) => { // substrate native token // const destResourceId = "0x00000000000000000000000000000063a7e2be78898ba83824b0c0cc8dfb6001" const destResourceId = context.parachainConfig.api.consts.bridgeTransfer.nativeTokenResourceId.toHex(); + const depositAmount = toHex(BigNumber.from('100,000,000,000,000,000,000'.replace(/,/g, '')).toString()); let destinationChainID = parseInt(context.parachainConfig.api.consts.chainBridge.bridgeChainId.toString()); + console.log(destinationChainID); + //FERDIE key command: polkadot key inspect //Ferdie const destinationRecipientAddress = '0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c'; @@ -64,7 +67,7 @@ describeCrossChainTransfer('Test Cross-chain Transfer', ``, (context) => { context.ethConfig.erc20Handler.address ); const fee = await context.parachainConfig.api.query.chainBridge.bridgeFee(0); - const Bridge = require('../bridge/contracts/Bridge.json'); + const Bridge = require('../common/abi/bridge/Bridge.json'); const inter = new ethers.utils.Interface(Bridge.abi); await signAndSend( context.parachainConfig.api.tx.bridgeTransfer.transferNative( diff --git a/ts-tests/tests/evm-contract.test.ts b/ts-tests/integration-tests/evm-contract.test.ts similarity index 99% rename from ts-tests/tests/evm-contract.test.ts rename to ts-tests/integration-tests/evm-contract.test.ts index b94771c1e7..4811b9cb94 100644 --- a/ts-tests/tests/evm-contract.test.ts +++ b/ts-tests/integration-tests/evm-contract.test.ts @@ -1,11 +1,11 @@ import { assert, expect } from 'chai'; import { step } from 'mocha-steps'; -import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; +import { signAndSend, describeLitentry, loadConfig, sleep } from '../common/utils'; import { evmToAddress } from '@polkadot/util-crypto'; import Web3 from 'web3'; -import { compiled } from './compile'; +import { compiled } from '../common/utils/compile'; describeLitentry('Test EVM Module Contract', ``, (context) => { console.log(`Test EVM Module Contract`); diff --git a/ts-tests/tests/evm-transfer.test.ts b/ts-tests/integration-tests/evm-transfer.test.ts similarity index 99% rename from ts-tests/tests/evm-transfer.test.ts rename to ts-tests/integration-tests/evm-transfer.test.ts index 82b6904c03..b7a5d7fe52 100644 --- a/ts-tests/tests/evm-transfer.test.ts +++ b/ts-tests/integration-tests/evm-transfer.test.ts @@ -1,7 +1,7 @@ import { assert, expect } from 'chai'; import { step } from 'mocha-steps'; -import { signAndSend, describeLitentry, loadConfig } from './utils'; +import { signAndSend, describeLitentry, loadConfig } from '../common/utils'; import { hexToU8a, u8aToHex } from '@polkadot/util'; import { createPair, encodeAddress } from '@polkadot/keyring'; import { evmToAddress } from '@polkadot/util-crypto'; diff --git a/ts-tests/tests/precompile-contract.test.ts b/ts-tests/integration-tests/precompile-contract.test.ts similarity index 97% rename from ts-tests/tests/precompile-contract.test.ts rename to ts-tests/integration-tests/precompile-contract.test.ts index efc9cec007..0119b62864 100644 --- a/ts-tests/tests/precompile-contract.test.ts +++ b/ts-tests/integration-tests/precompile-contract.test.ts @@ -1,10 +1,10 @@ import { assert, expect } from 'chai'; import { step } from 'mocha-steps'; import { AbiItem } from 'web3-utils'; -import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; +import { signAndSend, describeLitentry, loadConfig } from '../common/utils'; import Web3 from 'web3'; -import precompileContractAbi from '../precompile/contracts/staking.json'; -import { mnemonicGenerate, mnemonicToMiniSecret, decodeAddress, evmToAddress } from '@polkadot/util-crypto'; +import precompileContractAbi from '../common/abi/precompile/Staking.json'; +import { mnemonicGenerate, mnemonicToMiniSecret, evmToAddress } from '@polkadot/util-crypto'; import { KeyringPair } from '@polkadot/keyring/types'; const toBigNumber = (int: number) => int * 1e12; diff --git a/ts-tests/tests/runtime-upgrade.test.ts b/ts-tests/integration-tests/runtime-upgrade.test.ts similarity index 97% rename from ts-tests/tests/runtime-upgrade.test.ts rename to ts-tests/integration-tests/runtime-upgrade.test.ts index 00611d9a98..2c6019c8e2 100644 --- a/ts-tests/tests/runtime-upgrade.test.ts +++ b/ts-tests/integration-tests/runtime-upgrade.test.ts @@ -1,7 +1,7 @@ import { blake2AsHex } from '@polkadot/util-crypto'; import * as fs from 'fs'; import { Keyring, ApiPromise, WsProvider } from '@polkadot/api'; -import { describeLitentry } from './utils'; +import { describeLitentry } from '../common/utils/integration-setup'; import '@polkadot/wasm-crypto/initOnlyAsm'; import * as path from 'path'; import { expect } from 'chai'; diff --git a/ts-tests/tests/transaction-fee.test.ts b/ts-tests/integration-tests/transaction-fee.test.ts similarity index 99% rename from ts-tests/tests/transaction-fee.test.ts rename to ts-tests/integration-tests/transaction-fee.test.ts index 57e0e12c0b..d6eca16117 100644 --- a/ts-tests/tests/transaction-fee.test.ts +++ b/ts-tests/integration-tests/transaction-fee.test.ts @@ -2,7 +2,7 @@ import { u8aConcat } from '@polkadot/util'; import { expect } from 'chai'; import { step } from 'mocha-steps'; -import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; +import { signAndSend, describeLitentry, loadConfig, sleep } from '../common/utils'; describeLitentry('Test Transaction Fee', ``, (context) => { console.log(`Test Transaction Fee`); diff --git a/ts-tests/tests/transfer.test.ts b/ts-tests/integration-tests/transfer.test.ts similarity index 96% rename from ts-tests/tests/transfer.test.ts rename to ts-tests/integration-tests/transfer.test.ts index cb7082875a..4537f7feb2 100644 --- a/ts-tests/tests/transfer.test.ts +++ b/ts-tests/integration-tests/transfer.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { step } from 'mocha-steps'; -import { signAndSend, describeLitentry, loadConfig, sleep } from './utils'; +import { signAndSend, describeLitentry } from '../common/utils'; describeLitentry('Test Balance Transfer', ``, (context) => { console.log(`Test Balance Transfer`); diff --git a/ts-tests/package.json b/ts-tests/package.json index 5ac5afd6d7..ca9bdb873a 100644 --- a/ts-tests/package.json +++ b/ts-tests/package.json @@ -4,20 +4,20 @@ "description": "This is a set of integration tests for litentry runtime, using TypeScript.", "main": "index.js", "directories": { - "test": "tests" + "test": "integration-tests" }, "scripts": { - "register-parathread": "pnpm exec ts-node tests/register-parathread.ts", - "upgrade-parathread": "pnpm exec ts-node tests/upgrade-parathread.ts", - "setup-enclave": "pnpm exec ts-node tests/setup-enclave.ts", - "test-filter": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/base-filter.test.ts'", - "test-bridge": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/bridge.test.ts'", - "test-evm-transfer": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/evm-transfer.test.ts'", - "test-evm-contract": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/evm-contract.test.ts'", - "test-runtime-upgrade": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/runtime-upgrade.test.ts'", - "test-all": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/**/*.test.ts'", - "test-precompile-contract": "pnpm exec mocha --exit --sort -r ts-node/register 'tests/precompile-contract.test.ts'", - "format": "pnpm exec prettier --write 'tests/**/*.test.ts'" + "register-parathread": "pnpm exec ts-node common/setup/register-parathread.ts", + "upgrade-parathread": "pnpm exec ts-node common/setup/upgrade-parathread.ts", + "setup-enclave": "pnpm exec ts-node common/setup/setup-enclave.ts", + "test-filter": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/base-filter.test.ts'", + "test-bridge": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/bridge.test.ts'", + "test-evm-transfer": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/evm-transfer.test.ts'", + "test-evm-contract": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/evm-contract.test.ts'", + "test-runtime-upgrade": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/runtime-upgrade.test.ts'", + "test-all": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/**/*.test.ts'", + "test-precompile-contract": "pnpm exec mocha --exit --sort -r ts-node/register 'integration-tests/precompile-contract.test.ts'", + "format": "pnpm exec prettier --write '**.ts'" }, "author": "Litentry Dev", "license": "ISC", diff --git a/ts-tests/tests/global.d.ts b/ts-tests/tests/global.d.ts deleted file mode 100644 index 54ae6ea73f..0000000000 --- a/ts-tests/tests/global.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'solc'; \ No newline at end of file diff --git a/ts-tests/tsconfig.json b/ts-tests/tsconfig.json index edce41abe9..7543742807 100644 --- a/ts-tests/tsconfig.json +++ b/ts-tests/tsconfig.json @@ -8,6 +8,6 @@ "rootDir": ".", "outDir": "build" }, - "include": ["tests/**/*.ts", "tests/**/*.d.ts"], + "include": ["ts-tests/**/*.ts", "ts-tests/**/*.d.ts"], "exclude": ["node_modules"] } From 0da63f0f18eff67d0ea63b8f0ebbefc4ac81768d Mon Sep 17 00:00:00 2001 From: Kasper Ziemianek Date: Sat, 30 Dec 2023 16:57:36 +0100 Subject: [PATCH 26/43] wait 1 sec before querying state in ts tests (#2369) --- tee-worker/ts-tests/integration-tests/common/di-utils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tee-worker/ts-tests/integration-tests/common/di-utils.ts b/tee-worker/ts-tests/integration-tests/common/di-utils.ts index 69e959a750..3a0b59de1d 100644 --- a/tee-worker/ts-tests/integration-tests/common/di-utils.ts +++ b/tee-worker/ts-tests/integration-tests/common/di-utils.ts @@ -5,7 +5,7 @@ import { TypeRegistry } from '@polkadot/types'; import { Bytes } from '@polkadot/types-codec'; import { IntegrationTestContext, JsonRpcRequest } from './common-types'; import { WorkerRpcReturnValue, TrustedCallSigned, Getter } from 'parachain-api'; -import { encryptWithTeeShieldingKey, Signer, encryptWithAes } from './utils'; +import { encryptWithTeeShieldingKey, Signer, encryptWithAes, sleep } from './utils'; import { aesKey, decodeRpcBytesAsString, keyNonce } from './call'; import { createPublicKey, KeyObject } from 'crypto'; import WebSocketAsPromised from 'websocket-as-promised'; @@ -336,6 +336,9 @@ export const sendRequestFromGetter = async ( // this is what `state_executeGetter` expects in rust const requestParam = await createRsaRequest(context.api, context.mrEnclave, teeShieldingKey, true, getter.toU8a()); const request = createJsonRpcRequest('state_executeGetter', [u8aToHex(requestParam)], nextRequestId(context)); + // in multiworker setup in some cases state might not be immediately propagated to other nodes so we wait 1 sec + // hopefully we will query correct state + await sleep(1); return sendRequest(context.tee, request, context.api); }; From fb37481b9603e3efde20c10d6fef6c37818ebed0 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:52:14 +0800 Subject: [PATCH 27/43] fix lit staking response result field to Option (#2372) --- .../core/assertion-build/src/lit_staking.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tee-worker/litentry/core/assertion-build/src/lit_staking.rs b/tee-worker/litentry/core/assertion-build/src/lit_staking.rs index 32d98bc92c..223c0f41a0 100644 --- a/tee-worker/litentry/core/assertion-build/src/lit_staking.rs +++ b/tee-worker/litentry/core/assertion-build/src/lit_staking.rs @@ -66,7 +66,7 @@ impl RestPath for JsonRPCRequest { pub struct JsonRPCResponse { pub id: usize, pub jsonrpc: String, - pub result: String, + pub result: Option, } pub struct LitentryStakingClient { @@ -102,13 +102,14 @@ impl LitentryStakingClient { } pub trait QueryParachainStaking { - fn query_delegator_state(&mut self, key: &str) -> Result; + fn query_delegator_state(&mut self, key: &str) -> Result>; } impl QueryParachainStaking for LitentryStakingClient { - fn query_delegator_state(&mut self, key: &str) -> Result { + fn query_delegator_state(&mut self, key: &str) -> Result> { let data = JsonRPCRequest::state_getstorage(key); let res = self.send_request(&data)?; + Ok(res.result) } } @@ -126,10 +127,12 @@ impl DelegatorState { let storage_key = DelegatorState::delegator_state_storage_key(identity)?; let storage_in_hex = client.query_delegator_state(&storage_key)?; - let delegator = DelegatorState::decode_delegator(&storage_in_hex)?; - let total = delegator.total; + if let Some(storage_in_hex) = storage_in_hex { + let delegator = DelegatorState::decode_delegator(&storage_in_hex)?; + let total = delegator.total; - total_staking_amount += total; + total_staking_amount += total; + } } Ok(total_staking_amount / LIT_TOKEN_DECIMALS) From 7fb7d24833a99f6121a5281f7bba9fe611e8aada Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Tue, 2 Jan 2024 10:57:38 +0100 Subject: [PATCH 28/43] Fix positional args in request-vc CLI (#2367) * try to fix it * add comments --- .../commands/litentry/request_vc.rs | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index 8336030771..8a7f1450a2 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -50,6 +50,9 @@ use sp_core::Pair; // // ./bin/litentry-cli trusted -d request-vc \ // did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 vip3-membership-card gold +// +// ./bin/litentry-cli trusted -d request-vc \ +// did:litentry:substrate:0x52a6c52dc82940a36fefd1474cc0778517bb1a56b7bda0e308b6c19152dd7510 achainable amount-token test-name -c=bsc,ethereum 1 token-value pub fn to_para_str(s: &str) -> ParameterString { ParameterString::truncate_from(s.as_bytes().to_vec()) @@ -74,7 +77,7 @@ pub struct RequestVcCommand { } // see `assertion.rs` -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum Command { A1, A2(A2Arg), @@ -101,12 +104,12 @@ pub enum Command { EVMAmountHolding(EVMAmountHoldingCommand), } -#[derive(Args)] +#[derive(Args, Debug)] pub struct A2Arg { pub guild_id: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct A3Arg { pub guild_id: String, pub channel_id: String, @@ -114,30 +117,30 @@ pub struct A3Arg { } // used in A4/A7/A10/A11 -#[derive(Args)] +#[derive(Args, Debug)] pub struct HolderArg { pub minimum_amount: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct A8Arg { #[clap(num_args = 0.., value_delimiter = ',')] pub networks: Vec, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct A13Arg { pub account: String, } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum OneblockCommand { Completion, Outstanding, Participation, } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum AchainableCommand { AmountHolding(AmountHoldingArg), AmountToken(AmountTokenArg), @@ -152,7 +155,7 @@ pub enum AchainableCommand { Token(TokenArg), } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum GenericDiscordRoleCommand { #[clap(subcommand)] Contest(ContestCommand), @@ -160,33 +163,33 @@ pub enum GenericDiscordRoleCommand { SoraQuiz(SoraQuizCommand), } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum VIP3MembershipCardLevelCommand { Gold, Silver, } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum ContestCommand { Legend, Popularity, Participant, } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum SoraQuizCommand { Attendee, Master, } -#[derive(Subcommand)] +#[derive(Subcommand, Debug)] pub enum EVMAmountHoldingCommand { Ton, Trx, } // I haven't found a good way to use common args for subcommands -#[derive(Args)] +#[derive(Args, Debug)] pub struct AmountHoldingArg { pub name: String, pub chain: String, @@ -195,22 +198,34 @@ pub struct AmountHoldingArg { pub token: Option, } -#[derive(Args)] +// positional args (to vec) + required arg + optional arg is a nightmare combination for clap parser, +// additionally, only the last positional argument, or second to last positional argument may be set to `.num_args()` +// +// the best bet is to use a flag explicitly, be sure to use euqal form for `chain`, e.g.: +// -- name -c=bsc,ethereum 10 +// -- name -c=bsc,ethereum 10 token +#[derive(Args, Debug)] pub struct AmountTokenArg { pub name: String, + #[clap( + short, long, + num_args = 1.., + required = true, + value_delimiter = ',', + )] pub chain: Vec, pub amount: String, pub token: Option, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct AmountArg { pub name: String, pub chain: String, pub amount: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct AmountsArg { pub name: String, pub chain: String, @@ -218,13 +233,13 @@ pub struct AmountsArg { pub amount2: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct BasicArg { pub name: String, pub chain: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct BetweenPercentsArg { pub name: String, pub chain: String, @@ -232,13 +247,13 @@ pub struct BetweenPercentsArg { pub less_than_or_equal_to: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct ClassOfYearArg { pub name: String, pub chain: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct DateIntervalArg { pub name: String, pub chain: String, @@ -246,7 +261,7 @@ pub struct DateIntervalArg { pub end_date: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct DatePercentArg { pub name: String, pub chain: String, @@ -255,14 +270,14 @@ pub struct DatePercentArg { pub percent: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct DateArg { pub name: String, pub chain: String, pub date: String, } -#[derive(Args)] +#[derive(Args, Debug)] pub struct TokenArg { pub name: String, pub chain: String, @@ -279,6 +294,8 @@ impl RequestVcCommand { let nonce = get_layer_two_nonce!(alice, cli, trusted_cli); println!(">>>nonce: {}", nonce); + println!(">>>command: {:#?}", self.command); + let assertion = match &self.command { Command::A1 => Assertion::A1, Command::A2(arg) => Assertion::A2(to_para_str(&arg.guild_id)), From 038b0f47e9df6657b7a656126371e46056b5b354 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:22:59 +0100 Subject: [PATCH 29/43] Support prettified bitcoin signing message (#2366) * add enum * add comment * add prettified impl and tests * fix tests --------- Co-authored-by: Kasper Ziemianek --- primitives/core/src/network.rs | 9 +++ .../interfaces/identity/definitions.ts | 1 + tee-worker/litentry/primitives/src/lib.rs | 49 +++++++++------ .../integration-tests/common/utils/context.ts | 1 + .../common/utils/identity-helper.ts | 27 +++++++- .../di_bitcoin_identity.test.ts | 63 ++++++++++++++----- 6 files changed, 113 insertions(+), 37 deletions(-) diff --git a/primitives/core/src/network.rs b/primitives/core/src/network.rs index 90561648ab..34fcb119ce 100644 --- a/primitives/core/src/network.rs +++ b/primitives/core/src/network.rs @@ -30,7 +30,16 @@ pub type BoundedWeb3Network = BoundedVec bool { match self { - Self::Ethereum(ref sig) => { - let data = msg; - return verify_evm_signature(evm_eip191_wrap(data).as_slice(), sig, signer) - || verify_evm_signature(data, sig, signer) - }, + Self::Ethereum(ref sig) => + return verify_evm_signature(evm_eip191_wrap(msg).as_slice(), sig, signer) + || verify_evm_signature(msg, sig, signer), Self::EthereumPrettified(ref sig) => { - let user_readable_message = - "Litentry authorization token: ".to_string() + &hex_encode(msg); - let data = user_readable_message.as_bytes(); - return verify_evm_signature(evm_eip191_wrap(data).as_slice(), sig, signer) - || verify_evm_signature(data, sig, signer) + let prettified_msg = + LITENTRY_PRETTIFIED_MESSAGE_PREFIX.to_string() + &hex_encode(msg); + let msg = prettified_msg.as_bytes(); + return verify_evm_signature(evm_eip191_wrap(msg).as_slice(), sig, signer) + || verify_evm_signature(msg, sig, signer) }, _ => false, } @@ -148,31 +151,37 @@ impl LitentryMultiSignature { fn verify_bitcoin(&self, msg: &[u8], signer: &Address33) -> bool { match self { - Self::Bitcoin(ref sig) => verify_bitcoin_signature(msg, sig, signer), + Self::Bitcoin(ref sig) => + verify_bitcoin_signature(hex::encode(msg).as_str(), sig, signer), + Self::BitcoinPrettified(ref sig) => { + let prettified_msg = + LITENTRY_PRETTIFIED_MESSAGE_PREFIX.to_string() + &hex_encode(msg); + verify_bitcoin_signature(prettified_msg.as_str(), sig, signer) + }, _ => false, } } } -pub fn verify_evm_signature(data: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { - let digest = keccak_256(data); +pub fn verify_evm_signature(msg: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { + let digest = keccak_256(msg); return match recover_evm_address(&digest, sig.as_ref()) { Ok(recovered_evm_address) => recovered_evm_address == who.as_ref().as_slice(), Err(_e) => { - error!("Could not verify evm signature msg: {:?}, signer {:?}", data, who); + error!("Could not verify evm signature msg: {:?}, signer {:?}", msg, who); false }, } } -pub fn verify_bitcoin_signature(msg: &[u8], sig: &BitcoinSignature, who: &Address33) -> bool { +pub fn verify_bitcoin_signature(msg: &str, sig: &BitcoinSignature, who: &Address33) -> bool { if let Ok(msg_sig) = MessageSignature::from_slice(sig.as_ref()) { - let msg_hash = signed_msg_hash(hex::encode(msg).as_str()); + let msg_hash = signed_msg_hash(msg); let secp = secp256k1::Secp256k1::new(); return match msg_sig.recover_pubkey(&secp, msg_hash) { Ok(recovered_pub_key) => &recovered_pub_key.inner.serialize() == who.as_ref(), Err(_) => { - error!("Could not verify bitcoin signature msg: {:?}, signer {:?}", msg, who); + error!("Could not recover pubkey from bitcoin msg: {:?}, signer {:?}", msg, who); false }, } @@ -264,7 +273,7 @@ mod tests { let pubkey_ref: &[u8] = pubkey.as_ref(); let sig_ref: &[u8] = sig.as_ref(); assert!(verify_bitcoin_signature( - &msg, + hex::encode(msg).as_str(), &sig_ref.try_into().unwrap(), &pubkey_ref.try_into().unwrap() )); diff --git a/tee-worker/ts-tests/integration-tests/common/utils/context.ts b/tee-worker/ts-tests/integration-tests/common/utils/context.ts index 529b3ff6aa..2903aa1227 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/context.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/context.ts @@ -49,6 +49,7 @@ export async function initIntegrationTestContext( const bitcoinWallet = { alice: new bitcore.PrivateKey(), + bob: new bitcore.PrivateKey(), }; const types = { ...identity.types, ...vc.types, ...trusted_operations.types, ...sidechain.types }; diff --git a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts index 247f0d8812..6b00033fa4 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts @@ -167,7 +167,7 @@ export async function buildValidations( signerIdentities: LitentryPrimitivesIdentity[], identities: LitentryPrimitivesIdentity[], startingSidechainNonce: number, - network: 'ethereum' | 'substrate' | 'twitter' | 'bitcoin', + network: 'ethereum' | 'substrate' | 'twitter' | 'bitcoin' | 'bitcoinPrettified', substrateSigners?: KeyringPair[] | KeyringPair, evmSigners?: ethers.Wallet[], bitcoinSigners?: bitcore.PrivateKey[] | bitcore.PrivateKey @@ -254,6 +254,31 @@ export async function buildValidations( bitcoinValidationData ) as unknown as LitentryValidationData; validations.push(encodedVerifyIdentityValidation); + } else if (network === 'bitcoinPrettified') { + const bitcoinValidationData = { + Web3Validation: { + Bitcoin: { + message: '' as HexString, + signature: { + BitcoinPrettified: '' as HexString, + }, + }, + }, + }; + console.log('post verification msg to bitcoin: ', msg); + bitcoinValidationData.Web3Validation.Bitcoin.message = msg; + const bitcoinSigner = Array.isArray(bitcoinSigners!) ? bitcoinSigners![index] : bitcoinSigners!; + const sig = new bitcore.Message('Litentry authorization token: ' + msg).sign(bitcoinSigner); + bitcoinSignature = bufferToU8a(Buffer.from(sig, 'base64')); + bitcoinValidationData!.Web3Validation.Bitcoin.signature.BitcoinPrettified = u8aToHex(bitcoinSignature); + console.log('bitcoin pubkey: ', u8aToHex(bufferToU8a(bitcoinSigner.toPublicKey().toBuffer()))); + console.log('bitcoin sig (base64): ', sig); + console.log('bitcoin sig (hex): ', u8aToHex(bitcoinSignature)); + const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType( + 'LitentryValidationData', + bitcoinValidationData + ) as unknown as LitentryValidationData; + validations.push(encodedVerifyIdentityValidation); } else if (network === 'twitter') { console.log('post verification msg to twitter: ', msg); const twitterValidationData = { diff --git a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts index fe6c5df292..b2fbb59709 100644 --- a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts @@ -36,15 +36,28 @@ describe('Test Identity (bitcoin direct invocation)', function () { let teeShieldingKey: KeyObject = undefined as any; let aliceBitcoinIdentity: LitentryPrimitivesIdentity = undefined as any; let aliceEvmIdentity: LitentryPrimitivesIdentity; + let bobBitcoinIdentity: LitentryPrimitivesIdentity; // Alice links: // - alice's evm identity + // - bob's bitcoin identity const linkIdentityRequestParams: { nonce: number; identity: LitentryPrimitivesIdentity; validation: LitentryValidationData; networks: Vec; }[] = []; + + const deactivateIdentityRequestParams: { + nonce: number; + identity: LitentryPrimitivesIdentity; + }[] = []; + + const activateIdentityRequestParams: { + nonce: number; + identity: LitentryPrimitivesIdentity; + }[] = []; + this.timeout(6000000); before(async () => { @@ -59,6 +72,11 @@ describe('Test Identity (bitcoin direct invocation)', function () { context ); aliceEvmIdentity = await buildIdentityFromKeypair(new EthersSigner(context.ethersWallet.alice), context); + bobBitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.bob.toPublicKey().toBuffer())), + 'Bitcoin', + context + ); }); step('check idGraph from sidechain storage before linking', async function () { @@ -76,12 +94,12 @@ describe('Test Identity (bitcoin direct invocation)', function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); const getNextNonce = () => currentNonce++; - const aliceNonce = getNextNonce(); + const aliceEvmNonce = getNextNonce(); const [aliceEvmValidation] = await buildValidations( context, [aliceBitcoinIdentity], [aliceEvmIdentity], - aliceNonce, + aliceEvmNonce, 'ethereum', undefined, [context.ethersWallet.alice] @@ -91,12 +109,34 @@ describe('Test Identity (bitcoin direct invocation)', function () { 'Bsc', ]) as unknown as Vec; // @fixme #1878 linkIdentityRequestParams.push({ - nonce: aliceNonce, + nonce: aliceEvmNonce, identity: aliceEvmIdentity, validation: aliceEvmValidation, networks: aliceEvmNetworks, }); + // link another bitcoin account with prettified signature + const bobBitcoinNonce = getNextNonce(); + const [bobBitcoinValidation] = await buildValidations( + context, + [aliceBitcoinIdentity], + [bobBitcoinIdentity], + bobBitcoinNonce, + 'bitcoinPrettified', + undefined, + undefined, + context.bitcoinWallet.bob + ); + const bobBitcoinNetowrks = context.api.createType('Vec', [ + 'BitcoinP2tr', + ]) as unknown as Vec; // @fixme #1878 + linkIdentityRequestParams.push({ + nonce: bobBitcoinNonce, + identity: bobBitcoinIdentity, + validation: bobBitcoinValidation, + networks: bobBitcoinNetowrks, + }); + const identityLinkedEvents: any[] = []; const idGraphHashResults: any[] = []; let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ @@ -104,6 +144,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { [aliceBitcoinIdentity, true], [aliceEvmIdentity, true], ], + [[bobBitcoinIdentity, true]], ]; for (const { nonce, identity, validation, networks } of linkIdentityRequestParams) { @@ -151,7 +192,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { new BitcoinSigner(context.bitcoinWallet.alice), identityLinkedEvents, idGraphHashResults, - 1 + 2 ); }); @@ -165,7 +206,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); // according to the order of linkIdentityRequestParams - const expectedWeb3Networks = [['Ethereum', 'Bsc']]; + const expectedWeb3Networks = [['Ethereum', 'Bsc'], ['BitcoinP2tr']]; let currentIndex = 0; for (const { identity } of linkIdentityRequestParams) { @@ -194,11 +235,6 @@ describe('Test Identity (bitcoin direct invocation)', function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); const getNextNonce = () => currentNonce++; - const deactivateIdentityRequestParams: { - nonce: number; - identity: LitentryPrimitivesIdentity; - }[] = []; - const aliceEvmNonce = getNextNonce(); deactivateIdentityRequestParams.push({ @@ -266,7 +302,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { const res = await sendRequestFromGetter(context, teeShieldingKey, idGraphGetter); const idGraph = decodeIdGraph(context.sidechainRegistry, res.value); - for (const { identity } of linkIdentityRequestParams) { + for (const { identity } of deactivateIdentityRequestParams) { const identityDump = JSON.stringify(identity.toHuman(), null, 4); console.debug(`checking identity: ${identityDump}`); const idGraphNode = idGraph.find(([idGraphNodeIdentity]) => idGraphNodeIdentity.eq(identity)); @@ -288,11 +324,6 @@ describe('Test Identity (bitcoin direct invocation)', function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceBitcoinIdentity)).toNumber(); const getNextNonce = () => currentNonce++; - const activateIdentityRequestParams: { - nonce: number; - identity: LitentryPrimitivesIdentity; - }[] = []; - const aliceEvmNonce = getNextNonce(); activateIdentityRequestParams.push({ From 28dcbd93000979c7e95410226551c5812a7ada67 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Thu, 4 Jan 2024 09:03:36 +0800 Subject: [PATCH 30/43] P-316 New Year - CryptoSummary (#2376) * force set the order and index before widely usage. * backup commit * make fmt * update logic * small update * update logic * add construct summary * add update_holding_flag & unittest * refine code * Finish Assertion logic * add bsc token address * update summary structure * add get_balance * using native_token_balance * remove 2048 limit * update unit test * catch a null case in nodereal * add total_tx --------- Co-authored-by: BillyWooo --- Cargo.lock | 149 +++--- primitives/core/src/assertion.rs | 6 +- .../commands/litentry/request_vc.rs | 2 + .../commands/litentry/request_vc_direct.rs | 1 + .../interfaces/vc/definitions.ts | 1 + .../src/nodereal/crypto_summary/mod.rs | 42 ++ .../core/assertion-build/src/nodereal/mod.rs | 1 + .../litentry/core/credentials/src/lib.rs | 9 +- .../src/nodereal/crypto_summary/mod.rs | 444 ++++++++++++++++++ .../src/nodereal/crypto_summary/summary.rs | 166 +++++++ .../core/credentials/src/nodereal/mod.rs | 1 + .../litentry/core/data-providers/src/lib.rs | 2 +- .../data-providers/src/nodereal_jsonrpc.rs | 79 ++++ .../receiver/src/handler/assertion.rs | 3 + .../lc-vc-task-receiver/src/vc_handling.rs | 3 + tee-worker/service/src/prometheus_metrics.rs | 1 + 16 files changed, 819 insertions(+), 91 deletions(-) create mode 100644 tee-worker/litentry/core/assertion-build/src/nodereal/crypto_summary/mod.rs create mode 100644 tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs create mode 100644 tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/summary.rs diff --git a/Cargo.lock b/Cargo.lock index 31abf9e548..0e53e8f3b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,7 +445,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -456,7 +456,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -1058,7 +1058,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -1729,10 +1729,10 @@ name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2045,7 +2045,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2062,7 +2062,7 @@ checksum = "b8fcfa71f66c8563c4fa9dd2bb68368d50267856f831ac5d85367e0805f9606c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2340,7 +2340,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2533,7 +2533,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2544,7 +2544,7 @@ checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2844,7 +2844,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -2892,7 +2892,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -3358,10 +3358,10 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -3476,7 +3476,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -3485,10 +3485,10 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -3498,7 +3498,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -3665,7 +3665,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -4493,7 +4493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" dependencies = [ "heck", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -5421,7 +5421,7 @@ version = "0.9.12" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -6179,7 +6179,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", @@ -6497,10 +6497,10 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -6598,7 +6598,7 @@ dependencies = [ "expander 0.0.6", "itertools", "petgraph", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -7848,10 +7848,10 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -8194,9 +8194,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -8209,11 +8209,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -8369,7 +8369,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -8410,7 +8410,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -9734,7 +9734,7 @@ dependencies = [ "proc-macro2", "quote", "sha3", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -9814,17 +9814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit 0.19.14", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" -dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit", ] [[package]] @@ -9859,7 +9849,7 @@ checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -10255,7 +10245,7 @@ checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -11030,10 +11020,10 @@ name = "sc-chain-spec-derive" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -12006,10 +11996,10 @@ name = "sc-tracing-proc-macro" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -12088,7 +12078,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -12295,7 +12285,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -12633,10 +12623,10 @@ dependencies = [ "Inflector", "blake2", "expander 1.0.0", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -12878,7 +12868,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -12897,7 +12887,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -13105,10 +13095,10 @@ version = "6.0.0" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -13276,7 +13266,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -13469,7 +13459,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -13654,9 +13644,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" dependencies = [ "proc-macro2", "quote", @@ -13780,7 +13770,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -13949,7 +13939,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -14008,7 +13998,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.19.14", + "toml_edit", ] [[package]] @@ -14033,17 +14023,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap 2.0.0", - "toml_datetime", - "winnow", -] - [[package]] name = "tower" version = "0.4.13" @@ -14106,7 +14085,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -14146,10 +14125,10 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "expander 2.0.0", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -14596,7 +14575,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", "wasm-bindgen-shared", ] @@ -14630,7 +14609,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -15704,7 +15683,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] @@ -15812,7 +15791,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.40", ] [[package]] diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 3f36328022..2ff0a2cce2 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -254,6 +254,9 @@ pub enum Assertion { #[codec(index = 22)] BRC20AmountHolder, + + #[codec(index = 23)] + CryptoSummary, } impl Assertion { @@ -290,7 +293,8 @@ impl Assertion { // LITStaking Self::LITStaking => vec![Web3Network::Litentry], // EVM Amount Holding - Self::EVMAmountHolding(_) => vec![Web3Network::Ethereum, Web3Network::Bsc], + Self::EVMAmountHolding(_) | Self::CryptoSummary => + vec![Web3Network::Ethereum, Web3Network::Bsc], // BRC20 Holder Self::BRC20AmountHolder => vec![Web3Network::BitcoinP2tr], // we don't care about any specific web3 network diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index 8a7f1450a2..be27084acc 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -102,6 +102,7 @@ pub enum Command { WeirdoGhostGangHolder, #[clap(subcommand)] EVMAmountHolding(EVMAmountHoldingCommand), + CryptoSummary, } #[derive(Args, Debug)] @@ -472,6 +473,7 @@ impl RequestVcCommand { EVMAmountHoldingCommand::Ton => Assertion::EVMAmountHolding(EVMTokenType::Ton), EVMAmountHoldingCommand::Trx => Assertion::EVMAmountHolding(EVMTokenType::Trx), }, + Command::CryptoSummary => Assertion::CryptoSummary, }; let key = Self::random_aes_key(); diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs index 39513c673e..1466b0abab 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs @@ -252,6 +252,7 @@ impl RequestVcDirectCommand { EVMAmountHoldingCommand::Ton => Assertion::EVMAmountHolding(EVMTokenType::Ton), EVMAmountHoldingCommand::Trx => Assertion::EVMAmountHolding(EVMTokenType::Trx), }, + Command::CryptoSummary => Assertion::CryptoSummary, }; let mut key: RequestAesKey = RequestAesKey::default(); diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts index 0b48610e21..4f29666552 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts @@ -30,6 +30,7 @@ export default { LITStaking: "Null", EVMAmountHolding: "EVMTokenType", BRC20AmountHolder: "Null", + CyptoSummary: "Null", }, }, AssertionSupportedNetwork: { diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/crypto_summary/mod.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/crypto_summary/mod.rs new file mode 100644 index 0000000000..240374d32d --- /dev/null +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/crypto_summary/mod.rs @@ -0,0 +1,42 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use lc_credentials::nodereal::crypto_summary::{ + summary::CryptoSummaryCredentialUpdate, CryptoSummaryClient, +}; + +use crate::*; + +pub fn build(req: &AssertionBuildRequest) -> Result { + let identities = transpose_identity(&req.identities); + let (txs, summary) = CryptoSummaryClient::new() + .logic(&identities) + .map_err(|e| Error::RequestVCFailed(Assertion::CryptoSummary, e))?; + + let mut credential_unsigned = Credential::new(&req.who, &req.shard).map_err(|e| { + error!("Generate unsigned credential failed {:?}", e); + Error::RequestVCFailed(Assertion::CryptoSummary, e.into_error_detail()) + })?; + credential_unsigned.update_crypto_summary_credential(txs, summary); + + Ok(credential_unsigned) +} diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs index bd8b22015c..84a4bff2f7 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/mod.rs @@ -22,4 +22,5 @@ extern crate sgx_tstd as std; pub mod amount_holding; pub mod bnb_domain; +pub mod crypto_summary; pub mod nft_holder; diff --git a/tee-worker/litentry/core/credentials/src/lib.rs b/tee-worker/litentry/core/credentials/src/lib.rs index 32e05d96fe..eb1555f26e 100644 --- a/tee-worker/litentry/core/credentials/src/lib.rs +++ b/tee-worker/litentry/core/credentials/src/lib.rs @@ -320,10 +320,11 @@ impl Credential { return Err(Error::EmptyCredentialIssuer) } - let exported = vc.to_json()?; - if exported.len() > MAX_CREDENTIAL_SIZE { - return Err(Error::CredentialIsTooLong) - } + // TODO: Do we need to set size restrictions + // let exported = vc.to_json()?; + // if exported.len() > MAX_CREDENTIAL_SIZE { + // return Err(Error::CredentialIsTooLong) + // } if vc.proof.is_none() { return Err(Error::InvalidProof) diff --git a/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs b/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs new file mode 100644 index 0000000000..fc6ecf3d9e --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs @@ -0,0 +1,444 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use self::summary::{ + CRYPTO_SUMMARY_NFT_ADDRESSES_ETH, CRYPTO_SUMMARY_TOKEN_ADDRESSES_BSC, + CRYPTO_SUMMARY_TOKEN_ADDRESSES_ETH, +}; +use crate::*; +use lc_data_providers::{ + achainable::web3_network_to_chain, + nodereal_jsonrpc::{ + FungibleApiList, GetNFTHoldingsParam, NftApiList, NoderealChain, NoderealJsonrpcClient, + TransactionCount, + }, +}; +use litentry_primitives::{ErrorDetail, IntoErrorDetail}; +use serde::{Deserialize, Serialize}; +use std::{string::String, vec, vec::Vec}; + +pub mod summary; + +const ETH_TOKEN_DECIMALS: f64 = 1_000_000_000_000_000_000.0; + +/* +SUMMARY: { + TOKEN: [ + { + network: BSC, + list: [ + { + name: PEPE, + address: 0x123, + }, + { + name: SHIB, + address: 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE , + }, + { + name: BNB, + address: "", // No smart contract address + }, + + //... + ] + }, + { + network: Ethereum, + list: [ + { + name: PEPE, + address: 0x123, + }, + { + name: SHIB, + address: 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE , + }, + { + name: ETH, + address: "", // No smart contract address + }, + //... + ] + }, + ], + NFT: [ + { + network: Ethereum, + list: [ + { + name: Moonbirds, + address: 0x23581767a106ae21c074b2276D25e5C3e136a68b + } + ] + } + ] +} + +*/ + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ResponseToken { + token_address: String, + token_balance: String, + token_name: String, + token_symbol: String, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ResponseTokenResult { + pub total_count: String, + pub native_token_balance: String, + pub details: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct NameAndAddress { + pub name: String, + pub address: String, +} + +impl NameAndAddress { + pub fn new(name: &str, address: &str) -> Self { + Self { name: name.to_string(), address: address.to_string() } + } +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct Item { + pub network: String, + pub list: Vec, +} + +impl Item { + pub fn new(network: String, list: Vec) -> Self { + let mut item = Item::default(); + + if !list.is_empty() { + item.network = network; + item.list = list; + } + + item + } + + pub fn is_empty(&self) -> bool { + self.list.is_empty() + } +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct TokenAndNFT { + #[serde(rename = "TOKEN")] + #[serde(skip_serializing_if = "Vec::is_empty")] + pub token: Vec, + + #[serde(rename = "NFT")] + #[serde(skip_serializing_if = "Vec::is_empty")] + pub nft: Vec, +} + +impl TokenAndNFT { + pub fn add_token(&mut self, item: Item) { + if !item.is_empty() { + self.token.push(item); + } + } + + pub fn add_nft(&mut self, item: Item) { + if !item.is_empty() { + self.nft.push(item); + } + } +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct SummaryHoldings { + #[serde(rename = "SUMMARRY")] + pub summary: TokenAndNFT, +} + +impl SummaryHoldings { + pub fn is_empty(&self) -> bool { + self.summary.token.is_empty() && self.summary.nft.is_empty() + } + + pub fn construct(bsc_token: &[bool], eth_token: &[bool], eth_nft: &[bool]) -> Self { + let bsc_token_list = Self::collect_list(&CRYPTO_SUMMARY_TOKEN_ADDRESSES_BSC, bsc_token); + let eth_token_list = Self::collect_list(&CRYPTO_SUMMARY_TOKEN_ADDRESSES_ETH, eth_token); + let eth_nft_list = Self::collect_list(&CRYPTO_SUMMARY_NFT_ADDRESSES_ETH, eth_nft); + + let mut token_and_nft = TokenAndNFT::default(); + token_and_nft + .add_token(Item::new(web3_network_to_chain(&Web3Network::Bsc), bsc_token_list)); + token_and_nft + .add_token(Item::new(web3_network_to_chain(&Web3Network::Ethereum), eth_token_list)); + token_and_nft + .add_nft(Item::new(web3_network_to_chain(&Web3Network::Ethereum), eth_nft_list)); + + SummaryHoldings { summary: token_and_nft } + } + + fn collect_list(source: &[(&str, &str)], flags: &[bool]) -> Vec { + let mut list = vec![]; + for (index, is_holder) in flags.iter().enumerate() { + if *is_holder { + let (address, name) = source[index]; + let name_and_address = NameAndAddress::new(name, address); + list.push(name_and_address) + } + } + + list + } +} + +pub struct CryptoSummaryClient { + pub eth_client: NoderealJsonrpcClient, + pub bsc_client: NoderealJsonrpcClient, +} + +impl Default for CryptoSummaryClient { + fn default() -> Self { + Self::new() + } +} + +impl CryptoSummaryClient { + pub fn new() -> Self { + let eth_client = NoderealJsonrpcClient::new(NoderealChain::Eth); + let bsc_client = NoderealJsonrpcClient::new(NoderealChain::Bsc); + + Self { eth_client, bsc_client } + } + + pub fn logic( + &mut self, + identities: &Vec<(Web3Network, Vec)>, + ) -> core::result::Result<(u64, SummaryHoldings), ErrorDetail> { + // Corresponds one-to-one with CRYPTO_SUMMARY_TOKEN_ADDRESSES_ETH + let mut flag_bsc_token: [bool; 12] = [false; 12]; + let mut flag_eth_token: [bool; 15] = [false; 15]; + let mut flag_eth_nft: [bool; 15] = [false; 15]; + + // ETH and BNB holder use different APIs than other tokens, so they need to be handled separately + let mut is_eth_holder = false; + let mut is_bnb_holder = false; + + let mut total_txs = 0_u64; + + for (network, addresses) in identities { + if *network == Web3Network::Bsc { + // Query Token + for address in addresses { + let res = self + .bsc_client + .get_token_holdings(address) + .map_err(|e| e.into_error_detail())?; + + let result: ResponseTokenResult = + serde_json::from_value(res.result).map_err(|_| ErrorDetail::ParseError)?; + let mut token_addresses = vec![]; + if let Some(details) = result.details { + details.iter().for_each(|detail| { + token_addresses.push(detail.token_address.clone()); + }); + Self::update_holding_flag( + &mut flag_bsc_token, + &CRYPTO_SUMMARY_TOKEN_ADDRESSES_BSC, + &token_addresses, + ); + } + + // Query BNB balance on BSC + if !is_bnb_holder { + let native_balance = result.native_token_balance; + let balance = get_native_token_balance(&native_balance); + if balance > 0.0 { + is_bnb_holder = true; + } + } + + // Total txs on BSC + let tx = self + .bsc_client + .get_transaction_count(address) + .map_err(|e| e.into_error_detail())?; + total_txs += tx; + } + } + + if *network == Web3Network::Ethereum { + for address in addresses { + // Query Token + let res_token = self + .eth_client + .get_token_holdings(address) + .map_err(|e| e.into_error_detail())?; + let result: ResponseTokenResult = serde_json::from_value(res_token.result) + .map_err(|_| ErrorDetail::ParseError)?; + + let mut token_addresses = vec![]; + if let Some(details) = result.details { + details.iter().for_each(|detail| { + token_addresses.push(detail.token_address.clone()); + }); + Self::update_holding_flag( + &mut flag_eth_token, + &CRYPTO_SUMMARY_TOKEN_ADDRESSES_ETH, + &token_addresses, + ); + } + + // Query ETH balance on Ethereum + if !is_eth_holder { + let native_balance = result.native_token_balance; + let balance = get_native_token_balance(&native_balance); + if balance > 0.0 { + is_eth_holder = true; + } + } + + // Query NFT + let param = GetNFTHoldingsParam { + account_address: address.to_string(), + token_type: "ERC721".to_string(), + page: 1, + page_size: 100, + }; + + let res_nft = self + .eth_client + .get_nft_holdings(¶m) + .map_err(|e| e.into_error_detail())?; + + let details = res_nft.details; + + let mut nft_addresses = vec![]; + details.iter().for_each(|detail| { + nft_addresses.push(detail.token_address.clone()); + }); + + Self::update_holding_flag( + &mut flag_eth_nft, + &CRYPTO_SUMMARY_NFT_ADDRESSES_ETH, + &nft_addresses, + ); + + // Total txs on Ethereum + let tx = self + .eth_client + .get_transaction_count(address) + .map_err(|e| e.into_error_detail())?; + total_txs += tx; + } + } + } + + // Update ETH and BNB + flag_bsc_token[11] = is_bnb_holder; + flag_eth_token[14] = is_eth_holder; + + Ok((total_txs, SummaryHoldings::construct(&flag_bsc_token, &flag_eth_token, &flag_eth_nft))) + } + + fn update_holding_flag( + flag_array: &mut [bool], + source: &[(&'static str, &'static str)], + token_addresses: &[String], + ) { + for (index, is_holder) in flag_array.iter_mut().enumerate() { + if !*is_holder { + let (token_address, _token_name) = source[index]; + if token_addresses.contains(&token_address.to_lowercase()) { + *is_holder = true; + } + } + } + } +} + +fn get_native_token_balance(native_balance: &str) -> f64 { + let native_balance = u64::from_str_radix(&native_balance[2..], 16).unwrap_or_default() as f64; + native_balance / ETH_TOKEN_DECIMALS +} + +#[cfg(test)] +mod tests { + use super::{get_native_token_balance, CryptoSummaryClient, SummaryHoldings}; + use crate::nodereal::crypto_summary::summary::CRYPTO_SUMMARY_NFT_ADDRESSES_ETH; + + #[test] + fn summary_construct_works() { + let flag_bsc_token = + [false, true, true, true, true, true, true, true, true, true, true, true]; + let flag_eth_token = [ + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, true, + ]; + let flag_eth_nft = [ + true, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, + ]; + + let summary = SummaryHoldings::construct(&flag_bsc_token, &flag_eth_token, &flag_eth_nft); + assert!(!summary.is_empty()); + } + + #[test] + fn update_nft_holding_flag_works() { + let nft_addresses = vec![ + "0x9401518f4EBBA857BAA879D9f76E1Cc8b31ed197".to_lowercase(), + "0x6339e5E072086621540D0362C4e3Cea0d643E114".to_lowercase(), + ]; + let mut flag_eth_nft = [ + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, + ]; + CryptoSummaryClient::update_holding_flag( + &mut flag_eth_nft, + &CRYPTO_SUMMARY_NFT_ADDRESSES_ETH, + &nft_addresses, + ); + assert!(flag_eth_nft.contains(&true)); + } + + #[test] + fn update_bsc_holding_flag_works() { + let bsc_addresses = vec![ + "0x9401518f4EBBA857BAA879D9f76E1Cc8b31ed197".to_lowercase(), + "0x6339e5E072086621540D0362C4e3Cea0d643E114".to_lowercase(), + ]; + let mut flag_bsc = + [false, false, false, false, false, false, false, false, false, false, false, false]; + CryptoSummaryClient::update_holding_flag( + &mut flag_bsc, + &CRYPTO_SUMMARY_NFT_ADDRESSES_ETH, + &bsc_addresses, + ); + assert!(flag_bsc.contains(&true)); + } + + #[test] + fn get_native_token_balance_works() { + let native_token_balance = + "0x00000000000000000000000000000000000000000000000000c92180664030d4"; + let balance = get_native_token_balance(native_token_balance); + assert_eq!(balance, 0.05661330567385518); + } +} diff --git a/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/summary.rs b/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/summary.rs new file mode 100644 index 0000000000..3d768c4735 --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/summary.rs @@ -0,0 +1,166 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use super::{Item, SummaryHoldings}; +use crate::*; + +const VC_CRYPTO_SUMMARY_DESCRIPTIONS: &str = "Generate a summary of your on-chain identity"; +const VC_CRYPTO_SUMMARY_TYPE: &str = "IDHub Crypto Summary"; + +/// Doesn't exists on BSC including: +/// PEPE, BLUR, WLD +pub const CRYPTO_SUMMARY_TOKEN_ADDRESSES_BSC: [(&str, &str); 12] = [ + ("0xb1547683DA678f2e1F003A780143EC10Af8a832B", "SHIB"), + ("0xBf5140A22578168FD562DCcF235E5D43A02ce9B1", "UNI"), + ("0x2170Ed0880ac9A755fd29B2688956BD959F933F8", "ETH"), + ("0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", "LINK"), + ("0xa050FFb3eEb8200eEB7F61ce34FF644420FD3522", "ARB"), + ("0x101d82428437127bF1608F699CD651e6Abf9766E", "BAT"), + ("0xa2B726B1145A4773F68593CF171187d8EBe4d495", "INJ"), + ("0xfb6115445Bff7b52FeB98650C87f44907E58f802", "AAVE"), + ("0x49BA054B9664e99ac335667a917c63bB94332E84", "FTT"), + ("0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", "CAKE"), + ("0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723", "LIT"), + ("", "BNB"), // Keep address empty +]; + +pub const CRYPTO_SUMMARY_TOKEN_ADDRESSES_ETH: [(&str, &str); 15] = [ + ("0x6982508145454Ce325dDbE47a25d4ec3d2311933", "PEPE"), + ("0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE", "SHIB"), + ("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", "UNI"), + ("0xB8c77482e45F1F44dE1745F52C74426C631bDD52", "BNB"), + ("0x514910771AF9Ca656af840dff83E8264EcF986CA", "LINK"), + ("0x5283d291dbcf85356a21ba090e6db59121208b44", "BLUR"), + ("0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1", "ARB"), + ("0x0d8775f648430679a709e98d2b0cb6250d2887ef", "BAT"), + ("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30", "INJ"), + ("0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9", "AAVE"), + ("0x163f8c2467924be0ae7b5347228cabf260318753", "WLD"), + ("0x50D1c9771902476076eCFc8B2A83Ad6b9355a4c9", "FTT"), + ("0x152649eA73beAb28c5b49B26eb48f7EAD6d4c898", "CAKE"), + ("0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723", "LIT"), + ("", "ETH"), // Keep address empty +]; + +pub const CRYPTO_SUMMARY_NFT_ADDRESSES_ETH: [(&str, &str); 15] = [ + ("0x9401518f4EBBA857BAA879D9f76E1Cc8b31ed197", "The Weirdo Ghost Gang"), + ("0x23581767a106ae21c074b2276D25e5C3e136a68b", "Moonbirds"), + ("0x142e03367eDE17Cd851477A4287D1F35676E6dC2", "Yogapetz"), + ("0x59325733eb952a92e069C87F0A6168b29E80627f", "Mocaverse"), + ("0xeC19CAeF9C046f5f87A497154766742ab9C90820", "y00ts"), + ("0x5CC5B05a8A13E3fBDB0BB9FcCd98D38e50F90c38", "The Sandbox"), + ("0x596a5CD859AD53fEc23Cd3fCD77522f0B407920d", "MATR1X KUKU"), + ("0x8a90CAb2b38dba80c64b7734e58Ee1dB38B8992e", "Doodles"), + ("0x49cF6f5d44E70224e2E23fDcdd2C053F30aDA28B", "CloneX"), + ("0xd774557b647330C91Bf44cfEAB205095f7E6c367", "Nakamigos"), + ("0x6339e5E072086621540D0362C4e3Cea0d643E114", "Opepen"), + ("0xe1dC516B1486Aba548eecD2947A11273518434a4", "The Grapes"), + ("0x769272677faB02575E84945F03Eca517ACc544C", "The Captainz"), + ("0x39ee2c7b3cb80254225884ca001F57118C8f21B6", "The Potatoz"), + ("0x7Bd29408f11D2bFC23c34f18275bBf23bB716Bc7", "Meebits"), +]; + +pub trait CryptoSummaryCredentialUpdate { + fn update_crypto_summary_credential(&mut self, txs: u64, summary: SummaryHoldings); +} + +impl CryptoSummaryCredentialUpdate for Credential { + fn update_crypto_summary_credential(&mut self, txs: u64, summary: SummaryHoldings) { + let (value, and_logic) = build_assertions(txs, summary); + + self.credential_subject.assertions.push(and_logic); + self.credential_subject.values.push(value); + + self.add_subject_info(VC_CRYPTO_SUMMARY_DESCRIPTIONS, VC_CRYPTO_SUMMARY_TYPE); + } +} + +fn build_assertions(txs: u64, summary: SummaryHoldings) -> (bool, AssertionLogic) { + let is_empty = summary.is_empty(); + + let mut and_logic = AssertionLogic::new_and(); + + // Total Txs + let txs_item = AssertionLogic::new_item("$total_txs", Op::Equal, &txs.to_string()); + and_logic = and_logic.add_item(txs_item); + + // TOKENs + let token_assertion = token_items("TOKEN", summary.summary.token); + and_logic = and_logic.add_item(token_assertion); + + // NFTs + let nft_assertion = token_items("NFT", summary.summary.nft); + and_logic = and_logic.add_item(nft_assertion); + + (!is_empty, and_logic) +} + +fn token_items(name: &str, items: Vec) -> AssertionLogic { + let mut and_logic = AssertionLogic::new_and(); + + let kind_item = AssertionLogic::new_item("$kind", Op::Equal, name); + and_logic = and_logic.add_item(kind_item); + + for item in items { + let mut item_logic = AssertionLogic::new_and(); + + let network_item = AssertionLogic::new_item("$network", Op::Equal, &item.network); + item_logic = item_logic.add_item(network_item); + + for token in item.list { + let mut inner_logic = AssertionLogic::new_and(); + + let name_item = AssertionLogic::new_item("$token_name", Op::Equal, &token.name); + inner_logic = inner_logic.add_item(name_item); + + let address_item = + AssertionLogic::new_item("$token_address", Op::Equal, &token.address); + inner_logic = inner_logic.add_item(address_item); + + item_logic = item_logic.add_item(inner_logic) + } + + and_logic = and_logic.add_item(item_logic); + } + + and_logic +} + +#[cfg(test)] +mod tests { + use crate::nodereal::crypto_summary::SummaryHoldings; + + use super::build_assertions; + + #[test] + fn build_assertions_works() { + let flag_bsc_token = + [false, true, true, true, true, true, true, true, true, true, true, true]; + let flag_eth_token = [ + false, false, true, false, false, false, false, false, false, false, false, false, + false, false, false, + ]; + let flag_eth_nft = [ + true, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, + ]; + + let txs = 100_u64; + let summary = SummaryHoldings::construct(&flag_bsc_token, &flag_eth_token, &flag_eth_nft); + let (value, _logic) = build_assertions(txs, summary); + assert!(value); + } +} diff --git a/tee-worker/litentry/core/credentials/src/nodereal/mod.rs b/tee-worker/litentry/core/credentials/src/nodereal/mod.rs index bd8b22015c..84a4bff2f7 100644 --- a/tee-worker/litentry/core/credentials/src/nodereal/mod.rs +++ b/tee-worker/litentry/core/credentials/src/nodereal/mod.rs @@ -22,4 +22,5 @@ extern crate sgx_tstd as std; pub mod amount_holding; pub mod bnb_domain; +pub mod crypto_summary; pub mod nft_holder; diff --git a/tee-worker/litentry/core/data-providers/src/lib.rs b/tee-worker/litentry/core/data-providers/src/lib.rs index 0489aba446..e8773c8342 100644 --- a/tee-worker/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/litentry/core/data-providers/src/lib.rs @@ -424,7 +424,7 @@ impl ConvertParameterString for AchainableParams { } } -fn hex_to_decimal(hex_string: &str) -> f64 { +pub fn hex_to_decimal(hex_string: &str) -> f64 { let parts: Vec<&str> = hex_string.split('.').collect(); let integer_part = u64::from_str_radix(parts[0], 16).unwrap_or_default(); diff --git a/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs b/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs index 346f5a5041..a028429bc5 100644 --- a/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs +++ b/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs @@ -299,6 +299,7 @@ pub struct GetTokenBalance20Param { // Fungible Tokens API pub trait FungibleApiList { fn get_token_balance_20(&mut self, param: &GetTokenBalance20Param) -> Result; + fn get_token_holdings(&mut self, address: &str) -> Result; } impl FungibleApiList for NoderealJsonrpcClient { @@ -329,6 +330,84 @@ impl FungibleApiList for NoderealJsonrpcClient { Err(e) => Err(Error::RequestError(format!("{:?}", e))), } } + + fn get_token_holdings(&mut self, address: &str) -> Result { + let params: Vec = vec![address.to_string(), "0x1".to_string(), "0x64".to_string()]; + debug!("get_token_holdings: {:?}", params); + + let req_body = RpcRequest { + jsonrpc: "2.0".to_string(), + method: "nr_getTokenHoldings".to_string(), + params: params.to_vec(), + id: Id::Number(1), + }; + + self.post(&req_body) + } +} + +pub trait EthBalance { + fn get_balance(&mut self, address: &str) -> Result; +} + +impl EthBalance for NoderealJsonrpcClient { + fn get_balance(&mut self, address: &str) -> Result { + let params = vec![address.to_string(), "latest".to_string()]; + + let req_body = RpcRequest { + jsonrpc: "2.0".to_string(), + method: "eth_getBalance".to_string(), + params, + id: Id::Number(1), + }; + + match self.post(&req_body) { + Ok(resp) => { + // result example: '0x', '0x8' + debug!("eth_getBalance, response: {:?}", resp); + match resp.result.as_str() { + Some(result) => Ok(hex_to_decimal(&result[2..])), + None => Err(Error::RequestError(format!( + "Cannot tansform response result {:?} to &str", + resp.result + ))), + } + }, + Err(e) => Err(Error::RequestError(format!("{:?}", e))), + } + } +} + +pub trait TransactionCount { + fn get_transaction_count(&mut self, address: &str) -> Result; +} + +impl TransactionCount for NoderealJsonrpcClient { + fn get_transaction_count(&mut self, address: &str) -> Result { + let params = vec![address.to_string(), "latest".to_string()]; + + let req_body = RpcRequest { + jsonrpc: "2.0".to_string(), + method: "eth_getTransactionCount".to_string(), + params, + id: Id::Number(1), + }; + + match self.post(&req_body) { + Ok(resp) => { + // result example: '0x', '0x8' + debug!("eth_getTransactionCount, response: {:?}", resp); + match resp.result.as_str() { + Some(result) => Ok(hex_to_decimal(&result[2..]) as u64), + None => Err(Error::RequestError(format!( + "Cannot tansform response result {:?} to &str", + resp.result + ))), + } + }, + Err(e) => Err(Error::RequestError(format!("{:?}", e))), + } + } } #[cfg(test)] diff --git a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs index 45c419d20f..e520c5189c 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs @@ -132,6 +132,9 @@ where Assertion::BRC20AmountHolder => lc_assertion_build::brc20::amount_holder::build(&self.req), + + Assertion::CryptoSummary => + lc_assertion_build::nodereal::crypto_summary::build(&self.req), }?; // post-process the credential diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs index 85928d84e3..63e8adb99a 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs @@ -108,6 +108,9 @@ where Assertion::BRC20AmountHolder => lc_assertion_build::brc20::amount_holder::build(&self.req), + + Assertion::CryptoSummary => + lc_assertion_build::nodereal::crypto_summary::build(&self.req), }?; // post-process the credential diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index d345a4bf2b..66fc15e94f 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -290,6 +290,7 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::LITStaking => "LITStaking", Assertion::EVMAmountHolding(_) => "EVMAmountHolding", Assertion::BRC20AmountHolder => "BRC20AmountHolder", + Assertion::CryptoSummary => "CryptoSummary", }, }; inc_stf_calls(category, label); From ec1d9f1247c6e4909192686f2ae24ef7b5abdad7 Mon Sep 17 00:00:00 2001 From: Verin1005 <104152026+Verin1005@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:54:07 +0800 Subject: [PATCH 31/43] Add precompile bridge(transferNative) test case (#2368) * add bridge test case * remove unused imports * update transferNative logic * remove unsued imports * rename steps desc * revert transfer amounts * check event data * remove nonce check --- ts-tests/common/utils/function.ts | 34 +++- .../precompile-contract.test.ts | 154 ++++++++++++++---- 2 files changed, 155 insertions(+), 33 deletions(-) diff --git a/ts-tests/common/utils/function.ts b/ts-tests/common/utils/function.ts index 5da60e9104..c94ede409f 100644 --- a/ts-tests/common/utils/function.ts +++ b/ts-tests/common/utils/function.ts @@ -1,6 +1,6 @@ import { AddressOrPair, ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; import { ApiPromise } from '@polkadot/api'; - +import { FrameSystemEventRecord } from '@polkadot/types/lookup'; export function sleep(secs: number) { return new Promise((resolve) => { setTimeout(resolve, secs * 1000); @@ -40,3 +40,35 @@ export async function sudoWrapper(api: ApiPromise, tx: SubmittableExtrinsic => { + return new Promise((resolve, reject) => { + let blocksToScan = 15; + const unsubscribe = api.rpc.chain.subscribeNewHeads(async (blockHeader) => { + const shiftedApi = await api.at(blockHeader.hash); + + const allBlockEvents = await shiftedApi.query.system.events(); + const allExtrinsicEvents = allBlockEvents.filter(({ phase }) => phase.isApplyExtrinsic); + + const matchingEvent = allExtrinsicEvents.filter(({ event, phase }) => { + return event.section === section && event.method === method; + }); + + if (matchingEvent.length == 0) { + blocksToScan -= 1; + if (blocksToScan < 1) { + reject(new Error(`timed out listening for event ${section}.${method}`)); + (await unsubscribe)(); + } + return; + } + + resolve(matchingEvent); + (await unsubscribe)(); + }); + }); +}; diff --git a/ts-tests/integration-tests/precompile-contract.test.ts b/ts-tests/integration-tests/precompile-contract.test.ts index 0119b62864..bb3b9d65d5 100644 --- a/ts-tests/integration-tests/precompile-contract.test.ts +++ b/ts-tests/integration-tests/precompile-contract.test.ts @@ -1,18 +1,23 @@ -import { assert, expect } from 'chai'; +import { expect } from 'chai'; import { step } from 'mocha-steps'; import { AbiItem } from 'web3-utils'; -import { signAndSend, describeLitentry, loadConfig } from '../common/utils'; +import { signAndSend, describeLitentry, loadConfig, subscribeToEvents } from '../common/utils'; import Web3 from 'web3'; -import precompileContractAbi from '../common/abi/precompile/Staking.json'; +import precompileStakingContractAbi from '../common/abi/precompile/Staking.json'; +import precompileBridgeContractAbi from '../common/abi/precompile/Bridge.json'; +const BN = require('bn.js'); import { mnemonicGenerate, mnemonicToMiniSecret, evmToAddress } from '@polkadot/util-crypto'; import { KeyringPair } from '@polkadot/keyring/types'; +import { HexString } from '@polkadot/util/types'; const toBigNumber = (int: number) => int * 1e12; +const bn1e12 = new BN(10).pow(new BN(12)).mul(new BN(1)); describeLitentry('Test Parachain Precompile Contract', ``, (context) => { const config = loadConfig(); - const precompileContractAddress = '0x000000000000000000000000000000000000502d'; + const precompileStakingContractAddress = '0x000000000000000000000000000000000000502d'; + const precompileBridgeContractAddress = '0x000000000000000000000000000000000000503d'; const evmAccountRaw = { privateKey: '0x01ab6e801c06e59ca97a14fc0a1978b27fa366fc87450e0b65459dd3515b7391', address: '0xaaafB3972B05630fCceE866eC69CdADd9baC2771', @@ -25,9 +30,17 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { const collatorPublicKey = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; const web3 = new Web3(config.parachain_ws); - const precompileContract = new web3.eth.Contract(precompileContractAbi as AbiItem[], precompileContractAddress); - const executeTransaction = async (delegateTransaction: any, label = '') => { + const precompileStakingContract = new web3.eth.Contract( + precompileStakingContractAbi as AbiItem[], + precompileStakingContractAddress + ); + const precompileBridgeContract = new web3.eth.Contract( + precompileBridgeContractAbi as AbiItem[], + precompileBridgeContractAddress + ); + + const executeTransaction = async (delegateTransaction: any, contractAddress: HexString, label = '') => { console.log(`=== Executing ${label} ===`); // estimate gas doesn't work @@ -36,7 +49,7 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { const transaction = await web3.eth.accounts.signTransaction( { - to: precompileContractAddress, + to: contractAddress, data: delegateTransaction.encodeABI(), gas: 1000000, }, @@ -85,7 +98,9 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { }; const isPendingRequest = async () => - await precompileContract.methods.delegationRequestIsPending(evmAccountRaw.publicKey, collatorPublicKey).call(); + await precompileStakingContract.methods + .delegationRequestIsPending(evmAccountRaw.publicKey, collatorPublicKey) + .call(); const collatorDetails = async () => { const response = await context.api.query.parachainStaking.autoCompoundingDelegations(collatorPublicKey); @@ -98,7 +113,7 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { const randomSeed = mnemonicToMiniSecret(mnemonicGenerate()); const secretKey = Buffer.from(randomSeed).toString('hex'); - const delegateWithAutoCompound = precompileContract.methods.delegateWithAutoCompound( + const delegateWithAutoCompound = precompileStakingContract.methods.delegateWithAutoCompound( collatorPublicKey, toBigNumber(60), 1 @@ -107,7 +122,7 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { try { await web3.eth.accounts.signTransaction( { - to: precompileContractAddress, + to: precompileStakingContractAddress, data: delegateWithAutoCompound.encodeABI(), gas: await delegateWithAutoCompound.estimateGas(), }, @@ -120,8 +135,8 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { }); // To see full params types for the interfaces, check notion page: https://web3builders.notion.site/Parachain-Precompile-Contract-0c34929e5f16408084446dcf3dd36006 - step('Test precompile contract', async function () { - console.time('Test precompile contract'); + step('Test precompile staking contract', async function () { + console.time('Test precompile staking contract'); const filterMode = (await context.api.query.extrinsicFilter.mode()).toHuman(); if ('Test' !== filterMode) { let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode('Test')); @@ -131,7 +146,6 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { temp = await context.api.rpc.chain.getBlock(); console.log(`setMode await end: ${temp.block.header.number}`); } - let balance = (await context.api.query.system.account(evmAccountRaw.mappedAddress)).data; printBalance('initial balance', balance); @@ -149,7 +163,7 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { const autoCompoundPercent = 20; // delegateWithAutoCompound(collator, amount, percent) - const delegateWithAutoCompound = precompileContract.methods.delegateWithAutoCompound( + const delegateWithAutoCompound = precompileStakingContract.methods.delegateWithAutoCompound( collatorPublicKey, toBigNumber(60), autoCompoundPercent @@ -158,7 +172,11 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { let afterDelegateBalance = balance; // skip test if already delegated if (balance.reserved.toNumber() === 0) { - await executeTransaction(delegateWithAutoCompound, 'delegateWithAutoCompound'); + await executeTransaction( + delegateWithAutoCompound, + precompileStakingContractAddress, + 'delegateWithAutoCompound' + ); afterDelegateBalance = (await context.api.query.system.account(evmAccountRaw.mappedAddress)).data; expect(balance.free.toNumber() - toBigNumber(60)).to.closeTo( @@ -171,8 +189,11 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { } // delegatorBondMore(collator, amount) - const delegatorBondMore = precompileContract.methods.delegatorBondMore(collatorPublicKey, toBigNumber(1)); - await executeTransaction(delegatorBondMore, 'delegatorBondMore'); + const delegatorBondMore = precompileStakingContract.methods.delegatorBondMore( + collatorPublicKey, + toBigNumber(1) + ); + await executeTransaction(delegatorBondMore, precompileStakingContractAddress, 'delegatorBondMore'); const { data: balanceAfterBondMore } = await context.api.query.system.account(evmAccountRaw.mappedAddress); expect(balanceAfterBondMore.free.toNumber()).to.closeTo( @@ -184,28 +205,39 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { ); // setAutoCompound(collator, percent); - const setAutoCompound = precompileContract.methods.setAutoCompound(collatorPublicKey, autoCompoundPercent + 5); - await executeTransaction(setAutoCompound, 'setAutoCompound'); + const setAutoCompound = precompileStakingContract.methods.setAutoCompound( + collatorPublicKey, + autoCompoundPercent + 5 + ); + await executeTransaction(setAutoCompound, precompileStakingContractAddress, 'setAutoCompound'); const collatorAfterCompound = await collatorDetails(); expect(collatorAfterCompound.value).to.eq(autoCompoundPercent + 5); // scheduleDelegatorBondLess(collator, amount) expect(await isPendingRequest()).to.be.false; - const scheduleDelegatorBondLess = precompileContract.methods.scheduleDelegatorBondLess( + const scheduleDelegatorBondLess = precompileStakingContract.methods.scheduleDelegatorBondLess( collatorPublicKey, toBigNumber(5) ); - await executeTransaction(scheduleDelegatorBondLess, 'scheduleDelegatorBondLess'); + await executeTransaction( + scheduleDelegatorBondLess, + precompileStakingContractAddress, + 'scheduleDelegatorBondLess' + ); expect(await isPendingRequest()).to.be.true; // cancelDelegationRequest(collator) - const cancelDelegationRequest = precompileContract.methods.cancelDelegationRequest(collatorPublicKey); + const cancelDelegationRequest = precompileStakingContract.methods.cancelDelegationRequest(collatorPublicKey); expect(await isPendingRequest()).to.be.true; - await executeTransaction(cancelDelegationRequest, 'cancelDelegationRequest'); + await executeTransaction(cancelDelegationRequest, precompileStakingContractAddress, 'cancelDelegationRequest'); expect(await isPendingRequest()).to.be.false; // testing bond less + execution - await executeTransaction(scheduleDelegatorBondLess, 'scheduleDelegatorBondLess again to test execution'); + await executeTransaction( + scheduleDelegatorBondLess, + precompileStakingContractAddress, + 'scheduleDelegatorBondLess again to test execution' + ); expect(await isPendingRequest()).to.be.true; console.log('Waiting 2 blocks before execute delegation request'); @@ -213,11 +245,15 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { await context.api.rpc.chain.getBlock(); // executeDelegationRequest(delegator, collator); - const executeDelegationRequest = precompileContract.methods.executeDelegationRequest( + const executeDelegationRequest = precompileStakingContract.methods.executeDelegationRequest( evmAccountRaw.publicKey, collatorPublicKey ); - await executeTransaction(executeDelegationRequest, 'executeDelegationRequest'); + await executeTransaction( + executeDelegationRequest, + precompileStakingContractAddress, + 'executeDelegationRequest' + ); const { data: balanceAfterBondLess } = await context.api.query.system.account(evmAccountRaw.mappedAddress); expect(balanceAfterBondLess.free.toNumber()).to.closeTo( balanceAfterBondMore.free.toNumber() + toBigNumber(5), @@ -229,21 +265,29 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { // testing revoke delegation + execute // scheduleRevokeDelegation(collator); - const scheduleRevokeDelegation = precompileContract.methods.scheduleRevokeDelegation(collatorPublicKey); - await executeTransaction(scheduleRevokeDelegation, 'scheduleRevokeDelegation'); + const scheduleRevokeDelegation = precompileStakingContract.methods.scheduleRevokeDelegation(collatorPublicKey); + await executeTransaction( + scheduleRevokeDelegation, + precompileStakingContractAddress, + 'scheduleRevokeDelegation' + ); console.log('Waiting 2 blocks before execute delegation request'); await context.api.rpc.chain.getBlock(); await context.api.rpc.chain.getBlock(); - await executeTransaction(executeDelegationRequest, 'executeDelegationRequest'); + await executeTransaction( + executeDelegationRequest, + precompileStakingContractAddress, + 'executeDelegationRequest' + ); const { data: balanceAfterRevoke } = await context.api.query.system.account(evmAccountRaw.mappedAddress); expect(balanceAfterRevoke.free.toNumber()).to.closeTo(balance.free.toNumber(), toBigNumber(1)); expect(balanceAfterRevoke.reserved.toNumber()).to.eq(0); // delegate(collator, amount); - const delegate = precompileContract.methods.delegate(collatorPublicKey, toBigNumber(57)); - await executeTransaction(delegate, 'delegate'); + const delegate = precompileStakingContract.methods.delegate(collatorPublicKey, toBigNumber(57)); + await executeTransaction(delegate, precompileStakingContractAddress, 'delegate'); const { data: balanceAfterDelegate } = await context.api.query.system.account(evmAccountRaw.mappedAddress); expect(balanceAfterDelegate.reserved.toNumber()).to.eq(toBigNumber(57)); @@ -251,6 +295,52 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { let extrinsic = context.api.tx.sudo.sudo(context.api.tx.extrinsicFilter.setMode(filterMode)); await signAndSend(extrinsic, context.alice); - console.timeEnd('Test precompile contract'); + console.timeEnd('Test precompile staking contract'); + }); + step('Test precompile bridge contract', async function () { + console.time('Test precompile bridge contract'); + const dest_address = '0xaaafb3972b05630fccee866ec69cdadd9bac2772'; // random address + let balance = (await context.api.query.system.account(evmAccountRaw.mappedAddress)).data; + if (balance.free.toNumber() < toBigNumber(0.01)) { + await transferTokens(context.alice, evmAccountRaw); + expect(balance.free.toNumber()).to.gt(toBigNumber(0.01)); + } + + // update chain bridge fee + const updateFeeTx = context.api.tx.sudo.sudo(context.api.tx.chainBridge.updateFee(0, bn1e12 / 1000)); + await signAndSend(updateFeeTx, context.alice); + + const bridge_fee = await context.api.query.chainBridge.bridgeFee(0); + expect(bridge_fee.toString()).to.eq((bn1e12 / 1000).toString()); + + // set chainId to whitelist + const whitelistChainTx = context.api.tx.sudo.sudo(context.api.tx.chainBridge.whitelistChain(0)); + await signAndSend(whitelistChainTx, context.alice); + + // The above two steps are necessary, otherwise the contract transaction will be reverted. + // transfer native token + const transferNativeTx = precompileBridgeContract.methods.transferNative( + bn1e12 / 100, // 0.01 LIT + dest_address, + 0 + ); + + const res = await executeTransaction(transferNativeTx, precompileBridgeContractAddress, 'transferNative'); + expect(res.status).to.eq(true); + + const eventsPromise = subscribeToEvents('chainBridge', 'FungibleTransfer', context.api); + const events = (await eventsPromise).map(({ event }) => event); + + expect(events.length).to.eq(1); + const event_data = events[0].toHuman().data! as Array; + + // FungibleTransfer(BridgeChainId, DepositNonce, ResourceId, u128, Vec) + expect(event_data[0]).to.eq('0'); + const destResourceId = context.api.consts.bridgeTransfer.nativeTokenResourceId.toHex(); + expect(event_data[2]).to.eq(destResourceId); + expect(event_data[3]).to.eq((bn1e12 / 100 - bn1e12 / 1000).toLocaleString()); + expect(event_data[4]).to.eq(dest_address); + + console.timeEnd('Test precompile bridge contract'); }); }); From 5f4908fdbbc25ef30ec7bbc4e338e3104a9c4ada Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:24:32 +0100 Subject: [PATCH 32/43] switch the order of unittests (#2374) Co-authored-by: Kasper Ziemianek Co-authored-by: WMQ <46511820+wangminqi@users.noreply.github.com> --- tee-worker/enclave-runtime/src/test/tests_main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tee-worker/enclave-runtime/src/test/tests_main.rs b/tee-worker/enclave-runtime/src/test/tests_main.rs index 28c3312693..64416fb0dd 100644 --- a/tee-worker/enclave-runtime/src/test/tests_main.rs +++ b/tee-worker/enclave-runtime/src/test/tests_main.rs @@ -154,8 +154,8 @@ pub extern "C" fn test_main_entrance() -> size_t { tls_ra::seal_handler::test::seal_state_works, tls_ra::seal_handler::test::seal_state_fails_for_invalid_state, tls_ra::seal_handler::test::unseal_seal_state_works, - tls_ra::tests::test_tls_ra_server_client_networking, tls_ra::tests::test_state_and_key_provisioning, + tls_ra::tests::test_tls_ra_server_client_networking, // RPC tests direct_rpc_tests::get_state_request_works, From f00fc012bd1bf1d0da7ca2aa7829a123b27caf35 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:31:47 +0800 Subject: [PATCH 33/43] update geniidata query limit to i32::MAX (#2377) Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com> --- tee-worker/litentry/core/data-providers/src/geniidata.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tee-worker/litentry/core/data-providers/src/geniidata.rs b/tee-worker/litentry/core/data-providers/src/geniidata.rs index e733f1df6c..8857fb8d0d 100644 --- a/tee-worker/litentry/core/data-providers/src/geniidata.rs +++ b/tee-worker/litentry/core/data-providers/src/geniidata.rs @@ -71,6 +71,9 @@ impl RestPath for GeniidataResponse { } } +// According to https://geniidata.readme.io/reference/get-brc20-tick-list-copy, the maximum limit is i32::MAX +const GENIIDATA_QUERY_LIMIT: &str = "2147483647"; + pub struct GeniidataClient { client: RestClient>, } @@ -95,7 +98,8 @@ impl GeniidataClient { ) -> Result, DataProviderError> { let mut all_items: Vec = Vec::new(); for address in addresses { - let query = vec![("limit", "20"), ("offset", "0"), ("address", &address)]; + let query = + vec![("limit", GENIIDATA_QUERY_LIMIT), ("offset", "0"), ("address", &address)]; let response = self .client .get_with::("".to_string(), query.as_slice()) From af8ee2b86b5b181ff8a2b23f3cf867ed42e5a792 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:40:09 +0800 Subject: [PATCH 34/43] P-396 ton amount error (#2378) * add unit test * add TON/Trx decimals * update test --- .../amount_holding/evm_amount_holding.rs | 21 ++++++++++++------- .../amount_holding/evm_amount_holding.rs | 12 +++++++++++ .../litentry/core/data-providers/src/lib.rs | 12 +++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs index d60b921f01..88229f3f9c 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs @@ -25,7 +25,7 @@ use core::result; use crate::*; use lc_credentials::{ nodereal::amount_holding::evm_amount_holding::{ - EVMAmountHoldingAssertionUpdate, EVMTokenAddress, + EVMAmountHoldingAssertionUpdate, EVMTokenAddress, TokenDecimals, }, Credential, }; @@ -45,6 +45,8 @@ fn get_holding_balance( let mut bsc_client = NoderealJsonrpcClient::new(NoderealChain::Bsc); let mut total_balance = 0_f64; + let decimals = token_type.get_decimals(); + for address in addresses.iter() { let param = GetTokenBalance20Param { contract_address: token_type.get_address(address.0).unwrap_or_default().into(), @@ -68,7 +70,7 @@ fn get_holding_balance( } } - Ok(total_balance) + Ok(total_balance / decimals) } pub fn build(req: &AssertionBuildRequest, token_type: EVMTokenType) -> Result { @@ -203,17 +205,17 @@ mod tests { Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::GreaterEq, - dst: "1600".into() + dst: "0".into() }), Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::LessThan, - dst: "3000".into() + dst: "100".into() }) ] } ); - assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), false); }, Err(e) => { panic!("build EVMAmount holding failed with error {:?}", e); @@ -309,12 +311,17 @@ mod tests { Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::GreaterEq, - dst: "3000".into() + dst: "0".into() + }), + Box::new(AssertionLogic::Item { + src: "$holding_amount".into(), + op: Op::LessThan, + dst: "100".into() }) ] } ); - assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), false); }, Err(e) => { panic!("build EVMAmount holding failed with error {:?}", e); diff --git a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs index b03d9fe399..4cdcf51ba8 100644 --- a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs @@ -75,6 +75,18 @@ impl AssertionTokenName for EVMTokenType { } } +pub trait TokenDecimals { + fn get_decimals(&self) -> f64; +} + +impl TokenDecimals for EVMTokenType { + fn get_decimals(&self) -> f64 { + match self { + EVMTokenType::Ton | EVMTokenType::Trx => 1_000_000_000.0, + } + } +} + pub trait EVMAmountHoldingAssertionUpdate { fn update_evm_amount_holding_assertion(&mut self, token_type: EVMTokenType, amount: f64); } diff --git a/tee-worker/litentry/core/data-providers/src/lib.rs b/tee-worker/litentry/core/data-providers/src/lib.rs index e8773c8342..30216ff696 100644 --- a/tee-worker/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/litentry/core/data-providers/src/lib.rs @@ -437,3 +437,15 @@ pub fn hex_to_decimal(hex_string: &str) -> f64 { integer_part as f64 } } + +#[cfg(test)] +mod tests { + use crate::hex_to_decimal; + + #[test] + fn hex_to_decimal_works() { + let hex_string = "0000000000000000000000000000000000000000000000000000000babf2cf8b"; + let d = hex_to_decimal(hex_string); + assert_eq!(d, 50129457035.0); + } +} From 4c6efc0c7e88091278cd78143360497da789bba5 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:41:04 +0100 Subject: [PATCH 35/43] Merged cargo update (#2375) * switch the order of unittests * Update dependabot carg deps * update num_enum * update Cargo.lock --- Cargo.lock | 477 ++++++++++++----------- node/Cargo.toml | 4 +- precompiles/bridge-transfer/Cargo.toml | 2 +- precompiles/parachain-staking/Cargo.toml | 2 +- precompiles/utils/Cargo.toml | 2 +- precompiles/utils/macro/Cargo.toml | 2 +- tee-worker/Cargo.lock | 32 +- 7 files changed, 271 insertions(+), 250 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e53e8f3b7..2f4b4db678 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,18 +445,18 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1058,7 +1058,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1512,7 +1512,7 @@ dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", "cumulus-primitives-core", - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "parking_lot 0.12.1", "polkadot-node-primitives", @@ -1535,7 +1535,7 @@ dependencies = [ "async-trait", "cumulus-client-consensus-common", "cumulus-primitives-core", - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "sc-client-api", "sc-consensus", @@ -1566,7 +1566,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", "dyn-clone", - "futures 0.3.29", + "futures 0.3.30", "log", "parity-scale-codec", "polkadot-primitives", @@ -1587,7 +1587,7 @@ source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603 dependencies = [ "async-trait", "cumulus-relay-chain-interface", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "parity-scale-codec", "parking_lot 0.12.1", @@ -1611,7 +1611,7 @@ dependencies = [ "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "parity-scale-codec", "polkadot-node-primitives", @@ -1641,7 +1641,7 @@ dependencies = [ "cumulus-relay-chain-inprocess-interface", "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", - "futures 0.3.29", + "futures 0.3.30", "polkadot-primitives", "sc-client-api", "sc-consensus", @@ -1729,10 +1729,10 @@ name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1832,7 +1832,7 @@ version = "0.1.0" source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "sp-inherents", "sp-std", @@ -1865,7 +1865,7 @@ dependencies = [ "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "polkadot-cli", "polkadot-client", @@ -1889,7 +1889,7 @@ source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603 dependencies = [ "async-trait", "cumulus-primitives-core", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee-core", "parity-scale-codec", "polkadot-overseer", @@ -1910,7 +1910,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", "cumulus-relay-chain-rpc-interface", - "futures 0.3.29", + "futures 0.3.30", "lru 0.9.0", "polkadot-availability-recovery", "polkadot-collator-protocol", @@ -1946,7 +1946,7 @@ dependencies = [ "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "jsonrpsee", "lru 0.9.0", @@ -2045,7 +2045,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -2062,7 +2062,7 @@ checksum = "b8fcfa71f66c8563c4fa9dd2bb68368d50267856f831ac5d85367e0805f9606c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -2340,7 +2340,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -2533,7 +2533,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -2544,7 +2544,7 @@ checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -2794,7 +2794,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", ] [[package]] @@ -2844,7 +2844,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -2892,7 +2892,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -2944,7 +2944,7 @@ dependencies = [ "fc-storage", "fp-consensus", "fp-rpc", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "parking_lot 0.12.1", @@ -2972,7 +2972,7 @@ dependencies = [ "fp-evm", "fp-rpc", "fp-storage", - "futures 0.3.29", + "futures 0.3.30", "hex", "jsonrpsee", "libsecp256k1", @@ -3101,7 +3101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" dependencies = [ "either", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "num-traits", @@ -3358,10 +3358,10 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3416,7 +3416,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-recursion", - "futures 0.3.29", + "futures 0.3.30", "indicatif", "jsonrpsee", "log", @@ -3476,7 +3476,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3485,10 +3485,10 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3498,7 +3498,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3595,9 +3595,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -3610,9 +3610,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -3620,15 +3620,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -3638,9 +3638,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -3659,13 +3659,13 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3681,15 +3681,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -3699,9 +3699,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures 0.1.31", "futures-channel", @@ -4190,7 +4190,7 @@ dependencies = [ "async-io", "core-foundation", "fnv", - "futures 0.3.29", + "futures 0.3.30", "if-addrs", "ipnet", "log", @@ -4493,7 +4493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" dependencies = [ "heck", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -4764,7 +4764,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7b0104790be871edcf97db9bd2356604984e623a08d825c3f27852290266b8" dependencies = [ "bytes", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "getrandom 0.2.10", "instant", @@ -4802,7 +4802,7 @@ dependencies = [ "ed25519-dalek", "either", "fnv", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "instant", "log", @@ -4833,7 +4833,7 @@ checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" dependencies = [ "either", "fnv", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "instant", "libp2p-identity", @@ -4859,7 +4859,7 @@ version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e42a271c1b49f789b92f7fc87749fa79ce5c7bdc88cbdfacb818a4bca47fec5" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "libp2p-core 0.38.0", "log", "parking_lot 0.12.1", @@ -4874,7 +4874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c052d0026f4817b44869bfb6810f4e1112f43aec8553f2cb38881c524b563abf" dependencies = [ "asynchronous-codec", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "libp2p-core 0.38.0", "libp2p-swarm", @@ -4917,7 +4917,7 @@ dependencies = [ "bytes", "either", "fnv", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "instant", "libp2p-core 0.38.0", @@ -4941,7 +4941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04f378264aade9872d6ccd315c0accc18be3a35d15fc1b9c36e5b6f983b62b5b" dependencies = [ "data-encoding", - "futures 0.3.29", + "futures 0.3.30", "if-watch", "libp2p-core 0.38.0", "libp2p-swarm", @@ -4976,7 +4976,7 @@ checksum = "03805b44107aa013e7cbbfa5627b31c36cbedfdfb00603c0311998882bc4bace" dependencies = [ "asynchronous-codec", "bytes", - "futures 0.3.29", + "futures 0.3.30", "libp2p-core 0.38.0", "log", "nohash-hasher", @@ -4994,7 +4994,7 @@ checksum = "a978cb57efe82e892ec6f348a536bfbd9fee677adbe5689d7a93ad3a9bffbf2e" dependencies = [ "bytes", "curve25519-dalek 3.2.0", - "futures 0.3.29", + "futures 0.3.30", "libp2p-core 0.38.0", "log", "once_cell", @@ -5015,7 +5015,7 @@ version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "929fcace45a112536e22b3dcfd4db538723ef9c3cb79f672b98be2cc8e25f37f" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "instant", "libp2p-core 0.38.0", @@ -5032,7 +5032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01e7c867e95c8130667b24409d236d37598270e6da69b3baf54213ba31ffca59" dependencies = [ "bytes", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "if-watch", "libp2p-core 0.38.0", @@ -5054,7 +5054,7 @@ checksum = "3236168796727bfcf4927f766393415361e2c644b08bedb6a6b13d957c9a4884" dependencies = [ "async-trait", "bytes", - "futures 0.3.29", + "futures 0.3.30", "instant", "libp2p-core 0.38.0", "libp2p-swarm", @@ -5072,7 +5072,7 @@ checksum = "b2a35472fe3276b3855c00f1c032ea8413615e030256429ad5349cdf67c6e1a0" dependencies = [ "either", "fnv", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "instant", "libp2p-core 0.38.0", @@ -5103,7 +5103,7 @@ version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b257baf6df8f2df39678b86c578961d48cc8b68642a12f0f763f56c8e5858d" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "if-watch", "libc", @@ -5119,7 +5119,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "futures-rustls", "libp2p-core 0.39.2", "libp2p-identity", @@ -5138,7 +5138,7 @@ version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bb1a35299860e0d4b3c02a3e74e3b293ad35ae0cee8a056363b0c862d082069" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "js-sys", "libp2p-core 0.38.0", "parity-send-wrapper", @@ -5155,7 +5155,7 @@ dependencies = [ "async-trait", "asynchronous-codec", "bytes", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "hex", "if-watch", @@ -5184,7 +5184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d705506030d5c0aaf2882437c70dab437605f21c5f9811978f694e6917a3b54" dependencies = [ "either", - "futures 0.3.29", + "futures 0.3.30", "futures-rustls", "libp2p-core 0.38.0", "log", @@ -5202,7 +5202,7 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f63594a0aa818642d9d4915c791945053877253f08a3626f13416b5cd928a29" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "libp2p-core 0.38.0", "log", "parking_lot 0.12.1", @@ -5361,7 +5361,7 @@ dependencies = [ "fp-rpc", "frame-benchmarking", "frame-benchmarking-cli", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "litentry-parachain-runtime", "litmus-parachain-runtime", @@ -5421,7 +5421,7 @@ version = "0.9.12" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -5784,7 +5784,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "rand 0.8.5", "thrift", ] @@ -5820,7 +5820,7 @@ name = "mmr-gadget" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "log", "parity-scale-codec", "sc-client-api", @@ -5931,7 +5931,7 @@ version = "0.1.0" source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" dependencies = [ "ethereum-types", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "moonbeam-client-evm-tracing", "moonbeam-rpc-core-types", @@ -5946,7 +5946,7 @@ version = "0.6.0" source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" dependencies = [ "ethereum-types", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "moonbeam-client-evm-tracing", "moonbeam-rpc-core-types", @@ -5989,7 +5989,7 @@ dependencies = [ "fc-rpc", "fc-storage", "fp-rpc", - "futures 0.3.29", + "futures 0.3.30", "hex-literal 0.3.4", "jsonrpsee", "moonbeam-client-evm-tracing", @@ -6052,7 +6052,7 @@ dependencies = [ "fc-rpc-core", "fc-storage", "fp-rpc", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "moonbeam-client-evm-tracing", "moonbeam-rpc-core-trace", @@ -6179,7 +6179,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", @@ -6200,7 +6200,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" dependencies = [ "bytes", - "futures 0.3.29", + "futures 0.3.30", "log", "pin-project", "smallvec", @@ -6294,7 +6294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" dependencies = [ "bytes", - "futures 0.3.29", + "futures 0.3.30", "log", "netlink-packet-core", "netlink-sys", @@ -6309,7 +6309,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ "bytes", - "futures 0.3.29", + "futures 0.3.30", "libc", "log", "tokio", @@ -6464,43 +6464,43 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.11" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" dependencies = [ - "num_enum_derive 0.5.11", + "num_enum_derive 0.6.1", ] [[package]] name = "num_enum" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" dependencies = [ - "num_enum_derive 0.6.1", + "num_enum_derive 0.7.1", ] [[package]] name = "num_enum_derive" -version = "0.5.11" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.46", ] [[package]] name = "num_enum_derive" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -6580,7 +6580,7 @@ checksum = "227585216d05ba65c7ab0a0450a3cf2cbd81a98862a54c4df8e14d5ac6adb015" dependencies = [ "async-trait", "dyn-clonable", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "orchestra-proc-macro", "pin-project", @@ -6598,7 +6598,7 @@ dependencies = [ "expander 0.0.6", "itertools", "petgraph", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -7207,7 +7207,7 @@ dependencies = [ "frame-system", "hex-literal 0.4.1", "log", - "num_enum 0.6.1", + "num_enum 0.7.1", "pallet-balances", "pallet-bridge", "pallet-bridge-transfer", @@ -7262,7 +7262,7 @@ dependencies = [ "frame-support", "frame-system", "log", - "num_enum 0.6.1", + "num_enum 0.7.1", "pallet-balances", "pallet-evm", "pallet-parachain-staking", @@ -7848,10 +7848,10 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -8194,9 +8194,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.4" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -8209,11 +8209,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.4" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.1", "proc-macro2", "quote", "syn 1.0.109", @@ -8369,7 +8369,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -8410,7 +8410,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -8474,7 +8474,7 @@ name = "polkadot-approval-distribution" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", @@ -8490,7 +8490,7 @@ name = "polkadot-availability-bitfield-distribution" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", @@ -8506,7 +8506,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "derive_more", "fatality", - "futures 0.3.29", + "futures 0.3.30", "lru 0.9.0", "parity-scale-codec", "polkadot-erasure-coding", @@ -8528,7 +8528,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "fatality", - "futures 0.3.29", + "futures 0.3.30", "lru 0.9.0", "parity-scale-codec", "polkadot-erasure-coding", @@ -8550,7 +8550,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "clap", "frame-benchmarking-cli", - "futures 0.3.29", + "futures 0.3.30", "log", "polkadot-client", "polkadot-node-core-pvf-worker", @@ -8582,7 +8582,7 @@ dependencies = [ "frame-benchmarking-cli", "frame-system", "frame-system-rpc-runtime-api", - "futures 0.3.29", + "futures 0.3.30", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "polkadot-core-primitives", @@ -8622,7 +8622,7 @@ dependencies = [ "always-assert", "bitvec", "fatality", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -8655,7 +8655,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "derive_more", "fatality", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "indexmap 1.9.3", "lru 0.9.0", @@ -8692,7 +8692,7 @@ name = "polkadot-gossip-support" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "polkadot-node-network-protocol", "polkadot-node-subsystem", @@ -8716,7 +8716,7 @@ dependencies = [ "async-trait", "bytes", "fatality", - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "parking_lot 0.12.1", "polkadot-node-metrics", @@ -8735,7 +8735,7 @@ name = "polkadot-node-collation-generation" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-primitives", @@ -8755,7 +8755,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "bitvec", "derive_more", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "kvdb", "lru 0.9.0", @@ -8783,7 +8783,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "kvdb", "parity-scale-codec", @@ -8805,7 +8805,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "bitvec", "fatality", - "futures 0.3.29", + "futures 0.3.30", "polkadot-erasure-coding", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -8822,7 +8822,7 @@ name = "polkadot-node-core-bitfield-signing" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", @@ -8838,7 +8838,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "parity-scale-codec", "polkadot-node-core-pvf", @@ -8857,7 +8857,7 @@ name = "polkadot-node-core-chain-api" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "polkadot-node-metrics", "polkadot-node-subsystem", "polkadot-primitives", @@ -8872,7 +8872,7 @@ name = "polkadot-node-core-chain-selection" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "kvdb", "parity-scale-codec", @@ -8890,7 +8890,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "fatality", - "futures 0.3.29", + "futures 0.3.30", "kvdb", "lru 0.9.0", "parity-scale-codec", @@ -8909,7 +8909,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "polkadot-node-subsystem", "polkadot-overseer", @@ -8927,7 +8927,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "bitvec", "fatality", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -8944,7 +8944,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "libc", "parity-scale-codec", @@ -8970,7 +8970,7 @@ name = "polkadot-node-core-pvf-checker" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", @@ -8988,7 +8988,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "assert_matches", "cpu-time", - "futures 0.3.29", + "futures 0.3.30", "libc", "parity-scale-codec", "polkadot-node-core-pvf", @@ -9015,7 +9015,7 @@ name = "polkadot-node-core-runtime-api" version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "lru 0.9.0", "polkadot-node-metrics", "polkadot-node-subsystem", @@ -9049,7 +9049,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bs58", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "parity-scale-codec", @@ -9070,7 +9070,7 @@ dependencies = [ "async-trait", "derive_more", "fatality", - "futures 0.3.29", + "futures 0.3.30", "hex", "parity-scale-codec", "polkadot-node-jaeger", @@ -9090,7 +9090,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-vec", - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", @@ -9123,7 +9123,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "async-trait", "derive_more", - "futures 0.3.29", + "futures 0.3.30", "orchestra", "polkadot-node-jaeger", "polkadot-node-network-protocol", @@ -9147,7 +9147,7 @@ dependencies = [ "async-trait", "derive_more", "fatality", - "futures 0.3.29", + "futures 0.3.30", "futures-channel", "itertools", "kvdb", @@ -9178,7 +9178,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "lru 0.9.0", "orchestra", @@ -9507,7 +9507,7 @@ dependencies = [ "frame-benchmarking-cli", "frame-support", "frame-system-rpc-runtime-api", - "futures 0.3.29", + "futures 0.3.30", "hex-literal 0.4.1", "kusama-runtime", "kvdb", @@ -9614,7 +9614,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f99 dependencies = [ "arrayvec 0.5.2", "fatality", - "futures 0.3.29", + "futures 0.3.30", "indexmap 1.9.3", "parity-scale-codec", "polkadot-node-network-protocol", @@ -9713,7 +9713,7 @@ dependencies = [ "hex-literal 0.4.1", "impl-trait-for-tuples", "log", - "num_enum 0.6.1", + "num_enum 0.7.1", "pallet-evm", "parity-scale-codec", "precompile-utils-macro", @@ -9730,11 +9730,11 @@ dependencies = [ name = "precompile-utils-macro" version = "0.9.17" dependencies = [ - "num_enum 0.5.11", + "num_enum 0.7.1", "proc-macro2", "quote", "sha3", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -9800,7 +9800,7 @@ dependencies = [ "coarsetime", "crossbeam-queue", "derive_more", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "nanorand", "thiserror", @@ -9814,7 +9814,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.14", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -9849,14 +9859,14 @@ checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -10040,9 +10050,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -10245,7 +10255,7 @@ checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -10660,7 +10670,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "log", "netlink-packet-route", "netlink-proto", @@ -10890,7 +10900,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "pin-project", "static_assertions", ] @@ -10936,7 +10946,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "ip_network", "libp2p", @@ -10963,7 +10973,7 @@ name = "sc-basic-authorship" version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "parity-scale-codec", @@ -11020,10 +11030,10 @@ name = "sc-chain-spec-derive" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -11035,7 +11045,7 @@ dependencies = [ "chrono", "clap", "fdlimit", - "futures 0.3.29", + "futures 0.3.30", "libp2p", "log", "names", @@ -11072,7 +11082,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "fnv", - "futures 0.3.29", + "futures 0.3.30", "log", "parity-scale-codec", "parking_lot 0.12.1", @@ -11124,7 +11134,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "libp2p", "log", @@ -11149,7 +11159,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "log", "parity-scale-codec", "sc-block-builder", @@ -11179,7 +11189,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "async-trait", "fork-tree", - "futures 0.3.29", + "futures 0.3.30", "log", "num-bigint", "num-rational", @@ -11213,7 +11223,7 @@ name = "sc-consensus-babe-rpc" version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "sc-consensus-babe", "sc-consensus-epochs", @@ -11238,7 +11248,7 @@ dependencies = [ "array-bytes 4.2.0", "async-trait", "fnv", - "futures 0.3.29", + "futures 0.3.30", "log", "parity-scale-codec", "parking_lot 0.12.1", @@ -11270,7 +11280,7 @@ name = "sc-consensus-beefy-rpc" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "log", "parity-scale-codec", @@ -11308,7 +11318,7 @@ dependencies = [ "dyn-clone", "finality-grandpa", "fork-tree", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "parity-scale-codec", @@ -11343,7 +11353,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "finality-grandpa", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "log", "parity-scale-codec", @@ -11363,7 +11373,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "parity-scale-codec", @@ -11454,7 +11464,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "log", "sc-client-api", @@ -11491,7 +11501,7 @@ dependencies = [ "bytes", "either", "fnv", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "ip_network", "libp2p", @@ -11530,7 +11540,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "cid", - "futures 0.3.29", + "futures 0.3.30", "libp2p", "log", "prost", @@ -11553,7 +11563,7 @@ dependencies = [ "async-trait", "bitflags 1.3.2", "bytes", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "libp2p", "parity-scale-codec", @@ -11578,7 +11588,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.3", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "libp2p", "log", @@ -11597,7 +11607,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", - "futures 0.3.29", + "futures 0.3.30", "libp2p", "log", "parity-scale-codec", @@ -11621,7 +11631,7 @@ dependencies = [ "array-bytes 4.2.0", "async-trait", "fork-tree", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "libp2p", "log", @@ -11653,7 +11663,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", - "futures 0.3.29", + "futures 0.3.30", "libp2p", "log", "parity-scale-codec", @@ -11675,7 +11685,7 @@ dependencies = [ "array-bytes 4.2.0", "bytes", "fnv", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "hyper", "hyper-rustls", @@ -11703,7 +11713,7 @@ name = "sc-peerset" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "libp2p", "log", "sc-utils", @@ -11725,7 +11735,7 @@ name = "sc-rpc" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "log", "parity-scale-codec", @@ -11790,7 +11800,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", - "futures 0.3.29", + "futures 0.3.30", "futures-util", "hex", "jsonrpsee", @@ -11818,7 +11828,7 @@ dependencies = [ "async-trait", "directories", "exit-future", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "jsonrpsee", "log", @@ -11894,7 +11904,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "clap", "fs4", - "futures 0.3.29", + "futures 0.3.30", "log", "sc-client-db", "sc-utils", @@ -11927,7 +11937,7 @@ name = "sc-sysinfo" version = "6.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "libc", "log", "rand 0.8.5", @@ -11947,7 +11957,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "chrono", - "futures 0.3.29", + "futures 0.3.30", "libp2p", "log", "parking_lot 0.12.1", @@ -11996,10 +12006,10 @@ name = "sc-tracing-proc-macro" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -12008,7 +12018,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "linked-hash-map", "log", @@ -12035,7 +12045,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "log", "serde", "sp-blockchain", @@ -12049,7 +12059,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-channel", - "futures 0.3.29", + "futures 0.3.30", "futures-timer", "lazy_static", "log", @@ -12078,7 +12088,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -12285,7 +12295,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -12587,7 +12597,7 @@ dependencies = [ "base64 0.13.1", "bytes", "flate2", - "futures 0.3.29", + "futures 0.3.30", "http", "httparse", "log", @@ -12623,10 +12633,10 @@ dependencies = [ "Inflector", "blake2", "expander 1.0.0", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -12686,7 +12696,7 @@ name = "sp-blockchain" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "log", "lru 0.8.1", "parity-scale-codec", @@ -12705,7 +12715,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "futures 0.3.29", + "futures 0.3.30", "log", "sp-core", "sp-inherents", @@ -12814,7 +12824,7 @@ dependencies = [ "bs58", "dyn-clonable", "ed25519-zebra", - "futures 0.3.29", + "futures 0.3.30", "hash-db 0.16.0", "hash256-std-hasher", "impl-serde", @@ -12868,7 +12878,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -12887,7 +12897,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -12924,7 +12934,7 @@ dependencies = [ "bytes", "ed25519", "ed25519-dalek", - "futures 0.3.29", + "futures 0.3.30", "libsecp256k1", "log", "parity-scale-codec", @@ -12958,7 +12968,7 @@ name = "sp-keystore" version = "0.13.0" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "parity-scale-codec", "parking_lot 0.12.1", "serde", @@ -13095,10 +13105,10 @@ version = "6.0.0" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -13266,7 +13276,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -13459,7 +13469,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -13542,7 +13552,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-system-rpc-runtime-api", - "futures 0.3.29", + "futures 0.3.30", "jsonrpsee", "log", "parity-scale-codec", @@ -13644,9 +13654,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", @@ -13770,7 +13780,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -13939,7 +13949,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -13998,7 +14008,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.14", ] [[package]] @@ -14023,6 +14033,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -14085,7 +14106,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -14125,10 +14146,10 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "expander 2.0.0", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -14310,7 +14331,7 @@ checksum = "4712ee30d123ec7ae26d1e1b218395a16c87cdbaf4b3925d170d684af62ea5e8" dependencies = [ "async-trait", "base64 0.13.1", - "futures 0.3.29", + "futures 0.3.30", "log", "md-5", "rand 0.8.5", @@ -14575,7 +14596,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", "wasm-bindgen-shared", ] @@ -14609,7 +14630,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -14676,7 +14697,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "js-sys", "parking_lot 0.11.2", "pin-utils", @@ -15683,7 +15704,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -15757,7 +15778,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" dependencies = [ - "futures 0.3.29", + "futures 0.3.30", "log", "nohash-hasher", "parking_lot 0.12.1", @@ -15791,7 +15812,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] diff --git a/node/Cargo.toml b/node/Cargo.toml index 9899f02c85..de0ebf6ed6 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -16,9 +16,9 @@ name = 'litentry-collator' targets = ['x86_64-unknown-linux-gnu'] [dependencies] -async-trait = "0.1.74" +async-trait = "0.1.76" clap = { version = "4.3", features = ["derive"] } -futures = { version = "0.3.29", features = ["compat"] } +futures = { version = "0.3.30", features = ["compat"] } log = "0.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/precompiles/bridge-transfer/Cargo.toml b/precompiles/bridge-transfer/Cargo.toml index 3dc81a73b9..a90dd3e709 100644 --- a/precompiles/bridge-transfer/Cargo.toml +++ b/precompiles/bridge-transfer/Cargo.toml @@ -6,7 +6,7 @@ version = '0.9.17' [dependencies] log = { version = "0.4", default-features = false } -num_enum = { version = "0.6.1", default-features = false } +num_enum = { version = "0.7.1", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } rustc-hex = { version = "2.0.1", default-features = false } diff --git a/precompiles/parachain-staking/Cargo.toml b/precompiles/parachain-staking/Cargo.toml index ec296475e8..920147bdbd 100644 --- a/precompiles/parachain-staking/Cargo.toml +++ b/precompiles/parachain-staking/Cargo.toml @@ -6,7 +6,7 @@ version = '0.9.17' [dependencies] log = { version = "0.4", default-features = false } -num_enum = { version = "0.6.1", default-features = false } +num_enum = { version = "0.7.1", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } rustc-hex = { version = "2.0.1", default-features = false } diff --git a/precompiles/utils/Cargo.toml b/precompiles/utils/Cargo.toml index c2dba34af5..1c5333f58b 100644 --- a/precompiles/utils/Cargo.toml +++ b/precompiles/utils/Cargo.toml @@ -9,7 +9,7 @@ version = '0.9.17' evm = { git = "https://github.com/rust-blockchain/evm", rev = "b7b82c7e1fc57b7449d6dfa6826600de37cc1e65", default-features = false, optional = true } impl-trait-for-tuples = "0.2.2" log = { version = "0.4", default-features = false } -num_enum = { version = "0.6.1", default-features = false } +num_enum = { version = "0.7.1", default-features = false } sha3 = { version = "0.10", default-features = false } similar-asserts = { version = "1.5.0", optional = true } diff --git a/precompiles/utils/macro/Cargo.toml b/precompiles/utils/macro/Cargo.toml index c2a0c9ed6a..81a17076bc 100644 --- a/precompiles/utils/macro/Cargo.toml +++ b/precompiles/utils/macro/Cargo.toml @@ -12,7 +12,7 @@ name = "tests" path = "tests/tests.rs" [dependencies] -num_enum = { version = "0.5.3", default-features = false } +num_enum = { version = "0.7.1", default-features = false } proc-macro2 = { version = "1" } quote = { version = "1" } sha3 = { version = "0.10", default-features = false } diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 0b3c40a4f1..35484c8fb9 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -8182,40 +8182,40 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.11" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" dependencies = [ - "num_enum_derive 0.5.11", + "num_enum_derive 0.6.1", ] [[package]] name = "num_enum" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" dependencies = [ - "num_enum_derive 0.6.1", + "num_enum_derive 0.7.1", ] [[package]] name = "num_enum_derive" -version = "0.5.11" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.32", ] [[package]] name = "num_enum_derive" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.32", @@ -8864,7 +8864,7 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.20", - "num_enum 0.6.1", + "num_enum 0.7.1", "pallet-bridge", "pallet-bridge-transfer", "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", @@ -8913,7 +8913,7 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.20", - "num_enum 0.6.1", + "num_enum 0.7.1", "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "pallet-parachain-staking", "parity-scale-codec", @@ -10187,7 +10187,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log 0.4.20", - "num_enum 0.6.1", + "num_enum 0.7.1", "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "parity-scale-codec", "precompile-utils-macro", @@ -10203,7 +10203,7 @@ dependencies = [ name = "precompile-utils-macro" version = "0.9.17" dependencies = [ - "num_enum 0.5.11", + "num_enum 0.7.1", "proc-macro2", "quote", "sha3", From 14e10334345fe7edb373fcd6d3fee6a98177adf5 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:08:37 +0800 Subject: [PATCH 36/43] update ton/trx amount range (#2379) --- .../src/nodereal/amount_holding/evm_amount_holding.rs | 10 +++++----- .../src/nodereal/amount_holding/evm_amount_holding.rs | 4 ++-- .../litentry/core/mock-server/src/nodereal_jsonrpc.rs | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs index 88229f3f9c..3ec696032e 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs @@ -210,7 +210,7 @@ mod tests { Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::LessThan, - dst: "100".into() + dst: "1".into() }) ] } @@ -258,17 +258,17 @@ mod tests { Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::GreaterEq, - dst: "0".into() + dst: "100".into() }), Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::LessThan, - dst: "100".into() + dst: "200".into() }) ] } ); - assert_eq!(*(credential.credential_subject.values.first().unwrap()), false); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); }, Err(e) => { panic!("build EVMAmount holding failed with error {:?}", e); @@ -316,7 +316,7 @@ mod tests { Box::new(AssertionLogic::Item { src: "$holding_amount".into(), op: Op::LessThan, - dst: "100".into() + dst: "1".into() }) ] } diff --git a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs index 4cdcf51ba8..c1632897a1 100644 --- a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs @@ -42,8 +42,8 @@ impl EVMTokenAddress for EVMTokenType { } } -const EVM_HOLDING_AMOUNT_RANGE: [f64; 8] = - [0.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1600.0, 3000.0]; +const EVM_HOLDING_AMOUNT_RANGE: [f64; 10] = + [0.0, 1.0, 50.0, 100.0, 200.0, 500.0, 800.0, 1200.0, 1600.0, 3000.0]; const TYPE: &str = "Token Holding Amount"; const DESCRIPTION: &str = "The amount of a particular token you are holding"; diff --git a/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs b/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs index 3a0f64fb56..fc7643d5b5 100644 --- a/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs +++ b/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs @@ -64,7 +64,8 @@ pub(crate) fn query() -> impl Filter { let value = match params[1].as_str() { - "0x85be4e2ccc9c85be8783798b6e8a101bdac6467f" => "0x1", + // 100_000_000_000 + "0x85be4e2ccc9c85be8783798b6e8a101bdac6467f" => "0x174876E800", // 3000 "0x90d53026a47ac20609accc3f2ddc9fb9b29bb310" => "0xBB8", // 800.1 From bf3f9f5aaa6ac0cf534667f721b02cb0df28c499 Mon Sep 17 00:00:00 2001 From: Zhouhui Tian <125243011+zhouhuitian@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:25:13 +0800 Subject: [PATCH 37/43] TRX DECIMAL 6 (#2380) --- .../src/nodereal/amount_holding/evm_amount_holding.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs index c1632897a1..4bd0ed6f3e 100644 --- a/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/credentials/src/nodereal/amount_holding/evm_amount_holding.rs @@ -82,7 +82,15 @@ pub trait TokenDecimals { impl TokenDecimals for EVMTokenType { fn get_decimals(&self) -> f64 { match self { - EVMTokenType::Ton | EVMTokenType::Trx => 1_000_000_000.0, + // TON on BSCÐ decimals are both 9 + // https://bscscan.com/token/0x76a797a59ba2c17726896976b7b3747bfd1d220f + // https://etherscan.io/token/0x582d872a1b094fc48f5de31d3b73f2d9be47def1 + EVMTokenType::Ton => 1_000_000_000.0, + + // TRX on BSCÐ decimals are both 6 + // https://bscscan.com/token/0xce7de646e7208a4ef112cb6ed5038fa6cc6b12e3 + // https://etherscan.io/token/0x50327c6c5a14dcade707abad2e27eb517df87ab5 + EVMTokenType::Trx => 1_000_000.0, } } } From 51ab2709c3a408fe9877e105ff2292c254cfd08f Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:52:33 +0100 Subject: [PATCH 38/43] Filter out web3 identities with empty networks (#2348) * Filter out web3 identities with empty networks * check if eligible identities are empty * add tests * try to fix A1 test * include prime identity when requesting VCs * fix vc tests --- primitives/core/src/assertion.rs | 7 +- primitives/core/src/error.rs | 3 + .../app-libs/stf/src/trusted_call_litentry.rs | 40 +++---- .../interfaces/sidechain/definitions.ts | 1 + .../lc-vc-task-receiver/src/lib.rs | 29 ++--- .../src/identity_context.rs | 33 +++++- .../pallets/identity-management/src/lib.rs | 8 +- .../pallets/identity-management/src/tests.rs | 27 ++++- .../litentry/primitives/src/identity.rs | 26 +++-- .../common/utils/vc-helper.ts | 6 - .../ts-tests/integration-tests/di_vc.test.ts | 107 ++++++++++++++++++ .../ts-tests/integration-tests/ii_vc.test.ts | 11 -- 12 files changed, 228 insertions(+), 70 deletions(-) diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 2ff0a2cce2..642448e71e 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -18,8 +18,8 @@ // when requesting VCs. use crate::{ - AccountId, BnbDigitDomainType, BoundedWeb3Network, EVMTokenType, GenericDiscordRoleType, - OneBlockCourseType, VIP3MembershipCardLevel, Web3Network, + all_web3networks, AccountId, BnbDigitDomainType, BoundedWeb3Network, EVMTokenType, + GenericDiscordRoleType, OneBlockCourseType, VIP3MembershipCardLevel, Web3Network, }; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -271,6 +271,8 @@ impl Assertion { // the broader `Web3Network` (see network.rs) pub fn get_supported_web3networks(&self) -> Vec { match self { + // A1, any web3 network is allowed + Self::A1 => all_web3networks(), // LIT holder, not including `LitentryRococo` as it's not supported by any data provider Self::A4(..) => vec![Web3Network::Litentry, Web3Network::Litmus, Web3Network::Ethereum], // DOT holder @@ -298,7 +300,6 @@ impl Assertion { // BRC20 Holder Self::BRC20AmountHolder => vec![Web3Network::BitcoinP2tr], // we don't care about any specific web3 network - Self::A1 | Self::A2(..) | Self::A3(..) | Self::A6 | diff --git a/primitives/core/src/error.rs b/primitives/core/src/error.rs index bb90a63735..6e93ebe6ea 100644 --- a/primitives/core/src/error.rs +++ b/primitives/core/src/error.rs @@ -62,6 +62,9 @@ pub enum ErrorDetail { // of verification data #[codec(index = 10)] VerifyWeb3SignatureFailed, + // error when trying to build vc but no eligible identity is found + #[codec(index = 11)] + NoEligibleIdentity, } // We could have used Into, but we want it to be more explicit, similar to `into_iter` 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 a265cc00b2..f63da8b922 100644 --- a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs +++ b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs @@ -28,8 +28,11 @@ use crate::{ H256, }; use codec::Encode; -use frame_support::{dispatch::UnfilteredDispatchable, ensure}; -use ita_sgx_runtime::{IDGraph, RuntimeOrigin, System}; +use frame_support::{dispatch::UnfilteredDispatchable, ensure, sp_runtime::traits::One}; +use ita_sgx_runtime::{ + pallet_imt::{get_eligible_identities, IdentityContext}, + BlockNumber, IDGraph, RuntimeOrigin, System, +}; use itp_node_api::metadata::NodeMetadataTrait; use itp_node_api_metadata::pallet_imp::IMPCallIndexes; use itp_node_api_metadata_provider::AccessNodeMetadata; @@ -40,8 +43,7 @@ use lc_stf_task_sender::{ AssertionBuildRequest, RequestType, Web2IdentityVerificationRequest, }; use litentry_primitives::{ - Assertion, ErrorDetail, Identity, IdentityNetworkTuple, RequestAesKey, ValidationData, - Web3Network, + Assertion, ErrorDetail, Identity, RequestAesKey, ValidationData, Web3Network, }; use log::*; use std::{sync::Arc, vec::Vec}; @@ -168,22 +170,22 @@ impl TrustedCallSigned { ), } - let id_graph = IMT::id_graph(&who); + let mut id_graph = IMT::id_graph(&who); + if id_graph.is_empty() { + // we are safe to use `default_web3networks` and `Active` as IDGraph would be non-empty otherwise + id_graph.push(( + who.clone(), + IdentityContext::new(BlockNumber::one(), who.default_web3networks()), + )); + } let assertion_networks = assertion.get_supported_web3networks(); - let identities: Vec = id_graph - .into_iter() - .filter(|item| item.1.is_active()) - .map(|item| { - let mut networks = item.1.web3networks.to_vec(); - // filter out the web3networks which are not supported by this specific `assertion`. - // We do it here before every request sending because: - // - it's a common step for all assertion buildings, for those assertions which only - // care about web2 identities, this step will empty `IdentityContext.web3networks` - // - it helps to reduce the request size a bit - networks.retain(|n| assertion_networks.contains(n)); - (item.0, networks) - }) - .collect(); + let identities = get_eligible_identities(id_graph, assertion_networks); + + ensure!( + !identities.is_empty(), + StfError::RequestVCFailed(assertion, ErrorDetail::NoEligibleIdentity) + ); + let assertion_build: RequestType = AssertionBuildRequest { shard: *shard, signer, diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts index 51f11ae57f..c111ab837b 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts @@ -76,6 +76,7 @@ export default { UnexpectedMessage: "Null", __Unused_WrongSignatureType: "Null", VerifyWeb3SignatureFailed: "Null", + NoEligibleIdentity: "Null", }, }, // teerex diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs index c14a874f00..d81661bb9f 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs @@ -19,12 +19,11 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] pub use crate::sgx_reexport_prelude::*; -mod vc_handling; - use crate::vc_handling::VCRequestHandler; use codec::{Decode, Encode}; +use frame_support::{ensure, sp_runtime::traits::One}; pub use futures; -use ita_sgx_runtime::{Hash, Runtime}; +use ita_sgx_runtime::{pallet_imt::get_eligible_identities, BlockNumber, Hash, Runtime}; use ita_stf::{ aes_encrypt_default, helpers::enclave_signer_account, trusted_call_result::RequestVCResult, ConvertAccountId, Getter, OpaqueCall, SgxParentchainTypeConverter, TrustedCall, @@ -57,6 +56,8 @@ use std::{ }; use threadpool::ThreadPool; +mod vc_handling; + pub fn run_vc_handler_runner( context: Arc>, extrinsic_factory: Arc, @@ -152,21 +153,21 @@ where // Sorts the IDGraph in place sort_id_graph::(&mut id_graph); + if id_graph.is_empty() { + // we are safe to use `default_web3networks` and `Active` as IDGraph would be non-empty otherwise + id_graph.push(( + who.clone(), + IdentityContext::new(BlockNumber::one(), who.default_web3networks()), + )); + } + let assertion_networks = assertion.clone().get_supported_web3networks(); - let identities: Vec = id_graph - .into_iter() - .filter(|item| item.1.is_active()) - .map(|item| { - let mut networks = item.1.web3networks.to_vec(); - networks.retain(|n| assertion_networks.contains(n)); - (item.0, networks) - }) - .collect(); - - identities + get_eligible_identities(id_graph, assertion_networks) }) .map_err(|e| format!("Failed to fetch sidechain data due to: {:?}", e))?; + ensure!(!identities.is_empty(), "No eligible identity".to_string()); + let signer = signer .to_account_id() .ok_or_else(|| "Invalid signer account, failed to convert".to_string())?; 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 36a91a7112..1dff25389e 100644 --- a/tee-worker/litentry/pallets/identity-management/src/identity_context.rs +++ b/tee-worker/litentry/pallets/identity-management/src/identity_context.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::{BlockNumberOf, Config, Web3Network}; +use crate::{BlockNumberOf, Config, IDGraph, Web3Network}; use codec::{Decode, Encode}; use core::cmp::Ordering; -use litentry_primitives::Identity; +use litentry_primitives::{Identity, IdentityNetworkTuple}; use scale_info::TypeInfo; use sp_std::vec::Vec; @@ -83,3 +83,32 @@ pub fn sort_id_graph(id_graph: &mut [(Identity, IdentityContext)]) } }); } + +// get the active identities in the `id_graph` whose web3networks match the `desired_web3networks`, +// return a `Vec<(Identity, Vec)` with retained web3networks +pub fn get_eligible_identities( + id_graph: IDGraph, + desired_web3networks: Vec, +) -> Vec { + id_graph + .into_iter() + .filter_map(|item| { + if item.1.is_active() { + let mut networks = item.1.web3networks.to_vec(); + // filter out identities whose web3networks are not supported by this specific `assertion`. + // We do it here before every request sending because: + // - it's a common step for all assertion buildings, for those assertions which only + // care about web2 identities, this step will empty `IdentityContext.web3networks` + // - it helps to reduce the request size a bit + networks.retain(|n| desired_web3networks.contains(n)); + if networks.is_empty() && item.0.is_web3() { + None + } else { + Some((item.0, networks)) + } + } else { + None + } + }) + .collect() +} diff --git a/tee-worker/litentry/pallets/identity-management/src/lib.rs b/tee-worker/litentry/pallets/identity-management/src/lib.rs index 256781f5c3..a672902373 100644 --- a/tee-worker/litentry/pallets/identity-management/src/lib.rs +++ b/tee-worker/litentry/pallets/identity-management/src/lib.rs @@ -156,15 +156,9 @@ pub mod pallet { Error::::IdentityAlreadyLinked ); - let prime_identity_web3networks = match who { - Identity::Substrate(_) => all_substrate_web3networks(), - Identity::Evm(_) => all_evm_web3networks(), - Identity::Bitcoin(_) => all_bitcoin_web3networks(), - _ => vec![], - }; let context = >::new( ::BlockNumber::one(), - prime_identity_web3networks, + who.default_web3networks(), ); Self::insert_identity_with_limit(&who, &who, context)?; } diff --git a/tee-worker/litentry/pallets/identity-management/src/tests.rs b/tee-worker/litentry/pallets/identity-management/src/tests.rs index 63dfca243c..ad8fa38528 100644 --- a/tee-worker/litentry/pallets/identity-management/src/tests.rs +++ b/tee-worker/litentry/pallets/identity-management/src/tests.rs @@ -14,13 +14,38 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::{mock::*, Error, IDGraph, Identity, IdentityContext, IdentityStatus, Web3Network}; +use crate::{ + get_eligible_identities, mock::*, Error, IDGraph, Identity, IdentityContext, IdentityStatus, + Web3Network, +}; use frame_support::{assert_err, assert_noop, assert_ok, traits::Get}; use sp_runtime::AccountId32; pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]); +#[test] +fn get_eligible_identities_works() { + let mut id_graph = IDGraph::::default(); + id_graph.push(( + alice_substrate_identity(), + IdentityContext::new(1u64, vec![Web3Network::Litentry, Web3Network::Khala]), + )); + id_graph.push((alice_twitter_identity(1), IdentityContext::new(2u64, vec![]))); + let desired_web3networks = vec![Web3Network::Litentry, Web3Network::Polkadot]; + let mut identities = get_eligible_identities(id_graph.clone(), desired_web3networks.clone()); + assert_eq!(identities.len(), 2); + assert_eq!(identities[0].1, vec![Web3Network::Litentry]); + assert_eq!(identities[1].1, vec![]); + + // `alice_evm_identity` should be filtered out + id_graph.push((alice_evm_identity(), IdentityContext::new(1u64, vec![Web3Network::Bsc]))); + identities = get_eligible_identities(id_graph, desired_web3networks); + assert_eq!(identities.len(), 2); + assert_eq!(identities[0].1, vec![Web3Network::Litentry]); + assert_eq!(identities[1].1, vec![]); +} + #[test] fn link_twitter_identity_works() { new_test_ext().execute_with(|| { diff --git a/tee-worker/litentry/primitives/src/identity.rs b/tee-worker/litentry/primitives/src/identity.rs index 781d107387..8aa63d6595 100644 --- a/tee-worker/litentry/primitives/src/identity.rs +++ b/tee-worker/litentry/primitives/src/identity.rs @@ -21,6 +21,7 @@ use core::fmt::{Debug, Formatter}; #[cfg(all(not(feature = "sgx"), feature = "std"))] use serde::{Deserialize, Serialize}; +use crate::{all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks}; use codec::{Decode, Encode, Error, Input, MaxEncodedLen}; use itp_utils::{ hex::{decode_hex, hex_encode}, @@ -306,14 +307,25 @@ impl Identity { matches!(self, Self::Bitcoin(..)) } + pub fn default_web3networks(&self) -> Vec { + match self { + Identity::Substrate(_) => all_substrate_web3networks(), + Identity::Evm(_) => all_evm_web3networks(), + Identity::Bitcoin(_) => all_bitcoin_web3networks(), + Identity::Twitter(_) | Identity::Discord(_) | Identity::Github(_) => Vec::new(), + } + } + // check if the given web3networks match the identity pub fn matches_web3networks(&self, networks: &Vec) -> bool { - (self.is_substrate() && !networks.is_empty() && networks.iter().all(|n| n.is_substrate())) - || (self.is_evm() && !networks.is_empty() && networks.iter().all(|n| n.is_evm())) - || (self.is_bitcoin() - && !networks.is_empty() - && networks.iter().all(|n| n.is_bitcoin())) - || (self.is_web2() && networks.is_empty()) + match self { + Identity::Substrate(_) => + !networks.is_empty() && networks.iter().all(|n| n.is_substrate()), + Identity::Evm(_) => !networks.is_empty() && networks.iter().all(|n| n.is_evm()), + Identity::Bitcoin(_) => !networks.is_empty() && networks.iter().all(|n| n.is_bitcoin()), + Identity::Twitter(_) | Identity::Discord(_) | Identity::Github(_) => + networks.is_empty(), + } } /// Currently we only support mapping from Address32/Address20 to AccountId, not opposite. @@ -323,7 +335,7 @@ impl Identity { Identity::Evm(address) => Some(HashedAddressMapping::into_account_id(H160::from_slice(address.as_ref()))), Identity::Bitcoin(address) => Some(blake2_256(address.as_ref()).into()), - _ => None, + Identity::Twitter(_) | Identity::Discord(_) | Identity::Github(_) => None, } } diff --git a/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts index f2a2769888..a51d5e208e 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts @@ -56,12 +56,6 @@ export const defaultAssertions = [ A4: '10', }, }, - { - description: "The range of the user's Twitter follower count", - assertion: { - A6: 'A6', - }, - }, { description: 'The length of time a user continues to hold DOT token', assertion: { diff --git a/tee-worker/ts-tests/integration-tests/di_vc.test.ts b/tee-worker/ts-tests/integration-tests/di_vc.test.ts index 0e17e4f750..4b7ea6f093 100644 --- a/tee-worker/ts-tests/integration-tests/di_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_vc.test.ts @@ -1,25 +1,42 @@ import { randomBytes, KeyObject } from 'crypto'; import { step } from 'mocha-steps'; import { assert } from 'chai'; +import { u8aToHex, bufferToU8a } from '@polkadot/util'; import { buildIdentityFromKeypair, initIntegrationTestContext, PolkadotSigner } from './common/utils'; import { assertIsInSidechainBlock, assertVc } from './common/utils/assertion'; import { getSidechainNonce, + createSignedTrustedCallLinkIdentity, getTeeShieldingKey, sendRequestFromTrustedCall, createSignedTrustedCallRequestVc, } from './common/di-utils'; // @fixme move to a better place +import { buildIdentityHelper, buildValidations } from './common/utils'; import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; import { LitentryPrimitivesIdentity } from 'sidechain-api'; import { subscribeToEventsWithExtHash } from './common/transactions'; import { defaultAssertions, unconfiguredAssertions } from './common/utils/vc-helper'; +import { LitentryValidationData, Web3Network } from 'parachain-api'; +import { Vec } from '@polkadot/types'; describe('Test Vc (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; let aliceSubstrateIdentity: LitentryPrimitivesIdentity = undefined as any; + // Alice links: + // - a `mock_user` twitter + // - alice's evm identity + // - alice's bitcoin identity] + // + // We need this linking to not have empty eligible identities for any vc request + const linkIdentityRequestParams: { + nonce: number; + identity: LitentryPrimitivesIdentity; + validation: LitentryValidationData; + networks: Vec; + }[] = []; this.timeout(6000000); before(async () => { @@ -34,6 +51,96 @@ describe('Test Vc (direct invocation)', function () { ); }); + step('linking identities (alice)', async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + + const twitterNonce = getNextNonce(); + const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); + const [twitterValidation] = await buildValidations( + context, + [aliceSubstrateIdentity], + [twitterIdentity], + twitterNonce, + 'twitter' + ); + const twitterNetworks = context.api.createType('Vec', []) as unknown as Vec; // @fixme #1878 + linkIdentityRequestParams.push({ + nonce: twitterNonce, + identity: twitterIdentity, + validation: twitterValidation, + networks: twitterNetworks, + }); + + const evmNonce = getNextNonce(); + const evmIdentity = await buildIdentityHelper(context.ethersWallet.alice.address, 'Evm', context); + const [evmValidation] = await buildValidations( + context, + [aliceSubstrateIdentity], + [evmIdentity], + evmNonce, + 'ethereum', + undefined, + [context.ethersWallet.alice] + ); + const evmNetworks = context.api.createType('Vec', [ + 'Ethereum', + 'Bsc', + ]) as unknown as Vec; // @fixme #1878 + linkIdentityRequestParams.push({ + nonce: evmNonce, + identity: evmIdentity, + validation: evmValidation, + networks: evmNetworks, + }); + + const bitcoinNonce = getNextNonce(); + const bitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())), + 'Bitcoin', + context + ); + console.log('bitcoin id: ', bitcoinIdentity.toHuman()); + const [bitcoinValidation] = await buildValidations( + context, + [aliceSubstrateIdentity], + [bitcoinIdentity], + bitcoinNonce, + 'bitcoin', + undefined, + undefined, + context.bitcoinWallet.alice + ); + const bitcoinNetworks = context.api.createType('Vec', [ + 'BitcoinP2tr', + ]) as unknown as Vec; // @fixme #1878 + linkIdentityRequestParams.push({ + nonce: bitcoinNonce, + identity: bitcoinIdentity, + validation: bitcoinValidation, + networks: bitcoinNetworks, + }); + + for (const { nonce, identity, validation, networks } of linkIdentityRequestParams) { + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const linkIdentityCall = await createSignedTrustedCallLinkIdentity( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new PolkadotSigner(context.substrateWallet.alice), + aliceSubstrateIdentity, + identity.toHex(), + validation.toHex(), + networks.toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall); + await assertIsInSidechainBlock('linkIdentityCall', res); + } + }); + defaultAssertions.forEach(({ description, assertion }) => { step(`request vc ${Object.keys(assertion)[0]} (alice)`, async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); diff --git a/tee-worker/ts-tests/integration-tests/ii_vc.test.ts b/tee-worker/ts-tests/integration-tests/ii_vc.test.ts index 28263e688b..d4b78418bb 100644 --- a/tee-worker/ts-tests/integration-tests/ii_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_vc.test.ts @@ -11,17 +11,6 @@ const allAssertions = [ { A1: 'A1', }, - { - A2: 'A2', - }, - - { - A3: ['A3', 'A3', 'A3'], - }, - - { - A4: '10', - }, ]; // It doesn't make much difference test A1 only vs test A1 - A11, one VC type is enough. From 24018516acc82db244df26e93c5e7aeba8b67a76 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:24:42 +0100 Subject: [PATCH 39/43] Replace `T::AccountId` with `Identity` in callback extrinsics (#2373) * relocate identity rs * remove sgx feature * fix vcmp * fix compile errors * fix compile error * fix ts-tests * fix benchmark tests * clippy * ii test * rename identity * fix compile tests --- Cargo.lock | 12 ++ .../identity-management/src/benchmarking.rs | 32 ++--- pallets/identity-management/src/lib.rs | 62 ++++++--- pallets/identity-management/src/tests.rs | 2 +- pallets/vc-management/Cargo.toml | 4 + pallets/vc-management/src/benchmarking.rs | 32 +++-- pallets/vc-management/src/lib.rs | 44 +++--- pallets/vc-management/src/tests.rs | 31 +++-- pallets/vc-management/src/vc_context.rs | 13 +- primitives/core/Cargo.toml | 8 ++ .../core}/src/identity.rs | 59 ++++---- primitives/core/src/lib.rs | 4 + tee-worker/Cargo.lock | 4 + tee-worker/app-libs/stf/src/trusted_call.rs | 63 +++------ .../app-libs/stf/src/trusted_call_litentry.rs | 11 +- tee-worker/core-primitives/utils/src/hex.rs | 2 +- tee-worker/enclave-runtime/Cargo.lock | 131 ++++++++++++++++-- .../litentry/core/credentials/src/lib.rs | 2 +- .../lc-vc-task-receiver/src/lib.rs | 11 +- tee-worker/litentry/primitives/src/lib.rs | 4 +- .../integration-tests/common/di-utils.ts | 24 ++-- .../common/utils/assertion.ts | 107 ++++---------- .../integration-tests/common/utils/crypto.ts | 19 ++- .../common/utils/identity-helper.ts | 55 +++----- .../integration-tests/common/utils/storage.ts | 5 +- .../common/utils/vc-helper.ts | 2 +- .../di_bitcoin_identity.test.ts | 24 ++-- .../integration-tests/di_evm_identity.test.ts | 22 +-- .../di_substrate_identity.test.ts | 23 +-- .../ts-tests/integration-tests/di_vc.test.ts | 6 +- .../integration-tests/ii_batch.test.ts | 10 +- .../integration-tests/ii_identity.test.ts | 17 +-- .../ts-tests/stress/src/litentry-api.ts | 64 ++++----- tee-worker/ts-tests/stress/src/steps.ts | 16 +-- .../ts-tests/stress/src/user-session.ts | 6 +- 35 files changed, 497 insertions(+), 434 deletions(-) rename {tee-worker/litentry/primitives => primitives/core}/src/identity.rs (91%) diff --git a/Cargo.lock b/Cargo.lock index 2f4b4db678..cd88f7ed4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1186,11 +1186,15 @@ name = "core-primitives" version = "0.9.12" dependencies = [ "frame-support", + "itp-utils", "litentry-macros", + "pallet-evm", "parity-scale-codec", "ring", "scale-info", + "serde", "sp-core", + "sp-io", "sp-runtime", "sp-std", "strum 0.25.0", @@ -4385,6 +4389,14 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "itp-utils" +version = "0.9.0" +dependencies = [ + "hex", + "parity-scale-codec", +] + [[package]] name = "jobserver" version = "0.1.26" diff --git a/pallets/identity-management/src/benchmarking.rs b/pallets/identity-management/src/benchmarking.rs index 5f62296215..0e9bbea396 100644 --- a/pallets/identity-management/src/benchmarking.rs +++ b/pallets/identity-management/src/benchmarking.rs @@ -20,7 +20,7 @@ use super::*; use crate::Pallet as IdentityManagement; #[allow(unused)] -use core_primitives::{ErrorDetail, IMPError}; +use core_primitives::{AccountId, ErrorDetail, IMPError, Identity}; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, BenchmarkError}; use frame_support::traits::EnsureOrigin; use frame_system::RawOrigin; @@ -99,10 +99,10 @@ benchmarks! { let id_graph_hash = H256::default(); let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); - }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) + let prime_identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); + }: _(call_origin, prime_identity.clone(), id_graph_hash, req_ext_hash) verify { - assert_last_event::(Event::IdentityLinked { account, id_graph_hash, req_ext_hash }.into()); + assert_last_event::(Event::IdentityLinked { prime_identity, id_graph_hash, req_ext_hash }.into()); } // Benchmark `identity_deactivated`. There are no worst conditions. The benchmark showed that @@ -111,10 +111,10 @@ benchmarks! { let id_graph_hash = H256::default(); let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); - }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) + let prime_identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); + }: _(call_origin, prime_identity.clone(), id_graph_hash, req_ext_hash) verify { - assert_last_event::(Event::IdentityDeactivated { account, id_graph_hash, req_ext_hash }.into()); + assert_last_event::(Event::IdentityDeactivated { prime_identity, id_graph_hash, req_ext_hash }.into()); } // Benchmark `identity_activated`. There are no worst conditions. The benchmark showed that @@ -123,10 +123,10 @@ benchmarks! { let id_graph_hash = H256::default(); let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); - }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) + let prime_identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); + }: _(call_origin, prime_identity.clone(), id_graph_hash, req_ext_hash) verify { - assert_last_event::(Event::IdentityActivated { account, id_graph_hash, req_ext_hash }.into()); + assert_last_event::(Event::IdentityActivated { prime_identity, id_graph_hash, req_ext_hash }.into()); } // Benchmark `identity_networks_set`. There are no worst conditions. The benchmark showed that @@ -135,23 +135,23 @@ benchmarks! { let id_graph_hash = H256::default(); let req_ext_hash = H256::default(); let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); - }: _(call_origin, account.clone(), id_graph_hash, req_ext_hash) + let prime_identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); + }: _(call_origin, prime_identity.clone(), id_graph_hash, req_ext_hash) verify { - assert_last_event::(Event::IdentityNetworksSet { account, id_graph_hash, req_ext_hash }.into()); + assert_last_event::(Event::IdentityNetworksSet { prime_identity, id_graph_hash, req_ext_hash }.into()); } // Benchmark `some_error`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. some_error { let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let prime_identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); let detail = ErrorDetail::WrongWeb2Handle; let error = IMPError::LinkIdentityFailed(detail.clone()); let req_ext_hash = H256::default(); - }: _(call_origin, Some(account.clone()), error, req_ext_hash) + }: _(call_origin, Some(prime_identity.clone()), error, req_ext_hash) verify { - assert_last_event::(Event::LinkIdentityFailed { account: Some(account), detail, req_ext_hash }.into()) + assert_last_event::(Event::LinkIdentityFailed { prime_identity: Some(prime_identity), detail, req_ext_hash }.into()) } } diff --git a/pallets/identity-management/src/lib.rs b/pallets/identity-management/src/lib.rs index 634941d924..b5051b5641 100644 --- a/pallets/identity-management/src/lib.rs +++ b/pallets/identity-management/src/lib.rs @@ -50,7 +50,7 @@ pub use teerex_primitives::ShardIdentifier; #[frame_support::pallet] pub mod pallet { use super::{ShardIdentifier, Vec, WeightInfo, H256}; - use core_primitives::{ErrorDetail, IMPError}; + use core_primitives::{ErrorDetail, IMPError, Identity}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -93,22 +93,22 @@ pub mod pallet { // TODO: what if the event is triggered by an extrinsic that is included in a batch call? // Can we retrieve that extrinsic hash in F/E? IdentityLinked { - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, }, IdentityDeactivated { - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, }, IdentityActivated { - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, }, IdentityNetworksSet { - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, }, @@ -116,26 +116,26 @@ pub mod pallet { // copied from core_primitives::IMPError, we use events instead of pallet::errors, // see https://github.com/litentry/litentry-parachain/issues/1275 // - // why is the `account` in the error event an Option? + // why is the `prime_identity` in the error event an Option? // because in some erroneous cases we can't get the extrinsic sender (e.g. decode error) LinkIdentityFailed { - account: Option, + prime_identity: Option, detail: ErrorDetail, req_ext_hash: H256, }, DeactivateIdentityFailed { - account: Option, + prime_identity: Option, detail: ErrorDetail, req_ext_hash: H256, }, ActivateIdentityFailed { - account: Option, + prime_identity: Option, detail: ErrorDetail, req_ext_hash: H256, }, ImportScheduledEnclaveFailed, UnclassifiedError { - account: Option, + prime_identity: Option, detail: ErrorDetail, req_ext_hash: H256, }, @@ -247,12 +247,16 @@ pub mod pallet { #[pallet::weight(::WeightInfo::identity_linked())] pub fn identity_linked( origin: OriginFor, - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - Self::deposit_event(Event::IdentityLinked { account, id_graph_hash, req_ext_hash }); + Self::deposit_event(Event::IdentityLinked { + prime_identity, + id_graph_hash, + req_ext_hash, + }); Ok(Pays::No.into()) } @@ -260,13 +264,13 @@ pub mod pallet { #[pallet::weight(::WeightInfo::identity_deactivated())] pub fn identity_deactivated( origin: OriginFor, - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; Self::deposit_event(Event::IdentityDeactivated { - account, + prime_identity, id_graph_hash, req_ext_hash, }); @@ -277,12 +281,16 @@ pub mod pallet { #[pallet::weight(::WeightInfo::identity_activated())] pub fn identity_activated( origin: OriginFor, - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - Self::deposit_event(Event::IdentityActivated { account, id_graph_hash, req_ext_hash }); + Self::deposit_event(Event::IdentityActivated { + prime_identity, + id_graph_hash, + req_ext_hash, + }); Ok(Pays::No.into()) } @@ -290,13 +298,13 @@ pub mod pallet { #[pallet::weight(::WeightInfo::identity_networks_set())] pub fn identity_networks_set( origin: OriginFor, - account: T::AccountId, + prime_identity: Identity, id_graph_hash: H256, req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; Self::deposit_event(Event::IdentityNetworksSet { - account, + prime_identity, id_graph_hash, req_ext_hash, }); @@ -307,30 +315,38 @@ pub mod pallet { #[pallet::weight(::WeightInfo::some_error())] pub fn some_error( origin: OriginFor, - account: Option, + prime_identity: Option, error: IMPError, req_ext_hash: H256, ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; match error { IMPError::LinkIdentityFailed(detail) => - Self::deposit_event(Event::LinkIdentityFailed { account, detail, req_ext_hash }), + Self::deposit_event(Event::LinkIdentityFailed { + prime_identity, + detail, + req_ext_hash, + }), IMPError::DeactivateIdentityFailed(detail) => Self::deposit_event(Event::DeactivateIdentityFailed { - account, + prime_identity, detail, req_ext_hash, }), IMPError::ActivateIdentityFailed(detail) => Self::deposit_event(Event::ActivateIdentityFailed { - account, + prime_identity, detail, req_ext_hash, }), IMPError::ImportScheduledEnclaveFailed => Self::deposit_event(Event::ImportScheduledEnclaveFailed), IMPError::UnclassifiedError(detail) => - Self::deposit_event(Event::UnclassifiedError { account, detail, req_ext_hash }), + Self::deposit_event(Event::UnclassifiedError { + prime_identity, + detail, + req_ext_hash, + }), } Ok(Pays::No.into()) } diff --git a/pallets/identity-management/src/tests.rs b/pallets/identity-management/src/tests.rs index 47bef80961..147d2c1240 100644 --- a/pallets/identity-management/src/tests.rs +++ b/pallets/identity-management/src/tests.rs @@ -143,7 +143,7 @@ fn tee_callback_with_registered_enclave_works() { )); System::assert_last_event(RuntimeEvent::IdentityManagement( crate::Event::LinkIdentityFailed { - account: None, + prime_identity: None, detail: ErrorDetail::WrongWeb2Handle, req_ext_hash: H256::default(), }, diff --git a/pallets/vc-management/Cargo.toml b/pallets/vc-management/Cargo.toml index fa05d00f38..1098aa0dc6 100644 --- a/pallets/vc-management/Cargo.toml +++ b/pallets/vc-management/Cargo.toml @@ -43,6 +43,8 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-group/runtime-benchmarks", "test-utils", ] std = [ @@ -56,5 +58,7 @@ std = [ "frame-benchmarking?/std", "core-primitives/std", "teerex-primitives/std", + "pallet-balances/std", + "pallet-group/std", ] try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/vc-management/src/benchmarking.rs b/pallets/vc-management/src/benchmarking.rs index 3b50409139..a6bde4b77b 100644 --- a/pallets/vc-management/src/benchmarking.rs +++ b/pallets/vc-management/src/benchmarking.rs @@ -19,7 +19,7 @@ use super::*; use crate::Pallet as VCManagement; -use core_primitives::{ErrorDetail, VCMPError}; +use core_primitives::{AccountId, Assertion, ErrorDetail, Identity, VCMPError}; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, BenchmarkError}; use frame_support::traits::EnsureOrigin; use frame_system::RawOrigin; @@ -82,10 +82,11 @@ benchmarks! { // execution time is constant irrespective of encrypted_data size. disable_vc { let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); let assertion = Assertion::A1; let req_ext_hash = H256::default(); let tee_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - VCManagement::::vc_issued(tee_origin, account.clone(), assertion, VC_INDEX, VC_HASH, req_ext_hash)?; + VCManagement::::vc_issued(tee_origin, identity, assertion, VC_INDEX, VC_HASH, req_ext_hash)?; }: _(RawOrigin::Signed(account.clone()), VC_INDEX) verify{ assert_last_event::(Event::VCDisabled{ account, index: VC_HASH }.into()); @@ -95,10 +96,11 @@ benchmarks! { // execution time is constant irrespective of encrypted_data size. revoke_vc { let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); let assertion = Assertion::A1; let req_ext_hash = H256::default(); let tee_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - VCManagement::::vc_issued(tee_origin, account.clone(), assertion, VC_INDEX, VC_HASH, req_ext_hash)?; + VCManagement::::vc_issued(tee_origin, identity, assertion, VC_INDEX, VC_HASH, req_ext_hash)?; }: _(RawOrigin::Signed(account.clone()), VC_INDEX) verify{ assert_last_event::(Event::VCRevoked{ account, index: VC_HASH }.into()); @@ -108,26 +110,26 @@ benchmarks! { // execution time is constant irrespective of encrypted_data size. vc_issued { let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); let assertion = Assertion::A1; let req_ext_hash = H256::default(); - }: _(call_origin, account.clone(), assertion.clone(), VC_INDEX, VC_HASH, req_ext_hash) + }: _(call_origin, identity.clone(), assertion.clone(), VC_INDEX, VC_HASH, req_ext_hash) verify{ - assert_last_event::(Event::VCIssued{ account, assertion, index: VC_INDEX, req_ext_hash}.into()); + assert_last_event::(Event::VCIssued{ identity, assertion, index: VC_INDEX, req_ext_hash}.into()); } // Benchmark `some_error`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. some_error { let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, USER_SEED).into(); let detail = ErrorDetail::WrongWeb2Handle; let assertion = Assertion::A1; let error = VCMPError::RequestVCFailed(assertion.clone(), detail.clone()); let req_ext_hash = H256::default(); - }: _(call_origin, Some(account.clone()), error, req_ext_hash) + }: _(call_origin, Some(identity.clone()), error, req_ext_hash) verify { - assert_last_event::(Event::RequestVCFailed { account: Some(account), assertion, detail, req_ext_hash }.into()) + assert_last_event::(Event::RequestVCFailed { identity: Some(identity), assertion, detail, req_ext_hash }.into()) } // Benchmark `set_admin`. There are no worst conditions. The benchmark showed that @@ -201,20 +203,22 @@ benchmarks! { // execution time is constant irrespective of encrypted_data size. add_vc_registry_item { let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let identity: Identity = frame_benchmarking::account::("TEST_B", 0u32, USER_SEED).into(); VCManagement::::set_admin(RawOrigin::Root.into(), account.clone())?; let assertion = Assertion::A1; - }: _(RawOrigin::Signed(account.clone()), VC_INDEX, account.clone(), assertion.clone(), VC_HASH) + }: _(RawOrigin::Signed(account.clone()), VC_INDEX, identity.clone(), assertion.clone(), VC_HASH) verify { - assert_last_event::(Event::VCRegistryItemAdded { account, assertion, index: VC_INDEX }.into()) + assert_last_event::(Event::VCRegistryItemAdded { identity, assertion, index: VC_INDEX }.into()) } // Benchmark `remove_vc_registry_item`. There are no worst conditions. The benchmark showed that // execution time is constant irrespective of encrypted_data size. remove_vc_registry_item { let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED); + let identity: Identity = frame_benchmarking::account::("TEST_B", 0u32, USER_SEED).into(); VCManagement::::set_admin(RawOrigin::Root.into(), account.clone())?; let assertion = Assertion::A1; - VCManagement::::add_vc_registry_item(RawOrigin::Signed(account.clone()).into(), VC_INDEX, account.clone(), assertion, VC_HASH)?; + VCManagement::::add_vc_registry_item(RawOrigin::Signed(account.clone()).into(), VC_INDEX, identity, assertion, VC_HASH)?; }: _(RawOrigin::Signed(account), VC_INDEX) verify { assert_last_event::(Event::VCRegistryItemRemoved { index: VC_INDEX }.into()) @@ -228,10 +232,10 @@ benchmarks! { let assertion = Assertion::A1; for i in 0..x { let seed = USER_SEED - i; - let candidate:T::AccountId = frame_benchmarking::account("TEST_A", 0u32, seed); + let identity: Identity = frame_benchmarking::account::("TEST_A", 0u32, seed).into(); let seed_hash_u8_32 = convert_u32_array_to_u8_array([seed; 8]); let hash: H256 = seed_hash_u8_32.into(); - VCManagement::::add_vc_registry_item(RawOrigin::Signed(account.clone()).into(), hash, candidate.clone(), assertion.clone(), VC_HASH)?; + VCManagement::::add_vc_registry_item(RawOrigin::Signed(account.clone()).into(), hash, identity, assertion.clone(), VC_HASH)?; } }: _(RawOrigin::Signed(account)) verify { diff --git a/pallets/vc-management/src/lib.rs b/pallets/vc-management/src/lib.rs index a37674cf71..ec62b54282 100644 --- a/pallets/vc-management/src/lib.rs +++ b/pallets/vc-management/src/lib.rs @@ -34,7 +34,6 @@ pub mod weights; pub use crate::weights::WeightInfo; -use core_primitives::{Assertion, SchemaIndex, SCHEMA_CONTENT_LEN, SCHEMA_ID_LEN}; pub use pallet::*; use sp_core::H256; use sp_std::vec::Vec; @@ -51,7 +50,9 @@ pub type VCIndex = H256; #[frame_support::pallet] pub mod pallet { use super::*; - use core_primitives::{ErrorDetail, VCMPError}; + use core_primitives::{ + Assertion, ErrorDetail, Identity, SchemaIndex, VCMPError, SCHEMA_CONTENT_LEN, SCHEMA_ID_LEN, + }; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -73,9 +74,10 @@ pub mod pallet { } // a map VCIndex -> VC context + // TODO: to be removed in P-350 #[pallet::storage] #[pallet::getter(fn vc_registry)] - pub type VCRegistry = StorageMap<_, Blake2_128Concat, VCIndex, VCContext>; + pub type VCRegistry = StorageMap<_, Blake2_128Concat, VCIndex, VCContext>; // the admin account #[pallet::storage] @@ -128,7 +130,7 @@ pub mod pallet { // event that should be triggered by TEECallOrigin // a VC is just issued VCIssued { - account: T::AccountId, + identity: Identity, assertion: Assertion, index: VCIndex, req_ext_hash: H256, @@ -166,18 +168,18 @@ pub mod pallet { // copied from core_primitives::VCMPError, we use events instead of pallet::errors, // see https://github.com/litentry/litentry-parachain/issues/1275 RequestVCFailed { - account: Option, + identity: Option, assertion: Assertion, detail: ErrorDetail, req_ext_hash: H256, }, UnclassifiedError { - account: Option, + identity: Option, detail: ErrorDetail, req_ext_hash: H256, }, VCRegistryItemAdded { - account: T::AccountId, + identity: Identity, assertion: Assertion, index: VCIndex, }, @@ -280,7 +282,10 @@ pub mod pallet { let who = T::ExtrinsicWhitelistOrigin::ensure_origin(origin)?; VCRegistry::::try_mutate(index, |context| { let mut c = context.take().ok_or(Error::::VCNotExist)?; - ensure!(who == c.subject, Error::::VCSubjectMismatch); + ensure!( + Some(who.clone()).encode() == c.subject.to_account_id().encode(), + Error::::VCSubjectMismatch + ); ensure!(c.status == Status::Active, Error::::VCAlreadyDisabled); c.status = Status::Disabled; *context = Some(c); @@ -294,7 +299,10 @@ pub mod pallet { pub fn revoke_vc(origin: OriginFor, index: VCIndex) -> DispatchResultWithPostInfo { let who = T::ExtrinsicWhitelistOrigin::ensure_origin(origin)?; let context = VCRegistry::::get(index).ok_or(Error::::VCNotExist)?; - ensure!(who == context.subject, Error::::VCSubjectMismatch); + ensure!( + Some(who.clone()).encode() == context.subject.to_account_id().encode(), + Error::::VCSubjectMismatch + ); VCRegistry::::remove(index); Self::deposit_event(Event::VCRevoked { account: who, index }); Ok(().into()) @@ -396,7 +404,7 @@ pub mod pallet { pub fn add_vc_registry_item( origin: OriginFor, index: VCIndex, - subject: T::AccountId, + identity: Identity, assertion: Assertion, hash: H256, ) -> DispatchResultWithPostInfo { @@ -405,9 +413,9 @@ pub mod pallet { ensure!(!VCRegistry::::contains_key(index), Error::::VCAlreadyExists); VCRegistry::::insert( index, - VCContext::::new(subject.clone(), assertion.clone(), hash), + VCContext::new(identity.clone(), assertion.clone(), hash), ); - Self::deposit_event(Event::VCRegistryItemAdded { account: subject, assertion, index }); + Self::deposit_event(Event::VCRegistryItemAdded { identity, assertion, index }); Ok(().into()) } @@ -443,7 +451,7 @@ pub mod pallet { #[pallet::weight(::WeightInfo::vc_issued())] pub fn vc_issued( origin: OriginFor, - account: T::AccountId, + identity: Identity, assertion: Assertion, index: H256, hash: H256, @@ -453,9 +461,9 @@ pub mod pallet { ensure!(!VCRegistry::::contains_key(index), Error::::VCAlreadyExists); VCRegistry::::insert( index, - VCContext::::new(account.clone(), assertion.clone(), hash), + VCContext::new(identity.clone(), assertion.clone(), hash), ); - Self::deposit_event(Event::VCIssued { account, assertion, index, req_ext_hash }); + Self::deposit_event(Event::VCIssued { identity, assertion, index, req_ext_hash }); Ok(Pays::No.into()) } @@ -463,7 +471,7 @@ pub mod pallet { #[pallet::weight(::WeightInfo::some_error())] pub fn some_error( origin: OriginFor, - account: Option, + identity: Option, error: VCMPError, req_ext_hash: H256, ) -> DispatchResultWithPostInfo { @@ -471,13 +479,13 @@ pub mod pallet { match error { VCMPError::RequestVCFailed(assertion, detail) => Self::deposit_event(Event::RequestVCFailed { - account, + identity, assertion, detail, req_ext_hash, }), VCMPError::UnclassifiedError(detail) => - Self::deposit_event(Event::UnclassifiedError { account, detail, req_ext_hash }), + Self::deposit_event(Event::UnclassifiedError { identity, detail, req_ext_hash }), } Ok(Pays::No.into()) } diff --git a/pallets/vc-management/src/tests.rs b/pallets/vc-management/src/tests.rs index d0aa819b68..32507d15a7 100644 --- a/pallets/vc-management/src/tests.rs +++ b/pallets/vc-management/src/tests.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::{mock::*, Assertion, Error, ShardIdentifier, Status}; +use crate::{mock::*, Error, ShardIdentifier, Status}; +use core_primitives::{Assertion, Identity}; use frame_support::{assert_noop, assert_ok}; use sp_core::H256; @@ -85,7 +86,7 @@ fn request_vc_13_with_unauthorized_delegatee_fails() { fn vc_issued_works() { new_test_ext().execute_with(|| { let teerex_signer: SystemAccountId = test_utils::get_signer(TEST8_SIGNER_PUB); - let alice: SystemAccountId = test_utils::get_signer(ALICE_PUBKEY); + let alice: Identity = test_utils::get_signer(ALICE_PUBKEY); assert_ok!(VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer), alice.clone(), @@ -110,7 +111,7 @@ fn vc_issued_with_unpriviledged_origin_fails() { assert_noop!( VCManagement::vc_issued( RuntimeOrigin::signed(bob), - alice, + alice.into(), Assertion::A1, H256::default(), H256::default(), @@ -128,7 +129,7 @@ fn vc_issued_with_duplicated_index_fails() { let alice: SystemAccountId = test_utils::get_signer(ALICE_PUBKEY); assert_ok!(VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer.clone()), - alice.clone(), + alice.clone().into(), Assertion::A1, VC_INDEX, VC_HASH, @@ -137,7 +138,7 @@ fn vc_issued_with_duplicated_index_fails() { assert_noop!( VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer), - alice, + alice.into(), Assertion::A1, VC_INDEX, VC_HASH, @@ -155,7 +156,7 @@ fn disable_vc_works() { let bob: SystemAccountId = test_utils::get_signer(BOB_PUBKEY); assert_ok!(VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer), - bob.clone(), + bob.clone().into(), Assertion::A1, VC_INDEX, VC_HASH, @@ -189,7 +190,7 @@ fn disable_vc_with_other_subject_fails() { let bob: SystemAccountId = test_utils::get_signer(BOB_PUBKEY); assert_ok!(VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer), - bob, + bob.into(), Assertion::A1, VC_INDEX, VC_HASH, @@ -211,7 +212,7 @@ fn revoke_vc_works() { let bob: SystemAccountId = test_utils::get_signer(BOB_PUBKEY); assert_ok!(VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer), - bob.clone(), + bob.clone().into(), Assertion::A1, VC_INDEX, VC_HASH, @@ -243,7 +244,7 @@ fn revoke_vc_with_other_subject_fails() { let bob: SystemAccountId = test_utils::get_signer(BOB_PUBKEY); assert_ok!(VCManagement::vc_issued( RuntimeOrigin::signed(teerex_signer), - bob, + bob.into(), Assertion::A1, VC_INDEX, VC_HASH, @@ -508,7 +509,7 @@ fn manual_add_remove_vc_registry_item_works() { VCManagement::add_vc_registry_item( RuntimeOrigin::signed(bob.clone()), VC_INDEX, - bob.clone(), + bob.clone().into(), Assertion::A1, VC_HASH ), @@ -518,14 +519,14 @@ fn manual_add_remove_vc_registry_item_works() { assert_ok!(VCManagement::add_vc_registry_item( RuntimeOrigin::signed(alice.clone()), VC_INDEX, - alice.clone(), + alice.clone().into(), Assertion::A1, VC_HASH )); // Check result assert!(VCManagement::vc_registry(VC_INDEX).is_some()); System::assert_last_event(RuntimeEvent::VCManagement(crate::Event::VCRegistryItemAdded { - account: alice.clone(), + identity: alice.clone().into(), assertion: Assertion::A1, index: VC_INDEX, })); @@ -554,7 +555,7 @@ fn manual_add_clear_vc_registry_item_works() { VCManagement::add_vc_registry_item( RuntimeOrigin::signed(bob.clone()), VC_INDEX, - bob.clone(), + bob.clone().into(), Assertion::A1, VC_HASH ), @@ -564,14 +565,14 @@ fn manual_add_clear_vc_registry_item_works() { assert_ok!(VCManagement::add_vc_registry_item( RuntimeOrigin::signed(alice.clone()), VC_INDEX, - alice.clone(), + alice.clone().into(), Assertion::A1, VC_HASH )); // Check result assert!(VCManagement::vc_registry(VC_INDEX).is_some()); System::assert_last_event(RuntimeEvent::VCManagement(crate::Event::VCRegistryItemAdded { - account: alice.clone(), + identity: alice.clone().into(), assertion: Assertion::A1, index: VC_INDEX, })); diff --git a/pallets/vc-management/src/vc_context.rs b/pallets/vc-management/src/vc_context.rs index 43020941b5..24815cbd51 100644 --- a/pallets/vc-management/src/vc_context.rs +++ b/pallets/vc-management/src/vc_context.rs @@ -15,11 +15,10 @@ // along with Litentry. If not, see . use codec::{Decode, Encode, MaxEncodedLen}; +use core_primitives::{Assertion, Identity}; use scale_info::TypeInfo; use sp_core::H256; -use crate::{Assertion, Config}; - #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub enum Status { #[codec(index = 0)] @@ -30,15 +29,13 @@ pub enum Status { } #[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(T))] -#[codec(mel_bound())] -pub struct VCContext { +pub struct VCContext { // To be discussed: shall we make it public? // pros: easier for the user to disable/revoke VCs, we'll need the AccountId to verify // the owner of VC. An alternative is to store such information within TEE. // cons: this information is then public, everyone knows e.g. ALICE owns VC ID 1234 + 4321 // It's not bad though as it helps to verify the ownership of VC - pub subject: T::AccountId, + pub subject: Identity, // requested assertion type pub assertion: Assertion, // hash of the VC, computed via blake2_256 @@ -47,8 +44,8 @@ pub struct VCContext { pub status: Status, } -impl VCContext { - pub fn new(subject: T::AccountId, assertion: Assertion, hash: H256) -> Self { +impl VCContext { + pub fn new(subject: Identity, assertion: Assertion, hash: H256) -> Self { Self { subject, assertion, hash, status: Status::Active } } } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index fd71773e7f..b42ebebf71 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -5,22 +5,27 @@ name = 'core-primitives' version = '0.9.12' [dependencies] +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } strum = { version = "0.25.0", default-features = false } strum_macros = { version = "0.25.3", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +pallet-evm = { git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.42", default-features = false } ring = { version = "0.16.20", default-features = false, features = ["alloc"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +itp-utils = { path = "../../tee-worker/core-primitives/utils", default-features = false } litentry-macros = { path = "macros" } [features] default = ["std"] std = [ + "serde/std", "strum/std", "codec/std", "scale-info/std", @@ -28,5 +33,8 @@ std = [ "sp-core/std", "sp-runtime/std", "sp-std/std", + "sp-io/std", "ring/std", + "itp-utils/std", + "pallet-evm/std", ] diff --git a/tee-worker/litentry/primitives/src/identity.rs b/primitives/core/src/identity.rs similarity index 91% rename from tee-worker/litentry/primitives/src/identity.rs rename to primitives/core/src/identity.rs index 8aa63d6595..35902f4660 100644 --- a/tee-worker/litentry/primitives/src/identity.rs +++ b/primitives/core/src/identity.rs @@ -14,23 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -#[cfg(all(not(feature = "std"), feature = "sgx"))] -extern crate sgx_tstd as std; +pub extern crate alloc; -use core::fmt::{Debug, Formatter}; -#[cfg(all(not(feature = "sgx"), feature = "std"))] -use serde::{Deserialize, Serialize}; - -use crate::{all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks}; +use crate::{ + all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, AccountId, + Web3Network, +}; +use alloc::{format, str, string::String}; use codec::{Decode, Encode, Error, Input, MaxEncodedLen}; +use core::fmt::{Debug, Formatter}; use itp_utils::{ hex::{decode_hex, hex_encode}, if_production_or, }; use pallet_evm::{AddressMapping, HashedAddressMapping as GenericHashedAddressMapping}; -use parentchain_primitives::{AccountId, Web3Network}; use scale_info::{meta_type, Type, TypeDefSequence, TypeInfo}; -use sp_core::{crypto::AccountId32, ecdsa, ed25519, sr25519, ByteArray, H160}; +use sp_core::{ + crypto::{AccountId32, ByteArray}, + ecdsa, ed25519, sr25519, H160, +}; use sp_io::hashing::blake2_256; use sp_runtime::{ traits::{BlakeTwo256, ConstU32}, @@ -60,9 +62,7 @@ impl Encode for IdentityString { } #[derive(Eq, PartialEq, Clone, MaxEncodedLen, Default)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct IdentityString { - #[cfg_attr(feature = "std", serde(flatten))] pub inner: IdentityInnerString, } @@ -339,9 +339,8 @@ impl Identity { } } - #[cfg(any(feature = "std", feature = "sgx"))] - pub fn from_did(s: &str) -> Result> { - let did_prefix = std::string::String::from("did:litentry:"); + pub fn from_did(s: &str) -> Result { + let did_prefix = String::from("did:litentry:"); if s.starts_with(&did_prefix) { let did_suffix = &s[did_prefix.len()..]; let v: Vec<&str> = did_suffix.split(':').collect(); @@ -374,41 +373,37 @@ impl Identity { } else if v[0] == "twitter" { return Ok(Identity::Twitter(IdentityString::new(v[1].as_bytes().to_vec()))) } else { - return Err("Unknown did type".into()) + return Err("Unknown did type") } } else { - return Err("Wrong did suffix".into()) + return Err("Wrong did suffix") } } - Err("Wrong did prefix".into()) + Err("Wrong did prefix") } - #[cfg(any(feature = "std", feature = "sgx"))] - pub fn to_did( - &self, - ) -> Result> { - Ok(std::format!( + pub fn to_did(&self) -> Result { + Ok(format!( "did:litentry:{}", match self { - Identity::Evm(address) => std::format!("evm:{}", &hex_encode(address.as_ref())), + Identity::Evm(address) => format!("evm:{}", &hex_encode(address.as_ref())), Identity::Substrate(address) => - std::format!("substrate:{}", &hex_encode(address.as_ref())), - Identity::Bitcoin(address) => - std::format!("bitcoin:{}", &hex_encode(address.as_ref())), - Identity::Twitter(handle) => std::format!( + format!("substrate:{}", &hex_encode(address.as_ref())), + Identity::Bitcoin(address) => format!("bitcoin:{}", &hex_encode(address.as_ref())), + Identity::Twitter(handle) => format!( "twitter:{}", - std::str::from_utf8(handle.inner_ref()) + str::from_utf8(handle.inner_ref()) .map_err(|_| "twitter handle conversion error")? ), - Identity::Discord(handle) => std::format!( + Identity::Discord(handle) => format!( "discord:{}", - std::str::from_utf8(handle.inner_ref()) + str::from_utf8(handle.inner_ref()) .map_err(|_| "discord handle conversion error")? ), - Identity::Github(handle) => std::format!( + Identity::Github(handle) => format!( "github:{}", - std::str::from_utf8(handle.inner_ref()) + str::from_utf8(handle.inner_ref()) .map_err(|_| "github handle conversion error")? ), } diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 49f992e4f6..8f41ee4af7 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -38,6 +38,9 @@ pub use error::*; mod vc; pub use vc::*; +pub mod identity; +pub use identity::*; + mod oneblock; pub use oneblock::*; @@ -55,6 +58,7 @@ pub use generic_discord_role::*; mod evm_amount_holding; pub use evm_amount_holding::*; + /// Common types of parachains. mod types { use sp_runtime::{ diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 35484c8fb9..4e92ea7348 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -1305,11 +1305,15 @@ name = "core-primitives" version = "0.9.12" dependencies = [ "frame-support", + "itp-utils", "litentry-macros 0.9.12", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "parity-scale-codec", "ring 0.16.20", "scale-info", + "serde 1.0.193", "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-std 5.0.0", "strum 0.25.0", diff --git a/tee-worker/app-libs/stf/src/trusted_call.rs b/tee-worker/app-libs/stf/src/trusted_call.rs index 30e8522608..307005313e 100644 --- a/tee-worker/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/app-libs/stf/src/trusted_call.rs @@ -38,9 +38,7 @@ use codec::{Compact, Decode, Encode}; use frame_support::{ensure, traits::UnfilteredDispatchable}; #[cfg(feature = "evm")] use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; -pub use ita_sgx_runtime::{ - Balance, ConvertAccountId, IDGraph, Index, Runtime, SgxParentchainTypeConverter, System, -}; +pub use ita_sgx_runtime::{Balance, IDGraph, Index, Runtime, System}; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; use itp_node_api_metadata::{ pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, @@ -60,9 +58,8 @@ pub use itp_types::{OpaqueCall, H256}; use itp_utils::stringify::account_id_to_string; pub use litentry_primitives::{ aes_encrypt_default, all_evm_web3networks, all_substrate_web3networks, AesOutput, Assertion, - ErrorDetail, IMPError, Identity, LitentryMultiSignature, ParentchainAccountId, - ParentchainBlockNumber, RequestAesKey, RequestAesKeyNonce, VCMPError, ValidationData, - Web3Network, + ErrorDetail, IMPError, Identity, LitentryMultiSignature, ParentchainBlockNumber, RequestAesKey, + RequestAesKeyNonce, VCMPError, ValidationData, Web3Network, }; use log::*; use sp_core::{ @@ -678,9 +675,6 @@ where req_ext_hash, ) => { debug!("link_identity, who: {}", account_id_to_string(&who)); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(Self::Error::InvalidAccount)?, - ); let verification_done = Self::link_identity_internal( shard, signer.to_account_id().ok_or(Self::Error::InvalidAccount)?, @@ -696,7 +690,7 @@ where push_call_imp_some_error( calls, node_metadata_repo.clone(), - Some(account), + Some(who.clone()), e.to_imp_error(), req_ext_hash, ); @@ -736,9 +730,6 @@ where }, TrustedCall::deactivate_identity(signer, who, identity, maybe_key, req_ext_hash) => { debug!("deactivate_identity, who: {}", account_id_to_string(&who)); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(Self::Error::InvalidAccount)?, - ); let call_index = node_metadata_repo .get_from_metadata(|m| m.identity_deactivated_call_indexes())??; @@ -752,7 +743,7 @@ where push_call_imp_some_error( calls, node_metadata_repo.clone(), - Some(account.clone()), + Some(who.clone()), e.to_imp_error(), req_ext_hash, ); @@ -764,7 +755,7 @@ where debug!("pushing identity_deactivated event ..."); calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + who.clone(), id_graph_hash, req_ext_hash, )))); @@ -787,9 +778,6 @@ where }, TrustedCall::activate_identity(signer, who, identity, maybe_key, req_ext_hash) => { debug!("activate_identity, who: {}", account_id_to_string(&who)); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(Self::Error::InvalidAccount)?, - ); let call_index = node_metadata_repo .get_from_metadata(|m| m.identity_activated_call_indexes())??; @@ -803,7 +791,7 @@ where push_call_imp_some_error( calls, node_metadata_repo.clone(), - Some(account.clone()), + Some(who.clone()), e.to_imp_error(), req_ext_hash, ); @@ -815,7 +803,7 @@ where debug!("pushing identity_activated event ..."); calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + who.clone(), id_graph_hash, req_ext_hash, )))); @@ -860,12 +848,9 @@ where assertion ); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(Self::Error::InvalidAccount)?, - ); Self::request_vc_internal( signer.to_account_id().ok_or(Self::Error::InvalidAccount)?, - who, + who.clone(), assertion, top_hash, req_ext_hash, @@ -877,7 +862,7 @@ where push_call_vcmp_some_error( calls, node_metadata_repo, - Some(account), + Some(who), e.to_vcmp_error(), req_ext_hash, ); @@ -900,9 +885,6 @@ where account_id_to_string(&who), assertion ); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(Self::Error::InvalidAccount)?, - ); Self::request_vc_callback_internal( signer.to_account_id().ok_or(Self::Error::InvalidAccount)?, @@ -913,7 +895,7 @@ where push_call_vcmp_some_error( calls, node_metadata_repo.clone(), - Some(account.clone()), + Some(who.clone()), e.to_vcmp_error(), req_ext_hash, ); @@ -926,7 +908,7 @@ where calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + who, assertion, vc_index, vc_hash, @@ -957,9 +939,6 @@ where ensure_self(&signer, &who), Self::Error::Dispatch("Unauthorized signer".to_string()) ); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(Self::Error::InvalidAccount)?, - ); let call_index = node_metadata_repo .get_from_metadata(|m| m.identity_networks_set_call_indexes())??; @@ -976,7 +955,7 @@ where debug!("pushing identity_networks_set event ..."); calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + who.clone(), id_graph_hash, req_ext_hash, )))); @@ -1002,25 +981,25 @@ where Ok(TrustedCallResult::Empty) }, - TrustedCall::handle_imp_error(_enclave_account, account, e, req_ext_hash) => { + TrustedCall::handle_imp_error(_enclave_account, identity, e, req_ext_hash) => { // checking of `_enclave_account` is not strictly needed, as this trusted call can // only be constructed internally push_call_imp_some_error( calls, node_metadata_repo, - account.and_then(|g| g.to_account_id()), + identity, e.clone(), req_ext_hash, ); Err(e.into()) }, - TrustedCall::handle_vcmp_error(_enclave_account, account, e, req_ext_hash) => { + TrustedCall::handle_vcmp_error(_enclave_account, identity, e, req_ext_hash) => { // checking of `_enclave_account` is not strictly needed, as this trusted call can // only be constructed internally push_call_vcmp_some_error( calls, node_metadata_repo, - account.and_then(|g| g.to_account_id()), + identity, e.clone(), req_ext_hash, ); @@ -1120,7 +1099,7 @@ where pub fn push_call_imp_some_error( calls: &mut Vec, node_metadata_repo: Arc, - account: Option, + identity: Option, e: IMPError, req_ext_hash: H256, ) where @@ -1132,7 +1111,7 @@ pub fn push_call_imp_some_error( match node_metadata_repo.get_from_metadata(|m| m.imp_some_error_call_indexes()) { Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + identity, e, req_ext_hash, )))), @@ -1144,7 +1123,7 @@ pub fn push_call_imp_some_error( pub fn push_call_vcmp_some_error( calls: &mut Vec, node_metadata_repo: Arc, - account: Option, + identity: Option, e: VCMPError, req_ext_hash: H256, ) where @@ -1155,7 +1134,7 @@ pub fn push_call_vcmp_some_error( match node_metadata_repo.get_from_metadata(|m| m.vcmp_some_error_call_indexes()) { Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + identity, e, req_ext_hash, )))), 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 f63da8b922..111b789bef 100644 --- a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs +++ b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs @@ -24,8 +24,7 @@ use crate::{ get_expected_raw_message, verify_web3_identity, }, trusted_call_result::{LinkIdentityResult, TrustedCallResult}, - AccountId, ConvertAccountId, SgxParentchainTypeConverter, ShardIdentifier, StfError, StfResult, - H256, + AccountId, ShardIdentifier, StfError, StfResult, H256, }; use codec::Encode; use frame_support::{dispatch::UnfilteredDispatchable, ensure, sp_runtime::traits::One}; @@ -257,10 +256,6 @@ impl TrustedCallSigned { NodeMetadataRepository::MetadataType: NodeMetadataTrait, { debug!("link_identity_callback, who: {}", account_id_to_string(&who)); - let account = SgxParentchainTypeConverter::convert( - who.to_account_id().ok_or(StfError::InvalidAccount)?, - ); - // the pallet extrinsic doesn't accept customised return type, so // we have to do the if-condition outside of extrinsic call let old_id_graph_len = IMT::id_graph_lens(&who); @@ -277,7 +272,7 @@ impl TrustedCallSigned { push_call_imp_some_error( calls, node_metadata_repo.clone(), - Some(account.clone()), + Some(who.clone()), e.to_imp_error(), req_ext_hash, ); @@ -292,7 +287,7 @@ impl TrustedCallSigned { node_metadata_repo.get_from_metadata(|m| m.identity_linked_call_indexes())??; calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( call_index, - account, + who.clone(), id_graph_hash, req_ext_hash, )))); diff --git a/tee-worker/core-primitives/utils/src/hex.rs b/tee-worker/core-primitives/utils/src/hex.rs index f9d30b5149..4c167af6f3 100644 --- a/tee-worker/core-primitives/utils/src/hex.rs +++ b/tee-worker/core-primitives/utils/src/hex.rs @@ -100,7 +100,7 @@ mod tests { fn hex_encode_decode_works_empty_input_for_decode() { let data = String::new(); - let decoded_data = decode_hex(&data).unwrap(); + let decoded_data = decode_hex(data).unwrap(); assert!(decoded_data.is_empty()); } diff --git a/tee-worker/enclave-runtime/Cargo.lock b/tee-worker/enclave-runtime/Cargo.lock index 5fb183c9e3..2bd785911c 100644 --- a/tee-worker/enclave-runtime/Cargo.lock +++ b/tee-worker/enclave-runtime/Cargo.lock @@ -608,11 +608,15 @@ name = "core-primitives" version = "0.9.12" dependencies = [ "frame-support", + "itp-utils", "litentry-macros 0.9.12", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "parity-scale-codec", "ring 0.16.20", "scale-info", + "serde 1.0.188", "sp-core", + "sp-io", "sp-runtime", "sp-std", "strum", @@ -1019,9 +1023,27 @@ checksum = "a49a4e11987c51220aa89dbe1a5cc877f5079fa6864c0a5b4533331db44e9365" dependencies = [ "auto_impl", "ethereum", - "evm-core", - "evm-gasometer", - "evm-runtime", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-gasometer 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "sha3 0.10.8", +] + +[[package]] +name = "evm" +version = "0.39.1" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "auto_impl", + "ethereum", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-gasometer 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", "log", "parity-scale-codec", "primitive-types", @@ -1041,14 +1063,34 @@ dependencies = [ "scale-info", ] +[[package]] +name = "evm-core" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", +] + [[package]] name = "evm-gasometer" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" dependencies = [ - "evm-core", - "evm-runtime", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", +] + +[[package]] +name = "evm-gasometer" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", "primitive-types", ] @@ -1059,7 +1101,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" dependencies = [ "auto_impl", - "evm-core", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", + "sha3 0.10.8", +] + +[[package]] +name = "evm-runtime" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "auto_impl", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", "primitive-types", "sha3 0.10.8", ] @@ -1147,12 +1200,43 @@ dependencies = [ "sp-std", ] +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "hex 0.4.3", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", +] + [[package]] name = "fp-evm" version = "3.0.0-dev" source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" dependencies = [ - "evm", + "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", "frame-support", "parity-scale-codec", "scale-info", @@ -1803,7 +1887,7 @@ dependencies = [ "frame-system", "itp-sgx-runtime-primitives", "pallet-balances", - "pallet-evm", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", "pallet-identity-management-tee", "pallet-parentchain", "pallet-sudo", @@ -3109,7 +3193,7 @@ dependencies = [ "itp-sgx-crypto", "itp-utils", "log", - "pallet-evm", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", "parity-scale-codec", "rand 0.7.3", "ring 0.16.20", @@ -3407,12 +3491,35 @@ name = "pallet-evm" version = "6.0.0-dev" source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" dependencies = [ - "evm", - "fp-account", - "fp-evm", + "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fp-account 1.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "fp-evm 3.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "frame-support", + "frame-system", + "hex 0.4.3", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "rlp", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "fp-account 1.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "frame-support", "frame-system", "hex 0.4.3", + "hex-literal", "impl-trait-for-tuples", "log", "parity-scale-codec", diff --git a/tee-worker/litentry/core/credentials/src/lib.rs b/tee-worker/litentry/core/credentials/src/lib.rs index eb1555f26e..0e0d28faf6 100644 --- a/tee-worker/litentry/core/credentials/src/lib.rs +++ b/tee-worker/litentry/core/credentials/src/lib.rs @@ -251,7 +251,7 @@ impl Credential { vc.issuer.mrenclave = shard.encode().to_base58(); vc.issuer.name = LITENTRY_ISSUER_NAME.to_string(); vc.credential_subject.id = - subject.to_did().map_err(|err| Error::ParseError(format!("{}", err)))?; + subject.to_did().map_err(|err| Error::ParseError(err.to_string()))?; vc.issuance_date = now_as_iso8601(); vc.credential_schema = None; vc.proof = None; diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs index d81661bb9f..7ee8aaa1a8 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs @@ -26,8 +26,7 @@ pub use futures; use ita_sgx_runtime::{pallet_imt::get_eligible_identities, BlockNumber, Hash, Runtime}; use ita_stf::{ aes_encrypt_default, helpers::enclave_signer_account, trusted_call_result::RequestVCResult, - ConvertAccountId, Getter, OpaqueCall, SgxParentchainTypeConverter, TrustedCall, - TrustedCallSigned, TrustedOperation, H256, + Getter, OpaqueCall, TrustedCall, TrustedCallSigned, TrustedOperation, H256, }; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ @@ -195,15 +194,9 @@ where .unwrap() .unwrap(); let result = aes_encrypt_default(&key, &response.vc_payload); - let account = SgxParentchainTypeConverter::convert( - match response.assertion_request.who.to_account_id() { - Some(s) => s, - None => return Err("Failed to convert account".to_string()), - }, - ); let call = OpaqueCall::from_tuple(&( call_index, - account, + response.assertion_request.who, response.assertion_request.assertion, response.vc_index, response.vc_hash, diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index b36f1e70b9..6a95622b8b 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -28,7 +28,6 @@ mod aes_request; mod bitcoin_address; mod bitcoin_signature; mod ethereum_signature; -mod identity; mod validation_data; pub use aes::*; @@ -36,7 +35,6 @@ pub use aes_request::*; pub use bitcoin_address::*; pub use bitcoin_signature::*; pub use ethereum_signature::*; -pub use identity::*; use sp_std::{boxed::Box, fmt::Debug, vec::Vec}; pub use validation_data::*; @@ -47,7 +45,7 @@ use itp_utils::hex::hex_encode; use log::error; pub use parentchain_primitives::{ all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, all_web3networks, - AccountId as ParentchainAccountId, AchainableAmount, AchainableAmountHolding, + identity::*, AccountId as ParentchainAccountId, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableMirror, AchainableParams, AchainableToken, AmountHoldingTimeType, Assertion, diff --git a/tee-worker/ts-tests/integration-tests/common/di-utils.ts b/tee-worker/ts-tests/integration-tests/common/di-utils.ts index 3a0b59de1d..4242dfc1c6 100644 --- a/tee-worker/ts-tests/integration-tests/common/di-utils.ts +++ b/tee-worker/ts-tests/integration-tests/common/di-utils.ts @@ -4,14 +4,14 @@ import { Codec } from '@polkadot/types/types'; import { TypeRegistry } from '@polkadot/types'; import { Bytes } from '@polkadot/types-codec'; import { IntegrationTestContext, JsonRpcRequest } from './common-types'; -import { WorkerRpcReturnValue, TrustedCallSigned, Getter } from 'parachain-api'; +import { WorkerRpcReturnValue, TrustedCallSigned, Getter, CorePrimitivesIdentity } from 'parachain-api'; import { encryptWithTeeShieldingKey, Signer, encryptWithAes, sleep } from './utils'; import { aesKey, decodeRpcBytesAsString, keyNonce } from './call'; import { createPublicKey, KeyObject } from 'crypto'; import WebSocketAsPromised from 'websocket-as-promised'; import { H256, Index } from '@polkadot/types/interfaces'; import { blake2AsHex } from '@polkadot/util-crypto'; -import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; +import type { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import { createJsonRpcRequest, nextRequestId } from './helpers'; // Send the request to worker ws @@ -158,7 +158,7 @@ export async function createSignedTrustedCallLinkIdentity( mrenclave: string, nonce: Codec, signer: Signer, - primeIdentity: LitentryPrimitivesIdentity, + primeIdentity: CorePrimitivesIdentity, identity: string, validationData: string, web3networks: string, @@ -183,7 +183,7 @@ export async function createSignedTrustedCallSetIdentityNetworks( mrenclave: string, nonce: Codec, signer: Signer, - primeIdentity: LitentryPrimitivesIdentity, + primeIdentity: CorePrimitivesIdentity, identity: string, web3networks: string, aesKey: string, @@ -207,7 +207,7 @@ export async function createSignedTrustedCallRequestVc( mrenclave: string, nonce: Codec, signer: Signer, - primeIdentity: LitentryPrimitivesIdentity, + primeIdentity: CorePrimitivesIdentity, assertion: string, aesKey: string, hash: string @@ -226,7 +226,7 @@ export async function createSignedTrustedCallDeactivateIdentity( mrenclave: string, nonce: Codec, signer: Signer, - primeIdentity: LitentryPrimitivesIdentity, + primeIdentity: CorePrimitivesIdentity, identity: string, aesKey: string, hash: string @@ -245,7 +245,7 @@ export async function createSignedTrustedCallActivateIdentity( mrenclave: string, nonce: Codec, signer: Signer, - primeIdentity: LitentryPrimitivesIdentity, + primeIdentity: CorePrimitivesIdentity, identity: string, aesKey: string, hash: string @@ -263,7 +263,7 @@ export async function createSignedTrustedCallActivateIdentity( export async function createSignedTrustedGetterIdGraph( parachainApi: ApiPromise, signer: Signer, - primeIdentity: LitentryPrimitivesIdentity + primeIdentity: CorePrimitivesIdentity ): Promise { const getterSigned = await createSignedTrustedGetter( parachainApi, @@ -277,7 +277,7 @@ export async function createSignedTrustedGetterIdGraph( export const getSidechainNonce = async ( context: IntegrationTestContext, teeShieldingKey: KeyObject, - primeIdentity: LitentryPrimitivesIdentity + primeIdentity: CorePrimitivesIdentity ): Promise => { const getterPublic = createPublicGetter(context.api, ['nonce', '(LitentryIdentity)'], primeIdentity.toHuman()); const getter = context.api.createType('Getter', { public: getterPublic }) as unknown as Getter; // @fixme 1878 @@ -289,7 +289,7 @@ export const getSidechainNonce = async ( export const getIdGraphHash = async ( context: IntegrationTestContext, teeShieldingKey: KeyObject, - primeIdentity: LitentryPrimitivesIdentity + primeIdentity: CorePrimitivesIdentity ): Promise => { const getterPublic = createPublicGetter( context.api, @@ -410,9 +410,9 @@ export const createAesRequest = async ( export function decodeIdGraph(sidechainRegistry: TypeRegistry, value: Bytes) { const idgraphBytes = sidechainRegistry.createType('Option', hexToU8a(value.toHex())); return sidechainRegistry.createType( - 'Vec<(LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', + 'Vec<(CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', idgraphBytes.unwrap() - ) as unknown as [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][]; + ) as unknown as [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][]; } export function getTopHash(parachainApi: ApiPromise, call: TrustedCallSigned) { diff --git a/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts b/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts index cd9aad1cee..bc5853364e 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts @@ -4,12 +4,11 @@ import { hexToU8a, u8aToHex } from '@polkadot/util'; import Ajv from 'ajv'; import { assert, expect } from 'chai'; import * as ed from '@noble/ed25519'; -import { parseIdGraph, parseIdentity } from './identity-helper'; -import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeError } from 'sidechain-api'; -import { TeerexPrimitivesEnclave } from 'parachain-api'; +import { parseIdGraph } from './identity-helper'; +import type { PalletIdentityManagementTeeError } from 'sidechain-api'; +import { TeerexPrimitivesEnclave, CorePrimitivesIdentity } from 'parachain-api'; import type { IntegrationTestContext } from '../common-types'; import { getIdGraphHash } from '../di-utils'; -import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; import { jsonSchema } from './vc-helper'; import { aesKey } from '../call'; @@ -60,8 +59,8 @@ export async function assertFailedEvent( } export function assertIdGraph( - actual: [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][], - expected: [LitentryPrimitivesIdentity, boolean][] + actual: [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][], + expected: [CorePrimitivesIdentity, boolean][] ) { assert.equal(actual.length, expected.length); expected.forEach((expected, i) => { @@ -77,50 +76,14 @@ export function assertIdGraph( }); } -export async function assertIdentityCreated( - context: IntegrationTestContext, - signers: KeyringPair | KeyringPair[], - events: any[], - aesKey: HexString, - expectedIdentities: LitentryPrimitivesIdentity[] -) { - for (let index = 0; index < events.length; index++) { - const signer = Array.isArray(signers) ? signers[index] : signers; - const expectedIdentity = expectedIdentities[index]; - const expectedIdentityTarget = expectedIdentity[`as${expectedIdentity.type}`]; - const eventData = events[index].data; - const who = eventData.account.toHex(); - const eventIdentity = parseIdentity(context.sidechainRegistry, eventData.identity, aesKey); - const eventIdentityTarget = eventIdentity[`as${eventIdentity.type}`]; - // Check identity caller - assert.equal(who, u8aToHex(signer.addressRaw), 'Check IdentityCreated error: signer should be equal to who'); - - // Check identity type - assert.equal( - expectedIdentity.type, - eventIdentity.type, - 'Check IdentityCreated error: eventIdentity type should be equal to expectedIdentity type' - ); - // Check identity in event - assert.equal( - expectedIdentityTarget.toString(), - eventIdentityTarget.toString(), - 'Check IdentityCreated error: eventIdentityTarget should be equal to expectedIdentityTarget' - ); - } - console.log(colors.green('assertIdentityCreated complete')); -} - -export async function assertIdentityDeactivated(signers: KeyringPair | KeyringPair[], events: any[]) { +export async function assertIdentityDeactivated(context: IntegrationTestContext, signer: Signer, events: any[]) { for (let index = 0; index < events.length; index++) { - const signer = Array.isArray(signers) ? signers[index] : signers; - const eventData = events[index].data; - const who = eventData.account.toHex(); - - assert.equal( - who, - u8aToHex(signer.addressRaw), + const who = eventData.primeIdentity; + const signerIdentity = await signer.getIdentity(context); + assert.deepEqual( + who.toHuman(), + signerIdentity.toHuman(), 'Check IdentityDeactivated error: signer should be equal to who' ); } @@ -128,18 +91,16 @@ export async function assertIdentityDeactivated(signers: KeyringPair | KeyringPa console.log(colors.green('assertIdentityDeactivated complete')); } -export async function assertIdentityActivated( - context: IntegrationTestContext, - signers: KeyringPair | KeyringPair[], - events: any[] -) { +export async function assertIdentityActivated(context: IntegrationTestContext, signer: Signer, events: any[]) { for (let index = 0; index < events.length; index++) { - const signer = Array.isArray(signers) ? signers[index] : signers; - const eventData = events[index].data; - const who = eventData.account.toHex(); - - assert.equal(who, u8aToHex(signer.addressRaw), 'Check IdentityActivated error: signer should be equal to who'); + const who = eventData.primeIdentity; + const signerIdentity = await signer.getIdentity(context); + assert.deepEqual( + who.toHuman(), + signerIdentity.toHuman(), + 'Check IdentityActivated error: signer should be equal to who' + ); } console.log(colors.green('assertIdentityActivated complete')); @@ -213,6 +174,7 @@ export async function checkJson(vc: any, proofJson: any): Promise { // for IdGraph mutation, assert the corresponding event is emitted for the given signer and the id_graph_hash matches export async function assertIdGraphMutationEvent( + context: IntegrationTestContext, signer: Signer, events: any[], idGraphHashResults: any[] | undefined, @@ -223,9 +185,9 @@ export async function assertIdGraphMutationEvent( assert.equal(idGraphHashResults!.length, expectedLength); } - const signerAddress = u8aToHex(signer.getAddressInSubstrateFormat()); + const signerIdentity = await signer.getIdentity(context); events.forEach((e, i) => { - assert.equal(signerAddress, e.data.account.toHex()); + assert.deepEqual(signerIdentity.toHuman(), e.data.primeIdentity.toHuman()); if (idGraphHashResults != undefined) { assert.equal(idGraphHashResults![i], e.data.idGraphHash.toHex()); } @@ -233,19 +195,6 @@ export async function assertIdGraphMutationEvent( console.log(colors.green('assertIdGraphMutationEvent passed')); } -export async function assertIdentity( - context: IntegrationTestContext, - events: any[], - expectedIdentities: LitentryPrimitivesIdentity[] -) { - assert.isAtLeast(events.length, 1, 'Check assertIdentity error: events length should be greater than 1'); - for (let index = 0; index < events.length; index++) { - const identity = parseIdentity(context.sidechainRegistry, events[index].data.identity, aesKey); - assert.deepEqual(identity.toString(), expectedIdentities[index].toString()); - } - console.log(colors.green('assertIdentity passed')); -} - export function assertWorkerError( context: IntegrationTestContext, check: (returnValue: StfError) => void, @@ -260,14 +209,14 @@ export function assertWorkerError( export async function assertIdGraphMutationResult( context: IntegrationTestContext, teeShieldingKey: KeyObject, - identity: LitentryPrimitivesIdentity, + identity: CorePrimitivesIdentity, returnValue: WorkerRpcReturnValue, resultType: | 'LinkIdentityResult' | 'DeactivateIdentityResult' | 'ActivateIdentityResult' | 'SetIdentityNetworksResult', - expectedIdGraph: [LitentryPrimitivesIdentity, boolean][] + expectedIdGraph: [CorePrimitivesIdentity, boolean][] ): Promise { const decodedResult = context.api.createType(resultType, returnValue.value) as any; assert.isNotNull(decodedResult.mutated_id_graph); @@ -293,7 +242,7 @@ export async function assertIdGraphMutationResult( TODO: This is incomplete; we still need to further check: https://github.com/litentry/litentry-parachain/issues/1873 */ -export async function assertVc(context: IntegrationTestContext, subject: LitentryPrimitivesIdentity, data: Bytes) { +export async function assertVc(context: IntegrationTestContext, subject: CorePrimitivesIdentity, data: Bytes) { const results = context.api.createType('RequestVCResult', data) as unknown as RequestVCResult; const vcHash = results.vc_hash.toString(); @@ -375,11 +324,11 @@ export async function assertVc(context: IntegrationTestContext, subject: Litentr export async function assertIdGraphHash( context: IntegrationTestContext, teeShieldingKey: KeyObject, - identity: LitentryPrimitivesIdentity, - idGraph: [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] + identity: CorePrimitivesIdentity, + idGraph: [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] ) { const idGraphType = context.sidechainRegistry.createType( - 'Vec<(LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', + 'Vec<(CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', idGraph ); const computedIdGraphHash = blake2AsHex(idGraphType.toU8a()); diff --git a/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts b/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts index 129a4a0dbc..d6c6b4e306 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/crypto.ts @@ -1,12 +1,14 @@ import type { HexString } from '@polkadot/util/types'; -import { bufferToU8a, hexToU8a, isString, stringToU8a } from '@polkadot/util'; +import { bufferToU8a, hexToU8a, isString, stringToU8a, u8aToHex } from '@polkadot/util'; import { KeyObject } from 'crypto'; -import { AesOutput } from 'parachain-api'; +import { AesOutput, CorePrimitivesIdentity } from 'parachain-api'; import crypto from 'crypto'; import { KeyringPair } from '@polkadot/keyring/types'; import { ethers } from 'ethers'; import { blake2AsU8a } from '@polkadot/util-crypto'; import bitcore from 'bitcore-lib'; +import { IntegrationTestContext } from 'common/common-types'; +import { buildIdentityHelper } from './identity-helper'; export type KeypairType = 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum' | 'bitcoin'; @@ -62,6 +64,7 @@ export interface Signer { sign(message: HexString | string | Uint8Array): Promise; type(): KeypairType; getAddressInSubstrateFormat(): Uint8Array; + getIdentity(api: IntegrationTestContext): Promise; } export class PolkadotSigner implements Signer { @@ -86,6 +89,10 @@ export class PolkadotSigner implements Signer { getAddressInSubstrateFormat(): Uint8Array { return this.getAddressRaw(); } + + getIdentity(context: IntegrationTestContext): Promise { + return buildIdentityHelper(u8aToHex(this.getAddressRaw()), 'Substrate', context); + } } export class EthersSigner implements Signer { @@ -117,6 +124,10 @@ export class EthersSigner implements Signer { merged.set(address, 4); return blake2AsU8a(merged, 256); } + + getIdentity(context: IntegrationTestContext): Promise { + return buildIdentityHelper(u8aToHex(this.getAddressRaw()), 'Evm', context); + } } export class BitcoinSigner implements Signer { @@ -148,4 +159,8 @@ export class BitcoinSigner implements Signer { getAddressInSubstrateFormat(): Uint8Array { return blake2AsU8a(this.getAddressRaw(), 256); } + + getIdentity(context: IntegrationTestContext): Promise { + return buildIdentityHelper(u8aToHex(this.getAddressRaw()), 'Bitcoin', context); + } } diff --git a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts index 6b00033fa4..233e24d986 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts @@ -5,8 +5,8 @@ import { AesOutput } from 'parachain-api'; import { decryptWithAes, encryptWithTeeShieldingKey, Signer } from './crypto'; import { ethers } from 'ethers'; import type { TypeRegistry } from '@polkadot/types'; -import type { LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; -import type { LitentryValidationData, Web3Network } from 'parachain-api'; +import type { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; +import type { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { HexString } from '@polkadot/util/types'; @@ -16,12 +16,12 @@ import bitcore from 'bitcore-lib'; // blake2_256( + + ) export function generateVerificationMessage( context: IntegrationTestContext, - signer: LitentryPrimitivesIdentity, - identity: LitentryPrimitivesIdentity, + signer: CorePrimitivesIdentity, + identity: CorePrimitivesIdentity, sidechainNonce: number ): HexString { - const encodedIdentity = context.sidechainRegistry.createType('LitentryPrimitivesIdentity', identity).toU8a(); - const encodedWho = context.sidechainRegistry.createType('LitentryPrimitivesIdentity', signer).toU8a(); + const encodedIdentity = context.api.createType('CorePrimitivesIdentity', identity).toU8a(); + const encodedWho = context.api.createType('CorePrimitivesIdentity', signer).toU8a(); const encodedSidechainNonce = context.api.createType('Index', sidechainNonce); const msg = Buffer.concat([encodedSidechainNonce.toU8a(), encodedWho, encodedIdentity]); return blake2AsHex(msg, 256); @@ -29,22 +29,19 @@ export function generateVerificationMessage( export async function buildIdentityHelper( address: HexString | string, - type: LitentryPrimitivesIdentity['type'], + type: CorePrimitivesIdentity['type'], context: IntegrationTestContext -): Promise { +): Promise { const identity = { [type]: address, }; - return context.sidechainRegistry.createType( - 'LitentryPrimitivesIdentity', - identity - ) as unknown as LitentryPrimitivesIdentity; + return context.api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; } export async function buildIdentityFromKeypair( signer: Signer, context: IntegrationTestContext -): Promise { +): Promise { const type: string = (() => { switch (signer.type()) { case 'ethereum': @@ -67,10 +64,7 @@ export async function buildIdentityFromKeypair( [type]: address, }; - return context.sidechainRegistry.createType( - 'LitentryPrimitivesIdentity', - identity - ) as unknown as LitentryPrimitivesIdentity; + return context.api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; } // If multiple transactions are built from multiple accounts, pass the signers as an array. @@ -80,7 +74,7 @@ export async function buildIdentityFromKeypair( export async function buildIdentityTxs( context: IntegrationTestContext, signers: KeyringPair[] | KeyringPair, - identities: LitentryPrimitivesIdentity[], + identities: CorePrimitivesIdentity[], method: 'linkIdentity' | 'deactivateIdentity' | 'activateIdentity', validations?: LitentryValidationData[], web3networks?: Web3Network[][] @@ -138,34 +132,21 @@ export function parseIdGraph( sidechainRegistry: TypeRegistry, idGraphOutput: AesOutput, aesKey: HexString -): [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] { +): [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] { const decryptedIdGraph = decryptWithAes(aesKey, idGraphOutput, 'hex'); - const idGraph: [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] = + const idGraph: [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][] = sidechainRegistry.createType( - 'Vec<(LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', + 'Vec<(CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', decryptedIdGraph - ) as unknown as [LitentryPrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][]; + ) as unknown as [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][]; return idGraph; } -export function parseIdentity( - sidechainRegistry: TypeRegistry, - identityOutput: AesOutput, - aesKey: HexString -): LitentryPrimitivesIdentity { - const decryptedIdentity = decryptWithAes(aesKey, identityOutput, 'hex'); - const identity = sidechainRegistry.createType( - 'LitentryPrimitivesIdentity', - decryptedIdentity - ) as unknown as LitentryPrimitivesIdentity; - return identity; -} - export async function buildValidations( context: IntegrationTestContext, - signerIdentities: LitentryPrimitivesIdentity[], - identities: LitentryPrimitivesIdentity[], + signerIdentities: CorePrimitivesIdentity[], + identities: CorePrimitivesIdentity[], startingSidechainNonce: number, network: 'ethereum' | 'substrate' | 'twitter' | 'bitcoin' | 'bitcoinPrettified', substrateSigners?: KeyringPair[] | KeyringPair, diff --git a/tee-worker/ts-tests/integration-tests/common/utils/storage.ts b/tee-worker/ts-tests/integration-tests/common/utils/storage.ts index d83472012a..ede4aced87 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/storage.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/storage.ts @@ -4,7 +4,8 @@ import { StorageEntryMetadataV14, SiLookupTypeId, StorageHasherV14 } from '@polk import { sendRequest } from '../call'; import { blake2128Concat, twox64Concat, identity, createJsonRpcRequest, nextRequestId } from '../helpers'; import type { IntegrationTestContext } from '../common-types'; -import type { PalletIdentityManagementTeeIdentityContext, LitentryPrimitivesIdentity } from 'sidechain-api'; +import type { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; +import type { CorePrimitivesIdentity } from 'parachain-api'; import type { HexString } from '@polkadot/util/types'; import type { Metadata } from '@polkadot/types'; @@ -94,7 +95,7 @@ export async function checkIdGraph( context: IntegrationTestContext, pallet: string, method: string, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, identity: HexString ): Promise { await sleep(6000); diff --git a/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts index a51d5e208e..1feeb3b883 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts @@ -7,7 +7,7 @@ export async function handleVcEvents( switch (method) { case 'VCIssued': results.push({ - account: events[k].data.account.toHex(), + identity: events[k].data.identity.toHex(), index: events[k].data.index.toHex(), }); break; diff --git a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts index b2fbb59709..9faa4af64f 100644 --- a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts @@ -26,36 +26,35 @@ import { } from './common/di-utils'; // @fixme move to a better place import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; -import { LitentryValidationData, Web3Network } from 'parachain-api'; -import { LitentryPrimitivesIdentity } from 'sidechain-api'; +import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import { Vec } from '@polkadot/types'; import { subscribeToEventsWithExtHash } from './common/transactions'; describe('Test Identity (bitcoin direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; - let aliceBitcoinIdentity: LitentryPrimitivesIdentity = undefined as any; - let aliceEvmIdentity: LitentryPrimitivesIdentity; - let bobBitcoinIdentity: LitentryPrimitivesIdentity; + let aliceBitcoinIdentity: CorePrimitivesIdentity = undefined as any; + let aliceEvmIdentity: CorePrimitivesIdentity; + let bobBitcoinIdentity: CorePrimitivesIdentity; // Alice links: // - alice's evm identity // - bob's bitcoin identity const linkIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; validation: LitentryValidationData; networks: Vec; }[] = []; const deactivateIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; }[] = []; const activateIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; }[] = []; this.timeout(6000000); @@ -139,7 +138,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { const identityLinkedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [ [aliceBitcoinIdentity, true], [aliceEvmIdentity, true], @@ -189,6 +188,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new BitcoinSigner(context.bitcoinWallet.alice), identityLinkedEvents, idGraphHashResults, @@ -244,7 +244,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { const identityDeactivatedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [[[aliceEvmIdentity, false]]]; + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [[[aliceEvmIdentity, false]]]; for (const { nonce, identity } of deactivateIdentityRequestParams) { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -286,6 +286,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new BitcoinSigner(context.bitcoinWallet.alice), identityDeactivatedEvents, idGraphHashResults, @@ -333,7 +334,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { const identityActivatedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [[[aliceEvmIdentity, true]]]; + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [[[aliceEvmIdentity, true]]]; for (const { nonce, identity } of activateIdentityRequestParams) { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -375,6 +376,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new BitcoinSigner(context.bitcoinWallet.alice), identityActivatedEvents, idGraphHashResults, diff --git a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts index 5de294b890..16b9b1a8c4 100644 --- a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts @@ -26,16 +26,15 @@ import { } from './common/di-utils'; // @fixme move to a better place import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; -import { LitentryValidationData, Web3Network } from 'parachain-api'; -import { LitentryPrimitivesIdentity } from 'sidechain-api'; +import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import { Vec } from '@polkadot/types'; import { subscribeToEventsWithExtHash } from './common/transactions'; describe('Test Identity (evm direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; - let aliceEvmIdentity: LitentryPrimitivesIdentity = undefined as any; - let bobEvmIdentity: LitentryPrimitivesIdentity; + let aliceEvmIdentity: CorePrimitivesIdentity = undefined as any; + let bobEvmIdentity: CorePrimitivesIdentity; // Alice links: // - a `mock_user` twitter @@ -43,7 +42,7 @@ describe('Test Identity (evm direct invocation)', function () { // - eve's substrate identity (as alice can't link her own substrate again) const linkIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; validation: LitentryValidationData; networks: Vec; }[] = []; @@ -125,7 +124,7 @@ describe('Test Identity (evm direct invocation)', function () { const identityLinkedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [ [aliceEvmIdentity, true], [bobEvmIdentity, true], @@ -175,6 +174,7 @@ describe('Test Identity (evm direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new EthersSigner(context.ethersWallet.alice), identityLinkedEvents, idGraphHashResults, @@ -227,7 +227,7 @@ describe('Test Identity (evm direct invocation)', function () { const deactivateIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; }[] = []; const bobEvmNonce = getNextNonce(); @@ -250,7 +250,7 @@ describe('Test Identity (evm direct invocation)', function () { const identityDeactivatedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [[bobEvmIdentity, false]], [[eveSubstrateIdentity, false]], ]; @@ -295,6 +295,7 @@ describe('Test Identity (evm direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new EthersSigner(context.ethersWallet.alice), identityDeactivatedEvents, idGraphHashResults, @@ -334,7 +335,7 @@ describe('Test Identity (evm direct invocation)', function () { const activateIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; }[] = []; const bobEvmNonce = getNextNonce(); @@ -357,7 +358,7 @@ describe('Test Identity (evm direct invocation)', function () { const identityActivatedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [[bobEvmIdentity, true]], [[eveSubstrateIdentity, true]], ]; @@ -402,6 +403,7 @@ describe('Test Identity (evm direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new EthersSigner(context.ethersWallet.alice), identityActivatedEvents, idGraphHashResults, diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index 68f594c410..cccf42b782 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -27,8 +27,7 @@ import { } from './common/di-utils'; // @fixme move to a better place import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; -import { LitentryValidationData, Web3Network } from 'parachain-api'; -import { LitentryPrimitivesIdentity } from 'sidechain-api'; +import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import { Vec } from '@polkadot/types'; import { ethers } from 'ethers'; import type { HexString } from '@polkadot/util/types'; @@ -37,7 +36,7 @@ import { subscribeToEventsWithExtHash } from './common/transactions'; describe('Test Identity (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; - let aliceSubstrateIdentity: LitentryPrimitivesIdentity = undefined as any; + let aliceSubstrateIdentity: CorePrimitivesIdentity = undefined as any; // Alice links: // - a `mock_user` twitter @@ -46,7 +45,7 @@ describe('Test Identity (direct invocation)', function () { // - alice's bitcoin identity const linkIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; validation: LitentryValidationData; networks: Vec; }[] = []; @@ -174,7 +173,7 @@ describe('Test Identity (direct invocation)', function () { const identityLinkedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [ [aliceSubstrateIdentity, true], [twitterIdentity, true], @@ -226,6 +225,7 @@ describe('Test Identity (direct invocation)', function () { } await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, idGraphHashResults, @@ -443,7 +443,7 @@ describe('Test Identity (direct invocation)', function () { const deactivateIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; }[] = []; const twitterNonce = getNextNonce(); @@ -486,7 +486,7 @@ describe('Test Identity (direct invocation)', function () { const identityDeactivatedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [[twitterIdentity, false]], [[evmIdentity, false]], [[eveSubstrateIdentity, false]], @@ -532,6 +532,7 @@ describe('Test Identity (direct invocation)', function () { }); } await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.alice), identityDeactivatedEvents, idGraphHashResults, @@ -571,7 +572,7 @@ describe('Test Identity (direct invocation)', function () { const activateIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; }[] = []; const twitterNonce = getNextNonce(); @@ -614,7 +615,7 @@ describe('Test Identity (direct invocation)', function () { const identityActivatedEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [ + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [ [[twitterIdentity, true]], [[evmIdentity, true]], [[eveSubstrateIdentity, true]], @@ -660,6 +661,7 @@ describe('Test Identity (direct invocation)', function () { }); } await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.alice), identityActivatedEvents, idGraphHashResults, @@ -721,7 +723,7 @@ describe('Test Identity (direct invocation)', function () { const identityNetworksSetEvents: any[] = []; const idGraphHashResults: any[] = []; - let expectedIdGraphs: [LitentryPrimitivesIdentity, boolean][][] = [[[eveSubstrateIdentity, true]]]; + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [[[eveSubstrateIdentity, true]]]; const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); // we set the network to ['Litentry', 'Kusama'] @@ -758,6 +760,7 @@ describe('Test Identity (direct invocation)', function () { } }); await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.alice), identityNetworksSetEvents, idGraphHashResults, diff --git a/tee-worker/ts-tests/integration-tests/di_vc.test.ts b/tee-worker/ts-tests/integration-tests/di_vc.test.ts index 4b7ea6f093..9403bafbd8 100644 --- a/tee-worker/ts-tests/integration-tests/di_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_vc.test.ts @@ -14,7 +14,7 @@ import { import { buildIdentityHelper, buildValidations } from './common/utils'; import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; -import { LitentryPrimitivesIdentity } from 'sidechain-api'; +import { CorePrimitivesIdentity } from 'parachain-api'; import { subscribeToEventsWithExtHash } from './common/transactions'; import { defaultAssertions, unconfiguredAssertions } from './common/utils/vc-helper'; import { LitentryValidationData, Web3Network } from 'parachain-api'; @@ -23,7 +23,7 @@ import { Vec } from '@polkadot/types'; describe('Test Vc (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; - let aliceSubstrateIdentity: LitentryPrimitivesIdentity = undefined as any; + let aliceSubstrateIdentity: CorePrimitivesIdentity = undefined as any; // Alice links: // - a `mock_user` twitter @@ -33,7 +33,7 @@ describe('Test Vc (direct invocation)', function () { // We need this linking to not have empty eligible identities for any vc request const linkIdentityRequestParams: { nonce: number; - identity: LitentryPrimitivesIdentity; + identity: CorePrimitivesIdentity; validation: LitentryValidationData; networks: Vec; }[] = []; diff --git a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts index 01bd32114c..c7522fcfea 100644 --- a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts @@ -11,16 +11,15 @@ import { step } from 'mocha-steps'; import { sendTxsWithUtility } from './common/transactions'; import { generateWeb3Wallets, assertIdGraphMutationEvent, assertIdentityDeactivated } from './common/utils'; import { ethers } from 'ethers'; -import type { LitentryPrimitivesIdentity } from 'sidechain-api'; -import type { LitentryValidationData, Web3Network } from 'parachain-api'; +import type { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import { Vec } from '@polkadot/types'; describeLitentry('Test Batch Utility', (context) => { - let identities: LitentryPrimitivesIdentity[] = []; + let identities: CorePrimitivesIdentity[] = []; let validations: LitentryValidationData[] = []; let evmSigners: ethers.Wallet[] = []; const we3networks: Web3Network[][] = []; - const signerIdentities: LitentryPrimitivesIdentity[] = []; + const signerIdentities: CorePrimitivesIdentity[] = []; step('generate web3 wallets', async function () { const web3Wallets = await generateWeb3Wallets(3); @@ -69,6 +68,7 @@ describeLitentry('Test Batch Utility', (context) => { const identityLinkedEvents = events.filter((e) => context.api.events.identityManagement.IdentityLinked.is(e)); await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, undefined, @@ -86,7 +86,7 @@ describeLitentry('Test Batch Utility', (context) => { ['IdentityDeactivated'] ); - await assertIdentityDeactivated(context.substrateWallet.alice, deactivatedEvents); + await assertIdentityDeactivated(context, new PolkadotSigner(context.substrateWallet.alice), deactivatedEvents); }); step('batch test: deactivate error identities', async function () { diff --git a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts index cf71f5c401..5a231493f8 100644 --- a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts @@ -16,8 +16,7 @@ import { u8aConcat, u8aToHex, u8aToU8a, stringToU8a } from '@polkadot/util'; import { step } from 'mocha-steps'; import { assert } from 'chai'; import { sendTxsWithUtility } from './common/transactions'; -import type { LitentryPrimitivesIdentity } from 'sidechain-api'; -import type { LitentryValidationData, Web3Network } from 'parachain-api'; +import type { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import type { IntegrationTestContext } from './common/common-types'; import type { HexString } from '@polkadot/util/types'; import { ethers } from 'ethers'; @@ -55,8 +54,8 @@ describeLitentry('Test Identity', (context) => { // random wrong msg const wrongMsg = '0x693d9131808e7a8574c7ea5eb7813bdf356223263e61fa8fe2ee8e434508bc75'; let signatureSubstrate; - let eveIdentities: LitentryPrimitivesIdentity[] = []; - let charlieIdentities: LitentryPrimitivesIdentity[] = []; + let eveIdentities: CorePrimitivesIdentity[] = []; + let charlieIdentities: CorePrimitivesIdentity[] = []; let eveValidations: LitentryValidationData[] = []; let bobValidations: LitentryValidationData[] = []; let web3networks: Web3Network[][] = []; @@ -159,6 +158,7 @@ describeLitentry('Test Identity', (context) => { ); await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.alice), identityLinkedEvents, undefined, @@ -221,6 +221,7 @@ describeLitentry('Test Identity', (context) => { identityLinkedEvents = bobRespEvents.filter((e) => context.api.events.identityManagement.IdentityLinked.is(e)); await assertIdGraphMutationEvent( + context, new PolkadotSigner(context.substrateWallet.bob), identityLinkedEvents, undefined, @@ -230,7 +231,7 @@ describeLitentry('Test Identity', (context) => { step('check IDGraph after LinkIdentity', async function () { const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); - const identityHex = context.sidechainRegistry.createType('LitentryPrimitivesIdentity', twitterIdentity).toHex(); + const identityHex = context.api.createType('CorePrimitivesIdentity', twitterIdentity).toHex(); const aliceSubstrateIdentity = await buildIdentityFromKeypair( new PolkadotSigner(context.substrateWallet.alice), context @@ -389,10 +390,10 @@ describeLitentry('Test Identity', (context) => { ); // Alice check identity - assertIdentityDeactivated(context.substrateWallet.alice, aliceDeactivatedEvents); + assertIdentityDeactivated(context, new PolkadotSigner(context.substrateWallet.alice), aliceDeactivatedEvents); // Bob check identity - assertIdentityDeactivated(context.substrateWallet.bob, bobDeactivatedEvents); + assertIdentityDeactivated(context, new PolkadotSigner(context.substrateWallet.bob), bobDeactivatedEvents); }); step('check IDGraph after deactivateIdentity', async function () { @@ -416,7 +417,7 @@ describeLitentry('Test Identity', (context) => { ['IdentityActivated'] ); // Alice check identity - await assertIdentityActivated(context, context.substrateWallet.alice, aliceActivatedEvents); + await assertIdentityActivated(context, new PolkadotSigner(context.substrateWallet.alice), aliceActivatedEvents); }); step('deactivate prime identity is disallowed', async function () { diff --git a/tee-worker/ts-tests/stress/src/litentry-api.ts b/tee-worker/ts-tests/stress/src/litentry-api.ts index 8852b98a6c..af3b425aed 100644 --- a/tee-worker/ts-tests/stress/src/litentry-api.ts +++ b/tee-worker/ts-tests/stress/src/litentry-api.ts @@ -11,11 +11,7 @@ import { } from '@polkadot/util'; import { blake2AsHex } from '@polkadot/util-crypto'; import crypto, { KeyObject, createPublicKey } from 'crypto'; -import { - LitentryPrimitivesIdentity, - TypeRegistry as SidechainTypeRegistry, - Metadata as SidechainMetadata, -} from 'sidechain-api'; +import { TypeRegistry as SidechainTypeRegistry, Metadata as SidechainMetadata } from 'sidechain-api'; import { Bytes, Codec, @@ -25,15 +21,16 @@ import { WorkerRpcReturnValue, LitentryValidationData, Assertion, + CorePrimitivesIdentity, + TrustedCallSigned, + PublicGetter, } from 'parachain-api'; import WebSocketAsPromised from 'websocket-as-promised'; import { Index } from '@polkadot/types/interfaces'; import { Option, u32, u8, Vector } from 'scale-ts'; -import { TrustedCallSigned } from 'parachain-api'; import WsWebSocket from 'ws'; import type { HexString } from '@polkadot/util/types'; import { ethers } from 'ethers'; -import { PublicGetter } from 'parachain-api'; async function logLine(log: WritableStream, message: string): Promise { const writer = log.getWriter(); @@ -69,13 +66,12 @@ function encryptWithAes(key: string, nonce: Uint8Array, cleartext: Buffer): HexS function generateVerificationMessage( parachainApi: ParachainApiPromise, - sidechainRegistry: SidechainTypeRegistry, - signer: LitentryPrimitivesIdentity, - identity: LitentryPrimitivesIdentity, + signer: CorePrimitivesIdentity, + identity: CorePrimitivesIdentity, sidechainNonce: number ): HexString { - const encodedIdentity = sidechainRegistry.createType('LitentryPrimitivesIdentity', identity).toU8a(); - const encodedWho = sidechainRegistry.createType('LitentryPrimitivesIdentity', signer).toU8a(); + const encodedIdentity = parachainApi.createType('CorePrimitivesIdentity', identity).toU8a(); + const encodedWho = parachainApi.createType('CorePrimitivesIdentity', signer).toU8a(); const encodedSidechainNonce = parachainApi.createType('Index', sidechainNonce); const msg = Buffer.concat([encodedSidechainNonce.toU8a(), encodedWho, encodedIdentity]); return blake2AsHex(msg, 256); @@ -84,18 +80,12 @@ function generateVerificationMessage( export async function buildValidation( parachainApi: ParachainApiPromise, sidechainRegistry: SidechainTypeRegistry, - signerIdentity: LitentryPrimitivesIdentity, - identity: LitentryPrimitivesIdentity, + signerIdentity: CorePrimitivesIdentity, + identity: CorePrimitivesIdentity, startingSidechainNonce: number, signer: Wallet ): Promise { - const message = generateVerificationMessage( - parachainApi, - sidechainRegistry, - signerIdentity, - identity, - startingSidechainNonce - ); + const message = generateVerificationMessage(parachainApi, signerIdentity, identity, startingSidechainNonce); return parachainApi.createType('LitentryValidationData', { Web3Validation: @@ -121,17 +111,14 @@ export async function buildValidation( export async function buildIdentityFromWallet( wallet: Wallet, - sidechainRegistry: SidechainTypeRegistry -): Promise { + api: ParachainApiPromise +): Promise { if (wallet.type === 'evm') { const identity = { Evm: wallet.wallet.address, }; - return sidechainRegistry.createType( - 'LitentryPrimitivesIdentity', - identity - ) as unknown as LitentryPrimitivesIdentity; + return api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; } const { keyringPair } = wallet; @@ -155,10 +142,7 @@ export async function buildIdentityFromWallet( [type]: address, }; - return sidechainRegistry.createType( - 'LitentryPrimitivesIdentity', - identity - ) as unknown as LitentryPrimitivesIdentity; + return api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; } export function decodeRpcBytesAsString(value: Bytes): string { @@ -264,7 +248,7 @@ export const createSignedTrustedGetter = ( export function createSignedTrustedGetterUserShieldingKey( parachainApi: ParachainApiPromise, signer: KeyringPair, - subject: LitentryPrimitivesIdentity + subject: CorePrimitivesIdentity ) { const getterSigned = createSignedTrustedGetter( parachainApi, @@ -343,7 +327,7 @@ export const getSidechainNonce = async ( parachainApi: ParachainApiPromise, mrenclave: string, teeShieldingKey: KeyObject, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise => { const getterPublic = createPublicGetter(parachainApi, ['nonce', '(LitentryIdentity)'], subject.toHuman()); @@ -499,7 +483,7 @@ export function createSignedTrustedCallSetUserShieldingKey( mrenclave: string, nonce: Codec, signer: Wallet, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, key: string, hash: string, withWrappedBytes = false @@ -520,7 +504,7 @@ export function createSignedTrustedCallLinkIdentity( mrenclave: string, nonce: Codec, signer: Wallet, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, identity: string, validationData: string, web3networks: string, @@ -545,8 +529,8 @@ export function createSignedTrustedCallDeactivateIdentity( mrenclave: string, nonce: Codec, signer: Wallet, - subject: LitentryPrimitivesIdentity, - identity: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, + identity: CorePrimitivesIdentity, hash: string ) { return createSignedTrustedCall( @@ -564,8 +548,8 @@ export function createSignedTrustedCallActivateIdentity( mrenclave: string, nonce: Codec, signer: Wallet, - subject: LitentryPrimitivesIdentity, - identity: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, + identity: CorePrimitivesIdentity, hash: string ) { return createSignedTrustedCall( @@ -583,7 +567,7 @@ export function createSignedTrustedCallRequestVc( mrenclave: string, nonce: Codec, signer: Wallet, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, assertion: Assertion, key: string, hash: string diff --git a/tee-worker/ts-tests/stress/src/steps.ts b/tee-worker/ts-tests/stress/src/steps.ts index 5a51491a27..2bc98fa59b 100644 --- a/tee-worker/ts-tests/stress/src/steps.ts +++ b/tee-worker/ts-tests/stress/src/steps.ts @@ -1,4 +1,4 @@ -import { LitentryPrimitivesIdentity, TypeRegistry as SidechainTypeRegistry } from 'sidechain-api'; +import { TypeRegistry as SidechainTypeRegistry } from 'sidechain-api'; import { Wallet, buildIdentityFromWallet, @@ -12,7 +12,7 @@ import { subscribeToEventsWithExtHash, } from './litentry-api'; import WebSocketAsPromised from 'websocket-as-promised'; -import { ApiPromise as ParachainApiPromise } from 'parachain-api'; +import { ApiPromise as ParachainApiPromise, CorePrimitivesIdentity } from 'parachain-api'; import crypto, { randomBytes } from 'crypto'; import { Index } from '@polkadot/types/interfaces'; import { Measurement, Runner } from './measurement'; @@ -29,7 +29,7 @@ export async function setShieldingKey( teeShieldingKey: crypto.KeyObject, userShieldingKey: string, nonce: Index, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -74,7 +74,7 @@ export async function linkIdentity( mrEnclave: string, teeShieldingKey: crypto.KeyObject, nonce: Index, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -127,7 +127,7 @@ export async function requestVc1( mrEnclave: string, teeShieldingKey: crypto.KeyObject, nonce: Index, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -162,7 +162,7 @@ export async function requestVc4( mrEnclave: string, teeShieldingKey: crypto.KeyObject, nonce: Index, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -199,7 +199,7 @@ export async function deactivateIdentity( teeShieldingKey: crypto.KeyObject, userShieldingKey: string, nonce: Index, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; @@ -242,7 +242,7 @@ export async function activateIdentity( mrEnclave: string, teeShieldingKey: crypto.KeyObject, nonce: Index, - subject: LitentryPrimitivesIdentity, + subject: CorePrimitivesIdentity, log: WritableStream ): Promise { const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; diff --git a/tee-worker/ts-tests/stress/src/user-session.ts b/tee-worker/ts-tests/stress/src/user-session.ts index 5e64794584..f776c834e3 100644 --- a/tee-worker/ts-tests/stress/src/user-session.ts +++ b/tee-worker/ts-tests/stress/src/user-session.ts @@ -1,4 +1,4 @@ -import { LitentryPrimitivesIdentity } from 'sidechain-api'; +import { CorePrimitivesIdentity } from 'parachain-api'; import { Index } from '@polkadot/types/interfaces'; import { buildIdentityFromWallet, getSidechainNonce, Wallet, Api } from './litentry-api'; import { Runner } from './measurement'; @@ -7,7 +7,7 @@ import { setShieldingKey } from './steps'; export type UserSession = { primary: Wallet; userShieldingKey: `0x${string}`; - subject: LitentryPrimitivesIdentity; + subject: CorePrimitivesIdentity; nextNonce: () => Index; }; export async function newUserSession( @@ -17,7 +17,7 @@ export async function newUserSession( log: WritableStream, runner: Runner ): Promise { - const subject = await buildIdentityFromWallet(primary, api.sidechainRegistry); + const subject = await buildIdentityFromWallet(primary, api.parachainApi); const initialNonce = await getSidechainNonce( api.teeWorker, api.parachainApi, From 29b06c40f46a43e6fbad1ce2463b765c96fa492a Mon Sep 17 00:00:00 2001 From: BillyWooo Date: Fri, 5 Jan 2024 18:20:53 +0100 Subject: [PATCH 40/43] skip DCAP setting when feature disabled. (#2381) --- tee-worker/service/src/main_impl.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tee-worker/service/src/main_impl.rs b/tee-worker/service/src/main_impl.rs index 0d1b53eda0..019fbdfe2e 100644 --- a/tee-worker/service/src/main_impl.rs +++ b/tee-worker/service/src/main_impl.rs @@ -160,6 +160,7 @@ pub(crate) fn main() { enclave_metrics_receiver, ))); + #[cfg(feature = "dcap")] let quoting_enclave_target_info = match enclave.qe_get_target_info() { Ok(target_info) => Some(target_info), Err(e) => { @@ -167,6 +168,7 @@ pub(crate) fn main() { None }, }; + #[cfg(feature = "dcap")] let quote_size = match enclave.qe_get_quote_size() { Ok(size) => Some(size), Err(e) => { @@ -175,6 +177,11 @@ pub(crate) fn main() { }, }; + #[cfg(not(feature = "dcap"))] + let quoting_enclave_target_info = None; + #[cfg(not(feature = "dcap"))] + let quote_size = None; + let data_provider_config = get_data_provider_config(&config); if let Some(run_config) = config.run_config() { From f6ecadf5d5a393c209c673694fd8c5f6866987bd Mon Sep 17 00:00:00 2001 From: Faisal Ahmed <42486737+felixfaisal@users.noreply.github.com> Date: Fri, 5 Jan 2024 22:54:24 +0530 Subject: [PATCH 41/43] feat: add bnb domain holding to cli (#2383) --- .../cli/src/trusted_base_cli/commands/litentry/request_vc.rs | 2 ++ .../src/trusted_base_cli/commands/litentry/request_vc_direct.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index be27084acc..b740d93d2a 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -91,6 +91,7 @@ pub enum Command { A13(A13Arg), A14, A20, + BnbDomainHolding, #[clap(subcommand)] Oneblock(OneblockCommand), #[clap(subcommand)] @@ -317,6 +318,7 @@ impl RequestVcCommand { }, Command::A14 => Assertion::A14, Command::A20 => Assertion::A20, + Command::BnbDomainHolding => Assertion::BnbDomainHolding, Command::Oneblock(c) => match c { OneblockCommand::Completion => Assertion::Oneblock(OneBlockCourseType::CourseCompletion), diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs index 1466b0abab..d909a05212 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs @@ -96,6 +96,7 @@ impl RequestVcDirectCommand { }, Command::A14 => Assertion::A14, Command::A20 => Assertion::A20, + Command::BnbDomainHolding => Assertion::BnbDomainHolding, Command::Oneblock(c) => match c { OneblockCommand::Completion => Assertion::Oneblock(OneBlockCourseType::CourseCompletion), From 533a6e10fddd95044025a4d9875fcdff2083d913 Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Sat, 6 Jan 2024 12:26:24 +0100 Subject: [PATCH 42/43] IDGraph should be created in more actions than linking (#2347) * init impl * remove tests * add test cases * fix test * fix clippy * fix tests * fix ii test * implement idgraph diff * fix tests --- tee-worker/app-libs/stf/src/trusted_call.rs | 82 ++++----- .../app-libs/stf/src/trusted_call_litentry.rs | 17 +- tee-worker/core/rpc-client/src/mock.rs | 2 +- .../pallets/identity-management/src/lib.rs | 42 +++-- .../pallets/identity-management/src/tests.rs | 13 +- .../integration-tests/di_evm_identity.test.ts | 53 +----- .../di_substrate_identity.test.ts | 156 +++++++++++++----- .../integration-tests/ii_identity.test.ts | 30 +--- 8 files changed, 192 insertions(+), 203 deletions(-) diff --git a/tee-worker/app-libs/stf/src/trusted_call.rs b/tee-worker/app-libs/stf/src/trusted_call.rs index 307005313e..3168d9bc16 100644 --- a/tee-worker/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/app-libs/stf/src/trusted_call.rs @@ -733,10 +733,11 @@ where let call_index = node_metadata_repo .get_from_metadata(|m| m.identity_deactivated_call_indexes())??; + let old_id_graph = IMT::id_graph(&who); Self::deactivate_identity_internal( signer.to_account_id().ok_or(Self::Error::InvalidAccount)?, who.clone(), - identity.clone(), + identity, ) .map_err(|e| { debug!("pushing error event ... error: {}", e); @@ -760,18 +761,14 @@ where req_ext_hash, )))); - let mut mutated_id_graph = IDGraph::::default(); - if let Some(identity_context) = IMT::id_graphs(&who, &identity) { - if let Some(key) = maybe_key { - mutated_id_graph.push((identity, identity_context)); - return Ok(TrustedCallResult::DeactivateIdentity(DeactivateIdentityResult { - mutated_id_graph: aes_encrypt_default(&key, &mutated_id_graph.encode()), - id_graph_hash, - })) - } - } else { - // if should not happen, so we just log the error here - error!("failed to get identity_context for {:?}, {:?}", &who, &identity); + let mut mutated_id_graph = IMT::id_graph(&who); + mutated_id_graph.retain(|i| !old_id_graph.contains(i)); + + if let Some(key) = maybe_key { + return Ok(TrustedCallResult::DeactivateIdentity(DeactivateIdentityResult { + mutated_id_graph: aes_encrypt_default(&key, &mutated_id_graph.encode()), + id_graph_hash, + })) } Ok(TrustedCallResult::Empty) @@ -780,11 +777,12 @@ where debug!("activate_identity, who: {}", account_id_to_string(&who)); let call_index = node_metadata_repo .get_from_metadata(|m| m.identity_activated_call_indexes())??; + let old_id_graph = IMT::id_graph(&who); Self::activate_identity_internal( signer.to_account_id().ok_or(Self::Error::InvalidAccount)?, who.clone(), - identity.clone(), + identity, ) .map_err(|e| { debug!("pushing error event ... error: {}", e); @@ -808,18 +806,14 @@ where req_ext_hash, )))); - let mut mutated_id_graph = IDGraph::::default(); - if let Some(identity_context) = IMT::id_graphs(&who, &identity) { - if let Some(key) = maybe_key { - mutated_id_graph.push((identity, identity_context)); - return Ok(TrustedCallResult::ActivateIdentity(ActivateIdentityResult { - mutated_id_graph: aes_encrypt_default(&key, &mutated_id_graph.encode()), - id_graph_hash, - })) - } - } else { - // if should not happen, so we just log the error here - error!("failed to get identity_context for {:?}, {:?}", &who, &identity); + let mut mutated_id_graph = IMT::id_graph(&who); + mutated_id_graph.retain(|i| !old_id_graph.contains(i)); + + if let Some(key) = maybe_key { + return Ok(TrustedCallResult::ActivateIdentity(ActivateIdentityResult { + mutated_id_graph: aes_encrypt_default(&key, &mutated_id_graph.encode()), + id_graph_hash, + })) } Ok(TrustedCallResult::Empty) @@ -941,14 +935,11 @@ where ); let call_index = node_metadata_repo .get_from_metadata(|m| m.identity_networks_set_call_indexes())??; + let old_id_graph = IMT::id_graph(&who); - IMTCall::set_identity_networks { - who: who.clone(), - identity: identity.clone(), - web3networks, - } - .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) - .map_err(|e| Self::Error::Dispatch(format!(" error: {:?}", e.error)))?; + IMTCall::set_identity_networks { who: who.clone(), identity, web3networks } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) + .map_err(|e| Self::Error::Dispatch(format!(" error: {:?}", e.error)))?; let id_graph_hash: H256 = IMT::id_graph_hash(&who).ok_or(StfError::EmptyIDGraph)?; @@ -960,23 +951,14 @@ where req_ext_hash, )))); - let mut mutated_id_graph = IDGraph::::default(); - if let Some(identity_context) = IMT::id_graphs(&who, &identity) { - if let Some(key) = maybe_key { - mutated_id_graph.push((identity, identity_context)); - return Ok(TrustedCallResult::SetIdentityNetworks( - SetIdentityNetworksResult { - mutated_id_graph: aes_encrypt_default( - &key, - &mutated_id_graph.encode(), - ), - id_graph_hash, - }, - )) - } - } else { - // if should not happen, so we just log the error here - error!("failed to get identity_context for {:?}, {:?}", &who, &identity); + let mut mutated_id_graph = IMT::id_graph(&who); + mutated_id_graph.retain(|i| !old_id_graph.contains(i)); + + if let Some(key) = maybe_key { + return Ok(TrustedCallResult::SetIdentityNetworks(SetIdentityNetworksResult { + mutated_id_graph: aes_encrypt_default(&key, &mutated_id_graph.encode()), + id_graph_hash, + })) } Ok(TrustedCallResult::Empty) 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 111b789bef..7b724d642c 100644 --- a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs +++ b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs @@ -30,7 +30,7 @@ use codec::Encode; use frame_support::{dispatch::UnfilteredDispatchable, ensure, sp_runtime::traits::One}; use ita_sgx_runtime::{ pallet_imt::{get_eligible_identities, IdentityContext}, - BlockNumber, IDGraph, RuntimeOrigin, System, + BlockNumber, RuntimeOrigin, System, }; use itp_node_api::metadata::NodeMetadataTrait; use itp_node_api_metadata::pallet_imp::IMPCallIndexes; @@ -258,13 +258,12 @@ impl TrustedCallSigned { debug!("link_identity_callback, who: {}", account_id_to_string(&who)); // the pallet extrinsic doesn't accept customised return type, so // we have to do the if-condition outside of extrinsic call - let old_id_graph_len = IMT::id_graph_lens(&who); - let mut mutated_id_graph = IDGraph::::default(); + let old_id_graph = IMT::id_graph(&who); Self::link_identity_callback_internal( signer.to_account_id().ok_or(StfError::InvalidAccount)?, who.clone(), - identity.clone(), + identity, web3networks, ) .map_err(|e| { @@ -292,14 +291,8 @@ impl TrustedCallSigned { req_ext_hash, )))); - if old_id_graph_len == 0 { - mutated_id_graph = IMT::id_graph(&who); - } else if let Some(identity_context) = IMT::id_graphs(&who, &identity) { - mutated_id_graph.push((identity, identity_context)) - } else { - // if should not happen, so we just log the error here - error!("failed to get identity_context for {:?}, {:?}", &who, &identity); - } + let mut mutated_id_graph = IMT::id_graph(&who); + mutated_id_graph.retain(|i| !old_id_graph.contains(i)); if let Some(key) = maybe_key { return Ok(TrustedCallResult::LinkIdentity(LinkIdentityResult { diff --git a/tee-worker/core/rpc-client/src/mock.rs b/tee-worker/core/rpc-client/src/mock.rs index a76851931a..8f582ecc27 100644 --- a/tee-worker/core/rpc-client/src/mock.rs +++ b/tee-worker/core/rpc-client/src/mock.rs @@ -120,7 +120,7 @@ impl DirectApi for DirectClientMock { unimplemented!() } - fn get_id_graph_hash(&self, shard: &ShardIdentifier, identity: &Identity) -> Result { + fn get_id_graph_hash(&self, _shard: &ShardIdentifier, _identity: &Identity) -> Result { unimplemented!() } } diff --git a/tee-worker/litentry/pallets/identity-management/src/lib.rs b/tee-worker/litentry/pallets/identity-management/src/lib.rs index a672902373..d5f12ee04b 100644 --- a/tee-worker/litentry/pallets/identity-management/src/lib.rs +++ b/tee-worker/litentry/pallets/identity-management/src/lib.rs @@ -95,8 +95,6 @@ pub mod pallet { IdentityNotExist, /// creating the prime identity manually is disallowed LinkPrimeIdentityDisallowed, - /// deactivate prime identity should be disallowed - DeactivatePrimeIdentityDisallowed, /// IDGraph len limit reached IDGraphLenLimitReached, /// identity doesn't match the network types @@ -148,20 +146,7 @@ pub mod pallet { Error::::WrongWeb3NetworkTypes ); - // if there's no IDGraph, create one - `who` will be the prime identity - // please note the web3networks for the prime identity will be all avaiable networks - if IDGraphs::::get(&who, &who).is_none() { - ensure!( - !LinkedIdentities::::contains_key(&who), - Error::::IdentityAlreadyLinked - ); - - let context = >::new( - ::BlockNumber::one(), - who.default_web3networks(), - ); - Self::insert_identity_with_limit(&who, &who, context)?; - } + Self::maybe_create_id_graph(&who)?; let context = >::new(>::block_number(), web3networks); @@ -178,8 +163,8 @@ pub mod pallet { identity: Identity, ) -> DispatchResult { T::ManageOrigin::ensure_origin(origin)?; + Self::maybe_create_id_graph(&who)?; ensure!(IDGraphs::::contains_key(&who, &identity), Error::::IdentityNotExist); - ensure!(identity != who, Error::::DeactivatePrimeIdentityDisallowed); IDGraphs::::try_mutate(&who, &identity, |context| { let mut c = context.take().ok_or(Error::::IdentityNotExist)?; @@ -199,7 +184,9 @@ pub mod pallet { identity: Identity, ) -> DispatchResult { T::ManageOrigin::ensure_origin(origin)?; + Self::maybe_create_id_graph(&who)?; ensure!(IDGraphs::::contains_key(&who, &identity), Error::::IdentityNotExist); + IDGraphs::::try_mutate(&who, &identity, |context| { let mut c = context.take().ok_or(Error::::IdentityNotExist)?; c.activate(); @@ -219,7 +206,9 @@ pub mod pallet { web3networks: Vec, ) -> DispatchResult { T::ManageOrigin::ensure_origin(origin)?; + Self::maybe_create_id_graph(&who)?; ensure!(IDGraphs::::contains_key(&who, &identity), Error::::IdentityNotExist); + IDGraphs::::try_mutate(&who, &identity, |context| { let mut c = context.take().ok_or(Error::::IdentityNotExist)?; ensure!( @@ -270,6 +259,25 @@ pub mod pallet { } impl Pallet { + // try to create an IDGraph if there's none - `who` will be the prime identity + // please note the web3networks for the prime identity will be all avaiable networks + fn maybe_create_id_graph(who: &Identity) -> Result<(), DispatchError> { + if IDGraphs::::get(who, who).is_none() { + ensure!( + !LinkedIdentities::::contains_key(who), + Error::::IdentityAlreadyLinked + ); + + let context = >::new( + ::BlockNumber::one(), + who.default_web3networks(), + ); + + Self::insert_identity_with_limit(who, who, context)?; + } + Ok(()) + } + fn insert_identity_with_limit( owner: &Identity, identity: &Identity, diff --git a/tee-worker/litentry/pallets/identity-management/src/tests.rs b/tee-worker/litentry/pallets/identity-management/src/tests.rs index ad8fa38528..8660d370a8 100644 --- a/tee-worker/litentry/pallets/identity-management/src/tests.rs +++ b/tee-worker/litentry/pallets/identity-management/src/tests.rs @@ -291,14 +291,11 @@ fn deactivate_identity_works() { // identity is only deactivated, so it still exists assert_eq!(crate::IDGraphLens::::get(&who.clone()), 2); - assert_noop!( - IMT::deactivate_identity( - RuntimeOrigin::signed(ALICE), - who.clone(), - bob_substrate_identity(), - ), - Error::::DeactivatePrimeIdentityDisallowed - ); + assert_ok!(IMT::deactivate_identity( + RuntimeOrigin::signed(ALICE), + who.clone(), + bob_substrate_identity(), + )); }); } diff --git a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts index 16b9b1a8c4..36a6d947ec 100644 --- a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts @@ -1,7 +1,7 @@ import { randomBytes, KeyObject } from 'crypto'; import { step } from 'mocha-steps'; import { assert } from 'chai'; -import { u8aToHex, u8aToString } from '@polkadot/util'; +import { u8aToHex } from '@polkadot/util'; import { buildIdentityFromKeypair, buildIdentityHelper, @@ -9,10 +9,9 @@ import { initIntegrationTestContext, EthersSigner, assertIdGraphMutationResult, - assertWorkerError, assertIdGraphHash, } from './common/utils'; -import { assertFailedEvent, assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; +import { assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; import { createSignedTrustedCallLinkIdentity, createSignedTrustedGetterIdGraph, @@ -437,52 +436,4 @@ describe('Test Identity (evm direct invocation)', function () { await assertIdGraphHash(context, teeShieldingKey, aliceEvmIdentity, idGraph); }); - - step('deactivating prime identity is disallowed', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceEvmIdentity)).toNumber(); - const getNextNonce = () => currentNonce++; - const nonce = getNextNonce(); - - // prime identity - const substratePrimeIdentity = await buildIdentityHelper( - u8aToHex(new EthersSigner(context.ethersWallet.alice).getAddressRaw()), - 'Evm', - context - ); - - const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; - const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); - const deactivateIdentityCall = await createSignedTrustedCallDeactivateIdentity( - context.api, - context.mrEnclave, - context.api.createType('Index', nonce), - new EthersSigner(context.ethersWallet.alice), - aliceEvmIdentity, - substratePrimeIdentity.toHex(), - context.api.createType('Option', aesKey).toHex(), - requestIdentifier - ); - - const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); - assert.isTrue(res.do_watch.isFalse); - assert.isTrue(res.status.asTrustedOperationStatus[0].isInvalid); - assertWorkerError( - context, - (v) => { - assert.isTrue( - v.isDeactivateIdentityFailed, - `expected DeactivateIdentityFailed, received ${v.type} instead` - ); - assert.isTrue( - v.asDeactivateIdentityFailed.isStfError, - `expected StfError, received ${v.asDeactivateIdentityFailed.type} instead` - ); - assert.equal(u8aToString(v.asDeactivateIdentityFailed.asStfError), 'DeactivatePrimeIdentityDisallowed'); - }, - res - ); - - const events = await eventsPromise; - await assertFailedEvent(context, events, 'DeactivateIdentityFailed', 'DeactivatePrimeIdentityDisallowed'); - }); }); diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index cccf42b782..8f19167d5e 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -271,13 +271,12 @@ describe('Test Identity (direct invocation)', function () { }); step('linking invalid identity', async function () { - const aliceSubstrateIdentity = await buildIdentityFromKeypair( + const bobSubstrateIdentity = await buildIdentityFromKeypair( new PolkadotSigner(context.substrateWallet.bob), context ); - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); - + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, bobSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); @@ -286,7 +285,7 @@ describe('Test Identity (direct invocation)', function () { const evmIdentity = await buildIdentityHelper(context.ethersWallet.alice.address, 'Evm', context); const [evmValidation] = await buildValidations( context, - [aliceSubstrateIdentity], + [bobSubstrateIdentity], [evmIdentity], evmNonce, 'ethereum', @@ -302,7 +301,7 @@ describe('Test Identity (direct invocation)', function () { context.mrEnclave, context.api.createType('Index', twitterNonce), new PolkadotSigner(context.substrateWallet.bob), - aliceSubstrateIdentity, + bobSubstrateIdentity, twitterIdentity.toHex(), evmValidation.toHex(), evmNetworks.toHex(), @@ -437,7 +436,7 @@ describe('Test Identity (direct invocation)', function () { await assertFailedEvent(context, events, 'LinkIdentityFailed', 'IdentityAlreadyLinked'); }); - step('deactivating identity', async function () { + step('deactivating linked identities', async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; @@ -566,7 +565,7 @@ describe('Test Identity (direct invocation)', function () { await assertIdGraphHash(context, teeShieldingKey, aliceSubstrateIdentity, idGraph); }); - step('activating identity', async function () { + step('activating linked identities', async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; @@ -818,7 +817,7 @@ describe('Test Identity (direct invocation)', function () { assert.isTrue(v.isDispatch, `expected Dispatch, received ${v.type} instead`); assert.equal( v.asDispatch.toString(), - ' error: Module(ModuleError { index: 6, error: [5, 0, 0, 0], message: Some("WrongWeb3NetworkTypes") })' + ' error: Module(ModuleError { index: 6, error: [4, 0, 0, 0], message: Some("WrongWeb3NetworkTypes") })' ); }, res @@ -843,52 +842,135 @@ describe('Test Identity (direct invocation)', function () { 'idGraph should not be changed after setting incompatible network' ); }); - step('deactivating prime identity is disallowed', async function () { - let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); + + step('deactivate prime identity', async function () { + // deactivating prime identity should be possible and create the IDGraph if one doesn't exist already + const bobSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.bob), + context + ); + + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, bobSubstrateIdentity)).toNumber(); const getNextNonce = () => currentNonce++; - // nonce should be plus 1 why? - const nonce = getNextNonce() + 1; + const deactivateIdentityRequestParams: { + nonce: number; + identity: CorePrimitivesIdentity; + }[] = []; + + deactivateIdentityRequestParams.push({ + nonce: getNextNonce(), + identity: bobSubstrateIdentity, + }); + + const identityDeactivatedEvents: any[] = []; + const idGraphHashResults: any[] = []; + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [[[bobSubstrateIdentity, false]]]; + + for (const { nonce, identity } of deactivateIdentityRequestParams) { + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); + const deactivateIdentityCall = await createSignedTrustedCallDeactivateIdentity( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new PolkadotSigner(context.substrateWallet.bob), + bobSubstrateIdentity, + identity.toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); + idGraphHashResults.push( + await assertIdGraphMutationResult( + context, + teeShieldingKey, + bobSubstrateIdentity, + res, + 'DeactivateIdentityResult', + expectedIdGraphs[0] + ) + ); + expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); + await assertIsInSidechainBlock('deactivateIdentityCall', res); + + const events = (await eventsPromise).map(({ event }) => event); + events.forEach((event) => { + if (context.api.events.identityManagement.DeactivateIdentityFailed.is(event)) { + assert.fail(JSON.stringify(event.toHuman(), null, 4)); + } + if (context.api.events.identityManagement.IdentityDeactivated.is(event)) { + identityDeactivatedEvents.push(event); + } + }); + } + await assertIdGraphMutationEvent( + context, + new PolkadotSigner(context.substrateWallet.bob), + identityDeactivatedEvents, + idGraphHashResults, + 1 + ); + }); - // prime identity - const substratePrimeIdentity = await buildIdentityHelper( - u8aToHex(context.substrateWallet.alice.addressRaw), + step('setting identity networks for prime identity)', async function () { + const charlieSubstrateIdentity = await buildIdentityHelper( + u8aToHex(context.substrateWallet.charlie.addressRaw), 'Substrate', context ); + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, charlieSubstrateIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const nonce = getNextNonce(); + + const identityNetworksSetEvents: any[] = []; + const idGraphHashResults: any[] = []; + let expectedIdGraphs: [CorePrimitivesIdentity, boolean][][] = [[[charlieSubstrateIdentity, true]]]; + const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); - const deactivateIdentityCall = await createSignedTrustedCallDeactivateIdentity( + // we set the network to ['Litentry', 'Kusama'] + const setIdentityNetworksCall = await createSignedTrustedCallSetIdentityNetworks( context.api, context.mrEnclave, context.api.createType('Index', nonce), - new PolkadotSigner(context.substrateWallet.alice), - aliceSubstrateIdentity, - substratePrimeIdentity.toHex(), + new PolkadotSigner(context.substrateWallet.charlie), + charlieSubstrateIdentity, + charlieSubstrateIdentity.toHex(), + context.api.createType('Vec', ['Litentry', 'Kusama']).toHex(), context.api.createType('Option', aesKey).toHex(), requestIdentifier ); - const res = await sendRequestFromTrustedCall(context, teeShieldingKey, deactivateIdentityCall); - assert.isTrue(res.do_watch.isFalse); - assert.isTrue(res.status.asTrustedOperationStatus[0].isInvalid); - assertWorkerError( + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, setIdentityNetworksCall); + idGraphHashResults.push( + await assertIdGraphMutationResult( + context, + teeShieldingKey, + charlieSubstrateIdentity, + res, + 'ActivateIdentityResult', + expectedIdGraphs[0] + ) + ); + expectedIdGraphs = expectedIdGraphs.slice(1, expectedIdGraphs.length); + await assertIsInSidechainBlock('setIdentityNetworksCall', res); + + const events = (await eventsPromise).map(({ event }) => event); + events.forEach((event) => { + if (context.api.events.identityManagement.IdentityNetworksSet.is(event)) { + identityNetworksSetEvents.push(event); + } + }); + await assertIdGraphMutationEvent( context, - (v) => { - assert.isTrue( - v.isDeactivateIdentityFailed, - `expected DeactivateIdentityFailed, received ${v.type} instead` - ); - assert.isTrue( - v.asDeactivateIdentityFailed.isStfError, - `expected StfError, received ${v.asDeactivateIdentityFailed.type} instead` - ); - assert.equal(u8aToString(v.asDeactivateIdentityFailed.asStfError), 'DeactivatePrimeIdentityDisallowed'); - }, - res + new PolkadotSigner(context.substrateWallet.charlie), + identityNetworksSetEvents, + idGraphHashResults, + 1 ); - const events = await eventsPromise; - await assertFailedEvent(context, events, 'DeactivateIdentityFailed', 'DeactivatePrimeIdentityDisallowed'); }); }); diff --git a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts index 5a231493f8..281a8c9b63 100644 --- a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts @@ -420,31 +420,6 @@ describeLitentry('Test Identity', (context) => { await assertIdentityActivated(context, new PolkadotSigner(context.substrateWallet.alice), aliceActivatedEvents); }); - step('deactivate prime identity is disallowed', async function () { - // deactivate prime identity - const substratePrimeIdentity = await buildIdentityHelper( - u8aToHex(context.substrateWallet.alice.addressRaw), - 'Substrate', - context - ); - - const primeTxs = await buildIdentityTxs( - context, - context.substrateWallet.alice, - [substratePrimeIdentity], - 'deactivateIdentity' - ); - const primeEvents = await sendTxsWithUtility( - context, - context.substrateWallet.alice, - primeTxs, - 'identityManagement', - ['DeactivateIdentityFailed'] - ); - - await checkErrorDetail(primeEvents, 'DeactivatePrimeIdentityDisallowed'); - }); - step('deactivate error identities', async function () { // Deactivate a nonexistent identity // context.substrateWallet.alice has already deactivated all identities in step('deactivate identities') @@ -465,7 +440,8 @@ describeLitentry('Test Identity', (context) => { await checkErrorDetail(aliceDeactivatedEvents, 'IdentityNotExist'); - // deactivate a wrong identity (alice) for charlie + // deactivate a idneity for charlie, who is already linked to another IDGraph + // so creation of charlie's IDGraph should fail const charlieDeactivateTxs = await buildIdentityTxs( context, context.substrateWallet.charlie, @@ -480,7 +456,7 @@ describeLitentry('Test Identity', (context) => { ['DeactivateIdentityFailed'] ); - await checkErrorDetail(charlieDeactivateEvents, 'IdentityNotExist'); + await checkErrorDetail(charlieDeactivateEvents, 'IdentityAlreadyLinked'); }); step('exceeding IDGraph limit not allowed', async function () { From 43eb30874bcf7e9f22e358c0b34b0cefc490c63f Mon Sep 17 00:00:00 2001 From: Kai <7630809+Kailai-Wang@users.noreply.github.com> Date: Mon, 8 Jan 2024 16:24:19 +0100 Subject: [PATCH 43/43] Add additional fields to VC (#2364) * init * add block number * pass parentchain block number * error handling * fix compile errors * fix test * fix compile error --- Cargo.lock | 65 +++++++------------ .../app-libs/stf/src/trusted_call_litentry.rs | 12 ++-- tee-worker/enclave-runtime/Cargo.lock | 1 + .../litentry/core/assertion-build/src/a13.rs | 4 +- .../litentry/core/assertion-build/src/a2.rs | 3 +- .../litentry/core/assertion-build/src/a3.rs | 3 +- .../src/generic_discord_role.rs | 6 +- .../amount_holding/evm_amount_holding.rs | 9 ++- .../nft_holder/weirdo_ghost_gang_holder.rs | 3 +- .../litentry/core/credentials/src/lib.rs | 12 ++-- .../credentials/src/templates/credential.json | 3 + .../receiver/src/handler/assertion.rs | 9 ++- .../core/stf-task/receiver/src/mock.rs | 3 +- .../litentry/core/stf-task/sender/Cargo.toml | 4 +- .../litentry/core/stf-task/sender/src/lib.rs | 10 +-- .../lc-vc-task-receiver/src/lib.rs | 52 ++++++++++----- .../lc-vc-task-receiver/src/vc_handling.rs | 4 +- tee-worker/litentry/primitives/src/lib.rs | 2 +- .../consensus/aura/src/slot_proposer.rs | 1 + tee-worker/sidechain/state/Cargo.toml | 4 +- tee-worker/sidechain/state/src/lib.rs | 13 ++++ 21 files changed, 126 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd88f7ed4a..e9908df97b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1733,7 +1733,7 @@ name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -2896,7 +2896,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -3362,7 +3362,7 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -3489,7 +3489,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -4505,7 +4505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" dependencies = [ "heck", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -6191,7 +6191,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", @@ -6498,7 +6498,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -6610,7 +6610,7 @@ dependencies = [ "expander 0.0.6", "itertools", "petgraph", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -7860,7 +7860,7 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -8206,9 +8206,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -8221,11 +8221,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -9826,17 +9826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit 0.19.14", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" -dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit", ] [[package]] @@ -11042,7 +11032,7 @@ name = "sc-chain-spec-derive" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -12018,7 +12008,7 @@ name = "sc-tracing-proc-macro" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -12100,7 +12090,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -12645,7 +12635,7 @@ dependencies = [ "Inflector", "blake2", "expander 1.0.0", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -13117,7 +13107,7 @@ version = "6.0.0" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", @@ -14020,7 +14010,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.19.14", + "toml_edit", ] [[package]] @@ -14045,17 +14035,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap 2.0.0", - "toml_datetime", - "winnow", -] - [[package]] name = "tower" version = "0.4.13" @@ -14158,7 +14137,7 @@ version = "0.9.42" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "expander 2.0.0", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.46", 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 7b724d642c..597f4ce1e9 100644 --- a/tee-worker/app-libs/stf/src/trusted_call_litentry.rs +++ b/tee-worker/app-libs/stf/src/trusted_call_litentry.rs @@ -20,8 +20,8 @@ extern crate sgx_tstd as std; use super::*; use crate::{ helpers::{ - enclave_signer_account, ensure_enclave_signer_account, ensure_enclave_signer_or_self, - get_expected_raw_message, verify_web3_identity, + ensure_enclave_signer_account, ensure_enclave_signer_or_self, get_expected_raw_message, + verify_web3_identity, }, trusted_call_result::{LinkIdentityResult, TrustedCallResult}, AccountId, ShardIdentifier, StfError, StfResult, H256, @@ -30,7 +30,7 @@ use codec::Encode; use frame_support::{dispatch::UnfilteredDispatchable, ensure, sp_runtime::traits::One}; use ita_sgx_runtime::{ pallet_imt::{get_eligible_identities, IdentityContext}, - BlockNumber, RuntimeOrigin, System, + BlockNumber, Parentchain, RuntimeOrigin, System, }; use itp_node_api::metadata::NodeMetadataTrait; use itp_node_api_metadata::pallet_imp::IMPCallIndexes; @@ -185,14 +185,18 @@ impl TrustedCallSigned { StfError::RequestVCFailed(assertion, ErrorDetail::NoEligibleIdentity) ); + let parachain_block_number = Parentchain::block_number(); + let sidechain_block_number = System::block_number(); + let assertion_build: RequestType = AssertionBuildRequest { shard: *shard, signer, - enclave_account: enclave_signer_account(), who, assertion: assertion.clone(), identities, top_hash, + parachain_block_number, + sidechain_block_number, maybe_key, req_ext_hash, } diff --git a/tee-worker/enclave-runtime/Cargo.lock b/tee-worker/enclave-runtime/Cargo.lock index 2bd785911c..277b721f63 100644 --- a/tee-worker/enclave-runtime/Cargo.lock +++ b/tee-worker/enclave-runtime/Cargo.lock @@ -2810,6 +2810,7 @@ dependencies = [ "sgx_tstd", "sp-core", "sp-io", + "sp-runtime", "thiserror", ] diff --git a/tee-worker/litentry/core/assertion-build/src/a13.rs b/tee-worker/litentry/core/assertion-build/src/a13.rs index e93d06599b..b89026ba07 100644 --- a/tee-worker/litentry/core/assertion-build/src/a13.rs +++ b/tee-worker/litentry/core/assertion-build/src/a13.rs @@ -47,9 +47,7 @@ pub fn build( .collect(); // if the signer can't be found in the delegatee list OR not the enclave account - if !(keys.iter().any(|k| k.ends_with(hex::encode(&req.signer).as_str())) - || req.signer == req.enclave_account) - { + if !(keys.iter().any(|k| k.ends_with(hex::encode(&req.signer).as_str()))) { return Err(Error::RequestVCFailed( Assertion::A13(who.clone()), ErrorDetail::UnauthorizedSigner, diff --git a/tee-worker/litentry/core/assertion-build/src/a2.rs b/tee-worker/litentry/core/assertion-build/src/a2.rs index 270a0cb969..60f9420934 100644 --- a/tee-worker/litentry/core/assertion-build/src/a2.rs +++ b/tee-worker/litentry/core/assertion-build/src/a2.rs @@ -103,11 +103,12 @@ mod tests { let req = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::A2(guild_id.clone()), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; diff --git a/tee-worker/litentry/core/assertion-build/src/a3.rs b/tee-worker/litentry/core/assertion-build/src/a3.rs index 74d3bf8a92..b0209afdab 100644 --- a/tee-worker/litentry/core/assertion-build/src/a3.rs +++ b/tee-worker/litentry/core/assertion-build/src/a3.rs @@ -136,11 +136,12 @@ mod tests { let req = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::A3(guild_id.clone(), channel_id.clone(), role_id.clone()), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; diff --git a/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs b/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs index fafa1bb7ba..3b16bebcea 100644 --- a/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs +++ b/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs @@ -125,13 +125,14 @@ mod tests { let req: AssertionBuildRequest = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::GenericDiscordRole(GenericDiscordRoleType::Contest( ContestType::Legend, )), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; @@ -167,13 +168,14 @@ mod tests { let req: AssertionBuildRequest = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::GenericDiscordRole(GenericDiscordRoleType::SoraQuiz( SoraQuizType::Attendee, )), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs index 3ec696032e..30759ff7a7 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs @@ -184,11 +184,12 @@ mod tests { let req: AssertionBuildRequest = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::EVMAmountHolding(EVMTokenType::Ton), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; @@ -237,11 +238,12 @@ mod tests { let req: AssertionBuildRequest = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::EVMAmountHolding(EVMTokenType::Ton), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; @@ -290,11 +292,12 @@ mod tests { let req: AssertionBuildRequest = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::EVMAmountHolding(EVMTokenType::Ton), identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs index af9b98e756..f4d3b13eb6 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs @@ -137,11 +137,12 @@ mod tests { let req: AssertionBuildRequest = AssertionBuildRequest { shard: ShardIdentifier::default(), signer: AccountId::from([0; 32]), - enclave_account: AccountId::from([0; 32]), who: AccountId::from([0; 32]).into(), assertion: Assertion::WeirdoGhostGangHolder, identities, top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, maybe_key: None, req_ext_hash: Default::default(), }; diff --git a/tee-worker/litentry/core/credentials/src/lib.rs b/tee-worker/litentry/core/credentials/src/lib.rs index 0e0d28faf6..d8fa42071a 100644 --- a/tee-worker/litentry/core/credentials/src/lib.rs +++ b/tee-worker/litentry/core/credentials/src/lib.rs @@ -38,9 +38,9 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam use codec::{Decode, Encode}; use itp_stf_primitives::types::ShardIdentifier; use itp_time_utils::{from_iso8601, now_as_iso8601}; -use itp_types::AccountId; +use itp_types::{AccountId, BlockNumber as SidechainBlockNumber}; use itp_utils::stringify::account_id_to_string; -use litentry_primitives::{Identity, Web3Network}; +use litentry_primitives::{Identity, ParentchainBlockNumber, Web3Network}; use log::*; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; @@ -141,6 +141,7 @@ pub struct CredentialSubject { pub description: String, #[serde(rename = "type")] pub types: String, + pub assertion_text: String, /// (Optional) Data source definitions for trusted data providers #[serde(skip_serializing_if = "Option::is_none")] pub data_source: Option>, @@ -158,10 +159,6 @@ impl CredentialSubject { pub fn is_empty(&self) -> bool { self.id.is_empty() } - - pub fn set_endpoint(&mut self, endpoint: String) { - self.endpoint = endpoint; - } } /// Verifiable Credentials JSON Schema 2022, W3C, 8 November 2022 @@ -224,6 +221,9 @@ pub struct Credential { /// The TEE enclave who issued the credential pub issuer: Issuer, pub issuance_date: String, + /// The parachain and sidechain block number on which the state is read and calculated + pub parachain_block_number: ParentchainBlockNumber, + pub sidechain_block_number: SidechainBlockNumber, /// Digital proof with the signature of Issuer #[serde(skip_serializing_if = "Option::is_none")] pub proof: Option, diff --git a/tee-worker/litentry/core/credentials/src/templates/credential.json b/tee-worker/litentry/core/credentials/src/templates/credential.json index e642e3122e..c26af00bf1 100644 --- a/tee-worker/litentry/core/credentials/src/templates/credential.json +++ b/tee-worker/litentry/core/credentials/src/templates/credential.json @@ -14,10 +14,13 @@ }, "subject":"", "issuanceDate":"", + "parachainBlockNumber": 0, + "sidechainBlockNumber": 0, "credentialSubject":{ "id":"", "description":"", "type":"", + "assertionText":"", "assertions":[ ], diff --git a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs index e520c5189c..3a720057d2 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs @@ -146,11 +146,14 @@ where ) })?; + credential.parachain_block_number = self.req.parachain_block_number; + credential.sidechain_block_number = self.req.sidechain_block_number; + let data_provider_config = DataProviderConfigReader::read() .map_err(|e| VCMPError::RequestVCFailed(self.req.assertion.clone(), e))?; - credential - .credential_subject - .set_endpoint(data_provider_config.credential_endpoint); + credential.credential_subject.endpoint = data_provider_config.credential_endpoint; + + credential.credential_subject.assertion_text = format!("{:?}", self.req.assertion); credential.issuer.id = Identity::Substrate(enclave_account.into()).to_did().map_err(|e| { diff --git a/tee-worker/litentry/core/stf-task/receiver/src/mock.rs b/tee-worker/litentry/core/stf-task/receiver/src/mock.rs index 5417849d82..452411ea4d 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/mock.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/mock.rs @@ -37,11 +37,12 @@ pub fn construct_assertion_request(assertion: Assertion) -> RequestType { let request: RequestType = AssertionBuildRequest { shard, signer: public_id.into(), - enclave_account: public_id.into(), who: public_id.into(), assertion, identities: vec![], maybe_key: Some(key), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, top_hash: H256::zero(), req_ext_hash: H256::zero(), } diff --git a/tee-worker/litentry/core/stf-task/sender/Cargo.toml b/tee-worker/litentry/core/stf-task/sender/Cargo.toml index 04d55f4a85..86e47cd01c 100644 --- a/tee-worker/litentry/core/stf-task/sender/Cargo.toml +++ b/tee-worker/litentry/core/stf-task/sender/Cargo.toml @@ -27,7 +27,7 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "polkad itp-types = { path = "../../../../core-primitives/types", default-features = false } # litentry -itp-stf-primitives = { default-features = false, path = "../../../../core-primitives/stf-primitives" } +itp-stf-primitives = { path = "../../../../core-primitives/stf-primitives", default-features = false } litentry-primitives = { path = "../../../primitives", default-features = false } [features] @@ -44,4 +44,6 @@ std = [ "thiserror", "url", "itp-types/std", + "itp-stf-primitives/std", + "litentry-primitives/std", ] diff --git a/tee-worker/litentry/core/stf-task/sender/src/lib.rs b/tee-worker/litentry/core/stf-task/sender/src/lib.rs index a4ff25aac3..96042e12af 100644 --- a/tee-worker/litentry/core/stf-task/sender/src/lib.rs +++ b/tee-worker/litentry/core/stf-task/sender/src/lib.rs @@ -30,14 +30,15 @@ pub mod sgx_reexport_prelude { pub use url_sgx as url; } -use itp_types::{AccountId, H256}; +// TODO: the sidechain block number type is chaotic from upstream +use itp_types::{AccountId, BlockNumber as SidechainBlockNumber, H256}; pub mod error; pub mod stf_task_sender; use codec::{Decode, Encode}; pub use error::Result; -use itp_stf_primitives::types::ShardIdentifier; use litentry_primitives::{ - Assertion, Identity, IdentityNetworkTuple, RequestAesKey, Web2ValidationData, Web3Network, + Assertion, Identity, IdentityNetworkTuple, ParentchainBlockNumber, RequestAesKey, + ShardIdentifier, Web2ValidationData, Web3Network, }; use sp_runtime::traits::ConstU32; use sp_std::prelude::Vec; @@ -85,11 +86,12 @@ pub type MaxIdentityLength = ConstU32<64>; pub struct AssertionBuildRequest { pub shard: ShardIdentifier, pub signer: AccountId, - pub enclave_account: AccountId, pub who: Identity, pub assertion: Assertion, pub identities: Vec, pub top_hash: H256, + pub parachain_block_number: ParentchainBlockNumber, + pub sidechain_block_number: SidechainBlockNumber, pub maybe_key: Option, pub req_ext_hash: H256, } diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs index 7ee8aaa1a8..4155fd20e5 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs @@ -25,8 +25,8 @@ use frame_support::{ensure, sp_runtime::traits::One}; pub use futures; use ita_sgx_runtime::{pallet_imt::get_eligible_identities, BlockNumber, Hash, Runtime}; use ita_stf::{ - aes_encrypt_default, helpers::enclave_signer_account, trusted_call_result::RequestVCResult, - Getter, OpaqueCall, TrustedCall, TrustedCallSigned, TrustedOperation, H256, + aes_encrypt_default, trusted_call_result::RequestVCResult, Getter, OpaqueCall, TrustedCall, + TrustedCallSigned, TrustedOperation, H256, }; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ @@ -37,15 +37,16 @@ use itp_sgx_crypto::{ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; use itp_sgx_externalities::SgxExternalitiesTrait; use itp_stf_executor::traits::StfEnclaveSigning; use itp_stf_state_handler::handle_state::HandleState; -use itp_storage::{storage_map_key, StorageHasher}; +use itp_storage::{storage_map_key, storage_value_key, StorageHasher}; use itp_top_pool_author::traits::AuthorApi; -use itp_types::parentchain::ParentchainId; +use itp_types::{parentchain::ParentchainId, BlockNumber as SidechainBlockNumber}; use lc_stf_task_receiver::StfTaskContext; use lc_stf_task_sender::AssertionBuildRequest; use lc_vc_task_sender::init_vc_task_sender_storage; use litentry_primitives::{ - aes_decrypt, AesOutput, Identity, IdentityNetworkTuple, RequestAesKey, ShardIdentifier, + aes_decrypt, AesOutput, Identity, ParentchainBlockNumber, RequestAesKey, ShardIdentifier, }; +use log::*; use pallet_identity_management_tee::{identity_context::sort_id_graph, IdentityContext}; use std::{ format, @@ -89,7 +90,7 @@ pub fn run_vc_handler_runner( extrinsic_factory_pool, node_metadata_repo_pool, )) { - log::warn!("Unable to submit response back to the handler: {:?}", e); + warn!("Unable to submit response back to the handler: {:?}", e); } }); } @@ -133,11 +134,11 @@ where .to_call() .ok_or_else(|| "Failed to convert trusted operation to trusted call".to_string())?; - if let TrustedCall::request_vc(signer, who, assertion, maybe_key, _hash) = + if let TrustedCall::request_vc(signer, who, assertion, maybe_key, req_ext_hash) = trusted_call.call.clone() { let key = maybe_key.ok_or_else(|| "User shielding key not provided".to_string())?; - let identities: Vec = context + let (identities, parachain_block_number, sidechain_block_number) = context .state_handler .execute_on_current(&shard, |state, _| { let prefix_key = storage_map_key( @@ -146,8 +147,11 @@ where &who, &StorageHasher::Blake2_128Concat, ); - let mut id_graph = - state.iter_prefix::>(&prefix_key).unwrap(); + + // `None` means empty IDGraph, thus `unwrap_or_default` + let mut id_graph = state + .iter_prefix::>(&prefix_key) + .unwrap_or_default(); // Sorts the IDGraph in place sort_id_graph::(&mut id_graph); @@ -160,8 +164,22 @@ where )); } + // should never be `None`, but use `unwrap_or_default` to not panic + let parachain_block_number = state + .get(&storage_value_key("Parentchain", "Number")) + .and_then(|v| ParentchainBlockNumber::decode(&mut v.as_slice()).ok()) + .unwrap_or_default(); + let sidechain_block_number = state + .get(&storage_value_key("System", "Number")) + .and_then(|v| SidechainBlockNumber::decode(&mut v.as_slice()).ok()) + .unwrap_or_default(); + let assertion_networks = assertion.clone().get_supported_web3networks(); - get_eligible_identities(id_graph, assertion_networks) + ( + get_eligible_identities(id_graph, assertion_networks), + parachain_block_number, + sidechain_block_number, + ) }) .map_err(|e| format!("Failed to fetch sidechain data due to: {:?}", e))?; @@ -171,20 +189,20 @@ where .to_account_id() .ok_or_else(|| "Invalid signer account, failed to convert".to_string())?; - let assertion_build: AssertionBuildRequest = AssertionBuildRequest { + let req = AssertionBuildRequest { shard, signer, - enclave_account: enclave_signer_account(), who, assertion, identities, - maybe_key, top_hash: H256::zero(), - req_ext_hash: H256::zero(), + parachain_block_number, + sidechain_block_number, + maybe_key, + req_ext_hash, }; - let vc_request_handler = - VCRequestHandler { req: assertion_build, context: context.clone() }; + let vc_request_handler = VCRequestHandler { req, context: context.clone() }; let response = vc_request_handler .process() .map_err(|e| format!("Failed to build assertion due to: {:?}", e))?; diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs index 63e8adb99a..1ad285938d 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs @@ -124,9 +124,7 @@ where let data_provider_config = DataProviderConfigReader::read() .map_err(|e| VCMPError::RequestVCFailed(self.req.assertion.clone(), e))?; - credential - .credential_subject - .set_endpoint(data_provider_config.credential_endpoint); + credential.credential_subject.endpoint = data_provider_config.credential_endpoint; credential.issuer.id = Identity::Substrate(enclave_account.into()).to_did().map_err(|e| { diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index 6a95622b8b..9d8dbb7426 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -64,7 +64,7 @@ use sp_io::{ }; use sp_runtime::traits::Verify; use std::string::{String, ToString}; -pub use teerex_primitives::{decl_rsa_request, ShardIdentifier}; +pub use teerex_primitives::{decl_rsa_request, ShardIdentifier, SidechainBlockNumber}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; diff --git a/tee-worker/sidechain/consensus/aura/src/slot_proposer.rs b/tee-worker/sidechain/consensus/aura/src/slot_proposer.rs index 0a893d9a32..2baea76519 100644 --- a/tee-worker/sidechain/consensus/aura/src/slot_proposer.rs +++ b/tee-worker/sidechain/consensus/aura/src/slot_proposer.rs @@ -137,6 +137,7 @@ impl< sidechain_db .set_block_number(&sidechain_db.get_block_number().map_or(1, |n| n + 1)); sidechain_db.set_timestamp(&now_as_millis()); + sidechain_db.set_parentchain_block_number(latest_parentchain_header); sidechain_db }, ) diff --git a/tee-worker/sidechain/state/Cargo.toml b/tee-worker/sidechain/state/Cargo.toml index 1b7207555e..538fb34c50 100644 --- a/tee-worker/sidechain/state/Cargo.toml +++ b/tee-worker/sidechain/state/Cargo.toml @@ -26,9 +26,6 @@ sp-io = { optional = true, default-features = false, features = ["disable_oom", # substrate deps sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# test deps -[dev-dependencies] sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } [features] @@ -45,6 +42,7 @@ std = [ # optional std crates "codec/std", "thiserror", + "sp-runtime/std", ] sgx = [ # teaclave diff --git a/tee-worker/sidechain/state/src/lib.rs b/tee-worker/sidechain/state/src/lib.rs index 7517f72c27..01f5e086ec 100644 --- a/tee-worker/sidechain/state/src/lib.rs +++ b/tee-worker/sidechain/state/src/lib.rs @@ -42,6 +42,7 @@ use its_primitives::{ }; use sp_core::H256; use sp_io::KillStorageResult; +use sp_runtime::traits::Header as ParentchainHeaderTrait; /// Contains the necessary data to update the `SidechainDB` when importing a `SidechainBlock`. #[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] @@ -160,6 +161,14 @@ pub trait SidechainSystemExt { /// Resets the events. fn reset_events(&mut self); + + /// Litentry: set the parentchain block number from the parentchain header + /// The reasons to put it here instead of calling `ParentchainPalletInterface::update_parentchain_block` somewhere are: + /// 1. The Stf::update_parentchain_block is too heavy weighted, where the whole state is loaded upon each parentchain + /// block import - btw it's not reachable for now as `storage_hashes_to_update_on_block` is always empty + /// 2. It represents the parentchain block number on which the current sidechain block is built, it's more natural to + /// call it in the state preprocessing before proposing a sidechain block + fn set_parentchain_block_number(&mut self, header: &PH); } impl SidechainSystemExt for T { @@ -192,4 +201,8 @@ impl SidechainSystemExt for T { self.clear_with_name("System", "EventCount"); self.clear_prefix_with_name("System", "EventTopics"); } + + fn set_parentchain_block_number(&mut self, header: &PH) { + self.set_with_name("Parentchain", "Number", header.number()) + } }