diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock
index 0a9fd4f4ea..03a9dff942 100644
--- a/tee-worker/Cargo.lock
+++ b/tee-worker/Cargo.lock
@@ -875,7 +875,7 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "core-primitives"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"base58",
"frame-support",
@@ -4988,7 +4988,7 @@ dependencies = [
[[package]]
name = "litentry-hex-utils"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"hex",
]
@@ -5000,7 +5000,7 @@ version = "0.1.0"
[[package]]
name = "litentry-macros"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
[[package]]
name = "litentry-primitives"
@@ -5030,7 +5030,7 @@ dependencies = [
[[package]]
name = "litentry-proc-macros"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"cargo_toml",
"proc-macro2",
@@ -6016,7 +6016,7 @@ dependencies = [
[[package]]
name = "pallet-parachain-staking"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"core-primitives",
"frame-support",
@@ -6083,7 +6083,7 @@ dependencies = [
[[package]]
name = "pallet-teebag"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"base64 0.13.1",
"chrono 0.4.38",
diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_subcommands.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_subcommands.rs
index 832b8636f8..be58a6653e 100644
--- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_subcommands.rs
+++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_subcommands.rs
@@ -53,6 +53,7 @@ pub enum Command {
#[clap(subcommand)]
NftHolder(NftHolderCommand),
Dynamic(DynamicArg),
+ LinkedIdentities,
}
#[derive(Args, Debug)]
@@ -492,6 +493,7 @@ impl Command {
return_log: arg.return_log.unwrap_or_default(),
}))
},
+ Command::LinkedIdentities => Ok(LinkedIdentities),
}
}
}
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 210d4038ea..bc8c4ad89d 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
@@ -35,6 +35,7 @@ export default {
PlatformUser: "PlatformUserType",
NftHolder: "Web3NftType",
Dynamic: "DynamicParams",
+ LinkedIdentities: "Null",
},
},
AssertionSupportedNetwork: {
diff --git a/tee-worker/enclave-runtime/Cargo.lock b/tee-worker/enclave-runtime/Cargo.lock
index 3cb495b83b..7146d0862a 100644
--- a/tee-worker/enclave-runtime/Cargo.lock
+++ b/tee-worker/enclave-runtime/Cargo.lock
@@ -600,7 +600,7 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "core-primitives"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"base58",
"frame-support",
@@ -3358,7 +3358,7 @@ dependencies = [
[[package]]
name = "litentry-hex-utils"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"hex",
]
@@ -3370,7 +3370,7 @@ version = "0.1.0"
[[package]]
name = "litentry-macros"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
[[package]]
name = "litentry-primitives"
@@ -3408,7 +3408,7 @@ dependencies = [
[[package]]
name = "litentry-proc-macros"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"cargo_toml",
"proc-macro2",
@@ -3801,7 +3801,7 @@ dependencies = [
[[package]]
name = "pallet-parachain-staking"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"core-primitives",
"frame-support",
@@ -3868,7 +3868,7 @@ dependencies = [
[[package]]
name = "pallet-teebag"
version = "0.1.0"
-source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#ea133d42f915d6e3cbbc51304f534d0b9f42e5d3"
+source = "git+https://github.com/litentry/litentry-parachain?branch=release-v0.9.19#d2249ff0f8a4b20e590c5cd2c0f68baa79e13aa4"
dependencies = [
"base64 0.13.1",
"chrono 0.4.31",
diff --git a/tee-worker/litentry/core/assertion-build-v2/src/lib.rs b/tee-worker/litentry/core/assertion-build-v2/src/lib.rs
index ef5b56095d..1124633f46 100644
--- a/tee-worker/litentry/core/assertion-build-v2/src/lib.rs
+++ b/tee-worker/litentry/core/assertion-build-v2/src/lib.rs
@@ -41,6 +41,7 @@ use lc_assertion_build::{transpose_identity, Result};
use lc_service::DataProviderConfig;
use log::*;
+pub mod linked_identities;
pub mod nft_holder;
pub mod platform_user;
pub mod token_holding_amount;
diff --git a/tee-worker/litentry/core/assertion-build-v2/src/linked_identities/mod.rs b/tee-worker/litentry/core/assertion-build-v2/src/linked_identities/mod.rs
new file mode 100644
index 0000000000..0e925a4a3a
--- /dev/null
+++ b/tee-worker/litentry/core/assertion-build-v2/src/linked_identities/mod.rs
@@ -0,0 +1,110 @@
+// 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 .
+
+#[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_v2::{
+ linked_identities::LinkedIdentitiesAssertionUpdate, Credential, IssuerRuntimeVersion,
+};
+use lc_stf_task_sender::AssertionBuildRequest;
+
+use crate::*;
+
+pub fn build(req: &AssertionBuildRequest) -> Result {
+ let identities = req
+ .identities
+ .iter()
+ .filter_map(|identity| identity.0.to_did().ok())
+ .collect::>();
+
+ let runtime_version = IssuerRuntimeVersion {
+ parachain: req.parachain_runtime_version,
+ sidechain: req.sidechain_runtime_version,
+ };
+
+ match Credential::new(&req.who, &req.shard, &runtime_version) {
+ Ok(mut credential_unsigned) => {
+ credential_unsigned.update_linked_identities_assertion(identities);
+ Ok(credential_unsigned)
+ },
+ Err(e) => {
+ error!("Generate unsigned credential failed {:?}", e);
+ Err(Error::RequestVCFailed(Assertion::LinkedIdentities, e.into_error_detail()))
+ },
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use itp_stf_primitives::types::ShardIdentifier;
+ use itp_types::AccountId;
+ use lc_credentials_v2::assertion_logic::{AssertionLogic, Op};
+ use litentry_primitives::{Identity, IdentityNetworkTuple, IdentityString};
+
+ #[test]
+ fn build_linked_identities_works() {
+ let mut identities: Vec = vec![
+ (Identity::Substrate([0; 32].into()), vec![]),
+ (Identity::Evm([0; 20].into()), vec![]),
+ (Identity::Bitcoin([0; 33].into()), vec![]),
+ (Identity::Solana([0; 32].into()), vec![]),
+ (Identity::Discord(IdentityString::new("discord_handle".as_bytes().to_vec())), vec![]),
+ (Identity::Twitter(IdentityString::new("twitter_handle".as_bytes().to_vec())), vec![]),
+ (Identity::Github(IdentityString::new("github_handle".as_bytes().to_vec())), vec![]),
+ ];
+
+ let req = AssertionBuildRequest {
+ shard: ShardIdentifier::default(),
+ signer: AccountId::from([0; 32]),
+ who: AccountId::from([0; 32]).into(),
+ assertion: Assertion::LinkedIdentities,
+ identities,
+ top_hash: Default::default(),
+ parachain_block_number: 0u32,
+ sidechain_block_number: 0u32,
+ parachain_runtime_version: 0u32,
+ sidechain_runtime_version: 0u32,
+ maybe_key: None,
+ should_create_id_graph: false,
+ req_ext_hash: Default::default(),
+ };
+
+ match build(&req) {
+ Ok(credential) => {
+ log::info!("build linked_identities done");
+ assert_eq!(
+ *(credential.credential_subject.assertions.first().unwrap()),
+ AssertionLogic::And {
+ items: vec![Box::new(AssertionLogic::Item {
+ src: "$identities".into(),
+ op: Op::Equal,
+ dst: "[\"did:litentry:substrate:0x0000000000000000000000000000000000000000000000000000000000000000\",\"did:litentry:evm:0x0000000000000000000000000000000000000000\",\"did:litentry:bitcoin:0x000000000000000000000000000000000000000000000000000000000000000000\",\"did:litentry:solana:11111111111111111111111111111111\",\"did:litentry:discord:discord_handle\",\"did:litentry:twitter:twitter_handle\",\"did:litentry:github:github_handle\"]".into()
+ })]
+ }
+ );
+ assert_eq!(*(credential.credential_subject.values.first().unwrap()), true);
+ },
+ Err(e) => {
+ panic!("build linked_identities failed with error {:?}", e);
+ },
+ }
+ }
+}
diff --git a/tee-worker/litentry/core/credentials-v2/src/lib.rs b/tee-worker/litentry/core/credentials-v2/src/lib.rs
index a831cd4302..876782a400 100644
--- a/tee-worker/litentry/core/credentials-v2/src/lib.rs
+++ b/tee-worker/litentry/core/credentials-v2/src/lib.rs
@@ -30,6 +30,7 @@ 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, IssuerRuntimeVersion};
+pub mod linked_identities;
pub mod nft_holder;
pub mod platform_user;
pub mod token_holding_amount;
diff --git a/tee-worker/litentry/core/credentials-v2/src/linked_identities/mod.rs b/tee-worker/litentry/core/credentials-v2/src/linked_identities/mod.rs
new file mode 100644
index 0000000000..812687b1c6
--- /dev/null
+++ b/tee-worker/litentry/core/credentials-v2/src/linked_identities/mod.rs
@@ -0,0 +1,48 @@
+// 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 .
+
+#[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::{
+ assertion_logic::{AssertionLogic, Op},
+ Credential,
+};
+use std::{string::String, vec::Vec};
+
+const TYPE: &str = "Linked web2/web3 identities";
+const DESCRIPTION: &str = "All web2 and web3 identities you linked";
+
+pub trait LinkedIdentitiesAssertionUpdate {
+ fn update_linked_identities_assertion(&mut self, identities: Vec);
+}
+
+impl LinkedIdentitiesAssertionUpdate for Credential {
+ fn update_linked_identities_assertion(&mut self, identities: Vec) {
+ self.add_subject_info(DESCRIPTION, TYPE);
+
+ let mut assertion = AssertionLogic::new_and();
+ let dst = format!("[\"{}\"]", identities.join("\",\""));
+ assertion =
+ assertion.add_item(AssertionLogic::new_item("$identities", Op::Equal, dst.as_str()));
+
+ self.credential_subject.assertions.push(assertion);
+ self.credential_subject.values.push(true);
+ }
+}
diff --git a/tee-worker/litentry/core/credentials/src/credential_schema.rs b/tee-worker/litentry/core/credentials/src/credential_schema.rs
index 282861d912..e0604271fb 100644
--- a/tee-worker/litentry/core/credentials/src/credential_schema.rs
+++ b/tee-worker/litentry/core/credentials/src/credential_schema.rs
@@ -115,5 +115,7 @@ pub fn get_schema_url(assertion: &Assertion) -> Option {
Some(format!("{BASE_URL}/25-token-holding-amount/1-1-4.json")),
Assertion::Dynamic(..) => None,
+
+ Assertion::LinkedIdentities => Some(format!("{BASE_URL}/27-linked-identities/1-0-0.json")),
}
}
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 9d1d1b31a9..d8db0a464d 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
@@ -207,6 +207,8 @@ where
vc_logs = Some(result.1);
Ok(result.0)
},
+
+ Assertion::LinkedIdentities => lc_assertion_build_v2::linked_identities::build(req),
}?;
// post-process the credential
diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs
index 69235686ec..45fc234a14 100644
--- a/tee-worker/service/src/prometheus_metrics.rs
+++ b/tee-worker/service/src/prometheus_metrics.rs
@@ -329,6 +329,7 @@ fn assertion_to_string(assertion: Assertion) -> String {
Assertion::Dynamic(param) => {
format!("DynamicAssertion({:?})", param.smart_contract_id)
},
+ Assertion::LinkedIdentities => "LinkedIdentities".into(),
};
assertion
}
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 0ef87b7065..a58f906594 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
@@ -345,4 +345,12 @@ export const mockAssertions = [
WeirdoGhostGangHolder: [],
},
},
+
+ // LinkedIdentities
+ {
+ description: 'All web2 and web3 identities you linked',
+ assertion: {
+ LinkedIdentities: [],
+ },
+ },
];