Skip to content

Commit

Permalink
feat: P-431 add karat dao user vc (#2467)
Browse files Browse the repository at this point in the history
Co-authored-by: higherordertech <higherordertech>
Co-authored-by: BillyWooo <thedreamofbilly@gmail.com>
  • Loading branch information
higherordertech and BillyWooo committed Feb 7, 2024
1 parent 01d88ed commit 9e876e5
Show file tree
Hide file tree
Showing 23 changed files with 722 additions and 8 deletions.
8 changes: 6 additions & 2 deletions primitives/core/src/assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

use crate::{
all_web3networks, AccountId, BnbDigitDomainType, BoundedWeb3Network, EVMTokenType,
GenericDiscordRoleType, OneBlockCourseType, VIP3MembershipCardLevel, Web3Network,
Web3TokenType,
GenericDiscordRoleType, OneBlockCourseType, PlatformUserType, VIP3MembershipCardLevel,
Web3Network, Web3TokenType,
};
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
Expand Down Expand Up @@ -261,6 +261,9 @@ pub enum Assertion {

#[codec(index = 24)]
TokenHoldingAmount(Web3TokenType),

#[codec(index = 25)]
PlatformUser(PlatformUserType),
}

impl Assertion {
Expand Down Expand Up @@ -309,6 +312,7 @@ impl Assertion {
// no web3 network is allowed
Self::A2(..) | Self::A3(..) | Self::A6 | Self::GenericDiscordRole(..) => vec![],
Self::TokenHoldingAmount(t_type) => t_type.get_supported_networks(),
Self::PlatformUser(p_type) => p_type.get_supported_networks(),
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions primitives/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ pub use evm_amount_holding::*;
mod web3_token;
pub use web3_token::*;

mod platform_user;
pub use platform_user::*;

/// Common types of parachains.
mod types {
use sp_runtime::{
Expand Down
35 changes: 35 additions & 0 deletions primitives/core/src/platform_user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2020-2024 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 <https://www.gnu.org/licenses/>.

use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_std::vec::Vec;

use crate::{all_evm_web3networks, Web3Network};

#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)]
pub enum PlatformUserType {
#[codec(index = 0)]
KaratDaoUser,
}

impl PlatformUserType {
pub fn get_supported_networks(&self) -> Vec<Web3Network> {
match self {
Self::KaratDaoUser => all_evm_web3networks(),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ use litentry_primitives::{
AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear,
AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams,
AchainableToken, Assertion, BoundedWeb3Network, ContestType, EVMTokenType,
GenericDiscordRoleType, Identity, OneBlockCourseType, ParameterString, RequestAesKey,
SoraQuizType, VIP3MembershipCardLevel, Web3Network, Web3TokenType, REQUEST_AES_KEY_LEN,
GenericDiscordRoleType, Identity, OneBlockCourseType, ParameterString, PlatformUserType,
RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network, Web3TokenType,
REQUEST_AES_KEY_LEN,
};
use sp_core::Pair;

Expand Down Expand Up @@ -108,6 +109,8 @@ pub enum Command {
BRC20AmountHolder,
#[clap(subcommand)]
TokenHoldingAmount(TokenHoldingAmountCommand),
#[clap(subcommand)]
PlatformUser(PlatformUserCommand),
}

#[derive(Args, Debug)]
Expand Down Expand Up @@ -220,6 +223,11 @@ pub enum TokenHoldingAmountCommand {
Trx,
}

#[derive(Subcommand, Debug)]
pub enum PlatformUserCommand {
KaratDaoUser,
}

// I haven't found a good way to use common args for subcommands
#[derive(Args, Debug)]
pub struct AmountHoldingArg {
Expand Down Expand Up @@ -544,6 +552,10 @@ impl RequestVcCommand {
TokenHoldingAmountCommand::Ton => Assertion::TokenHoldingAmount(Web3TokenType::Ton),
TokenHoldingAmountCommand::Trx => Assertion::TokenHoldingAmount(Web3TokenType::Trx),
},
Command::PlatformUser(arg) => match arg {
PlatformUserCommand::KaratDaoUser =>
Assertion::PlatformUser(PlatformUserType::KaratDaoUser),
},
};

let key = Self::random_aes_key();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use litentry_primitives::{
AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear,
AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams,
AchainableToken, Assertion, ContestType, EVMTokenType, GenericDiscordRoleType, Identity,
OneBlockCourseType, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network,
Web3TokenType, REQUEST_AES_KEY_LEN,
OneBlockCourseType, PlatformUserType, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel,
Web3Network, Web3TokenType, REQUEST_AES_KEY_LEN,
};
use sp_core::Pair;

Expand Down Expand Up @@ -293,6 +293,10 @@ impl RequestVcDirectCommand {
TokenHoldingAmountCommand::Ton => Assertion::TokenHoldingAmount(Web3TokenType::Ton),
TokenHoldingAmountCommand::Trx => Assertion::TokenHoldingAmount(Web3TokenType::Trx),
},
Command::PlatformUser(arg) => match arg {
PlatformUserCommand::KaratDaoUser =>
Assertion::PlatformUser(PlatformUserType::KaratDaoUser),
},
};

let key: [u8; 32] = Self::random_aes_key();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default {
BRC20AmountHolder: "Null",
CyptoSummary: "Null",
TokenHoldingAmount: "Web3TokenType",
PlatformUser: "PlatformUserType",
},
},
AssertionSupportedNetwork: {
Expand Down Expand Up @@ -173,5 +174,9 @@ export default {
"Trx",
],
},
// PlatformUserType
PlatformUserType: {
_enum: ["KaratDaoUser"],
},
},
};
1 change: 1 addition & 0 deletions tee-worker/litentry/core/assertion-build-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ use lc_assertion_build::{transpose_identity, Result};
use lc_service::DataProviderConfig;
use log::*;

pub mod platform_user;
pub mod token_holding_amount;
180 changes: 180 additions & 0 deletions tee-worker/litentry/core/assertion-build-v2/src/platform_user/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright 2020-2024 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 <https://www.gnu.org/licenses/>.

#[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 std::collections::HashSet;

use lc_credentials_v2::{platform_user::PlatformUserAssertionUpdate, Credential};
use lc_service::platform_user::is_user;
use lc_stf_task_sender::AssertionBuildRequest;
use litentry_primitives::{PlatformUserType, Web3Network};
use log::debug;

use crate::*;

pub fn build(
req: &AssertionBuildRequest,
platform_user_type: PlatformUserType,
data_provider_config: &DataProviderConfig,
) -> Result<Credential> {
debug!("platform user: {:?}", platform_user_type);

let identities: Vec<(Web3Network, Vec<String>)> = transpose_identity(&req.identities);
let addresses: Vec<String> = identities
.into_iter()
.flat_map(|(_, addresses)| addresses.into_iter())
.collect::<HashSet<String>>()
.into_iter()
.collect();

let result =
is_user(platform_user_type.clone(), addresses, data_provider_config).map_err(|e| {
Error::RequestVCFailed(
Assertion::PlatformUser(platform_user_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_platform_user_assertion(platform_user_type, value);
Ok(credential_unsigned)
},
Err(e) => {
error!("Generate unsigned credential failed {:?}", e);
Err(Error::RequestVCFailed(
Assertion::PlatformUser(platform_user_type),
e.into_error_detail(),
))
},
},
Err(e) => Err(e),
}
}

#[cfg(test)]
mod tests {
use super::*;
use itp_stf_primitives::types::ShardIdentifier;
use itp_types::AccountId;
use lc_common::platform_user::PlatformName;
use lc_credentials_v2::assertion_logic::{AssertionLogic, Op};
use lc_mock_server::run;
use litentry_hex_utils::decode_hex;
use litentry_primitives::{Identity, IdentityNetworkTuple};

fn init() -> DataProviderConfig {
let _ = env_logger::builder().is_test(true).try_init();
let url = run(0).unwrap() + "/karat_dao/";

let mut config = DataProviderConfig::new();
config.set_karat_dao_api_url(url);
config
}

fn crate_assertion_build_request(
platform_user_type: PlatformUserType,
identities: Vec<IdentityNetworkTuple>,
) -> AssertionBuildRequest {
AssertionBuildRequest {
shard: ShardIdentifier::default(),
signer: AccountId::from([0; 32]),
who: AccountId::from([0; 32]).into(),
assertion: Assertion::PlatformUser(platform_user_type),
identities,
top_hash: Default::default(),
parachain_block_number: 0u32,
sidechain_block_number: 0u32,
maybe_key: None,
should_create_id_graph: false,
req_ext_hash: Default::default(),
}
}

fn build_and_assert_result(
identities: Vec<IdentityNetworkTuple>,
platform_user_type: PlatformUserType,
assertion_value: bool,
data_provider_config: &DataProviderConfig,
) {
let req = crate_assertion_build_request(PlatformUserType::KaratDaoUser, identities);

match build(&req, platform_user_type.clone(), &data_provider_config) {
Ok(credential) => {
log::info!("build karat dao user done");
assert_eq!(
*(credential.credential_subject.assertions.first().unwrap()),
AssertionLogic::And {
items: vec![Box::new(AssertionLogic::Item {
src: "$platform".into(),
op: Op::Equal,
dst: platform_user_type.get_platform_name().into()
})]
}
);
assert_eq!(
*(credential.credential_subject.values.first().unwrap()),
assertion_value
);
},
Err(e) => {
panic!("build karat dao user failed with error {:?}", e);
},
}
}

#[test]
fn build_karat_dao_user_works() {
let data_provider_config = init();
let mut address =
decode_hex("0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee".as_bytes().to_vec())
.unwrap()
.as_slice()
.try_into()
.unwrap();
let mut identities: Vec<IdentityNetworkTuple> =
vec![(Identity::Evm(address), vec![Web3Network::Ethereum])];

build_and_assert_result(
identities,
PlatformUserType::KaratDaoUser,
true,
&data_provider_config,
);

address = decode_hex("0x75438d34c9125839c8b08d21b7f3167281659e7c".as_bytes().to_vec())
.unwrap()
.as_slice()
.try_into()
.unwrap();
identities = vec![(Identity::Evm(address), vec![Web3Network::Bsc, Web3Network::Ethereum])];

build_and_assert_result(
identities,
PlatformUserType::KaratDaoUser,
false,
&data_provider_config,
);
}
}
1 change: 1 addition & 0 deletions tee-worker/litentry/core/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extern crate sgx_tstd as std;

use litentry_primitives::Web3Network;

pub mod platform_user;
pub mod web3_token;

pub fn web3_network_to_chain(network: &Web3Network) -> &'static str {
Expand Down
35 changes: 35 additions & 0 deletions tee-worker/litentry/core/common/src/platform_user/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2020-2024 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 <https://www.gnu.org/licenses/>.

#[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 litentry_primitives::PlatformUserType;

pub trait PlatformName {
fn get_platform_name(&self) -> &'static str;
}

impl PlatformName for PlatformUserType {
fn get_platform_name(&self) -> &'static str {
match self {
Self::KaratDaoUser => "KaratDao",
}
}
}
1 change: 1 addition & 0 deletions tee-worker/litentry/core/credentials-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam
// TODO migration to v2 in the future
pub use lc_credentials::{assertion_logic, Credential};

pub mod platform_user;
pub mod token_holding_amount;

0 comments on commit 9e876e5

Please sign in to comment.