1use crate::{
21 authorship::{calculate_primary_threshold, secondary_slot_author},
22 babe_err, find_pre_digest, BlockT, Epoch, Error, AUTHORING_SCORE_LENGTH,
23 AUTHORING_SCORE_VRF_CONTEXT, LOG_TARGET,
24};
25use log::{debug, trace};
26use sc_consensus_epochs::Epoch as EpochT;
27use sc_consensus_slots::CheckedHeader;
28use sp_consensus_babe::{
29 digests::{
30 CompatibleDigestItem, PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest,
31 SecondaryVRFPreDigest,
32 },
33 make_vrf_sign_data, AuthorityPair, AuthoritySignature,
34};
35use sp_consensus_slots::Slot;
36use sp_core::{
37 crypto::{VrfPublic, Wraps},
38 Pair,
39};
40use sp_runtime::{traits::Header, DigestItem};
41
42pub(super) struct VerificationParams<'a, B: 'a + BlockT> {
44 pub(super) header: B::Header,
46 pub(super) pre_digest: Option<PreDigest>,
50 pub(super) slot_now: Slot,
52 pub(super) epoch: &'a Epoch,
54}
55
56pub(super) fn check_header<B: BlockT + Sized>(
68 params: VerificationParams<B>,
69) -> Result<CheckedHeader<B::Header, VerifiedHeaderInfo>, Error<B>> {
70 let VerificationParams { mut header, pre_digest, slot_now, epoch } = params;
71
72 let pre_digest = pre_digest.map(Ok).unwrap_or_else(|| find_pre_digest::<B>(&header))?;
73
74 trace!(target: LOG_TARGET, "Checking header");
75 let seal = header
76 .digest_mut()
77 .pop()
78 .ok_or_else(|| babe_err(Error::HeaderUnsealed(header.hash())))?;
79
80 let sig = seal
81 .as_babe_seal()
82 .ok_or_else(|| babe_err(Error::HeaderBadSeal(header.hash())))?;
83
84 let pre_hash = header.hash();
87
88 if pre_digest.slot() > slot_now {
89 header.digest_mut().push(seal);
90 return Ok(CheckedHeader::Deferred(header, pre_digest.slot()))
91 }
92
93 match &pre_digest {
94 PreDigest::Primary(primary) => {
95 debug!(
96 target: LOG_TARGET,
97 "Verifying primary block #{} at slot: {}",
98 header.number(),
99 primary.slot,
100 );
101
102 check_primary_header::<B>(pre_hash, primary, sig, epoch, epoch.config.c)?;
103 },
104 PreDigest::SecondaryPlain(secondary)
105 if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() =>
106 {
107 debug!(
108 target: LOG_TARGET,
109 "Verifying secondary plain block #{} at slot: {}",
110 header.number(),
111 secondary.slot,
112 );
113
114 check_secondary_plain_header::<B>(pre_hash, secondary, sig, epoch)?;
115 },
116 PreDigest::SecondaryVRF(secondary)
117 if epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() =>
118 {
119 debug!(
120 target: LOG_TARGET,
121 "Verifying secondary VRF block #{} at slot: {}",
122 header.number(),
123 secondary.slot,
124 );
125
126 check_secondary_vrf_header::<B>(pre_hash, secondary, sig, epoch)?;
127 },
128 _ => return Err(babe_err(Error::SecondarySlotAssignmentsDisabled)),
129 }
130
131 let info = VerifiedHeaderInfo { seal };
132 Ok(CheckedHeader::Checked(header, info))
133}
134
135pub(super) struct VerifiedHeaderInfo {
136 pub(super) seal: DigestItem,
137}
138
139fn check_primary_header<B: BlockT + Sized>(
144 pre_hash: B::Hash,
145 pre_digest: &PrimaryPreDigest,
146 signature: AuthoritySignature,
147 epoch: &Epoch,
148 c: (u64, u64),
149) -> Result<(), Error<B>> {
150 let authority_id = &epoch
151 .authorities
152 .get(pre_digest.authority_index as usize)
153 .ok_or(Error::SlotAuthorNotFound)?
154 .0;
155 let mut epoch_index = epoch.epoch_index;
156
157 if epoch.end_slot() <= pre_digest.slot {
158 epoch_index = epoch.clone_for_slot(pre_digest.slot).epoch_index;
160 }
161
162 if !AuthorityPair::verify(&signature, pre_hash, authority_id) {
163 return Err(babe_err(Error::BadSignature(pre_hash)))
164 }
165
166 let data = make_vrf_sign_data(&epoch.randomness, pre_digest.slot, epoch_index);
167
168 if !authority_id.as_inner_ref().vrf_verify(&data, &pre_digest.vrf_signature) {
169 return Err(babe_err(Error::VrfVerificationFailed))
170 }
171
172 let threshold =
173 calculate_primary_threshold(c, &epoch.authorities, pre_digest.authority_index as usize);
174
175 let score = authority_id
176 .as_inner_ref()
177 .make_bytes::<AUTHORING_SCORE_LENGTH>(
178 AUTHORING_SCORE_VRF_CONTEXT,
179 &data.as_ref(),
180 &pre_digest.vrf_signature.pre_output,
181 )
182 .map(u128::from_le_bytes)
183 .map_err(|_| babe_err(Error::VrfVerificationFailed))?;
184
185 if score >= threshold {
186 return Err(babe_err(Error::VrfThresholdExceeded(threshold)))
187 }
188
189 Ok(())
190}
191
192fn check_secondary_plain_header<B: BlockT>(
197 pre_hash: B::Hash,
198 pre_digest: &SecondaryPlainPreDigest,
199 signature: AuthoritySignature,
200 epoch: &Epoch,
201) -> Result<(), Error<B>> {
202 let expected_author =
204 secondary_slot_author(pre_digest.slot, &epoch.authorities, epoch.randomness)
205 .ok_or(Error::NoSecondaryAuthorExpected)?;
206
207 let author = &epoch
208 .authorities
209 .get(pre_digest.authority_index as usize)
210 .ok_or(Error::SlotAuthorNotFound)?
211 .0;
212
213 if expected_author != author {
214 return Err(Error::InvalidAuthor(expected_author.clone(), author.clone()))
215 }
216
217 if !AuthorityPair::verify(&signature, pre_hash.as_ref(), author) {
218 return Err(Error::BadSignature(pre_hash))
219 }
220
221 Ok(())
222}
223
224fn check_secondary_vrf_header<B: BlockT>(
226 pre_hash: B::Hash,
227 pre_digest: &SecondaryVRFPreDigest,
228 signature: AuthoritySignature,
229 epoch: &Epoch,
230) -> Result<(), Error<B>> {
231 let expected_author =
233 secondary_slot_author(pre_digest.slot, &epoch.authorities, epoch.randomness)
234 .ok_or(Error::NoSecondaryAuthorExpected)?;
235
236 let author = &epoch
237 .authorities
238 .get(pre_digest.authority_index as usize)
239 .ok_or(Error::SlotAuthorNotFound)?
240 .0;
241
242 if expected_author != author {
243 return Err(Error::InvalidAuthor(expected_author.clone(), author.clone()))
244 }
245
246 let mut epoch_index = epoch.epoch_index;
247 if epoch.end_slot() <= pre_digest.slot {
248 epoch_index = epoch.clone_for_slot(pre_digest.slot).epoch_index;
250 }
251
252 if !AuthorityPair::verify(&signature, pre_hash.as_ref(), author) {
253 return Err(Error::BadSignature(pre_hash))
254 }
255
256 let data = make_vrf_sign_data(&epoch.randomness, pre_digest.slot, epoch_index);
257
258 if !author.as_inner_ref().vrf_verify(&data, &pre_digest.vrf_signature) {
259 return Err(Error::VrfVerificationFailed)
260 }
261
262 Ok(())
263}