Sanity check for Babe's configuration (#11385)

* Prevent div by zero in native babe code
* Additional sanity check for babe config
* Further sanity checks and postpone threshold computation
* Apply suggestions from code review
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Davide Galassi
2022-05-10 15:37:51 +02:00
committed by GitHub
parent 29c0c6a4a8
commit 07098c7d50
2 changed files with 23 additions and 8 deletions
@@ -41,6 +41,14 @@ pub(super) fn calculate_primary_threshold(
use num_rational::BigRational;
use num_traits::{cast::ToPrimitive, identities::One};
// Prevent div by zero and out of bounds access.
// While Babe's pallet implementation that ships with FRAME performs a sanity check over
// configuration parameters, this is not sufficient to guarantee that `c.1` is non-zero
// (i.e. third party implementations are possible).
if c.1 == 0 || authority_index >= authorities.len() {
return 0
}
let c = c.0 as f64 / c.1 as f64;
let theta = authorities[authority_index].1 as f64 /
@@ -235,12 +243,6 @@ fn claim_primary_slot(
for (authority_id, authority_index) in keys {
let transcript = make_transcript(randomness, slot, *epoch_index);
let transcript_data = make_transcript_data(randomness, slot, *epoch_index);
// Compute the threshold we will use.
//
// We already checked that authorities contains `key.public()`, so it can't
// be empty. Therefore, this division in `calculate_threshold` is safe.
let threshold = calculate_primary_threshold(c, authorities, *authority_index);
let result = SyncCryptoStore::sr25519_vrf_sign(
&**keystore,
AuthorityId::ID,
@@ -253,6 +255,8 @@ fn claim_primary_slot(
Ok(inout) => inout,
Err(_) => continue,
};
let threshold = calculate_primary_threshold(c, authorities, *authority_index);
if check_primary_threshold(&inout, threshold) {
let pre_digest = PreDigest::Primary(PrimaryPreDigest {
slot,