1use bitflags::bitflags;
8use ed25519_compact::{KeyPair, Noise, PublicKey, Seed, Signature};
9use flarch::nodeids::{NodeID, U256};
10use flmacro::VersionedSerde;
11use serde_derive::{Deserialize, Serialize};
12use serde_with::{base64::Base64, hex::Hex, serde_as};
13use std::fmt::{Debug, Formatter};
14use thiserror::Error;
15
16use crate::Modules;
17
18#[derive(Error, Debug)]
20pub enum ConfigError {
21 #[error("Didn't find public key")]
23 PublicKeyMissing,
24 #[error("Couldn't decode")]
26 NoInfo,
27 #[error(transparent)]
29 DecodeYaml(#[from] serde_yaml::Error),
30}
31
32#[serde_as]
34#[derive(VersionedSerde, Clone, Hash)]
35#[versions = "[NodeInfoV1,NodeInfoV2]"]
36pub struct NodeInfo {
37 pub name: String,
39 pub client: String,
41 #[serde_as(as = "Hex")]
43 pub pubkey: Vec<u8>,
44 pub modules: Modules,
46 #[serde(skip)]
47 id: Option<NodeID>,
48}
49
50impl NodeInfo {
51 pub fn new(pubkey: PublicKey) -> NodeInfo {
53 NodeInfo {
54 name: names::Generator::default().next().unwrap(),
55 client: "libc".to_string(),
56 pubkey: pubkey.as_ref().to_vec(),
57 modules: Modules::stable(),
58 id: None,
59 }
60 }
61
62 pub fn new_from_id(id: NodeID) -> NodeInfo {
63 let keypair = KeyPair::from_seed(Seed::default());
64 Self::new_from_id_kp(id, keypair.pk)
65 }
66
67 pub fn new_from_id_kp(id: NodeID, pubkey: PublicKey) -> NodeInfo {
68 NodeInfo {
69 name: names::Generator::default().next().unwrap(),
70 client: "libc".to_string(),
71 pubkey: pubkey.as_ref().to_vec(),
72 modules: Modules::stable(),
73 id: Some(id),
74 }
75 }
76
77 pub fn get_id(&self) -> U256 {
79 if let Some(id) = self.id {
80 return id;
81 }
82 let a: [u8; PublicKey::BYTES] = self.pubkey.clone().try_into().unwrap();
83 U256::from(a)
84 }
85
86 pub fn verify(&self, msg: &[u8], sig_bytes: &[u8]) -> bool {
88 let pubkey = PublicKey::from_slice(&self.pubkey).unwrap();
89 let sig = match Signature::from_slice(sig_bytes) {
90 Ok(sig) => sig,
91 Err(_) => return false,
92 };
93 pubkey.verify(msg, &sig).is_ok()
94 }
95
96 pub fn decode(data: &str) -> Result<Self, ConfigError> {
98 Ok(serde_yaml::from_str(data)?)
99 }
100
101 pub fn encode(&self) -> String {
103 serde_yaml::to_string(&self).unwrap()
104 }
105}
106
107impl Debug for NodeInfo {
108 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
109 let pubkey: String = self.pubkey.iter().map(|b| format!("{:02x}", b)).collect();
110
111 write!(
112 f,
113 "NodeInfo: {{ info: '{}', client: '{}', pubkey: {} }}",
114 self.name, self.client, pubkey
115 )
116 }
117}
118
119impl PartialEq for NodeInfo {
120 fn eq(&self, other: &Self) -> bool {
121 self.get_id() == other.get_id()
122 }
123}
124
125impl Eq for NodeInfo {}
126
127impl From<NodeInfoV2> for NodeInfo {
128 fn from(old: NodeInfoV2) -> Self {
129 Self {
130 name: old.name,
131 client: old.client,
132 pubkey: old.pubkey,
133 modules: old.modules.into(),
134 id: None,
135 }
136 }
137}
138
139#[serde_as]
140#[derive(Serialize, Deserialize, Clone)]
141struct NodeInfoV2 {
142 pub name: String,
144 pub client: String,
146 #[serde_as(as = "Base64")]
148 pub pubkey: Vec<u8>,
149 #[serde(default = "ModulesV2::all")]
151 pub modules: ModulesV2,
152 #[serde(skip)]
153 _id: Option<NodeID>,
154}
155
156impl Into<Modules> for ModulesV2 {
157 fn into(self) -> Modules {
158 Modules::from_bits(self.bits()).unwrap_or(Modules::stable())
159 }
160}
161
162bitflags! {
163 #[derive(Clone, Copy, Serialize, Deserialize, PartialEq, Hash)]
164 pub struct ModulesV2: u32 {
165 const ENABLE_STAT = 0x1;
166 const ENABLE_RAND = 0x2;
167 const ENABLE_GOSSIP = 0x4;
168 const ENABLE_PING = 0x8;
169 const ENABLE_WEBPROXY = 0x10;
170 const ENABLE_WEBPROXY_REQUESTS = 0x20;
171 }
172}
173
174impl From<NodeInfoV1> for NodeInfoV2 {
175 fn from(_: NodeInfoV1) -> Self {
176 panic!("Old configuration not supported anymore")
177 }
178}
179
180#[derive(Serialize, Deserialize, Clone)]
182struct NodeInfoV1 {}
183
184#[serde_as]
186#[derive(VersionedSerde, Debug, PartialEq)]
187#[versions = "[NodeConfigV1]"]
188pub struct NodeConfig {
189 pub info: NodeInfo,
191 #[serde_as(as = "Hex")]
193 pub keypair: Vec<u8>,
194}
195
196impl Default for NodeConfig {
197 fn default() -> Self {
198 Self::new()
199 }
200}
201
202impl NodeConfig {
203 pub fn new() -> Self {
205 let keypair = KeyPair::from_seed(Seed::default());
206 NodeConfig {
207 info: NodeInfo::new(keypair.pk),
208 keypair: keypair.as_ref().to_vec(),
209 }
210 }
211
212 pub fn new_id(id: NodeID) -> Self {
214 let keypair = KeyPair::from_seed(Seed::default());
215 NodeConfig {
216 info: NodeInfo::new_from_id_kp(id, keypair.pk),
217 keypair: keypair.as_ref().to_vec(),
218 }
219 }
220
221 pub fn encode(&self) -> String {
223 serde_yaml::to_string(&self).unwrap()
224 }
225
226 pub fn decode(data: &str) -> Self {
229 serde_yaml::from_str(data)
230 .ok()
231 .unwrap_or_else(|| Self::new())
232 }
233
234 pub fn sign(&self, hash: [u8; 32]) -> Vec<u8> {
238 let keypair = KeyPair::from_slice(&self.keypair).unwrap();
239 keypair.sk.sign(&hash, Some(Noise::default())).to_vec()
240 }
241}
242
243impl Clone for NodeConfig {
244 fn clone(&self) -> Self {
245 NodeConfig {
246 info: self.info.clone(),
247 keypair: self.keypair.clone(),
248 }
249 }
250}
251
252#[serde_as]
253#[derive(Serialize, Deserialize, Clone)]
254struct NodeConfigV1 {
255 info: NodeInfoV2,
257 #[serde_as(as = "Base64")]
259 keypair: Vec<u8>,
260}
261
262impl From<NodeConfigV1> for NodeConfig {
263 fn from(old: NodeConfigV1) -> Self {
264 Self {
265 info: old.info.into(),
266 keypair: old.keypair,
267 }
268 }
269}
270
271#[cfg(test)]
272mod tests {
273 use flarch::start_logging_filter_level;
274
275 use super::*;
276
277 #[test]
278 fn save_load() -> Result<(), ConfigError> {
279 start_logging_filter_level(vec![], log::LevelFilter::Debug);
280
281 let nc = NodeConfig::new();
282 let nc_str = nc.encode();
283 log::debug!("NodeConfig is: {nc_str}");
284 let nc_clone = NodeConfig::decode(&nc_str);
285 assert_eq!(nc.keypair, nc_clone.keypair);
286 assert_eq!(nc.info.pubkey, nc_clone.info.pubkey);
287
288 let i = nc.info.clone();
289 let ncv1 = NodeConfigVersion::NodeConfigV1(NodeConfigV1 {
290 info: NodeInfoV2 {
291 name: i.name,
292 client: i.client,
293 pubkey: i.pubkey,
294 modules: ModulesV2::all(),
295 _id: i.id,
296 },
297 keypair: nc.keypair.clone(),
298 });
299 let ncv1_str = serde_yaml::to_string(&ncv1)?;
300 let ncv2 = NodeConfig::decode(&ncv1_str);
301 println!("{ncv1_str}");
302 assert_eq!(ncv2, nc);
303 Ok(())
304 }
305
306 #[test]
307 fn node_info_serde() -> anyhow::Result<()>{
308 let nc = NodeConfig::new();
309 let ni = nc.info;
310 let ni_str = ni.encode();
311 let ni_clone = NodeInfo::decode(&ni_str)?;
312 assert_eq!(ni, ni_clone);
313
314 Ok(())
315 }
316}