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 pub fn inner_mut(&mut self) -> &mut BitVec<u8, bitvec::order::Lsb0> {
300 &mut self.0
301 }
302
303 pub fn into_inner(self) -> BitVec<u8, bitvec::order::Lsb0> {
305 self.0
306 }
307 }
308
309 impl AsBitIndex for CandidateIndex {
310 fn as_bit_index(&self) -> BitIndex {
311 BitIndex(*self as usize)
312 }
313 }
314
315 impl AsBitIndex for CoreIndex {
316 fn as_bit_index(&self) -> BitIndex {
317 BitIndex(self.0 as usize)
318 }
319 }
320
321 impl AsBitIndex for usize {
322 fn as_bit_index(&self) -> BitIndex {
323 BitIndex(*self)
324 }
325 }
326
327 impl<T> From<T> for Bitfield<T>
328 where
329 T: AsBitIndex,
330 {
331 fn from(value: T) -> Self {
332 Self(
333 {
334 let mut bv = bitvec::bitvec![u8, Lsb0; 0; value.as_bit_index().0 + 1];
335 bv.set(value.as_bit_index().0, true);
336 bv
337 },
338 Default::default(),
339 )
340 }
341 }
342
343 impl<T> TryFrom<Vec<T>> for Bitfield<T>
344 where
345 T: Into<Bitfield<T>>,
346 {
347 type Error = BitfieldError;
348
349 fn try_from(mut value: Vec<T>) -> Result<Self, Self::Error> {
350 if value.is_empty() {
351 return Err(BitfieldError::NullAssignment)
352 }
353
354 let initial_bitfield =
355 value.pop().expect("Just checked above it's not empty; qed").into();
356
357 Ok(Self(
358 value.into_iter().fold(initial_bitfield.0, |initial_bitfield, element| {
359 let mut bitfield: Bitfield<T> = element.into();
360 bitfield
361 .0
362 .resize(std::cmp::max(initial_bitfield.len(), bitfield.0.len()), false);
363 bitfield.0.bitor(initial_bitfield)
364 }),
365 Default::default(),
366 ))
367 }
368 }
369
370 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
373 pub enum AssignmentCertKindV2 {
374 #[codec(index = 0)]
379 RelayVRFModuloCompact {
380 core_bitfield: CoreBitfield,
382 },
383 #[codec(index = 1)]
388 RelayVRFDelay {
389 core_index: CoreIndex,
391 },
392 #[codec(index = 2)]
398 RelayVRFModulo {
399 sample: u32,
401 },
402 }
403
404 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
406 pub struct AssignmentCertV2 {
407 pub kind: AssignmentCertKindV2,
409 pub vrf: VrfSignature,
411 }
412
413 impl From<super::v1::AssignmentCert> for AssignmentCertV2 {
414 fn from(cert: super::v1::AssignmentCert) -> Self {
415 Self {
416 kind: match cert.kind {
417 super::v1::AssignmentCertKind::RelayVRFDelay { core_index } =>
418 AssignmentCertKindV2::RelayVRFDelay { core_index },
419 super::v1::AssignmentCertKind::RelayVRFModulo { sample } =>
420 AssignmentCertKindV2::RelayVRFModulo { sample },
421 },
422 vrf: cert.vrf,
423 }
424 }
425 }
426
427 #[derive(Debug)]
429 pub enum AssignmentConversionError {
430 CertificateNotSupported,
432 }
433
434 impl TryFrom<AssignmentCertV2> for super::v1::AssignmentCert {
435 type Error = AssignmentConversionError;
436 fn try_from(cert: AssignmentCertV2) -> Result<Self, AssignmentConversionError> {
437 Ok(Self {
438 kind: match cert.kind {
439 AssignmentCertKindV2::RelayVRFDelay { core_index } =>
440 super::v1::AssignmentCertKind::RelayVRFDelay { core_index },
441 AssignmentCertKindV2::RelayVRFModulo { sample } =>
442 super::v1::AssignmentCertKind::RelayVRFModulo { sample },
443 _ => return Err(AssignmentConversionError::CertificateNotSupported),
445 },
446 vrf: cert.vrf,
447 })
448 }
449 }
450
451 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
454 pub struct IndirectAssignmentCertV2 {
455 pub block_hash: Hash,
457 pub validator: ValidatorIndex,
459 pub cert: AssignmentCertV2,
461 }
462
463 impl From<super::v1::IndirectAssignmentCert> for IndirectAssignmentCertV2 {
464 fn from(indirect_cert: super::v1::IndirectAssignmentCert) -> Self {
465 Self {
466 block_hash: indirect_cert.block_hash,
467 validator: indirect_cert.validator,
468 cert: indirect_cert.cert.into(),
469 }
470 }
471 }
472
473 impl TryFrom<IndirectAssignmentCertV2> for super::v1::IndirectAssignmentCert {
474 type Error = AssignmentConversionError;
475 fn try_from(
476 indirect_cert: IndirectAssignmentCertV2,
477 ) -> Result<Self, AssignmentConversionError> {
478 Ok(Self {
479 block_hash: indirect_cert.block_hash,
480 validator: indirect_cert.validator,
481 cert: indirect_cert.cert.try_into()?,
482 })
483 }
484 }
485
486 impl From<super::v1::IndirectSignedApprovalVote> for IndirectSignedApprovalVoteV2 {
487 fn from(value: super::v1::IndirectSignedApprovalVote) -> Self {
488 Self {
489 block_hash: value.block_hash,
490 validator: value.validator,
491 candidate_indices: value.candidate_index.into(),
492 signature: value.signature,
493 }
494 }
495 }
496
497 #[derive(Debug)]
499 pub enum ApprovalConversionError {
500 MoreThanOneCandidate(usize),
502 }
503
504 impl TryFrom<IndirectSignedApprovalVoteV2> for super::v1::IndirectSignedApprovalVote {
505 type Error = ApprovalConversionError;
506
507 fn try_from(value: IndirectSignedApprovalVoteV2) -> Result<Self, Self::Error> {
508 if value.candidate_indices.count_ones() != 1 {
509 return Err(ApprovalConversionError::MoreThanOneCandidate(
510 value.candidate_indices.count_ones(),
511 ))
512 }
513 Ok(Self {
514 block_hash: value.block_hash,
515 validator: value.validator,
516 candidate_index: value.candidate_indices.first_one().expect("Qed we checked above")
517 as u32,
518 signature: value.signature,
519 })
520 }
521 }
522
523 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
528 pub struct IndirectSignedApprovalVoteV2 {
529 pub block_hash: Hash,
531 pub candidate_indices: CandidateBitfield,
533 pub validator: ValidatorIndex,
535 pub signature: ValidatorSignature,
537 }
538}
539
540#[cfg(test)]
541mod test {
542 use super::v2::{BitIndex, Bitfield};
543
544 use polkadot_primitives::{CandidateIndex, CoreIndex};
545
546 #[test]
547 fn test_assignment_bitfield_from_vec() {
548 let candidate_indices = vec![1u32, 7, 3, 10, 45, 8, 200, 2];
549 let max_index = *candidate_indices.iter().max().unwrap();
550 let bitfield = Bitfield::try_from(candidate_indices.clone()).unwrap();
551 let candidate_indices =
552 candidate_indices.into_iter().map(|i| BitIndex(i as usize)).collect::<Vec<_>>();
553
554 for index in candidate_indices.clone() {
556 assert!(bitfield.bit_at(index));
557 }
558
559 for index in 0..max_index {
561 if candidate_indices.contains(&BitIndex(index as usize)) {
562 continue
563 }
564 assert!(!bitfield.bit_at(BitIndex(index as usize)));
565 }
566 }
567
568 #[test]
569 fn test_assignment_bitfield_invariant_msb() {
570 let core_indices = vec![CoreIndex(1), CoreIndex(3), CoreIndex(10), CoreIndex(20)];
571 let mut bitfield = Bitfield::try_from(core_indices.clone()).unwrap();
572 assert!(bitfield.inner_mut().pop().unwrap());
573
574 for i in 0..1024 {
575 assert!(Bitfield::try_from(CoreIndex(i)).unwrap().inner_mut().pop().unwrap());
576 assert!(Bitfield::try_from(i).unwrap().inner_mut().pop().unwrap());
577 }
578 }
579
580 #[test]
581 fn test_assignment_bitfield_basic() {
582 let bitfield = Bitfield::try_from(CoreIndex(0)).unwrap();
583 assert!(bitfield.bit_at(BitIndex(0)));
584 assert!(!bitfield.bit_at(BitIndex(1)));
585 assert_eq!(bitfield.len(), 1);
586
587 let mut bitfield = Bitfield::try_from(20 as CandidateIndex).unwrap();
588 assert!(bitfield.bit_at(BitIndex(20)));
589 assert_eq!(bitfield.inner_mut().count_ones(), 1);
590 assert_eq!(bitfield.len(), 21);
591 }
592}