penumbra_sdk_sct/
event.rs

1use anyhow::{anyhow, Context as _};
2use pbjson_types::Timestamp;
3use penumbra_sdk_tct as tct;
4use tct::builder::{block, epoch};
5
6use penumbra_sdk_proto::{
7    core::component::sct::v1::{self as pb},
8    DomainType, Name as _,
9};
10
11use crate::CommitmentSource;
12
13pub fn anchor(height: u64, anchor: tct::Root, timestamp: i64) -> pb::EventAnchor {
14    pb::EventAnchor {
15        height,
16        anchor: Some(anchor.into()),
17        timestamp: Some(Timestamp {
18            seconds: timestamp,
19            nanos: 0,
20        }),
21    }
22}
23
24#[derive(Debug, Clone)]
25pub struct EventBlockRoot {
26    pub height: u64,
27    pub root: block::Root,
28    pub timestamp_seconds: i64,
29}
30
31impl TryFrom<pb::EventBlockRoot> for EventBlockRoot {
32    type Error = anyhow::Error;
33
34    fn try_from(value: pb::EventBlockRoot) -> Result<Self, Self::Error> {
35        fn inner(value: pb::EventBlockRoot) -> anyhow::Result<EventBlockRoot> {
36            Ok(EventBlockRoot {
37                height: value.height,
38                root: value.root.ok_or(anyhow!("missing `root`"))?.try_into()?,
39                timestamp_seconds: value
40                    .timestamp
41                    .ok_or(anyhow!("missing `timestamp`"))?
42                    .seconds,
43            })
44        }
45        inner(value).context(format!("parsing {}", pb::EventBlockRoot::NAME))
46    }
47}
48
49impl From<EventBlockRoot> for pb::EventBlockRoot {
50    fn from(value: EventBlockRoot) -> Self {
51        Self {
52            height: value.height,
53            root: Some(value.root.into()),
54            timestamp: Some(Timestamp {
55                seconds: value.timestamp_seconds,
56                nanos: 0,
57            }),
58        }
59    }
60}
61
62impl DomainType for EventBlockRoot {
63    type Proto = pb::EventBlockRoot;
64}
65
66#[derive(Debug, Clone)]
67pub struct EventEpochRoot {
68    pub index: u64,
69    pub root: epoch::Root,
70    pub timestamp_seconds: i64,
71}
72
73impl From<EventEpochRoot> for pb::EventEpochRoot {
74    fn from(value: EventEpochRoot) -> Self {
75        pb::EventEpochRoot {
76            index: value.index,
77            root: Some(value.root.into()),
78            timestamp: Some(Timestamp {
79                seconds: value.timestamp_seconds,
80                nanos: 0,
81            }),
82        }
83    }
84}
85
86impl TryFrom<pb::EventEpochRoot> for EventEpochRoot {
87    type Error = anyhow::Error;
88
89    fn try_from(value: pb::EventEpochRoot) -> Result<Self, Self::Error> {
90        fn inner(value: pb::EventEpochRoot) -> anyhow::Result<EventEpochRoot> {
91            Ok(EventEpochRoot {
92                index: value.index,
93                root: value.root.ok_or(anyhow!("missing `root`"))?.try_into()?,
94                timestamp_seconds: value
95                    .timestamp
96                    .ok_or(anyhow!("missing `timestamp`"))?
97                    .seconds,
98            })
99        }
100        inner(value).context(format!("parsing {}", pb::EventEpochRoot::NAME))
101    }
102}
103
104impl DomainType for EventEpochRoot {
105    type Proto = pb::EventEpochRoot;
106}
107
108pub fn commitment(
109    commitment: tct::StateCommitment,
110    position: tct::Position,
111    source: CommitmentSource,
112) -> pb::EventCommitment {
113    pb::EventCommitment {
114        commitment: Some(commitment.into()),
115        position: position.into(),
116        source: Some(source.into()),
117    }
118}