Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+43 -75
View File
@@ -18,30 +18,21 @@
//! RPC api for babe.
use sc_consensus_babe::{Epoch, authorship, Config};
use futures::{FutureExt as _, TryFutureExt as _};
use jsonrpc_core::{
Error as RpcError,
futures::future as rpc_future,
};
use jsonrpc_core::{futures::future as rpc_future, Error as RpcError};
use jsonrpc_derive::rpc;
use sc_consensus_babe::{authorship, Config, Epoch};
use sc_consensus_epochs::{descendent_query, Epoch as EpochT, SharedEpochChanges};
use sp_consensus_babe::{
AuthorityId,
BabeApi as BabeRuntimeApi,
digests::PreDigest,
};
use serde::{Deserialize, Serialize};
use sp_core::{
crypto::Public,
};
use sp_application_crypto::AppKey;
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
use sc_rpc_api::DenyUnsafe;
use sp_api::{ProvideRuntimeApi, BlockId};
use serde::{Deserialize, Serialize};
use sp_api::{BlockId, ProvideRuntimeApi};
use sp_application_crypto::AppKey;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use sp_consensus::{Error as ConsensusError, SelectChain};
use sp_consensus_babe::{digests::PreDigest, AuthorityId, BabeApi as BabeRuntimeApi};
use sp_core::crypto::Public;
use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
use sp_runtime::traits::{Block as BlockT, Header as _};
use sp_consensus::{SelectChain, Error as ConsensusError};
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as BlockChainError};
use std::{collections::HashMap, sync::Arc};
type FutureResult<T> = Box<dyn rpc_future::Future<Item = T, Error = RpcError> + Send>;
@@ -81,14 +72,7 @@ impl<B: BlockT, C, SC> BabeRpcHandler<B, C, SC> {
select_chain: SC,
deny_unsafe: DenyUnsafe,
) -> Self {
Self {
client,
shared_epoch_changes,
keystore,
babe_config,
select_chain,
deny_unsafe,
}
Self { client, shared_epoch_changes, keystore, babe_config, select_chain, deny_unsafe }
}
}
@@ -104,16 +88,10 @@ where
{
fn epoch_authorship(&self) -> FutureResult<HashMap<AuthorityId, EpochAuthorship>> {
if let Err(err) = self.deny_unsafe.check_if_safe() {
return Box::new(rpc_future::err(err.into()));
return Box::new(rpc_future::err(err.into()))
}
let (
babe_config,
keystore,
shared_epoch,
client,
select_chain,
) = (
let (babe_config, keystore, shared_epoch, client, select_chain) = (
self.babe_config.clone(),
self.keystore.clone(),
self.shared_epoch_changes.clone(),
@@ -126,14 +104,9 @@ where
.runtime_api()
.current_epoch_start(&BlockId::Hash(header.hash()))
.map_err(|err| Error::StringError(format!("{:?}", err)))?;
let epoch = epoch_data(
&shared_epoch,
&client,
&babe_config,
*epoch_start,
&select_chain,
)
.await?;
let epoch =
epoch_data(&shared_epoch, &client, &babe_config, *epoch_start, &select_chain)
.await?;
let (epoch_start, epoch_end) = (epoch.start_slot(), epoch.end_slot());
let mut claims: HashMap<AuthorityId, EpochAuthorship> = HashMap::new();
@@ -163,10 +136,10 @@ where
match claim {
PreDigest::Primary { .. } => {
claims.entry(key).or_default().primary.push(slot);
}
},
PreDigest::SecondaryPlain { .. } => {
claims.entry(key).or_default().secondary.push(slot);
}
},
PreDigest::SecondaryVRF { .. } => {
claims.entry(key).or_default().secondary_vrf.push(slot.into());
},
@@ -199,7 +172,7 @@ pub enum Error {
/// Consensus error
Consensus(ConsensusError),
/// Errors that can be formatted as a String
StringError(String)
StringError(String),
}
impl From<Error> for jsonrpc_core::Error {
@@ -226,13 +199,15 @@ where
SC: SelectChain<B>,
{
let parent = select_chain.best_chain().await?;
epoch_changes.shared_data().epoch_data_for_child_of(
descendent_query(&**client),
&parent.hash(),
parent.number().clone(),
slot.into(),
|slot| Epoch::genesis(&babe_config, slot),
)
epoch_changes
.shared_data()
.epoch_data_for_child_of(
descendent_query(&**client),
&parent.hash(),
parent.number().clone(),
slot.into(),
|slot| Epoch::genesis(&babe_config, slot),
)
.map_err(|e| Error::Consensus(ConsensusError::ChainLookup(format!("{:?}", e))))?
.ok_or(Error::Consensus(ConsensusError::InvalidAuthoritiesSet))
}
@@ -240,31 +215,27 @@ where
#[cfg(test)]
mod tests {
use super::*;
use substrate_test_runtime_client::{
runtime::Block,
Backend,
DefaultTestClientBuilderExt,
TestClient,
TestClientBuilderExt,
TestClientBuilder,
};
use sp_application_crypto::AppPair;
use sp_keyring::Sr25519Keyring;
use sp_core::{crypto::key_types::BABE};
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
use sc_keystore::LocalKeystore;
use sp_application_crypto::AppPair;
use sp_core::crypto::key_types::BABE;
use sp_keyring::Sr25519Keyring;
use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
use substrate_test_runtime_client::{
runtime::Block, Backend, DefaultTestClientBuilderExt, TestClient, TestClientBuilder,
TestClientBuilderExt,
};
use std::sync::Arc;
use sc_consensus_babe::{Config, block_import, AuthorityPair};
use jsonrpc_core::IoHandler;
use sc_consensus_babe::{block_import, AuthorityPair, Config};
use std::sync::Arc;
/// creates keystore backed by a temp file
fn create_temp_keystore<P: AppPair>(
authority: Sr25519Keyring,
) -> (SyncCryptoStorePtr, tempfile::TempDir) {
let keystore_path = tempfile::tempdir().expect("Creates keystore path");
let keystore = Arc::new(LocalKeystore::open(keystore_path.path(), None)
.expect("Creates keystore"));
let keystore =
Arc::new(LocalKeystore::open(keystore_path.path(), None).expect("Creates keystore"));
SyncCryptoStore::sr25519_generate_new(&*keystore, BABE, Some(&authority.to_seed()))
.expect("Creates authority key");
@@ -272,17 +243,14 @@ mod tests {
}
fn test_babe_rpc_handler(
deny_unsafe: DenyUnsafe
deny_unsafe: DenyUnsafe,
) -> BabeRpcHandler<Block, TestClient, sc_consensus::LongestChain<Backend, Block>> {
let builder = TestClientBuilder::new();
let (client, longest_chain) = builder.build_with_longest_chain();
let client = Arc::new(client);
let config = Config::get_or_compute(&*client).expect("config available");
let (_, link) = block_import(
config.clone(),
client.clone(),
client.clone(),
).expect("can initialize block-import");
let (_, link) = block_import(config.clone(), client.clone(), client.clone())
.expect("can initialize block-import");
let epoch_changes = link.epoch_changes().clone();
let keystore = create_temp_keystore::<AuthorityPair>(Sr25519Keyring::Alice).0;
@@ -18,23 +18,17 @@
//! BABE authority selection and slot claiming.
use super::Epoch;
use codec::Encode;
use schnorrkel::{keys::PublicKey, vrf::VRFInOut};
use sp_application_crypto::AppKey;
use sp_consensus_babe::{
BABE_VRF_PREFIX, AuthorityId, BabeAuthorityWeight, make_transcript, make_transcript_data,
Slot,
};
use sp_consensus_babe::digests::{
PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest,
digests::{PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest},
make_transcript, make_transcript_data, AuthorityId, BabeAuthorityWeight, Slot, BABE_VRF_PREFIX,
};
use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof};
use sp_core::{U256, blake2_256, crypto::Public};
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
use codec::Encode;
use schnorrkel::{
keys::PublicKey,
vrf::VRFInOut,
};
use super::Epoch;
use sp_core::{blake2_256, crypto::Public, U256};
use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
/// Calculates the primary selection threshold for a given authority, taking
/// into account `c` (`1 - c` represents the probability of a slot being empty).
@@ -49,8 +43,7 @@ pub(super) fn calculate_primary_threshold(
let c = c.0 as f64 / c.1 as f64;
let theta =
authorities[authority_index].1 as f64 /
let theta = authorities[authority_index].1 as f64 /
authorities.iter().map(|(_, weight)| weight).sum::<u64>() as f64;
assert!(theta > 0.0, "authority with weight 0.");
@@ -74,14 +67,14 @@ pub(super) fn calculate_primary_threshold(
"returns None when the given value is negative; \
p is defined as `1 - n` where n is defined in (0, 1]; \
p must be a value in [0, 1); \
qed."
qed.",
);
let denom = p.denom().to_biguint().expect(
"returns None when the given value is negative; \
p is defined as `1 - n` where n is defined in (0, 1]; \
p must be a value in [0, 1); \
qed."
qed.",
);
((BigUint::one() << 128) * numer / denom).to_u128().expect(
@@ -108,7 +101,7 @@ pub(super) fn secondary_slot_author(
randomness: [u8; 32],
) -> Option<&AuthorityId> {
if authorities.is_empty() {
return None;
return None
}
let rand = U256::from((randomness, slot).using_encoded(blake2_256));
@@ -116,9 +109,10 @@ pub(super) fn secondary_slot_author(
let authorities_len = U256::from(authorities.len());
let idx = rand % authorities_len;
let expected_author = authorities.get(idx.as_u32() as usize)
.expect("authorities not empty; index constrained to list length; \
this is a valid index; qed");
let expected_author = authorities.get(idx.as_u32() as usize).expect(
"authorities not empty; index constrained to list length; \
this is a valid index; qed",
);
Some(&expected_author.0)
}
@@ -136,23 +130,15 @@ fn claim_secondary_slot(
let Epoch { authorities, randomness, epoch_index, .. } = epoch;
if authorities.is_empty() {
return None;
return None
}
let expected_author = secondary_slot_author(
slot,
authorities,
*randomness,
)?;
let expected_author = secondary_slot_author(slot, authorities, *randomness)?;
for (authority_id, authority_index) in keys {
if authority_id == expected_author {
let pre_digest = if author_secondary_vrf {
let transcript_data = make_transcript_data(
randomness,
slot,
*epoch_index,
);
let transcript_data = make_transcript_data(randomness, slot, *epoch_index);
let result = SyncCryptoStore::sr25519_vrf_sign(
&**keystore,
AuthorityId::ID,
@@ -169,7 +155,10 @@ fn claim_secondary_slot(
} else {
None
}
} else if SyncCryptoStore::has_keys(&**keystore, &[(authority_id.to_raw_vec(), AuthorityId::ID)]) {
} else if SyncCryptoStore::has_keys(
&**keystore,
&[(authority_id.to_raw_vec(), AuthorityId::ID)],
) {
Some(PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
slot,
authority_index: *authority_index as u32,
@@ -179,7 +168,7 @@ fn claim_secondary_slot(
};
if let Some(pre_digest) = pre_digest {
return Some((pre_digest, authority_id.clone()));
return Some((pre_digest, authority_id.clone()))
}
}
}
@@ -196,7 +185,9 @@ pub fn claim_slot(
epoch: &Epoch,
keystore: &SyncCryptoStorePtr,
) -> Option<(PreDigest, AuthorityId)> {
let authorities = epoch.authorities.iter()
let authorities = epoch
.authorities
.iter()
.enumerate()
.map(|(index, a)| (a.0.clone(), index))
.collect::<Vec<_>>();
@@ -211,22 +202,21 @@ pub fn claim_slot_using_keys(
keystore: &SyncCryptoStorePtr,
keys: &[(AuthorityId, usize)],
) -> Option<(PreDigest, AuthorityId)> {
claim_primary_slot(slot, epoch, epoch.config.c, keystore, &keys)
.or_else(|| {
if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() ||
epoch.config.allowed_slots.is_secondary_vrf_slots_allowed()
{
claim_secondary_slot(
slot,
&epoch,
keys,
&keystore,
epoch.config.allowed_slots.is_secondary_vrf_slots_allowed(),
)
} else {
None
}
})
claim_primary_slot(slot, epoch, epoch.config.c, keystore, &keys).or_else(|| {
if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() ||
epoch.config.allowed_slots.is_secondary_vrf_slots_allowed()
{
claim_secondary_slot(
slot,
&epoch,
keys,
&keystore,
epoch.config.allowed_slots.is_secondary_vrf_slots_allowed(),
)
} else {
None
}
})
}
/// Claim a primary slot if it is our turn. Returns `None` if it is not our turn.
@@ -243,16 +233,8 @@ fn claim_primary_slot(
let Epoch { authorities, randomness, epoch_index, .. } = epoch;
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
);
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
@@ -279,7 +261,7 @@ fn claim_primary_slot(
authority_index: *authority_index as u32,
});
return Some((pre_digest, authority_id.clone()));
return Some((pre_digest, authority_id.clone()))
}
}
}
@@ -290,10 +272,10 @@ fn claim_primary_slot(
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
use sp_core::{sr25519::Pair, crypto::Pair as _};
use sp_consensus_babe::{AuthorityId, BabeEpochConfiguration, AllowedSlots};
use sc_keystore::LocalKeystore;
use sp_consensus_babe::{AllowedSlots, AuthorityId, BabeEpochConfiguration};
use sp_core::{crypto::Pair as _, sr25519::Pair};
use std::sync::Arc;
#[test]
fn claim_secondary_plain_slot_works() {
@@ -302,7 +284,8 @@ mod tests {
&*keystore,
AuthorityId::ID,
Some(sp_core::crypto::DEV_PHRASE),
).unwrap();
)
.unwrap();
let authorities = vec![
(AuthorityId::from(Pair::generate().0.public()), 5),
@@ -18,15 +18,15 @@
//! Schema for BABE epoch changes in the aux-db.
use log::info;
use codec::{Decode, Encode};
use log::info;
use crate::{migration::EpochV0, Epoch};
use sc_client_api::backend::AuxStore;
use sp_blockchain::{Result as ClientResult, Error as ClientError};
use sp_runtime::traits::Block as BlockT;
use sc_consensus_epochs::{migration::EpochChangesForV0, EpochChangesFor, SharedEpochChanges};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_consensus_babe::{BabeBlockWeight, BabeGenesisConfiguration};
use sc_consensus_epochs::{EpochChangesFor, SharedEpochChanges, migration::EpochChangesForV0};
use crate::{Epoch, migration::EpochV0};
use sp_runtime::traits::Block as BlockT;
const BABE_EPOCH_CHANGES_VERSION: &[u8] = b"babe_epoch_changes_version";
const BABE_EPOCH_CHANGES_KEY: &[u8] = b"babe_epoch_changes";
@@ -38,16 +38,16 @@ pub fn block_weight_key<H: Encode>(block_hash: H) -> Vec<u8> {
}
fn load_decode<B, T>(backend: &B, key: &[u8]) -> ClientResult<Option<T>>
where
B: AuxStore,
T: Decode,
where
B: AuxStore,
T: Decode,
{
let corrupt = |e: codec::Error| {
ClientError::Backend(format!("BABE DB is corrupted. Decode error: {}", e))
};
match backend.get_aux(key)? {
None => Ok(None),
Some(t) => T::decode(&mut &t[..]).map(Some).map_err(corrupt)
Some(t) => T::decode(&mut &t[..]).map(Some).map_err(corrupt),
}
}
@@ -59,32 +59,26 @@ pub fn load_epoch_changes<Block: BlockT, B: AuxStore>(
let version = load_decode::<_, u32>(backend, BABE_EPOCH_CHANGES_VERSION)?;
let maybe_epoch_changes = match version {
None => load_decode::<_, EpochChangesForV0<Block, EpochV0>>(
backend,
BABE_EPOCH_CHANGES_KEY,
)?.map(|v0| v0.migrate().map(|_, _, epoch| epoch.migrate(config))),
Some(1) => load_decode::<_, EpochChangesFor<Block, EpochV0>>(
backend,
BABE_EPOCH_CHANGES_KEY,
)?.map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))),
Some(BABE_EPOCH_CHANGES_CURRENT_VERSION) => load_decode::<_, EpochChangesFor<Block, Epoch>>(
backend,
BABE_EPOCH_CHANGES_KEY,
)?,
Some(other) => {
return Err(ClientError::Backend(
format!("Unsupported BABE DB version: {:?}", other)
))
},
None =>
load_decode::<_, EpochChangesForV0<Block, EpochV0>>(backend, BABE_EPOCH_CHANGES_KEY)?
.map(|v0| v0.migrate().map(|_, _, epoch| epoch.migrate(config))),
Some(1) =>
load_decode::<_, EpochChangesFor<Block, EpochV0>>(backend, BABE_EPOCH_CHANGES_KEY)?
.map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))),
Some(BABE_EPOCH_CHANGES_CURRENT_VERSION) =>
load_decode::<_, EpochChangesFor<Block, Epoch>>(backend, BABE_EPOCH_CHANGES_KEY)?,
Some(other) =>
return Err(ClientError::Backend(format!("Unsupported BABE DB version: {:?}", other))),
};
let epoch_changes = SharedEpochChanges::<Block, Epoch>::new(maybe_epoch_changes.unwrap_or_else(|| {
info!(
target: "babe",
"👶 Creating empty BABE epoch changes on what appears to be first startup.",
);
EpochChangesFor::<Block, Epoch>::default()
}));
let epoch_changes =
SharedEpochChanges::<Block, Epoch>::new(maybe_epoch_changes.unwrap_or_else(|| {
info!(
target: "babe",
"👶 Creating empty BABE epoch changes on what appears to be first startup.",
);
EpochChangesFor::<Block, Epoch>::default()
}));
// rebalance the tree after deserialization. this isn't strictly necessary
// since the tree is now rebalanced on every update operation. but since the
@@ -99,15 +93,16 @@ pub fn load_epoch_changes<Block: BlockT, B: AuxStore>(
pub(crate) fn write_epoch_changes<Block: BlockT, F, R>(
epoch_changes: &EpochChangesFor<Block, Epoch>,
write_aux: F,
) -> R where
) -> R
where
F: FnOnce(&[(&'static [u8], &[u8])]) -> R,
{
BABE_EPOCH_CHANGES_CURRENT_VERSION.using_encoded(|version| {
let encoded_epoch_changes = epoch_changes.encode();
write_aux(
&[(BABE_EPOCH_CHANGES_KEY, encoded_epoch_changes.as_slice()),
(BABE_EPOCH_CHANGES_VERSION, version)],
)
write_aux(&[
(BABE_EPOCH_CHANGES_KEY, encoded_epoch_changes.as_slice()),
(BABE_EPOCH_CHANGES_VERSION, version),
])
})
}
@@ -116,15 +111,12 @@ pub(crate) fn write_block_weight<H: Encode, F, R>(
block_hash: H,
block_weight: BabeBlockWeight,
write_aux: F,
) -> R where
) -> R
where
F: FnOnce(&[(Vec<u8>, &[u8])]) -> R,
{
let key = block_weight_key(block_hash);
block_weight.using_encoded(|s|
write_aux(
&[(key, s)],
)
)
block_weight.using_encoded(|s| write_aux(&[(key, s)]))
}
/// Load the cumulative chain-weight associated with a block.
@@ -140,13 +132,13 @@ mod test {
use super::*;
use crate::migration::EpochV0;
use fork_tree::ForkTree;
use substrate_test_runtime_client;
use sc_consensus_epochs::{EpochHeader, PersistedEpoch, PersistedEpochHeader};
use sc_network_test::Block as TestBlock;
use sp_consensus::Error as ConsensusError;
use sp_consensus_babe::{AllowedSlots, BabeGenesisConfiguration};
use sp_core::H256;
use sp_runtime::traits::NumberFor;
use sp_consensus_babe::{AllowedSlots, BabeGenesisConfiguration};
use sc_consensus_epochs::{PersistedEpoch, PersistedEpochHeader, EpochHeader};
use sp_consensus::Error as ConsensusError;
use sc_network_test::Block as TestBlock;
use substrate_test_runtime_client;
#[test]
fn load_decode_from_v0_epoch_changes() {
@@ -159,26 +151,30 @@ mod test {
};
let client = substrate_test_runtime_client::new();
let mut v0_tree = ForkTree::<H256, NumberFor<TestBlock>, _>::new();
v0_tree.import::<_, ConsensusError>(
Default::default(),
Default::default(),
PersistedEpoch::Regular(epoch),
&|_, _| Ok(false), // Test is single item only so this can be set to false.
).unwrap();
v0_tree
.import::<_, ConsensusError>(
Default::default(),
Default::default(),
PersistedEpoch::Regular(epoch),
&|_, _| Ok(false), // Test is single item only so this can be set to false.
)
.unwrap();
client.insert_aux(
&[(BABE_EPOCH_CHANGES_KEY,
&EpochChangesForV0::<TestBlock, EpochV0>::from_raw(v0_tree).encode()[..])],
&[],
).unwrap();
client
.insert_aux(
&[(
BABE_EPOCH_CHANGES_KEY,
&EpochChangesForV0::<TestBlock, EpochV0>::from_raw(v0_tree).encode()[..],
)],
&[],
)
.unwrap();
assert_eq!(
load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(),
None,
);
assert_eq!(load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(), None,);
let epoch_changes = load_epoch_changes::<TestBlock, _>(
&client, &BabeGenesisConfiguration {
&client,
&BabeGenesisConfiguration {
slot_duration: 10,
epoch_length: 4,
c: (3, 10),
@@ -186,10 +182,12 @@ mod test {
randomness: Default::default(),
allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots,
},
).unwrap();
)
.unwrap();
assert!(
epoch_changes.shared_data()
epoch_changes
.shared_data()
.tree()
.iter()
.map(|(_, _, epoch)| epoch.clone())
@@ -200,16 +198,10 @@ mod test {
})],
); // PersistedEpochHeader does not implement Debug, so we use assert! directly.
write_epoch_changes::<TestBlock, _, _>(
&epoch_changes.shared_data(),
|values| {
client.insert_aux(values, &[]).unwrap();
},
);
write_epoch_changes::<TestBlock, _, _>(&epoch_changes.shared_data(), |values| {
client.insert_aux(values, &[]).unwrap();
});
assert_eq!(
load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(),
Some(2),
);
assert_eq!(load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(), Some(2),);
}
}
File diff suppressed because it is too large Load Diff
@@ -16,12 +16,12 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use codec::{Encode, Decode};
use sc_consensus_epochs::Epoch as EpochT;
use crate::{
Epoch, AuthorityId, BabeAuthorityWeight, BabeGenesisConfiguration,
BabeEpochConfiguration, VRF_OUTPUT_LENGTH, NextEpochDescriptor,
AuthorityId, BabeAuthorityWeight, BabeEpochConfiguration, BabeGenesisConfiguration, Epoch,
NextEpochDescriptor, VRF_OUTPUT_LENGTH,
};
use codec::{Decode, Encode};
use sc_consensus_epochs::Epoch as EpochT;
use sp_consensus_slots::Slot;
/// BABE epoch information, version 0.
@@ -43,10 +43,7 @@ impl EpochT for EpochV0 {
type NextEpochDescriptor = NextEpochDescriptor;
type Slot = Slot;
fn increment(
&self,
descriptor: NextEpochDescriptor
) -> EpochV0 {
fn increment(&self, descriptor: NextEpochDescriptor) -> EpochV0 {
EpochV0 {
epoch_index: self.epoch_index + 1,
start_slot: self.start_slot + self.duration,
@@ -74,10 +71,7 @@ impl EpochV0 {
duration: self.duration,
authorities: self.authorities,
randomness: self.randomness,
config: BabeEpochConfiguration {
c: config.c,
allowed_slots: config.allowed_slots,
},
config: BabeEpochConfiguration { c: config.c, allowed_slots: config.allowed_slots },
}
}
}
+207 -204
View File
@@ -23,35 +23,33 @@
#![allow(deprecated)]
use super::*;
use authorship::claim_slot;
use sp_core::crypto::Pair;
use sp_keystore::{
SyncCryptoStore,
vrf::make_transcript as transcript_from_data,
use futures::executor::block_on;
use log::debug;
use rand::RngCore;
use rand_chacha::{rand_core::SeedableRng, ChaChaRng};
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
use sc_client_api::{backend::TransactionFor, BlockchainEvents};
use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging;
use sc_keystore::LocalKeystore;
use sc_network::config::ProtocolConfig;
use sc_network_test::{Block as TestBlock, *};
use sp_application_crypto::key_types::BABE;
use sp_consensus::{
import_queue::{BoxBlockImport, BoxJustificationImport},
AlwaysCanAuthor, DisableProofRecording, NoNetwork as DummyOracle, Proposal,
};
use sp_consensus_babe::{
AuthorityPair, Slot, AllowedSlots, make_transcript, make_transcript_data,
inherents::InherentDataProvider,
inherents::InherentDataProvider, make_transcript, make_transcript_data, AllowedSlots,
AuthorityPair, Slot,
};
use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging;
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
use sp_consensus::{
NoNetwork as DummyOracle, Proposal, DisableProofRecording, AlwaysCanAuthor,
import_queue::{BoxBlockImport, BoxJustificationImport},
use sp_core::crypto::Pair;
use sp_keystore::{vrf::make_transcript as transcript_from_data, SyncCryptoStore};
use sp_runtime::{
generic::DigestItem,
traits::{Block as BlockT, DigestFor},
};
use sc_network_test::{Block as TestBlock, *};
use sc_network::config::ProtocolConfig;
use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}};
use sc_client_api::{BlockchainEvents, backend::TransactionFor};
use log::debug;
use std::{time::Duration, cell::RefCell, task::Poll};
use rand::RngCore;
use rand_chacha::{
rand_core::SeedableRng, ChaChaRng,
};
use sc_keystore::LocalKeystore;
use sp_application_crypto::key_types::BABE;
use futures::executor::block_on;
use sp_timestamp::InherentDataProvider as TimestampInherentDataProvider;
use std::{cell::RefCell, task::Poll, time::Duration};
type Item = DigestItem<Hash>;
@@ -95,10 +93,7 @@ impl Environment<TestBlock> for DummyFactory {
type Proposer = DummyProposer;
type Error = Error;
fn init(&mut self, parent_header: &<TestBlock as BlockT>::Header)
-> Self::CreateProposer
{
fn init(&mut self, parent_header: &<TestBlock as BlockT>::Header) -> Self::CreateProposer {
let parent_slot = crate::find_pre_digest::<TestBlock>(parent_header)
.expect("parent header has a pre-digest")
.slot();
@@ -113,23 +108,24 @@ impl Environment<TestBlock> for DummyFactory {
}
impl DummyProposer {
fn propose_with(&mut self, pre_digests: DigestFor<TestBlock>)
-> future::Ready<
Result<
Proposal<
TestBlock,
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>,
()
>,
Error
>
>
{
let block_builder = self.factory.client.new_block_at(
&BlockId::Hash(self.parent_hash),
pre_digests,
false,
).unwrap();
fn propose_with(
&mut self,
pre_digests: DigestFor<TestBlock>,
) -> future::Ready<
Result<
Proposal<
TestBlock,
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>,
(),
>,
Error,
>,
> {
let block_builder = self
.factory
.client
.new_block_at(&BlockId::Hash(self.parent_hash), pre_digests, false)
.unwrap();
let mut block = match block_builder.build().map_err(|e| e.into()) {
Ok(b) => b.block,
@@ -143,13 +139,14 @@ impl DummyProposer {
// figure out if we should add a consensus digest, since the test runtime
// doesn't.
let epoch_changes = self.factory.epoch_changes.shared_data();
let epoch = epoch_changes.epoch_data_for_child_of(
descendent_query(&*self.factory.client),
&self.parent_hash,
self.parent_number,
this_slot,
|slot| Epoch::genesis(&self.factory.config, slot),
)
let epoch = epoch_changes
.epoch_data_for_child_of(
descendent_query(&*self.factory.client),
&self.parent_hash,
self.parent_number,
this_slot,
|slot| Epoch::genesis(&self.factory.config, slot),
)
.expect("client has data to find epoch")
.expect("can compute epoch for baked block");
@@ -162,7 +159,8 @@ impl DummyProposer {
let digest_data = ConsensusLog::NextEpochData(NextEpochDescriptor {
authorities: epoch.authorities.clone(),
randomness: epoch.randomness.clone(),
}).encode();
})
.encode();
let digest = DigestItem::Consensus(BABE_ENGINE_ID, digest_data);
block.header.digest_mut().push(digest)
}
@@ -176,7 +174,8 @@ impl DummyProposer {
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Transaction = sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>;
type Transaction =
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>;
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction, ()>, Error>>;
type ProofRecording = DisableProofRecording;
type Proof = ();
@@ -201,9 +200,9 @@ pub struct PanickingBlockImport<B>(B);
#[async_trait::async_trait]
impl<B: BlockImport<TestBlock>> BlockImport<TestBlock> for PanickingBlockImport<B>
where
B::Transaction: Send,
B: Send,
where
B::Transaction: Send,
B: Send,
{
type Error = B::Error;
type Transaction = B::Transaction;
@@ -233,10 +232,8 @@ pub struct BabeTestNet {
type TestHeader = <TestBlock as BlockT>::Header;
type TestExtrinsic = <TestBlock as BlockT>::Extrinsic;
type TestSelectChain = substrate_test_runtime_client::LongestChain<
substrate_test_runtime_client::Backend,
TestBlock,
>;
type TestSelectChain =
substrate_test_runtime_client::LongestChain<substrate_test_runtime_client::Backend, TestBlock>;
pub struct TestVerifier {
inner: BabeVerifier<
@@ -244,11 +241,13 @@ pub struct TestVerifier {
PeersFullClient,
TestSelectChain,
AlwaysCanAuthor,
Box<dyn CreateInherentDataProviders<
TestBlock,
(),
InherentDataProviders = (TimestampInherentDataProvider, InherentDataProvider)
>>
Box<
dyn CreateInherentDataProviders<
TestBlock,
(),
InherentDataProviders = (TimestampInherentDataProvider, InherentDataProvider),
>,
>,
>,
mutator: Mutator,
}
@@ -274,7 +273,12 @@ impl Verifier<TestBlock> for TestVerifier {
pub struct PeerData {
link: BabeLink<TestBlock>,
block_import: Mutex<
Option<BoxBlockImport<TestBlock, TransactionFor<substrate_test_runtime_client::Backend, TestBlock>>>
Option<
BoxBlockImport<
TestBlock,
TransactionFor<substrate_test_runtime_client::Backend, TestBlock>,
>,
>,
>,
}
@@ -286,32 +290,27 @@ impl TestNetFactory for BabeTestNet {
/// Create new test network with peers and given config.
fn from_config(_config: &ProtocolConfig) -> Self {
debug!(target: "babe", "Creating test network from config");
BabeTestNet {
peers: Vec::new(),
}
BabeTestNet { peers: Vec::new() }
}
fn make_block_import(&self, client: PeersClient)
-> (
BlockImportAdapter<Self::BlockImport>,
Option<BoxJustificationImport<Block>>,
Option<PeerData>,
)
{
fn make_block_import(
&self,
client: PeersClient,
) -> (
BlockImportAdapter<Self::BlockImport>,
Option<BoxJustificationImport<Block>>,
Option<PeerData>,
) {
let client = client.as_full().expect("only full clients are tested");
let config = Config::get_or_compute(&*client).expect("config available");
let (block_import, link) = crate::block_import(
config,
client.clone(),
client.clone(),
).expect("can initialize block-import");
let (block_import, link) = crate::block_import(config, client.clone(), client.clone())
.expect("can initialize block-import");
let block_import = PanickingBlockImport(block_import);
let data_block_import = Mutex::new(
Some(Box::new(block_import.clone()) as BoxBlockImport<_, _>)
);
let data_block_import =
Mutex::new(Some(Box::new(block_import.clone()) as BoxBlockImport<_, _>));
(
BlockImportAdapter::new(block_import),
None,
@@ -324,16 +323,16 @@ impl TestNetFactory for BabeTestNet {
client: PeersClient,
_cfg: &ProtocolConfig,
maybe_link: &Option<PeerData>,
)
-> Self::Verifier
{
) -> Self::Verifier {
use substrate_test_runtime_client::DefaultTestClientBuilderExt;
let client = client.as_full().expect("only full clients are used in test");
trace!(target: "babe", "Creating a verifier");
// ensure block import and verifier are linked correctly.
let data = maybe_link.as_ref().expect("babe link always provided to verifier instantiation");
let data = maybe_link
.as_ref()
.expect("babe link always provided to verifier instantiation");
let (_, longest_chain) = TestClientBuilder::new().build_with_longest_chain();
@@ -369,10 +368,7 @@ impl TestNetFactory for BabeTestNet {
&self.peers
}
fn mut_peers<F: FnOnce(&mut Vec<BabePeer>)>(
&mut self,
closure: F,
) {
fn mut_peers<F: FnOnce(&mut Vec<BabePeer>)>(&mut self, closure: F) {
closure(&mut self.peers);
}
}
@@ -382,9 +378,7 @@ impl TestNetFactory for BabeTestNet {
fn rejects_empty_block() {
sp_tracing::try_init_simple();
let mut net = BabeTestNet::new(3);
let block_builder = |builder: BlockBuilder<_, _, _>| {
builder.build().unwrap().block
};
let block_builder = |builder: BlockBuilder<_, _, _>| builder.build().unwrap().block;
net.mut_peers(|peer| {
peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder);
})
@@ -397,11 +391,7 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static
MUTATOR.with(|m| *m.borrow_mut() = mutator.clone());
let net = BabeTestNet::new(3);
let peers = &[
(0, "//Alice"),
(1, "//Bob"),
(2, "//Charlie"),
];
let peers = &[(0, "//Alice"), (1, "//Bob"), (2, "//Charlie")];
let net = Arc::new(Mutex::new(net));
let mut import_notifications = Vec::new();
@@ -415,9 +405,10 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static
let select_chain = peer.select_chain().expect("Full client has select_chain");
let keystore_path = tempfile::tempdir().expect("Creates keystore path");
let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::open(keystore_path.path(), None)
.expect("Creates keystore"));
SyncCryptoStore::sr25519_generate_new(&*keystore, BABE, Some(seed)).expect("Generates authority key");
let keystore: SyncCryptoStorePtr =
Arc::new(LocalKeystore::open(keystore_path.path(), None).expect("Creates keystore"));
SyncCryptoStore::sr25519_generate_new(&*keystore, BABE, Some(seed))
.expect("Generates authority key");
keystore_paths.push(keystore_path);
let mut got_own = false;
@@ -435,47 +426,54 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static
import_notifications.push(
// run each future until we get one of our own blocks with number higher than 5
// that was produced locally.
client.import_notification_stream()
.take_while(move |n| future::ready(n.header.number() < &5 || {
if n.origin == BlockOrigin::Own {
got_own = true;
} else {
got_other = true;
}
client
.import_notification_stream()
.take_while(move |n| {
future::ready(
n.header.number() < &5 || {
if n.origin == BlockOrigin::Own {
got_own = true;
} else {
got_other = true;
}
// continue until we have at least one block of our own
// and one of another peer.
!(got_own && got_other)
}))
.for_each(|_| future::ready(()) )
// continue until we have at least one block of our own
// and one of another peer.
!(got_own && got_other)
},
)
})
.for_each(|_| future::ready(())),
);
babe_futures.push(
start_babe(BabeParams {
block_import: data.block_import.lock().take().expect("import set up during init"),
select_chain,
client,
env: environ,
sync_oracle: DummyOracle,
create_inherent_data_providers: Box::new(|_, _| async {
let timestamp = TimestampInherentDataProvider::from_system_time();
let slot = InherentDataProvider::from_timestamp_and_duration(
*timestamp,
Duration::from_secs(6),
);
babe_futures.push(start_babe(BabeParams {
block_import: data.block_import.lock().take().expect("import set up during init"),
select_chain,
client,
env: environ,
sync_oracle: DummyOracle,
create_inherent_data_providers: Box::new(|_, _| async {
let timestamp = TimestampInherentDataProvider::from_system_time();
let slot = InherentDataProvider::from_timestamp_and_duration(
*timestamp,
Duration::from_secs(6),
);
Ok((timestamp, slot))
}),
force_authoring: false,
backoff_authoring_blocks: Some(BackoffAuthoringOnFinalizedHeadLagging::default()),
babe_link: data.link.clone(),
keystore,
can_author_with: sp_consensus::AlwaysCanAuthor,
justification_sync_link: (),
block_proposal_slot_portion: SlotProportion::new(0.5),
max_block_proposal_slot_portion: None,
telemetry: None,
}).expect("Starts babe"));
Ok((timestamp, slot))
}),
force_authoring: false,
backoff_authoring_blocks: Some(BackoffAuthoringOnFinalizedHeadLagging::default()),
babe_link: data.link.clone(),
keystore,
can_author_with: sp_consensus::AlwaysCanAuthor,
justification_sync_link: (),
block_proposal_slot_portion: SlotProportion::new(0.5),
max_block_proposal_slot_portion: None,
telemetry: None,
})
.expect("Starts babe"),
);
}
block_on(future::select(
futures::future::poll_fn(move |cx| {
@@ -489,7 +487,7 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static
Poll::<()>::Pending
}),
future::select(future::join_all(import_notifications), future::join_all(babe_futures))
future::select(future::join_all(import_notifications), future::join_all(babe_futures)),
));
}
@@ -503,7 +501,8 @@ fn authoring_blocks() {
fn rejects_missing_inherent_digest() {
run_one_test(|header: &mut TestHeader, stage| {
let v = std::mem::take(&mut header.digest_mut().logs);
header.digest_mut().logs = v.into_iter()
header.digest_mut().logs = v
.into_iter()
.filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none())
.collect()
})
@@ -514,7 +513,8 @@ fn rejects_missing_inherent_digest() {
fn rejects_missing_seals() {
run_one_test(|header: &mut TestHeader, stage| {
let v = std::mem::take(&mut header.digest_mut().logs);
header.digest_mut().logs = v.into_iter()
header.digest_mut().logs = v
.into_iter()
.filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none())
.collect()
})
@@ -525,7 +525,8 @@ fn rejects_missing_seals() {
fn rejects_missing_consensus_digests() {
run_one_test(|header: &mut TestHeader, stage| {
let v = std::mem::take(&mut header.digest_mut().logs);
header.digest_mut().logs = v.into_iter()
header.digest_mut().logs = v
.into_iter()
.filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none())
.collect()
});
@@ -560,8 +561,8 @@ fn sig_is_not_pre_digest() {
fn can_author_block() {
sp_tracing::try_init_simple();
let keystore_path = tempfile::tempdir().expect("Creates keystore path");
let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::open(keystore_path.path(), None)
.expect("Creates keystore"));
let keystore: SyncCryptoStorePtr =
Arc::new(LocalKeystore::open(keystore_path.path(), None).expect("Creates keystore"));
let public = SyncCryptoStore::sr25519_generate_new(&*keystore, BABE, Some("//Alice"))
.expect("Generates authority pair");
@@ -601,8 +602,8 @@ fn can_author_block() {
None => i += 1,
Some(s) => {
debug!(target: "babe", "Authored block {:?}", s.0);
break;
}
break
},
}
}
}
@@ -622,26 +623,27 @@ fn propose_and_import_block<Transaction: Send + 'static>(
});
let pre_digest = sp_runtime::generic::Digest {
logs: vec![
Item::babe_pre_digest(
PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
authority_index: 0,
slot,
}),
),
],
logs: vec![Item::babe_pre_digest(PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
authority_index: 0,
slot,
}))],
};
let parent_hash = parent.hash();
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap().block;
let epoch_descriptor = proposer_factory.epoch_changes.shared_data().epoch_descriptor_for_child_of(
descendent_query(&*proposer_factory.client),
&parent_hash,
*parent.number(),
slot,
).unwrap().unwrap();
let epoch_descriptor = proposer_factory
.epoch_changes
.shared_data()
.epoch_descriptor_for_child_of(
descendent_query(&*proposer_factory.client),
&parent_hash,
*parent.number(),
slot,
)
.unwrap()
.unwrap();
let seal = {
// sign the pre-sealed hash of the block and then
@@ -706,13 +708,12 @@ fn importing_block_one_sets_genesis_epoch() {
let genesis_epoch = Epoch::genesis(&data.link.config, 999.into());
let epoch_changes = data.link.epoch_changes.shared_data();
let epoch_for_second_block = epoch_changes.epoch_data_for_child_of(
descendent_query(&*client),
&block_hash,
1,
1000.into(),
|slot| Epoch::genesis(&data.link.config, slot),
).unwrap().unwrap();
let epoch_for_second_block = epoch_changes
.epoch_data_for_child_of(descendent_query(&*client), &block_hash, 1, 1000.into(), |slot| {
Epoch::genesis(&data.link.config, slot)
})
.unwrap()
.unwrap();
assert_eq!(epoch_for_second_block, genesis_epoch);
}
@@ -779,16 +780,10 @@ fn importing_epoch_change_block_prunes_tree() {
let fork_3 = propose_and_import_blocks(BlockId::Hash(canon_hashes[18]), 10);
// We should be tracking a total of 9 epochs in the fork tree
assert_eq!(
epoch_changes.shared_data().tree().iter().count(),
9,
);
assert_eq!(epoch_changes.shared_data().tree().iter().count(), 9,);
// And only one root
assert_eq!(
epoch_changes.shared_data().tree().roots().count(),
1,
);
assert_eq!(epoch_changes.shared_data().tree().roots().count(), 1,);
// We finalize block #13 from the canon chain, so on the next epoch
// change the tree should be pruned, to not contain F (#7).
@@ -796,32 +791,47 @@ fn importing_epoch_change_block_prunes_tree() {
propose_and_import_blocks(BlockId::Hash(client.chain_info().best_hash), 7);
// at this point no hashes from the first fork must exist on the tree
assert!(
!epoch_changes.shared_data().tree().iter().map(|(h, _, _)| h).any(|h| fork_1.contains(h)),
);
assert!(!epoch_changes
.shared_data()
.tree()
.iter()
.map(|(h, _, _)| h)
.any(|h| fork_1.contains(h)),);
// but the epoch changes from the other forks must still exist
assert!(
epoch_changes.shared_data().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h))
);
assert!(epoch_changes
.shared_data()
.tree()
.iter()
.map(|(h, _, _)| h)
.any(|h| fork_2.contains(h)));
assert!(
epoch_changes.shared_data().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)),
);
assert!(epoch_changes
.shared_data()
.tree()
.iter()
.map(|(h, _, _)| h)
.any(|h| fork_3.contains(h)),);
// finalizing block #25 from the canon chain should prune out the second fork
client.finalize_block(BlockId::Hash(canon_hashes[24]), None, false).unwrap();
propose_and_import_blocks(BlockId::Hash(client.chain_info().best_hash), 8);
// at this point no hashes from the second fork must exist on the tree
assert!(
!epoch_changes.shared_data().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)),
);
assert!(!epoch_changes
.shared_data()
.tree()
.iter()
.map(|(h, _, _)| h)
.any(|h| fork_2.contains(h)),);
// while epoch changes from the last fork should still exist
assert!(
epoch_changes.shared_data().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)),
);
assert!(epoch_changes
.shared_data()
.tree()
.iter()
.map(|(h, _, _)| h)
.any(|h| fork_3.contains(h)),);
}
#[test]
@@ -856,20 +866,15 @@ fn verify_slots_are_strictly_increasing() {
// we should fail to import this block since the slot number didn't increase.
// we will panic due to the `PanickingBlockImport` defined above.
propose_and_import_block(
&b1,
Some(999.into()),
&mut proposer_factory,
&mut block_import,
);
propose_and_import_block(&b1, Some(999.into()), &mut proposer_factory, &mut block_import);
}
#[test]
fn babe_transcript_generation_match() {
sp_tracing::try_init_simple();
let keystore_path = tempfile::tempdir().expect("Creates keystore path");
let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::open(keystore_path.path(), None)
.expect("Creates keystore"));
let keystore: SyncCryptoStorePtr =
Arc::new(LocalKeystore::open(keystore_path.path(), None).expect("Creates keystore"));
let public = SyncCryptoStore::sr25519_generate_new(&*keystore, BABE, Some("//Alice"))
.expect("Generates authority pair");
@@ -890,9 +895,7 @@ fn babe_transcript_generation_match() {
let test = |t: merlin::Transcript| -> [u8; 16] {
let mut b = [0u8; 16];
t.build_rng()
.finalize(&mut ChaChaRng::from_seed([0u8;32]))
.fill_bytes(&mut b);
t.build_rng().finalize(&mut ChaChaRng::from_seed([0u8; 32])).fill_bytes(&mut b);
b
};
debug_assert!(test(orig_transcript) == test(transcript_from_data(new_transcript)));
@@ -17,18 +17,22 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Verification for BABE headers.
use sp_runtime::{traits::Header, traits::DigestItemFor};
use sp_core::{Pair, Public};
use sp_consensus_babe::{make_transcript, AuthoritySignature, AuthorityPair, AuthorityId};
use sp_consensus_babe::digests::{
PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest,
CompatibleDigestItem
use super::{
authorship::{calculate_primary_threshold, check_primary_threshold, secondary_slot_author},
babe_err, find_pre_digest, BlockT, Epoch, Error,
};
use sc_consensus_slots::CheckedHeader;
use sp_consensus_slots::Slot;
use log::{debug, trace};
use super::{find_pre_digest, babe_err, Epoch, BlockT, Error};
use super::authorship::{calculate_primary_threshold, check_primary_threshold, secondary_slot_author};
use sc_consensus_slots::CheckedHeader;
use sp_consensus_babe::{
digests::{
CompatibleDigestItem, PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest,
SecondaryVRFPreDigest,
},
make_transcript, AuthorityId, AuthorityPair, AuthoritySignature,
};
use sp_consensus_slots::Slot;
use sp_core::{Pair, Public};
use sp_runtime::traits::{DigestItemFor, Header};
/// BABE verification parameters
pub(super) struct VerificationParams<'a, B: 'a + BlockT> {
@@ -57,26 +61,24 @@ pub(super) struct VerificationParams<'a, B: 'a + BlockT> {
/// with each having different validation logic.
pub(super) fn check_header<B: BlockT + Sized>(
params: VerificationParams<B>,
) -> Result<CheckedHeader<B::Header, VerifiedHeaderInfo<B>>, Error<B>> where
) -> Result<CheckedHeader<B::Header, VerifiedHeaderInfo<B>>, Error<B>>
where
DigestItemFor<B>: CompatibleDigestItem,
{
let VerificationParams {
mut header,
pre_digest,
slot_now,
epoch,
} = params;
let VerificationParams { mut header, pre_digest, slot_now, epoch } = params;
let authorities = &epoch.authorities;
let pre_digest = pre_digest.map(Ok).unwrap_or_else(|| find_pre_digest::<B>(&header))?;
trace!(target: "babe", "Checking header");
let seal = header.digest_mut().pop()
let seal = header
.digest_mut()
.pop()
.ok_or_else(|| babe_err(Error::HeaderUnsealed(header.hash())))?;
let sig = seal.as_babe_seal().ok_or_else(|| {
babe_err(Error::HeaderBadSeal(header.hash()))
})?;
let sig = seal
.as_babe_seal()
.ok_or_else(|| babe_err(Error::HeaderBadSeal(header.hash())))?;
// the pre-hash of the header doesn't include the seal
// and that's what we sign
@@ -84,7 +86,7 @@ pub(super) fn check_header<B: BlockT + Sized>(
if pre_digest.slot() > slot_now {
header.digest_mut().push(seal);
return Ok(CheckedHeader::Deferred(header, pre_digest.slot()));
return Ok(CheckedHeader::Deferred(header, pre_digest.slot()))
}
let author = match authorities.get(pre_digest.authority_index() as usize) {
@@ -100,45 +102,31 @@ pub(super) fn check_header<B: BlockT + Sized>(
primary.slot,
);
check_primary_header::<B>(
pre_hash,
primary,
sig,
&epoch,
epoch.config.c,
)?;
check_primary_header::<B>(pre_hash, primary, sig, &epoch, epoch.config.c)?;
},
PreDigest::SecondaryPlain(secondary) if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() => {
PreDigest::SecondaryPlain(secondary)
if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() =>
{
debug!(target: "babe",
"Verifying secondary plain block #{} at slot: {}",
header.number(),
secondary.slot,
);
check_secondary_plain_header::<B>(
pre_hash,
secondary,
sig,
&epoch,
)?;
},
PreDigest::SecondaryVRF(secondary) if epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() => {
check_secondary_plain_header::<B>(pre_hash, secondary, sig, &epoch)?;
}
PreDigest::SecondaryVRF(secondary)
if epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() =>
{
debug!(target: "babe",
"Verifying secondary VRF block #{} at slot: {}",
header.number(),
secondary.slot,
);
check_secondary_vrf_header::<B>(
pre_hash,
secondary,
sig,
&epoch,
)?;
},
_ => {
return Err(babe_err(Error::SecondarySlotAssignmentsDisabled));
check_secondary_vrf_header::<B>(pre_hash, secondary, sig, &epoch)?;
}
_ => return Err(babe_err(Error::SecondarySlotAssignmentsDisabled)),
}
let info = VerifiedHeaderInfo {
@@ -170,27 +158,20 @@ fn check_primary_header<B: BlockT + Sized>(
if AuthorityPair::verify(&signature, pre_hash, &author) {
let (inout, _) = {
let transcript = make_transcript(
&epoch.randomness,
pre_digest.slot,
epoch.epoch_index,
);
let transcript = make_transcript(&epoch.randomness, pre_digest.slot, epoch.epoch_index);
schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| {
p.vrf_verify(transcript, &pre_digest.vrf_output, &pre_digest.vrf_proof)
}).map_err(|s| {
babe_err(Error::VRFVerificationFailed(s))
})?
schnorrkel::PublicKey::from_bytes(author.as_slice())
.and_then(|p| {
p.vrf_verify(transcript, &pre_digest.vrf_output, &pre_digest.vrf_proof)
})
.map_err(|s| babe_err(Error::VRFVerificationFailed(s)))?
};
let threshold = calculate_primary_threshold(
c,
&epoch.authorities,
pre_digest.authority_index as usize,
);
let threshold =
calculate_primary_threshold(c, &epoch.authorities, pre_digest.authority_index as usize);
if !check_primary_threshold(&inout, threshold) {
return Err(babe_err(Error::VRFVerificationOfBlockFailed(author.clone(), threshold)));
return Err(babe_err(Error::VRFVerificationOfBlockFailed(author.clone(), threshold)))
}
Ok(())
@@ -211,16 +192,14 @@ fn check_secondary_plain_header<B: BlockT>(
) -> Result<(), Error<B>> {
// check the signature is valid under the expected authority and
// chain state.
let expected_author = secondary_slot_author(
pre_digest.slot,
&epoch.authorities,
epoch.randomness,
).ok_or_else(|| Error::NoSecondaryAuthorExpected)?;
let expected_author =
secondary_slot_author(pre_digest.slot, &epoch.authorities, epoch.randomness)
.ok_or_else(|| Error::NoSecondaryAuthorExpected)?;
let author = &epoch.authorities[pre_digest.authority_index as usize].0;
if expected_author != author {
return Err(Error::InvalidAuthor(expected_author.clone(), author.clone()));
return Err(Error::InvalidAuthor(expected_author.clone(), author.clone()))
}
if AuthorityPair::verify(&signature, pre_hash.as_ref(), author) {
@@ -239,30 +218,22 @@ fn check_secondary_vrf_header<B: BlockT>(
) -> Result<(), Error<B>> {
// check the signature is valid under the expected authority and
// chain state.
let expected_author = secondary_slot_author(
pre_digest.slot,
&epoch.authorities,
epoch.randomness,
).ok_or_else(|| Error::NoSecondaryAuthorExpected)?;
let expected_author =
secondary_slot_author(pre_digest.slot, &epoch.authorities, epoch.randomness)
.ok_or_else(|| Error::NoSecondaryAuthorExpected)?;
let author = &epoch.authorities[pre_digest.authority_index as usize].0;
if expected_author != author {
return Err(Error::InvalidAuthor(expected_author.clone(), author.clone()));
return Err(Error::InvalidAuthor(expected_author.clone(), author.clone()))
}
if AuthorityPair::verify(&signature, pre_hash.as_ref(), author) {
let transcript = make_transcript(
&epoch.randomness,
pre_digest.slot,
epoch.epoch_index,
);
let transcript = make_transcript(&epoch.randomness, pre_digest.slot, epoch.epoch_index);
schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| {
p.vrf_verify(transcript, &pre_digest.vrf_output, &pre_digest.vrf_proof)
}).map_err(|s| {
babe_err(Error::VRFVerificationFailed(s))
})?;
schnorrkel::PublicKey::from_bytes(author.as_slice())
.and_then(|p| p.vrf_verify(transcript, &pre_digest.vrf_output, &pre_digest.vrf_proof))
.map_err(|s| babe_err(Error::VRFVerificationFailed(s)))?;
Ok(())
} else {