feat: Rebrand Polkadot/Substrate references to PezkuwiChain

This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
+56
View File
@@ -0,0 +1,56 @@
[package]
name = "pezpallet-people"
version = "1.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "Personhood-tracking pallet"
readme = "README.md"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { workspace = true, features = ["derive"] }
pezframe-benchmarking = { workspace = true, optional = true }
pezframe-support = { workspace = true }
pezframe-system = { workspace = true }
log = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
pezsp-arithmetic = { workspace = true }
pezsp-core = { workspace = true }
pezsp-io = { workspace = true }
pezsp-runtime = { workspace = true }
verifiable = { workspace = true, features = ["small-ring"] }
[features]
default = ["std"]
std = [
"codec/std",
"pezframe-benchmarking?/std",
"pezframe-support/std",
"pezframe-system/std",
"log/std",
"scale-info/std",
"pezsp-arithmetic/std",
"pezsp-core/std",
"pezsp-io/std",
"pezsp-runtime/std",
"verifiable/std",
]
runtime-benchmarks = [
"pezframe-benchmarking/runtime-benchmarks",
"pezframe-support/runtime-benchmarks",
"pezframe-system/runtime-benchmarks",
"pezsp-io/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
"verifiable/no-std-prover",
]
try-runtime = [
"pezframe-support/try-runtime",
"pezframe-system/try-runtime",
"pezsp-runtime/try-runtime",
]
+98
View File
@@ -0,0 +1,98 @@
# People Pallet
A pallet managing the registry of proven individuals.
## Overview
The People pallet stores and manages identifiers of individuals who have proven their personhood. It
tracks their personal IDs, organizes their cryptographic keys into rings, and allows them to use
contextual aliases through authentication in extensions. When transactions include cryptographic
proofs of belonging to the people set, the pallet's transaction extension verifies these proofs
before allowing the transaction to proceed. This enables other pallets to check if actions come from
unique persons while preserving privacy through the ring-based structure.
The pallet accepts new persons after they prove their uniqueness elsewhere, stores their
information, and supports removing persons via suspensions. While other systems (e.g., wallets)
generate the proofs, this pallet handles the storage of all necessary data and verifies the proofs
when used.
## Key Features
- **Stores Identity Data**: Tracks personal IDs and cryptographic keys of proven persons
- **Organizes Keys**: Groups keys into rings to enable privacy-preserving proofs
- **Verifies Proofs**: Checks personhood proofs attached to transactions
- **Links Accounts**: Allows connecting blockchain accounts to contextual aliases
- **Manages Registry**: Adds proven persons and will support removing them
## Interface
### Dispatchable Functions
- `set_alias_account(origin, account)`: Link an account to a contextual alias Once linked, this
allows the account to dispatch transactions as a person with the alias origin using a regular
signed transaction with a nonce, providing a simpler alternative to attaching full proofs.
- `unset_alias_account(origin)`: Remove an account-alias link.
- `merge_rings`: Merge the people in two rings into a single, new ring.
- `force_recognize_personhood`: Recognize a set of people without any additional checks.
- `set_personal_id_account`: Set a personal id account.
- `unset_personal_id_account`: Unset the personal id account.
- `migrate_included_key`: Migrate the key for a person who was onboarded and is currently included
in a ring.
- `migrate_onboarding_key`: Migrate the key for a person who is currently onboarding. The operation
is instant, replacing the old key in the onboarding queue.
- `set_onboarding_size`: Force set the onboarding size for new people. This call requires root
privileges.
- `build_ring_manual`: Manually build a ring root by including registered people. The transaction
fee is refunded on a successful call.
- `onboard_people_manual`: Manually onboard people into a ring. The transaction fee is refunded on
a successful call.
### Automated tasks performed by the pallet in hooks
- Ring building: Build or update a ring's cryptographic commitment. This task processes queued keys
into a ring commitment that enables proof generation and verification. Since ring construction, or
rather adding keys to the ring, is computationally expensive, it's performed periodically in
batches rather than processing each key immediately. The batch size needs to be reasonably large
to enhance privacy by obscuring the exact timing of when individuals' keys were added to the ring,
making it more difficult to correlate specific persons with their keys.
- People onboarding: Onboard people from the onboarding queue into a ring. This task takes the
unincluded keys of recognized people from the onboarding queue and registers them into the ring.
People can be onboarded only in batches of at least `OnboardingSize` and when the remaining open
slots in a ring are at least `OnboardingSize`. This does not compute the root, that is done using
`build_ring`.
- Cleaning of suspended people: Remove people's keys marked as suspended or inactive from rings. The
keys are stored in the `PendingSuspensions` map and they are removed from rings and their roots
are reset. The ring roots will subsequently be build in the ring building phase from scratch.
sequentially.
- Key migration: Migrate the keys for people who were onboarded and are currently included in rings.
The migration is not instant as the key replacement and subsequent inclusion in a new ring root
will happen only after the next mutation session.
- Onboarding queue page merging: Merge the two pages at the front of the onboarding queue. After a
round of suspensions, it is possible for the second page of the onboarding queue to be left with
few members such that, if the first page also has few members, the total count is below the
required onboarding size, thus stalling the queue. This function fixes this by moving the people
from the first page to the front of the second page, defragmenting the queue.
### Transaction Extension
The pallet provides the `AsPerson` transaction extension that allows transactions to be dispatched
with special origins: `PersonalIdentity` and `PersonalAlias`. These origins prove the transaction
comes from a unique person, either through their identity or through a contextual alias. To make use
of the personhood system, other pallets should check for these origins.
The extension verifies the proof of personhood during transaction validation and, if valid,
transforms the transaction's origin into one of these special origins.
## Usage
Other pallets can verify personhood through origin checks:
- `EnsurePersonalIdentity`: Verifies the origin represents a specific person using their PersonalId
- `EnsurePersonalAlias`: Verifies the origin has a valid alias for any context
- `EnsurePersonalAliasInContext`: Verifies the origin has a valid alias for a specific context
- `EnsureRevisedPersonalAlias`: Verifies the origin has a valid alias for any context and includes
the revision of the member's ring
- `EnsureRevisedPersonalAliasInContext`: Verifies the origin has a valid alias for a specific
context and includes the revision of the member's ring
License: Apache-2.0
File diff suppressed because it is too large Load Diff
+309
View File
@@ -0,0 +1,309 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// 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.
//! People transaction extensions.
use crate::*;
use codec::{Decode, DecodeWithMemTracking, Encode};
use core::fmt;
use pezframe_support::{
ensure, pezpallet_prelude::TransactionSource, traits::reality::Context, weights::Weight,
CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound,
};
use pezframe_system::{CheckNonce, ValidNonceInfo};
use scale_info::TypeInfo;
use pezsp_core::twox_64;
use pezsp_runtime::{
traits::{DispatchInfoOf, TransactionExtension, ValidateResult},
transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction},
Saturating,
};
/// Information required to transform an origin into a personal alias or personal identity.
#[derive(
Encode, Decode, TypeInfo, EqNoBound, CloneNoBound, PartialEqNoBound, DecodeWithMemTracking,
)]
#[scale_info(skip_type_params(T))]
pub enum AsPersonInfo<T: Config + Send + Sync> {
/// The signed origin will be transformed using account to alias.
AsPersonalAliasWithAccount(T::Nonce),
/// The none origin will be transformed using proof.
///
/// This can only dispatch the call `set_alias_account`.
///
/// Replay is only protected against resetting the same account during the tolerance period
/// after `call_valid_at` parameter.
/// If 2 transaction that set 2 different account are sent for an overlapping validity period,
/// then those 2 transactions can be replayed indefinitely for the duration of the overlapping
/// period.
AsPersonalAliasWithProof(<T::Crypto as GenerateVerifiable>::Proof, RingIndex, Context),
/// The none origin will be transformed using signature.
///
/// This can only dispatch the call `set_personal_id_account`.
///
/// Replay is only protected against resetting the same account during the tolerance period
/// after `call_valid_at` parameter.
/// If 2 transaction that set 2 different account are sent for an overlapping validity period,
/// then those 2 transactions can be replayed indefinitely for the duration of the overlapping
/// period.
AsPersonalIdentityWithProof(<T::Crypto as GenerateVerifiable>::Signature, PersonalId),
/// The signed origin will be transformed using account to personal id.
AsPersonalIdentityWithAccount(T::Nonce),
}
/// Transaction extension to transform an origin into a personal alias or personal identity.
#[derive(
Encode,
Decode,
TypeInfo,
EqNoBound,
CloneNoBound,
PartialEqNoBound,
DefaultNoBound,
DecodeWithMemTracking,
)]
#[scale_info(skip_type_params(T))]
pub struct AsPerson<T: Config + Send + Sync>(Option<AsPersonInfo<T>>);
impl<T: Config + Send + Sync> fmt::Debug for AsPerson<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "AsPerson")
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
impl<T: Config + Send + Sync> AsPerson<T> {
pub fn new(explicit: Option<AsPersonInfo<T>>) -> Self {
Self(explicit)
}
}
/// Info returned by validate to prepare in the [`AsPerson`] transaction extension.
pub enum Val<T: Config + Send + Sync> {
NotUsing,
UsingProof,
UsingAccount(T::AccountId, T::Nonce),
}
impl<T: Config + Send + Sync> TransactionExtension<<T as pezframe_system::Config>::RuntimeCall>
for AsPerson<T>
{
const IDENTIFIER: &'static str = "AsPerson";
type Implicit = ();
type Val = Val<T>;
type Pre = ();
fn weight(&self, _call: &<T as pezframe_system::Config>::RuntimeCall) -> Weight {
match self.0 {
// Extension is passthrough
None => Weight::zero(),
// Alias with existing account
Some(AsPersonInfo::AsPersonalAliasWithAccount(_)) =>
T::WeightInfo::as_person_alias_with_account(),
// Alias with proof
Some(AsPersonInfo::AsPersonalAliasWithProof(_, _, _)) =>
T::WeightInfo::as_person_alias_with_proof(),
// Personal Identity with proof
Some(AsPersonInfo::AsPersonalIdentityWithProof(_, _)) =>
T::WeightInfo::as_person_identity_with_proof(),
// Personal Identity with existing account
Some(AsPersonInfo::AsPersonalIdentityWithAccount(_)) =>
T::WeightInfo::as_person_identity_with_account(),
}
}
fn validate(
&self,
origin: <T as pezframe_system::Config>::RuntimeOrigin,
call: &<T as pezframe_system::Config>::RuntimeCall,
_info: &DispatchInfoOf<<T as pezframe_system::Config>::RuntimeCall>,
_len: usize,
_self_implicit: Self::Implicit,
inherited_implication: &impl Encode,
_source: TransactionSource,
) -> ValidateResult<Self::Val, <T as pezframe_system::Config>::RuntimeCall> {
match &self.0 {
Some(AsPersonInfo::AsPersonalAliasWithAccount(nonce)) => {
let Some(pezframe_system::Origin::<T>::Signed(who)) = origin.as_system_ref() else {
return Err(InvalidTransaction::BadSigner.into());
};
let who = who.clone();
let rev_ca = AccountToAlias::<T>::get(&who).ok_or(InvalidTransaction::BadSigner)?;
ensure!(
Root::<T>::get(rev_ca.ring)
.is_some_and(|ring| ring.revision == rev_ca.revision),
InvalidTransaction::BadSigner,
);
let local_origin = Origin::PersonalAlias(rev_ca);
let mut origin = origin;
origin.set_caller_from(local_origin);
let ValidNonceInfo { requires, provides } =
CheckNonce::<T>::validate_nonce_for_account(&who, *nonce)?;
let validity = ValidTransaction { requires, provides, ..Default::default() };
Ok((validity, Val::UsingAccount(who, *nonce), origin))
},
Some(AsPersonInfo::AsPersonalIdentityWithAccount(nonce)) => {
let Some(pezframe_system::Origin::<T>::Signed(who)) = origin.as_system_ref() else {
return Err(InvalidTransaction::BadSigner.into());
};
let who = who.clone();
let id =
AccountToPersonalId::<T>::get(&who).ok_or(InvalidTransaction::BadSigner)?;
let local_origin = Origin::PersonalIdentity(id);
let mut origin = origin;
origin.set_caller_from(local_origin);
let ValidNonceInfo { requires, provides } =
CheckNonce::<T>::validate_nonce_for_account(&who, *nonce)?;
let validity = ValidTransaction { requires, provides, ..Default::default() };
Ok((validity, Val::UsingAccount(who, *nonce), origin))
},
Some(AsPersonInfo::AsPersonalAliasWithProof(proof, ring_index, context)) => {
ensure!(
matches!(origin.as_system_ref(), Some(pezframe_system::RawOrigin::None)),
InvalidTransaction::BadSigner
);
let Some(Call::<T>::set_alias_account { account, call_valid_at }) =
call.is_sub_type()
else {
return Err(InvalidTransaction::Call.into());
};
let ring = Root::<T>::get(ring_index).ok_or(InvalidTransaction::Call)?;
let now = pezframe_system::Pallet::<T>::block_number();
if now < *call_valid_at {
return Err(InvalidTransaction::Future.into());
}
let time_tolerance = Pallet::<T>::account_setup_time_tolerance();
if now > call_valid_at.saturating_add(time_tolerance) {
return Err(InvalidTransaction::Stale.into());
}
let msg = inherited_implication.using_encoded(pezsp_io::hashing::blake2_256);
let alias = T::Crypto::validate(proof, &ring.root, &context[..], &msg[..])
.map_err(|_| InvalidTransaction::BadProof)?;
let rev_ca = RevisedContextualAlias {
revision: ring.revision,
ring: *ring_index,
ca: ContextualAlias { alias, context: *context },
};
// This protects again replay attack.
if AccountToAlias::<T>::get(account)
.is_some_and(|stored_rev_ca| stored_rev_ca == rev_ca)
{
return Err(InvalidTransaction::Stale.into());
}
// The extrinsic provides the setup of the account for the alias.
let provides = twox_64(&("setup", &rev_ca, &account).encode()[..]);
let valid_transaction =
ValidTransaction::with_tag_prefix("Ppl:Alias").and_provides(provides).into();
// We transmute the origin.
let local_origin = Origin::PersonalAlias(rev_ca);
let mut origin = origin;
origin.set_caller_from(local_origin);
Ok((valid_transaction, Val::UsingProof, origin))
},
Some(AsPersonInfo::AsPersonalIdentityWithProof(signature, index)) => {
ensure!(
matches!(origin.as_system_ref(), Some(pezframe_system::RawOrigin::None)),
InvalidTransaction::BadSigner
);
let Some(Call::<T>::set_personal_id_account { account, call_valid_at }) =
call.is_sub_type()
else {
return Err(InvalidTransaction::Call.into());
};
let now = pezframe_system::Pallet::<T>::block_number();
if now < *call_valid_at {
return Err(InvalidTransaction::Future.into());
}
let time_tolerance = Pallet::<T>::account_setup_time_tolerance();
if now > call_valid_at.saturating_add(time_tolerance) {
return Err(InvalidTransaction::Stale.into());
}
let key = People::<T>::get(index)
.map(|record| record.key)
.ok_or(InvalidTransaction::BadSigner)?;
let msg = inherited_implication.using_encoded(pezsp_io::hashing::blake2_256);
if !T::Crypto::verify_signature(signature, &msg[..], &key) {
return Err(InvalidTransaction::BadProof.into());
}
// This protects again replay attack.
if People::<T>::get(index).is_some_and(|record| {
record.account.is_some_and(|stored_account| stored_account == *account)
}) {
return Err(InvalidTransaction::Stale.into());
}
// The extrinsic provides the setup of the account for the personal id.
let provides = twox_64(&("setup", index, &account).encode()[..]);
let valid_transaction =
ValidTransaction::with_tag_prefix("Ppl:Id").and_provides(provides).into();
// We transmute the origin.
let local_origin = Origin::PersonalIdentity(*index);
let mut origin = origin;
origin.set_caller_from(local_origin);
Ok((valid_transaction, Val::UsingProof, origin))
},
None => Ok((ValidTransaction::default(), Val::NotUsing, origin)),
}
}
fn prepare(
self,
val: Self::Val,
_origin: &<T as pezframe_system::Config>::RuntimeOrigin,
_call: &<T as pezframe_system::Config>::RuntimeCall,
_info: &DispatchInfoOf<<T as pezframe_system::Config>::RuntimeCall>,
_len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
match val {
Val::UsingAccount(who, nonce) =>
CheckNonce::<T>::prepare_nonce_for_account(&who, nonce)?,
Val::NotUsing | Val::UsingProof => (),
}
Ok(())
}
}
File diff suppressed because it is too large Load Diff
+390
View File
@@ -0,0 +1,390 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// 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 crate::{
extension::{AsPerson, AsPersonInfo},
*,
};
use pezframe_support::{
assert_ok, derive_impl, dispatch::DispatchErrorWithPostInfo, match_types, parameter_types,
storage::with_transaction, weights::RuntimeDbWeight,
};
use pezframe_system::{offchain::CreateTransactionBase, ChainContext};
use pezsp_core::{ConstU16, ConstU32, ConstU64, H256};
use pezsp_runtime::{
testing::UintAuthorityId,
traits::{Applyable, BlakeTwo256, Checkable, IdentityLookup},
transaction_validity::{InvalidTransaction, TransactionSource, TransactionValidityError},
BuildStorage, DispatchError, Weight,
};
use verifiable::demo_impls::Simple;
// First ring, used in testing.
pub const RI_ZERO: RingIndex = 0;
const EXTENSION_VERSION: u8 = 0;
pub type TransactionExtension = (AsPerson<Test>, pezframe_system::CheckNonce<Test>);
pub type Header = pezsp_runtime::generic::Header<u64, pezsp_runtime::traits::BlakeTwo256>;
pub type Block = pezsp_runtime::generic::Block<Header, UncheckedExtrinsic>;
pub type UncheckedExtrinsic = pezsp_runtime::generic::UncheckedExtrinsic<
u64,
RuntimeCall,
pezsp_runtime::testing::UintAuthorityId,
TransactionExtension,
>;
// Configure a mock runtime to test the pallet.
pezframe_support::construct_runtime!(
pub enum Test
{
System: pezframe_system,
PeoplePallet: crate,
}
);
parameter_types! {
pub const MockDbWeight: RuntimeDbWeight = RuntimeDbWeight {
read: 10,
write: 20,
};
}
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
impl pezframe_system::Config for Test {
type BaseCallFilter = pezframe_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = MockDbWeight;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ConstU64<250>;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ConstU16<42>;
type OnSetCode = ();
type MaxConsumers = pezframe_support::traits::ConstU32<16>;
}
pub type Extrinsic = pezsp_runtime::testing::TestXt<RuntimeCall, ()>;
impl CreateTransactionBase<Call<Self>> for Test {
type Extrinsic = Extrinsic;
type RuntimeCall = RuntimeCall;
}
parameter_types! {
pub static MaxRingSize: u32 = 10;
}
pub const MOCK_CONTEXT: Context = *b"pop:pezkuwi.network/mock ";
match_types! {
pub type TestAccountContexts: impl Contains<Context> = {
&MOCK_CONTEXT
};
}
pub struct MockWeights;
impl crate::WeightInfo for MockWeights {
fn under_alias() -> pezsp_runtime::Weight {
Weight::from_parts(3, 3)
}
fn set_alias_account() -> pezsp_runtime::Weight {
Weight::from_parts(4, 4)
}
fn unset_alias_account() -> pezsp_runtime::Weight {
Weight::from_parts(5, 5)
}
fn reset_root() -> pezsp_runtime::Weight {
Weight::from_parts(6, 6)
}
fn force_recognize_personhood() -> pezsp_runtime::Weight {
Weight::from_parts(7, 7)
}
fn set_personal_id_account() -> pezsp_runtime::Weight {
Weight::from_parts(8, 8)
}
fn unset_personal_id_account() -> pezsp_runtime::Weight {
Weight::from_parts(9, 9)
}
fn set_onboarding_size() -> pezsp_runtime::Weight {
Weight::from_parts(10, 10)
}
fn merge_rings() -> pezsp_runtime::Weight {
Weight::from_parts(11, 11)
}
fn migrate_included_key() -> pezsp_runtime::Weight {
Weight::from_parts(12, 12)
}
fn migrate_onboarding_key() -> pezsp_runtime::Weight {
Weight::from_parts(13, 13)
}
fn should_build_ring(n: u32) -> pezsp_runtime::Weight {
Weight::from_parts(n as u64 * 14, n as u64 * 14)
}
fn build_ring(n: u32) -> pezsp_runtime::Weight {
Weight::from_parts(n as u64 * 14, n as u64 * 14)
}
fn onboard_people() -> pezsp_runtime::Weight {
Weight::from_parts(15, 15)
}
fn remove_suspended_people(n: u32) -> pezsp_runtime::Weight {
Weight::from_parts(n as u64 * 16, n as u64 * 16)
}
fn pending_suspensions_iteration() -> Weight {
Weight::from_parts(1, 1)
}
fn migrate_keys_single_included_key() -> pezsp_runtime::Weight {
Weight::from_parts(17, 17)
}
fn merge_queue_pages() -> pezsp_runtime::Weight {
Weight::from_parts(18, 18)
}
fn on_poll_base() -> pezsp_runtime::Weight {
Weight::from_parts(19, 19)
}
fn on_idle_base() -> pezsp_runtime::Weight {
Weight::from_parts(20, 20)
}
fn as_person_alias_with_account() -> Weight {
Weight::from_parts(20, 20)
}
fn as_person_identity_with_account() -> Weight {
Weight::from_parts(21, 21)
}
fn as_person_alias_with_proof() -> Weight {
Weight::from_parts(22, 22)
}
fn as_person_identity_with_proof() -> Weight {
Weight::from_parts(23, 23)
}
}
impl crate::Config for Test {
type WeightInfo = MockWeights;
type RuntimeEvent = RuntimeEvent;
type Crypto = verifiable::demo_impls::Simple;
type AccountContexts = TestAccountContexts;
type ChunkPageSize = ConstU32<5>;
type MaxRingSize = MaxRingSize;
type OnboardingQueuePageSize = ConstU32<40>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = BenchHelper;
}
#[cfg(feature = "runtime-benchmarks")]
pub struct BenchHelper {}
#[cfg(feature = "runtime-benchmarks")]
impl<Chunk> BenchmarkHelper<Chunk> for BenchHelper
where
Chunk: From<<verifiable::demo_impls::Simple as verifiable::GenerateVerifiable>::StaticChunk>,
{
fn valid_account_context() -> Context {
MOCK_CONTEXT
}
fn initialize_chunks() -> Vec<Chunk> {
vec![]
}
}
#[allow(dead_code)]
pub fn advance_to(b: u64) {
while System::block_number() < b {
System::set_block_number(System::block_number() + 1);
}
}
pub struct ConfigRecord;
pub fn new_config() -> ConfigRecord {
ConfigRecord
}
pub struct TestExt(ConfigRecord);
#[allow(dead_code)]
impl TestExt {
pub(crate) fn max_ring_size(self, size: u32) -> Self {
MaxRingSize::set(size);
self
}
pub fn new() -> Self {
Self(new_config())
}
pub fn execute_with<R>(self, f: impl Fn() -> R) -> R {
new_test_ext().execute_with(f)
}
}
pub fn new_test_ext() -> pezsp_io::TestExternalities {
let chunks: Vec<<verifiable::demo_impls::Simple as GenerateVerifiable>::StaticChunk> =
[(); 512].to_vec();
let encoded_chunks = chunks.encode();
RuntimeGenesisConfig {
system: Default::default(),
people_pallet: crate::GenesisConfig::<Test> {
encoded_chunks: encoded_chunks.clone(),
..Default::default()
},
}
.build_storage()
.unwrap()
.into()
}
/// We gather both error into a single type in order to do `assert_ok` and `assert_err` safely.
/// Otherwise, we can easily miss the inner error in a `Resut<Resut<_, _>, _>`.
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum TransactionExecutionError {
Validity(TransactionValidityError),
// This ignores the post info.
Dispatch(DispatchErrorWithPostInfo),
}
impl From<DispatchErrorWithPostInfo> for TransactionExecutionError {
fn from(e: DispatchErrorWithPostInfo) -> Self {
TransactionExecutionError::Dispatch(e)
}
}
impl From<TransactionValidityError> for TransactionExecutionError {
fn from(e: TransactionValidityError) -> Self {
TransactionExecutionError::Validity(e)
}
}
impl From<DispatchError> for TransactionExecutionError {
fn from(e: DispatchError) -> Self {
TransactionExecutionError::Dispatch(e.into())
}
}
impl From<InvalidTransaction> for TransactionExecutionError {
fn from(e: InvalidTransaction) -> Self {
TransactionExecutionError::Validity(e.into())
}
}
/// Execute a transaction with the given origin, call and transaction extension.
pub fn exec_tx(
who: Option<u64>,
tx_ext: TransactionExtension,
call: impl Into<RuntimeCall>,
) -> Result<(), TransactionExecutionError> {
let tx = match who {
Some(who) => UncheckedExtrinsic::new_signed(call.into(), who, UintAuthorityId(who), tx_ext),
None => UncheckedExtrinsic::new_transaction(call.into(), tx_ext),
};
let info = tx.get_dispatch_info();
let len = tx.encoded_size();
// Check and validate the extrinsic.
let checked = Checkable::check(tx, &ChainContext::<Test>::default())?;
with_transaction(|| {
let valid = checked.validate::<Test>(TransactionSource::External, &info, len);
pezsp_runtime::TransactionOutcome::Rollback(Result::<_, DispatchError>::Ok(valid))
})
.unwrap()?;
// Finally, apply the extrinsic.
checked.apply::<Test>(&info, len)??;
Ok(())
}
pub fn exec_as_alias_tx(
who: u64,
call: impl Into<RuntimeCall>,
) -> Result<(), TransactionExecutionError> {
let nonce = pezframe_system::Account::<Test>::get(who).nonce;
let tx_ext = (
AsPerson::new(Some(AsPersonInfo::AsPersonalAliasWithAccount(nonce))),
pezframe_system::CheckNonce::from(nonce),
);
exec_tx(Some(who), tx_ext, call)
}
/// Call `set_alias_account` for the given personal id and account.
pub fn setup_alias_account(
key: &<Simple as GenerateVerifiable>::Member,
secret: &<Simple as GenerateVerifiable>::Secret,
context: Context,
account: u64,
) {
let id = crate::Keys::<Test>::get(key).expect("id not found");
let record = crate::People::<Test>::get(id).expect("record not found");
let ring_index = record.position.ring_index().expect("person not included in a ring");
let commitment = {
let all_keys = crate::RingKeys::<Test>::get(ring_index);
Simple::open(key, all_keys.into_iter()).unwrap()
};
let call = RuntimeCall::PeoplePallet(crate::Call::set_alias_account {
account,
call_valid_at: pezframe_system::Pallet::<Test>::block_number(),
});
let other_tx_ext = (pezframe_system::CheckNonce::<Test>::from(0),);
// Here we simply ignore implicit as they are null.
let msg = (&EXTENSION_VERSION, &call, &other_tx_ext).using_encoded(pezsp_io::hashing::blake2_256);
let (proof, _alias) =
Simple::create(commitment, secret, &context, &msg).expect("proof creation failed");
let tx_ext = (
AsPerson::<Test>::new(Some(AsPersonInfo::AsPersonalAliasWithProof(
proof, ring_index, context,
))),
other_tx_ext.0,
);
assert_ok!(exec_tx(None, tx_ext.clone(), call.clone()));
}
File diff suppressed because it is too large Load Diff
+238
View File
@@ -0,0 +1,238 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// 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.
//! Types for Proof-of-Personhood system.
#![allow(clippy::result_unit_err)]
use super::*;
use pezframe_support::{pezpallet_prelude::*, DefaultNoBound};
pub type RevisionIndex = u32;
pub type PageIndex = u32;
pub type KeyCount = u64;
pub type MemberOf<T> = <<T as Config>::Crypto as GenerateVerifiable>::Member;
pub type MembersOf<T> = <<T as Config>::Crypto as GenerateVerifiable>::Members;
pub type IntermediateOf<T> = <<T as Config>::Crypto as GenerateVerifiable>::Intermediate;
pub type SecretOf<T> = <<T as Config>::Crypto as GenerateVerifiable>::Secret;
pub type SignatureOf<T> = <<T as Config>::Crypto as GenerateVerifiable>::Signature;
pub type ChunksOf<T> = BoundedVec<
<<T as Config>::Crypto as GenerateVerifiable>::StaticChunk,
<T as Config>::ChunkPageSize,
>;
/// The overarching state of all people rings regarding the actions that are currently allowed to be
/// performed on them.
#[derive(
Clone,
PartialEq,
Eq,
RuntimeDebug,
Encode,
Decode,
MaxEncodedLen,
TypeInfo,
DecodeWithMemTracking,
)]
pub enum RingMembersState {
/// The rings can accept new people sequentially if the maximum capacity has not been reached
/// yet. Ring building is permitted in this state by building the ring roots on top of
/// previously computed roots. In case a ring suffered mutations that invalidated a previous
/// ring root through the removal of an included member, the existing ring root will be removed
/// and ring building will start from scratch.
AppendOnly,
/// A semaphore counting the number of entities making changes to the ring members list which
/// require the entire ring to be rebuilt. Whenever a DIM would want to suspend
/// people, it would first need to increment this counter and then start submitting the
/// suspended indices. After all indices are registered, the counter is decremented. Ring
/// merges are allowed only when no entity is allowed to suspend keys and the counter is 0.
Mutating(u8),
/// After mutations to the member set, any pending key migrations are enacted before the new
/// ring roots will be built in order to reflect the latest changes in state.
KeyMigration,
}
impl Default for RingMembersState {
fn default() -> Self {
Self::AppendOnly
}
}
impl RingMembersState {
/// Returns whether the state allows only incremental additions to rings and their roots.
pub fn append_only(&self) -> bool {
matches!(self, Self::AppendOnly)
}
/// Returns whether the state allows mutating the member set of rings.
pub fn mutating(&self) -> bool {
matches!(self, Self::Mutating(_))
}
/// Returns whether the state allows the pending key migrations to be enacted.
pub fn key_migration(&self) -> bool {
matches!(self, Self::KeyMigration)
}
/// Move to a mutation state.
pub fn start_mutation_session(self) -> Result<Self, ()> {
match self {
Self::AppendOnly => Ok(Self::Mutating(1)),
Self::Mutating(n) => Ok(Self::Mutating(n.checked_add(1).ok_or(())?)),
Self::KeyMigration => Err(()),
}
}
/// Move out of a mutation state.
pub fn end_mutation_session(self) -> Result<Self, ()> {
match self {
Self::AppendOnly => Err(()),
Self::Mutating(1) => Ok(Self::KeyMigration),
Self::Mutating(n) => Ok(Self::Mutating(n.saturating_sub(1))),
Self::KeyMigration => Err(()),
}
}
/// Move out of a key migration state.
pub fn end_key_migration(self) -> Result<Self, ()> {
match self {
Self::KeyMigration => Ok(Self::AppendOnly),
_ => Err(()),
}
}
}
/// A contextual alias [`ContextualAlias`] used in a specific ring revision.
///
/// The revision can be used to tell in the future if an alias may have been suspended.
/// For instance, if a person is suspended, then ring will get revised, the revised alias with the
/// old revision shows that the alias may not be owned by a valid person anymore.
#[derive(
Clone,
PartialEq,
Eq,
RuntimeDebug,
Encode,
Decode,
MaxEncodedLen,
TypeInfo,
DecodeWithMemTracking,
)]
pub struct RevisedContextualAlias {
pub revision: RevisionIndex,
pub ring: RingIndex,
pub ca: ContextualAlias,
}
/// An alias [`Alias`] used in a specific ring revision.
///
/// The revision can be used to tell in the future if an alias may have been suspended.
/// For instance, if a person is suspended, then ring will get revised, the revised alias with the
/// old revision shows that the alias may not be owned by a valid person anymore.
#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
pub struct RevisedAlias {
pub revision: RevisionIndex,
pub ring: RingIndex,
pub alias: Alias,
}
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub struct RingRoot<T: Config> {
/// The ring root for the current ring.
pub root: MembersOf<T>,
/// The revision index of the ring.
pub revision: RevisionIndex,
/// An intermediate value if the ring is not full.
pub intermediate: IntermediateOf<T>,
}
#[derive(
PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen, DefaultNoBound,
)]
#[scale_info(skip_type_params(T))]
/// Information about the current key inclusion status in a ring.
pub struct RingStatus {
/// The number of keys in the ring.
pub total: u32,
/// The number of keys that have already been baked in.
pub included: u32,
}
/// The state of a person's key within the pallet along with its position in relevant structures.
///
/// Differentiates between individuals included in a ring, those being onboarded and the suspended
/// ones. For those already included, provides ring index and position in it. For those being
/// onboarded, provides queue page index and position in the queue.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub enum RingPosition {
/// Coordinates within the onboarding queue for a person that doesn't belong to a ring yet.
Onboarding { queue_page: PageIndex },
/// Coordinates within the rings for a person that was registered.
Included { ring_index: RingIndex, ring_position: u32, scheduled_for_removal: bool },
/// The person is suspended and isn't part of any ring or onboarding queue page.
Suspended,
}
impl RingPosition {
/// Returns whether the person is suspended and has no position.
pub fn suspended(&self) -> bool {
matches!(self, Self::Suspended)
}
/// Returns whether the person is included in a ring and is scheduled for removal.
pub fn scheduled_for_removal(&self) -> bool {
match &self {
Self::Included { scheduled_for_removal, .. } => *scheduled_for_removal,
_ => false,
}
}
/// Returns the index of the ring if this person is included.
pub fn ring_index(&self) -> Option<RingIndex> {
match &self {
Self::Included { ring_index, .. } => Some(*ring_index),
_ => None,
}
}
}
/// Record of personhood.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct PersonRecord<Member, AccountId> {
// The key used for the person.
pub key: Member,
// The position identifier of the key.
pub position: RingPosition,
/// An optional privileged account that can send transaction on the behalf of the person.
pub account: Option<AccountId>,
}
/// Describes the action to take after checking the first two pages of the onboarding queue for a
/// potential merge.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub(crate) enum QueueMergeAction<T: Config> {
Merge {
initial_head: PageIndex,
new_head: PageIndex,
first_key_page: BoundedVec<MemberOf<T>, T::OnboardingQueuePageSize>,
second_key_page: BoundedVec<MemberOf<T>, T::OnboardingQueuePageSize>,
},
NoAction,
}
+270
View File
@@ -0,0 +1,270 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// 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.
//! Autogenerated weights for pezpallet_ranked_collective
//!
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2022-05-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
// Executed Command:
// /Users/gav/Core/bizinikiwi/target/release/bizinikiwi
// benchmark
// pallet
// --pallet
// pezpallet-ranked-collective
// --extrinsic=*
// --chain=dev
// --steps=50
// --repeat=20
// --output=../../../frame/ranked-collective/src/weights.rs
// --template=../../../.maintain/frame-weight-template.hbs
// --header=../../../HEADER-APACHE2
// --record-proof
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use core::marker::PhantomData;
/// Weight functions needed for pezpallet_ranked_collective.
pub trait WeightInfo {
fn under_alias() -> Weight;
fn set_alias_account() -> Weight;
fn unset_alias_account() -> Weight;
fn reset_root() -> Weight;
fn force_recognize_personhood() -> Weight;
fn set_personal_id_account() -> Weight;
fn unset_personal_id_account() -> Weight;
fn set_onboarding_size() -> Weight;
fn merge_rings() -> Weight;
fn migrate_included_key() -> Weight;
fn migrate_onboarding_key() -> Weight;
fn should_build_ring(n: u32) -> Weight;
fn build_ring(n: u32) -> Weight;
fn onboard_people() -> Weight;
fn remove_suspended_people(n: u32) -> Weight;
fn pending_suspensions_iteration() -> Weight;
fn migrate_keys_single_included_key() -> Weight;
fn merge_queue_pages() -> Weight;
fn as_person_alias_with_account() -> Weight;
fn as_person_identity_with_account() -> Weight;
fn as_person_alias_with_proof() -> Weight;
fn as_person_identity_with_proof() -> Weight;
fn on_poll_base() -> Weight;
fn on_idle_base() -> Weight;
}
pub struct BizinikiwiWeight<T>(PhantomData<T>);
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
fn under_alias() -> Weight {
Weight::zero()
}
fn set_alias_account() -> Weight {
Weight::zero()
}
fn unset_alias_account() -> Weight {
Weight::zero()
}
fn reset_root() -> Weight {
Weight::zero()
}
fn force_recognize_personhood() -> Weight {
Weight::zero()
}
fn set_personal_id_account() -> Weight {
Weight::zero()
}
fn unset_personal_id_account() -> Weight {
Weight::zero()
}
fn set_onboarding_size() -> Weight {
Weight::zero()
}
fn merge_rings() -> Weight {
Weight::zero()
}
fn migrate_included_key() -> Weight {
Weight::zero()
}
fn migrate_onboarding_key() -> Weight {
Weight::zero()
}
fn should_build_ring(_n: u32) -> Weight {
Weight::zero()
}
fn build_ring(_n: u32) -> Weight {
Weight::zero()
}
fn onboard_people() -> Weight {
Weight::zero()
}
fn remove_suspended_people(_n: u32) -> Weight {
Weight::zero()
}
fn pending_suspensions_iteration() -> Weight {
Weight::zero()
}
fn migrate_keys_single_included_key() -> Weight {
Weight::zero()
}
fn merge_queue_pages() -> Weight {
Weight::zero()
}
fn as_person_alias_with_account() -> Weight {
Weight::zero()
}
fn as_person_identity_with_account() -> Weight {
Weight::zero()
}
fn as_person_alias_with_proof() -> Weight {
Weight::zero()
}
fn as_person_identity_with_proof() -> Weight {
Weight::zero()
}
fn on_poll_base() -> Weight {
Weight::zero()
}
fn on_idle_base() -> Weight {
Weight::zero()
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
fn under_alias() -> Weight {
Weight::zero()
}
fn set_alias_account() -> Weight {
Weight::zero()
}
fn unset_alias_account() -> Weight {
Weight::zero()
}
fn reset_root() -> Weight {
Weight::zero()
}
fn force_recognize_personhood() -> Weight {
Weight::zero()
}
fn set_personal_id_account() -> Weight {
Weight::zero()
}
fn unset_personal_id_account() -> Weight {
Weight::zero()
}
fn set_onboarding_size() -> Weight {
Weight::zero()
}
fn merge_rings() -> Weight {
Weight::zero()
}
fn migrate_included_key() -> Weight {
Weight::zero()
}
fn migrate_onboarding_key() -> Weight {
Weight::zero()
}
fn should_build_ring(_n: u32) -> Weight {
Weight::zero()
}
fn build_ring(_n: u32) -> Weight {
Weight::zero()
}
fn onboard_people() -> Weight {
Weight::zero()
}
fn remove_suspended_people(_n: u32) -> Weight {
Weight::zero()
}
fn pending_suspensions_iteration() -> Weight {
Weight::zero()
}
fn migrate_keys_single_included_key() -> Weight {
Weight::zero()
}
fn merge_queue_pages() -> Weight {
Weight::zero()
}
fn as_person_alias_with_account() -> Weight {
Weight::zero()
}
fn as_person_identity_with_account() -> Weight {
Weight::zero()
}
fn as_person_alias_with_proof() -> Weight {
Weight::zero()
}
fn as_person_identity_with_proof() -> Weight {
Weight::zero()
}
fn on_poll_base() -> Weight {
Weight::zero()
}
fn on_idle_base() -> Weight {
Weight::zero()
}
}