1pub mod criteria;
21
22pub mod time;
24
25pub mod v1 {
27 use sp_consensus_babe as babe_primitives;
28 pub use sp_consensus_babe::{
29 Randomness, Slot, VrfPreOutput, VrfProof, VrfSignature, VrfTranscript,
30 };
31
32 use codec::{Decode, Encode};
33 use polkadot_primitives::{
34 BlockNumber, CandidateHash, CandidateIndex, CoreIndex, GroupIndex, Hash, Header,
35 SessionIndex, ValidatorIndex, ValidatorSignature,
36 };
37 use sp_application_crypto::ByteArray;
38
39 pub type DelayTranche = u32;
42
43 pub const RELAY_VRF_STORY_CONTEXT: &[u8] = b"A&V RC-VRF";
46
47 pub const RELAY_VRF_MODULO_CONTEXT: &[u8] = b"A&V MOD";
49
50 pub const RELAY_VRF_DELAY_CONTEXT: &[u8] = b"A&V DELAY";
52
53 pub const ASSIGNED_CORE_CONTEXT: &[u8] = b"A&V ASSIGNED";
55
56 pub const CORE_RANDOMNESS_CONTEXT: &[u8] = b"A&V CORE";
58
59 pub const TRANCHE_RANDOMNESS_CONTEXT: &[u8] = b"A&V TRANCHE";
61
62 #[derive(Debug, Clone, Encode, Decode, PartialEq)]
65 pub struct RelayVRFStory(pub [u8; 32]);
66
67 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
70 pub enum AssignmentCertKind {
71 RelayVRFModulo {
76 sample: u32,
78 },
79 RelayVRFDelay {
84 core_index: CoreIndex,
86 },
87 }
88
89 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
91 pub struct AssignmentCert {
92 pub kind: AssignmentCertKind,
94 pub vrf: VrfSignature,
96 }
97
98 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
101 pub struct IndirectAssignmentCert {
102 pub block_hash: Hash,
104 pub validator: ValidatorIndex,
106 pub cert: AssignmentCert,
108 }
109
110 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
115 pub struct IndirectSignedApprovalVote {
116 pub block_hash: Hash,
118 pub candidate_index: CandidateIndex,
120 pub validator: ValidatorIndex,
122 pub signature: ValidatorSignature,
124 }
125
126 #[derive(Debug, Clone)]
128 pub struct BlockApprovalMeta {
129 pub hash: Hash,
131 pub number: BlockNumber,
133 pub parent_hash: Hash,
135 pub candidates: Vec<(CandidateHash, CoreIndex, GroupIndex)>,
138 pub slot: Slot,
140 pub session: SessionIndex,
142 pub vrf_story: RelayVRFStory,
144 }
145
146 #[derive(Debug, thiserror::Error)]
148 #[allow(missing_docs)]
149 pub enum ApprovalError {
150 #[error("Schnorrkel signature error")]
151 SchnorrkelSignature(schnorrkel::errors::SignatureError),
152 #[error("Authority index {0} out of bounds")]
153 AuthorityOutOfBounds(usize),
154 }
155
156 pub struct UnsafeVRFPreOutput {
158 vrf_pre_output: VrfPreOutput,
159 slot: Slot,
160 authority_index: u32,
161 }
162
163 impl UnsafeVRFPreOutput {
164 pub fn slot(&self) -> Slot {
166 self.slot
167 }
168
169 pub fn compute_randomness(
171 self,
172 authorities: &[(babe_primitives::AuthorityId, babe_primitives::BabeAuthorityWeight)],
173 randomness: &babe_primitives::Randomness,
174 epoch_index: u64,
175 ) -> Result<RelayVRFStory, ApprovalError> {
176 let author = match authorities.get(self.authority_index as usize) {
177 None => return Err(ApprovalError::AuthorityOutOfBounds(self.authority_index as _)),
178 Some(x) => &x.0,
179 };
180
181 let pubkey = schnorrkel::PublicKey::from_bytes(author.as_slice())
182 .map_err(ApprovalError::SchnorrkelSignature)?;
183
184 let transcript =
185 sp_consensus_babe::make_vrf_transcript(randomness, self.slot, epoch_index);
186
187 let inout = self
188 .vrf_pre_output
189 .0
190 .attach_input_hash(&pubkey, transcript.0)
191 .map_err(ApprovalError::SchnorrkelSignature)?;
192 Ok(RelayVRFStory(inout.make_bytes(super::v1::RELAY_VRF_STORY_CONTEXT)))
193 }
194 }
195
196 pub fn babe_unsafe_vrf_info(header: &Header) -> Option<UnsafeVRFPreOutput> {
202 use babe_primitives::digests::CompatibleDigestItem;
203
204 for digest in &header.digest.logs {
205 if let Some(pre) = digest.as_babe_pre_digest() {
206 let slot = pre.slot();
207 let authority_index = pre.authority_index();
208
209 return pre.vrf_signature().map(|sig| UnsafeVRFPreOutput {
210 vrf_pre_output: sig.pre_output.clone(),
211 slot,
212 authority_index,
213 })
214 }
215 }
216
217 None
218 }
219}
220
221pub mod v2 {
223 use codec::{Decode, Encode};
224 pub use sp_consensus_babe::{
225 Randomness, Slot, VrfPreOutput, VrfProof, VrfSignature, VrfTranscript,
226 };
227 use std::ops::BitOr;
228
229 use bitvec::{prelude::Lsb0, vec::BitVec};
230 use polkadot_primitives::{
231 CandidateIndex, CoreIndex, Hash, ValidatorIndex, ValidatorSignature,
232 };
233
234 pub const CORE_RANDOMNESS_CONTEXT: &[u8] = b"A&V CORE v2";
236 pub const ASSIGNED_CORE_CONTEXT: &[u8] = b"A&V ASSIGNED v2";
238 pub const RELAY_VRF_MODULO_CONTEXT: &[u8] = b"A&V MOD v2";
240 #[derive(Clone, Debug, Encode, Decode, Hash, PartialEq, Eq)]
242 pub struct Bitfield<T>(BitVec<u8, bitvec::order::Lsb0>, std::marker::PhantomData<T>);
243
244 pub type CandidateBitfield = Bitfield<CandidateIndex>;
247 pub type CoreBitfield = Bitfield<CoreIndex>;
249
250 #[derive(Debug)]
252 pub enum BitfieldError {
253 NullAssignment,
255 }
256
257 #[cfg_attr(test, derive(PartialEq, Clone))]
259 pub struct BitIndex(pub usize);
260
261 pub trait AsBitIndex {
263 fn as_bit_index(&self) -> BitIndex;
265 }
266
267 impl<T> Bitfield<T> {
268 pub fn bit_at(&self, index: BitIndex) -> bool {
271 if self.0.len() <= index.0 {
272 false
273 } else {
274 self.0[index.0]
275 }
276 }
277
278 pub fn len(&self) -> usize {
280 self.0.len()
281 }
282
283 pub fn count_ones(&self) -> usize {
285 self.0.count_ones()
286 }
287
288 pub fn first_one(&self) -> Option<usize> {
290 self.0.first_one()
291 }
292
293 pub fn iter_ones(&self) -> bitvec::slice::IterOnes<u8, bitvec::order::Lsb0> {
295 self.0.iter_ones()
296 }
297
298 #[cfg(test)]
300 pub fn inner_mut(&mut self) -> &mut BitVec<u8, bitvec::order::Lsb0> {
301 &mut self.0
302 }
303
304 pub fn into_inner(self) -> BitVec<u8, bitvec::order::Lsb0> {
306 self.0
307 }
308 }
309
310 impl AsBitIndex for CandidateIndex {
311 fn as_bit_index(&self) -> BitIndex {
312 BitIndex(*self as usize)
313 }
314 }
315
316 impl AsBitIndex for CoreIndex {
317 fn as_bit_index(&self) -> BitIndex {
318 BitIndex(self.0 as usize)
319 }
320 }
321
322 impl AsBitIndex for usize {
323 fn as_bit_index(&self) -> BitIndex {
324 BitIndex(*self)
325 }
326 }
327
328 impl<T> From<T> for Bitfield<T>
329 where
330 T: AsBitIndex,
331 {
332 fn from(value: T) -> Self {
333 Self(
334 {
335 let mut bv = bitvec::bitvec![u8, Lsb0; 0; value.as_bit_index().0 + 1];
336 bv.set(value.as_bit_index().0, true);
337 bv
338 },
339 Default::default(),
340 )
341 }
342 }
343
344 impl<T> TryFrom<Vec<T>> for Bitfield<T>
345 where
346 T: Into<Bitfield<T>>,
347 {
348 type Error = BitfieldError;
349
350 fn try_from(mut value: Vec<T>) -> Result<Self, Self::Error> {
351 if value.is_empty() {
352 return Err(BitfieldError::NullAssignment)
353 }
354
355 let initial_bitfield =
356 value.pop().expect("Just checked above it's not empty; qed").into();
357
358 Ok(Self(
359 value.into_iter().fold(initial_bitfield.0, |initial_bitfield, element| {
360 let mut bitfield: Bitfield<T> = element.into();
361 bitfield
362 .0
363 .resize(std::cmp::max(initial_bitfield.len(), bitfield.0.len()), false);
364 bitfield.0.bitor(initial_bitfield)
365 }),
366 Default::default(),
367 ))
368 }
369 }
370
371 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
374 pub enum AssignmentCertKindV2 {
375 #[codec(index = 0)]
380 RelayVRFModuloCompact {
381 core_bitfield: CoreBitfield,
383 },
384 #[codec(index = 1)]
389 RelayVRFDelay {
390 core_index: CoreIndex,
392 },
393 #[codec(index = 2)]
399 RelayVRFModulo {
400 sample: u32,
402 },
403 }
404
405 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
407 pub struct AssignmentCertV2 {
408 pub kind: AssignmentCertKindV2,
410 pub vrf: VrfSignature,
412 }
413
414 impl From<super::v1::AssignmentCert> for AssignmentCertV2 {
415 fn from(cert: super::v1::AssignmentCert) -> Self {
416 Self {
417 kind: match cert.kind {
418 super::v1::AssignmentCertKind::RelayVRFDelay { core_index } =>
419 AssignmentCertKindV2::RelayVRFDelay { core_index },
420 super::v1::AssignmentCertKind::RelayVRFModulo { sample } =>
421 AssignmentCertKindV2::RelayVRFModulo { sample },
422 },
423 vrf: cert.vrf,
424 }
425 }
426 }
427
428 #[derive(Debug)]
430 pub enum AssignmentConversionError {
431 CertificateNotSupported,
433 }
434
435 impl TryFrom<AssignmentCertV2> for super::v1::AssignmentCert {
436 type Error = AssignmentConversionError;
437 fn try_from(cert: AssignmentCertV2) -> Result<Self, AssignmentConversionError> {
438 Ok(Self {
439 kind: match cert.kind {
440 AssignmentCertKindV2::RelayVRFDelay { core_index } =>
441 super::v1::AssignmentCertKind::RelayVRFDelay { core_index },
442 AssignmentCertKindV2::RelayVRFModulo { sample } =>
443 super::v1::AssignmentCertKind::RelayVRFModulo { sample },
444 _ => return Err(AssignmentConversionError::CertificateNotSupported),
446 },
447 vrf: cert.vrf,
448 })
449 }
450 }
451
452 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
455 pub struct IndirectAssignmentCertV2 {
456 pub block_hash: Hash,
458 pub validator: ValidatorIndex,
460 pub cert: AssignmentCertV2,
462 }
463
464 impl From<super::v1::IndirectAssignmentCert> for IndirectAssignmentCertV2 {
465 fn from(indirect_cert: super::v1::IndirectAssignmentCert) -> Self {
466 Self {
467 block_hash: indirect_cert.block_hash,
468 validator: indirect_cert.validator,
469 cert: indirect_cert.cert.into(),
470 }
471 }
472 }
473
474 impl TryFrom<IndirectAssignmentCertV2> for super::v1::IndirectAssignmentCert {
475 type Error = AssignmentConversionError;
476 fn try_from(
477 indirect_cert: IndirectAssignmentCertV2,
478 ) -> Result<Self, AssignmentConversionError> {
479 Ok(Self {
480 block_hash: indirect_cert.block_hash,
481 validator: indirect_cert.validator,
482 cert: indirect_cert.cert.try_into()?,
483 })
484 }
485 }
486
487 impl From<super::v1::IndirectSignedApprovalVote> for IndirectSignedApprovalVoteV2 {
488 fn from(value: super::v1::IndirectSignedApprovalVote) -> Self {
489 Self {
490 block_hash: value.block_hash,
491 validator: value.validator,
492 candidate_indices: value.candidate_index.into(),
493 signature: value.signature,
494 }
495 }
496 }
497
498 #[derive(Debug)]
500 pub enum ApprovalConversionError {
501 MoreThanOneCandidate(usize),
503 }
504
505 impl TryFrom<IndirectSignedApprovalVoteV2> for super::v1::IndirectSignedApprovalVote {
506 type Error = ApprovalConversionError;
507
508 fn try_from(value: IndirectSignedApprovalVoteV2) -> Result<Self, Self::Error> {
509 if value.candidate_indices.count_ones() != 1 {
510 return Err(ApprovalConversionError::MoreThanOneCandidate(
511 value.candidate_indices.count_ones(),
512 ))
513 }
514 Ok(Self {
515 block_hash: value.block_hash,
516 validator: value.validator,
517 candidate_index: value.candidate_indices.first_one().expect("Qed we checked above")
518 as u32,
519 signature: value.signature,
520 })
521 }
522 }
523
524 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
529 pub struct IndirectSignedApprovalVoteV2 {
530 pub block_hash: Hash,
532 pub candidate_indices: CandidateBitfield,
534 pub validator: ValidatorIndex,
536 pub signature: ValidatorSignature,
538 }
539}
540
541#[cfg(test)]
542mod test {
543 use super::v2::{BitIndex, Bitfield};
544
545 use polkadot_primitives::{CandidateIndex, CoreIndex};
546
547 #[test]
548 fn test_assignment_bitfield_from_vec() {
549 let candidate_indices = vec![1u32, 7, 3, 10, 45, 8, 200, 2];
550 let max_index = *candidate_indices.iter().max().unwrap();
551 let bitfield = Bitfield::try_from(candidate_indices.clone()).unwrap();
552 let candidate_indices =
553 candidate_indices.into_iter().map(|i| BitIndex(i as usize)).collect::<Vec<_>>();
554
555 for index in candidate_indices.clone() {
557 assert!(bitfield.bit_at(index));
558 }
559
560 for index in 0..max_index {
562 if candidate_indices.contains(&BitIndex(index as usize)) {
563 continue
564 }
565 assert!(!bitfield.bit_at(BitIndex(index as usize)));
566 }
567 }
568
569 #[test]
570 fn test_assignment_bitfield_invariant_msb() {
571 let core_indices = vec![CoreIndex(1), CoreIndex(3), CoreIndex(10), CoreIndex(20)];
572 let mut bitfield = Bitfield::try_from(core_indices.clone()).unwrap();
573 assert!(bitfield.inner_mut().pop().unwrap());
574
575 for i in 0..1024 {
576 assert!(Bitfield::try_from(CoreIndex(i)).unwrap().inner_mut().pop().unwrap());
577 assert!(Bitfield::try_from(i).unwrap().inner_mut().pop().unwrap());
578 }
579 }
580
581 #[test]
582 fn test_assignment_bitfield_basic() {
583 let bitfield = Bitfield::try_from(CoreIndex(0)).unwrap();
584 assert!(bitfield.bit_at(BitIndex(0)));
585 assert!(!bitfield.bit_at(BitIndex(1)));
586 assert_eq!(bitfield.len(), 1);
587
588 let mut bitfield = Bitfield::try_from(20 as CandidateIndex).unwrap();
589 assert!(bitfield.bit_at(BitIndex(20)));
590 assert_eq!(bitfield.inner_mut().count_ones(), 1);
591 assert_eq!(bitfield.len(), 21);
592 }
593}