Skip to content

Commit

Permalink
Use whole unsigned VC as VC proof signature payload (#2404)
Browse files Browse the repository at this point in the history
* Use whole unsigned VC as VC proof signature payload

* fix fmt

* fix ii-vc ts-test

* improve test

* remove VCRegistry and events

* [benchmarking bot] Auto commit generated weights files (#2409)

Co-authored-by: kziemianek <kziemianek@users.noreply.github.com>

---------

Co-authored-by: BillyWooo <thedreamofbilly@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kziemianek <kziemianek@users.noreply.github.com>
  • Loading branch information
4 people committed Jan 19, 2024
1 parent aaff988 commit d0759fb
Show file tree
Hide file tree
Showing 22 changed files with 99 additions and 1,148 deletions.
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 {
#[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

0 comments on commit d0759fb

Please sign in to comment.