From 99df39194d5de45f46aa107fe5debb49ef2678db Mon Sep 17 00:00:00 2001 From: Serban Iorga <serban@parity.io> Date: Fri, 15 Dec 2023 08:09:39 +0100 Subject: [PATCH] BEEFY: `expect_validator_set()` fix (#2716) Fixes #https://github.com/paritytech/polkadot-sdk/issues/2699 Modifying `expect_validator_set()` in order to be able to walk back until block 0. The chain state at block 0 is available even if we use `--sync fast` or `--sync warp`. This way we can retrieve the initial authority set even when BEEFY genesis is 1 and there is no authority change entry in the headers log. Credits to @acatangiu for the solution --------- Co-authored-by: Adrian Catangiu <adrian@parity.io> --- substrate/client/consensus/beefy/src/lib.rs | 38 ++++++++++----------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs index b3ff11add27..c3da2b886f4 100644 --- a/substrate/client/consensus/beefy/src/lib.rs +++ b/substrate/client/consensus/beefy/src/lib.rs @@ -543,25 +543,23 @@ where R: ProvideRuntimeApi<B>, R::Api: BeefyApi<B, AuthorityId>, { - debug!(target: LOG_TARGET, "🥩 Try to find validator set active at header: {:?}", at_header); - runtime - .runtime_api() - .validator_set(at_header.hash()) - .ok() - .flatten() - .or_else(|| { - // if state unavailable, fallback to walking up the chain looking for the header - // Digest emitted when validator set active 'at_header' was enacted. - let blockchain = backend.blockchain(); - let mut header = at_header.clone(); - loop { - debug!(target: LOG_TARGET, "🥩 look for auth set change digest in header number: {:?}", *header.number()); - match worker::find_authorities_change::<B>(&header) { - Some(active) => return Some(active), - // Move up the chain. - None => header = blockchain.expect_header(*header.parent_hash()).ok()?, - } + let blockchain = backend.blockchain(); + + // Walk up the chain looking for the validator set active at 'at_header'. Process both state and + // header digests. + debug!(target: LOG_TARGET, "🥩 Trying to find validator set active at header: {:?}", at_header); + let mut header = at_header.clone(); + loop { + if let Ok(Some(active)) = runtime.runtime_api().validator_set(at_header.hash()) { + return Ok(active) + } else { + debug!(target: LOG_TARGET, "🥩 Looking for auth set change at block number: {:?}", *header.number()); + match worker::find_authorities_change::<B>(&header) { + Some(active) => return Ok(active), + // Move up the chain. Ultimately we'll get it from chain genesis state, or error out + // here. + None => header = blockchain.expect_header(*header.parent_hash())?, } - }) - .ok_or_else(|| ClientError::Backend("Could not find initial validator set".into())) + } + } } -- GitLab