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