cumulus_pallet_aura_ext/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
36
37use frame_support::traits::{ExecuteBlock, FindAuthor};
38use sp_application_crypto::RuntimeAppPublic;
39use sp_consensus_aura::{digests::CompatibleDigestItem, Slot};
40use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
41
42pub mod consensus_hook;
43pub use consensus_hook::FixedVelocityConsensusHook;
44
45type Aura<T> = pallet_aura::Pallet<T>;
46
47pub use pallet::*;
48
49#[frame_support::pallet]
50pub mod pallet {
51 use super::*;
52 use frame_support::pallet_prelude::*;
53 use frame_system::pallet_prelude::*;
54
55 #[pallet::config]
57 pub trait Config: pallet_aura::Config + frame_system::Config {}
58
59 #[pallet::pallet]
60 pub struct Pallet<T>(_);
61
62 #[pallet::hooks]
63 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
64 fn on_finalize(_: BlockNumberFor<T>) {
65 Authorities::<T>::put(pallet_aura::Authorities::<T>::get());
67 }
68
69 fn on_initialize(_: BlockNumberFor<T>) -> Weight {
70 Authorities::<T>::get();
72
73 let new_slot = pallet_aura::CurrentSlot::<T>::get();
74
75 let (new_slot, authored) = match SlotInfo::<T>::get() {
76 Some((slot, authored)) if slot == new_slot => (slot, authored + 1),
77 Some((slot, _)) if slot < new_slot => (new_slot, 1),
78 Some(..) => {
79 panic!("slot moved backwards")
80 },
81 None => (new_slot, 1),
82 };
83
84 SlotInfo::<T>::put((new_slot, authored));
85
86 T::DbWeight::get().reads_writes(4, 2)
87 }
88 }
89
90 #[pallet::storage]
96 pub(crate) type Authorities<T: Config> = StorageValue<
97 _,
98 BoundedVec<T::AuthorityId, <T as pallet_aura::Config>::MaxAuthorities>,
99 ValueQuery,
100 >;
101
102 #[pallet::storage]
106 pub(crate) type SlotInfo<T: Config> = StorageValue<_, (Slot, u32), OptionQuery>;
107
108 #[pallet::genesis_config]
109 #[derive(frame_support::DefaultNoBound)]
110 pub struct GenesisConfig<T: Config> {
111 #[serde(skip)]
112 pub _config: core::marker::PhantomData<T>,
113 }
114
115 #[pallet::genesis_build]
116 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
117 fn build(&self) {
118 let authorities = pallet_aura::Authorities::<T>::get();
119 Authorities::<T>::put(authorities);
120 }
121 }
122}
123
124pub struct BlockExecutor<T, I>(core::marker::PhantomData<(T, I)>);
129
130impl<Block, T, I> ExecuteBlock<Block> for BlockExecutor<T, I>
131where
132 Block: BlockT,
133 T: Config,
134 I: ExecuteBlock<Block>,
135{
136 fn execute_block(block: Block) {
137 let (mut header, extrinsics) = block.deconstruct();
138 let authorities = Authorities::<T>::get();
141
142 let mut seal = None;
143 header.digest_mut().logs.retain(|s| {
144 let s =
145 CompatibleDigestItem::<<T::AuthorityId as RuntimeAppPublic>::Signature>::as_aura_seal(s);
146 match (s, seal.is_some()) {
147 (Some(_), true) => panic!("Found multiple AuRa seal digests"),
148 (None, _) => true,
149 (Some(s), false) => {
150 seal = Some(s);
151 false
152 },
153 }
154 });
155
156 let seal = seal.expect("Could not find an AuRa seal digest!");
157
158 let author = Aura::<T>::find_author(
159 header.digest().logs().iter().filter_map(|d| d.as_pre_runtime()),
160 )
161 .expect("Could not find AuRa author index!");
162
163 let pre_hash = header.hash();
164
165 if !authorities
166 .get(author as usize)
167 .unwrap_or_else(|| {
168 panic!("Invalid AuRa author index {} for authorities: {:?}", author, authorities)
169 })
170 .verify(&pre_hash, &seal)
171 {
172 panic!("Invalid AuRa seal");
173 }
174
175 I::execute_block(Block::new(header, extrinsics));
176 }
177}