Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use whole unsigned VC as VC proof signature payload #2404

Merged
merged 9 commits into from
Jan 19, 2024
89 changes: 2 additions & 87 deletions pallets/vc-management/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,11 @@ use sp_std::vec;

use test_utils::ias::consts::TEST8_MRENCLAVE;
const USER_SEED: u32 = 9966;
const VC_HASH: H256 = H256::zero();
const VC_INDEX: H256 = H256::zero();

fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
}

fn convert_u32_array_to_u8_array(u32_array: [u32; 8]) -> [u8; 32] {
let mut u8_array = [0u8; 32];
let mut index = 0;

for u32_element in &u32_array {
let u8_slice = u32_element.to_le_bytes();
u8_array[index..index + 4].copy_from_slice(&u8_slice);
index += 4;
}

u8_array
}

benchmarks! {
// Benchmark `add_delegatee`. There are no worst conditions. The benchmark showed that
// execution time is constant irrespective of encrypted_data size.
Expand Down Expand Up @@ -78,44 +63,16 @@ benchmarks! {
assert_last_event::<T>(Event::VCRequested{ account, shard, assertion }.into());
}

// Benchmark `disable_vc`. There are no worst conditions. The benchmark showed that
// 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::<AccountId>("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::<T>::vc_issued(tee_origin, identity, assertion, VC_INDEX, VC_HASH, req_ext_hash)?;
}: _(RawOrigin::Signed(account.clone()), VC_INDEX)
verify{
assert_last_event::<T>(Event::VCDisabled{ account, index: VC_HASH }.into());
}

// Benchmark `revoke_vc`. There are no worst conditions. The benchmark showed that
// 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::<AccountId>("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::<T>::vc_issued(tee_origin, identity, assertion, VC_INDEX, VC_HASH, req_ext_hash)?;
}: _(RawOrigin::Signed(account.clone()), VC_INDEX)
verify{
assert_last_event::<T>(Event::VCRevoked{ account, index: VC_HASH }.into());
}

// Benchmark `vc_issued`. There are no worst conditions. The benchmark showed that
// execution time is constant irrespective of encrypted_data size.
vc_issued {
let call_origin = T::TEECallOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
let identity: Identity = frame_benchmarking::account::<AccountId>("TEST_A", 0u32, USER_SEED).into();
let assertion = Assertion::A1;
let req_ext_hash = H256::default();
}: _<T::RuntimeOrigin>(call_origin, identity.clone(), assertion.clone(), VC_INDEX, VC_HASH, req_ext_hash)
}: _<T::RuntimeOrigin>(call_origin, identity.clone(), assertion.clone(), req_ext_hash)
verify{
assert_last_event::<T>(Event::VCIssued{ identity, assertion, index: VC_INDEX, req_ext_hash}.into());
assert_last_event::<T>(Event::VCIssued{ identity, assertion, req_ext_hash}.into());
}

// Benchmark `some_error`. There are no worst conditions. The benchmark showed that
Expand Down Expand Up @@ -199,48 +156,6 @@ benchmarks! {
assert_last_event::<T>(Event::SchemaRevoked { account, shard, index: 0 }.into())
}

