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	pub attempt: TicketAttempt,
52	/// Ring signature of the ticket `body`.
53	pub signature: TicketSignature,
54}
55
56impl Ord for TicketEnvelope {
57	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
58		self.id().cmp(&other.id())
59	}
60}
61
62impl PartialOrd for TicketEnvelope {
63	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
64		Some(self.cmp(other))
65	}
66}
67
68impl TicketEnvelope {
69	/// Construct [`TicketId`] from [`TicketEnvelope`] signature.
70	pub fn id(&self) -> TicketId {
71		TicketId::from(self.signature.vrf_output())
72	}
73
74	/// Construct [`TicketBody`] from [`TicketEnvelope`] signature.
75	pub fn body(&self) -> TicketBody {
76		TicketBody { id: self.id(), attempt: self.attempt }
77	}
78}
79
80/// A collection of ticket bodies.
81pub type TicketBodies = BoundedVec<TicketBody, EpochPeriod>;