tempo_commonware_node_config/
lib.rs

1//! Definitions to read and write a tempo consensus configuration.
2
3#![cfg_attr(not(test), warn(unused_crate_dependencies))]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6use std::{fmt::Display, net::SocketAddr, path::Path};
7
8use commonware_codec::{DecodeExt as _, Encode as _, FixedSize, Read};
9use commonware_cryptography::{
10    Signer,
11    bls12381::primitives::{
12        group::Share,
13        poly::Public,
14        variant::{MinSig, Variant},
15    },
16    ed25519::{PrivateKey, PublicKey},
17};
18use commonware_utils::set::{Ordered, OrderedAssociated};
19use indexmap::IndexMap;
20use serde::{
21    Deserialize,
22    Deserializer,
23    Serialize,
24    ser::{SerializeMap as _, Serializer}, // codespell:ignore ser
25};
26
27#[cfg(test)]
28mod tests;
29
30#[derive(Clone, Debug, PartialEq, Eq)]
31pub struct Peers {
32    inner: OrderedAssociated<PublicKey, SocketAddr>,
33}
34
35impl Peers {
36    pub fn empty() -> Self {
37        Self {
38            inner: OrderedAssociated::from(vec![]),
39        }
40    }
41
42    pub fn into_inner(self) -> OrderedAssociated<PublicKey, SocketAddr> {
43        self.inner
44    }
45
46    pub fn public_keys(&self) -> &Ordered<PublicKey> {
47        self.inner.keys()
48    }
49
50    pub fn socket_addresses(&self) -> &[SocketAddr] {
51        self.inner.values()
52    }
53}
54
55impl From<OrderedAssociated<PublicKey, SocketAddr>> for Peers {
56    fn from(inner: OrderedAssociated<PublicKey, SocketAddr>) -> Self {
57        Self { inner }
58    }
59}
60
61impl Serialize for Peers {
62    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
63    where
64        S: Serializer,
65    {
66        /// Serialization target for public keys.
67        struct Helper<'a>(&'a PublicKey);
68        impl<'a> Serialize for Helper<'a> {
69            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70            where
71                S: serde::Serializer,
72            {
73                use commonware_codec::Encode as _;
74
75                let bytes = self.0.encode();
76                const_hex::serde::serialize(&bytes, serializer)
77            }
78        }
79        let mut map = serializer.serialize_map(Some(self.inner.len()))?;
80        for (key, addr) in &self.inner {
81            map.serialize_entry(&Helper(key), addr)?;
82        }
83        map.end()
84    }
85}
86
87impl<'de> Deserialize<'de> for Peers {
88    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89    where
90        D: Deserializer<'de>,
91    {
92        // Deserialization target for public keys.
93        struct Helper(PublicKey);
94        impl<'de> Deserialize<'de> for Helper {
95            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96            where
97                D: Deserializer<'de>,
98            {
99                let bytes: Vec<u8> = const_hex::serde::deserialize(deserializer)?;
100                let key = PublicKey::decode(&bytes[..]).map_err(|err| {
101                    serde::de::Error::custom(format!(
102                        "failed decoding hex-formatted bytes as public key: {err:?}"
103                    ))
104                })?;
105                Ok(Self(key))
106            }
107        }
108        struct PeersVisitor;
109
110        impl<'de> serde::de::Visitor<'de> for PeersVisitor {
111            type Value = IndexMap<crate::PublicKey, SocketAddr>;
112
113            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114                formatter
115                    .write_str("a map of hex-formatted ed25519 public keys to <ip>:<port> entries")
116            }
117
118            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
119            where
120                A: serde::de::MapAccess<'de>,
121            {
122                let mut peers = IndexMap::with_capacity(map.size_hint().unwrap_or(0));
123                while let Some((key, addr)) = map.next_entry::<Helper, _>()? {
124                    let key = key.0;
125                    if peers.insert(key.clone(), addr).is_some() {
126                        return Err(serde::de::Error::custom(format!(
127                            "peers must not have duplicate entries; duplicate key: `{key}`",
128                        )))?;
129                    }
130                }
131                Ok(peers)
132            }
133        }
134
135        let peers = deserializer.deserialize_map(PeersVisitor)?;
136        Ok(Self {
137            inner: peers.into_iter().collect(),
138        })
139    }
140}
141
142#[derive(Clone, Debug, PartialEq, Eq)]
143pub struct PublicPolynomial {
144    inner: Public<MinSig>,
145}
146
147impl PublicPolynomial {
148    pub fn into_inner(self) -> Public<MinSig> {
149        self.inner
150    }
151}
152
153impl From<Public<MinSig>> for PublicPolynomial {
154    fn from(inner: Public<MinSig>) -> Self {
155        Self { inner }
156    }
157}
158
159impl Serialize for PublicPolynomial {
160    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
161    where
162        S: Serializer,
163    {
164        let bytes = self.inner.encode();
165        const_hex::serde::serialize(&bytes, serializer)
166    }
167}
168
169impl<'de> Deserialize<'de> for PublicPolynomial {
170    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
171    where
172        D: Deserializer<'de>,
173    {
174        let bytes: Vec<u8> = const_hex::serde::deserialize(deserializer)?;
175        let degree_of_public_polynomial = degree_of_public_polynomial_from_bytes(&bytes);
176        let inner = Public::<MinSig>::read_cfg(&mut &bytes[..], &degree_of_public_polynomial)
177            .map_err(serde::de::Error::custom)?;
178        Ok(Self { inner })
179    }
180}
181
182#[derive(Clone, PartialEq, Eq, derive_more::Debug)]
183pub struct SigningKey {
184    #[debug(skip)]
185    inner: PrivateKey,
186}
187
188impl SigningKey {
189    pub fn into_inner(self) -> PrivateKey {
190        self.inner
191    }
192
193    pub fn read_from_file<P: AsRef<Path>>(path: P) -> Result<Self, SigningKeyError> {
194        let hex = std::fs::read_to_string(path).map_err(SigningKeyErrorKind::Read)?;
195        Self::try_from_hex(&hex)
196    }
197
198    pub fn try_from_hex(hex: &str) -> Result<Self, SigningKeyError> {
199        let bytes = const_hex::decode(hex).map_err(SigningKeyErrorKind::Hex)?;
200        let inner = PrivateKey::decode(&bytes[..]).map_err(SigningKeyErrorKind::Parse)?;
201        Ok(Self { inner })
202    }
203
204    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), SigningKeyError> {
205        std::fs::write(path, self.to_string()).map_err(SigningKeyErrorKind::Write)?;
206        Ok(())
207    }
208
209    pub fn public_key(&self) -> PublicKey {
210        self.inner.public_key()
211    }
212}
213
214impl Display for SigningKey {
215    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216        f.write_str(&const_hex::encode_prefixed(self.inner.encode().as_ref()))
217    }
218}
219
220impl From<PrivateKey> for SigningKey {
221    fn from(inner: PrivateKey) -> Self {
222        Self { inner }
223    }
224}
225
226#[derive(Debug, thiserror::Error)]
227#[error(transparent)]
228pub struct SigningKeyError {
229    #[from]
230    inner: SigningKeyErrorKind,
231}
232
233#[derive(Debug, thiserror::Error)]
234enum SigningKeyErrorKind {
235    #[error("failed decoding file contents as hex-encoded bytes")]
236    Hex(#[source] const_hex::FromHexError),
237    #[error("failed parsing hex-decoded bytes as ed25519 private key")]
238    Parse(#[source] commonware_codec::Error),
239    #[error("failed reading file")]
240    Read(#[source] std::io::Error),
241    #[error("failed writing to file")]
242    Write(#[source] std::io::Error),
243}
244
245#[derive(Clone, Debug, PartialEq, Eq)]
246pub struct SigningShare {
247    inner: Share,
248}
249
250impl SigningShare {
251    pub fn into_inner(self) -> Share {
252        self.inner
253    }
254
255    pub fn read_from_file<P: AsRef<Path>>(path: P) -> Result<Self, SigningShareError> {
256        let hex = std::fs::read_to_string(path).map_err(SigningShareErrorKind::Read)?;
257        Self::try_from_hex(&hex)
258    }
259
260    pub fn try_from_hex(hex: &str) -> Result<Self, SigningShareError> {
261        let bytes = const_hex::decode(hex).map_err(SigningShareErrorKind::Hex)?;
262        let inner = Share::decode(&bytes[..]).map_err(SigningShareErrorKind::Parse)?;
263        Ok(Self { inner })
264    }
265
266    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), SigningShareError> {
267        std::fs::write(path, self.to_string()).map_err(SigningShareErrorKind::Write)?;
268        Ok(())
269    }
270}
271
272impl Display for SigningShare {
273    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274        f.write_str(&const_hex::encode_prefixed(self.inner.encode().as_ref()))
275    }
276}
277
278impl From<Share> for SigningShare {
279    fn from(inner: Share) -> Self {
280        Self { inner }
281    }
282}
283
284#[derive(Debug, thiserror::Error)]
285#[error(transparent)]
286pub struct SigningShareError {
287    #[from]
288    inner: SigningShareErrorKind,
289}
290
291#[derive(Debug, thiserror::Error)]
292enum SigningShareErrorKind {
293    #[error("failed decoding file contents as hex-encoded bytes")]
294    Hex(#[source] const_hex::FromHexError),
295    #[error("failed parsing hex-decoded bytes as bls12381 private share")]
296    Parse(#[source] commonware_codec::Error),
297    #[error("failed reading file")]
298    Read(#[source] std::io::Error),
299    #[error("failed writing to file")]
300    Write(#[source] std::io::Error),
301}
302
303// Reverses the operation C::SIZE * self.0.len() from
304// <Public<Minsig> as EncodeSize>::encode_size.
305fn degree_of_public_polynomial_from_bytes(bytes: &[u8]) -> usize {
306    bytes.len() / <<MinSig as Variant>::Public as FixedSize>::SIZE
307}