feat: initialize Kurdistan SDK - independent fork of Polkadot SDK
This commit is contained in:
@@ -0,0 +1,329 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezkuwi.
|
||||
|
||||
// Pezkuwi 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.
|
||||
|
||||
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use crate::configuration::HostConfiguration;
|
||||
use alloc::vec;
|
||||
use frame_benchmarking::v2::*;
|
||||
use frame_support::traits::fungible::Mutate;
|
||||
use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
|
||||
use pezkuwi_primitives::{
|
||||
HeadData, Id as ParaId, ValidationCode, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE,
|
||||
};
|
||||
use sp_runtime::traits::{One, Saturating};
|
||||
|
||||
pub mod mmr_setup;
|
||||
mod pvf_check;
|
||||
|
||||
use self::pvf_check::{VoteCause, VoteOutcome};
|
||||
|
||||
// 2 ^ 10, because binary search time complexity is O(log(2, n)) and n = 1024 gives us a big and
|
||||
// round number.
|
||||
// Due to the limited number of teyrchains, the number of pruning, upcoming upgrades and cooldowns
|
||||
// shouldn't exceed this number.
|
||||
const SAMPLE_SIZE: u32 = 1024;
|
||||
|
||||
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
||||
let events = frame_system::Pallet::<T>::events();
|
||||
let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
|
||||
// compare to the last event record
|
||||
let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
|
||||
assert_eq!(event, &system_event);
|
||||
}
|
||||
|
||||
fn generate_disordered_pruning<T: Config>() {
|
||||
let mut needs_pruning = Vec::new();
|
||||
|
||||
for i in 0..SAMPLE_SIZE {
|
||||
let id = ParaId::from(i);
|
||||
let block_number = BlockNumberFor::<T>::from(1000u32);
|
||||
needs_pruning.push((id, block_number));
|
||||
}
|
||||
|
||||
PastCodePruning::<T>::put(needs_pruning);
|
||||
}
|
||||
|
||||
pub(crate) fn generate_disordered_upgrades<T: Config>() {
|
||||
let mut upgrades = Vec::new();
|
||||
let mut cooldowns = Vec::new();
|
||||
|
||||
for i in 0..SAMPLE_SIZE {
|
||||
let id = ParaId::from(i);
|
||||
let block_number = BlockNumberFor::<T>::from(1000u32);
|
||||
upgrades.push((id, block_number));
|
||||
cooldowns.push((id, block_number));
|
||||
}
|
||||
|
||||
UpcomingUpgrades::<T>::put(upgrades);
|
||||
UpgradeCooldowns::<T>::put(cooldowns);
|
||||
}
|
||||
|
||||
fn generate_disordered_actions_queue<T: Config>() {
|
||||
let mut queue = Vec::new();
|
||||
let next_session = shared::CurrentSessionIndex::<T>::get().saturating_add(One::one());
|
||||
|
||||
for _ in 0..SAMPLE_SIZE {
|
||||
let id = ParaId::from(1000);
|
||||
queue.push(id);
|
||||
}
|
||||
|
||||
ActionsQueue::<T>::mutate(next_session, |v| {
|
||||
*v = queue;
|
||||
});
|
||||
}
|
||||
|
||||
#[benchmarks]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
#[benchmark]
|
||||
fn force_set_current_code(c: Linear<MIN_CODE_SIZE, MAX_CODE_SIZE>) {
|
||||
let new_code = ValidationCode(vec![0; c as usize]);
|
||||
let para_id = ParaId::from(c as u32);
|
||||
CurrentCodeHash::<T>::insert(¶_id, new_code.hash());
|
||||
generate_disordered_pruning::<T>();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, new_code);
|
||||
|
||||
assert_last_event::<T>(Event::CurrentCodeUpdated(para_id).into());
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_set_current_head(s: Linear<MIN_CODE_SIZE, MAX_HEAD_DATA_SIZE>) {
|
||||
let new_head = HeadData(vec![0; s as usize]);
|
||||
let para_id = ParaId::from(1000);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, new_head);
|
||||
|
||||
assert_last_event::<T>(Event::CurrentHeadUpdated(para_id).into());
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_set_most_recent_context() {
|
||||
let para_id = ParaId::from(1000);
|
||||
let context = BlockNumberFor::<T>::from(1000u32);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, context);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_schedule_code_upgrade(c: Linear<MIN_CODE_SIZE, MAX_CODE_SIZE>) {
|
||||
let new_code = ValidationCode(vec![0; c as usize]);
|
||||
let para_id = ParaId::from(c as u32);
|
||||
let block = BlockNumberFor::<T>::from(c);
|
||||
generate_disordered_upgrades::<T>();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, new_code, block);
|
||||
|
||||
assert_last_event::<T>(Event::CodeUpgradeScheduled(para_id).into());
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_note_new_head(s: Linear<MIN_CODE_SIZE, MAX_HEAD_DATA_SIZE>) {
|
||||
let para_id = ParaId::from(1000);
|
||||
let new_head = HeadData(vec![0; s as usize]);
|
||||
let old_code_hash = ValidationCode(vec![0]).hash();
|
||||
CurrentCodeHash::<T>::insert(¶_id, old_code_hash);
|
||||
frame_system::Pallet::<T>::set_block_number(10u32.into());
|
||||
// schedule an expired code upgrade for this `para_id` so that force_note_new_head would use
|
||||
// the worst possible code path
|
||||
let expired = frame_system::Pallet::<T>::block_number().saturating_sub(One::one());
|
||||
let config = HostConfiguration::<BlockNumberFor<T>>::default();
|
||||
generate_disordered_pruning::<T>();
|
||||
Pallet::<T>::schedule_code_upgrade(
|
||||
para_id,
|
||||
ValidationCode(vec![0u8; MIN_CODE_SIZE as usize]),
|
||||
expired,
|
||||
&config,
|
||||
UpgradeStrategy::SetGoAheadSignal,
|
||||
);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, new_head);
|
||||
|
||||
assert_last_event::<T>(Event::NewHeadNoted(para_id).into());
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_queue_action() {
|
||||
let para_id = ParaId::from(1000);
|
||||
generate_disordered_actions_queue::<T>();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id);
|
||||
|
||||
let next_session =
|
||||
crate::shared::CurrentSessionIndex::<T>::get().saturating_add(One::one());
|
||||
assert_last_event::<T>(Event::ActionQueued(para_id, next_session).into());
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn add_trusted_validation_code(c: Linear<MIN_CODE_SIZE, MAX_CODE_SIZE>) {
|
||||
let new_code = ValidationCode(vec![0; c as usize]);
|
||||
|
||||
pvf_check::prepare_bypassing_bench::<T>(new_code.clone());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, new_code);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn poke_unused_validation_code() {
|
||||
let code_hash = [0; 32].into();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, code_hash);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn include_pvf_check_statement() {
|
||||
let (stmt, signature) = pvf_check::prepare_inclusion_bench::<T>();
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ =
|
||||
Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, signature);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn include_pvf_check_statement_finalize_upgrade_accept() {
|
||||
let (stmt, signature) =
|
||||
pvf_check::prepare_finalization_bench::<T>(VoteCause::Upgrade, VoteOutcome::Accept);
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ =
|
||||
Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, signature);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn include_pvf_check_statement_finalize_upgrade_reject() {
|
||||
let (stmt, signature) =
|
||||
pvf_check::prepare_finalization_bench::<T>(VoteCause::Upgrade, VoteOutcome::Reject);
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ =
|
||||
Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, signature);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn include_pvf_check_statement_finalize_onboarding_accept() {
|
||||
let (stmt, signature) =
|
||||
pvf_check::prepare_finalization_bench::<T>(VoteCause::Onboarding, VoteOutcome::Accept);
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ =
|
||||
Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, signature);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn include_pvf_check_statement_finalize_onboarding_reject() {
|
||||
let (stmt, signature) =
|
||||
pvf_check::prepare_finalization_bench::<T>(VoteCause::Onboarding, VoteOutcome::Reject);
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ =
|
||||
Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, signature);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn remove_upgrade_cooldown() -> Result<(), BenchmarkError> {
|
||||
let para_id = ParaId::from(1000);
|
||||
let old_code_hash = ValidationCode(vec![0]).hash();
|
||||
CurrentCodeHash::<T>::insert(¶_id, old_code_hash);
|
||||
frame_system::Pallet::<T>::set_block_number(10u32.into());
|
||||
let inclusion = frame_system::Pallet::<T>::block_number().saturating_add(10u32.into());
|
||||
let config = HostConfiguration::<BlockNumberFor<T>>::default();
|
||||
Pallet::<T>::schedule_code_upgrade(
|
||||
para_id,
|
||||
ValidationCode(vec![0u8; MIN_CODE_SIZE as usize]),
|
||||
inclusion,
|
||||
&config,
|
||||
UpgradeStrategy::SetGoAheadSignal,
|
||||
);
|
||||
|
||||
let who: T::AccountId = whitelisted_caller();
|
||||
|
||||
T::Fungible::mint_into(
|
||||
&who,
|
||||
T::CooldownRemovalMultiplier::get().saturating_mul(1_000_000u32.into()),
|
||||
)?;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(who), para_id);
|
||||
|
||||
assert_last_event::<T>(Event::UpgradeCooldownRemoved { para_id }.into());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn authorize_force_set_current_code_hash() {
|
||||
let para_id = ParaId::from(1000);
|
||||
let code = ValidationCode(vec![0; 32]);
|
||||
let new_code_hash = code.hash();
|
||||
let valid_period = BlockNumberFor::<T>::from(1_000_000_u32);
|
||||
ParaLifecycles::<T>::insert(¶_id, ParaLifecycle::Teyrchain);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, new_code_hash, valid_period);
|
||||
|
||||
assert_last_event::<T>(
|
||||
Event::CodeAuthorized {
|
||||
para_id,
|
||||
code_hash: new_code_hash,
|
||||
expire_at: frame_system::Pallet::<T>::block_number().saturating_add(valid_period),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn apply_authorized_force_set_current_code(c: Linear<MIN_CODE_SIZE, MAX_CODE_SIZE>) {
|
||||
let code = ValidationCode(vec![0; c as usize]);
|
||||
let para_id = ParaId::from(1000);
|
||||
let expire_at =
|
||||
frame_system::Pallet::<T>::block_number().saturating_add(BlockNumberFor::<T>::from(c));
|
||||
AuthorizedCodeHash::<T>::insert(
|
||||
¶_id,
|
||||
AuthorizedCodeHashAndExpiry::from((code.hash(), expire_at)),
|
||||
);
|
||||
generate_disordered_pruning::<T>();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, para_id, code);
|
||||
|
||||
assert_last_event::<T>(Event::CurrentCodeUpdated(para_id).into());
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
Pallet,
|
||||
crate::mock::new_test_ext(Default::default()),
|
||||
crate::mock::Test
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezkuwi.
|
||||
|
||||
// Pezkuwi 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.
|
||||
|
||||
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Implements benchmarking setup for the `merkle-mountain-range` pallet.
|
||||
|
||||
use crate::paras::*;
|
||||
use pallet_mmr::BenchmarkHelper;
|
||||
use sp_std::vec;
|
||||
|
||||
/// Struct to setup benchmarks for the `merkle-mountain-range` pallet.
|
||||
pub struct MmrSetup<T>(core::marker::PhantomData<T>);
|
||||
|
||||
impl<T> BenchmarkHelper for MmrSetup<T>
|
||||
where
|
||||
T: Config,
|
||||
{
|
||||
fn setup() {
|
||||
// Create a head with 1024 bytes of data.
|
||||
let head = vec![42u8; 1024];
|
||||
|
||||
for para in 0..MAX_PARA_HEADS {
|
||||
let id = (para as u32).into();
|
||||
let h = head.clone().into();
|
||||
Pallet::<T>::heads_insert(&id, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezkuwi.
|
||||
|
||||
// Pezkuwi 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.
|
||||
|
||||
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! This module focuses on the benchmarking of the `include_pvf_check_statement` dispatchable.
|
||||
|
||||
use crate::{configuration, paras::*, shared::Pallet as ParasShared};
|
||||
use alloc::{vec, vec::Vec};
|
||||
use frame_support::assert_ok;
|
||||
use frame_system::RawOrigin;
|
||||
use pezkuwi_primitives::{HeadData, Id as ParaId, ValidationCode, ValidatorId, ValidatorIndex};
|
||||
use sp_application_crypto::RuntimeAppPublic;
|
||||
|
||||
// Constants for the benchmarking
|
||||
const SESSION_INDEX: SessionIndex = 1;
|
||||
const VALIDATOR_NUM: usize = 800;
|
||||
const CAUSES_NUM: usize = 100;
|
||||
fn validation_code() -> ValidationCode {
|
||||
ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
}
|
||||
fn old_validation_code() -> ValidationCode {
|
||||
ValidationCode(vec![9, 8, 7, 6, 5, 4, 3, 2, 1])
|
||||
}
|
||||
|
||||
/// Prepares the PVF check statement and the validator signature to pass into
|
||||
/// `include_pvf_check_statement` during benchmarking phase.
|
||||
///
|
||||
/// It won't trigger finalization, so we expect the benchmarking will only measure the performance
|
||||
/// of only vote accounting.
|
||||
pub fn prepare_inclusion_bench<T>() -> (PvfCheckStatement, ValidatorSignature)
|
||||
where
|
||||
T: Config + shared::Config,
|
||||
{
|
||||
initialize::<T>();
|
||||
// we do not plan to trigger finalization, thus the cause is inconsequential.
|
||||
initialize_pvf_active_vote::<T>(VoteCause::Onboarding, CAUSES_NUM);
|
||||
|
||||
// `unwrap` cannot panic here since the `initialize` function should initialize validators count
|
||||
// to be more than 0.
|
||||
//
|
||||
// VoteDirection doesn't matter here as well.
|
||||
let stmt_n_sig = generate_statements::<T>(VoteOutcome::Accept).next().unwrap();
|
||||
|
||||
stmt_n_sig
|
||||
}
|
||||
|
||||
/// Prepares conditions for benchmarking of the finalization part of `include_pvf_check_statement`.
|
||||
///
|
||||
/// This function will initialize a PVF pre-check vote, then submit a number of PVF pre-checking
|
||||
/// statements so that to achieve the quorum only one statement is left. This statement is returned
|
||||
/// from this function and is expected to be passed into `include_pvf_check_statement` during the
|
||||
/// benchmarking phase.
|
||||
pub fn prepare_finalization_bench<T>(
|
||||
cause: VoteCause,
|
||||
outcome: VoteOutcome,
|
||||
) -> (PvfCheckStatement, ValidatorSignature)
|
||||
where
|
||||
T: Config + shared::Config,
|
||||
{
|
||||
initialize::<T>();
|
||||
initialize_pvf_active_vote::<T>(cause, CAUSES_NUM);
|
||||
|
||||
let mut stmts = generate_statements::<T>(outcome).collect::<Vec<_>>();
|
||||
// this should be ensured by the `initialize` function.
|
||||
assert!(stmts.len() > 2);
|
||||
|
||||
// stash the last statement to be used in the benchmarking phase.
|
||||
let stmt_n_sig = stmts.pop().unwrap();
|
||||
|
||||
for (stmt, sig) in stmts {
|
||||
let r = Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, sig);
|
||||
assert!(r.is_ok());
|
||||
}
|
||||
|
||||
stmt_n_sig
|
||||
}
|
||||
|
||||
/// Prepares storage for invoking `add_trusted_validation_code` with several paras initializing to
|
||||
/// the same code.
|
||||
pub fn prepare_bypassing_bench<T>(validation_code: ValidationCode)
|
||||
where
|
||||
T: Config + shared::Config,
|
||||
{
|
||||
// Suppose a sensible number of paras initialize to the same code.
|
||||
const PARAS_NUM: usize = 10;
|
||||
|
||||
initialize::<T>();
|
||||
for i in 0..PARAS_NUM {
|
||||
let id = ParaId::from(i as u32);
|
||||
assert_ok!(Pallet::<T>::schedule_para_initialize(
|
||||
id,
|
||||
ParaGenesisArgs {
|
||||
para_kind: ParaKind::Teyrchain,
|
||||
genesis_head: HeadData(vec![1, 2, 3, 4]),
|
||||
validation_code: validation_code.clone(),
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// What caused the PVF pre-checking vote?
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum VoteCause {
|
||||
Onboarding,
|
||||
Upgrade,
|
||||
}
|
||||
|
||||
/// The outcome of the PVF pre-checking vote.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum VoteOutcome {
|
||||
Accept,
|
||||
Reject,
|
||||
}
|
||||
|
||||
fn initialize<T>()
|
||||
where
|
||||
T: Config + shared::Config,
|
||||
{
|
||||
// 0. generate a list of validators
|
||||
let validators = (0..VALIDATOR_NUM)
|
||||
.map(|_| <ValidatorId as RuntimeAppPublic>::generate_pair(None))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// 1. Make sure PVF pre-checking is enabled in the config.
|
||||
let config = configuration::ActiveConfig::<T>::get();
|
||||
configuration::Pallet::<T>::force_set_active_config(config.clone());
|
||||
|
||||
// 2. initialize a new session with deterministic validator set.
|
||||
ParasShared::<T>::set_active_validators_ascending(validators.clone());
|
||||
ParasShared::<T>::set_session_index(SESSION_INDEX);
|
||||
}
|
||||
|
||||
/// Creates a new PVF pre-checking active vote.
|
||||
///
|
||||
/// The subject of the vote (i.e. validation code) and the cause (upgrade/onboarding) is specified
|
||||
/// by the test setup.
|
||||
fn initialize_pvf_active_vote<T>(vote_cause: VoteCause, causes_num: usize)
|
||||
where
|
||||
T: Config + shared::Config,
|
||||
{
|
||||
for i in 0..causes_num {
|
||||
let id = ParaId::from(i as u32);
|
||||
|
||||
if vote_cause == VoteCause::Upgrade {
|
||||
// we do care about validation code being actually different, since there is a check
|
||||
// that prevents upgrading to the same code.
|
||||
let old_validation_code = old_validation_code();
|
||||
let validation_code = validation_code();
|
||||
|
||||
let mut teyrchains = TeyrchainsCache::new();
|
||||
Pallet::<T>::initialize_para_now(
|
||||
&mut teyrchains,
|
||||
id,
|
||||
&ParaGenesisArgs {
|
||||
para_kind: ParaKind::Teyrchain,
|
||||
genesis_head: HeadData(vec![1, 2, 3, 4]),
|
||||
validation_code: old_validation_code,
|
||||
},
|
||||
);
|
||||
// don't care about performance here, but we do care about robustness. So dump the cache
|
||||
// asap.
|
||||
drop(teyrchains);
|
||||
|
||||
Pallet::<T>::schedule_code_upgrade(
|
||||
id,
|
||||
validation_code,
|
||||
/* relay_parent_number */ 1u32.into(),
|
||||
&configuration::ActiveConfig::<T>::get(),
|
||||
UpgradeStrategy::SetGoAheadSignal,
|
||||
);
|
||||
} else {
|
||||
let r = Pallet::<T>::schedule_para_initialize(
|
||||
id,
|
||||
ParaGenesisArgs {
|
||||
para_kind: ParaKind::Teyrchain,
|
||||
genesis_head: HeadData(vec![1, 2, 3, 4]),
|
||||
validation_code: validation_code(),
|
||||
},
|
||||
);
|
||||
assert!(r.is_ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a list of votes combined with signatures for the active validator set. The number of
|
||||
/// votes is equal to the minimum number of votes required to reach the threshold for either accept
|
||||
/// or reject.
|
||||
fn generate_statements<T>(
|
||||
vote_outcome: VoteOutcome,
|
||||
) -> impl Iterator<Item = (PvfCheckStatement, ValidatorSignature)>
|
||||
where
|
||||
T: Config + shared::Config,
|
||||
{
|
||||
let validators = shared::ActiveValidatorKeys::<T>::get();
|
||||
|
||||
let accept_threshold = pezkuwi_primitives::supermajority_threshold(validators.len());
|
||||
let required_votes = match vote_outcome {
|
||||
VoteOutcome::Accept => accept_threshold,
|
||||
VoteOutcome::Reject => validators.len() - accept_threshold,
|
||||
};
|
||||
(0..required_votes).map(move |validator_index| {
|
||||
let stmt = PvfCheckStatement {
|
||||
accept: vote_outcome == VoteOutcome::Accept,
|
||||
subject: validation_code().hash(),
|
||||
session_index: SESSION_INDEX,
|
||||
|
||||
validator_index: ValidatorIndex(validator_index as u32),
|
||||
};
|
||||
let signature = validators[validator_index].sign(&stmt.signing_payload()).unwrap();
|
||||
|
||||
(stmt, signature)
|
||||
})
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user