// Benchmark `add_vc_registry_item`. There are no worst conditions. The benchmark showed that
// 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::<AccountId>("TEST_B", 0u32, USER_SEED).into();
VCManagement::<T>::set_admin(RawOrigin::Root.into(), account.clone())?;
let assertion = Assertion::A1;
}: _(RawOrigin::Signed(account.clone()), VC_INDEX, identity.clone(), assertion.clone(), VC_HASH)
verify {
assert_last_event::<T>(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::<AccountId>("TEST_B", 0u32, USER_SEED).into();
VCManagement::<T>::set_admin(RawOrigin::Root.into(), account.clone())?;
let assertion = Assertion::A1;
VCManagement::<T>::add_vc_registry_item(RawOrigin::Signed(account.clone()).into(), VC_INDEX, identity, assertion, VC_HASH)?;
}: _(RawOrigin::Signed(account), VC_INDEX)
verify {
assert_last_event::<T>(Event::VCRegistryItemRemoved { index: VC_INDEX }.into())
}

// Benchmark `clear_vc_registry`.
clear_vc_registry {
let x in 0..100u32;
let account: T::AccountId = frame_benchmarking::account("TEST_A", 0u32, USER_SEED);
VCManagement::<T>::set_admin(RawOrigin::Root.into(), account.clone())?;
let assertion = Assertion::A1;
for i in 0..x {
let seed = USER_SEED - i;
let identity: Identity = frame_benchmarking::account::<AccountId>("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::<T>::add_vc_registry_item(RawOrigin::Signed(account.clone()).into(), hash, identity, assertion.clone(), VC_HASH)?;
}
}: _(RawOrigin::Signed(account))
verify {
assert_last_event::<T>(Event::VCRegistryCleared.into())
}
}

#[cfg(test)]
Expand Down
117 changes: 2 additions & 115 deletions pallets/vc-management/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ use sp_core::H256;
use sp_std::vec::Vec;
use teerex_primitives::ShardIdentifier;

mod vc_context;
pub use vc_context::*;

mod schema;
pub use schema::*;

Expand Down Expand Up @@ -73,12 +70,6 @@ pub mod pallet {
type ExtrinsicWhitelistOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
}

// a map VCIndex -> VC context
// TODO: to be removed in P-350
#[pallet::storage]
#[pallet::getter(fn vc_registry)]
pub type VCRegistry<T: Config> = StorageMap<_, Blake2_128Concat, VCIndex, VCContext>;

// the admin account
#[pallet::storage]
#[pallet::getter(fn admin)]
Expand All @@ -87,7 +78,7 @@ pub mod pallet {
// delegatees who can request (and receive) VCs on users' behalf,
// some VCs can only be requested by delegatee accounts (e.g. A13)
// delegatees and admins are different:
// - admins are meant to manage the pallet state manually, e.g. schema, vcRegistry
// - admins are meant to manage the pallet state manually, e.g. schema
// - delegatees can request VCs for users, similar to `proxied account`
#[pallet::storage]
#[pallet::getter(fn delegatee)]
Expand Down Expand Up @@ -117,22 +108,11 @@ pub mod pallet {
shard: ShardIdentifier,
assertion: Assertion,
},
// a VC is disabled on chain
VCDisabled {
account: T::AccountId,
index: VCIndex,
},
// a VC is revoked on chain
VCRevoked {
account: T::AccountId,
index: VCIndex,
},
// event that should be triggered by TEECallOrigin
// a VC is just issued
VCIssued {
identity: Identity,
assertion: Assertion,
index: VCIndex,
req_ext_hash: H256,
},
// Admin account was changed
Expand Down Expand Up @@ -178,15 +158,6 @@ pub mod pallet {
detail: ErrorDetail,
req_ext_hash: H256,
},
VCRegistryItemAdded {
identity: Identity,
assertion: Assertion,
index: VCIndex,
},
VCRegistryItemRemoved {
index: VCIndex,
},
VCRegistryCleared,
}

#[pallet::error]
Expand Down Expand Up @@ -276,38 +247,6 @@ pub mod pallet {
Ok(().into())
}

#[pallet::call_index(3)]
#[pallet::weight(<T as Config>::WeightInfo::disable_vc())]
pub fn disable_vc(origin: OriginFor<T>, index: VCIndex) -> DispatchResultWithPostInfo {
let who = T::ExtrinsicWhitelistOrigin::ensure_origin(origin)?;
VCRegistry::<T>::try_mutate(index, |context| {
let mut c = context.take().ok_or(Error::<T>::VCNotExist)?;
ensure!(
Some(who.clone()).encode() == c.subject.to_account_id().encode(),
Error::<T>::VCSubjectMismatch
);
ensure!(c.status == Status::Active, Error::<T>::VCAlreadyDisabled);
c.status = Status::Disabled;
*context = Some(c);
Self::deposit_event(Event::VCDisabled { account: who, index });
Ok(().into())
})
}

#[pallet::call_index(4)]
#[pallet::weight(<T as Config>::WeightInfo::revoke_vc())]
pub fn revoke_vc(origin: OriginFor<T>, index: VCIndex) -> DispatchResultWithPostInfo {
let who = T::ExtrinsicWhitelistOrigin::ensure_origin(origin)?;
let context = VCRegistry::<T>::get(index).ok_or(Error::<T>::VCNotExist)?;
ensure!(
Some(who.clone()).encode() == context.subject.to_account_id().encode(),
Error::<T>::VCSubjectMismatch
);
VCRegistry::<T>::remove(index);
Self::deposit_event(Event::VCRevoked { account: who, index });
Ok(().into())
}

#[pallet::call_index(5)]
#[pallet::weight(<T as Config>::WeightInfo::set_admin())]
pub fn set_admin(origin: OriginFor<T>, new: T::AccountId) -> DispatchResultWithPostInfo {
Expand Down Expand Up @@ -399,51 +338,6 @@ pub mod pallet {
Ok(().into())
}

#[pallet::call_index(10)]
#[pallet::weight(<T as Config>::WeightInfo::add_vc_registry_item())]
pub fn add_vc_registry_item(
origin: OriginFor<T>,
index: VCIndex,
identity: Identity,
assertion: Assertion,
hash: H256,
) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;
ensure!(Some(sender) == Self::admin(), Error::<T>::RequireAdmin);
ensure!(!VCRegistry::<T>::contains_key(index), Error::<T>::VCAlreadyExists);
VCRegistry::<T>::insert(
index,
VCContext::new(identity.clone(), assertion.clone(), hash),
);
Self::deposit_event(Event::VCRegistryItemAdded { identity, assertion, index });
Ok(().into())
}

#[pallet::call_index(11)]
#[pallet::weight(<T as Config>::WeightInfo::remove_vc_registry_item())]
pub fn remove_vc_registry_item(
origin: OriginFor<T>,
index: VCIndex,
) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;
ensure!(Some(sender) == Self::admin(), Error::<T>::RequireAdmin);
let _ = VCRegistry::<T>::get(index).ok_or(Error::<T>::VCNotExist)?;
VCRegistry::<T>::remove(index);
Self::deposit_event(Event::VCRegistryItemRemoved { index });
Ok(().into())
}

