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::sync::Arc;
34
35use sc_consensus::{BlockImportParams, ForkChoiceStrategy, Verifier};
36use sp_api::{ProvideRuntimeApi, StorageProof};
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> {
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}
73
74pub struct BabeVerifier<B: BlockT, C> {
76 epoch_changes: SharedEpochChanges<B, Epoch>,
78
79 client: Arc<C>,
81}
82
83impl<B: BlockT, C> BabeVerifier<B, C> {
84 pub fn new(epoch_changes: SharedEpochChanges<B, Epoch>, client: Arc<C>) -> BabeVerifier<B, C> {
86 BabeVerifier { epoch_changes, client }
87 }
88}
89
90#[async_trait::async_trait]
92impl<B, C> Verifier<B> for BabeVerifier<B, C>
93where
94 B: BlockT,
95 C: HeaderBackend<B> + HeaderMetadata<B, Error = sp_blockchain::Error>,
96{
97 async fn verify(
98 &self,
99 mut import_params: BlockImportParams<B>,
100 ) -> Result<BlockImportParams<B>, String> {
101 import_params.finalized = false;
102 import_params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
103
104 let pre_digest = find_pre_digest::<B>(&import_params.header)?;
105
106 let parent_hash = import_params.header.parent_hash();
107 let parent = self
108 .client
109 .header(*parent_hash)
110 .ok()
111 .flatten()
112 .ok_or_else(|| format!("header for block {} not found", parent_hash))?;
113 let epoch_changes = self.epoch_changes.shared_data();
114 let epoch_descriptor = epoch_changes
115 .epoch_descriptor_for_child_of(
116 descendent_query(&*self.client),
117 &parent.hash(),
118 *parent.number(),
119 pre_digest.slot(),
120 )
121 .map_err(|e| format!("failed to fetch epoch_descriptor: {}", e))?
122 .ok_or_else(|| format!("{}", sp_consensus::Error::InvalidAuthoritiesSet))?;
123 drop(epoch_changes);
125
126 import_params
127 .insert_intermediate(INTERMEDIATE_KEY, BabeIntermediate::<B> { epoch_descriptor });
128
129 Ok(import_params)
130 }
131}
132
133impl<B, C> BabeConsensusDataProvider<B, C>
134where
135 B: BlockT,
136 C: AuxStore
137 + HeaderBackend<B>
138 + ProvideRuntimeApi<B>
139 + HeaderMetadata<B, Error = sp_blockchain::Error>
140 + UsageProvider<B>,
141 C::Api: BabeApi<B>,
142{
143 pub fn new(
144 client: Arc<C>,
145 keystore: KeystorePtr,
146 epoch_changes: SharedEpochChanges<B, Epoch>,
147 authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
148 ) -> Result<Self, Error> {
149 if authorities.is_empty() {
150 return Err(Error::StringError("Cannot supply empty authority set!".into()))
151 }
152
153 let config = sc_consensus_babe::configuration(&*client)?;
154
155 Ok(Self { config, client, keystore, epoch_changes, authorities })
156 }
157
158 fn epoch(&self, parent: &B::Header, slot: Slot) -> Result<Epoch, Error> {
159 let epoch_changes = self.epoch_changes.shared_data();
160 let epoch_descriptor = epoch_changes
161 .epoch_descriptor_for_child_of(
162 descendent_query(&*self.client),
163 &parent.hash(),
164 *parent.number(),
165 slot,
166 )
167 .map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
168 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
169
170 let epoch = epoch_changes
171 .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot))
172 .ok_or_else(|| {
173 log::info!(target: LOG_TARGET, "create_digest: no viable_epoch :(");
174 sp_consensus::Error::InvalidAuthoritiesSet
175 })?;
176
177 Ok(epoch.as_ref().clone())
178 }
179}
180
181impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
182where
183 B: BlockT,
184 C: AuxStore
185 + HeaderBackend<B>
186 + HeaderMetadata<B, Error = sp_blockchain::Error>
187 + UsageProvider<B>
188 + ProvideRuntimeApi<B>,
189 C::Api: BabeApi<B>,
190{
191 fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result<Digest, Error> {
192 let slot = inherents
193 .babe_inherent_data()?
194 .ok_or_else(|| Error::StringError("No babe inherent data".into()))?;
195 let epoch = self.epoch(parent, slot)?;
196
197 let logs = if let Some((predigest, _)) =
199 authorship::claim_slot(slot, &epoch, &self.keystore)
200 {
201 vec![<DigestItem as CompatibleDigestItem>::babe_pre_digest(predigest)]
202 } else {
203 let predigest =
207 PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot, authority_index: 0_u32 });
208
209 let mut epoch_changes = self.epoch_changes.shared_data();
210 let epoch_descriptor = epoch_changes
211 .epoch_descriptor_for_child_of(
212 descendent_query(&*self.client),
213 &parent.hash(),
214 *parent.number(),
215 slot,
216 )
217 .map_err(|e| {
218 Error::StringError(format!("failed to fetch epoch_descriptor: {}", e))
219 })?
220 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
221
222 match epoch_descriptor {
223 ViableEpochDescriptor::Signaled(identifier, _epoch_header) => {
224 let epoch_mut = epoch_changes
225 .epoch_mut(&identifier)
226 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
227
228 epoch_mut.authorities = self.authorities.clone();
230
231 let next_epoch = ConsensusLog::NextEpochData(NextEpochDescriptor {
232 authorities: self.authorities.clone(),
233 randomness: epoch_mut.randomness,
235 });
236
237 vec![
238 DigestItem::PreRuntime(BABE_ENGINE_ID, predigest.encode()),
239 DigestItem::Consensus(BABE_ENGINE_ID, next_epoch.encode()),
240 ]
241 },
242 ViableEpochDescriptor::UnimportedGenesis(_) => {
243 vec![DigestItem::PreRuntime(BABE_ENGINE_ID, predigest.encode())]
245 },
246 }
247 };
248
249 Ok(Digest { logs })
250 }
251
252 fn append_block_import(
253 &self,
254 parent: &B::Header,
255 params: &mut BlockImportParams<B>,
256 inherents: &InherentData,
257 _proof: StorageProof,
258 ) -> Result<(), Error> {
259 let slot = inherents
260 .babe_inherent_data()?
261 .ok_or_else(|| Error::StringError("No babe inherent data".into()))?;
262 let epoch_changes = self.epoch_changes.shared_data();
263 let mut epoch_descriptor = epoch_changes
264 .epoch_descriptor_for_child_of(
265 descendent_query(&*self.client),
266 &parent.hash(),
267 *parent.number(),
268 slot,
269 )
270 .map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
271 .ok_or(sp_consensus::Error::InvalidAuthoritiesSet)?;
272 drop(epoch_changes);
274 let epoch = self.epoch(parent, slot)?;
276 let (authority, _) = self.authorities.first().expect("authorities is non-emptyp; qed");
277 let has_authority = epoch.authorities.iter().any(|(id, _)| *id == *authority);
278
279 if !has_authority {
280 log::info!(target: LOG_TARGET, "authority not found");
281 let timestamp = inherents
282 .timestamp_inherent_data()?
283 .ok_or_else(|| Error::StringError("No timestamp inherent data".into()))?;
284
285 let slot = Slot::from_timestamp(timestamp, self.config.slot_duration());
286
287 epoch_descriptor = match epoch_descriptor {
289 ViableEpochDescriptor::Signaled(identifier, _header) =>
290 ViableEpochDescriptor::Signaled(
291 identifier,
292 EpochHeader {
293 start_slot: slot,
294 end_slot: (*slot * self.config.epoch_length).into(),
295 },
296 ),
297 _ => unreachable!(
298 "we're not in the authorities, so this isn't the genesis epoch; qed"
299 ),
300 };
301 }
302
303 params.insert_intermediate(INTERMEDIATE_KEY, BabeIntermediate::<B> { epoch_descriptor });
304
305 Ok(())
306 }
307}