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
@@ -0,0 +1,2 @@
hfuzz_target
hfuzz_workspace
@@ -0,0 +1,49 @@
[package]
name = "pezsp-npos-elections-fuzzer"
version = "2.0.0-alpha.5"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "Fuzzer for phragmén implementation."
documentation = "https://docs.rs/pezsp-npos-elections-fuzzer"
publish = false
[lints]
workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[[bin]]
name = "reduce"
path = "src/reduce.rs"
[[bin]]
name = "phragmen_balancing"
path = "src/phragmen_balancing.rs"
[[bin]]
name = "phragmms_balancing"
path = "src/phragmms_balancing.rs"
[[bin]]
name = "phragmen_pjr"
path = "src/phragmen_pjr.rs"
[dependencies]
clap = { features = ["derive"], workspace = true }
honggfuzz = { workspace = true }
rand = { features = [
"small_rng",
"std",
], workspace = true, default-features = true }
pezsp-npos-elections = { workspace = true, default-features = true }
pezsp-runtime = { workspace = true, default-features = true }
[features]
runtime-benchmarks = [
"pezsp-npos-elections/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
]
@@ -0,0 +1,170 @@
// 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.
//! Common fuzzing utils.
// Each function will be used based on which fuzzer binary is being used.
#![allow(dead_code)]
use rand::{self, seq::SliceRandom, Rng, RngCore};
use pezsp_npos_elections::{phragmms, seq_phragmen, BalancingConfig, ElectionResult, VoteWeight};
use pezsp_runtime::Perbill;
use std::collections::{BTreeMap, HashSet};
/// converts x into the range [a, b] in a pseudo-fair way.
pub fn to_range(x: usize, a: usize, b: usize) -> usize {
// does not work correctly if b < 2 * a
assert!(b >= 2 * a);
let collapsed = x % b;
if collapsed >= a {
collapsed
} else {
collapsed + a
}
}
pub enum ElectionType {
Phragmen(Option<BalancingConfig>),
Phragmms(Option<BalancingConfig>),
}
pub type AccountId = u64;
/// Generate a set of inputs suitable for fuzzing an election algorithm
///
/// Given parameters governing how many candidates and voters should exist, generates a voting
/// scenario suitable for fuzz-testing an election algorithm.
///
/// The returned candidate list is sorted. This sorting property should not affect the result of the
/// calculation.
///
/// The returned voters list is sorted. This enables binary searching for a particular voter by
/// account id. This sorting property should not affect the results of the calculation.
///
/// Each voter's selection of candidates to vote for is sorted.
///
/// Note that this does not generate balancing parameters.
pub fn generate_random_npos_inputs(
candidate_count: usize,
voter_count: usize,
mut rng: impl Rng,
) -> (usize, Vec<AccountId>, Vec<(AccountId, VoteWeight, Vec<AccountId>)>) {
// cache for fast generation of unique candidate and voter ids
let mut used_ids = HashSet::with_capacity(candidate_count + voter_count);
// always generate a sensible desired number of candidates: elections are uninteresting if we
// desire 0 candidates, or a number of candidates >= the actual number of candidates present
let rounds = rng.gen_range(1..candidate_count);
// candidates are easy: just a completely random set of IDs
let mut candidates: Vec<AccountId> = Vec::with_capacity(candidate_count);
for _ in 0..candidate_count {
let mut id = rng.gen();
// insert returns `false` when the value was already present
while !used_ids.insert(id) {
id = rng.gen();
}
candidates.push(id);
}
candidates.sort();
candidates.dedup();
assert_eq!(candidates.len(), candidate_count);
let mut voters = Vec::with_capacity(voter_count);
for _ in 0..voter_count {
let mut id = rng.gen();
// insert returns `false` when the value was already present
while !used_ids.insert(id) {
id = rng.gen();
}
let vote_weight = rng.gen();
// it's not interesting if a voter chooses 0 or all candidates, so rule those cases out.
let n_candidates_chosen = rng.gen_range(1..candidates.len());
let mut chosen_candidates = Vec::with_capacity(n_candidates_chosen);
chosen_candidates.extend(candidates.choose_multiple(&mut rng, n_candidates_chosen));
chosen_candidates.sort();
voters.push((id, vote_weight, chosen_candidates));
}
voters.sort();
voters.dedup_by_key(|(id, _weight, _chosen_candidates)| *id);
assert_eq!(voters.len(), voter_count);
(rounds, candidates, voters)
}
pub fn generate_random_npos_result(
voter_count: u64,
target_count: u64,
to_elect: usize,
mut rng: impl RngCore,
election_type: ElectionType,
) -> (
ElectionResult<AccountId, Perbill>,
Vec<AccountId>,
Vec<(AccountId, VoteWeight, Vec<AccountId>)>,
BTreeMap<AccountId, VoteWeight>,
) {
let prefix = 100_000;
// Note, it is important that stakes are always bigger than ed.
let base_stake: u64 = 1_000_000_000_000;
let ed: u64 = base_stake;
let mut candidates = Vec::with_capacity(target_count as usize);
let mut stake_of: BTreeMap<AccountId, VoteWeight> = BTreeMap::new();
(1..=target_count).for_each(|acc| {
candidates.push(acc);
let stake_var = rng.gen_range(ed..100 * ed);
stake_of.insert(acc, base_stake + stake_var);
});
let mut voters = Vec::with_capacity(voter_count as usize);
(prefix..=(prefix + voter_count)).for_each(|acc| {
let edge_per_this_voter = rng.gen_range(1..candidates.len());
// all possible targets
let mut all_targets = candidates.clone();
// we remove and pop into `targets` `edge_per_this_voter` times.
let targets = (0..edge_per_this_voter)
.map(|_| {
let upper = all_targets.len() - 1;
let idx = rng.gen_range(0..upper);
all_targets.remove(idx)
})
.collect::<Vec<AccountId>>();
let stake_var = rng.gen_range(ed..100 * ed);
let stake = base_stake + stake_var;
stake_of.insert(acc, stake);
voters.push((acc, stake, targets));
});
(
match election_type {
ElectionType::Phragmen(conf) =>
seq_phragmen(to_elect, candidates.clone(), voters.clone(), conf).unwrap(),
ElectionType::Phragmms(conf) =>
phragmms(to_elect, candidates.clone(), voters.clone(), conf).unwrap(),
},
candidates,
voters,
stake_of,
)
}
@@ -0,0 +1,96 @@
// 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.
//! Fuzzing for sequential phragmen with potential balancing.
mod common;
use common::*;
use honggfuzz::fuzz;
use rand::{self, SeedableRng};
use pezsp_npos_elections::{
assignment_ratio_to_staked_normalized, seq_phragmen, to_supports, BalancingConfig,
ElectionResult, EvaluateSupport, VoteWeight,
};
fn main() {
loop {
fuzz!(|data: (usize, usize, usize, usize, u64)| {
let (mut target_count, mut voter_count, mut iterations, mut to_elect, seed) = data;
let rng = rand::rngs::SmallRng::seed_from_u64(seed);
target_count = to_range(target_count, 100, 200);
voter_count = to_range(voter_count, 100, 200);
iterations = to_range(iterations, 0, 30);
to_elect = to_range(to_elect, 25, target_count);
println!(
"++ [voter_count: {} / target_count:{} / to_elect:{} / iterations:{}]",
voter_count, target_count, to_elect, iterations,
);
let (unbalanced, candidates, voters, stake_of_tree) = generate_random_npos_result(
voter_count as u64,
target_count as u64,
to_elect,
rng,
ElectionType::Phragmen(None),
);
let stake_of = |who: &AccountId| -> VoteWeight { *stake_of_tree.get(who).unwrap() };
let unbalanced_score = {
let staked =
assignment_ratio_to_staked_normalized(unbalanced.assignments, &stake_of)
.unwrap();
let score = to_supports(staked.as_ref()).evaluate();
if score.minimal_stake == 0 {
// such cases cannot be improved by balancing.
return;
}
score
};
if iterations > 0 {
let config = BalancingConfig { iterations, tolerance: 0 };
let balanced: ElectionResult<AccountId, pezsp_runtime::Perbill> =
seq_phragmen(to_elect, candidates, voters, Some(config)).unwrap();
let balanced_score = {
let staked =
assignment_ratio_to_staked_normalized(balanced.assignments, &stake_of)
.unwrap();
to_supports(staked.as_ref()).evaluate()
};
let enhance = balanced_score.strict_better(unbalanced_score);
println!(
"iter = {} // {:?} -> {:?} [{}]",
iterations, unbalanced_score, balanced_score, enhance,
);
// The only guarantee of balancing is such that the first and third element of the
// score cannot decrease.
assert!(
balanced_score.minimal_stake >= unbalanced_score.minimal_stake &&
balanced_score.sum_stake == unbalanced_score.sum_stake &&
balanced_score.sum_stake_squared <= unbalanced_score.sum_stake_squared
);
}
});
}
}
@@ -0,0 +1,118 @@
// 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.
//! Fuzzing which ensures that running unbalanced sequential phragmen always produces a result
//! which satisfies our PJR checker.
//!
//! ## Running a single iteration
//!
//! Honggfuzz shuts down each individual loop iteration after a configurable time limit.
//! It can be helpful to run a single iteration on your hardware to help benchmark how long that
//! time limit should reasonably be. Simply run the program without the `fuzzing` configuration to
//! run a single iteration: `cargo run --bin phragmen_pjr`.
//!
//! ## Running
//!
//! Run with `HFUZZ_RUN_ARGS="-t 10" cargo hfuzz run phragmen_pjr`.
//!
//! Note the environment variable: by default, `cargo hfuzz` shuts down each iteration after 1
//! second of runtime. We significantly increase that to ensure that the fuzzing gets a chance to
//! complete. Running a single iteration can help determine an appropriate value for this parameter.
//!
//! ## Debugging a panic
//!
//! Once a panic is found, it can be debugged with
//! `HFUZZ_RUN_ARGS="-t 10" cargo hfuzz run-debug phragmen_pjr hfuzz_workspace/phragmen_pjr/*.fuzz`.
#[cfg(fuzzing)]
use honggfuzz::fuzz;
#[cfg(not(fuzzing))]
use clap::Parser;
mod common;
use common::{generate_random_npos_inputs, to_range};
use rand::{self, SeedableRng};
use pezsp_npos_elections::{pjr_check_core, seq_phragmen_core, setup_inputs, standard_threshold};
type AccountId = u64;
const MIN_CANDIDATES: usize = 250;
const MAX_CANDIDATES: usize = 1000;
const MIN_VOTERS: usize = 500;
const MAX_VOTERS: usize = 2500;
#[cfg(fuzzing)]
fn main() {
loop {
fuzz!(|data: (usize, usize, u64)| {
let (candidate_count, voter_count, seed) = data;
iteration(candidate_count, voter_count, seed);
});
}
}
#[cfg(not(fuzzing))]
#[derive(Debug, Parser)]
#[command(author, version, about)]
struct Opt {
/// How many candidates participate in this election
#[arg(short, long)]
candidates: Option<usize>,
/// How many voters participate in this election
#[arg(short, long)]
voters: Option<usize>,
/// Random seed to use in this election
#[arg(long)]
seed: Option<u64>,
}
#[cfg(not(fuzzing))]
fn main() {
let opt = Opt::parse();
// candidates and voters by default use the maxima, which turn out to be one less than
// the constant.
iteration(
opt.candidates.unwrap_or(MAX_CANDIDATES - 1),
opt.voters.unwrap_or(MAX_VOTERS - 1),
opt.seed.unwrap_or_default(),
);
}
fn iteration(mut candidate_count: usize, mut voter_count: usize, seed: u64) {
let rng = rand::rngs::SmallRng::seed_from_u64(seed);
candidate_count = to_range(candidate_count, MIN_CANDIDATES, MAX_CANDIDATES);
voter_count = to_range(voter_count, MIN_VOTERS, MAX_VOTERS);
let (rounds, candidates, voters) =
generate_random_npos_inputs(candidate_count, voter_count, rng);
let (candidates, voters) = setup_inputs(candidates, voters);
// Run seq-phragmen
let (candidates, voters) = seq_phragmen_core::<AccountId>(rounds, candidates, voters)
.expect("seq_phragmen must succeed");
let threshold = standard_threshold(rounds, voters.iter().map(|voter| voter.budget()));
assert!(
pjr_check_core(&candidates, &voters, threshold).is_ok(),
"unbalanced sequential phragmen must satisfy PJR",
);
}
@@ -0,0 +1,94 @@
// 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.
//! Fuzzing for phragmms.
mod common;
use common::*;
use honggfuzz::fuzz;
use rand::{self, SeedableRng};
use pezsp_npos_elections::{
assignment_ratio_to_staked_normalized, phragmms, to_supports, BalancingConfig, ElectionResult,
EvaluateSupport, VoteWeight,
};
use pezsp_runtime::Perbill;
fn main() {
loop {
fuzz!(|data: (usize, usize, usize, usize, u64)| {
let (mut target_count, mut voter_count, mut iterations, mut to_elect, seed) = data;
let rng = rand::rngs::SmallRng::seed_from_u64(seed);
target_count = to_range(target_count, 100, 200);
voter_count = to_range(voter_count, 100, 200);
iterations = to_range(iterations, 5, 30);
to_elect = to_range(to_elect, 25, target_count);
println!(
"++ [voter_count: {} / target_count:{} / to_elect:{} / iterations:{}]",
voter_count, target_count, to_elect, iterations,
);
let (unbalanced, candidates, voters, stake_of_tree) = generate_random_npos_result(
voter_count as u64,
target_count as u64,
to_elect,
rng,
ElectionType::Phragmms(None),
);
let stake_of = |who: &AccountId| -> VoteWeight { *stake_of_tree.get(who).unwrap() };
let unbalanced_score = {
let staked =
assignment_ratio_to_staked_normalized(unbalanced.assignments, &stake_of)
.unwrap();
let score = to_supports(&staked).evaluate();
if score.minimal_stake == 0 {
// such cases cannot be improved by balancing.
return;
}
score
};
let config = BalancingConfig { iterations, tolerance: 0 };
let balanced: ElectionResult<AccountId, Perbill> =
phragmms(to_elect, candidates, voters, Some(config)).unwrap();
let balanced_score = {
let staked =
assignment_ratio_to_staked_normalized(balanced.assignments, &stake_of).unwrap();
to_supports(staked.as_ref()).evaluate()
};
let enhance = balanced_score.strict_better(unbalanced_score);
println!(
"iter = {} // {:?} -> {:?} [{}]",
iterations, unbalanced_score, balanced_score, enhance,
);
// The only guarantee of balancing is such that the first and third element of the score
// cannot decrease.
assert!(
balanced_score.minimal_stake >= unbalanced_score.minimal_stake &&
balanced_score.sum_stake == unbalanced_score.sum_stake &&
balanced_score.sum_stake_squared <= unbalanced_score.sum_stake_squared
);
});
}
}
@@ -0,0 +1,143 @@
// 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.
//! Fuzzing for the reduce algorithm.
//!
//! It that reduce always return a new set og edges in which the bound is kept (`edges_after <= m +
//! n,`) and the result must effectively be the same, meaning that the same support map should be
//! computable from both.
//!
//! # Running
//!
//! Run with `cargo hfuzz run reduce`. `honggfuzz`.
//!
//! # Debugging a panic
//!
//! Once a panic is found, it can be debugged with
//! `cargo hfuzz run-debug reduce hfuzz_workspace/reduce/*.fuzz`.
use honggfuzz::fuzz;
mod common;
use common::to_range;
use rand::{self, Rng, RngCore, SeedableRng};
use pezsp_npos_elections::{reduce, to_support_map, ExtendedBalance, StakedAssignment};
type Balance = u128;
type AccountId = u64;
/// Or any other token type.
const KSM: Balance = 1_000_000_000_000;
fn main() {
loop {
fuzz!(|data: (usize, usize, u64)| {
let (mut voter_count, mut target_count, seed) = data;
let rng = rand::rngs::SmallRng::seed_from_u64(seed);
target_count = to_range(target_count, 100, 1000);
voter_count = to_range(voter_count, 100, 2000);
let (assignments, winners) =
generate_random_phragmen_assignment(voter_count, target_count, 8, 8, rng);
reduce_and_compare(&assignments, &winners);
});
}
}
fn generate_random_phragmen_assignment(
voter_count: usize,
target_count: usize,
avg_edge_per_voter: usize,
edge_per_voter_var: usize,
mut rng: impl RngCore,
) -> (Vec<StakedAssignment<AccountId>>, Vec<AccountId>) {
// prefix to distinguish the voter and target account ranges.
let target_prefix = 1_000_000;
assert!(voter_count < target_prefix);
let mut assignments = Vec::with_capacity(voter_count as usize);
let mut winners: Vec<AccountId> = Vec::new();
let all_targets = (target_prefix..(target_prefix + target_count))
.map(|a| a as AccountId)
.collect::<Vec<AccountId>>();
(1..=voter_count).for_each(|acc| {
let mut targets_to_chose_from = all_targets.clone();
let targets_to_chose = if edge_per_voter_var > 0 {
rng.gen_range(
avg_edge_per_voter - edge_per_voter_var..avg_edge_per_voter + edge_per_voter_var,
)
} else {
avg_edge_per_voter
};
let distribution = (0..targets_to_chose)
.map(|_| {
let target =
targets_to_chose_from.remove(rng.gen_range(0..targets_to_chose_from.len()));
if winners.iter().all(|w| *w != target) {
winners.push(target);
}
(target, rng.gen_range(1 * KSM..100 * KSM))
})
.collect::<Vec<(AccountId, ExtendedBalance)>>();
assignments.push(StakedAssignment { who: (acc as AccountId), distribution });
});
(assignments, winners)
}
fn assert_assignments_equal(
ass1: &Vec<StakedAssignment<AccountId>>,
ass2: &Vec<StakedAssignment<AccountId>>,
) {
let support_1 = to_support_map::<AccountId>(ass1);
let support_2 = to_support_map::<AccountId>(ass2);
for (who, support) in support_1.iter() {
assert_eq!(support.total, support_2.get(who).unwrap().total);
}
}
fn reduce_and_compare(assignment: &Vec<StakedAssignment<AccountId>>, winners: &Vec<AccountId>) {
let mut altered_assignment = assignment.clone();
let n = assignment.len() as u32;
let m = winners.len() as u32;
let edges_before = assignment_len(assignment);
let num_changed = reduce(&mut altered_assignment);
let edges_after = edges_before - num_changed;
assert!(
edges_after <= m + n,
"reduce bound not satisfied. n = {}, m = {}, edges after reduce = {} (removed {})",
n,
m,
edges_after,
num_changed,
);
assert_assignments_equal(&assignment, &altered_assignment);
}
fn assignment_len(assignments: &[StakedAssignment<AccountId>]) -> u32 {
let mut counter = 0;
assignments
.iter()
.for_each(|x| x.distribution.iter().for_each(|_| counter += 1));
counter
}