sc_consensus_manual_seal/consensus/
babe.rs1use super::ConsensusDataProvider;
23use crate::{Error, LOG_TARGET};
24use codec::Encode;
25use sc_client_api::{AuxStore, UsageProvider};
26use sc_consensus_babe::{
27 authorship, find_pre_digest, BabeIntermediate, CompatibleDigestItem, Epoch, INTERMEDIATE_KEY,
28};
29use sc_consensus_epochs::{
30 descendent_query, EpochHeader, SharedEpochChanges, ViableEpochDescriptor,
31};
32use sp_keystore::KeystorePtr;
33use std::{marker::PhantomData, sync::Arc};
34
35use sc_consensus::{BlockImportParams, ForkChoiceStrategy, Verifier};
36use sp_api::ProvideRuntimeApi;
37use sp_blockchain::{HeaderBackend, HeaderMetadata};
38use sp_consensus_babe::{
39 digests::{NextEpochDescriptor, PreDigest, SecondaryPlainPreDigest},
40 inherents::BabeInherentData,
41 AuthorityId, BabeApi, BabeAuthorityWeight, BabeConfiguration, ConsensusLog, BABE_ENGINE_ID,
42};
43use sp_consensus_slots::Slot;
44use sp_inherents::InherentData;
45use sp_runtime::{
46 generic::Digest,
47 traits::{Block as BlockT, Header},
48 DigestItem,
49};
50use sp_timestamp::TimestampInherentData;
51
52pub struct BabeConsensusDataProvider<B: BlockT, C, P> {
55 keystore: KeystorePtr,
57
58 client: Arc<C>,
60
61 epoch_changes: SharedEpochChanges<B, Epoch>,
63
64 config: BabeConfiguration,
69
70 authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
72 _phantom: PhantomData<P>,
73}
74
75pub struct BabeVerifier<B: BlockT, C> {
77 epoch_changes: SharedEpochChanges<B, Epoch>,
79
80 client: Arc<C>,
82}
83
84impl<B: BlockT, C> BabeVerifier<B, C> {
85 pub fn new(epoch_changes: SharedEpochChanges<B, Epoch>, client: Arc<C>) -> BabeVerifier<B, C> {
87 BabeVerifier { epoch_changes, client }
88 }
89}
90
91#[async_trait::async_trait]
93impl<B, C> Verifier<B> for BabeVerifier<B, C>
94where
95 B: BlockT,
96 C: HeaderBackend<B> + HeaderMetadata<B, Error = sp_blockchain::Error>,
97{
98 async fn verify(
99 &self,
100 mut import_params: BlockImportParams<B>,
101 ) -> Result<BlockImportParams<B>, String> {
102 import_params.finalized = false;
103 import_params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
104
105 let pre_digest = find_pre_digest::<B>(&import_params.header)?;
106
107 let parent_hash = import_params.header.parent_hash();
108 let parent = self
109 .client
110 .header(*parent_hash)
111 .ok()
112 .flatten()
113 .ok_or_else(|| format!("header for block {} not found", parent_hash))?;
114 let epoch_changes = self.epoch_changes.shared_data();
115 let epoch_descriptor = epoch_changes
116 .epoch_descriptor_for_child_of(
117 descendent_query(&*self.client),
118 &parent.hash(),
119 *parent.number(),
120 pre_digest.slot(),
121 )
122 .map_err(|e| format!("failed to fetch epoch_descriptor: {}", e))?
123 .ok_or_else(|| format!("{}", sp_consensus::Error::InvalidAuthoritiesSet))?;
124 drop(epoch_changes);
126
127 import_params
128 .insert_intermediate(INTERMEDIATE_KEY, BabeIntermediate::<B> { epoch_descriptor });
129
130 Ok(import_params)
131 }
132}
133
134impl<B, C, P> BabeConsensusDataProvider<B, C, P>
135where
136 B: BlockT,
137 C: AuxStore
138 + HeaderBackend<B>
139 + ProvideRuntimeApi<B>
140 + HeaderMetadata<B, Error = sp_blockchain::Error>
141 + UsageProvider<B>,
142 C::Api: BabeApi<B>,
143{
144 pub fn new(
145 client: Arc<C>,
146 keystore: KeystorePtr,
147 epoch_changes: SharedEpochChanges<B, Epoch>,
148 authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
149 ) -> Result<Self, Error> {
150 if authorities.is_empty() {
151 return Err(Error::StringError("Cannot supply empty authority set!".into()))
152 }
153
154 let config = sc_consensus_babe::configuration(&*client)?;
155
156 Ok(Self {
157 config,
158 client,
159 keystore,
160 epoch_changes,
161 authorities,
162 _phantom: Default::default(),
163 })
164 }
165
166 fn epoch(&self, parent: &B::Header, slot: Slot) -> Result<Epoch, Error> {
167 let epoch_changes = self.epoch_changes.shared_data();
168 let epoch_descriptor = epoch_changes
169 .epoch_descriptor_for_child_of(
170 descendent_query(&*self.client),
171 &parent.hash(),
172 *parent.number(),
173 slot,
174 )
175 .map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
176 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
177
178 let epoch = epoch_changes
179 .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot))
180 .ok_or_else(|| {
181 log::info!(target: LOG_TARGET, "create_digest: no viable_epoch :(");
182 sp_consensus::Error::InvalidAuthoritiesSet
183 })?;
184
185 Ok(epoch.as_ref().clone())
186 }
187}
188
189impl<B, C, P> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C, P>
190where
191 B: BlockT,
192 C: AuxStore
193 + HeaderBackend<B>
194 + HeaderMetadata<B, Error = sp_blockchain::Error>
195 + UsageProvider<B>
196 + ProvideRuntimeApi<B>,
197 C::Api: BabeApi<B>,
198 P: Send + Sync,
199{
200 type Proof = P;
201
202 fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result<Digest, Error> {
203 let slot = inherents
204 .babe_inherent_data()?
205 .ok_or_else(|| Error::StringError("No babe inherent data".into()))?;
206 let epoch = self.epoch(parent, slot)?;
207
208 let logs = if let Some((predigest, _)) =
210 authorship::claim_slot(slot, &epoch, &self.keystore)
211 {
212 vec![<DigestItem as CompatibleDigestItem>::babe_pre_digest(predigest)]
213 } else {
214 let predigest =
218 PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot, authority_index: 0_u32 });
219
220 let mut epoch_changes = self.epoch_changes.shared_data();
221 let epoch_descriptor = epoch_changes
222 .epoch_descriptor_for_child_of(
223 descendent_query(&*self.client),
224 &parent.hash(),
225 *parent.number(),
226 slot,
227 )
228 .map_err(|e| {
229 Error::StringError(format!("failed to fetch epoch_descriptor: {}", e))
230 })?
231 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
232
233 match epoch_descriptor {
234 ViableEpochDescriptor::Signaled(identifier, _epoch_header) => {
235 let epoch_mut = epoch_changes
236 .epoch_mut(&identifier)
237 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
238
239 epoch_mut.authorities = self.authorities.clone();
241
242 let next_epoch = ConsensusLog::NextEpochData(NextEpochDescriptor {
243 authorities: self.authorities.clone(),
244 randomness: epoch_mut.randomness,
246 });
247
248 vec![
249 DigestItem::PreRuntime(BABE_ENGINE_ID, predigest.encode()),
250 DigestItem::Consensus(BABE_ENGINE_ID, next_epoch.encode()),
251 ]
252 },
253 ViableEpochDescriptor::UnimportedGenesis(_) => {
254 vec![DigestItem::PreRuntime(BABE_ENGINE_ID, predigest.encode())]
256 },
257 }
258 };
259
260 Ok(Digest { logs })
261 }
262
263 fn append_block_import(
264 &self,
265 parent: &B::Header,
266 params: &mut BlockImportParams<B>,
267 inherents: &InherentData,
268 _proof: Self::Proof,
269 ) -> Result<(), Error> {
270 let slot = inherents
271 .babe_inherent_data()?
272 .ok_or_else(|| Error::StringError("No babe inherent data".into()))?;
273 let epoch_changes = self.epoch_changes.shared_data();
274 let mut epoch_descriptor = epoch_changes
275 .epoch_descriptor_for_child_of(
276 descendent_query(&*self.client),
277 &parent.hash(),
278 *parent.number(),
279 slot,
280 )
281 .map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
282 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
283 drop(epoch_changes);
285 let epoch = self.epoch(parent, slot)?;
287 let (authority, _) = self.authorities.first().expect("authorities is non-emptyp; qed");
288 let has_authority = epoch.authorities.iter().any(|(id, _)| *id == *authority);
289
290 if !has_authority {
291 log::info!(target: LOG_TARGET, "authority not found");
292 let timestamp = inherents
293 .timestamp_inherent_data()?
294 .ok_or_else(|| Error::StringError("No timestamp inherent data".into()))?;
295
296 let slot = Slot::from_timestamp(timestamp, self.config.slot_duration());
297
298 epoch_descriptor = match epoch_descriptor {
300 ViableEpochDescriptor::Signaled(identifier, _header) =>
301 ViableEpochDescriptor::Signaled(
302 identifier,
303 EpochHeader {
304 start_slot: slot,
305 end_slot: (*slot * self.config.epoch_length).into(),
306 },
307 ),
308 _ => unreachable!(
309 "we're not in the authorities, so this isn't the genesis epoch; qed"
310 ),
311 };
312 }
313
314 params.insert_intermediate(INTERMEDIATE_KEY, BabeIntermediate::<B> { epoch_descriptor });
315
316 Ok(())
317 }
318}