cumulus_pallet_aura_ext/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
35
36use frame_support::traits::{ExecuteBlock, FindAuthor};
37use sp_application_crypto::RuntimeAppPublic;
38use sp_consensus_aura::{digests::CompatibleDigestItem, Slot};
39use sp_runtime::traits::{Block as BlockT, Header as HeaderT, LazyBlock};
40
41pub mod consensus_hook;
42pub mod migration;
43pub mod signature_verifier;
44#[cfg(test)]
45mod test;
46
47pub use consensus_hook::FixedVelocityConsensusHook;
48pub use signature_verifier::AuraSchedulingVerifier;
49
50type Aura<T> = pallet_aura::Pallet<T>;
51
52pub use pallet::*;
53
54#[frame_support::pallet]
55pub mod pallet {
56 use super::*;
57 use frame_support::pallet_prelude::*;
58 use frame_system::pallet_prelude::*;
59
60 #[pallet::config]
62 pub trait Config: pallet_aura::Config + frame_system::Config {}
63
64 #[pallet::pallet]
65 #[pallet::storage_version(migration::STORAGE_VERSION)]
66 pub struct Pallet<T>(_);
67
68 #[pallet::hooks]
69 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
70 fn on_finalize(_: BlockNumberFor<T>) {
71 Authorities::<T>::put(pallet_aura::Authorities::<T>::get());
73 }
74
75 fn on_initialize(_: BlockNumberFor<T>) -> Weight {
76 Authorities::<T>::get();
78
79 T::DbWeight::get().reads_writes(1, 0)
80 }
81 }
82
83 #[pallet::storage]
89 pub(crate) type Authorities<T: Config> = StorageValue<
90 _,
91 BoundedVec<T::AuthorityId, <T as pallet_aura::Config>::MaxAuthorities>,
92 ValueQuery,
93 >;
94
95 #[pallet::storage]
100 pub(crate) type RelaySlotInfo<T: Config> = StorageValue<_, (Slot, u32), OptionQuery>;
101
102 #[pallet::genesis_config]
103 #[derive(frame_support::DefaultNoBound)]
104 pub struct GenesisConfig<T: Config> {
105 #[serde(skip)]
106 pub _config: core::marker::PhantomData<T>,
107 }
108
109 #[pallet::genesis_build]
110 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
111 fn build(&self) {
112 let authorities = pallet_aura::Authorities::<T>::get();
113 Authorities::<T>::put(authorities);
114 }
115 }
116}
117
118pub struct BlockExecutor<T, I>(core::marker::PhantomData<(T, I)>);
123
124impl<Block, T, I> ExecuteBlock<Block> for BlockExecutor<T, I>
125where
126 Block: BlockT,
127 T: Config,
128 I: ExecuteBlock<Block>,
129{
130 fn verify_and_remove_seal(block: &mut <Block as BlockT>::LazyBlock) {
131 let header = block.header_mut();
132 let authorities = Authorities::<T>::get();
135
136 let mut seal = None;
137 header.digest_mut().logs.retain(|s| {
138 let s =
139 CompatibleDigestItem::<<T::AuthorityId as RuntimeAppPublic>::Signature>::as_aura_seal(s);
140 match (s, seal.is_some()) {
141 (Some(_), true) => panic!("Found multiple AuRa seal digests"),
142 (None, _) => true,
143 (Some(s), false) => {
144 seal = Some(s);
145 false
146 },
147 }
148 });
149
150 let seal = seal.expect("Could not find an AuRa seal digest!");
151
152 let author = Aura::<T>::find_author(
153 header.digest().logs().iter().filter_map(|d| d.as_pre_runtime()),
154 )
155 .expect("Could not find AuRa author index!");
156
157 let pre_hash = header.hash();
158
159 if !authorities
160 .get(author as usize)
161 .unwrap_or_else(|| {
162 panic!("Invalid AuRa author index {} for authorities: {:?}", author, authorities)
163 })
164 .verify(&pre_hash, &seal)
165 {
166 panic!("Invalid AuRa seal");
167 }
168 }
169
170 fn execute_verified_block(block: Block::LazyBlock) {
171 I::execute_verified_block(block);
172 }
173}