mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-20 05:45:41 +00:00
fix BABE randomness calculation (#3305)
This commit is contained in:
committed by
DemiMarie-parity
parent
a7c6950f1b
commit
d5726d8e8a
@@ -79,8 +79,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||||||
// and set impl_version to equal spec_version. If only runtime
|
// and set impl_version to equal spec_version. If only runtime
|
||||||
// implementation changes and behavior does not, then leave spec_version as
|
// implementation changes and behavior does not, then leave spec_version as
|
||||||
// is and increment impl_version.
|
// is and increment impl_version.
|
||||||
spec_version: 127,
|
spec_version: 129,
|
||||||
impl_version: 128,
|
impl_version: 129,
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
pub use timestamp;
|
pub use timestamp;
|
||||||
|
|
||||||
use rstd::{result, prelude::*};
|
use rstd::{result, prelude::*};
|
||||||
use srml_support::{decl_storage, decl_module, StorageValue, traits::FindAuthor, traits::Get};
|
use srml_support::{decl_storage, decl_module, StorageValue, StorageMap, traits::FindAuthor, traits::Get};
|
||||||
use timestamp::{OnTimestampSet};
|
use timestamp::{OnTimestampSet};
|
||||||
use sr_primitives::{generic::DigestItem, ConsensusEngineId};
|
use sr_primitives::{generic::DigestItem, ConsensusEngineId};
|
||||||
use sr_primitives::traits::{IsMember, SaturatedConversion, Saturating, RandomnessBeacon, Convert};
|
use sr_primitives::traits::{IsMember, SaturatedConversion, Saturating, RandomnessBeacon, Convert};
|
||||||
@@ -115,6 +115,8 @@ pub trait Trait: timestamp::Trait {
|
|||||||
/// The length of the BABE randomness
|
/// The length of the BABE randomness
|
||||||
pub const RANDOMNESS_LENGTH: usize = 32;
|
pub const RANDOMNESS_LENGTH: usize = 32;
|
||||||
|
|
||||||
|
const UNDER_CONSTRUCTION_SEGMENT_LENGTH: usize = 256;
|
||||||
|
|
||||||
decl_storage! {
|
decl_storage! {
|
||||||
trait Store for Module<T: Trait> as Babe {
|
trait Store for Module<T: Trait> as Babe {
|
||||||
/// Current epoch index.
|
/// Current epoch index.
|
||||||
@@ -150,7 +152,16 @@ decl_storage! {
|
|||||||
NextRandomness: [u8; 32 /* RANDOMNESS_LENGTH */];
|
NextRandomness: [u8; 32 /* RANDOMNESS_LENGTH */];
|
||||||
|
|
||||||
/// Randomness under construction.
|
/// Randomness under construction.
|
||||||
UnderConstruction: [u8; 32 /* VRF_OUTPUT_LENGTH */];
|
///
|
||||||
|
/// We make a tradeoff between storage accesses and list length.
|
||||||
|
/// We store the under-construction randomness in segments of up to
|
||||||
|
/// `UNDER_CONSTRUCTION_SEGMENT_LENGTH`.
|
||||||
|
///
|
||||||
|
/// Once a segment reaches this length, we begin the next one.
|
||||||
|
/// We reset all segments and return to `0` at the beginning of every
|
||||||
|
/// epoch.
|
||||||
|
SegmentIndex build(|_| 0): u32;
|
||||||
|
UnderConstruction: map u32 => Vec<[u8; 32 /* VRF_OUTPUT_LENGTH */]>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,19 +259,35 @@ impl<T: Trait> Module<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deposit_vrf_output(vrf_output: &[u8; VRF_OUTPUT_LENGTH]) {
|
fn deposit_vrf_output(vrf_output: &[u8; VRF_OUTPUT_LENGTH]) {
|
||||||
UnderConstruction::mutate(|z| z.iter_mut().zip(vrf_output).for_each(|(x, y)| *x^=y))
|
let segment_idx = <SegmentIndex>::get();
|
||||||
|
let mut segment = <UnderConstruction>::get(&segment_idx);
|
||||||
|
if segment.len() < UNDER_CONSTRUCTION_SEGMENT_LENGTH {
|
||||||
|
// push onto current segment: not full.
|
||||||
|
segment.push(*vrf_output);
|
||||||
|
<UnderConstruction>::insert(&segment_idx, &segment);
|
||||||
|
} else {
|
||||||
|
// move onto the next segment and update the index.
|
||||||
|
let segment_idx = segment_idx + 1;
|
||||||
|
<UnderConstruction>::insert(&segment_idx, vec![*vrf_output].as_ref());
|
||||||
|
<SegmentIndex>::put(&segment_idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call this function exactly once when an epoch changes, to update the
|
/// Call this function exactly once when an epoch changes, to update the
|
||||||
/// randomness. Returns the new randomness.
|
/// randomness. Returns the new randomness.
|
||||||
fn randomness_change_epoch(next_epoch_index: u64) -> [u8; RANDOMNESS_LENGTH] {
|
fn randomness_change_epoch(next_epoch_index: u64) -> [u8; RANDOMNESS_LENGTH] {
|
||||||
let this_randomness = NextRandomness::get();
|
let this_randomness = NextRandomness::get();
|
||||||
|
let segment_idx: u32 = <SegmentIndex>::mutate(|s| rstd::mem::replace(s, 0));
|
||||||
|
|
||||||
|
// overestimate to the segment being full.
|
||||||
|
let rho_size = segment_idx.saturating_add(1) as usize * UNDER_CONSTRUCTION_SEGMENT_LENGTH;
|
||||||
|
|
||||||
let next_randomness = compute_randomness(
|
let next_randomness = compute_randomness(
|
||||||
this_randomness,
|
this_randomness,
|
||||||
next_epoch_index,
|
next_epoch_index,
|
||||||
UnderConstruction::get(),
|
(0..segment_idx).flat_map(|i| <UnderConstruction>::take(&i)),
|
||||||
|
Some(rho_size),
|
||||||
);
|
);
|
||||||
UnderConstruction::put(&[0; RANDOMNESS_LENGTH]);
|
|
||||||
NextRandomness::put(&next_randomness);
|
NextRandomness::put(&next_randomness);
|
||||||
this_randomness
|
this_randomness
|
||||||
}
|
}
|
||||||
@@ -345,15 +372,24 @@ impl<T: Trait + staking::Trait> session::OneSessionHandler<T::AccountId> for Mod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compute randomness for a new epoch. rho is the concatenation of all
|
||||||
|
// VRF outputs in the prior epoch.
|
||||||
|
//
|
||||||
|
// an optional size hint as to how many VRF outputs there were may be provided.
|
||||||
fn compute_randomness(
|
fn compute_randomness(
|
||||||
last_epoch_randomness: [u8; RANDOMNESS_LENGTH],
|
last_epoch_randomness: [u8; RANDOMNESS_LENGTH],
|
||||||
epoch_index: u64,
|
epoch_index: u64,
|
||||||
rho: [u8; VRF_OUTPUT_LENGTH],
|
rho: impl Iterator<Item=[u8; VRF_OUTPUT_LENGTH]>,
|
||||||
|
rho_size_hint: Option<usize>,
|
||||||
) -> [u8; RANDOMNESS_LENGTH] {
|
) -> [u8; RANDOMNESS_LENGTH] {
|
||||||
let mut s = [0; 40 + VRF_OUTPUT_LENGTH];
|
let mut s = Vec::with_capacity(40 + rho_size_hint.unwrap_or(0) * VRF_OUTPUT_LENGTH);
|
||||||
s[..32].copy_from_slice(&last_epoch_randomness);
|
s.extend_from_slice(&last_epoch_randomness);
|
||||||
s[32..40].copy_from_slice(&epoch_index.to_le_bytes());
|
s.extend_from_slice(&epoch_index.to_le_bytes());
|
||||||
s[40..].copy_from_slice(&rho);
|
|
||||||
|
for vrf_output in rho {
|
||||||
|
s.extend_from_slice(&vrf_output[..]);
|
||||||
|
}
|
||||||
|
|
||||||
runtime_io::blake2_256(&s)
|
runtime_io::blake2_256(&s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user