1use std::sync::Arc;
10
11use hotshot_utils::anytrace::*;
12use serde::{Deserialize, Serialize};
13
14use crate::{
15 data::{
16 DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposalWrapper,
17 UpgradeProposal, VidDisperseShare, VidDisperseShare0, ViewNumber,
18 },
19 error::HotShotError,
20 message::{Proposal, convert_proposal},
21 simple_certificate::{
22 CertificatePair, LightClientStateUpdateCertificateV2, QuorumCertificate, QuorumCertificate2,
23 },
24 simple_vote::TimeoutVote2,
25 traits::{ValidatedState, node_implementation::NodeType},
26 vote::HasViewNumber,
27};
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
34#[serde(bound(deserialize = "TYPES: NodeType"))]
35pub struct Event<TYPES: NodeType> {
36 pub view_number: ViewNumber,
38 pub event: EventType<TYPES>,
40}
41
42impl<TYPES: NodeType> Event<TYPES> {
43 pub fn to_legacy(self) -> anyhow::Result<LegacyEvent<TYPES>> {
44 Ok(LegacyEvent {
45 view_number: self.view_number,
46 event: self.event.to_legacy()?,
47 })
48 }
49}
50
51#[derive(Clone, Debug, Serialize, Deserialize)]
53#[serde(bound(deserialize = "TYPES: NodeType"))]
54pub struct LegacyEvent<TYPES: NodeType> {
55 pub view_number: ViewNumber,
57 pub event: LegacyEventType<TYPES>,
59}
60
61#[derive(Clone, Debug, Serialize, Deserialize)]
63#[serde(bound(deserialize = "TYPES: NodeType"))]
64pub struct LeafInfo<TYPES: NodeType> {
65 pub leaf: Leaf2<TYPES>,
67 pub state: Arc<<TYPES as NodeType>::ValidatedState>,
69 pub delta: Option<Arc<<<TYPES as NodeType>::ValidatedState as ValidatedState<TYPES>>::Delta>>,
71 pub vid_share: Option<VidDisperseShare<TYPES>>,
73 pub state_cert: Option<LightClientStateUpdateCertificateV2<TYPES>>,
75}
76
77impl<TYPES: NodeType> LeafInfo<TYPES> {
78 pub fn new(
80 leaf: Leaf2<TYPES>,
81 state: Arc<<TYPES as NodeType>::ValidatedState>,
82 delta: Option<Arc<<<TYPES as NodeType>::ValidatedState as ValidatedState<TYPES>>::Delta>>,
83 vid_share: Option<VidDisperseShare<TYPES>>,
84 state_cert: Option<LightClientStateUpdateCertificateV2<TYPES>>,
85 ) -> Self {
86 Self {
87 leaf,
88 state,
89 delta,
90 vid_share,
91 state_cert,
92 }
93 }
94
95 pub fn to_legacy_unsafe(self) -> anyhow::Result<LegacyLeafInfo<TYPES>> {
96 Ok(LegacyLeafInfo {
97 leaf: self.leaf.to_leaf_unsafe(),
98 state: self.state,
99 delta: self.delta,
100 vid_share: self
101 .vid_share
102 .map(|share| match share {
103 VidDisperseShare::V0(share) => Ok(share),
104 _ => Err(error!("VID share is post-epoch")),
105 })
106 .transpose()?,
107 })
108 }
109}
110
111#[derive(Clone, Debug, Serialize, Deserialize)]
113#[serde(bound(deserialize = "TYPES: NodeType"))]
114pub struct LegacyLeafInfo<TYPES: NodeType> {
115 pub leaf: Leaf<TYPES>,
117 pub state: Arc<<TYPES as NodeType>::ValidatedState>,
119 pub delta: Option<Arc<<<TYPES as NodeType>::ValidatedState as ValidatedState<TYPES>>::Delta>>,
121 pub vid_share: Option<VidDisperseShare0<TYPES>>,
123}
124
125impl<TYPES: NodeType> LegacyLeafInfo<TYPES> {
126 pub fn new(
128 leaf: Leaf<TYPES>,
129 state: Arc<<TYPES as NodeType>::ValidatedState>,
130 delta: Option<Arc<<<TYPES as NodeType>::ValidatedState as ValidatedState<TYPES>>::Delta>>,
131 vid_share: Option<VidDisperseShare0<TYPES>>,
132 ) -> Self {
133 Self {
134 leaf,
135 state,
136 delta,
137 vid_share,
138 }
139 }
140}
141
142pub type LeafChain<TYPES> = Vec<LeafInfo<TYPES>>;
144
145pub type LegacyLeafChain<TYPES> = Vec<LegacyLeafInfo<TYPES>>;
147
148pub mod error_adaptor {
150 use serde::{de::Deserializer, ser::Serializer};
151
152 use super::{Arc, Deserialize, HotShotError, NodeType};
153
154 pub fn serialize<S: Serializer, TYPES: NodeType>(
159 elem: &Arc<HotShotError<TYPES>>,
160 serializer: S,
161 ) -> Result<S::Ok, S::Error> {
162 serializer.serialize_str(&format!("{elem}"))
163 }
164
165 pub fn deserialize<'de, D: Deserializer<'de>, TYPES: NodeType>(
170 deserializer: D,
171 ) -> Result<Arc<HotShotError<TYPES>>, D::Error> {
172 let str = String::deserialize(deserializer)?;
173 Ok(Arc::new(HotShotError::FailedToDeserialize(str)))
174 }
175}
176
177#[non_exhaustive]
182#[derive(Clone, Debug, Serialize, Deserialize)]
183#[serde(bound(deserialize = "TYPES: NodeType"))]
184#[allow(clippy::large_enum_variant)]
185pub enum EventType<TYPES: NodeType> {
186 Error {
188 #[serde(with = "error_adaptor")]
190 error: Arc<HotShotError<TYPES>>,
191 },
192 Decide {
194 leaf_chain: Arc<LeafChain<TYPES>>,
202 committing_qc: Arc<CertificatePair<TYPES>>,
207 deciding_qc: Option<Arc<CertificatePair<TYPES>>>,
212 block_size: Option<u64>,
214 },
215 ReplicaViewTimeout {
217 view_number: ViewNumber,
219 },
220 ViewFinished {
222 view_number: ViewNumber,
224 },
225 ViewTimeout {
227 view_number: ViewNumber,
229 },
230 Transactions {
233 transactions: Vec<TYPES::Transaction>,
235 },
236 DaProposal {
239 proposal: Proposal<TYPES, DaProposal2<TYPES>>,
241 sender: TYPES::SignatureKey,
243 },
244 QuorumProposal {
247 proposal: Proposal<TYPES, QuorumProposalWrapper<TYPES>>,
249 sender: TYPES::SignatureKey,
251 },
252 UpgradeProposal {
255 proposal: Proposal<TYPES, UpgradeProposal>,
257 sender: TYPES::SignatureKey,
259 },
260
261 ExternalMessageReceived {
263 sender: TYPES::SignatureKey,
265 data: Vec<u8>,
267 },
268
269 LegacyTimeoutVoteEmitted {
276 vote: TimeoutVote2<TYPES>,
278 },
279
280 LegacyHighQcFormed {
285 qc: QuorumCertificate2<TYPES>,
287 },
288}
289
290impl<TYPES: NodeType> std::fmt::Display for Event<TYPES> {
291 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
292 write!(f, "{} (view {})", self.event, self.view_number)
293 }
294}
295
296impl<TYPES: NodeType> std::fmt::Display for EventType<TYPES> {
297 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298 match self {
299 Self::Error { error } => write!(f, "Error: {error}"),
300 Self::Decide { leaf_chain, .. } => {
301 let newest = leaf_chain.first().map(|l| l.leaf.view_number());
302 let oldest = leaf_chain.last().map(|l| l.leaf.view_number());
303 write!(
304 f,
305 "Decide: leaves={} oldest={:?} newest={:?}",
306 leaf_chain.len(),
307 oldest,
308 newest,
309 )
310 },
311 Self::ReplicaViewTimeout { view_number } => {
312 write!(f, "ReplicaViewTimeout: view={view_number}")
313 },
314 Self::ViewFinished { view_number } => {
315 write!(f, "ViewFinished: view={view_number}")
316 },
317 Self::ViewTimeout { view_number } => {
318 write!(f, "ViewTimeout: view={view_number}")
319 },
320 Self::Transactions { transactions } => {
321 write!(f, "Transactions: count={}", transactions.len())
322 },
323 Self::DaProposal { proposal, .. } => {
324 write!(f, "DaProposal: view={}", proposal.data.view_number())
325 },
326 Self::QuorumProposal { proposal, .. } => {
327 write!(f, "QuorumProposal: view={}", proposal.data.view_number())
328 },
329 Self::UpgradeProposal { proposal, .. } => {
330 write!(
331 f,
332 "UpgradeProposal: view={} old_version={} new_version={}",
333 proposal.data.view_number,
334 proposal.data.upgrade_proposal.old_version,
335 proposal.data.upgrade_proposal.new_version,
336 )
337 },
338 Self::ExternalMessageReceived { .. } => {
339 write!(f, "ExternalMessageReceived")
340 },
341 Self::LegacyTimeoutVoteEmitted { vote } => {
342 write!(f, "LegacyTimeoutVoteEmitted: view={}", vote.view_number())
343 },
344 Self::LegacyHighQcFormed { qc } => {
345 write!(f, "LegacyHighQcFormed: view={}", qc.view_number())
346 },
347 }
348 }
349}
350
351impl<TYPES: NodeType> EventType<TYPES> {
352 pub fn to_legacy(self) -> anyhow::Result<LegacyEventType<TYPES>> {
353 Ok(match self {
354 EventType::Error { error } => LegacyEventType::Error { error },
355 EventType::Decide {
356 leaf_chain,
357 committing_qc: qc,
358 block_size,
359 ..
360 } => LegacyEventType::Decide {
361 leaf_chain: Arc::new(
362 leaf_chain
363 .iter()
364 .cloned()
365 .map(LeafInfo::to_legacy_unsafe)
366 .collect::<anyhow::Result<_, _>>()?,
367 ),
368 qc: Arc::new(qc.qc().clone().to_qc()),
369 block_size,
370 },
371 EventType::ReplicaViewTimeout { view_number } => {
372 LegacyEventType::ReplicaViewTimeout { view_number }
373 },
374 EventType::ViewFinished { view_number } => {
375 LegacyEventType::ViewFinished { view_number }
376 },
377 EventType::ViewTimeout { view_number } => LegacyEventType::ViewTimeout { view_number },
378 EventType::Transactions { transactions } => {
379 LegacyEventType::Transactions { transactions }
380 },
381 EventType::DaProposal { proposal, sender } => LegacyEventType::DaProposal {
382 proposal: convert_proposal(proposal),
383 sender,
384 },
385 EventType::QuorumProposal { proposal, sender } => LegacyEventType::QuorumProposal {
386 proposal: convert_proposal(proposal),
387 sender,
388 },
389 EventType::UpgradeProposal { proposal, sender } => {
390 LegacyEventType::UpgradeProposal { proposal, sender }
391 },
392 EventType::ExternalMessageReceived { sender, data } => {
393 LegacyEventType::ExternalMessageReceived { sender, data }
394 },
395 EventType::LegacyTimeoutVoteEmitted { .. } => {
399 anyhow::bail!(
400 "LegacyTimeoutVoteEmitted is upgrade-bridging only and has no legacy \
401 equivalent"
402 )
403 },
404 EventType::LegacyHighQcFormed { .. } => {
405 anyhow::bail!(
406 "LegacyHighQcFormed is upgrade-bridging only and has no legacy equivalent"
407 )
408 },
409 })
410 }
411}
412
413#[non_exhaustive]
415#[derive(Clone, Debug, Serialize, Deserialize)]
416#[serde(bound(deserialize = "TYPES: NodeType"))]
417#[allow(clippy::large_enum_variant)]
418pub enum LegacyEventType<TYPES: NodeType> {
419 Error {
421 #[serde(with = "error_adaptor")]
423 error: Arc<HotShotError<TYPES>>,
424 },
425 Decide {
427 leaf_chain: Arc<LegacyLeafChain<TYPES>>,
435 qc: Arc<QuorumCertificate<TYPES>>,
440 block_size: Option<u64>,
442 },
443 ReplicaViewTimeout {
445 view_number: ViewNumber,
447 },
448 ViewFinished {
450 view_number: ViewNumber,
452 },
453 ViewTimeout {
455 view_number: ViewNumber,
457 },
458 Transactions {
461 transactions: Vec<TYPES::Transaction>,
463 },
464 DaProposal {
467 proposal: Proposal<TYPES, DaProposal<TYPES>>,
469 sender: TYPES::SignatureKey,
471 },
472 QuorumProposal {
475 proposal: Proposal<TYPES, QuorumProposal<TYPES>>,
477 sender: TYPES::SignatureKey,
479 },
480 UpgradeProposal {
483 proposal: Proposal<TYPES, UpgradeProposal>,
485 sender: TYPES::SignatureKey,
487 },
488
489 ExternalMessageReceived {
491 sender: TYPES::SignatureKey,
493 data: Vec<u8>,
495 },
496}
497
498#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
499pub enum HotShotAction {
501 Vote,
503 TimeoutVote,
505 ViewSyncVote,
507 Propose,
509 DaPropose,
511 DaVote,
513 DaCert,
515 VidDisperse,
517 UpgradeVote,
519 UpgradePropose,
521}