Skip to main content

jam_std_common/safrole/
ticket.rs

1//! Types related to tickets.
2
3use crate::{bandersnatch::ring_vrf, Entropy};
4use bounded_collections::BoundedVec;
5use codec::{Decode, Encode, MaxEncodedLen};
6use jam_types::{opaque, EpochPeriod, TicketAttempt};
7
8// Ticket identifier.
9//
10// Output of a VRF whose inputs cannot be controlled by the
11// ticket's creator (refer to [`super::vrf::ticket_id_input`] parameters).
12//
13// The value is used as the ticket score to decide if the ticket is worth being considered.
14opaque! { pub struct TicketId(pub [u8; 32]); }
15
16impl TicketId {
17	pub fn from(entropy: Entropy) -> TicketId {
18		TicketId(*entropy)
19	}
20}
21
22/// Ticket data on-chain.
23#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
24pub struct TicketBody {
25	/// Ticket identifier
26	pub id: TicketId,
27	/// Attempt index.
28	#[codec(compact)]
29	pub attempt: TicketAttempt,
30}
31
32impl Ord for TicketBody {
33	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
34		self.id.cmp(&other.id)
35	}
36}
37
38impl PartialOrd for TicketBody {
39	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
40		Some(self.cmp(other))
41	}
42}
43
44/// Ticket ring vrf signature.
45pub type TicketSignature = ring_vrf::Signature;
46
47/// Ticket envelope used during submission.
48#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
49pub struct TicketEnvelope {
50	/// Ticket attempt.
51	#[codec(compact)]
52	pub attempt: TicketAttempt,
53	/// Ring signature of the ticket `body`.
54	pub signature: TicketSignature,
55}
56
57impl Ord for TicketEnvelope {
58	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
59		self.id().cmp(&other.id())
60	}
61}
62
63impl PartialOrd for TicketEnvelope {
64	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
65		Some(self.cmp(other))
66	}
67}
68
69impl TicketEnvelope {
70	/// Construct [`TicketId`] from [`TicketEnvelope`] signature.
71	pub fn id(&self) -> TicketId {
72		TicketId::from(self.signature.vrf_output())
73	}
74
75	/// Construct [`TicketBody`] from [`TicketEnvelope`] signature.
76	pub fn body(&self) -> TicketBody {
77		TicketBody { id: self.id(), attempt: self.attempt }
78	}
79}
80
81/// A collection of ticket bodies.
82pub type TicketBodies = BoundedVec<TicketBody, EpochPeriod>;