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,272 @@
// 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.
//! Benchmarks for the Sassafras pallet.
use crate::*;
use pezsp_consensus_sassafras::{vrf::VrfSignature, EphemeralPublic, EpochConfiguration};
use pezframe_benchmarking::v2::*;
use pezframe_support::traits::Hooks;
use pezframe_system::RawOrigin;
const LOG_TARGET: &str = "sassafras::benchmark";
const TICKETS_DATA: &[u8] = include_bytes!("data/25_tickets_100_auths.bin");
fn make_dummy_vrf_signature() -> VrfSignature {
// This leverages our knowledge about serialized vrf signature structure.
// Mostly to avoid to import all the bandersnatch primitive just for this test.
let buf = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xb5, 0x5f, 0x8e, 0xc7, 0x68, 0xf5, 0x05, 0x3f, 0xa9,
0x18, 0xca, 0x07, 0x13, 0xc7, 0x4b, 0xa3, 0x9a, 0x97, 0xd3, 0x76, 0x8f, 0x0c, 0xbf, 0x2e,
0xd4, 0xf9, 0x3a, 0xae, 0xc1, 0x96, 0x2a, 0x64, 0x80,
];
VrfSignature::decode(&mut &buf[..]).unwrap()
}
#[benchmarks]
mod benchmarks {
use super::*;
// For first block (#1) we do some extra operation.
// But is a one shot operation, so we don't account for it here.
// We use 0, as it will be the path used by all the blocks with n != 1
#[benchmark]
fn on_initialize() {
let block_num = BlockNumberFor::<T>::from(0u32);
let slot_claim = SlotClaim {
authority_idx: 0,
slot: Default::default(),
vrf_signature: make_dummy_vrf_signature(),
ticket_claim: None,
};
pezframe_system::Pallet::<T>::deposit_log((&slot_claim).into());
// We currently don't account for the potential weight added by the `on_finalize`
// incremental sorting of the tickets.
#[block]
{
// According to `Hooks` trait docs, `on_finalize` `Weight` should be bundled
// together with `on_initialize` `Weight`.
Pallet::<T>::on_initialize(block_num);
Pallet::<T>::on_finalize(block_num)
}
}
// Weight for the default internal epoch change trigger.
//
// Parameters:
// - `x`: number of authorities (1:100).
// - `y`: epoch length in slots (1000:5000)
//
// This accounts for the worst case which includes:
// - load the full ring context.
// - recompute the ring verifier.
// - sorting the epoch tickets in one shot
// (here we account for the very unlucky scenario where we haven't done any sort work yet)
// - pending epoch change config.
//
// For this bench we assume a redundancy factor of 2 (suggested value to be used in prod).
#[benchmark]
fn enact_epoch_change(x: Linear<1, 100>, y: Linear<1000, 5000>) {
let authorities_count = x as usize;
let epoch_length = y as u32;
let redundancy_factor = 2;
let unsorted_tickets_count = epoch_length * redundancy_factor;
let mut meta = TicketsMetadata { unsorted_tickets_count, tickets_count: [0, 0] };
let config = EpochConfiguration { redundancy_factor, attempts_number: 32 };
// Triggers ring verifier computation for `x` authorities
let mut raw_data = TICKETS_DATA;
let (authorities, _): (Vec<AuthorityId>, Vec<TicketEnvelope>) =
Decode::decode(&mut raw_data).expect("Failed to decode tickets buffer");
let next_authorities: Vec<_> = authorities[..authorities_count].to_vec();
let next_authorities = WeakBoundedVec::force_from(next_authorities, None);
NextAuthorities::<T>::set(next_authorities);
// Triggers JIT sorting tickets
(0..meta.unsorted_tickets_count)
.collect::<Vec<_>>()
.chunks(SEGMENT_MAX_SIZE as usize)
.enumerate()
.for_each(|(segment_id, chunk)| {
let segment = chunk
.iter()
.map(|i| {
let id_bytes = crate::hashing::blake2_128(&i.to_le_bytes());
TicketId::from_le_bytes(id_bytes)
})
.collect::<Vec<_>>();
UnsortedSegments::<T>::insert(
segment_id as u32,
BoundedVec::truncate_from(segment),
);
});
// Triggers some code related to config change (dummy values)
NextEpochConfig::<T>::set(Some(config));
PendingEpochConfigChange::<T>::set(Some(config));
// Triggers the cleanup of the "just elapsed" epoch tickets (i.e. the current one)
let epoch_tag = EpochIndex::<T>::get() & 1;
meta.tickets_count[epoch_tag as usize] = epoch_length;
(0..epoch_length).for_each(|i| {
let id_bytes = crate::hashing::blake2_128(&i.to_le_bytes());
let id = TicketId::from_le_bytes(id_bytes);
TicketsIds::<T>::insert((epoch_tag as u8, i), id);
let body = TicketBody {
attempt_idx: i,
erased_public: EphemeralPublic::from([i as u8; 32]),
revealed_public: EphemeralPublic::from([i as u8; 32]),
};
TicketsData::<T>::set(id, Some(body));
});
TicketsMeta::<T>::set(meta);
#[block]
{
Pallet::<T>::should_end_epoch(BlockNumberFor::<T>::from(3u32));
let next_authorities = Pallet::<T>::next_authorities();
// Using a different set of authorities triggers the recomputation of ring verifier.
Pallet::<T>::enact_epoch_change(Default::default(), next_authorities);
}
}
#[benchmark]
fn submit_tickets(x: Linear<1, 25>) {
let tickets_count = x as usize;
let mut raw_data = TICKETS_DATA;
let (authorities, tickets): (Vec<AuthorityId>, Vec<TicketEnvelope>) =
Decode::decode(&mut raw_data).expect("Failed to decode tickets buffer");
log::debug!(target: LOG_TARGET, "PreBuiltTickets: {} tickets, {} authorities", tickets.len(), authorities.len());
// Set `NextRandomness` to the same value used for pre-built tickets
// (see `make_tickets_data` test).
NextRandomness::<T>::set([0; 32]);
Pallet::<T>::update_ring_verifier(&authorities);
// Set next epoch config to accept all the tickets
let next_config = EpochConfiguration { attempts_number: 1, redundancy_factor: u32::MAX };
NextEpochConfig::<T>::set(Some(next_config));
// Use the authorities in the pre-build tickets
let authorities = WeakBoundedVec::force_from(authorities, None);
NextAuthorities::<T>::set(authorities);
let tickets = tickets[..tickets_count].to_vec();
let tickets = BoundedVec::truncate_from(tickets);
log::debug!(target: LOG_TARGET, "Submitting {} tickets", tickets_count);
#[extrinsic_call]
submit_tickets(RawOrigin::None, tickets);
}
#[benchmark]
fn plan_config_change() {
let config = EpochConfiguration { redundancy_factor: 1, attempts_number: 10 };
#[extrinsic_call]
plan_config_change(RawOrigin::Root, config);
}
// Construction of ring verifier
#[benchmark]
fn update_ring_verifier(x: Linear<1, 100>) {
let authorities_count = x as usize;
let mut raw_data = TICKETS_DATA;
let (authorities, _): (Vec<AuthorityId>, Vec<TicketEnvelope>) =
Decode::decode(&mut raw_data).expect("Failed to decode tickets buffer");
let authorities: Vec<_> = authorities[..authorities_count].to_vec();
#[block]
{
Pallet::<T>::update_ring_verifier(&authorities);
}
}
// Bare loading of ring context.
//
// It is interesting to see how this compares to 'update_ring_verifier', which
// also recomputes and stores the new verifier.
#[benchmark]
fn load_ring_context() {
#[block]
{
let _ring_ctx = RingContext::<T>::get().unwrap();
}
}
// Tickets segments sorting function benchmark.
#[benchmark]
fn sort_segments(x: Linear<1, 100>) {
let segments_count = x as u32;
let tickets_count = segments_count * SEGMENT_MAX_SIZE;
// Construct a bunch of dummy tickets
let tickets: Vec<_> = (0..tickets_count)
.map(|i| {
let body = TicketBody {
attempt_idx: i,
erased_public: EphemeralPublic::from([i as u8; 32]),
revealed_public: EphemeralPublic::from([i as u8; 32]),
};
let id_bytes = crate::hashing::blake2_128(&i.to_le_bytes());
let id = TicketId::from_le_bytes(id_bytes);
(id, body)
})
.collect();
for (chunk_id, chunk) in tickets.chunks(SEGMENT_MAX_SIZE as usize).enumerate() {
let segment: Vec<TicketId> = chunk
.iter()
.map(|(id, body)| {
TicketsData::<T>::set(id, Some(body.clone()));
*id
})
.collect();
let segment = BoundedVec::truncate_from(segment);
UnsortedSegments::<T>::insert(chunk_id as u32, segment);
}
// Update metadata
let mut meta = TicketsMeta::<T>::get();
meta.unsorted_tickets_count = tickets_count;
TicketsMeta::<T>::set(meta);
log::debug!(target: LOG_TARGET, "Before sort: {:?}", meta);
#[block]
{
Pallet::<T>::sort_segments(u32::MAX, 0, &mut meta);
}
log::debug!(target: LOG_TARGET, "After sort: {:?}", meta);
}
}
@@ -0,0 +1,99 @@
# Benchmarks High Level Results
- **Ring size**: the actual number of validators for an epoch
- **Domain size**: a value which bounds the max size of the ring (max_ring_size = domain_size - 256)
## Verify Submitted Tickets (extrinsic)
`x` = Number of tickets
### Domain=1024, Uncompressed (~ 13 ms + 11·x ms)
Time ~= 13400
+ x 11390
µs
### Domain=1024, Compressed (~ 13 ms + 11·x ms)
Time ~= 13120
+ x 11370
µs
### Domain=2048, Uncompressed (~ 26 ms + 11·x ms)
Time ~= 26210
+ x 11440
µs
### Domain=2048, Compressed (~ 26 ms + 11·x ms)
Time ~= 26250
+ x 11460
µs
### Conclusions
- Verification doesn't depend on ring size as verification key is already constructed.
- The call is fast as far as the max number of tickets which can be submitted in one shot
is appropriately bounded.
- Currently, the bound is set equal epoch length, which iirc for Pezkuwi is 3600.
In this case if all the tickets are submitted in one shot timing is expected to be
~39 seconds, which is not acceptable. TODO: find a sensible bound
---
## Recompute Ring Verifier Key (on epoch change)
`x` = Ring size
### Domain=1024, Uncompressed (~ 50 ms)
Time ~= 54070
+ x 98.53
µs
### Domain=1024, Compressed (~ 700 ms)
Time ~= 733700
+ x 90.49
µs
### Domain=2048, Uncompressed (~ 100 ms)
Time ~= 107700
+ x 108.5
µs
### Domain=2048, Compressed (~ 1.5 s)
Time ~= 1462400
+ x 65.14
µs
### Conclusions
- Here we load the full ring context data to recompute verification key for the epoch
- Ring size influence is marginal (e.g. for 1500 validators → ~98 ms to be added to the base time)
- This step is performed at most once per epoch (if validator set changes).
- Domain size for ring context influence the PoV size (see next paragraph)
- Decompression heavily influence timings (1.5sec vs 100ms for same domain size)
---
## Ring Context Data Size
### Domain=1024, Uncompressed
295412 bytes = ~ 300 KiB
### Domain=1024, Compressed
147716 bytes = ~ 150 KiB
### Domain=2048, Uncompressed
590324 bytes = ~ 590 KiB
### Domain=2048, Compressed
295172 bytes = ~ 300 KiB
@@ -0,0 +1,274 @@
# Segments Incremental Sorting Strategy Empirical Results
Parameters:
- 128 segments
- segment max length 128
- 32767 random tickets ids
- epoch length 3600 (== max tickets to keep)
The table shows the comparison between the segments left in the unsorted segments buffer
and the number of new tickets which are added from the last segment to the sorted tickets
buffer (i.e. how many tickets we retain from the last processed segment)
| Segments Left | Tickets Pushed |
|-----|-----|
| 255 | 128 |
| 254 | 128 |
| 253 | 128 |
| 252 | 128 |
| 251 | 128 |
| 250 | 128 |
| 249 | 128 |
| 248 | 128 |
| 247 | 128 |
| 246 | 128 |
| 245 | 128 |
| 244 | 128 |
| 243 | 128 |
| 242 | 128 |
| 241 | 128 |
| 240 | 128 |
| 239 | 128 |
| 238 | 128 |
| 237 | 128 |
| 236 | 128 |
| 235 | 128 |
| 234 | 128 |
| 233 | 128 |
| 232 | 128 |
| 231 | 128 |
| 230 | 128 |
| 229 | 128 |
| 228 | 128 |
| 227 | 128 |
| 226 | 126 |
| 225 | 117 |
| 224 | 120 |
| 223 | 110 |
| 222 | 110 |
| 221 | 102 |
| 220 | 107 |
| 219 | 96 |
| 218 | 105 |
| 217 | 92 |
| 216 | 91 |
| 215 | 85 |
| 214 | 84 |
| 213 | 88 |
| 212 | 77 |
| 211 | 86 |
| 210 | 73 |
| 209 | 73 |
| 208 | 81 |
| 207 | 83 |
| 206 | 70 |
| 205 | 84 |
| 204 | 71 |
| 203 | 63 |
| 202 | 60 |
| 201 | 53 |
| 200 | 73 |
| 199 | 55 |
| 198 | 65 |
| 197 | 62 |
| 196 | 55 |
| 195 | 63 |
| 194 | 61 |
| 193 | 48 |
| 192 | 67 |
| 191 | 61 |
| 190 | 55 |
| 189 | 49 |
| 188 | 60 |
| 187 | 49 |
| 186 | 51 |
| 185 | 53 |
| 184 | 47 |
| 183 | 51 |
| 182 | 51 |
| 181 | 53 |
| 180 | 42 |
| 179 | 43 |
| 178 | 48 |
| 177 | 46 |
| 176 | 39 |
| 175 | 54 |
| 174 | 39 |
| 173 | 44 |
| 172 | 51 |
| 171 | 49 |
| 170 | 48 |
| 169 | 48 |
| 168 | 41 |
| 167 | 39 |
| 166 | 41 |
| 165 | 40 |
| 164 | 43 |
| 163 | 53 |
| 162 | 51 |
| 161 | 36 |
| 160 | 45 |
| 159 | 40 |
| 158 | 29 |
| 157 | 37 |
| 156 | 31 |
| 155 | 38 |
| 154 | 31 |
| 153 | 38 |
| 152 | 39 |
| 151 | 30 |
| 150 | 37 |
| 149 | 42 |
| 148 | 35 |
| 147 | 33 |
| 146 | 35 |
| 145 | 37 |
| 144 | 38 |
| 143 | 31 |
| 142 | 38 |
| 141 | 38 |
| 140 | 27 |
| 139 | 31 |
| 138 | 25 |
| 137 | 31 |
| 136 | 26 |
| 135 | 30 |
| 134 | 31 |
| 133 | 37 |
| 132 | 29 |
| 131 | 24 |
| 130 | 31 |
| 129 | 34 |
| 128 | 31 |
| 127 | 28 |
| 126 | 28 |
| 125 | 19 |
| 124 | 27 |
| 123 | 29 |
| 122 | 36 |
| 121 | 32 |
| 120 | 29 |
| 119 | 28 |
| 118 | 33 |
| 117 | 18 |
| 116 | 28 |
| 115 | 27 |
| 114 | 28 |
| 113 | 21 |
| 112 | 23 |
| 111 | 19 |
| 110 | 21 |
| 109 | 20 |
| 108 | 26 |
| 107 | 23 |
| 106 | 30 |
| 105 | 31 |
| 104 | 19 |
| 103 | 25 |
| 102 | 23 |
| 101 | 29 |
| 100 | 18 |
| 99 | 19 |
| 98 | 20 |
| 97 | 21 |
| 96 | 23 |
| 95 | 20 |
| 94 | 27 |
| 93 | 20 |
| 92 | 22 |
| 91 | 23 |
| 90 | 23 |
| 89 | 20 |
| 88 | 15 |
| 87 | 17 |
| 86 | 28 |
| 85 | 25 |
| 84 | 10 |
| 83 | 20 |
| 82 | 23 |
| 81 | 28 |
| 80 | 17 |
| 79 | 23 |
| 78 | 24 |
| 77 | 22 |
| 76 | 18 |
| 75 | 25 |
| 74 | 31 |
| 73 | 27 |
| 72 | 19 |
| 71 | 13 |
| 70 | 17 |
| 69 | 24 |
| 68 | 20 |
| 67 | 12 |
| 66 | 17 |
| 65 | 16 |
| 64 | 26 |
| 63 | 24 |
| 62 | 12 |
| 61 | 19 |
| 60 | 18 |
| 59 | 20 |
| 58 | 18 |
| 57 | 12 |
| 56 | 15 |
| 55 | 17 |
| 54 | 14 |
| 53 | 25 |
| 52 | 22 |
| 51 | 15 |
| 50 | 17 |
| 49 | 15 |
| 48 | 17 |
| 47 | 18 |
| 46 | 17 |
| 45 | 23 |
| 44 | 17 |
| 43 | 13 |
| 42 | 15 |
| 41 | 18 |
| 40 | 11 |
| 39 | 19 |
| 38 | 18 |
| 37 | 12 |
| 36 | 19 |
| 35 | 18 |
| 34 | 15 |
| 33 | 12 |
| 32 | 25 |
| 31 | 20 |
| 30 | 24 |
| 29 | 20 |
| 28 | 10 |
| 27 | 15 |
| 26 | 16 |
| 25 | 15 |
| 24 | 15 |
| 23 | 13 |
| 22 | 12 |
| 21 | 14 |
| 20 | 19 |
| 19 | 17 |
| 18 | 17 |
| 17 | 18 |
| 16 | 15 |
| 15 | 13 |
| 14 | 11 |
| 13 | 16 |
| 12 | 13 |
| 11 | 18 |
| 10 | 19 |
| 9 | 10 |
| 8 | 7 |
| 7 | 15 |
| 6 | 12 |
| 5 | 12 |
| 4 | 17 |
| 3 | 14 |
| 2 | 17 |
| 1 | 9 |
| 0 | 13 |
# Graph of the same data
![graph](tickets-sort.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because it is too large Load Diff
+352
View File
@@ -0,0 +1,352 @@
// 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.
//! Test utilities for Sassafras pallet.
use crate::{self as pezpallet_sassafras, EpochChangeInternalTrigger, *};
use pezframe_support::{
derive_impl,
traits::{ConstU32, OnFinalize, OnInitialize},
};
use pezsp_consensus_sassafras::{
digests::SlotClaim,
vrf::{RingProver, VrfSignature},
AuthorityIndex, AuthorityPair, EpochConfiguration, Slot, TicketBody, TicketEnvelope, TicketId,
};
use pezsp_core::{
crypto::{ByteArray, Pair, UncheckedFrom, VrfSecret, Wraps},
ed25519::Public as EphemeralPublic,
H256, U256,
};
use pezsp_runtime::{
testing::{Digest, DigestItem, Header},
BuildStorage,
};
const LOG_TARGET: &str = "sassafras::tests";
const EPOCH_LENGTH: u32 = 10;
const MAX_AUTHORITIES: u32 = 100;
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
impl pezframe_system::Config for Test {
type Block = pezframe_system::mocking::MockBlock<Test>;
}
impl<C> pezframe_system::offchain::CreateTransactionBase<C> for Test
where
RuntimeCall: From<C>,
{
type RuntimeCall = RuntimeCall;
type Extrinsic = pezframe_system::mocking::MockUncheckedExtrinsic<Test>;
}
impl<C> pezframe_system::offchain::CreateBare<C> for Test
where
RuntimeCall: From<C>,
{
fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic {
pezframe_system::mocking::MockUncheckedExtrinsic::<Test>::new_bare(call)
}
}
impl pezpallet_sassafras::Config for Test {
type EpochLength = ConstU32<EPOCH_LENGTH>;
type MaxAuthorities = ConstU32<MAX_AUTHORITIES>;
type EpochChangeTrigger = EpochChangeInternalTrigger;
type WeightInfo = ();
}
pezframe_support::construct_runtime!(
pub enum Test {
System: pezframe_system,
Sassafras: pezpallet_sassafras,
}
);
// Default used for most of the tests.
//
// The redundancy factor has been set to max value to accept all submitted
// tickets without worrying about the threshold.
pub const TEST_EPOCH_CONFIGURATION: EpochConfiguration =
EpochConfiguration { redundancy_factor: u32::MAX, attempts_number: 5 };
/// Build and returns test storage externalities
pub fn new_test_ext(authorities_len: usize) -> pezsp_io::TestExternalities {
new_test_ext_with_pairs(authorities_len, false).1
}
/// Build and returns test storage externalities and authority set pairs used
/// by Sassafras genesis configuration.
pub fn new_test_ext_with_pairs(
authorities_len: usize,
with_ring_context: bool,
) -> (Vec<AuthorityPair>, pezsp_io::TestExternalities) {
let pairs = (0..authorities_len)
.map(|i| AuthorityPair::from_seed(&U256::from(i).to_big_endian()))
.collect::<Vec<_>>();
let authorities: Vec<_> = pairs.iter().map(|p| p.public()).collect();
let mut storage = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
pezpallet_sassafras::GenesisConfig::<Test> {
authorities: authorities.clone(),
epoch_config: TEST_EPOCH_CONFIGURATION,
_phantom: core::marker::PhantomData,
}
.assimilate_storage(&mut storage)
.unwrap();
let mut ext: pezsp_io::TestExternalities = storage.into();
if with_ring_context {
ext.execute_with(|| {
log::debug!(target: LOG_TARGET, "Building testing ring context");
let ring_ctx = vrf::RingContext::new_testing();
RingContext::<Test>::set(Some(ring_ctx.clone()));
Sassafras::update_ring_verifier(&authorities);
});
}
(pairs, ext)
}
fn make_ticket_with_prover(
attempt: u32,
pair: &AuthorityPair,
prover: &RingProver,
) -> TicketEnvelope {
log::debug!("attempt: {}", attempt);
// Values are referring to the next epoch
let epoch = Sassafras::epoch_index() + 1;
let randomness = Sassafras::next_randomness();
// Make a dummy ephemeral public that hopefully is unique within one test instance.
// In the tests, the values within the erased public are just used to compare
// ticket bodies, so it is not important to be a valid key.
let mut raw: [u8; 32] = [0; 32];
raw.copy_from_slice(&pair.public().as_slice()[0..32]);
let erased_public = EphemeralPublic::unchecked_from(raw);
let revealed_public = erased_public;
let ticket_id_input = vrf::ticket_id_input(&randomness, attempt, epoch);
let body = TicketBody { attempt_idx: attempt, erased_public, revealed_public };
let sign_data = vrf::ticket_body_sign_data(&body, ticket_id_input);
let signature = pair.as_ref().ring_vrf_sign(&sign_data, &prover);
// Ticket-id can be generated via vrf-preout.
// We don't care that much about its value here.
TicketEnvelope { body, signature }
}
pub fn make_prover(pair: &AuthorityPair) -> RingProver {
let public = pair.public();
let mut prover_idx = None;
let ring_ctx = Sassafras::ring_context().unwrap();
let pks: Vec<pezsp_core::bandersnatch::Public> = Sassafras::authorities()
.iter()
.enumerate()
.map(|(idx, auth)| {
if public == *auth {
prover_idx = Some(idx);
}
*auth.as_ref()
})
.collect();
log::debug!("Building prover. Ring size: {}", pks.len());
let prover = ring_ctx.prover(&pks, prover_idx.unwrap());
log::debug!("Done");
prover
}
/// Construct `attempts` tickets envelopes for the next epoch.
///
/// E.g. by passing an optional threshold
pub fn make_tickets(attempts: u32, pair: &AuthorityPair) -> Vec<TicketEnvelope> {
let prover = make_prover(pair);
(0..attempts)
.into_iter()
.map(|attempt| make_ticket_with_prover(attempt, pair, &prover))
.collect()
}
pub fn make_ticket_body(attempt_idx: u32, pair: &AuthorityPair) -> (TicketId, TicketBody) {
// Values are referring to the next epoch
let epoch = Sassafras::epoch_index() + 1;
let randomness = Sassafras::next_randomness();
let ticket_id_input = vrf::ticket_id_input(&randomness, attempt_idx, epoch);
let ticket_id_pre_output = pair.as_inner_ref().vrf_pre_output(&ticket_id_input);
let id = vrf::make_ticket_id(&ticket_id_pre_output);
// Make a dummy ephemeral public that hopefully is unique within one test instance.
// In the tests, the values within the erased public are just used to compare
// ticket bodies, so it is not important to be a valid key.
let mut raw: [u8; 32] = [0; 32];
raw[..16].copy_from_slice(&pair.public().as_slice()[0..16]);
raw[16..].copy_from_slice(&id.to_le_bytes());
let erased_public = EphemeralPublic::unchecked_from(raw);
let revealed_public = erased_public;
let body = TicketBody { attempt_idx, erased_public, revealed_public };
(id, body)
}
pub fn make_dummy_ticket_body(attempt_idx: u32) -> (TicketId, TicketBody) {
let hash = pezsp_crypto_hashing::blake2_256(&attempt_idx.to_le_bytes());
let erased_public = EphemeralPublic::unchecked_from(hash);
let revealed_public = erased_public;
let body = TicketBody { attempt_idx, erased_public, revealed_public };
let mut bytes = [0u8; 16];
bytes.copy_from_slice(&hash[..16]);
let id = TicketId::from_le_bytes(bytes);
(id, body)
}
pub fn make_ticket_bodies(
number: u32,
pair: Option<&AuthorityPair>,
) -> Vec<(TicketId, TicketBody)> {
(0..number)
.into_iter()
.map(|i| match pair {
Some(pair) => make_ticket_body(i, pair),
None => make_dummy_ticket_body(i),
})
.collect()
}
/// Persist the given tickets in the unsorted segments buffer.
///
/// This function skips all the checks performed by the `submit_tickets` extrinsic and
/// directly appends the tickets to the `UnsortedSegments` structure.
pub fn persist_next_epoch_tickets_as_segments(tickets: &[(TicketId, TicketBody)]) {
let mut ids = Vec::with_capacity(tickets.len());
tickets.iter().for_each(|(id, body)| {
TicketsData::<Test>::set(id, Some(body.clone()));
ids.push(*id);
});
let max_chunk_size = Sassafras::epoch_length() as usize;
ids.chunks(max_chunk_size).for_each(|chunk| {
Sassafras::append_tickets(BoundedVec::truncate_from(chunk.to_vec()));
})
}
/// Calls the [`persist_next_epoch_tickets_as_segments`] and then proceeds to the
/// sorting of the candidates.
///
/// Only "winning" tickets are left.
pub fn persist_next_epoch_tickets(tickets: &[(TicketId, TicketBody)]) {
persist_next_epoch_tickets_as_segments(tickets);
// Force sorting of next epoch tickets (enactment) by explicitly querying the first of them.
let next_epoch = Sassafras::next_epoch();
assert_eq!(TicketsMeta::<Test>::get().unsorted_tickets_count, tickets.len() as u32);
Sassafras::slot_ticket(next_epoch.start).unwrap();
assert_eq!(TicketsMeta::<Test>::get().unsorted_tickets_count, 0);
}
fn slot_claim_vrf_signature(slot: Slot, pair: &AuthorityPair) -> VrfSignature {
let mut epoch = Sassafras::epoch_index();
let mut randomness = Sassafras::randomness();
// Check if epoch is going to change on initialization.
let epoch_start = Sassafras::current_epoch_start();
let epoch_length = EPOCH_LENGTH.into();
if epoch_start != 0_u64 && slot >= epoch_start + epoch_length {
epoch += slot.saturating_sub(epoch_start).saturating_div(epoch_length);
randomness = crate::NextRandomness::<Test>::get();
}
let data = vrf::slot_claim_sign_data(&randomness, slot, epoch);
pair.as_ref().vrf_sign(&data)
}
/// Construct a `PreDigest` instance for the given parameters.
pub fn make_slot_claim(
authority_idx: AuthorityIndex,
slot: Slot,
pair: &AuthorityPair,
) -> SlotClaim {
let vrf_signature = slot_claim_vrf_signature(slot, pair);
SlotClaim { authority_idx, slot, vrf_signature, ticket_claim: None }
}
/// Construct a `Digest` with a `SlotClaim` item.
pub fn make_digest(authority_idx: AuthorityIndex, slot: Slot, pair: &AuthorityPair) -> Digest {
let claim = make_slot_claim(authority_idx, slot, pair);
Digest { logs: vec![DigestItem::from(&claim)] }
}
pub fn initialize_block(
number: u64,
slot: Slot,
parent_hash: H256,
pair: &AuthorityPair,
) -> Digest {
let digest = make_digest(0, slot, pair);
System::reset_events();
System::initialize(&number, &parent_hash, &digest);
Sassafras::on_initialize(number);
digest
}
pub fn finalize_block(number: u64) -> Header {
Sassafras::on_finalize(number);
System::finalize()
}
/// Progress the pallet state up to the given block `number` and `slot`.
pub fn go_to_block(number: u64, slot: Slot, pair: &AuthorityPair) -> Digest {
Sassafras::on_finalize(System::block_number());
let parent_hash = System::finalize().hash();
let digest = make_digest(0, slot, pair);
System::reset_events();
System::initialize(&number, &parent_hash, &digest);
Sassafras::on_initialize(number);
digest
}
/// Progress the pallet state up to the given block `number`.
/// Slots will grow linearly accordingly to blocks.
pub fn progress_to_block(number: u64, pair: &AuthorityPair) -> Option<Digest> {
let mut slot = Sassafras::current_slot() + 1;
let mut digest = None;
for i in System::block_number() + 1..=number {
let dig = go_to_block(i, slot, pair);
digest = Some(dig);
slot = slot + 1;
}
digest
}
+876
View File
@@ -0,0 +1,876 @@
// 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.
//! Tests for Sassafras pallet.
use crate::*;
use mock::*;
use pezsp_consensus_sassafras::Slot;
fn h2b<const N: usize>(hex: &str) -> [u8; N] {
array_bytes::hex2array_unchecked(hex)
}
fn b2h<const N: usize>(bytes: [u8; N]) -> String {
array_bytes::bytes2hex("", &bytes)
}
#[test]
fn genesis_values_assumptions_check() {
new_test_ext(3).execute_with(|| {
assert_eq!(Sassafras::authorities().len(), 3);
assert_eq!(Sassafras::config(), TEST_EPOCH_CONFIGURATION);
});
}
#[test]
fn post_genesis_randomness_initialization() {
let (pairs, mut ext) = new_test_ext_with_pairs(1, false);
let pair = &pairs[0];
ext.execute_with(|| {
assert_eq!(Sassafras::randomness(), [0; 32]);
assert_eq!(Sassafras::next_randomness(), [0; 32]);
assert_eq!(Sassafras::randomness_accumulator(), [0; 32]);
// Test the values with a zero genesis block hash
let _ = initialize_block(1, 123.into(), [0x00; 32].into(), pair);
assert_eq!(Sassafras::randomness(), [0; 32]);
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("b9497550deeeb4adc134555930de61968a0558f8947041eb515b2f5fa68ffaf7")
);
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("febcc7fe9539fe17ed29f525831394edfb30b301755dc9bd91584a1f065faf87")
);
let (id1, _) = make_ticket_bodies(1, Some(pair))[0];
// Reset what is relevant
System::set_block_number(0);
NextRandomness::<Test>::set([0; 32]);
RandomnessAccumulator::<Test>::set([0; 32]);
// Test the values with a non-zero genesis block hash
let _ = initialize_block(1, 123.into(), [0xff; 32].into(), pair);
assert_eq!(Sassafras::randomness(), [0; 32]);
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("51c1e3b3a73d2043b3cabae98ff27bdd4aad8967c21ecda7b9465afaa0e70f37")
);
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("466bf3007f2e17bffee0b3c42c90f33d654f5ff61eff28b0cc650825960abd52")
);
let (id2, _) = make_ticket_bodies(1, Some(pair))[0];
// Ticket ids should be different when next epoch randomness is different
assert_ne!(id1, id2);
// Reset what is relevant
System::set_block_number(0);
NextRandomness::<Test>::set([0; 32]);
RandomnessAccumulator::<Test>::set([0; 32]);
// Test the values with a non-zero genesis block hash
let _ = initialize_block(1, 321.into(), [0x00; 32].into(), pair);
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("d85d84a54f79453000eb62e8a17b30149bd728d3232bc2787a89d51dc9a36008")
);
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("8a035eed02b5b8642b1515ed19752df8df156627aea45c4ef6e3efa88be9a74d")
);
let (id2, _) = make_ticket_bodies(1, Some(pair))[0];
// Ticket ids should be different when next epoch randomness is different
assert_ne!(id1, id2);
});
}
// Tests if the sorted tickets are assigned to each slot outside-in.
#[test]
fn slot_ticket_id_outside_in_fetch() {
let genesis_slot = Slot::from(100);
let tickets_count = 6;
// Current epoch tickets
let curr_tickets: Vec<TicketId> = (0..tickets_count).map(|i| i as TicketId).collect();
// Next epoch tickets
let next_tickets: Vec<TicketId> =
(0..tickets_count - 1).map(|i| (i + tickets_count) as TicketId).collect();
new_test_ext(0).execute_with(|| {
// Some corner cases
TicketsIds::<Test>::insert((0, 0_u32), 1_u128);
// Cleanup
(0..3).for_each(|i| TicketsIds::<Test>::remove((0, i as u32)));
curr_tickets
.iter()
.enumerate()
.for_each(|(i, id)| TicketsIds::<Test>::insert((0, i as u32), id));
next_tickets
.iter()
.enumerate()
.for_each(|(i, id)| TicketsIds::<Test>::insert((1, i as u32), id));
TicketsMeta::<Test>::set(TicketsMetadata {
tickets_count: [curr_tickets.len() as u32, next_tickets.len() as u32],
unsorted_tickets_count: 0,
});
// Before importing the first block the pallet always return `None`
// This is a kind of special hardcoded case that should never happen in practice
// as the first thing the pallet does is to initialize the genesis slot.
assert_eq!(Sassafras::slot_ticket_id(0.into()), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 0), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 1), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 100), None);
// Initialize genesis slot..
GenesisSlot::<Test>::set(genesis_slot);
pezframe_system::Pallet::<Test>::set_block_number(One::one());
// Try to fetch a ticket for a slot before current epoch.
assert_eq!(Sassafras::slot_ticket_id(0.into()), None);
// Current epoch tickets.
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 0), Some(curr_tickets[1]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 1), Some(curr_tickets[3]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 2), Some(curr_tickets[5]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 3), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 4), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 5), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 6), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 7), Some(curr_tickets[4]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 8), Some(curr_tickets[2]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 9), Some(curr_tickets[0]));
// Next epoch tickets (note that only 5 tickets are available)
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 10), Some(next_tickets[1]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 11), Some(next_tickets[3]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 12), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 13), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 14), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 15), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 16), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 17), Some(next_tickets[4]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 18), Some(next_tickets[2]));
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 19), Some(next_tickets[0]));
// Try to fetch the tickets for slots beyond the next epoch.
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 20), None);
assert_eq!(Sassafras::slot_ticket_id(genesis_slot + 42), None);
});
}
// Different test for outside-in test with more focus on corner case correctness.
#[test]
fn slot_ticket_id_outside_in_fetch_corner_cases() {
new_test_ext(0).execute_with(|| {
pezframe_system::Pallet::<Test>::set_block_number(One::one());
let mut meta = TicketsMetadata { tickets_count: [0, 0], unsorted_tickets_count: 0 };
let curr_epoch_idx = EpochIndex::<Test>::get();
let mut epoch_test = |epoch_idx| {
let tag = (epoch_idx & 1) as u8;
let epoch_start = Sassafras::epoch_start(epoch_idx);
// cleanup
meta.tickets_count = [0, 0];
TicketsMeta::<Test>::set(meta);
assert!((0..10).all(|i| Sassafras::slot_ticket_id((epoch_start + i).into()).is_none()));
meta.tickets_count[tag as usize] += 1;
TicketsMeta::<Test>::set(meta);
TicketsIds::<Test>::insert((tag, 0_u32), 1_u128);
assert_eq!(Sassafras::slot_ticket_id((epoch_start + 9).into()), Some(1_u128));
assert!((0..9).all(|i| Sassafras::slot_ticket_id((epoch_start + i).into()).is_none()));
meta.tickets_count[tag as usize] += 1;
TicketsMeta::<Test>::set(meta);
TicketsIds::<Test>::insert((tag, 1_u32), 2_u128);
assert_eq!(Sassafras::slot_ticket_id((epoch_start + 0).into()), Some(2_u128));
assert!((1..9).all(|i| Sassafras::slot_ticket_id((epoch_start + i).into()).is_none()));
meta.tickets_count[tag as usize] += 2;
TicketsMeta::<Test>::set(meta);
TicketsIds::<Test>::insert((tag, 2_u32), 3_u128);
assert_eq!(Sassafras::slot_ticket_id((epoch_start + 8).into()), Some(3_u128));
assert!((1..8).all(|i| Sassafras::slot_ticket_id((epoch_start + i).into()).is_none()));
};
// Even epoch
epoch_test(curr_epoch_idx);
epoch_test(curr_epoch_idx + 1);
});
}
#[test]
fn on_first_block_after_genesis() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
ext.execute_with(|| {
let start_slot = Slot::from(100);
let start_block = 1;
let digest = initialize_block(start_block, start_slot, Default::default(), &pairs[0]);
let common_assertions = || {
assert_eq!(Sassafras::genesis_slot(), start_slot);
assert_eq!(Sassafras::current_slot(), start_slot);
assert_eq!(Sassafras::epoch_index(), 0);
assert_eq!(Sassafras::current_epoch_start(), start_slot);
assert_eq!(Sassafras::current_slot_index(), 0);
assert_eq!(Sassafras::randomness(), [0; 32]);
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("a49592ef190b96f3eb87bde4c8355e33df28c75006156e8c81998158de2ed49e")
);
};
// Post-initialization status
assert!(SlotRandomness::<Test>::exists());
common_assertions();
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("f0d42f6b7c0d157ecbd788be44847b80a96c290c04b5dfa5d1d40c98aa0c04ed")
);
let header = finalize_block(start_block);
// Post-finalization status
assert!(!SlotRandomness::<Test>::exists());
common_assertions();
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("95a508cf10f877cf0457af3503a6cb3192763d5c15a7b9a58e40dc543efae889"),
);
// Header data check
assert_eq!(header.digest.logs.len(), 2);
assert_eq!(header.digest.logs[0], digest.logs[0]);
// Genesis epoch start deposits consensus
let consensus_log = pezsp_consensus_sassafras::digests::ConsensusLog::NextEpochData(
pezsp_consensus_sassafras::digests::NextEpochDescriptor {
authorities: Sassafras::next_authorities().into_inner(),
randomness: Sassafras::next_randomness(),
config: None,
},
);
let consensus_digest = DigestItem::Consensus(SASSAFRAS_ENGINE_ID, consensus_log.encode());
assert_eq!(header.digest.logs[1], consensus_digest)
})
}
#[test]
fn on_normal_block() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
let start_slot = Slot::from(100);
let start_block = 1;
let end_block = start_block + 1;
ext.execute_with(|| {
initialize_block(start_block, start_slot, Default::default(), &pairs[0]);
// We don't want to trigger an epoch change in this test.
let epoch_length = Sassafras::epoch_length() as u64;
assert!(epoch_length > end_block);
// Progress to block 2
let digest = progress_to_block(end_block, &pairs[0]).unwrap();
let common_assertions = || {
assert_eq!(Sassafras::genesis_slot(), start_slot);
assert_eq!(Sassafras::current_slot(), start_slot + 1);
assert_eq!(Sassafras::epoch_index(), 0);
assert_eq!(Sassafras::current_epoch_start(), start_slot);
assert_eq!(Sassafras::current_slot_index(), 1);
assert_eq!(Sassafras::randomness(), [0; 32]);
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("a49592ef190b96f3eb87bde4c8355e33df28c75006156e8c81998158de2ed49e")
);
};
// Post-initialization status
assert!(SlotRandomness::<Test>::exists());
common_assertions();
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("95a508cf10f877cf0457af3503a6cb3192763d5c15a7b9a58e40dc543efae889"),
);
let header = finalize_block(end_block);
// Post-finalization status
assert!(!SlotRandomness::<Test>::exists());
common_assertions();
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("5465cb257ad20cd4b9400a9fc85af7b1e2e72b59debd8ca06580dfb76bfca394"),
);
// Header data check
assert_eq!(header.digest.logs.len(), 1);
assert_eq!(header.digest.logs[0], digest.logs[0]);
});
}
#[test]
fn produce_epoch_change_digest_no_config() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
ext.execute_with(|| {
let start_slot = Slot::from(100);
let start_block = 1;
initialize_block(start_block, start_slot, Default::default(), &pairs[0]);
// We want to trigger an epoch change in this test.
let epoch_length = Sassafras::epoch_length() as u64;
let end_block = start_block + epoch_length;
let digest = progress_to_block(end_block, &pairs[0]).unwrap();
let common_assertions = || {
assert_eq!(Sassafras::genesis_slot(), start_slot);
assert_eq!(Sassafras::current_slot(), start_slot + epoch_length);
assert_eq!(Sassafras::epoch_index(), 1);
assert_eq!(Sassafras::current_epoch_start(), start_slot + epoch_length);
assert_eq!(Sassafras::current_slot_index(), 0);
println!("[DEBUG] {}", b2h(Sassafras::randomness()));
assert_eq!(
Sassafras::randomness(),
h2b("a49592ef190b96f3eb87bde4c8355e33df28c75006156e8c81998158de2ed49e")
);
};
// Post-initialization status
assert!(SlotRandomness::<Test>::exists());
common_assertions();
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("c4d374ed47b71e1c29e57143db23861916ff2d0c59ead4c51070d42ff4af2830"),
);
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("c6d84d1f389853959c39271a38010f2f27abe6ff56cc419cf9e89eafcae1ab5e"),
);
let header = finalize_block(end_block);
// Post-finalization status
assert!(!SlotRandomness::<Test>::exists());
common_assertions();
println!("[DEBUG] {}", b2h(Sassafras::next_randomness()));
assert_eq!(
Sassafras::next_randomness(),
h2b("c4d374ed47b71e1c29e57143db23861916ff2d0c59ead4c51070d42ff4af2830"),
);
println!("[DEBUG] {}", b2h(Sassafras::randomness_accumulator()));
assert_eq!(
Sassafras::randomness_accumulator(),
h2b("6ca02b90e14ef11b3855069794da7e9d4007526b0588c426c3e3533b0b6ade7a"),
);
// Header data check
assert_eq!(header.digest.logs.len(), 2);
assert_eq!(header.digest.logs[0], digest.logs[0]);
// Deposits consensus log on epoch change
let consensus_log = pezsp_consensus_sassafras::digests::ConsensusLog::NextEpochData(
pezsp_consensus_sassafras::digests::NextEpochDescriptor {
authorities: Sassafras::next_authorities().into_inner(),
randomness: Sassafras::next_randomness(),
config: None,
},
);
let consensus_digest = DigestItem::Consensus(SASSAFRAS_ENGINE_ID, consensus_log.encode());
assert_eq!(header.digest.logs[1], consensus_digest)
})
}
#[test]
fn produce_epoch_change_digest_with_config() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
ext.execute_with(|| {
let start_slot = Slot::from(100);
let start_block = 1;
initialize_block(start_block, start_slot, Default::default(), &pairs[0]);
let config = EpochConfiguration { redundancy_factor: 1, attempts_number: 123 };
Sassafras::plan_config_change(RuntimeOrigin::root(), config).unwrap();
// We want to trigger an epoch change in this test.
let epoch_length = Sassafras::epoch_length() as u64;
let end_block = start_block + epoch_length;
let digest = progress_to_block(end_block, &pairs[0]).unwrap();
let header = finalize_block(end_block);
// Header data check.
// Skip pallet status checks that were already performed by other tests.
assert_eq!(header.digest.logs.len(), 2);
assert_eq!(header.digest.logs[0], digest.logs[0]);
// Deposits consensus log on epoch change
let consensus_log = pezsp_consensus_sassafras::digests::ConsensusLog::NextEpochData(
pezsp_consensus_sassafras::digests::NextEpochDescriptor {
authorities: Sassafras::next_authorities().into_inner(),
randomness: Sassafras::next_randomness(),
config: Some(config),
},
);
let consensus_digest = DigestItem::Consensus(SASSAFRAS_ENGINE_ID, consensus_log.encode());
assert_eq!(header.digest.logs[1], consensus_digest)
})
}
#[test]
fn segments_incremental_sort_works() {
let (pairs, mut ext) = new_test_ext_with_pairs(1, false);
let pair = &pairs[0];
let segments_count = 14;
let start_slot = Slot::from(100);
let start_block = 1;
ext.execute_with(|| {
let epoch_length = Sassafras::epoch_length() as u64;
// -3 just to have the last segment not full...
let submitted_tickets_count = segments_count * SEGMENT_MAX_SIZE - 3;
initialize_block(start_block, start_slot, Default::default(), pair);
// Manually populate the segments to skip the threshold check
let mut tickets = make_ticket_bodies(submitted_tickets_count, None);
persist_next_epoch_tickets_as_segments(&tickets);
// Proceed to half of the epoch (sortition should not have been started yet)
let half_epoch_block = start_block + epoch_length / 2;
progress_to_block(half_epoch_block, pair);
let mut unsorted_tickets_count = submitted_tickets_count;
// Check that next epoch tickets sortition is not started yet
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, unsorted_tickets_count);
assert_eq!(meta.tickets_count, [0, 0]);
// Follow the incremental sortition block by block
progress_to_block(half_epoch_block + 1, pair);
unsorted_tickets_count -= 3 * SEGMENT_MAX_SIZE - 3;
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, unsorted_tickets_count,);
assert_eq!(meta.tickets_count, [0, 0]);
progress_to_block(half_epoch_block + 2, pair);
unsorted_tickets_count -= 3 * SEGMENT_MAX_SIZE;
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, unsorted_tickets_count);
assert_eq!(meta.tickets_count, [0, 0]);
progress_to_block(half_epoch_block + 3, pair);
unsorted_tickets_count -= 3 * SEGMENT_MAX_SIZE;
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, unsorted_tickets_count);
assert_eq!(meta.tickets_count, [0, 0]);
progress_to_block(half_epoch_block + 4, pair);
unsorted_tickets_count -= 3 * SEGMENT_MAX_SIZE;
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, unsorted_tickets_count);
assert_eq!(meta.tickets_count, [0, 0]);
let header = finalize_block(half_epoch_block + 4);
// Sort should be finished now.
// Check that next epoch tickets count have the correct value.
// Bigger ticket ids were discarded during sortition.
unsorted_tickets_count -= 2 * SEGMENT_MAX_SIZE;
assert_eq!(unsorted_tickets_count, 0);
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, unsorted_tickets_count);
assert_eq!(meta.tickets_count, [0, epoch_length as u32]);
// Epoch change log should have been pushed as well
assert_eq!(header.digest.logs.len(), 1);
// No tickets for the current epoch
assert_eq!(TicketsIds::<Test>::get((0, 0)), None);
// Check persistence of "winning" tickets
tickets.sort_by_key(|t| t.0);
(0..epoch_length as usize).into_iter().for_each(|i| {
let id = TicketsIds::<Test>::get((1, i as u32)).unwrap();
let body = TicketsData::<Test>::get(id).unwrap();
assert_eq!((id, body), tickets[i]);
});
// Check removal of "loosing" tickets
(epoch_length as usize..tickets.len()).into_iter().for_each(|i| {
assert!(TicketsIds::<Test>::get((1, i as u32)).is_none());
assert!(TicketsData::<Test>::get(tickets[i].0).is_none());
});
// The next block will be the first produced on the new epoch.
// At this point the tickets are found already sorted and ready to be used.
let slot = Sassafras::current_slot() + 1;
let number = System::block_number() + 1;
initialize_block(number, slot, header.hash(), pair);
let header = finalize_block(number);
// Epoch changes digest is also produced
assert_eq!(header.digest.logs.len(), 2);
});
}
#[test]
fn tickets_fetch_works_after_epoch_change() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
let pair = &pairs[0];
let start_slot = Slot::from(100);
let start_block = 1;
let submitted_tickets = 300;
ext.execute_with(|| {
initialize_block(start_block, start_slot, Default::default(), pair);
// We don't want to trigger an epoch change in this test.
let epoch_length = Sassafras::epoch_length() as u64;
assert!(epoch_length > 2);
progress_to_block(2, &pairs[0]).unwrap();
// Persist tickets as three different segments.
let tickets = make_ticket_bodies(submitted_tickets, None);
persist_next_epoch_tickets_as_segments(&tickets);
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, submitted_tickets);
assert_eq!(meta.tickets_count, [0, 0]);
// Progress up to the last epoch slot (do not enact epoch change)
progress_to_block(epoch_length, &pairs[0]).unwrap();
// At this point next epoch tickets should have been sorted and ready to be used
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, 0);
assert_eq!(meta.tickets_count, [0, epoch_length as u32]);
// Compute and sort the tickets ids (aka tickets scores)
let mut expected_ids: Vec<_> = tickets.into_iter().map(|(id, _)| id).collect();
expected_ids.sort();
expected_ids.truncate(epoch_length as usize);
// Check if we can fetch next epoch tickets ids (outside-in).
let slot = Sassafras::current_slot();
assert_eq!(Sassafras::slot_ticket_id(slot + 1).unwrap(), expected_ids[1]);
assert_eq!(Sassafras::slot_ticket_id(slot + 2).unwrap(), expected_ids[3]);
assert_eq!(Sassafras::slot_ticket_id(slot + 3).unwrap(), expected_ids[5]);
assert_eq!(Sassafras::slot_ticket_id(slot + 4).unwrap(), expected_ids[7]);
assert_eq!(Sassafras::slot_ticket_id(slot + 7).unwrap(), expected_ids[6]);
assert_eq!(Sassafras::slot_ticket_id(slot + 8).unwrap(), expected_ids[4]);
assert_eq!(Sassafras::slot_ticket_id(slot + 9).unwrap(), expected_ids[2]);
assert_eq!(Sassafras::slot_ticket_id(slot + 10).unwrap(), expected_ids[0]);
assert!(Sassafras::slot_ticket_id(slot + 11).is_none());
// Enact epoch change by progressing one more block
progress_to_block(epoch_length + 1, &pairs[0]).unwrap();
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, 0);
assert_eq!(meta.tickets_count, [0, 10]);
// Check if we can fetch current epoch tickets ids (outside-in).
let slot = Sassafras::current_slot();
assert_eq!(Sassafras::slot_ticket_id(slot).unwrap(), expected_ids[1]);
assert_eq!(Sassafras::slot_ticket_id(slot + 1).unwrap(), expected_ids[3]);
assert_eq!(Sassafras::slot_ticket_id(slot + 2).unwrap(), expected_ids[5]);
assert_eq!(Sassafras::slot_ticket_id(slot + 3).unwrap(), expected_ids[7]);
assert_eq!(Sassafras::slot_ticket_id(slot + 6).unwrap(), expected_ids[6]);
assert_eq!(Sassafras::slot_ticket_id(slot + 7).unwrap(), expected_ids[4]);
assert_eq!(Sassafras::slot_ticket_id(slot + 8).unwrap(), expected_ids[2]);
assert_eq!(Sassafras::slot_ticket_id(slot + 9).unwrap(), expected_ids[0]);
assert!(Sassafras::slot_ticket_id(slot + 10).is_none());
// Enact another epoch change, for which we don't have any ticket
progress_to_block(2 * epoch_length + 1, &pairs[0]).unwrap();
let meta = TicketsMeta::<Test>::get();
assert_eq!(meta.unsorted_tickets_count, 0);
assert_eq!(meta.tickets_count, [0, 0]);
});
}
#[test]
fn block_allowed_to_skip_epochs() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
let pair = &pairs[0];
let start_slot = Slot::from(100);
let start_block = 1;
ext.execute_with(|| {
let epoch_length = Sassafras::epoch_length() as u64;
initialize_block(start_block, start_slot, Default::default(), pair);
let tickets = make_ticket_bodies(3, Some(pair));
persist_next_epoch_tickets(&tickets);
let next_random = Sassafras::next_randomness();
// We want to skip 3 epochs in this test.
let offset = 4 * epoch_length;
System::set_block_number(start_block + offset - 1);
go_to_block(start_block + offset, start_slot + offset, &pairs[0]);
// Post-initialization status
assert!(SlotRandomness::<Test>::exists());
assert_eq!(Sassafras::genesis_slot(), start_slot);
assert_eq!(Sassafras::current_slot(), start_slot + offset);
assert_eq!(Sassafras::epoch_index(), 4);
assert_eq!(Sassafras::current_epoch_start(), start_slot + offset);
assert_eq!(Sassafras::current_slot_index(), 0);
// Tickets data has been discarded
assert_eq!(TicketsMeta::<Test>::get(), TicketsMetadata::default());
assert!(tickets.iter().all(|(id, _)| TicketsData::<Test>::get(id).is_none()));
assert_eq!(SortedCandidates::<Test>::get().len(), 0);
// We used the last known next epoch randomness as a fallback
assert_eq!(next_random, Sassafras::randomness());
});
}
#[test]
fn obsolete_tickets_are_removed_on_epoch_change() {
let (pairs, mut ext) = new_test_ext_with_pairs(4, false);
let pair = &pairs[0];
let start_slot = Slot::from(100);
let start_block = 1;
ext.execute_with(|| {
let epoch_length = Sassafras::epoch_length() as u64;
initialize_block(start_block, start_slot, Default::default(), pair);
let tickets = make_ticket_bodies(10, Some(pair));
let mut epoch1_tickets = tickets[..4].to_vec();
let mut epoch2_tickets = tickets[4..].to_vec();
// Persist some tickets for next epoch (N)
persist_next_epoch_tickets(&epoch1_tickets);
assert_eq!(TicketsMeta::<Test>::get().tickets_count, [0, 4]);
// Check next epoch tickets presence
epoch1_tickets.sort_by_key(|t| t.0);
(0..epoch1_tickets.len()).into_iter().for_each(|i| {
let id = TicketsIds::<Test>::get((1, i as u32)).unwrap();
let body = TicketsData::<Test>::get(id).unwrap();
assert_eq!((id, body), epoch1_tickets[i]);
});
// Advance one epoch to enact the tickets
progress_to_block(start_block + epoch_length, pair).unwrap();
assert_eq!(TicketsMeta::<Test>::get().tickets_count, [0, 4]);
// Persist some tickets for next epoch (N+1)
persist_next_epoch_tickets(&epoch2_tickets);
assert_eq!(TicketsMeta::<Test>::get().tickets_count, [6, 4]);
epoch2_tickets.sort_by_key(|t| t.0);
// Check for this epoch and next epoch tickets presence
(0..epoch1_tickets.len()).into_iter().for_each(|i| {
let id = TicketsIds::<Test>::get((1, i as u32)).unwrap();
let body = TicketsData::<Test>::get(id).unwrap();
assert_eq!((id, body), epoch1_tickets[i]);
});
(0..epoch2_tickets.len()).into_iter().for_each(|i| {
let id = TicketsIds::<Test>::get((0, i as u32)).unwrap();
let body = TicketsData::<Test>::get(id).unwrap();
assert_eq!((id, body), epoch2_tickets[i]);
});
// Advance to epoch 2 and check for cleanup
progress_to_block(start_block + 2 * epoch_length, pair).unwrap();
assert_eq!(TicketsMeta::<Test>::get().tickets_count, [6, 0]);
(0..epoch1_tickets.len()).into_iter().for_each(|i| {
let id = TicketsIds::<Test>::get((1, i as u32)).unwrap();
assert!(TicketsData::<Test>::get(id).is_none());
});
(0..epoch2_tickets.len()).into_iter().for_each(|i| {
let id = TicketsIds::<Test>::get((0, i as u32)).unwrap();
let body = TicketsData::<Test>::get(id).unwrap();
assert_eq!((id, body), epoch2_tickets[i]);
});
})
}
const TICKETS_FILE: &str = "src/data/25_tickets_100_auths.bin";
fn data_read<T: Decode>(filename: &str) -> T {
use std::{fs::File, io::Read};
let mut file = File::open(filename).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
T::decode(&mut &buf[..]).unwrap()
}
fn data_write<T: Encode>(filename: &str, data: T) {
use std::{fs::File, io::Write};
let mut file = File::create(filename).unwrap();
let buf = data.encode();
file.write_all(&buf).unwrap();
}
// We don't want to implement anything secure here.
// Just a trivial shuffle for the tests.
fn trivial_fisher_yates_shuffle<T>(vector: &mut Vec<T>, random_seed: u64) {
let mut rng = random_seed as usize;
for i in (1..vector.len()).rev() {
let j = rng % (i + 1);
vector.swap(i, j);
rng = (rng.wrapping_mul(6364793005) + 1) as usize; // Some random number generation
}
}
// For this test we use a set of pre-constructed tickets from a file.
// Creating a large set of tickets on the fly takes time, and may be annoying
// for test execution.
//
// A valid ring-context is required for this test since we are passing through the
// `submit_ticket` call which tests for ticket validity.
#[test]
fn submit_tickets_with_ring_proof_check_works() {
use pezsp_core::Pair as _;
let (authorities, mut tickets): (Vec<AuthorityId>, Vec<TicketEnvelope>) =
data_read(TICKETS_FILE);
// Also checks that duplicates are discarded
tickets.extend(tickets.clone());
trivial_fisher_yates_shuffle(&mut tickets, 321);
let (pairs, mut ext) = new_test_ext_with_pairs(authorities.len(), true);
let pair = &pairs[0];
// Check if deserialized data has been generated for the correct set of authorities...
assert!(authorities.iter().zip(pairs.iter()).all(|(auth, pair)| auth == &pair.public()));
ext.execute_with(|| {
let start_slot = Slot::from(0);
let start_block = 1;
// Tweak the config to discard ~half of the tickets.
let mut config = EpochConfig::<Test>::get();
config.redundancy_factor = 25;
EpochConfig::<Test>::set(config);
initialize_block(start_block, start_slot, Default::default(), pair);
NextRandomness::<Test>::set([0; 32]);
// Check state before tickets submission
assert_eq!(
TicketsMeta::<Test>::get(),
TicketsMetadata { unsorted_tickets_count: 0, tickets_count: [0, 0] },
);
// Submit the tickets
let max_tickets_per_call = Sassafras::epoch_length() as usize;
tickets.chunks(max_tickets_per_call).for_each(|chunk| {
let chunk = BoundedVec::truncate_from(chunk.to_vec());
Sassafras::submit_tickets(RuntimeOrigin::none(), chunk).unwrap();
});
// Check state after submission
assert_eq!(
TicketsMeta::<Test>::get(),
TicketsMetadata { unsorted_tickets_count: 13, tickets_count: [0, 0] },
);
assert_eq!(UnsortedSegments::<Test>::get(0).len(), 13);
assert_eq!(UnsortedSegments::<Test>::get(1).len(), 0);
finalize_block(start_block);
})
}
#[test]
#[ignore = "test tickets data generator"]
fn make_tickets_data() {
use super::*;
use pezsp_core::crypto::Pair;
// Number of authorities who produces tickets (for the sake of this test)
let tickets_authors_count = 5;
// Total number of authorities (the ring)
let authorities_count = 100;
let (pairs, mut ext) = new_test_ext_with_pairs(authorities_count, true);
let authorities: Vec<_> = pairs.iter().map(|sk| sk.public()).collect();
ext.execute_with(|| {
let config = EpochConfig::<Test>::get();
let tickets_count = tickets_authors_count * config.attempts_number as usize;
let mut tickets = Vec::with_capacity(tickets_count);
// Construct pre-built tickets with a well known `NextRandomness` value.
NextRandomness::<Test>::set([0; 32]);
println!("Constructing {} tickets", tickets_count);
pairs.iter().take(tickets_authors_count).enumerate().for_each(|(i, pair)| {
let t = make_tickets(config.attempts_number, pair);
tickets.extend(t);
println!("{:.2}%", 100f32 * ((i + 1) as f32 / tickets_authors_count as f32));
});
data_write(TICKETS_FILE, (authorities, tickets));
});
}
@@ -0,0 +1,425 @@
// 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_sassafras`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-11-16, STEPS: `20`, REPEAT: `3`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `behemoth`, CPU: `AMD Ryzen Threadripper 3970X 32-Core Processor`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
// Executed Command:
// ./target/release/node-template
// benchmark
// pallet
// --chain
// dev
// --pallet
// pezpallet_sassafras
// --extrinsic
// *
// --steps
// 20
// --repeat
// 3
// --output
// weights.rs
// --template
// bizinikiwi/.maintain/frame-weight-template.hbs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use core::marker::PhantomData;
/// Weight functions needed for `pezpallet_sassafras`.
pub trait WeightInfo {
fn on_initialize() -> Weight;
fn enact_epoch_change(x: u32, y: u32, ) -> Weight;
fn submit_tickets(x: u32, ) -> Weight;
fn plan_config_change() -> Weight;
fn update_ring_verifier(x: u32, ) -> Weight;
fn load_ring_context() -> Weight;
fn sort_segments(x: u32, ) -> Weight;
}
/// Weights for `pezpallet_sassafras` using the Bizinikiwi node and recommended hardware.
pub struct BizinikiwiWeight<T>(PhantomData<T>);
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
/// Storage: `System::Digest` (r:1 w:1)
/// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Sassafras::NextRandomness` (r:1 w:0)
/// Proof: `Sassafras::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextAuthorities` (r:1 w:0)
/// Proof: `Sassafras::NextAuthorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::CurrentRandomness` (r:1 w:0)
/// Proof: `Sassafras::CurrentRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochIndex` (r:1 w:0)
/// Proof: `Sassafras::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RandomnessAccumulator` (r:1 w:1)
/// Proof: `Sassafras::RandomnessAccumulator` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::CurrentSlot` (r:0 w:1)
/// Proof: `Sassafras::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::ClaimTemporaryData` (r:0 w:1)
/// Proof: `Sassafras::ClaimTemporaryData` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::GenesisSlot` (r:0 w:1)
/// Proof: `Sassafras::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
fn on_initialize() -> Weight {
// Proof Size summary in bytes:
// Measured: `302`
// Estimated: `4787`
// Minimum execution time: 438_039_000 picoseconds.
Weight::from_parts(439_302_000, 4787)
.saturating_add(T::DbWeight::get().reads(6_u64))
.saturating_add(T::DbWeight::get().writes(5_u64))
}
/// Storage: `Sassafras::CurrentSlot` (r:1 w:0)
/// Proof: `Sassafras::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochIndex` (r:1 w:1)
/// Proof: `Sassafras::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::GenesisSlot` (r:1 w:0)
/// Proof: `Sassafras::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextAuthorities` (r:1 w:1)
/// Proof: `Sassafras::NextAuthorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingContext` (r:1 w:0)
/// Proof: `Sassafras::RingContext` (`max_values`: Some(1), `max_size`: Some(590324), added: 590819, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsMeta` (r:1 w:1)
/// Proof: `Sassafras::TicketsMeta` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextRandomness` (r:1 w:1)
/// Proof: `Sassafras::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RandomnessAccumulator` (r:1 w:0)
/// Proof: `Sassafras::RandomnessAccumulator` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextEpochConfig` (r:1 w:1)
/// Proof: `Sassafras::NextEpochConfig` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::PendingEpochConfigChange` (r:1 w:1)
/// Proof: `Sassafras::PendingEpochConfigChange` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `System::Digest` (r:1 w:1)
/// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Sassafras::SortedCandidates` (r:1 w:0)
/// Proof: `Sassafras::SortedCandidates` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::UnsortedSegments` (r:79 w:79)
/// Proof: `Sassafras::UnsortedSegments` (`max_values`: None, `max_size`: Some(2054), added: 4529, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsIds` (r:5000 w:200)
/// Proof: `Sassafras::TicketsIds` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::Authorities` (r:0 w:1)
/// Proof: `Sassafras::Authorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsData` (r:0 w:9896)
/// Proof: `Sassafras::TicketsData` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingVerifierData` (r:0 w:1)
/// Proof: `Sassafras::RingVerifierData` (`max_values`: Some(1), `max_size`: Some(388), added: 883, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochConfig` (r:0 w:1)
/// Proof: `Sassafras::EpochConfig` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::CurrentRandomness` (r:0 w:1)
/// Proof: `Sassafras::CurrentRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 100]`.
/// The range of component `y` is `[1000, 5000]`.
fn enact_epoch_change(x: u32, y: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `594909 + x * (33 ±0) + y * (53 ±0)`
// Estimated: `593350 + x * (24 ±1) + y * (2496 ±0)`
// Minimum execution time: 121_279_846_000 picoseconds.
Weight::from_parts(94_454_851_972, 593350)
// Standard Error: 24_177_301
.saturating_add(Weight::from_parts(8_086_191, 0).saturating_mul(x.into()))
// Standard Error: 601_053
.saturating_add(Weight::from_parts(15_578_413, 0).saturating_mul(y.into()))
.saturating_add(T::DbWeight::get().reads(13_u64))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into())))
.saturating_add(T::DbWeight::get().writes(112_u64))
.saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(y.into())))
.saturating_add(Weight::from_parts(0, 24).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 2496).saturating_mul(y.into()))
}
/// Storage: `Sassafras::CurrentSlot` (r:1 w:0)
/// Proof: `Sassafras::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochIndex` (r:1 w:0)
/// Proof: `Sassafras::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::GenesisSlot` (r:1 w:0)
/// Proof: `Sassafras::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingVerifierData` (r:1 w:0)
/// Proof: `Sassafras::RingVerifierData` (`max_values`: Some(1), `max_size`: Some(388), added: 883, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextAuthorities` (r:1 w:0)
/// Proof: `Sassafras::NextAuthorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextEpochConfig` (r:1 w:0)
/// Proof: `Sassafras::NextEpochConfig` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextRandomness` (r:1 w:0)
/// Proof: `Sassafras::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsData` (r:25 w:25)
/// Proof: `Sassafras::TicketsData` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsMeta` (r:1 w:1)
/// Proof: `Sassafras::TicketsMeta` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::UnsortedSegments` (r:1 w:1)
/// Proof: `Sassafras::UnsortedSegments` (`max_values`: None, `max_size`: Some(2054), added: 4529, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 25]`.
fn submit_tickets(x: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `3869`
// Estimated: `5519 + x * (2559 ±0)`
// Minimum execution time: 36_904_934_000 picoseconds.
Weight::from_parts(25_822_957_295, 5519)
// Standard Error: 11_047_832
.saturating_add(Weight::from_parts(11_338_353_299, 0).saturating_mul(x.into()))
.saturating_add(T::DbWeight::get().reads(9_u64))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into())))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into())))
.saturating_add(Weight::from_parts(0, 2559).saturating_mul(x.into()))
}
/// Storage: `Sassafras::PendingEpochConfigChange` (r:0 w:1)
/// Proof: `Sassafras::PendingEpochConfigChange` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
fn plan_config_change() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 4_038_000 picoseconds.
Weight::from_parts(4_499_000, 0)
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Sassafras::RingContext` (r:1 w:0)
/// Proof: `Sassafras::RingContext` (`max_values`: Some(1), `max_size`: Some(590324), added: 590819, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingVerifierData` (r:0 w:1)
/// Proof: `Sassafras::RingVerifierData` (`max_values`: Some(1), `max_size`: Some(388), added: 883, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 100]`.
fn update_ring_verifier(x: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `590485`
// Estimated: `591809`
// Minimum execution time: 105_121_424_000 picoseconds.
Weight::from_parts(105_527_334_385, 591809)
// Standard Error: 2_933_910
.saturating_add(Weight::from_parts(96_136_261, 0).saturating_mul(x.into()))
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Sassafras::RingContext` (r:1 w:0)
/// Proof: `Sassafras::RingContext` (`max_values`: Some(1), `max_size`: Some(590324), added: 590819, mode: `MaxEncodedLen`)
fn load_ring_context() -> Weight {
// Proof Size summary in bytes:
// Measured: `590485`
// Estimated: `591809`
// Minimum execution time: 44_005_681_000 picoseconds.
Weight::from_parts(44_312_079_000, 591809)
.saturating_add(T::DbWeight::get().reads(1_u64))
}
/// Storage: `Sassafras::SortedCandidates` (r:1 w:0)
/// Proof: `Sassafras::SortedCandidates` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::UnsortedSegments` (r:100 w:100)
/// Proof: `Sassafras::UnsortedSegments` (`max_values`: None, `max_size`: Some(2054), added: 4529, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsIds` (r:0 w:200)
/// Proof: `Sassafras::TicketsIds` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsData` (r:0 w:12600)
/// Proof: `Sassafras::TicketsData` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 100]`.
fn sort_segments(x: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `222 + x * (2060 ±0)`
// Estimated: `4687 + x * (4529 ±0)`
// Minimum execution time: 183_501_000 picoseconds.
Weight::from_parts(183_501_000, 4687)
// Standard Error: 1_426_363
.saturating_add(Weight::from_parts(169_156_241, 0).saturating_mul(x.into()))
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into())))
.saturating_add(T::DbWeight::get().writes((129_u64).saturating_mul(x.into())))
.saturating_add(Weight::from_parts(0, 4529).saturating_mul(x.into()))
}
}
// For backwards compatibility and tests.
impl WeightInfo for () {
/// Storage: `System::Digest` (r:1 w:1)
/// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Sassafras::NextRandomness` (r:1 w:0)
/// Proof: `Sassafras::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextAuthorities` (r:1 w:0)
/// Proof: `Sassafras::NextAuthorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::CurrentRandomness` (r:1 w:0)
/// Proof: `Sassafras::CurrentRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochIndex` (r:1 w:0)
/// Proof: `Sassafras::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RandomnessAccumulator` (r:1 w:1)
/// Proof: `Sassafras::RandomnessAccumulator` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::CurrentSlot` (r:0 w:1)
/// Proof: `Sassafras::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::ClaimTemporaryData` (r:0 w:1)
/// Proof: `Sassafras::ClaimTemporaryData` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::GenesisSlot` (r:0 w:1)
/// Proof: `Sassafras::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
fn on_initialize() -> Weight {
// Proof Size summary in bytes:
// Measured: `302`
// Estimated: `4787`
// Minimum execution time: 438_039_000 picoseconds.
Weight::from_parts(439_302_000, 4787)
.saturating_add(RocksDbWeight::get().reads(6_u64))
.saturating_add(RocksDbWeight::get().writes(5_u64))
}
/// Storage: `Sassafras::CurrentSlot` (r:1 w:0)
/// Proof: `Sassafras::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochIndex` (r:1 w:1)
/// Proof: `Sassafras::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::GenesisSlot` (r:1 w:0)
/// Proof: `Sassafras::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextAuthorities` (r:1 w:1)
/// Proof: `Sassafras::NextAuthorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingContext` (r:1 w:0)
/// Proof: `Sassafras::RingContext` (`max_values`: Some(1), `max_size`: Some(590324), added: 590819, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsMeta` (r:1 w:1)
/// Proof: `Sassafras::TicketsMeta` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextRandomness` (r:1 w:1)
/// Proof: `Sassafras::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RandomnessAccumulator` (r:1 w:0)
/// Proof: `Sassafras::RandomnessAccumulator` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextEpochConfig` (r:1 w:1)
/// Proof: `Sassafras::NextEpochConfig` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::PendingEpochConfigChange` (r:1 w:1)
/// Proof: `Sassafras::PendingEpochConfigChange` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `System::Digest` (r:1 w:1)
/// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Sassafras::SortedCandidates` (r:1 w:0)
/// Proof: `Sassafras::SortedCandidates` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::UnsortedSegments` (r:79 w:79)
/// Proof: `Sassafras::UnsortedSegments` (`max_values`: None, `max_size`: Some(2054), added: 4529, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsIds` (r:5000 w:200)
/// Proof: `Sassafras::TicketsIds` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::Authorities` (r:0 w:1)
/// Proof: `Sassafras::Authorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsData` (r:0 w:9896)
/// Proof: `Sassafras::TicketsData` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingVerifierData` (r:0 w:1)
/// Proof: `Sassafras::RingVerifierData` (`max_values`: Some(1), `max_size`: Some(388), added: 883, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochConfig` (r:0 w:1)
/// Proof: `Sassafras::EpochConfig` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::CurrentRandomness` (r:0 w:1)
/// Proof: `Sassafras::CurrentRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 100]`.
/// The range of component `y` is `[1000, 5000]`.
fn enact_epoch_change(x: u32, y: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `594909 + x * (33 ±0) + y * (53 ±0)`
// Estimated: `593350 + x * (24 ±1) + y * (2496 ±0)`
// Minimum execution time: 121_279_846_000 picoseconds.
Weight::from_parts(94_454_851_972, 593350)
// Standard Error: 24_177_301
.saturating_add(Weight::from_parts(8_086_191, 0).saturating_mul(x.into()))
// Standard Error: 601_053
.saturating_add(Weight::from_parts(15_578_413, 0).saturating_mul(y.into()))
.saturating_add(RocksDbWeight::get().reads(13_u64))
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y.into())))
.saturating_add(RocksDbWeight::get().writes(112_u64))
.saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(y.into())))
.saturating_add(Weight::from_parts(0, 24).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 2496).saturating_mul(y.into()))
}
/// Storage: `Sassafras::CurrentSlot` (r:1 w:0)
/// Proof: `Sassafras::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::EpochIndex` (r:1 w:0)
/// Proof: `Sassafras::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::GenesisSlot` (r:1 w:0)
/// Proof: `Sassafras::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingVerifierData` (r:1 w:0)
/// Proof: `Sassafras::RingVerifierData` (`max_values`: Some(1), `max_size`: Some(388), added: 883, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextAuthorities` (r:1 w:0)
/// Proof: `Sassafras::NextAuthorities` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextEpochConfig` (r:1 w:0)
/// Proof: `Sassafras::NextEpochConfig` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::NextRandomness` (r:1 w:0)
/// Proof: `Sassafras::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsData` (r:25 w:25)
/// Proof: `Sassafras::TicketsData` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsMeta` (r:1 w:1)
/// Proof: `Sassafras::TicketsMeta` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::UnsortedSegments` (r:1 w:1)
/// Proof: `Sassafras::UnsortedSegments` (`max_values`: None, `max_size`: Some(2054), added: 4529, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 25]`.
fn submit_tickets(x: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `3869`
// Estimated: `5519 + x * (2559 ±0)`
// Minimum execution time: 36_904_934_000 picoseconds.
Weight::from_parts(25_822_957_295, 5519)
// Standard Error: 11_047_832
.saturating_add(Weight::from_parts(11_338_353_299, 0).saturating_mul(x.into()))
.saturating_add(RocksDbWeight::get().reads(9_u64))
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into())))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(x.into())))
.saturating_add(Weight::from_parts(0, 2559).saturating_mul(x.into()))
}
/// Storage: `Sassafras::PendingEpochConfigChange` (r:0 w:1)
/// Proof: `Sassafras::PendingEpochConfigChange` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
fn plan_config_change() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 4_038_000 picoseconds.
Weight::from_parts(4_499_000, 0)
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Sassafras::RingContext` (r:1 w:0)
/// Proof: `Sassafras::RingContext` (`max_values`: Some(1), `max_size`: Some(590324), added: 590819, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::RingVerifierData` (r:0 w:1)
/// Proof: `Sassafras::RingVerifierData` (`max_values`: Some(1), `max_size`: Some(388), added: 883, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 100]`.
fn update_ring_verifier(x: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `590485`
// Estimated: `591809`
// Minimum execution time: 105_121_424_000 picoseconds.
Weight::from_parts(105_527_334_385, 591809)
// Standard Error: 2_933_910
.saturating_add(Weight::from_parts(96_136_261, 0).saturating_mul(x.into()))
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Sassafras::RingContext` (r:1 w:0)
/// Proof: `Sassafras::RingContext` (`max_values`: Some(1), `max_size`: Some(590324), added: 590819, mode: `MaxEncodedLen`)
fn load_ring_context() -> Weight {
// Proof Size summary in bytes:
// Measured: `590485`
// Estimated: `591809`
// Minimum execution time: 44_005_681_000 picoseconds.
Weight::from_parts(44_312_079_000, 591809)
.saturating_add(RocksDbWeight::get().reads(1_u64))
}
/// Storage: `Sassafras::SortedCandidates` (r:1 w:0)
/// Proof: `Sassafras::SortedCandidates` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::UnsortedSegments` (r:100 w:100)
/// Proof: `Sassafras::UnsortedSegments` (`max_values`: None, `max_size`: Some(2054), added: 4529, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsIds` (r:0 w:200)
/// Proof: `Sassafras::TicketsIds` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`)
/// Storage: `Sassafras::TicketsData` (r:0 w:12600)
/// Proof: `Sassafras::TicketsData` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// The range of component `x` is `[1, 100]`.
fn sort_segments(x: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `222 + x * (2060 ±0)`
// Estimated: `4687 + x * (4529 ±0)`
// Minimum execution time: 183_501_000 picoseconds.
Weight::from_parts(183_501_000, 4687)
// Standard Error: 1_426_363
.saturating_add(Weight::from_parts(169_156_241, 0).saturating_mul(x.into()))
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into())))
.saturating_add(RocksDbWeight::get().writes((129_u64).saturating_mul(x.into())))
.saturating_add(Weight::from_parts(0, 4529).saturating_mul(x.into()))
}
}