tempo_commonware_node/
utils.rs1use std::{
2 future::Future,
3 ops::{Deref, DerefMut},
4 pin::Pin,
5 task::{Poll, ready},
6};
7
8use alloy_primitives::B256;
9use commonware_cryptography::ed25519::PublicKey;
10use futures::future::FusedFuture;
11use pin_project::pin_project;
12
13pub(crate) fn public_key_to_b256(key: &PublicKey) -> B256 {
14 key.as_ref()
15 .try_into()
16 .expect("ed25519 pub keys always map to B256")
17}
18
19pub(crate) fn public_key_to_tempo_primitive(
20 key: &PublicKey,
21) -> tempo_primitives::ed25519::PublicKey {
22 tempo_primitives::ed25519::PublicKey::try_from(B256::from_slice(key.as_ref()))
23 .expect("shared implementation of ed25519 pub keys")
24}
25
26#[pin_project]
35pub(crate) struct OptionFuture<F>(#[pin] Option<F>);
36
37impl<F> OptionFuture<F> {
38 pub(crate) fn new(maybe_fut: Option<F>) -> Self {
39 Self(maybe_fut)
40 }
41
42 pub(crate) fn none() -> Self {
43 Self::new(None)
44 }
45
46 pub(crate) fn some(fut: F) -> Self {
47 Self::new(Some(fut))
48 }
49
50 pub(crate) fn is_none(&self) -> bool {
51 self.0.is_none()
52 }
53
54 pub(crate) fn replace(&mut self, fut: F) -> Option<F> {
55 self.0.replace(fut)
56 }
57}
58
59impl<F: Future> Default for OptionFuture<F> {
60 fn default() -> Self {
61 Self::none()
62 }
63}
64
65impl<F: Future> From<Option<F>> for OptionFuture<F> {
66 fn from(opt: Option<F>) -> Self {
67 Self::new(opt)
68 }
69}
70
71impl<F: Future> Deref for OptionFuture<F> {
72 type Target = Option<F>;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79impl<F: Future> DerefMut for OptionFuture<F> {
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 &mut self.0
82 }
83}
84
85impl<F: Future> Future for OptionFuture<F> {
86 type Output = F::Output;
87
88 fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
89 let output = match self.as_mut().project().0.as_pin_mut() {
90 Some(fut) => ready!(fut.poll(cx)),
91 None => return Poll::Pending,
92 };
93 self.as_mut().project().0.set(None);
94 Poll::Ready(output)
95 }
96}
97
98impl<F: Future> FusedFuture for OptionFuture<F> {
99 fn is_terminated(&self) -> bool {
100 self.0.is_none()
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use std::task::Poll;
107
108 use commonware_cryptography::ed25519::PublicKey as CommonwarePublicKey;
109 use futures::{channel::oneshot, executor::block_on, pin_mut};
110 use tempo_primitives::ed25519::PublicKey as TempoPublicKey;
111
112 use crate::utils::{OptionFuture, public_key_to_tempo_primitive};
113
114 #[test]
115 fn commonware_public_key_to_tempo_primitive_conversion() {
116 let tempo_key = TempoPublicKey::from_seed([42u8; 32]);
117 let cw_key = CommonwarePublicKey::from(tempo_key.get());
118 assert_eq!(public_key_to_tempo_primitive(&cw_key), tempo_key);
119 assert_eq!(tempo_key.get().to_bytes(), cw_key.as_ref());
120 }
121
122 #[test]
123 fn option_future() {
124 block_on(async {
125 let option_future = OptionFuture::<oneshot::Receiver<()>>::from(None);
126 pin_mut!(option_future);
127
128 let waker = futures::task::noop_waker();
129 let mut cx = std::task::Context::from_waker(&waker);
130 assert!(option_future.poll(&mut cx).is_pending());
131
132 let (tx, rx) = oneshot::channel();
133 let option_future: OptionFuture<_> = Some(rx).into();
134 pin_mut!(option_future);
135
136 tx.send(1usize).unwrap();
137 assert_eq!(option_future.poll(&mut cx), Poll::Ready(Ok(1)));
138 });
139 }
140}