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:
@@ -0,0 +1,69 @@
|
||||
[package]
|
||||
name = "pezpallet-sassafras"
|
||||
version = "0.3.5-dev"
|
||||
authors = [
|
||||
"Kurdistan Tech Institute <info@pezkuwichain.io>",
|
||||
"Parity Technologies <admin@parity.io>",
|
||||
]
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Consensus extension module for Sassafras consensus."
|
||||
readme = "README.md"
|
||||
publish = false
|
||||
|
||||
[package.metadata.pezkuwi-sdk]
|
||||
exclude-from-umbrella = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { features = ["derive"], workspace = true }
|
||||
pezframe-benchmarking = { optional = true, workspace = true }
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
log = { workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
pezsp-consensus-sassafras = { features = ["serde"], workspace = true }
|
||||
pezsp-io = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
array-bytes = { workspace = true, default-features = true }
|
||||
pezsp-core = { workspace = true, default-features = true }
|
||||
pezsp-crypto-hashing = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"pezframe-benchmarking?/std",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"log/std",
|
||||
"scale-info/std",
|
||||
"pezsp-consensus-sassafras/std",
|
||||
"pezsp-io/std",
|
||||
"pezsp-runtime/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezframe-benchmarking/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezsp-consensus-sassafras/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"pezframe-support/try-runtime",
|
||||
"pezframe-system/try-runtime",
|
||||
"pezsp-runtime/try-runtime",
|
||||
]
|
||||
# Construct dummy ring context on genesis.
|
||||
# Mostly used for testing and development.
|
||||
construct-dummy-ring-context = []
|
||||
@@ -0,0 +1,8 @@
|
||||
Runtime module for SASSAFRAS consensus.
|
||||
|
||||
- Tracking issue: https://github.com/pezkuwichain/pezkuwi-sdk/issues/95
|
||||
- Protocol RFC proposal: https://github.com/polkadot-fellows/RFCs/pull/26
|
||||
|
||||
# ⚠️ WARNING ⚠️
|
||||
|
||||
The crate interfaces and structures are experimental and may be subject to changes.
|
||||
@@ -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
|
||||
|
||||

|
||||
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user