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};
40
41pub mod consensus_hook;
42pub mod migration;
43mod test;
44
45pub use consensus_hook::FixedVelocityConsensusHook;
46
47type Aura<T> = pallet_aura::Pallet<T>;
48
49pub use pallet::*;
50
51#[frame_support::pallet]
52pub mod pallet {
53 use super::*;
54 use frame_support::pallet_prelude::*;
55 use frame_system::pallet_prelude::*;
56
57 #[pallet::config]
59 pub trait Config: pallet_aura::Config + frame_system::Config {}
60
61 #[pallet::pallet]
62 #[pallet::storage_version(migration::STORAGE_VERSION)]
63 pub struct Pallet<T>(_);
64
65 #[pallet::hooks]
66 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
67 fn on_finalize(_: BlockNumberFor<T>) {
68 Authorities::<T>::put(pallet_aura::Authorities::<T>::get());
70 }
71
72 fn on_initialize(_: BlockNumberFor<T>) -> Weight {
73 Authorities::<T>::get();
75
76 T::DbWeight::get().reads_writes(1, 0)
77 }
78 }
79
80 #[pallet::storage]
86 pub(crate) type Authorities<T: Config> = StorageValue<
87 _,
88 BoundedVec<T::AuthorityId, <T as pallet_aura::Config>::MaxAuthorities>,
89 ValueQuery,
90 >;
91
92 #[pallet::storage]
97 pub(crate) type RelaySlotInfo<T: Config> = StorageValue<_, (Slot, u32), OptionQuery>;
98
99 #[pallet::genesis_config]
100 #[derive(frame_support::DefaultNoBound)]
101 pub struct GenesisConfig<T: Config> {
102 #[serde(skip)]
103 pub _config: core::marker::PhantomData<T>,
104 }
105
106 #[pallet::genesis_build]
107 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
108 fn build(&self) {
109 let authorities = pallet_aura::Authorities::<T>::get();
110 Authorities::<T>::put(authorities);
111 }
112 }
113}
114
115pub struct BlockExecutor<T, I>(core::marker::PhantomData<(T, I)>);
120
121impl<Block, T, I> ExecuteBlock<Block> for BlockExecutor<T, I>
122where
123 Block: BlockT,
124 T: Config,
125 I: ExecuteBlock<Block>,
126{
127 fn execute_block(block: Block) {
128 let (mut header, extrinsics) = block.deconstruct();
129 let authorities = Authorities::<T>::get();
132
133 let mut seal = None;
134 header.digest_mut().logs.retain(|s| {
135 let s =
136 CompatibleDigestItem::<<T::AuthorityId as RuntimeAppPublic>::Signature>::as_aura_seal(s);
137 match (s, seal.is_some()) {
138 (Some(_), true) => panic!("Found multiple AuRa seal digests"),
139 (None, _) => true,
140 (Some(s), false) => {
141 seal = Some(s);
142 false
143 },
144 }
145 });
146
147 let seal = seal.expect("Could not find an AuRa seal digest!");
148
149 let author = Aura::<T>::find_author(
150 header.digest().logs().iter().filter_map(|d| d.as_pre_runtime()),
151 )
152 .expect("Could not find AuRa author index!");
153
154 let pre_hash = header.hash();
155
156 if !authorities
157 .get(author as usize)
158 .unwrap_or_else(|| {
159 panic!("Invalid AuRa author index {} for authorities: {:?}", author, authorities)
160 })
161 .verify(&pre_hash, &seal)
162 {
163 panic!("Invalid AuRa seal");
164 }
165
166 I::execute_block(Block::new(header, extrinsics));
167 }
168}