1use core::fmt;
8use std::any::{Any, TypeId};
9use std::borrow::Cow;
10use std::collections::BTreeMap;
11use std::fmt::{Debug, Display, Formatter};
12use std::io::Read;
13use std::str::FromStr;
14use std::sync::Arc;
15
16use bitcoin::hashes::{Hash, sha256};
17use fedimint_core::encoding::{Decodable, DecodeError, DynEncodable, Encodable};
18use fedimint_core::module::registry::ModuleDecoderRegistry;
19use rand::RngCore;
20use serde::{Deserialize, Deserializer, Serialize};
21
22use crate::module::registry::ModuleRegistry;
23use crate::{
24 erased_eq_no_instance_id, module_plugin_dyn_newtype_clone_passthrough,
25 module_plugin_dyn_newtype_define, module_plugin_dyn_newtype_display_passthrough,
26 module_plugin_dyn_newtype_encode_decode, module_plugin_dyn_newtype_eq_passthrough,
27 module_plugin_static_trait_define, module_plugin_static_trait_define_config,
28};
29
30pub mod backup;
31
32#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, PartialOrd, Ord)]
56pub struct OperationId(pub [u8; 32]);
57
58pub struct OperationIdFullFmt<'a>(&'a OperationId);
59pub struct OperationIdShortFmt<'a>(&'a OperationId);
60
61impl OperationId {
62 pub fn new_random() -> Self {
64 let mut rng = rand::thread_rng();
65 let mut bytes = [0u8; 32];
66 rng.fill_bytes(&mut bytes);
67 Self(bytes)
68 }
69
70 pub fn from_encodable<E: Encodable>(encodable: &E) -> Self {
71 Self(encodable.consensus_hash::<sha256::Hash>().to_byte_array())
72 }
73
74 pub fn fmt_short(&'_ self) -> OperationIdShortFmt<'_> {
75 OperationIdShortFmt(self)
76 }
77 pub fn fmt_full(&'_ self) -> OperationIdFullFmt<'_> {
78 OperationIdFullFmt(self)
79 }
80}
81
82impl Display for OperationIdShortFmt<'_> {
83 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84 fedimint_core::format_hex(&self.0.0[0..4], f)?;
85 f.write_str("_")?;
86 fedimint_core::format_hex(&self.0.0[28..], f)?;
87 Ok(())
88 }
89}
90
91impl Display for OperationIdFullFmt<'_> {
92 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
93 fedimint_core::format_hex(&self.0.0, f)
94 }
95}
96
97impl Debug for OperationId {
98 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
99 write!(f, "OperationId({})", self.fmt_short())
100 }
101}
102
103impl FromStr for OperationId {
104 type Err = hex::FromHexError;
105
106 fn from_str(s: &str) -> Result<Self, Self::Err> {
107 let bytes: [u8; 32] = hex::FromHex::from_hex(s)?;
108 Ok(Self(bytes))
109 }
110}
111
112impl Serialize for OperationId {
113 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
114 if serializer.is_human_readable() {
115 serializer.serialize_str(&self.fmt_full().to_string())
116 } else {
117 serializer.serialize_bytes(&self.0)
118 }
119 }
120}
121
122impl<'de> Deserialize<'de> for OperationId {
123 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
124 where
125 D: Deserializer<'de>,
126 {
127 if deserializer.is_human_readable() {
128 let s = String::deserialize(deserializer)?;
129 let operation_id = Self::from_str(&s)
130 .map_err(|e| serde::de::Error::custom(format!("invalid operation id: {e}")))?;
131 Ok(operation_id)
132 } else {
133 let bytes: [u8; 32] = <[u8; 32]>::deserialize(deserializer)?;
134 Ok(Self(bytes))
135 }
136 }
137}
138
139pub type ModuleInstanceId = u16;
153
154pub const MODULE_INSTANCE_ID_GLOBAL: u16 = u16::MAX;
156
157#[derive(PartialEq, Eq, Clone, PartialOrd, Ord, Serialize, Deserialize, Encodable, Decodable)]
163pub struct ModuleKind(Cow<'static, str>);
164
165impl ModuleKind {
166 pub fn clone_from_str(s: &str) -> Self {
167 Self(Cow::from(s.to_owned()))
168 }
169
170 pub const fn from_static_str(s: &'static str) -> Self {
171 Self(Cow::Borrowed(s))
172 }
173
174 pub fn as_str(&self) -> &str {
175 &self.0
176 }
177}
178
179impl From<String> for ModuleKind {
180 fn from(value: String) -> Self {
181 Self(Cow::Owned(value))
182 }
183}
184
185impl fmt::Display for ModuleKind {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 std::fmt::Display::fmt(&self.0, f)
188 }
189}
190
191impl fmt::Debug for ModuleKind {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 std::fmt::Display::fmt(&self.0, f)
194 }
195}
196
197impl From<&'static str> for ModuleKind {
198 fn from(val: &'static str) -> Self {
199 Self::from_static_str(val)
200 }
201}
202
203#[derive(Debug, Hash, PartialEq, Eq, Clone)]
208pub struct DynUnknown(pub Vec<u8>);
209
210impl fmt::Display for DynUnknown {
211 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
212 f.write_str(&self.0.consensus_encode_to_hex())
213 }
214}
215
216impl Encodable for DynUnknown {
223 fn consensus_encode<W: std::io::Write>(&self, w: &mut W) -> Result<(), std::io::Error> {
224 w.write_all(&self.0[..])?;
225 Ok(())
226 }
227}
228
229pub trait IntoDynInstance {
231 type DynType: 'static;
233
234 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType;
236}
237
238type DecodeFn = Box<
239 dyn for<'a> Fn(
240 Box<dyn Read + 'a>,
241 ModuleInstanceId,
242 &ModuleDecoderRegistry,
243 ) -> Result<Box<dyn Any>, DecodeError>
244 + Send
245 + Sync,
246>;
247
248#[derive(Default)]
249pub struct DecoderBuilder {
250 decode_fns: BTreeMap<TypeId, DecodeFn>,
251 transparent: bool,
252}
253
254impl DecoderBuilder {
255 pub fn build(self) -> Decoder {
256 Decoder {
257 decode_fns: Arc::new(self.decode_fns),
258 }
259 }
260
261 pub fn with_decodable_type<Type>(&mut self)
273 where
274 Type: IntoDynInstance + Decodable,
275 {
276 let is_transparent_decoder = self.transparent;
277 let decode_fn: DecodeFn = Box::new(
280 move |mut reader, instance, decoders: &ModuleDecoderRegistry| {
281 let decoders = if is_transparent_decoder {
285 decoders
286 } else {
287 &ModuleRegistry::default()
288 };
289 let typed_val =
290 Type::consensus_decode_partial(&mut reader, decoders).map_err(|err| {
291 err.context(format!("while decoding Dyn type module_id={instance}"))
292 })?;
293 let dyn_val = typed_val.into_dyn(instance);
294 let any_val: Box<dyn Any> = Box::new(dyn_val);
295 Ok(any_val)
296 },
297 );
298 if self
299 .decode_fns
300 .insert(TypeId::of::<Type::DynType>(), decode_fn)
301 .is_some()
302 {
303 panic!("Tried to add multiple decoders for the same DynType");
304 }
305 }
306}
307
308#[derive(Clone, Default)]
310pub struct Decoder {
311 decode_fns: Arc<BTreeMap<TypeId, DecodeFn>>,
312}
313
314impl Decoder {
315 pub fn builder() -> DecoderBuilder {
318 DecoderBuilder::default()
319 }
320
321 #[doc(hidden)]
323 pub fn builder_system() -> DecoderBuilder {
324 DecoderBuilder {
325 transparent: true,
326 ..DecoderBuilder::default()
327 }
328 }
329
330 pub fn decode_complete<DynType: Any>(
335 &self,
336 reader: &mut dyn Read,
337 total_len: u64,
338 module_id: ModuleInstanceId,
339 decoders: &ModuleDecoderRegistry,
340 ) -> Result<DynType, DecodeError> {
341 let mut reader = reader.take(total_len);
342
343 let val = self.decode_partial(&mut reader, module_id, decoders)?;
344 let left = reader.limit();
345
346 if left != 0 {
347 return Err(fedimint_core::encoding::DecodeError::custom(format!(
348 "Dyn type did not consume all bytes during decoding; module_id={module_id}; \
349 expected={total_len}; left={left}; type={}",
350 std::any::type_name::<DynType>(),
351 )));
352 }
353
354 Ok(val)
355 }
356
357 pub fn decode_partial<DynType: Any>(
360 &self,
361 reader: &mut dyn Read,
362 module_id: ModuleInstanceId,
363 decoders: &ModuleDecoderRegistry,
364 ) -> Result<DynType, DecodeError> {
365 let Some(decode_fn) = self.decode_fns.get(&TypeId::of::<DynType>()) else {
366 panic!(
367 "Types being decoded must be registered: Type unknown to decoder: {}, \
368 (registered decoders={})",
369 std::any::type_name::<DynType>(),
370 self.decode_fns.len()
371 );
372 };
373 Ok(*decode_fn(Box::new(reader), module_id, decoders)?
374 .downcast::<DynType>()
375 .expect("Decode fn returned wrong type, can't happen due to with_decodable_type"))
376 }
377}
378
379impl Debug for Decoder {
380 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
381 write!(f, "Decoder(registered_types = {})", self.decode_fns.len())
382 }
383}
384
385pub trait IClientConfig: Debug + Display + DynEncodable {
386 fn as_any(&self) -> &(dyn Any + Send + Sync);
387 fn module_kind(&self) -> Option<ModuleKind>;
388 fn clone(&self, instance_id: ModuleInstanceId) -> DynClientConfig;
389 fn dyn_hash(&self) -> u64;
390 fn erased_eq_no_instance_id(&self, other: &DynClientConfig) -> bool;
391 fn to_json(&self) -> Option<serde_json::Value>;
392}
393
394module_plugin_static_trait_define_config! {
395 DynClientConfig, ClientConfig, IClientConfig,
396 { },
397 {
398 erased_eq_no_instance_id!(DynClientConfig);
399
400 fn to_json(&self) -> Option<serde_json::Value> {
401 Some(serde_json::to_value(self.to_owned()).expect("serialization can't fail"))
402 }
403 },
404 {
405 erased_eq_no_instance_id!(DynClientConfig);
406
407 fn to_json(&self) -> Option<serde_json::Value> {
408 None
409 }
410 }
411}
412
413module_plugin_dyn_newtype_define! {
414 pub DynClientConfig(Box<IClientConfig>)
416}
417module_plugin_dyn_newtype_encode_decode!(DynClientConfig);
418
419module_plugin_dyn_newtype_clone_passthrough!(DynClientConfig);
420
421module_plugin_dyn_newtype_eq_passthrough!(DynClientConfig);
422
423module_plugin_dyn_newtype_display_passthrough!(DynClientConfig);
424
425pub trait IInput: Debug + Display + DynEncodable {
430 fn as_any(&self) -> &(dyn Any + Send + Sync);
431 fn module_kind(&self) -> Option<ModuleKind>;
432 fn clone(&self, instance_id: ModuleInstanceId) -> DynInput;
433 fn dyn_hash(&self) -> u64;
434 fn erased_eq_no_instance_id(&self, other: &DynInput) -> bool;
435}
436
437module_plugin_static_trait_define! {
438 DynInput, Input, IInput,
439 { },
440 {
441 erased_eq_no_instance_id!(DynInput);
442 }
443}
444
445module_plugin_dyn_newtype_define! {
446 pub DynInput(Box<IInput>)
448}
449module_plugin_dyn_newtype_encode_decode!(DynInput);
450
451module_plugin_dyn_newtype_clone_passthrough!(DynInput);
452
453module_plugin_dyn_newtype_eq_passthrough!(DynInput);
454
455module_plugin_dyn_newtype_display_passthrough!(DynInput);
456
457pub trait IOutput: Debug + Display + DynEncodable {
462 fn as_any(&self) -> &(dyn Any + Send + Sync);
463 fn module_kind(&self) -> Option<ModuleKind>;
464 fn clone(&self, instance_id: ModuleInstanceId) -> DynOutput;
465 fn dyn_hash(&self) -> u64;
466 fn erased_eq_no_instance_id(&self, other: &DynOutput) -> bool;
467}
468
469module_plugin_dyn_newtype_define! {
470 pub DynOutput(Box<IOutput>)
472}
473module_plugin_static_trait_define! {
474 DynOutput, Output, IOutput,
475 { },
476 {
477 erased_eq_no_instance_id!(DynOutput);
478 }
479}
480module_plugin_dyn_newtype_encode_decode!(DynOutput);
481
482module_plugin_dyn_newtype_clone_passthrough!(DynOutput);
483
484module_plugin_dyn_newtype_eq_passthrough!(DynOutput);
485
486module_plugin_dyn_newtype_display_passthrough!(DynOutput);
487
488pub enum FinalizationError {
489 SomethingWentWrong,
490}
491
492pub trait IOutputOutcome: Debug + Display + DynEncodable {
493 fn as_any(&self) -> &(dyn Any + Send + Sync);
494 fn module_kind(&self) -> Option<ModuleKind>;
495 fn clone(&self, module_instance_id: ModuleInstanceId) -> DynOutputOutcome;
496 fn dyn_hash(&self) -> u64;
497 fn erased_eq_no_instance_id(&self, other: &DynOutputOutcome) -> bool;
498}
499
500module_plugin_dyn_newtype_define! {
501 pub DynOutputOutcome(Box<IOutputOutcome>)
503}
504module_plugin_static_trait_define! {
505 DynOutputOutcome, OutputOutcome, IOutputOutcome,
506 { },
507 {
508 erased_eq_no_instance_id!(DynOutputOutcome);
509 }
510}
511module_plugin_dyn_newtype_encode_decode!(DynOutputOutcome);
512module_plugin_dyn_newtype_clone_passthrough!(DynOutputOutcome);
513module_plugin_dyn_newtype_eq_passthrough!(DynOutputOutcome);
514module_plugin_dyn_newtype_display_passthrough!(DynOutputOutcome);
515
516pub trait IModuleConsensusItem: Debug + Display + DynEncodable {
517 fn as_any(&self) -> &(dyn Any + Send + Sync);
518 fn module_kind(&self) -> Option<ModuleKind>;
519 fn clone(&self, module_instance_id: ModuleInstanceId) -> DynModuleConsensusItem;
520 fn dyn_hash(&self) -> u64;
521
522 fn erased_eq_no_instance_id(&self, other: &DynModuleConsensusItem) -> bool;
523}
524
525module_plugin_dyn_newtype_define! {
526 pub DynModuleConsensusItem(Box<IModuleConsensusItem>)
528}
529module_plugin_static_trait_define! {
530 DynModuleConsensusItem, ModuleConsensusItem, IModuleConsensusItem,
531 { },
532 {
533 erased_eq_no_instance_id!(DynModuleConsensusItem);
534 }
535}
536module_plugin_dyn_newtype_encode_decode!(DynModuleConsensusItem);
537
538module_plugin_dyn_newtype_clone_passthrough!(DynModuleConsensusItem);
539
540module_plugin_dyn_newtype_eq_passthrough!(DynModuleConsensusItem);
541
542module_plugin_dyn_newtype_display_passthrough!(DynModuleConsensusItem);
543
544pub trait IOutputError: Debug + Display + DynEncodable {
545 fn as_any(&self) -> &(dyn Any + Send + Sync);
546 fn module_kind(&self) -> Option<ModuleKind>;
547 fn clone(&self, module_instance_id: ModuleInstanceId) -> DynOutputError;
548 fn dyn_hash(&self) -> u64;
549
550 fn erased_eq_no_instance_id(&self, other: &DynOutputError) -> bool;
551}
552
553module_plugin_dyn_newtype_define! {
554 pub DynOutputError(Box<IOutputError>)
555}
556module_plugin_static_trait_define! {
557 DynOutputError, OutputError, IOutputError,
558 { },
559 {
560 erased_eq_no_instance_id!(DynOutputError);
561 }
562}
563module_plugin_dyn_newtype_encode_decode!(DynOutputError);
564
565module_plugin_dyn_newtype_clone_passthrough!(DynOutputError);
566
567module_plugin_dyn_newtype_eq_passthrough!(DynOutputError);
568
569module_plugin_dyn_newtype_display_passthrough!(DynOutputError);
570
571pub trait IInputError: Debug + Display + DynEncodable {
572 fn as_any(&self) -> &(dyn Any + Send + Sync);
573 fn module_kind(&self) -> Option<ModuleKind>;
574 fn clone(&self, module_instance_id: ModuleInstanceId) -> DynInputError;
575 fn dyn_hash(&self) -> u64;
576
577 fn erased_eq_no_instance_id(&self, other: &DynInputError) -> bool;
578}
579
580module_plugin_dyn_newtype_define! {
581 pub DynInputError(Box<IInputError>)
582}
583module_plugin_static_trait_define! {
584 DynInputError, InputError, IInputError,
585 { },
586 {
587 erased_eq_no_instance_id!(DynInputError);
588 }
589}
590module_plugin_dyn_newtype_encode_decode!(DynInputError);
591
592module_plugin_dyn_newtype_clone_passthrough!(DynInputError);
593
594module_plugin_dyn_newtype_eq_passthrough!(DynInputError);
595
596module_plugin_dyn_newtype_display_passthrough!(DynInputError);