1use std::collections::{BTreeMap, BTreeSet};
2use std::fmt::{Debug, Display};
3use std::hash::Hash;
4use std::path::Path;
5use std::str::FromStr;
6
7use anyhow::{Context, format_err};
8use bitcoin::hashes::sha256::HashEngine;
9use bitcoin::hashes::{Hash as BitcoinHash, hex, sha256};
10use bls12_381::Scalar;
11use fedimint_core::core::{ModuleInstanceId, ModuleKind};
12use fedimint_core::encoding::{DynRawFallback, Encodable};
13use fedimint_core::module::registry::ModuleRegistry;
14use fedimint_core::util::SafeUrl;
15use fedimint_core::{ModuleDecoderRegistry, format_hex};
16use fedimint_logging::LOG_CORE;
17use hex::FromHex;
18use secp256k1::PublicKey;
19use serde::de::DeserializeOwned;
20use serde::ser::SerializeMap;
21use serde::{Deserialize, Deserializer, Serialize, Serializer};
22use serde_json::json;
23use threshold_crypto::{G1Projective, G2Projective};
24use tracing::warn;
25
26use crate::core::DynClientConfig;
27use crate::encoding::Decodable;
28use crate::module::{
29 CoreConsensusVersion, DynCommonModuleInit, IDynCommonModuleInit, ModuleConsensusVersion,
30};
31use crate::{PeerId, maybe_add_send_sync};
32
33pub const ALEPH_BFT_UNIT_BYTE_LIMIT: usize = 50_000;
36
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
43pub struct JsonWithKind {
44 kind: ModuleKind,
45 #[serde(flatten)]
46 value: serde_json::Value,
47}
48
49impl JsonWithKind {
50 pub fn new(kind: ModuleKind, value: serde_json::Value) -> Self {
51 Self { kind, value }
52 }
53
54 pub fn with_fixed_empty_value(self) -> Self {
75 if let serde_json::Value::Object(ref o) = self.value {
76 if o.is_empty() {
77 return Self {
78 kind: self.kind,
79 value: serde_json::Value::Null,
80 };
81 }
82 }
83
84 self
85 }
86
87 pub fn value(&self) -> &serde_json::Value {
88 &self.value
89 }
90
91 pub fn kind(&self) -> &ModuleKind {
92 &self.kind
93 }
94
95 pub fn is_kind(&self, kind: &ModuleKind) -> bool {
96 &self.kind == kind
97 }
98}
99
100#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Encodable, Decodable)]
101pub struct PeerUrl {
102 pub url: SafeUrl,
104 pub name: String,
106}
107
108#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
112pub struct ClientConfigV0 {
113 #[serde(flatten)]
114 pub global: GlobalClientConfigV0,
115 #[serde(deserialize_with = "de_int_key")]
116 pub modules: BTreeMap<ModuleInstanceId, ClientModuleConfig>,
117}
118
119#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
123pub struct ClientConfig {
124 #[serde(flatten)]
125 pub global: GlobalClientConfig,
126 #[serde(deserialize_with = "de_int_key")]
127 pub modules: BTreeMap<ModuleInstanceId, ClientModuleConfig>,
128}
129
130fn de_int_key<'de, D, K, V>(deserializer: D) -> Result<BTreeMap<K, V>, D::Error>
132where
133 D: Deserializer<'de>,
134 K: Eq + Ord + FromStr,
135 K::Err: Display,
136 V: Deserialize<'de>,
137{
138 let string_map = <BTreeMap<String, V>>::deserialize(deserializer)?;
139 let map = string_map
140 .into_iter()
141 .map(|(key_str, value)| {
142 let key = K::from_str(&key_str).map_err(serde::de::Error::custom)?;
143 Ok((key, value))
144 })
145 .collect::<Result<BTreeMap<_, _>, _>>()?;
146 Ok(map)
147}
148
149fn optional_de_int_key<'de, D, K, V>(deserializer: D) -> Result<Option<BTreeMap<K, V>>, D::Error>
150where
151 D: Deserializer<'de>,
152 K: Eq + Ord + FromStr,
153 K::Err: Display,
154 V: Deserialize<'de>,
155{
156 let Some(string_map) = <Option<BTreeMap<String, V>>>::deserialize(deserializer)? else {
157 return Ok(None);
158 };
159
160 let map = string_map
161 .into_iter()
162 .map(|(key_str, value)| {
163 let key = K::from_str(&key_str).map_err(serde::de::Error::custom)?;
164 Ok((key, value))
165 })
166 .collect::<Result<BTreeMap<_, _>, _>>()?;
167
168 Ok(Some(map))
169}
170
171#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
174pub struct JsonClientConfig {
175 pub global: GlobalClientConfig,
176 pub modules: BTreeMap<ModuleInstanceId, JsonWithKind>,
177}
178
179#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
181pub struct GlobalClientConfigV0 {
182 #[serde(deserialize_with = "de_int_key")]
184 pub api_endpoints: BTreeMap<PeerId, PeerUrl>,
185 pub consensus_version: CoreConsensusVersion,
187 pub meta: BTreeMap<String, String>,
190}
191
192#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
194pub struct GlobalClientConfig {
195 #[serde(deserialize_with = "de_int_key")]
197 pub api_endpoints: BTreeMap<PeerId, PeerUrl>,
198 #[serde(default, deserialize_with = "optional_de_int_key")]
201 pub broadcast_public_keys: Option<BTreeMap<PeerId, PublicKey>>,
202 pub consensus_version: CoreConsensusVersion,
204 pub meta: BTreeMap<String, String>,
207}
208
209impl GlobalClientConfig {
210 pub fn calculate_federation_id(&self) -> FederationId {
213 FederationId(self.api_endpoints.consensus_hash())
214 }
215
216 pub fn federation_name(&self) -> Option<&str> {
218 self.meta.get(META_FEDERATION_NAME_KEY).map(|x| &**x)
219 }
220}
221
222impl ClientConfig {
223 pub fn redecode_raw(
225 self,
226 modules: &ModuleDecoderRegistry,
227 ) -> Result<Self, crate::encoding::DecodeError> {
228 Ok(Self {
229 modules: self
230 .modules
231 .into_iter()
232 .map(|(k, v)| {
233 let kind = v.kind.clone();
236 v.redecode_raw(modules)
237 .context(format!("redecode_raw: instance: {k}, kind: {kind}"))
238 .map(|v| (k, v))
239 })
240 .collect::<Result<_, _>>()?,
241 ..self
242 })
243 }
244
245 pub fn calculate_federation_id(&self) -> FederationId {
246 self.global.calculate_federation_id()
247 }
248
249 pub fn meta<V: serde::de::DeserializeOwned + 'static>(
251 &self,
252 key: &str,
253 ) -> Result<Option<V>, anyhow::Error> {
254 let Some(str_value) = self.global.meta.get(key) else {
255 return Ok(None);
256 };
257 let res = serde_json::from_str(str_value)
258 .map(Some)
259 .context(format!("Decoding meta field '{key}' failed"));
260
261 if res.is_err() && std::any::TypeId::of::<V>() == std::any::TypeId::of::<String>() {
265 let string_ret = Box::new(str_value.clone());
266 let ret = unsafe {
267 std::mem::transmute::<Box<String>, Box<V>>(string_ret)
269 };
270 Ok(Some(*ret))
271 } else {
272 res
273 }
274 }
275
276 pub fn to_json(&self) -> JsonClientConfig {
282 JsonClientConfig {
283 global: self.global.clone(),
284 modules: self
285 .modules
286 .iter()
287 .map(|(&module_instance_id, module_config)| {
288 let module_config_json = JsonWithKind {
289 kind: module_config.kind.clone(),
290 value: module_config.config
291 .clone()
292 .decoded()
293 .and_then(|dyn_cfg| dyn_cfg.to_json())
294 .unwrap_or_else(|| json!({
295 "unknown_module_hex": module_config.config.consensus_encode_to_hex()
296 })),
297 };
298 (module_instance_id, module_config_json)
299 })
300 .collect(),
301 }
302 }
303}
304
305#[derive(
311 Debug,
312 Copy,
313 Serialize,
314 Deserialize,
315 Clone,
316 Eq,
317 Hash,
318 PartialEq,
319 Encodable,
320 Decodable,
321 Ord,
322 PartialOrd,
323)]
324pub struct FederationId(pub sha256::Hash);
325
326#[derive(
327 Debug,
328 Copy,
329 Serialize,
330 Deserialize,
331 Clone,
332 Eq,
333 Hash,
334 PartialEq,
335 Encodable,
336 Decodable,
337 Ord,
338 PartialOrd,
339)]
340pub struct FederationIdPrefix([u8; 4]);
346
347impl Display for FederationIdPrefix {
348 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
349 format_hex(&self.0, f)
350 }
351}
352
353impl Display for FederationId {
354 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
355 format_hex(&self.0.to_byte_array(), f)
356 }
357}
358
359impl FromStr for FederationIdPrefix {
360 type Err = anyhow::Error;
361
362 fn from_str(s: &str) -> Result<Self, Self::Err> {
363 Ok(Self(<[u8; 4]>::from_hex(s)?))
364 }
365}
366
367impl FederationIdPrefix {
368 pub fn to_bytes(&self) -> Vec<u8> {
369 self.0.to_vec()
370 }
371}
372
373impl FederationId {
375 pub fn dummy() -> Self {
377 Self(sha256::Hash::from_byte_array([42; 32]))
378 }
379
380 pub(crate) fn from_byte_array(bytes: [u8; 32]) -> Self {
381 Self(sha256::Hash::from_byte_array(bytes))
382 }
383
384 pub fn to_prefix(&self) -> FederationIdPrefix {
385 FederationIdPrefix(self.0[..4].try_into().expect("can't fail"))
386 }
387
388 pub fn to_fake_ln_pub_key(
398 &self,
399 secp: &bitcoin::secp256k1::Secp256k1<bitcoin::secp256k1::All>,
400 ) -> anyhow::Result<bitcoin::secp256k1::PublicKey> {
401 let sk = bitcoin::secp256k1::SecretKey::from_slice(&self.0.to_byte_array())?;
402 Ok(bitcoin::secp256k1::PublicKey::from_secret_key(secp, &sk))
403 }
404}
405
406impl FromStr for FederationId {
407 type Err = anyhow::Error;
408
409 fn from_str(s: &str) -> Result<Self, Self::Err> {
410 Ok(Self::from_byte_array(<[u8; 32]>::from_hex(s)?))
411 }
412}
413
414impl ClientConfig {
415 pub fn consensus_hash(&self) -> sha256::Hash {
417 let mut engine = HashEngine::default();
418 self.consensus_encode(&mut engine)
419 .expect("Consensus hashing should never fail");
420 sha256::Hash::from_engine(engine)
421 }
422
423 pub fn get_module<T: Decodable + 'static>(&self, id: ModuleInstanceId) -> anyhow::Result<&T> {
424 self.modules.get(&id).map_or_else(
425 || Err(format_err!("Client config for module id {id} not found")),
426 |client_cfg| client_cfg.cast(),
427 )
428 }
429
430 pub fn get_module_cfg(&self, id: ModuleInstanceId) -> anyhow::Result<ClientModuleConfig> {
432 self.modules.get(&id).map_or_else(
433 || Err(format_err!("Client config for module id {id} not found")),
434 |client_cfg| Ok(client_cfg.clone()),
435 )
436 }
437
438 pub fn get_first_module_by_kind<T: Decodable + 'static>(
446 &self,
447 kind: impl Into<ModuleKind>,
448 ) -> anyhow::Result<(ModuleInstanceId, &T)> {
449 let kind: ModuleKind = kind.into();
450 let Some((id, module_cfg)) = self.modules.iter().find(|(_, v)| v.is_kind(&kind)) else {
451 anyhow::bail!("Module kind {kind} not found")
452 };
453 Ok((*id, module_cfg.cast()?))
454 }
455
456 pub fn get_first_module_by_kind_cfg(
458 &self,
459 kind: impl Into<ModuleKind>,
460 ) -> anyhow::Result<(ModuleInstanceId, ClientModuleConfig)> {
461 let kind: ModuleKind = kind.into();
462 self.modules
463 .iter()
464 .find(|(_, v)| v.is_kind(&kind))
465 .map(|(id, v)| (*id, v.clone()))
466 .ok_or_else(|| anyhow::format_err!("Module kind {kind} not found"))
467 }
468}
469
470#[derive(Clone, Debug)]
471pub struct ModuleInitRegistry<M>(BTreeMap<ModuleKind, M>);
472
473impl<M> ModuleInitRegistry<M> {
474 pub fn iter(&self) -> impl Iterator<Item = (&ModuleKind, &M)> {
475 self.0.iter()
476 }
477}
478
479impl<M> Default for ModuleInitRegistry<M> {
480 fn default() -> Self {
481 Self(BTreeMap::new())
482 }
483}
484
485#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
488pub struct ConfigGenModuleParams {
489 pub local: serde_json::Value,
490 pub consensus: serde_json::Value,
491}
492
493impl ConfigGenModuleParams {
494 pub fn new(local: serde_json::Value, consensus: serde_json::Value) -> Self {
495 Self { local, consensus }
496 }
497
498 pub fn to_typed<P: ModuleInitParams>(&self) -> anyhow::Result<P> {
501 Ok(P::from_parts(
502 Self::parse("local", self.local.clone())?,
503 Self::parse("consensus", self.consensus.clone())?,
504 ))
505 }
506
507 fn parse<P: DeserializeOwned>(name: &str, json: serde_json::Value) -> anyhow::Result<P> {
508 serde_json::from_value(json).with_context(|| format!("Schema mismatch for {name} argument"))
509 }
510
511 pub fn from_typed<P: ModuleInitParams>(p: P) -> anyhow::Result<Self> {
512 let (local, consensus) = p.to_parts();
513 Ok(Self {
514 local: serde_json::to_value(local)?,
515 consensus: serde_json::to_value(consensus)?,
516 })
517 }
518}
519
520pub type CommonModuleInitRegistry = ModuleInitRegistry<DynCommonModuleInit>;
521
522pub type ServerModuleConfigGenParamsRegistry = ModuleRegistry<ConfigGenModuleParams>;
524
525impl Eq for ServerModuleConfigGenParamsRegistry {}
526
527impl PartialEq for ServerModuleConfigGenParamsRegistry {
528 fn eq(&self, other: &Self) -> bool {
529 self.iter_modules().eq(other.iter_modules())
530 }
531}
532
533impl Serialize for ServerModuleConfigGenParamsRegistry {
534 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
535 let modules: Vec<_> = self.iter_modules().collect();
536 let mut serializer = serializer.serialize_map(Some(modules.len()))?;
537 for (id, kind, params) in modules {
538 serializer.serialize_key(&id)?;
539 serializer.serialize_value(&(kind.clone(), params.clone()))?;
540 }
541 serializer.end()
542 }
543}
544
545impl<'de> Deserialize<'de> for ServerModuleConfigGenParamsRegistry {
546 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
547 where
548 D: Deserializer<'de>,
549 {
550 let json: BTreeMap<ModuleInstanceId, (ModuleKind, ConfigGenModuleParams)> =
551 Deserialize::deserialize(deserializer)?;
552 let mut params = BTreeMap::new();
553
554 for (id, (kind, module)) in json {
555 params.insert(id, (kind, module));
556 }
557 Ok(Self::from(params))
558 }
559}
560
561impl<M> From<Vec<M>> for ModuleInitRegistry<M>
562where
563 M: AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static>,
564{
565 fn from(value: Vec<M>) -> Self {
566 Self(
567 value
568 .into_iter()
569 .map(|i| (i.as_ref().module_kind(), i))
570 .collect::<BTreeMap<_, _>>(),
571 )
572 }
573}
574
575impl<M> FromIterator<M> for ModuleInitRegistry<M>
576where
577 M: AsRef<maybe_add_send_sync!(dyn IDynCommonModuleInit + 'static)>,
578{
579 fn from_iter<T: IntoIterator<Item = M>>(iter: T) -> Self {
580 Self(
581 iter.into_iter()
582 .map(|i| (i.as_ref().module_kind(), i))
583 .collect::<BTreeMap<_, _>>(),
584 )
585 }
586}
587
588impl<M> ModuleInitRegistry<M> {
589 pub fn new() -> Self {
590 Self::default()
591 }
592
593 pub fn attach<T>(&mut self, r#gen: T)
594 where
595 T: Into<M> + 'static + Send + Sync,
596 M: AsRef<dyn IDynCommonModuleInit + 'static + Send + Sync>,
597 {
598 let r#gen: M = r#gen.into();
599 let kind = r#gen.as_ref().module_kind();
600 assert!(
601 self.0.insert(kind.clone(), r#gen).is_none(),
602 "Can't insert module of same kind twice: {kind}"
603 );
604 }
605
606 pub fn kinds(&self) -> BTreeSet<ModuleKind> {
607 self.0.keys().cloned().collect()
608 }
609
610 pub fn get(&self, k: &ModuleKind) -> Option<&M> {
611 self.0.get(k)
612 }
613}
614
615impl ModuleRegistry<ConfigGenModuleParams> {
616 pub fn attach_config_gen_params_by_id<T: ModuleInitParams>(
617 &mut self,
618 id: ModuleInstanceId,
619 kind: ModuleKind,
620 r#gen: T,
621 ) -> &mut Self {
622 let params = ConfigGenModuleParams::from_typed(r#gen)
623 .unwrap_or_else(|err| panic!("Invalid config gen params for {kind}: {err}"));
624 self.register_module(id, kind, params);
625 self
626 }
627
628 pub fn attach_config_gen_params<T: ModuleInitParams>(
629 &mut self,
630 kind: ModuleKind,
631 r#gen: T,
632 ) -> &mut Self {
633 let params = ConfigGenModuleParams::from_typed(r#gen)
634 .unwrap_or_else(|err| panic!("Invalid config gen params for {kind}: {err}"));
635 self.append_module(kind, params);
636 self
637 }
638}
639
640impl<M> ModuleInitRegistry<M>
641where
642 M: AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static>,
643{
644 #[deprecated(
645 note = "You probably want `available_decoders` to support missing module kinds. If you really want a strict behavior, use `decoders_strict`"
646 )]
647 pub fn decoders<'a>(
648 &self,
649 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
650 ) -> anyhow::Result<ModuleDecoderRegistry> {
651 self.decoders_strict(modules)
652 }
653
654 pub fn decoders_strict<'a>(
656 &self,
657 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
658 ) -> anyhow::Result<ModuleDecoderRegistry> {
659 let mut decoders = BTreeMap::new();
660 for (id, kind) in modules {
661 let Some(init) = self.0.get(kind) else {
662 anyhow::bail!(
663 "Detected configuration for unsupported module id: {id}, kind: {kind}"
664 )
665 };
666
667 decoders.insert(id, (kind.clone(), init.as_ref().decoder()));
668 }
669 Ok(ModuleDecoderRegistry::from(decoders))
670 }
671
672 pub fn available_decoders<'a>(
674 &self,
675 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
676 ) -> anyhow::Result<ModuleDecoderRegistry> {
677 let mut decoders = BTreeMap::new();
678 for (id, kind) in modules {
679 let Some(init) = self.0.get(kind) else {
680 warn!(target: LOG_CORE, "Unsupported module id: {id}, kind: {kind}");
681 continue;
682 };
683
684 decoders.insert(id, (kind.clone(), init.as_ref().decoder()));
685 }
686 Ok(ModuleDecoderRegistry::from(decoders))
687 }
688}
689
690#[derive(Debug, Default, Clone, Serialize, Deserialize)]
692pub struct EmptyGenParams {}
693
694pub trait ModuleInitParams: serde::Serialize + serde::de::DeserializeOwned {
695 type Local: DeserializeOwned + Serialize;
697 type Consensus: DeserializeOwned + Serialize;
699
700 fn from_parts(local: Self::Local, consensus: Self::Consensus) -> Self;
702
703 fn to_parts(self) -> (Self::Local, Self::Consensus);
705}
706
707#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
708pub struct ServerModuleConsensusConfig {
709 pub kind: ModuleKind,
710 pub version: ModuleConsensusVersion,
711 #[serde(with = "::hex::serde")]
712 pub config: Vec<u8>,
713}
714
715#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
721pub struct ClientModuleConfig {
722 pub kind: ModuleKind,
723 pub version: ModuleConsensusVersion,
724 #[serde(with = "::fedimint_core::encoding::as_hex")]
725 pub config: DynRawFallback<DynClientConfig>,
726}
727
728impl ClientModuleConfig {
729 pub fn from_typed<T: fedimint_core::core::ClientConfig>(
730 module_instance_id: ModuleInstanceId,
731 kind: ModuleKind,
732 version: ModuleConsensusVersion,
733 value: T,
734 ) -> anyhow::Result<Self> {
735 Ok(Self {
736 kind,
737 version,
738 config: fedimint_core::core::DynClientConfig::from_typed(module_instance_id, value)
739 .into(),
740 })
741 }
742
743 pub fn redecode_raw(
744 self,
745 modules: &ModuleDecoderRegistry,
746 ) -> Result<Self, crate::encoding::DecodeError> {
747 Ok(Self {
748 config: self.config.redecode_raw(modules)?,
749 ..self
750 })
751 }
752
753 pub fn is_kind(&self, kind: &ModuleKind) -> bool {
754 &self.kind == kind
755 }
756
757 pub fn kind(&self) -> &ModuleKind {
758 &self.kind
759 }
760}
761
762impl ClientModuleConfig {
763 pub fn cast<T>(&self) -> anyhow::Result<&T>
764 where
765 T: 'static,
766 {
767 self.config
768 .expect_decoded_ref()
769 .as_any()
770 .downcast_ref::<T>()
771 .context("can't convert client module config to desired type")
772 }
773}
774
775#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
779pub struct ServerModuleConfig {
780 pub local: JsonWithKind,
781 pub private: JsonWithKind,
782 pub consensus: ServerModuleConsensusConfig,
783}
784
785impl ServerModuleConfig {
786 pub fn from(
787 local: JsonWithKind,
788 private: JsonWithKind,
789 consensus: ServerModuleConsensusConfig,
790 ) -> Self {
791 Self {
792 local,
793 private,
794 consensus,
795 }
796 }
797
798 pub fn to_typed<T: TypedServerModuleConfig>(&self) -> anyhow::Result<T> {
799 let local = serde_json::from_value(self.local.value().clone())?;
800 let private = serde_json::from_value(self.private.value().clone())?;
801 let consensus = <T::Consensus>::consensus_decode_whole(
802 &self.consensus.config[..],
803 &ModuleRegistry::default(),
804 )?;
805
806 Ok(TypedServerModuleConfig::from_parts(
807 local, private, consensus,
808 ))
809 }
810}
811
812pub trait TypedServerModuleConsensusConfig:
814 DeserializeOwned + Serialize + Encodable + Decodable
815{
816 fn kind(&self) -> ModuleKind;
817
818 fn version(&self) -> ModuleConsensusVersion;
819
820 fn from_erased(erased: &ServerModuleConsensusConfig) -> anyhow::Result<Self> {
821 Ok(Self::consensus_decode_whole(
822 &erased.config[..],
823 &ModuleRegistry::default(),
824 )?)
825 }
826}
827
828pub trait TypedServerModuleConfig: DeserializeOwned + Serialize {
830 type Local: DeserializeOwned + Serialize;
832 type Private: DeserializeOwned + Serialize;
835 type Consensus: TypedServerModuleConsensusConfig;
837
838 fn from_parts(local: Self::Local, private: Self::Private, consensus: Self::Consensus) -> Self;
840
841 fn to_parts(self) -> (ModuleKind, Self::Local, Self::Private, Self::Consensus);
843
844 fn to_erased(self) -> ServerModuleConfig {
846 let (kind, local, private, consensus) = self.to_parts();
847
848 ServerModuleConfig {
849 local: JsonWithKind::new(
850 kind.clone(),
851 serde_json::to_value(local).expect("serialization can't fail"),
852 ),
853 private: JsonWithKind::new(
854 kind,
855 serde_json::to_value(private).expect("serialization can't fail"),
856 ),
857 consensus: ServerModuleConsensusConfig {
858 kind: consensus.kind(),
859 version: consensus.version(),
860 config: consensus.consensus_encode_to_vec(),
861 },
862 }
863 }
864}
865
866#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encodable, Decodable)]
867pub enum P2PMessage {
868 Aleph(Vec<u8>),
869 Checksum(sha256::Hash),
870 Dkg(DkgMessage),
871 Encodable(Vec<u8>),
872}
873
874#[derive(Debug, PartialEq, Eq, Clone, Encodable, Decodable)]
875pub enum DkgMessage {
876 Hash(sha256::Hash),
877 Commitment(Vec<(G1Projective, G2Projective)>),
878 Share(Scalar),
879}
880
881impl Serialize for DkgMessage {
884 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
885 where
886 S: Serializer,
887 {
888 self.consensus_encode_to_hex().serialize(serializer)
889 }
890}
891
892impl<'de> Deserialize<'de> for DkgMessage {
893 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
894 where
895 D: Deserializer<'de>,
896 {
897 Self::consensus_decode_hex(
898 &String::deserialize(deserializer)?,
899 &ModuleDecoderRegistry::default(),
900 )
901 .map_err(serde::de::Error::custom)
902 }
903}
904
905pub const META_FEDERATION_NAME_KEY: &str = "federation_name";
908
909pub fn load_from_file<T: DeserializeOwned>(path: &Path) -> Result<T, anyhow::Error> {
910 let file = std::fs::File::open(path)?;
911 Ok(serde_json::from_reader(file)?)
912}
913
914pub mod serde_binary_human_readable {
915 use std::borrow::Cow;
916
917 use hex::{FromHex, ToHex};
918 use serde::de::DeserializeOwned;
919 use serde::{Deserialize, Deserializer, Serialize, Serializer};
920
921 pub fn serialize<T: Serialize, S: Serializer>(x: &T, s: S) -> Result<S::Ok, S::Error> {
922 if s.is_human_readable() {
923 let bytes =
924 bincode::serialize(x).map_err(|e| serde::ser::Error::custom(format!("{e:?}")))?;
925 s.serialize_str(&bytes.encode_hex::<String>())
926 } else {
927 Serialize::serialize(x, s)
928 }
929 }
930
931 pub fn deserialize<'d, T: DeserializeOwned, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
932 if d.is_human_readable() {
933 let hex_str: Cow<str> = Deserialize::deserialize(d)?;
934 let bytes = Vec::from_hex(hex_str.as_ref()).map_err(serde::de::Error::custom)?;
935 bincode::deserialize(&bytes).map_err(|e| serde::de::Error::custom(format!("{e:?}")))
936 } else {
937 Deserialize::deserialize(d)
938 }
939 }
940}
941
942#[cfg(test)]
943mod tests;