1#[cfg(feature = "uniffi")]
2use std::collections::HashMap;
3use std::collections::{BTreeMap, BTreeSet};
4use std::fmt::{Debug, Display};
5use std::hash::Hash;
6use std::path::Path;
7use std::str::FromStr;
8
9use anyhow::{Context, format_err};
10use bitcoin::hashes::sha256::HashEngine;
11use bitcoin::hashes::{Hash as BitcoinHash, hex, sha256};
12use bls12_381::Scalar;
13use fedimint_core::core::{ModuleInstanceId, ModuleKind};
14use fedimint_core::encoding::{DynRawFallback, Encodable};
15use fedimint_core::module::registry::ModuleRegistry;
16use fedimint_core::util::SafeUrl;
17use fedimint_core::{ModuleDecoderRegistry, format_hex};
18use fedimint_logging::LOG_CORE;
19use hex::FromHex;
20use secp256k1::PublicKey;
21use serde::de::DeserializeOwned;
22use serde::{Deserialize, Deserializer, Serialize, Serializer};
23use serde_json::json;
24use threshold_crypto::{G1Projective, G2Projective};
25use tracing::warn;
26
27use crate::core::DynClientConfig;
28use crate::encoding::Decodable;
29use crate::module::{
30 CoreConsensusVersion, DynCommonModuleInit, IDynCommonModuleInit, ModuleConsensusVersion,
31 SerdeModuleEncoding,
32};
33use crate::session_outcome::SignedSessionOutcome;
34use crate::{PeerId, maybe_add_send_sync, secp256k1};
35
36pub const ALEPH_BFT_UNIT_BYTE_LIMIT: usize = 50_000;
39
40#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
46pub struct JsonWithKind {
47 kind: ModuleKind,
48 #[serde(flatten)]
49 value: serde_json::Value,
50}
51
52impl JsonWithKind {
53 pub fn new(kind: ModuleKind, value: serde_json::Value) -> Self {
54 Self { kind, value }
55 }
56
57 pub fn with_fixed_empty_value(self) -> Self {
78 if let serde_json::Value::Object(ref o) = self.value
79 && o.is_empty()
80 {
81 return Self {
82 kind: self.kind,
83 value: serde_json::Value::Null,
84 };
85 }
86
87 self
88 }
89
90 pub fn value(&self) -> &serde_json::Value {
91 &self.value
92 }
93
94 pub fn kind(&self) -> &ModuleKind {
95 &self.kind
96 }
97
98 pub fn is_kind(&self, kind: &ModuleKind) -> bool {
99 &self.kind == kind
100 }
101}
102
103#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Encodable, Decodable)]
104#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
105pub struct PeerUrl {
106 pub url: SafeUrl,
108 pub name: String,
110}
111
112#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
116pub struct ClientConfigV0 {
117 #[serde(flatten)]
118 pub global: GlobalClientConfigV0,
119 #[serde(deserialize_with = "de_int_key")]
120 pub modules: BTreeMap<ModuleInstanceId, ClientModuleConfig>,
121}
122
123#[cfg(feature = "uniffi")]
128type ClientModulesMap = BTreeMap<ModuleInstanceId, ClientModuleConfig>;
129
130#[cfg(feature = "uniffi")]
131uniffi::custom_type!(ClientModulesMap, HashMap<ModuleInstanceId, ClientModuleConfig>, {
132 remote,
133 lower: |m| m.into_iter().collect(),
134 try_lift: |h| Ok(h.into_iter().collect()),
135});
136
137#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
141#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
142pub struct ClientConfig {
143 #[serde(flatten)]
144 pub global: GlobalClientConfig,
145 #[serde(deserialize_with = "de_int_key")]
146 pub modules: BTreeMap<ModuleInstanceId, ClientModuleConfig>,
147}
148
149#[cfg(feature = "uniffi")]
150uniffi::custom_type!(PublicKey, String, {
151 remote,
152 lower: |pk| pk.to_string(),
153 try_lift: |s| PublicKey::from_str(&s).map_err(|e| anyhow::anyhow!(e)),
154});
155
156fn de_int_key<'de, D, K, V>(deserializer: D) -> Result<BTreeMap<K, V>, D::Error>
158where
159 D: Deserializer<'de>,
160 K: Eq + Ord + FromStr,
161 K::Err: Display,
162 V: Deserialize<'de>,
163{
164 let string_map = <BTreeMap<String, V>>::deserialize(deserializer)?;
165 let map = string_map
166 .into_iter()
167 .map(|(key_str, value)| {
168 let key = K::from_str(&key_str).map_err(serde::de::Error::custom)?;
169 Ok((key, value))
170 })
171 .collect::<Result<BTreeMap<_, _>, _>>()?;
172 Ok(map)
173}
174
175fn optional_de_int_key<'de, D, K, V>(deserializer: D) -> Result<Option<BTreeMap<K, V>>, D::Error>
176where
177 D: Deserializer<'de>,
178 K: Eq + Ord + FromStr,
179 K::Err: Display,
180 V: Deserialize<'de>,
181{
182 let Some(string_map) = <Option<BTreeMap<String, V>>>::deserialize(deserializer)? else {
183 return Ok(None);
184 };
185
186 let map = string_map
187 .into_iter()
188 .map(|(key_str, value)| {
189 let key = K::from_str(&key_str).map_err(serde::de::Error::custom)?;
190 Ok((key, value))
191 })
192 .collect::<Result<BTreeMap<_, _>, _>>()?;
193
194 Ok(Some(map))
195}
196
197#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
200pub struct JsonClientConfig {
201 pub global: GlobalClientConfig,
202 pub modules: BTreeMap<ModuleInstanceId, JsonWithKind>,
203}
204
205#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
207pub struct GlobalClientConfigV0 {
208 #[serde(deserialize_with = "de_int_key")]
210 pub api_endpoints: BTreeMap<PeerId, PeerUrl>,
211 pub consensus_version: CoreConsensusVersion,
213 pub meta: BTreeMap<String, String>,
216}
217
218#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
220#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
221pub struct GlobalClientConfig {
222 #[serde(deserialize_with = "de_int_key")]
224 pub api_endpoints: BTreeMap<PeerId, PeerUrl>,
225 #[serde(default, deserialize_with = "optional_de_int_key")]
228 pub broadcast_public_keys: Option<BTreeMap<PeerId, PublicKey>>,
229 pub consensus_version: CoreConsensusVersion,
231 pub meta: BTreeMap<String, String>,
234}
235
236#[cfg(feature = "uniffi")]
241type ApiEndpointsMap = BTreeMap<PeerId, PeerUrl>;
242#[cfg(feature = "uniffi")]
243type BroadcastPublicKeysMap = BTreeMap<PeerId, PublicKey>;
244#[cfg(feature = "uniffi")]
245type MetaMap = BTreeMap<String, String>;
246
247#[cfg(feature = "uniffi")]
248uniffi::custom_type!(ApiEndpointsMap, HashMap<PeerId, PeerUrl>, {
249 remote,
250 lower: |m| m.into_iter().collect(),
251 try_lift: |h| Ok(h.into_iter().collect()),
252});
253
254#[cfg(feature = "uniffi")]
255uniffi::custom_type!(BroadcastPublicKeysMap, HashMap<PeerId, PublicKey>, {
256 remote,
257 lower: |m| m.into_iter().collect(),
258 try_lift: |h| Ok(h.into_iter().collect()),
259});
260
261#[cfg(feature = "uniffi")]
262uniffi::custom_type!(MetaMap, HashMap<String, String>, {
263 remote,
264 lower: |m| m.into_iter().collect(),
265 try_lift: |h| Ok(h.into_iter().collect()),
266});
267
268impl GlobalClientConfig {
269 pub fn calculate_federation_id(&self) -> FederationId {
272 FederationId(self.api_endpoints.consensus_hash())
273 }
274
275 pub fn federation_name(&self) -> Option<&str> {
277 self.meta.get(META_FEDERATION_NAME_KEY).map(|x| &**x)
278 }
279}
280
281impl ClientConfig {
282 pub fn redecode_raw(
284 self,
285 modules: &ModuleDecoderRegistry,
286 ) -> Result<Self, crate::encoding::DecodeError> {
287 Ok(Self {
288 modules: self
289 .modules
290 .into_iter()
291 .map(|(module_id, v)| {
292 let kind = v.kind.clone();
295
296 v.redecode_raw(modules)
297 .context(format!("redecode_raw: instance: {module_id}, kind: {kind}"))
298 .map(|v| (module_id, v))
299 })
300 .collect::<Result<_, _>>()?,
301 ..self
302 })
303 }
304
305 pub fn calculate_federation_id(&self) -> FederationId {
306 self.global.calculate_federation_id()
307 }
308
309 pub fn meta<V: serde::de::DeserializeOwned + 'static>(
311 &self,
312 key: &str,
313 ) -> Result<Option<V>, anyhow::Error> {
314 let Some(str_value) = self.global.meta.get(key) else {
315 return Ok(None);
316 };
317 let res = serde_json::from_str(str_value)
318 .map(Some)
319 .context(format!("Decoding meta field '{key}' failed"));
320
321 if res.is_err() && std::any::TypeId::of::<V>() == std::any::TypeId::of::<String>() {
325 let string_ret = Box::new(str_value.clone());
326 let ret = unsafe {
327 std::mem::transmute::<Box<String>, Box<V>>(string_ret)
329 };
330 Ok(Some(*ret))
331 } else {
332 res
333 }
334 }
335
336 pub fn to_json(&self) -> JsonClientConfig {
342 JsonClientConfig {
343 global: self.global.clone(),
344 modules: self
345 .modules
346 .iter()
347 .map(|(&module_instance_id, module_config)| {
348 let module_config_json = JsonWithKind {
349 kind: module_config.kind.clone(),
350 value: module_config.config
351 .clone()
352 .decoded()
353 .and_then(|dyn_cfg| dyn_cfg.to_json())
354 .unwrap_or_else(|| json!({
355 "unknown_module_hex": module_config.config.consensus_encode_to_hex()
356 })),
357 };
358 (module_instance_id, module_config_json)
359 })
360 .collect(),
361 }
362 }
363}
364
365#[derive(
371 Debug,
372 Copy,
373 Serialize,
374 Deserialize,
375 Clone,
376 Eq,
377 Hash,
378 PartialEq,
379 Encodable,
380 Decodable,
381 Ord,
382 PartialOrd,
383)]
384pub struct FederationId(pub sha256::Hash);
385
386#[cfg(feature = "uniffi")]
387uniffi::custom_type!(FederationId, String, {
388 lower: |obj| obj.to_string(),
389 try_lift: |bytes| {
390 let obj: FederationId = bytes.parse().map_err(|e| anyhow::anyhow!("Failed to parse FederationId from string: {e}"))?;
391 Ok(obj)
392 },
393});
394
395#[derive(
396 Debug,
397 Copy,
398 Serialize,
399 Deserialize,
400 Clone,
401 Eq,
402 Hash,
403 PartialEq,
404 Encodable,
405 Decodable,
406 Ord,
407 PartialOrd,
408)]
409pub struct FederationIdPrefix([u8; 4]);
415
416impl Display for FederationIdPrefix {
417 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
418 format_hex(&self.0, f)
419 }
420}
421
422impl Display for FederationId {
423 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
424 format_hex(&self.0.to_byte_array(), f)
425 }
426}
427
428impl FromStr for FederationIdPrefix {
429 type Err = anyhow::Error;
430
431 fn from_str(s: &str) -> Result<Self, Self::Err> {
432 Ok(Self(<[u8; 4]>::from_hex(s)?))
433 }
434}
435
436impl FederationIdPrefix {
437 pub fn to_bytes(&self) -> Vec<u8> {
438 self.0.to_vec()
439 }
440}
441
442impl FederationId {
444 pub fn dummy() -> Self {
446 Self(sha256::Hash::from_byte_array([42; 32]))
447 }
448
449 pub(crate) fn from_byte_array(bytes: [u8; 32]) -> Self {
450 Self(sha256::Hash::from_byte_array(bytes))
451 }
452
453 pub fn to_prefix(&self) -> FederationIdPrefix {
454 FederationIdPrefix(self.0[..4].try_into().expect("can't fail"))
455 }
456
457 pub fn to_fake_ln_pub_key(
467 &self,
468 secp: &bitcoin::secp256k1::Secp256k1<bitcoin::secp256k1::All>,
469 ) -> anyhow::Result<bitcoin::secp256k1::PublicKey> {
470 let sk = bitcoin::secp256k1::SecretKey::from_slice(&self.0.to_byte_array())?;
471 Ok(bitcoin::secp256k1::PublicKey::from_secret_key(secp, &sk))
472 }
473}
474
475impl FromStr for FederationId {
476 type Err = anyhow::Error;
477
478 fn from_str(s: &str) -> Result<Self, Self::Err> {
479 Ok(Self::from_byte_array(<[u8; 32]>::from_hex(s)?))
480 }
481}
482
483impl ClientConfig {
484 pub fn consensus_hash(&self) -> sha256::Hash {
486 let mut engine = HashEngine::default();
487 self.consensus_encode(&mut engine)
488 .expect("Consensus hashing should never fail");
489 sha256::Hash::from_engine(engine)
490 }
491
492 pub fn get_module<T: Decodable + 'static>(&self, id: ModuleInstanceId) -> anyhow::Result<&T> {
493 self.modules.get(&id).map_or_else(
494 || Err(format_err!("Client config for module id {id} not found")),
495 |client_cfg| client_cfg.cast(),
496 )
497 }
498
499 pub fn get_module_cfg(&self, id: ModuleInstanceId) -> anyhow::Result<ClientModuleConfig> {
501 self.modules.get(&id).map_or_else(
502 || Err(format_err!("Client config for module id {id} not found")),
503 |client_cfg| Ok(client_cfg.clone()),
504 )
505 }
506
507 pub fn get_first_module_by_kind<T: Decodable + 'static>(
515 &self,
516 kind: impl Into<ModuleKind>,
517 ) -> anyhow::Result<(ModuleInstanceId, &T)> {
518 let kind: ModuleKind = kind.into();
519 let Some((id, module_cfg)) = self.modules.iter().find(|(_, v)| v.is_kind(&kind)) else {
520 anyhow::bail!("Module kind {kind} not found")
521 };
522 Ok((*id, module_cfg.cast()?))
523 }
524
525 pub fn get_first_module_by_kind_cfg(
527 &self,
528 kind: impl Into<ModuleKind>,
529 ) -> anyhow::Result<(ModuleInstanceId, ClientModuleConfig)> {
530 let kind: ModuleKind = kind.into();
531 self.modules
532 .iter()
533 .find(|(_, v)| v.is_kind(&kind))
534 .map(|(id, v)| (*id, v.clone()))
535 .ok_or_else(|| anyhow::format_err!("Module kind {kind} not found"))
536 }
537}
538
539#[derive(Clone, Debug)]
540pub struct ModuleInitRegistry<M>(BTreeMap<ModuleKind, M>);
541
542const LEGACY_MODULE_ORDER: &[&str] = &["ln", "mint", "wallet", "lnv2", "meta", "unknown"];
545
546impl<M> ModuleInitRegistry<M> {
547 pub fn iter(&self) -> impl Iterator<Item = (&ModuleKind, &M)> {
548 self.0.iter()
549 }
550
551 pub fn iter_legacy_order(&self) -> Vec<(&ModuleKind, &M)> {
555 let mut ordered: Vec<(&ModuleKind, &M)> = Vec::new();
556
557 for kind_str in LEGACY_MODULE_ORDER {
559 let kind = ModuleKind::from_static_str(kind_str);
560 if let Some((k, m)) = self.0.get_key_value(&kind) {
561 ordered.push((k, m));
562 }
563 }
564
565 for (kind, module) in &self.0 {
567 if !LEGACY_MODULE_ORDER.contains(&kind.as_str()) {
568 ordered.push((kind, module));
569 }
570 }
571
572 ordered
573 }
574}
575
576impl<M> Default for ModuleInitRegistry<M> {
577 fn default() -> Self {
578 Self(BTreeMap::new())
579 }
580}
581
582pub type CommonModuleInitRegistry = ModuleInitRegistry<DynCommonModuleInit>;
583
584impl<M> From<Vec<M>> for ModuleInitRegistry<M>
585where
586 M: AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static>,
587{
588 fn from(value: Vec<M>) -> Self {
589 Self(
590 value
591 .into_iter()
592 .map(|i| (i.as_ref().module_kind(), i))
593 .collect::<BTreeMap<_, _>>(),
594 )
595 }
596}
597
598impl<M> FromIterator<M> for ModuleInitRegistry<M>
599where
600 M: AsRef<maybe_add_send_sync!(dyn IDynCommonModuleInit + 'static)>,
601{
602 fn from_iter<T: IntoIterator<Item = M>>(iter: T) -> Self {
603 Self(
604 iter.into_iter()
605 .map(|i| (i.as_ref().module_kind(), i))
606 .collect::<BTreeMap<_, _>>(),
607 )
608 }
609}
610
611impl<M> ModuleInitRegistry<M> {
612 pub fn new() -> Self {
613 Self::default()
614 }
615
616 pub fn attach<T>(&mut self, r#gen: T)
617 where
618 T: Into<M> + 'static + Send + Sync,
619 M: AsRef<dyn IDynCommonModuleInit + 'static + Send + Sync>,
620 {
621 let r#gen: M = r#gen.into();
622 let kind = r#gen.as_ref().module_kind();
623 assert!(
624 self.0.insert(kind.clone(), r#gen).is_none(),
625 "Can't insert module of same kind twice: {kind}"
626 );
627 }
628
629 pub fn kinds(&self) -> BTreeSet<ModuleKind> {
630 self.0.keys().cloned().collect()
631 }
632
633 pub fn get(&self, k: &ModuleKind) -> Option<&M> {
634 self.0.get(k)
635 }
636}
637
638impl<M> ModuleInitRegistry<M>
639where
640 M: AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static>,
641{
642 #[deprecated(
643 note = "You probably want `available_decoders` to support missing module kinds. If you really want a strict behavior, use `decoders_strict`"
644 )]
645 pub fn decoders<'a>(
646 &self,
647 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
648 ) -> anyhow::Result<ModuleDecoderRegistry> {
649 self.decoders_strict(modules)
650 }
651
652 pub fn decoders_strict<'a>(
654 &self,
655 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
656 ) -> anyhow::Result<ModuleDecoderRegistry> {
657 let mut decoders = BTreeMap::new();
658 for (id, kind) in modules {
659 let Some(init) = self.0.get(kind) else {
660 anyhow::bail!(
661 "Detected configuration for unsupported module id: {id}, kind: {kind}"
662 )
663 };
664
665 decoders.insert(id, (kind.clone(), init.as_ref().decoder()));
666 }
667 Ok(ModuleDecoderRegistry::from(decoders))
668 }
669
670 pub fn available_decoders<'a>(
672 &self,
673 modules: impl Iterator<Item = (ModuleInstanceId, &'a ModuleKind)>,
674 ) -> anyhow::Result<ModuleDecoderRegistry> {
675 let mut decoders = BTreeMap::new();
676 for (id, kind) in modules {
677 let Some(init) = self.0.get(kind) else {
678 warn!(target: LOG_CORE, "Unsupported module id: {id}, kind: {kind}");
679 continue;
680 };
681
682 decoders.insert(id, (kind.clone(), init.as_ref().decoder()));
683 }
684 Ok(ModuleDecoderRegistry::from(decoders))
685 }
686}
687
688#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
689pub struct ServerModuleConsensusConfig {
690 pub kind: ModuleKind,
691 pub version: ModuleConsensusVersion,
692 #[serde(with = "::hex::serde")]
693 pub config: Vec<u8>,
694}
695
696#[cfg(feature = "uniffi")]
703type ClientModuleConfigRaw = DynRawFallback<DynClientConfig>;
704
705#[cfg(feature = "uniffi")]
706uniffi::custom_type!(ClientModuleConfigRaw, String, {
707 lower: |v| v.consensus_encode_to_hex(),
708 try_lift: |s| {
709 ClientModuleConfigRaw::consensus_decode_hex(&s, &ModuleDecoderRegistry::default())
710 .map_err(|e| anyhow::anyhow!("Failed to decode client module config: {e}"))
711 },
712});
713
714#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encodable, Decodable)]
720#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
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 private: JsonWithKind,
781 pub consensus: ServerModuleConsensusConfig,
782}
783
784impl ServerModuleConfig {
785 pub fn from(private: JsonWithKind, consensus: ServerModuleConsensusConfig) -> Self {
786 Self { private, consensus }
787 }
788
789 pub fn to_typed<T: TypedServerModuleConfig>(&self) -> anyhow::Result<T> {
790 let private = serde_json::from_value(self.private.value().clone())?;
791 let consensus = <T::Consensus>::consensus_decode_whole(
792 &self.consensus.config[..],
793 &ModuleRegistry::default(),
794 )?;
795
796 Ok(TypedServerModuleConfig::from_parts(private, consensus))
797 }
798}
799
800pub trait TypedServerModuleConsensusConfig:
802 DeserializeOwned + Serialize + Encodable + Decodable
803{
804 fn kind(&self) -> ModuleKind;
805
806 fn version(&self) -> ModuleConsensusVersion;
807
808 fn from_erased(erased: &ServerModuleConsensusConfig) -> anyhow::Result<Self> {
809 Ok(Self::consensus_decode_whole(
810 &erased.config[..],
811 &ModuleRegistry::default(),
812 )?)
813 }
814}
815
816pub trait TypedServerModuleConfig: DeserializeOwned + Serialize {
818 type Private: DeserializeOwned + Serialize;
821 type Consensus: TypedServerModuleConsensusConfig;
823
824 fn from_parts(private: Self::Private, consensus: Self::Consensus) -> Self;
826
827 fn to_parts(self) -> (ModuleKind, Self::Private, Self::Consensus);
829
830 fn to_erased(self) -> ServerModuleConfig {
832 let (kind, private, consensus) = self.to_parts();
833
834 ServerModuleConfig {
835 private: JsonWithKind::new(
836 kind,
837 serde_json::to_value(private).expect("serialization can't fail"),
838 ),
839 consensus: ServerModuleConsensusConfig {
840 kind: consensus.kind(),
841 version: consensus.version(),
842 config: consensus.consensus_encode_to_vec(),
843 },
844 }
845 }
846}
847
848#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encodable, Decodable)]
849pub enum P2PMessage {
850 Aleph(Vec<u8>),
851 SessionSignature(secp256k1::schnorr::Signature),
852 SessionIndex(u64),
853 SignedSessionOutcome(SerdeModuleEncoding<SignedSessionOutcome>),
854 Checksum(sha256::Hash),
855 DkgG1(DkgMessageG1),
856 DkgG2(DkgMessageG2),
857 Encodable(Vec<u8>),
858 #[encodable_default]
859 Default {
860 variant: u64,
861 bytes: Vec<u8>,
862 },
863}
864
865#[derive(Debug, PartialEq, Eq, Clone, Encodable, Decodable)]
866pub enum DkgMessageG1 {
867 Hash(sha256::Hash),
868 Commitment(Vec<G1Projective>),
869 Share(Scalar),
870}
871
872#[derive(Debug, PartialEq, Eq, Clone, Encodable, Decodable)]
873pub enum DkgMessageG2 {
874 Hash(sha256::Hash),
875 Commitment(Vec<G2Projective>),
876 Share(Scalar),
877}
878
879impl Serialize for DkgMessageG1 {
882 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
883 where
884 S: Serializer,
885 {
886 self.consensus_encode_to_hex().serialize(serializer)
887 }
888}
889
890impl<'de> Deserialize<'de> for DkgMessageG1 {
891 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
892 where
893 D: Deserializer<'de>,
894 {
895 Self::consensus_decode_hex(
896 &String::deserialize(deserializer)?,
897 &ModuleDecoderRegistry::default(),
898 )
899 .map_err(serde::de::Error::custom)
900 }
901}
902
903impl Serialize for DkgMessageG2 {
906 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
907 where
908 S: Serializer,
909 {
910 self.consensus_encode_to_hex().serialize(serializer)
911 }
912}
913
914impl<'de> Deserialize<'de> for DkgMessageG2 {
915 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
916 where
917 D: Deserializer<'de>,
918 {
919 Self::consensus_decode_hex(
920 &String::deserialize(deserializer)?,
921 &ModuleDecoderRegistry::default(),
922 )
923 .map_err(serde::de::Error::custom)
924 }
925}
926
927pub const META_FEDERATION_NAME_KEY: &str = "federation_name";
930
931pub fn load_from_file<T: DeserializeOwned>(path: &Path) -> Result<T, anyhow::Error> {
932 let file = std::fs::File::open(path)?;
933 Ok(serde_json::from_reader(file)?)
934}
935
936#[cfg(test)]
937mod tests;