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 && o.is_empty()
77 {
78 return Self {
79 kind: self.kind,
80 value: serde_json::Value::Null,
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(|(module_id, v)| {
233 let kind = v.kind.clone();
236
237 v.redecode_raw(modules)
238 .context(format!("redecode_raw: instance: {module_id}, kind: {kind}"))
239 .map(|v| (module_id, v))
240 })
241 .collect::<Result<_, _>>()?,
242 ..self
243 })
244 }
245
246 pub fn calculate_federation_id(&self) -> FederationId {
247 self.global.calculate_federation_id()
248 }
249
250 pub fn meta<V: serde::de::DeserializeOwned + 'static>(
252 &self,
253 key: &str,
254 ) -> Result<Option<V>, anyhow::Error> {
255 let Some(str_value) = self.global.meta.get(key) else {
256 return Ok(None);
257 };
258 let res = serde_json::from_str(str_value)
259 .map(Some)
260 .context(format!("Decoding meta field '{key}' failed"));
261
262 if res.is_err() && std::any::TypeId::of::<V>() == std::any::TypeId::of::<String>() {
266 let string_ret = Box::new(str_value.clone());
267 let ret = unsafe {
268 std::mem::transmute::<Box<String>, Box<V>>(string_ret)
270 };
271 Ok(Some(*ret))
272 } else {
273 res
274 }
275 }
276
277 pub fn to_json(&self) -> JsonClientConfig {
283 JsonClientConfig {
284 global: self.global.clone(),
285 modules: self
286 .modules
287 .iter()
288 .map(|(&module_instance_id, module_config)| {
289 let module_config_json = JsonWithKind {
290 kind: module_config.kind.clone(),
291 value: module_config.config
292 .clone()
293 .decoded()
294 .and_then(|dyn_cfg| dyn_cfg.to_json())
295 .unwrap_or_else(|| json!({
296 "unknown_module_hex": module_config.config.consensus_encode_to_hex()
297 })),
298 };
299 (module_instance_id, module_config_json)
300 })
301 .collect(),
302 }
303 }
304}
305
306#[derive(
312 Debug,
313 Copy,
314 Serialize,
315 Deserialize,
316 Clone,
317 Eq,
318 Hash,
319 PartialEq,
320 Encodable,
321 Decodable,
322 Ord,
323 PartialOrd,
324)]
325pub struct FederationId(pub sha256::Hash);
326
327#[derive(
328 Debug,
329 Copy,
330 Serialize,
331 Deserialize,
332 Clone,
333 Eq,
334 Hash,
335 PartialEq,
336 Encodable,
337 Decodable,
338 Ord,
339 PartialOrd,
340)]
341pub struct FederationIdPrefix([u8; 4]);
347
348impl Display for FederationIdPrefix {
349 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
350 format_hex(&self.0, f)
351 }
352}
353
354impl Display for FederationId {
355 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
356 format_hex(&self.0.to_byte_array(), f)
357 }
358}
359
360impl FromStr for FederationIdPrefix {
361 type Err = anyhow::Error;
362
363 fn from_str(s: &str) -> Result<Self, Self::Err> {
364 Ok(Self(<[u8; 4]>::from_hex(s)?))
365 }
366}
367
368impl FederationIdPrefix {
369 pub fn to_bytes(&self) -> Vec<u8> {
370 self.0.to_vec()
371 }
372}
373
374impl FederationId {
376 pub fn dummy() -> Self {
378 Self(sha256::Hash::from_byte_array([42; 32]))
379 }
380
381 pub(crate) fn from_byte_array(bytes: [u8; 32]) -> Self {
382 Self(sha256::Hash::from_byte_array(bytes))
383 }
384
385 pub fn to_prefix(&self) -> FederationIdPrefix {
386 FederationIdPrefix(self.0[..4].try_into().expect("can't fail"))
387 }
388
389 pub fn to_fake_ln_pub_key(
399 &self,
400 secp: &bitcoin::secp256k1::Secp256k1<bitcoin::secp256k1::All>,
401 ) -> anyhow::Result<bitcoin::secp256k1::PublicKey> {
402 let sk = bitcoin::secp256k1::SecretKey::from_slice(&self.0.to_byte_array())?;
403 Ok(bitcoin::secp256k1::PublicKey::from_secret_key(secp, &sk))
404 }
405}
406
407impl FromStr for FederationId {
408 type Err = anyhow::Error;
409
410 fn from_str(s: &str) -> Result<Self, Self::Err> {
411 Ok(Self::from_byte_array(<[u8; 32]>::from_hex(s)?))
412 }
413}
414
415impl ClientConfig {
416 pub fn consensus_hash(&self) -> sha256::Hash {
418 let mut engine = HashEngine::default();
419 self.consensus_encode(&mut engine)
420 .expect("Consensus hashing should never fail");
421 sha256::Hash::from_engine(engine)
422 }
423
424 pub fn get_module<T: Decodable + 'static>(&self, id: ModuleInstanceId) -> anyhow::Result<&T> {
425 self.modules.get(&id).map_or_else(
426 || Err(format_err!("Client config for module id {id} not found")),
427 |client_cfg| client_cfg.cast(),
428 )
429 }
430
431 pub fn get_module_cfg(&self, id: ModuleInstanceId) -> anyhow::Result<ClientModuleConfig> {
433 self.modules.get(&id).map_or_else(
434 || Err(format_err!("Client config for module id {id} not found")),
435 |client_cfg| Ok(client_cfg.clone()),
436 )
437 }
438
439 pub fn get_first_module_by_kind<T: Decodable + 'static>(
447 &self,
448 kind: impl Into<ModuleKind>,
449 ) -> anyhow::Result<(ModuleInstanceId, &T)> {
450 let kind: ModuleKind = kind.into();
451 let Some((id, module_cfg)) = self.modules.iter().find(|(_, v)| v.is_kind(&kind)) else {
452 anyhow::bail!("Module kind {kind} not found")
453 };
454 Ok((*id, module_cfg.cast()?))
455 }
456
457 pub fn get_first_module_by_kind_cfg(
459 &self,
460 kind: impl Into<ModuleKind>,
461 ) -> anyhow::Result<(ModuleInstanceId, ClientModuleConfig)> {
462 let kind: ModuleKind = kind.into();
463 self.modules
464 .iter()
465 .find(|(_, v)| v.is_kind(&kind))
466 .map(|(id, v)| (*id, v.clone()))
467 .ok_or_else(|| anyhow::format_err!("Module kind {kind} not found"))
468 }
469}
470
471#[derive(Clone, Debug)]
472pub struct ModuleInitRegistry<M>(BTreeMap<ModuleKind, M>);
473
474impl<M> ModuleInitRegistry<M> {
475 pub fn iter(&self) -> impl Iterator<Item = (&ModuleKind, &M)> {
476 self.0.iter()
477 }
478}
479
480impl<M> Default for ModuleInitRegistry<M> {
481 fn default() -> Self {
482 Self(BTreeMap::new())
483 }
484}
485
486#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
489pub struct ConfigGenModuleParams {
490 pub local: serde_json::Value,
491 pub consensus: serde_json::Value,
492}
493
494impl ConfigGenModuleParams {
495 pub fn new(local: serde_json::Value, consensus: serde_json::Value) -> Self {
496 Self { local, consensus }
497 }
498
499 pub fn to_typed<P: ModuleInitParams>(&self) -> anyhow::Result<P> {
502 Ok(P::from_parts(
503 Self::parse("local", self.local.clone())?,
504 Self::parse("consensus", self.consensus.clone())?,
505 ))
506 }
507
508 fn parse<P: DeserializeOwned>(name: &str, json: serde_json::Value) -> anyhow::Result<P> {
509 serde_json::from_value(json).with_context(|| format!("Schema mismatch for {name} argument"))
510 }
511
512 pub fn from_typed<P: ModuleInitParams>(p: P) -> anyhow::Result<Self> {
513 let (local, consensus) = p.to_parts();
514 Ok(Self {
515 local: serde_json::to_value(local)?,
516 consensus: serde_json::to_value(consensus)?,
517 })
518 }
519}
520
521pub type CommonModuleInitRegistry = ModuleInitRegistry<DynCommonModuleInit>;
522
523pub type ServerModuleConfigGenParamsRegistry = ModuleRegistry<ConfigGenModuleParams>;
525
526impl Eq for ServerModuleConfigGenParamsRegistry {}
527
528impl PartialEq for ServerModuleConfigGenParamsRegistry {
529 fn eq(&self, other: &Self) -> bool {
530 self.iter_modules().eq(other.iter_modules())
531 }
532}
533
534impl Serialize for ServerModuleConfigGenParamsRegistry {
535 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
536 let modules: Vec<_> = self.iter_modules().collect();
537 let mut serializer = serializer.serialize_map(Some(modules.len()))?;
538 for (id, kind, params) in modules {
539 serializer.serialize_key(&id)?;
540 serializer.serialize_value(&(kind.clone(), params.clone()))?;
541 }
542 serializer.end()
543 }
544}
545
546impl<'de> Deserialize<'de> for ServerModuleConfigGenParamsRegistry {
547 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
548 where
549 D: Deserializer<'de>,
550 {
551 let json: BTreeMap<ModuleInstanceId, (ModuleKind, ConfigGenModuleParams)> =
552 Deserialize::deserialize(deserializer)?;
553 let mut params = BTreeMap::new();
554
555 for (id, (kind, module)) in json {
556 params.insert(id, (kind, module));
557 }
558 Ok(Self::from(params))
559 }
560}
561
562impl<M> From<Vec<M>> for ModuleInitRegistry<M>
563where
564 M: AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static>,
565{
566 fn from(value: Vec<M>) -> Self {
567 Self(
568 value
569 .into_iter()
570 .map(|i| (i.as_ref().module_kind(), i))
571 .collect::<BTreeMap<_, _>>(),
572 )
573 }
574}
575
576impl<M> FromIterator<M> for ModuleInitRegistry<M>
577where
578 M: AsRef<maybe_add_send_sync!(dyn IDynCommonModuleInit + 'static)>,
579{
580 fn from_iter<T: IntoIterator<Item = M>>(iter: T) -> Self {
581 Self(
582 iter.into_iter()
583 .map(|i| (i.as_ref().module_kind(), i))
584 .collect::<BTreeMap<_, _>>(),
585 )
586 }
587}
588
589impl<M> ModuleInitRegistry<M> {
590 pub fn new() -> Self {
591 Self::default()
592 }
593
594 pub fn attach<T>(&mut self, r#gen: T)
595 where
596 T: Into<M> + 'static + Send + Sync,
597 M: AsRef<dyn IDynCommonModuleInit + 'static + Send + Sync>,
598 {
599 let r#gen: M = r#gen.into();
600 let kind = r#gen.as_ref().module_kind();
601 assert!(
602 self.0.insert(kind.clone(), r#gen).is_none(),
603 "Can't insert module of same kind twice: {kind}"
604 );
605 }
606
607 pub fn kinds(&self) -> BTreeSet<ModuleKind> {
608 self.0.keys().cloned().collect()
609 }
610
611 pub fn get(&self, k: &ModuleKind) -> Option<&M> {
612 self.0.get(k)
613 }
614}
615
616impl ModuleRegistry<ConfigGenModuleParams> {
617 pub fn attach_config_gen_params_by_id<T: ModuleInitParams>(
618 &mut self,
619 id: ModuleInstanceId,
620 kind: ModuleKind,
621 r#gen: T,
622 ) -> &mut Self {
623 let params = ConfigGenModuleParams::from_typed(r#gen)
624 .unwrap_or_else(|err| panic!("Invalid config gen params for {kind}: {err}"));
625 self.register_module(id, kind, params);
626 self
627 }
628
629 pub fn attach_config_gen_params<T: ModuleInitParams>(
630 &mut self,
631 kind: ModuleKind,
632 r#gen: T,
633 ) -> &mut Self {
634 let params = ConfigGenModuleParams::from_typed(r#gen)
635 .unwrap_or_else(|err| panic!("Invalid config gen params for {kind}: {err}"));
636 self.append_module(kind, params);
637 self
638 }
639}
640
641impl<M> ModuleInitRegistry<M>
642where
643 M: AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static>,
644{
645 #[deprecated(
646 note = "You probably want `available_decoders` to support missing module kinds. If you really want a strict behavior, use `decoders_strict`"
647 )]
648 pub fn decoders<'a>(
649 &self,
650 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
651 ) -> anyhow::Result<ModuleDecoderRegistry> {
652 self.decoders_strict(modules)
653 }
654
655 pub fn decoders_strict<'a>(
657 &self,
658 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
659 ) -> anyhow::Result<ModuleDecoderRegistry> {
660 let mut decoders = BTreeMap::new();
661 for (id, kind) in modules {
662 let Some(init) = self.0.get(kind) else {
663 anyhow::bail!(
664 "Detected configuration for unsupported module id: {id}, kind: {kind}"
665 )
666 };
667
668 decoders.insert(id, (kind.clone(), init.as_ref().decoder()));
669 }
670 Ok(ModuleDecoderRegistry::from(decoders))
671 }
672
673 pub fn available_decoders<'a>(
675 &self,
676 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
677 ) -> anyhow::Result<ModuleDecoderRegistry> {
678 let mut decoders = BTreeMap::new();
679 for (id, kind) in modules {
680 let Some(init) = self.0.get(kind) else {
681 warn!(target: LOG_CORE, "Unsupported module id: {id}, kind: {kind}");
682 continue;
683 };
684
685 decoders.insert(id, (kind.clone(), init.as_ref().decoder()));
686 }
687 Ok(ModuleDecoderRegistry::from(decoders))
688 }
689}
690
691#[derive(Debug, Default, Clone, Serialize, Deserialize)]
693pub struct EmptyGenParams {}
694
695pub trait ModuleInitParams: serde::Serialize + serde::de::DeserializeOwned {
696 type Local: DeserializeOwned + Serialize;
698 type Consensus: DeserializeOwned + Serialize;
700
701 fn from_parts(local: Self::Local, consensus: Self::Consensus) -> Self;
703
704 fn to_parts(self) -> (Self::Local, Self::Consensus);
706}
707
708#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
709pub struct ServerModuleConsensusConfig {
710 pub kind: ModuleKind,
711 pub version: ModuleConsensusVersion,
712 #[serde(with = "::hex::serde")]
713 pub config: Vec<u8>,
714}
715
716#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
722pub struct ClientModuleConfig {
723 pub kind: ModuleKind,
724 pub version: ModuleConsensusVersion,
725 #[serde(with = "::fedimint_core::encoding::as_hex")]
726 pub config: DynRawFallback<DynClientConfig>,
727}
728
729impl ClientModuleConfig {
730 pub fn from_typed<T: fedimint_core::core::ClientConfig>(
731 module_instance_id: ModuleInstanceId,
732 kind: ModuleKind,
733 version: ModuleConsensusVersion,
734 value: T,
735 ) -> anyhow::Result<Self> {
736 Ok(Self {
737 kind,
738 version,
739 config: fedimint_core::core::DynClientConfig::from_typed(module_instance_id, value)
740 .into(),
741 })
742 }
743
744 pub fn redecode_raw(
745 self,
746 modules: &ModuleDecoderRegistry,
747 ) -> Result<Self, crate::encoding::DecodeError> {
748 Ok(Self {
749 config: self.config.redecode_raw(modules)?,
750 ..self
751 })
752 }
753
754 pub fn is_kind(&self, kind: &ModuleKind) -> bool {
755 &self.kind == kind
756 }
757
758 pub fn kind(&self) -> &ModuleKind {
759 &self.kind
760 }
761}
762
763impl ClientModuleConfig {
764 pub fn cast<T>(&self) -> anyhow::Result<&T>
765 where
766 T: 'static,
767 {
768 self.config
769 .expect_decoded_ref()
770 .as_any()
771 .downcast_ref::<T>()
772 .context("can't convert client module config to desired type")
773 }
774}
775
776#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
780pub struct ServerModuleConfig {
781 pub private: JsonWithKind,
782 pub consensus: ServerModuleConsensusConfig,
783}
784
785impl ServerModuleConfig {
786 pub fn from(private: JsonWithKind, consensus: ServerModuleConsensusConfig) -> Self {
787 Self { private, consensus }
788 }
789
790 pub fn to_typed<T: TypedServerModuleConfig>(&self) -> anyhow::Result<T> {
791 let private = serde_json::from_value(self.private.value().clone())?;
792 let consensus = <T::Consensus>::consensus_decode_whole(
793 &self.consensus.config[..],
794 &ModuleRegistry::default(),
795 )?;
796
797 Ok(TypedServerModuleConfig::from_parts(private, consensus))
798 }
799}
800
801pub trait TypedServerModuleConsensusConfig:
803 DeserializeOwned + Serialize + Encodable + Decodable
804{
805 fn kind(&self) -> ModuleKind;
806
807 fn version(&self) -> ModuleConsensusVersion;
808
809 fn from_erased(erased: &ServerModuleConsensusConfig) -> anyhow::Result<Self> {
810 Ok(Self::consensus_decode_whole(
811 &erased.config[..],
812 &ModuleRegistry::default(),
813 )?)
814 }
815}
816
817pub trait TypedServerModuleConfig: DeserializeOwned + Serialize {
819 type Private: DeserializeOwned + Serialize;
822 type Consensus: TypedServerModuleConsensusConfig;
824
825 fn from_parts(private: Self::Private, consensus: Self::Consensus) -> Self;
827
828 fn to_parts(self) -> (ModuleKind, Self::Private, Self::Consensus);
830
831 fn to_erased(self) -> ServerModuleConfig {
833 let (kind, private, consensus) = self.to_parts();
834
835 ServerModuleConfig {
836 private: JsonWithKind::new(
837 kind,
838 serde_json::to_value(private).expect("serialization can't fail"),
839 ),
840 consensus: ServerModuleConsensusConfig {
841 kind: consensus.kind(),
842 version: consensus.version(),
843 config: consensus.consensus_encode_to_vec(),
844 },
845 }
846 }
847}
848
849#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encodable, Decodable)]
850pub enum P2PMessage {
851 Aleph(Vec<u8>),
852 Checksum(sha256::Hash),
853 Dkg(DkgMessage),
854 Encodable(Vec<u8>),
855}
856
857#[derive(Debug, PartialEq, Eq, Clone, Encodable, Decodable)]
858pub enum DkgMessage {
859 Hash(sha256::Hash),
860 Commitment(Vec<(G1Projective, G2Projective)>),
861 Share(Scalar),
862}
863
864impl Serialize for DkgMessage {
867 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
868 where
869 S: Serializer,
870 {
871 self.consensus_encode_to_hex().serialize(serializer)
872 }
873}
874
875impl<'de> Deserialize<'de> for DkgMessage {
876 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
877 where
878 D: Deserializer<'de>,
879 {
880 Self::consensus_decode_hex(
881 &String::deserialize(deserializer)?,
882 &ModuleDecoderRegistry::default(),
883 )
884 .map_err(serde::de::Error::custom)
885 }
886}
887
888pub const META_FEDERATION_NAME_KEY: &str = "federation_name";
891
892pub fn load_from_file<T: DeserializeOwned>(path: &Path) -> Result<T, anyhow::Error> {
893 let file = std::fs::File::open(path)?;
894 Ok(serde_json::from_reader(file)?)
895}
896
897#[cfg(test)]
898mod tests;