#[pallet::call_index(12)]
#[pallet::weight(<T as Config>::WeightInfo::clear_vc_registry(u32::max_value()))]
pub fn clear_vc_registry(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;
ensure!(Some(sender) == Self::admin(), Error::<T>::RequireAdmin);
// If more than u32 max, the map itself is overflow, so no worry
let _ = VCRegistry::<T>::clear(u32::max_value(), None);
Self::deposit_event(Event::VCRegistryCleared);
Ok(Pays::No.into())
}

/// ---------------------------------------------------
/// The following extrinsics are supposed to be called by TEE only
/// ---------------------------------------------------
Expand All @@ -453,17 +347,10 @@ pub mod pallet {
origin: OriginFor<T>,
identity: Identity,
assertion: Assertion,
index: H256,
hash: H256,
req_ext_hash: H256,
) -> DispatchResultWithPostInfo {
let _ = T::TEECallOrigin::ensure_origin(origin)?;
ensure!(!VCRegistry::<T>::contains_key(index), Error::<T>::VCAlreadyExists);
VCRegistry::<T>::insert(
index,
VCContext::new(identity.clone(), assertion.clone(), hash),
);
Self::deposit_event(Event::VCIssued { identity, assertion, index, req_ext_hash });
Self::deposit_event(Event::VCIssued { identity, assertion, req_ext_hash });
Ok(Pays::No.into())
}

Expand Down
11 changes: 10 additions & 1 deletion pallets/vc-management/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@
// VC Schema
// According to https://w3c-ccg.github.io/vc-json-schemas/, it defines JSON Schema for W3C Verifiable Credential.

use crate::{vc_context::Status, Config};
use crate::Config;
use codec::{Decode, Encode, MaxEncodedLen};
use core_primitives::{SchemaContentString, SchemaIdString};
use scale_info::TypeInfo;
use sp_std::vec::Vec;

#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
pub enum Status {
kziemianek marked this conversation as resolved.
Show resolved Hide resolved
#[codec(index = 0)]
Active,
#[codec(index = 1)]
Disabled,
// Revoked, // commented out for now, we can delete the VC entry when revoked
}

#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
Expand Down
Loading
Loading