fedimint_core/encoding/
mod.rs

1//! Binary encoding interface suitable for
2//! consensus critical encoding.
3//!
4//! Over time all structs that ! need to be encoded to binary will be migrated
5//! to this interface.
6//!
7//! This code is based on corresponding `rust-bitcoin` types.
8//!
9//! See [`Encodable`] and [`Decodable`] for two main traits.
10
11pub mod as_hex;
12mod bls12_381;
13pub mod btc;
14mod secp256k1;
15mod threshold_crypto;
16
17#[cfg(not(target_family = "wasm"))]
18mod tls;
19
20use std::any::TypeId;
21use std::borrow::Cow;
22use std::collections::{BTreeMap, BTreeSet, VecDeque};
23use std::fmt::{Debug, Formatter};
24use std::io::{self, Error, Read, Write};
25use std::time::{Duration, SystemTime, UNIX_EPOCH};
26use std::{cmp, mem};
27
28use anyhow::{format_err, Context};
29pub use fedimint_derive::{Decodable, Encodable};
30use hex::{FromHex, ToHex};
31use lightning::util::ser::{Readable, Writeable};
32use serde::{Deserialize, Serialize};
33use thiserror::Error;
34
35use crate::core::ModuleInstanceId;
36use crate::module::registry::{ModuleDecoderRegistry, ModuleRegistry};
37use crate::util::SafeUrl;
38
39/// Object-safe trait for things that can encode themselves
40///
41/// Like `rust-bitcoin`'s `consensus_encode`, but without generics,
42/// so can be used in `dyn` objects.
43pub trait DynEncodable {
44    fn consensus_encode_dyn(
45        &self,
46        writer: &mut dyn std::io::Write,
47    ) -> Result<usize, std::io::Error>;
48}
49
50impl Encodable for dyn DynEncodable {
51    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
52        self.consensus_encode_dyn(writer)
53    }
54}
55
56impl<T> DynEncodable for T
57where
58    T: Encodable,
59{
60    fn consensus_encode_dyn(
61        &self,
62        mut writer: &mut dyn std::io::Write,
63    ) -> Result<usize, std::io::Error> {
64        <Self as Encodable>::consensus_encode(self, &mut writer)
65    }
66}
67
68impl Encodable for Box<dyn DynEncodable> {
69    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
70        (**self).consensus_encode_dyn(writer)
71    }
72}
73
74impl<T> Encodable for &T
75where
76    T: Encodable,
77{
78    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
79        (**self).consensus_encode(writer)
80    }
81}
82
83/// Data which can be encoded in a consensus-consistent way
84pub trait Encodable {
85    /// Encode an object with a well-defined format.
86    /// Returns the number of bytes written on success.
87    ///
88    /// The only errors returned are errors propagated from the writer.
89    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error>;
90
91    /// [`Self::consensus_encode`] to newly allocated `Vec<u8>`
92    fn consensus_encode_to_vec(&self) -> Vec<u8> {
93        let mut bytes = vec![];
94        self.consensus_encode(&mut bytes)
95            .expect("encoding to bytes can't fail for io reasons");
96        bytes
97    }
98
99    /// Encode and convert to hex string representation
100    fn consensus_encode_to_hex(&self) -> String {
101        let mut bytes = vec![];
102        self.consensus_encode(&mut bytes)
103            .expect("encoding to bytes can't fail for io reasons");
104        // TODO: This double allocation offends real Rustaceans. We should
105        // be able to go straight to String, but this use case seems under-served
106        // by hex encoding crates.
107        bytes.encode_hex()
108    }
109
110    /// Encode without storing the encoding, return the size
111    fn consensus_encode_to_len(&self) -> usize {
112        self.consensus_encode(&mut io::sink())
113            .expect("encoding to bytes can't fail for io reasons")
114    }
115
116    /// Generate a SHA256 hash of the consensus encoding using the default hash
117    /// engine for `H`.
118    ///
119    /// Can be used to validate all federation members agree on state without
120    /// revealing the object
121    fn consensus_hash<H>(&self) -> H
122    where
123        H: bitcoin::hashes::Hash,
124        H::Engine: std::io::Write,
125    {
126        let mut engine = H::engine();
127        self.consensus_encode(&mut engine)
128            .expect("writing to HashEngine cannot fail");
129        H::from_engine(engine)
130    }
131}
132
133/// Maximum size, in bytes, of data we are allowed to ever decode
134/// for a single value.
135pub const MAX_DECODE_SIZE: usize = 16_000_000;
136
137/// Data which can be encoded in a consensus-consistent way
138pub trait Decodable: Sized {
139    /// Decode `Self` from a size-limited reader.
140    ///
141    /// Like `consensus_decode` but relies on the reader being limited in the
142    /// amount of data it returns, e.g. by being wrapped in
143    /// [`std::io::Take`].
144    ///
145    /// Failing to abide to this requirement might lead to memory exhaustion
146    /// caused by malicious inputs.
147    ///
148    /// Users should default to `consensus_decode`, but when data to be decoded
149    /// is already in a byte vector of a limited size, calling this function
150    /// directly might be marginally faster (due to avoiding extra checks).
151    ///
152    /// ### Rules for trait implementations
153    ///
154    /// * Simple types that that have a fixed size (own and member fields),
155    ///   don't have to overwrite this method, or be concern with it, should
156    ///   only impl `consensus_decode`.
157    /// * Types that deserialize based on decoded untrusted length should
158    ///   implement `consensus_decode_from_finite_reader` only:
159    ///   * Default implementation of `consensus_decode` will forward to
160    ///     `consensus_decode_bytes_from_finite_reader` with the reader wrapped
161    ///     by `Take`, protecting from readers that keep returning data.
162    ///   * Implementation must make sure to put a cap on things like
163    ///     `Vec::with_capacity` and other allocations to avoid oversized
164    ///     allocations, and rely on the reader being finite and running out of
165    ///     data, and collections reallocating on a legitimately oversized input
166    ///     data, instead of trying to enforce arbitrary length limits.
167    /// * Types that contain other types that might be require limited reader
168    ///   (thus implementing `consensus_decode_from_finite_reader`), should also
169    ///   implement it applying same rules, and in addition make sure to call
170    ///   `consensus_decode_from_finite_reader` on all members, to avoid
171    ///   creating redundant `Take` wrappers (`Take<Take<...>>`). Failure to do
172    ///   so might result only in a tiny performance hit.
173    #[inline]
174    fn consensus_decode_from_finite_reader<R: std::io::Read>(
175        r: &mut R,
176        modules: &ModuleDecoderRegistry,
177    ) -> Result<Self, DecodeError> {
178        // This method is always strictly less general than, `consensus_decode`, so it's
179        // safe and make sense to default to just calling it. This way most
180        // types, that don't care about protecting against resource exhaustion
181        // due to malicious input, can just ignore it.
182        Self::consensus_decode(r, modules)
183    }
184
185    /// Decode an object with a well-defined format.
186    ///
187    /// This is the method that should be implemented for a typical, fixed sized
188    /// type implementing this trait. Default implementation is wrapping the
189    /// reader in [`std::io::Take`] to limit the input size to
190    /// [`MAX_DECODE_SIZE`], and forwards the call to
191    /// [`Self::consensus_decode_from_finite_reader`], which is convenient
192    /// for types that override [`Self::consensus_decode_from_finite_reader`]
193    /// instead.
194    #[inline]
195    fn consensus_decode<R: std::io::Read>(
196        r: &mut R,
197        modules: &ModuleDecoderRegistry,
198    ) -> Result<Self, DecodeError> {
199        Self::consensus_decode_from_finite_reader(&mut r.take(MAX_DECODE_SIZE as u64), modules)
200    }
201
202    /// Decode an object from hex
203    fn consensus_decode_hex(
204        hex: &str,
205        modules: &ModuleDecoderRegistry,
206    ) -> Result<Self, DecodeError> {
207        let bytes = Vec::<u8>::from_hex(hex)
208            .map_err(anyhow::Error::from)
209            .map_err(DecodeError::new_custom)?;
210        let mut reader = std::io::Cursor::new(bytes);
211        Decodable::consensus_decode(&mut reader, modules)
212    }
213
214    fn consensus_decode_vec(
215        bytes: Vec<u8>,
216        modules: &ModuleDecoderRegistry,
217    ) -> Result<Self, DecodeError> {
218        let mut reader = std::io::Cursor::new(bytes);
219        Decodable::consensus_decode(&mut reader, modules)
220    }
221}
222
223impl Encodable for SafeUrl {
224    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
225        self.to_string().consensus_encode(writer)
226    }
227}
228
229impl Decodable for SafeUrl {
230    fn consensus_decode_from_finite_reader<D: std::io::Read>(
231        d: &mut D,
232        modules: &ModuleDecoderRegistry,
233    ) -> Result<Self, DecodeError> {
234        String::consensus_decode_from_finite_reader(d, modules)?
235            .parse::<Self>()
236            .map_err(DecodeError::from_err)
237    }
238}
239
240#[derive(Debug, Error)]
241pub struct DecodeError(pub(crate) anyhow::Error);
242
243impl DecodeError {
244    pub fn new_custom(e: anyhow::Error) -> Self {
245        Self(e)
246    }
247}
248
249impl From<anyhow::Error> for DecodeError {
250    fn from(e: anyhow::Error) -> Self {
251        Self(e)
252    }
253}
254
255pub use lightning::util::ser::BigSize;
256
257impl Encodable for BigSize {
258    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
259        let mut writer = CountWrite::from(writer);
260        self.write(&mut writer)?;
261        Ok(usize::try_from(writer.count()).expect("can't overflow"))
262    }
263}
264
265impl Decodable for BigSize {
266    fn consensus_decode<R: std::io::Read>(
267        r: &mut R,
268        _modules: &ModuleDecoderRegistry,
269    ) -> Result<Self, DecodeError> {
270        Self::read(&mut SimpleBitcoinRead(r))
271            .map_err(|e| DecodeError::new_custom(anyhow::anyhow!("BigSize decoding error: {e:?}")))
272    }
273}
274
275macro_rules! impl_encode_decode_num_as_plain {
276    ($num_type:ty) => {
277        impl Encodable for $num_type {
278            fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
279                let bytes = self.to_be_bytes();
280                writer.write_all(&bytes[..])?;
281                Ok(bytes.len())
282            }
283        }
284
285        impl Decodable for $num_type {
286            fn consensus_decode<D: std::io::Read>(
287                d: &mut D,
288                _modules: &ModuleDecoderRegistry,
289            ) -> Result<Self, crate::encoding::DecodeError> {
290                let mut bytes = [0u8; (<$num_type>::BITS / 8) as usize];
291                d.read_exact(&mut bytes).map_err(DecodeError::from_err)?;
292                Ok(<$num_type>::from_be_bytes(bytes))
293            }
294        }
295    };
296}
297
298macro_rules! impl_encode_decode_num_as_bigsize {
299    ($num_type:ty) => {
300        impl Encodable for $num_type {
301            fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
302                BigSize(u64::from(*self)).consensus_encode(writer)
303            }
304        }
305
306        impl Decodable for $num_type {
307            fn consensus_decode<D: std::io::Read>(
308                d: &mut D,
309                _modules: &ModuleDecoderRegistry,
310            ) -> Result<Self, crate::encoding::DecodeError> {
311                let varint = BigSize::consensus_decode(d, &Default::default())
312                    .context(concat!("VarInt inside ", stringify!($num_type)))?;
313                <$num_type>::try_from(varint.0).map_err(crate::encoding::DecodeError::from_err)
314            }
315        }
316    };
317}
318
319impl<T> Encodable for std::ops::RangeInclusive<T>
320where
321    T: Encodable,
322{
323    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
324        (self.start(), self.end()).consensus_encode(writer)
325    }
326}
327
328impl<T> Decodable for std::ops::RangeInclusive<T>
329where
330    T: Decodable,
331{
332    fn consensus_decode<D: std::io::Read>(
333        d: &mut D,
334        _modules: &ModuleDecoderRegistry,
335    ) -> Result<Self, crate::encoding::DecodeError> {
336        let r = <(T, T)>::consensus_decode(d, &ModuleRegistry::default())?;
337        Ok(Self::new(r.0, r.1))
338    }
339}
340
341impl_encode_decode_num_as_bigsize!(u64);
342impl_encode_decode_num_as_bigsize!(u32);
343impl_encode_decode_num_as_bigsize!(u16);
344impl_encode_decode_num_as_plain!(u8);
345
346macro_rules! impl_encode_decode_tuple {
347    ($($x:ident),*) => (
348        #[allow(non_snake_case)]
349        impl <$($x: Encodable),*> Encodable for ($($x),*) {
350            fn consensus_encode<W: std::io::Write>(&self, s: &mut W) -> Result<usize, std::io::Error> {
351                let &($(ref $x),*) = self;
352                let mut len = 0;
353                $(len += $x.consensus_encode(s)?;)*
354                Ok(len)
355            }
356        }
357
358        #[allow(non_snake_case)]
359        impl<$($x: Decodable),*> Decodable for ($($x),*) {
360            fn consensus_decode<D: std::io::Read>(d: &mut D, modules: &ModuleDecoderRegistry) -> Result<Self, DecodeError> {
361                Ok(($({let $x = Decodable::consensus_decode(d, modules)?; $x }),*))
362            }
363        }
364    );
365}
366
367/// Specialized version of Encodable for bytes
368pub fn consensus_encode_bytes<W: std::io::Write>(
369    bytes: &[u8],
370    writer: &mut W,
371) -> Result<usize, Error> {
372    let mut len = 0;
373    len += (bytes.len() as u64).consensus_encode(writer)?;
374    writer.write_all(bytes)?;
375    len += bytes.len();
376    Ok(len)
377}
378
379/// Specialized version of Encodable for static byte arrays
380pub fn consensus_encode_bytes_static<const N: usize, W: std::io::Write>(
381    bytes: &[u8; N],
382    writer: &mut W,
383) -> Result<usize, Error> {
384    writer.write_all(bytes)?;
385    Ok(bytes.len())
386}
387
388struct ReadBytesFromFiniteReaderOpts {
389    len: usize,
390    chunk_size: usize,
391}
392
393/// Read `opts.len` bytes from reader, where `opts.len` could potentially be
394/// malicious.
395///
396/// Adapted from <https://github.com/rust-bitcoin/rust-bitcoin/blob/e2b9555070d9357fb552e56085fb6fb3f0274560/bitcoin/src/consensus/encode.rs#L659>
397#[inline]
398fn read_bytes_from_finite_reader<D: Read + ?Sized>(
399    d: &mut D,
400    mut opts: ReadBytesFromFiniteReaderOpts,
401) -> Result<Vec<u8>, io::Error> {
402    let mut ret = vec![];
403
404    assert_ne!(opts.chunk_size, 0);
405
406    while opts.len > 0 {
407        let chunk_start = ret.len();
408        let chunk_size = core::cmp::min(opts.len, opts.chunk_size);
409        let chunk_end = chunk_start + chunk_size;
410        ret.resize(chunk_end, 0u8);
411        d.read_exact(&mut ret[chunk_start..chunk_end])?;
412        opts.len -= chunk_size;
413    }
414
415    Ok(ret)
416}
417
418/// Specialized version of Decodable for bytes
419pub fn consensus_decode_bytes<D: std::io::Read>(r: &mut D) -> Result<Vec<u8>, DecodeError> {
420    consensus_decode_bytes_from_finite_reader(&mut r.take(MAX_DECODE_SIZE as u64))
421}
422
423/// Specialized version of Decodable for bytes
424pub fn consensus_decode_bytes_from_finite_reader<D: std::io::Read>(
425    r: &mut D,
426) -> Result<Vec<u8>, DecodeError> {
427    let len = u64::consensus_decode_from_finite_reader(r, &ModuleRegistry::default())?;
428
429    let len: usize =
430        usize::try_from(len).map_err(|_| DecodeError::from_str("size exceeds memory"))?;
431
432    let opts = ReadBytesFromFiniteReaderOpts {
433        len,
434        chunk_size: 64 * 1024,
435    };
436
437    read_bytes_from_finite_reader(r, opts).map_err(DecodeError::from_err)
438}
439
440/// Specialized version of Decodable for fixed-size byte arrays
441pub fn consensus_decode_bytes_static<const N: usize, D: std::io::Read>(
442    r: &mut D,
443) -> Result<[u8; N], DecodeError> {
444    consensus_decode_bytes_static_from_finite_reader(&mut r.take(MAX_DECODE_SIZE as u64))
445}
446/// Specialized version of Decodable for fixed-size byte arrays
447pub fn consensus_decode_bytes_static_from_finite_reader<const N: usize, D: std::io::Read>(
448    r: &mut D,
449) -> Result<[u8; N], DecodeError> {
450    let mut bytes = [0u8; N];
451    r.read_exact(bytes.as_mut_slice())
452        .map_err(DecodeError::from_err)?;
453    Ok(bytes)
454}
455
456impl_encode_decode_tuple!(T1, T2);
457impl_encode_decode_tuple!(T1, T2, T3);
458impl_encode_decode_tuple!(T1, T2, T3, T4);
459
460impl<T> Encodable for &[T]
461where
462    T: Encodable + 'static,
463{
464    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
465        if TypeId::of::<T>() == TypeId::of::<u8>() {
466            // unsafe: we've just checked that T is `u8` so the transmute here is a no-op
467            return consensus_encode_bytes(unsafe { mem::transmute::<&[T], &[u8]>(self) }, writer);
468        }
469
470        let mut len = 0;
471        len += (self.len() as u64).consensus_encode(writer)?;
472
473        for item in *self {
474            len += item.consensus_encode(writer)?;
475        }
476        Ok(len)
477    }
478}
479
480impl<T> Encodable for Vec<T>
481where
482    T: Encodable + 'static,
483{
484    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
485        (self as &[T]).consensus_encode(writer)
486    }
487}
488
489impl<T> Decodable for Vec<T>
490where
491    T: Decodable + 'static,
492{
493    fn consensus_decode_from_finite_reader<D: std::io::Read>(
494        d: &mut D,
495        modules: &ModuleDecoderRegistry,
496    ) -> Result<Self, DecodeError> {
497        if TypeId::of::<T>() == TypeId::of::<u8>() {
498            // unsafe: we've just checked that T is `u8` so the transmute here is a no-op
499            return Ok(unsafe {
500                mem::transmute::<Vec<u8>, Self>(consensus_decode_bytes_from_finite_reader(d)?)
501            });
502        }
503        let len = u64::consensus_decode_from_finite_reader(d, modules)?;
504
505        // `collect` under the hood uses `FromIter::from_iter`, which can potentially be
506        // backed by code like:
507        // <https://github.com/rust-lang/rust/blob/fe03b46ee4688a99d7155b4f9dcd875b6903952d/library/alloc/src/vec/spec_from_iter_nested.rs#L31>
508        // This can take `size_hint` from input iterator and pre-allocate memory
509        // upfront with `Vec::with_capacity`. Because of that untrusted `len`
510        // should not be used directly.
511        let cap_len = cmp::min(8_000 / mem::size_of::<T>() as u64, len);
512
513        // Up to a cap, use the (potentially specialized for better perf in stdlib)
514        // `from_iter`.
515        let mut v: Self = (0..cap_len)
516            .map(|_| T::consensus_decode_from_finite_reader(d, modules))
517            .collect::<Result<Self, DecodeError>>()?;
518
519        // Add any excess manually avoiding any surprises.
520        while (v.len() as u64) < len {
521            v.push(T::consensus_decode_from_finite_reader(d, modules)?);
522        }
523
524        assert_eq!(v.len() as u64, len);
525
526        Ok(v)
527    }
528}
529
530impl<T> Encodable for VecDeque<T>
531where
532    T: Encodable + 'static,
533{
534    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
535        let mut len = (self.len() as u64).consensus_encode(writer)?;
536        for i in self {
537            len += i.consensus_encode(writer)?;
538        }
539        Ok(len)
540    }
541}
542
543#[test]
544fn vec_decode_sanity() {
545    let buf = [
546        0xffu8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
547    ];
548
549    // On malicious large len, return an error instead of panicking.
550    assert!(Vec::<u8>::consensus_decode(&mut buf.as_slice(), &ModuleRegistry::default()).is_err());
551    assert!(Vec::<u16>::consensus_decode(&mut buf.as_slice(), &ModuleRegistry::default()).is_err());
552}
553
554impl<T> Decodable for VecDeque<T>
555where
556    T: Decodable + 'static,
557{
558    fn consensus_decode_from_finite_reader<D: std::io::Read>(
559        d: &mut D,
560        modules: &ModuleDecoderRegistry,
561    ) -> Result<Self, DecodeError> {
562        Ok(Self::from(Vec::<T>::consensus_decode_from_finite_reader(
563            d, modules,
564        )?))
565    }
566}
567
568#[test]
569fn vec_deque_decode_sanity() {
570    let buf = [
571        0xffu8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
572    ];
573
574    // On malicious large len, return an error instead of panicking.
575    assert!(
576        VecDeque::<u8>::consensus_decode(&mut buf.as_slice(), &ModuleRegistry::default()).is_err()
577    );
578    assert!(
579        VecDeque::<u16>::consensus_decode(&mut buf.as_slice(), &ModuleRegistry::default()).is_err()
580    );
581}
582
583impl<T, const SIZE: usize> Encodable for [T; SIZE]
584where
585    T: Encodable + 'static,
586{
587    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
588        if TypeId::of::<T>() == TypeId::of::<u8>() {
589            // unsafe: we've just checked that T is `u8` so the transmute here is a no-op
590            return consensus_encode_bytes_static(
591                unsafe { mem::transmute::<&[T; SIZE], &[u8; SIZE]>(self) },
592                writer,
593            );
594        }
595
596        let mut len = 0;
597        for item in self {
598            len += item.consensus_encode(writer)?;
599        }
600        Ok(len)
601    }
602}
603
604// From <https://github.com/rust-lang/rust/issues/61956>
605unsafe fn horribe_array_transmute_workaround<const N: usize, A, B>(mut arr: [A; N]) -> [B; N] {
606    let ptr = std::ptr::from_mut(&mut arr).cast::<[B; N]>();
607    let res = unsafe { ptr.read() };
608    core::mem::forget(arr);
609    res
610}
611
612impl<T, const SIZE: usize> Decodable for [T; SIZE]
613where
614    T: Decodable + Debug + Default + Copy + 'static,
615{
616    fn consensus_decode_from_finite_reader<D: std::io::Read>(
617        d: &mut D,
618        modules: &ModuleDecoderRegistry,
619    ) -> Result<Self, DecodeError> {
620        if TypeId::of::<T>() == TypeId::of::<u8>() {
621            // unsafe: we've just checked that T is `u8` so the transmute here is a no-op
622            return Ok(unsafe {
623                let arr = consensus_decode_bytes_static_from_finite_reader(d)?;
624                horribe_array_transmute_workaround::<SIZE, u8, T>(arr)
625            });
626        }
627        // todo: impl without copy
628        let mut data = [T::default(); SIZE];
629        for item in &mut data {
630            *item = T::consensus_decode_from_finite_reader(d, modules)?;
631        }
632        Ok(data)
633    }
634}
635
636impl<T> Encodable for Option<T>
637where
638    T: Encodable,
639{
640    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
641        let mut len = 0;
642        if let Some(inner) = self {
643            len += 1u8.consensus_encode(writer)?;
644            len += inner.consensus_encode(writer)?;
645        } else {
646            len += 0u8.consensus_encode(writer)?;
647        }
648        Ok(len)
649    }
650}
651
652impl<T> Decodable for Option<T>
653where
654    T: Decodable,
655{
656    fn consensus_decode_from_finite_reader<D: std::io::Read>(
657        d: &mut D,
658        modules: &ModuleDecoderRegistry,
659    ) -> Result<Self, DecodeError> {
660        let flag = u8::consensus_decode_from_finite_reader(d, modules)?;
661        match flag {
662            0 => Ok(None),
663            1 => Ok(Some(T::consensus_decode_from_finite_reader(d, modules)?)),
664            _ => Err(DecodeError::from_str(
665                "Invalid flag for option enum, expected 0 or 1",
666            )),
667        }
668    }
669}
670
671impl<T, E> Encodable for Result<T, E>
672where
673    T: Encodable,
674    E: Encodable,
675{
676    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
677        let mut len = 0;
678
679        match self {
680            Ok(value) => {
681                len += 1u8.consensus_encode(writer)?;
682                len += value.consensus_encode(writer)?;
683            }
684            Err(error) => {
685                len += 0u8.consensus_encode(writer)?;
686                len += error.consensus_encode(writer)?;
687            }
688        }
689
690        Ok(len)
691    }
692}
693
694impl<T, E> Decodable for Result<T, E>
695where
696    T: Decodable,
697    E: Decodable,
698{
699    fn consensus_decode_from_finite_reader<D: std::io::Read>(
700        d: &mut D,
701        modules: &ModuleDecoderRegistry,
702    ) -> Result<Self, DecodeError> {
703        let flag = u8::consensus_decode_from_finite_reader(d, modules)?;
704        match flag {
705            0 => Ok(Err(E::consensus_decode_from_finite_reader(d, modules)?)),
706            1 => Ok(Ok(T::consensus_decode_from_finite_reader(d, modules)?)),
707            _ => Err(DecodeError::from_str(
708                "Invalid flag for option enum, expected 0 or 1",
709            )),
710        }
711    }
712}
713
714impl<T> Encodable for Box<T>
715where
716    T: Encodable,
717{
718    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
719        self.as_ref().consensus_encode(writer)
720    }
721}
722
723impl<T> Decodable for Box<T>
724where
725    T: Decodable,
726{
727    fn consensus_decode_from_finite_reader<D: std::io::Read>(
728        d: &mut D,
729        modules: &ModuleDecoderRegistry,
730    ) -> Result<Self, DecodeError> {
731        Ok(Self::new(T::consensus_decode_from_finite_reader(
732            d, modules,
733        )?))
734    }
735}
736
737impl Encodable for () {
738    fn consensus_encode<W: std::io::Write>(
739        &self,
740        _writer: &mut W,
741    ) -> Result<usize, std::io::Error> {
742        Ok(0)
743    }
744}
745
746impl Decodable for () {
747    fn consensus_decode<D: std::io::Read>(
748        _d: &mut D,
749        _modules: &ModuleDecoderRegistry,
750    ) -> Result<Self, DecodeError> {
751        Ok(())
752    }
753}
754
755impl Encodable for &str {
756    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
757        self.as_bytes().consensus_encode(writer)
758    }
759}
760
761impl Encodable for String {
762    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
763        self.as_bytes().consensus_encode(writer)
764    }
765}
766
767impl Decodable for String {
768    fn consensus_decode_from_finite_reader<D: std::io::Read>(
769        d: &mut D,
770        modules: &ModuleDecoderRegistry,
771    ) -> Result<Self, DecodeError> {
772        Self::from_utf8(Decodable::consensus_decode_from_finite_reader(d, modules)?)
773            .map_err(DecodeError::from_err)
774    }
775}
776
777impl Encodable for SystemTime {
778    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
779        let duration = self.duration_since(UNIX_EPOCH).expect("valid duration");
780        duration.consensus_encode_dyn(writer)
781    }
782}
783
784impl Decodable for SystemTime {
785    fn consensus_decode<D: std::io::Read>(
786        d: &mut D,
787        modules: &ModuleDecoderRegistry,
788    ) -> Result<Self, DecodeError> {
789        let duration = Duration::consensus_decode(d, modules)?;
790        Ok(UNIX_EPOCH + duration)
791    }
792}
793
794impl Encodable for Duration {
795    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
796        let mut count = 0;
797        count += self.as_secs().consensus_encode(writer)?;
798        count += self.subsec_nanos().consensus_encode(writer)?;
799
800        Ok(count)
801    }
802}
803
804impl Decodable for Duration {
805    fn consensus_decode<D: std::io::Read>(
806        d: &mut D,
807        modules: &ModuleDecoderRegistry,
808    ) -> Result<Self, DecodeError> {
809        let secs = Decodable::consensus_decode(d, modules)?;
810        let nsecs = Decodable::consensus_decode(d, modules)?;
811        Ok(Self::new(secs, nsecs))
812    }
813}
814
815impl Encodable for lightning_invoice::Bolt11Invoice {
816    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
817        self.to_string().consensus_encode(writer)
818    }
819}
820
821impl Encodable for lightning_invoice::RoutingFees {
822    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
823        let mut len = 0;
824        len += self.base_msat.consensus_encode(writer)?;
825        len += self.proportional_millionths.consensus_encode(writer)?;
826        Ok(len)
827    }
828}
829
830impl Decodable for lightning_invoice::RoutingFees {
831    fn consensus_decode<D: std::io::Read>(
832        d: &mut D,
833        modules: &ModuleDecoderRegistry,
834    ) -> Result<Self, DecodeError> {
835        let base_msat = Decodable::consensus_decode(d, modules)?;
836        let proportional_millionths = Decodable::consensus_decode(d, modules)?;
837        Ok(Self {
838            base_msat,
839            proportional_millionths,
840        })
841    }
842}
843
844impl Decodable for lightning_invoice::Bolt11Invoice {
845    fn consensus_decode<D: std::io::Read>(
846        d: &mut D,
847        modules: &ModuleDecoderRegistry,
848    ) -> Result<Self, DecodeError> {
849        String::consensus_decode(d, modules)?
850            .parse::<Self>()
851            .map_err(DecodeError::from_err)
852    }
853}
854
855impl Encodable for bool {
856    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
857        let bool_as_u8 = u8::from(*self);
858        writer.write_all(&[bool_as_u8])?;
859        Ok(1)
860    }
861}
862
863impl Decodable for bool {
864    fn consensus_decode<D: Read>(
865        d: &mut D,
866        _modules: &ModuleDecoderRegistry,
867    ) -> Result<Self, DecodeError> {
868        let mut bool_as_u8 = [0u8];
869        d.read_exact(&mut bool_as_u8)
870            .map_err(DecodeError::from_err)?;
871        match bool_as_u8[0] {
872            0 => Ok(false),
873            1 => Ok(true),
874            _ => Err(DecodeError::from_str("Out of range, expected 0 or 1")),
875        }
876    }
877}
878
879impl DecodeError {
880    // TODO: think about better name
881    #[allow(clippy::should_implement_trait)]
882    pub fn from_str(s: &'static str) -> Self {
883        #[derive(Debug)]
884        struct StrError(&'static str);
885
886        impl std::fmt::Display for StrError {
887            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
888                std::fmt::Display::fmt(&self.0, f)
889            }
890        }
891
892        impl std::error::Error for StrError {}
893
894        Self(anyhow::Error::from(StrError(s)))
895    }
896
897    pub fn from_err<E: std::error::Error + Send + Sync + 'static>(e: E) -> Self {
898        Self(anyhow::Error::from(e))
899    }
900}
901
902impl std::fmt::Display for DecodeError {
903    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
904        std::fmt::Display::fmt(&self.0, f)
905    }
906}
907
908impl<K, V> Encodable for BTreeMap<K, V>
909where
910    K: Encodable,
911    V: Encodable,
912{
913    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
914        let mut len = 0;
915        len += (self.len() as u64).consensus_encode(writer)?;
916        for (k, v) in self {
917            len += k.consensus_encode(writer)?;
918            len += v.consensus_encode(writer)?;
919        }
920        Ok(len)
921    }
922}
923
924impl<K, V> Decodable for BTreeMap<K, V>
925where
926    K: Decodable + Ord,
927    V: Decodable,
928{
929    fn consensus_decode_from_finite_reader<D: std::io::Read>(
930        d: &mut D,
931        modules: &ModuleDecoderRegistry,
932    ) -> Result<Self, DecodeError> {
933        let mut res = Self::new();
934        let len = u64::consensus_decode_from_finite_reader(d, modules)?;
935        for _ in 0..len {
936            let k = K::consensus_decode_from_finite_reader(d, modules)?;
937            if res
938                .last_key_value()
939                .is_some_and(|(prev_key, _v)| k <= *prev_key)
940            {
941                return Err(DecodeError::from_str("Non-canonical encoding"));
942            }
943            let v = V::consensus_decode_from_finite_reader(d, modules)?;
944            if res.insert(k, v).is_some() {
945                return Err(DecodeError(format_err!("Duplicate key")));
946            }
947        }
948        Ok(res)
949    }
950}
951
952impl<K> Encodable for BTreeSet<K>
953where
954    K: Encodable,
955{
956    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
957        let mut len = 0;
958        len += (self.len() as u64).consensus_encode(writer)?;
959        for k in self {
960            len += k.consensus_encode(writer)?;
961        }
962        Ok(len)
963    }
964}
965
966impl<K> Decodable for BTreeSet<K>
967where
968    K: Decodable + Ord,
969{
970    fn consensus_decode_from_finite_reader<D: std::io::Read>(
971        d: &mut D,
972        modules: &ModuleDecoderRegistry,
973    ) -> Result<Self, DecodeError> {
974        let mut res = Self::new();
975        let len = u64::consensus_decode_from_finite_reader(d, modules)?;
976        for _ in 0..len {
977            let k = K::consensus_decode_from_finite_reader(d, modules)?;
978            if res.last().is_some_and(|prev_key| k <= *prev_key) {
979                return Err(DecodeError::from_str("Non-canonical encoding"));
980            }
981            if !res.insert(k) {
982                return Err(DecodeError(format_err!("Duplicate key")));
983            }
984        }
985        Ok(res)
986    }
987}
988
989impl Encodable for Cow<'static, str> {
990    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
991        self.as_ref().consensus_encode(writer)
992    }
993}
994
995impl Decodable for Cow<'static, str> {
996    fn consensus_decode<D: std::io::Read>(
997        d: &mut D,
998        modules: &ModuleDecoderRegistry,
999    ) -> Result<Self, DecodeError> {
1000        Ok(Cow::Owned(String::consensus_decode(d, modules)?))
1001    }
1002}
1003
1004// Simple decoder implementing `bitcoin_io::Read` for `std::io::Read`.
1005// This is needed because `bitcoin::consensus::Decodable` requires a
1006// `bitcoin_io::Read`.
1007pub struct SimpleBitcoinRead<R: std::io::Read>(R);
1008
1009impl<R: std::io::Read> bitcoin_io::Read for SimpleBitcoinRead<R> {
1010    fn read(&mut self, buf: &mut [u8]) -> bitcoin_io::Result<usize> {
1011        self.0.read(buf).map_err(bitcoin_io::Error::from)
1012    }
1013}
1014
1015/// Wrap buffering support for implementations of Read.
1016/// A reader which keeps an internal buffer to avoid hitting the underlying
1017/// stream directly for every read.
1018///
1019/// In order to avoid reading bytes past the first object, and those bytes then
1020/// ending up getting dropped, this BufBitcoinReader operates in
1021/// one-byte-increments.
1022///
1023/// This code is vendored from the `lightning` crate:
1024/// <https://github.com/lightningdevkit/rust-lightning/blob/5718baaed947fcaa9c60d80cdf309040c0c68489/lightning/src/util/ser.rs#L72-L138>
1025struct BufBitcoinReader<'a, R: Read> {
1026    inner: &'a mut R,
1027    buf: [u8; 1],
1028    is_consumed: bool,
1029}
1030
1031impl<'a, R: Read> BufBitcoinReader<'a, R> {
1032    /// Creates a [`BufBitcoinReader`] which will read from the given `inner`.
1033    pub fn new(inner: &'a mut R) -> Self {
1034        BufBitcoinReader {
1035            inner,
1036            buf: [0; 1],
1037            is_consumed: true,
1038        }
1039    }
1040}
1041
1042impl<'a, R: Read> bitcoin_io::Read for BufBitcoinReader<'a, R> {
1043    #[inline]
1044    fn read(&mut self, output: &mut [u8]) -> bitcoin_io::Result<usize> {
1045        if output.is_empty() {
1046            return Ok(0);
1047        }
1048        #[allow(clippy::useless_let_if_seq)]
1049        let mut offset = 0;
1050        if !self.is_consumed {
1051            output[0] = self.buf[0];
1052            self.is_consumed = true;
1053            offset = 1;
1054        }
1055        Ok(self
1056            .inner
1057            .read(&mut output[offset..])
1058            .map(|len| len + offset)?)
1059    }
1060}
1061
1062impl<'a, R: Read> bitcoin_io::BufRead for BufBitcoinReader<'a, R> {
1063    #[inline]
1064    fn fill_buf(&mut self) -> bitcoin_io::Result<&[u8]> {
1065        debug_assert!(false, "rust-bitcoin doesn't actually use this");
1066        if self.is_consumed {
1067            let count = self.inner.read(&mut self.buf[..])?;
1068            debug_assert!(count <= 1, "read gave us a garbage length");
1069
1070            // upon hitting EOF, assume the byte is already consumed
1071            self.is_consumed = count == 0;
1072        }
1073
1074        if self.is_consumed {
1075            Ok(&[])
1076        } else {
1077            Ok(&self.buf[..])
1078        }
1079    }
1080
1081    #[inline]
1082    fn consume(&mut self, amount: usize) {
1083        debug_assert!(false, "rust-bitcoin doesn't actually use this");
1084        if amount >= 1 {
1085            debug_assert_eq!(amount, 1, "Can only consume one byte");
1086            debug_assert!(!self.is_consumed, "Cannot consume more than had been read");
1087            self.is_consumed = true;
1088        }
1089    }
1090}
1091
1092/// A writer counting number of writes written to it
1093///
1094/// Copy&pasted from <https://github.com/SOF3/count-write> which
1095/// uses Apache license (and it's a trivial amount of code, repeating
1096/// on stack overflow).
1097pub struct CountWrite<W> {
1098    inner: W,
1099    count: u64,
1100}
1101
1102impl<W> CountWrite<W> {
1103    /// Returns the number of bytes successfully written so far
1104    pub fn count(&self) -> u64 {
1105        self.count
1106    }
1107
1108    /// Extracts the inner writer, discarding this wrapper
1109    pub fn into_inner(self) -> W {
1110        self.inner
1111    }
1112}
1113
1114impl<W> From<W> for CountWrite<W> {
1115    fn from(inner: W) -> Self {
1116        Self { inner, count: 0 }
1117    }
1118}
1119
1120impl<W: Write> bitcoin_io::Write for CountWrite<W> {
1121    fn write(&mut self, buf: &[u8]) -> bitcoin_io::Result<usize> {
1122        let written = self.inner.write(buf)?;
1123        self.count += written as u64;
1124        Ok(written)
1125    }
1126
1127    fn flush(&mut self) -> bitcoin_io::Result<()> {
1128        self.inner.flush().map_err(bitcoin_io::Error::from)
1129    }
1130}
1131
1132/// A type that decodes `module_instance_id`-prefixed `T`s even
1133/// when corresponding `Decoder` is not available.
1134///
1135/// All dyn-module types are encoded as:
1136///
1137/// ```norust
1138/// module_instance_id | len_u64 | data
1139/// ```
1140///
1141/// So clients that don't have a corresponding module, can read
1142/// the `len_u64` and skip the amount of data specified in it.
1143///
1144/// This type makes it more convenient. It's possible to attempt
1145/// to retry decoding after more modules become available by using
1146/// [`DynRawFallback::redecode_raw`].
1147///
1148/// Notably this struct does not ignore any errors. It only skips
1149/// decoding when the module decoder is not available.
1150#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
1151pub enum DynRawFallback<T> {
1152    Raw {
1153        module_instance_id: ModuleInstanceId,
1154        #[serde(with = "::fedimint_core::encoding::as_hex")]
1155        raw: Vec<u8>,
1156    },
1157    Decoded(T),
1158}
1159
1160impl<T> DynRawFallback<T>
1161where
1162    T: Decodable + 'static,
1163{
1164    /// Get the decoded `T` or `None` if not decoded yet
1165    pub fn decoded(self) -> Option<T> {
1166        match self {
1167            Self::Raw { .. } => None,
1168            Self::Decoded(v) => Some(v),
1169        }
1170    }
1171
1172    /// Convert into the decoded `T` and panic if not decoded yet
1173    pub fn expect_decoded(self) -> T {
1174        match self {
1175            Self::Raw { .. } => {
1176                panic!("Expected decoded value. Possibly `redecode_raw` call is missing.")
1177            }
1178            Self::Decoded(v) => v,
1179        }
1180    }
1181
1182    /// Get the decoded `T` and panic if not decoded yet
1183    pub fn expect_decoded_ref(&self) -> &T {
1184        match self {
1185            Self::Raw { .. } => {
1186                panic!("Expected decoded value. Possibly `redecode_raw` call is missing.")
1187            }
1188            Self::Decoded(v) => v,
1189        }
1190    }
1191
1192    /// Attempt to re-decode raw values with new set of of `modules`
1193    ///
1194    /// In certain contexts it might be necessary to try again with
1195    /// a new set of modules.
1196    pub fn redecode_raw(
1197        self,
1198        decoders: &ModuleDecoderRegistry,
1199    ) -> Result<Self, crate::encoding::DecodeError> {
1200        Ok(match self {
1201            Self::Raw {
1202                module_instance_id,
1203                raw,
1204            } => match decoders.get(module_instance_id) {
1205                Some(decoder) => Self::Decoded(decoder.decode_complete(
1206                    &mut &raw[..],
1207                    raw.len() as u64,
1208                    module_instance_id,
1209                    decoders,
1210                )?),
1211                None => Self::Raw {
1212                    module_instance_id,
1213                    raw,
1214                },
1215            },
1216            Self::Decoded(v) => Self::Decoded(v),
1217        })
1218    }
1219}
1220
1221impl<T> From<T> for DynRawFallback<T> {
1222    fn from(value: T) -> Self {
1223        Self::Decoded(value)
1224    }
1225}
1226
1227impl<T> Decodable for DynRawFallback<T>
1228where
1229    T: Decodable + 'static,
1230{
1231    fn consensus_decode_from_finite_reader<R: std::io::Read>(
1232        reader: &mut R,
1233        decoders: &ModuleDecoderRegistry,
1234    ) -> Result<Self, crate::encoding::DecodeError> {
1235        let module_instance_id =
1236            fedimint_core::core::ModuleInstanceId::consensus_decode_from_finite_reader(
1237                reader, decoders,
1238            )?;
1239        Ok(match decoders.get(module_instance_id) {
1240            Some(decoder) => {
1241                let total_len_u64 = u64::consensus_decode_from_finite_reader(reader, decoders)?;
1242                Self::Decoded(decoder.decode_complete(
1243                    reader,
1244                    total_len_u64,
1245                    module_instance_id,
1246                    decoders,
1247                )?)
1248            }
1249            None => {
1250                // since the decoder is not available, just read the raw data
1251                Self::Raw {
1252                    module_instance_id,
1253                    raw: Vec::consensus_decode_from_finite_reader(reader, decoders)?,
1254                }
1255            }
1256        })
1257    }
1258}
1259
1260impl<T> Encodable for DynRawFallback<T>
1261where
1262    T: Encodable,
1263{
1264    fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
1265        match self {
1266            Self::Raw {
1267                module_instance_id,
1268                raw,
1269            } => {
1270                let mut written = module_instance_id.consensus_encode(writer)?;
1271                written += raw.consensus_encode(writer)?;
1272                Ok(written)
1273            }
1274            Self::Decoded(v) => v.consensus_encode(writer),
1275        }
1276    }
1277}
1278
1279#[cfg(test)]
1280mod tests {
1281    use std::fmt::Debug;
1282    use std::io::Cursor;
1283    use std::str::FromStr;
1284
1285    use super::*;
1286    use crate::db::DatabaseValue;
1287    use crate::encoding::{Decodable, Encodable};
1288
1289    pub(crate) fn test_roundtrip<T>(value: &T)
1290    where
1291        T: Encodable + Decodable + Eq + Debug,
1292    {
1293        let mut bytes = Vec::new();
1294        let len = value.consensus_encode(&mut bytes).unwrap();
1295        assert_eq!(len, bytes.len());
1296
1297        let mut cursor = Cursor::new(bytes);
1298        let decoded = T::consensus_decode(&mut cursor, &ModuleDecoderRegistry::default()).unwrap();
1299        assert_eq!(value, &decoded);
1300        assert_eq!(cursor.position(), len as u64);
1301    }
1302
1303    pub(crate) fn test_roundtrip_expected<T>(value: &T, expected: &[u8])
1304    where
1305        T: Encodable + Decodable + Eq + Debug,
1306    {
1307        let mut bytes = Vec::new();
1308        let len = value.consensus_encode(&mut bytes).unwrap();
1309        assert_eq!(len, bytes.len());
1310        assert_eq!(&expected, &bytes);
1311
1312        let mut cursor = Cursor::new(bytes);
1313        let decoded = T::consensus_decode(&mut cursor, &ModuleDecoderRegistry::default()).unwrap();
1314        assert_eq!(value, &decoded);
1315        assert_eq!(cursor.position(), len as u64);
1316    }
1317
1318    #[derive(Debug, Eq, PartialEq, Encodable, Decodable)]
1319    enum NoDefaultEnum {
1320        Foo,
1321        Bar(u32, String),
1322        Baz { baz: u8 },
1323    }
1324
1325    #[derive(Debug, Eq, PartialEq, Encodable, Decodable)]
1326    enum DefaultEnum {
1327        Foo,
1328        Bar(u32, String),
1329        #[encodable_default]
1330        Default {
1331            variant: u64,
1332            bytes: Vec<u8>,
1333        },
1334    }
1335
1336    #[test_log::test]
1337    fn test_derive_enum_no_default_roundtrip_success() {
1338        let enums = [
1339            NoDefaultEnum::Foo,
1340            NoDefaultEnum::Bar(
1341                42,
1342                "The answer to life, the universe, and everything".to_string(),
1343            ),
1344            NoDefaultEnum::Baz { baz: 0 },
1345        ];
1346
1347        for e in enums {
1348            test_roundtrip(&e);
1349        }
1350    }
1351
1352    #[test_log::test]
1353    fn test_derive_enum_no_default_decode_fail() {
1354        let unknown_variant = DefaultEnum::Default {
1355            variant: 42,
1356            bytes: vec![0, 1, 2, 3],
1357        };
1358        let mut unknown_variant_encoding = vec![];
1359        unknown_variant
1360            .consensus_encode(&mut unknown_variant_encoding)
1361            .unwrap();
1362
1363        let mut cursor = Cursor::new(&unknown_variant_encoding);
1364        let decode_res = NoDefaultEnum::consensus_decode(&mut cursor, &ModuleRegistry::default());
1365
1366        match decode_res {
1367            Ok(_) => panic!("Should return error"),
1368            Err(e) => assert!(e.to_string().contains("Invalid enum variant")),
1369        }
1370    }
1371
1372    #[test_log::test]
1373    fn test_derive_enum_default_decode_success() {
1374        let unknown_variant = NoDefaultEnum::Baz { baz: 123 };
1375        let mut unknown_variant_encoding = vec![];
1376        unknown_variant
1377            .consensus_encode(&mut unknown_variant_encoding)
1378            .unwrap();
1379
1380        let mut cursor = Cursor::new(&unknown_variant_encoding);
1381        let decode_res = DefaultEnum::consensus_decode(&mut cursor, &ModuleRegistry::default());
1382
1383        assert_eq!(
1384            decode_res.unwrap(),
1385            DefaultEnum::Default {
1386                variant: 2,
1387                bytes: vec![123],
1388            }
1389        );
1390    }
1391
1392    #[test_log::test]
1393    fn test_derive_struct() {
1394        #[derive(Debug, Encodable, Decodable, Eq, PartialEq)]
1395        struct TestStruct {
1396            vec: Vec<u8>,
1397            num: u32,
1398        }
1399
1400        let reference = TestStruct {
1401            vec: vec![1, 2, 3],
1402            num: 42,
1403        };
1404        let bytes = [3, 1, 2, 3, 42];
1405
1406        test_roundtrip_expected(&reference, &bytes);
1407    }
1408
1409    #[test_log::test]
1410    fn test_derive_tuple_struct() {
1411        #[derive(Debug, Encodable, Decodable, Eq, PartialEq)]
1412        struct TestStruct(Vec<u8>, u32);
1413
1414        let reference = TestStruct(vec![1, 2, 3], 42);
1415        let bytes = [3, 1, 2, 3, 42];
1416
1417        test_roundtrip_expected(&reference, &bytes);
1418    }
1419
1420    #[test_log::test]
1421    fn test_derive_enum() {
1422        #[derive(Debug, Encodable, Decodable, Eq, PartialEq)]
1423        enum TestEnum {
1424            Foo(Option<u64>),
1425            Bar { bazz: Vec<u8> },
1426        }
1427
1428        let test_cases = [
1429            (TestEnum::Foo(Some(42)), vec![0, 2, 1, 42]),
1430            (TestEnum::Foo(None), vec![0, 1, 0]),
1431            (
1432                TestEnum::Bar {
1433                    bazz: vec![1, 2, 3],
1434                },
1435                vec![1, 4, 3, 1, 2, 3],
1436            ),
1437        ];
1438
1439        for (reference, bytes) in test_cases {
1440            test_roundtrip_expected(&reference, &bytes);
1441        }
1442    }
1443
1444    #[test_log::test]
1445    fn test_invoice() {
1446        let invoice_str = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
1447			h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
1448			5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
1449			h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
1450			j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
1451			ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
1452			guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
1453			ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
1454			p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
1455			8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
1456			j5r6drg6k6zcqj0fcwg";
1457        let invoice = invoice_str
1458            .parse::<lightning_invoice::Bolt11Invoice>()
1459            .unwrap();
1460        test_roundtrip(&invoice);
1461    }
1462
1463    #[test_log::test]
1464    fn test_btreemap() {
1465        test_roundtrip(&BTreeMap::from([
1466            ("a".to_string(), 1u32),
1467            ("b".to_string(), 2),
1468        ]));
1469    }
1470
1471    #[test_log::test]
1472    fn test_btreeset() {
1473        test_roundtrip(&BTreeSet::from(["a".to_string(), "b".to_string()]));
1474    }
1475
1476    #[test_log::test]
1477    fn test_systemtime() {
1478        test_roundtrip(&fedimint_core::time::now());
1479    }
1480
1481    #[test]
1482    fn test_derive_empty_enum_decode() {
1483        #[derive(Debug, Encodable, Decodable)]
1484        enum NotConstructable {}
1485
1486        let vec = vec![42u8];
1487        let mut cursor = Cursor::new(vec);
1488
1489        assert!(
1490            NotConstructable::consensus_decode(&mut cursor, &ModuleDecoderRegistry::default())
1491                .is_err()
1492        );
1493    }
1494
1495    #[test]
1496    fn test_custom_index_enum() {
1497        #[derive(Debug, PartialEq, Eq, Encodable, Decodable)]
1498        enum Old {
1499            Foo,
1500            Bar,
1501            Baz,
1502        }
1503
1504        #[derive(Debug, PartialEq, Eq, Encodable, Decodable)]
1505        enum New {
1506            #[encodable(index = 0)]
1507            Foo,
1508            #[encodable(index = 2)]
1509            Baz,
1510            #[encodable_default]
1511            Default { variant: u64, bytes: Vec<u8> },
1512        }
1513
1514        let test_vector = vec![
1515            (Old::Foo, New::Foo),
1516            (
1517                Old::Bar,
1518                New::Default {
1519                    variant: 1,
1520                    bytes: vec![],
1521                },
1522            ),
1523            (Old::Baz, New::Baz),
1524        ];
1525
1526        for (old, new) in test_vector {
1527            let old_bytes = old.consensus_encode_to_vec();
1528            let decoded_new = New::consensus_decode_vec(old_bytes, &ModuleRegistry::default())
1529                .expect("Decoding failed");
1530            assert_eq!(decoded_new, new);
1531        }
1532    }
1533
1534    fn encode_value<T: Encodable>(value: &T) -> Vec<u8> {
1535        let mut writer = Vec::new();
1536        value.consensus_encode(&mut writer).unwrap();
1537        writer
1538    }
1539
1540    fn decode_value<T: Decodable>(bytes: &Vec<u8>) -> T {
1541        T::consensus_decode(&mut Cursor::new(bytes), &ModuleDecoderRegistry::default()).unwrap()
1542    }
1543
1544    fn keeps_ordering_after_serialization<T: Ord + Encodable + Decodable + Debug>(mut vec: Vec<T>) {
1545        vec.sort();
1546        let mut encoded = vec.iter().map(encode_value).collect::<Vec<_>>();
1547        encoded.sort();
1548        let decoded = encoded.iter().map(decode_value).collect::<Vec<_>>();
1549        for (i, (a, b)) in vec.iter().zip(decoded.iter()).enumerate() {
1550            assert_eq!(a, b, "difference at index {i}");
1551        }
1552    }
1553
1554    #[test]
1555    fn test_lexicographical_sorting() {
1556        #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Encodable, Decodable)]
1557        struct TestAmount(u64);
1558
1559        #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Encodable, Decodable)]
1560        struct TestComplexAmount(u16, u32, u64);
1561
1562        #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Encodable, Decodable)]
1563        struct Text(String);
1564
1565        let amounts = (0..20000).map(TestAmount).collect::<Vec<_>>();
1566        keeps_ordering_after_serialization(amounts);
1567
1568        let complex_amounts = (10..20000)
1569            .flat_map(|i| {
1570                (i - 1..=i + 1).flat_map(move |j| {
1571                    (i - 1..=i + 1).map(move |k| TestComplexAmount(i as u16, j as u32, k as u64))
1572                })
1573            })
1574            .collect::<Vec<_>>();
1575        keeps_ordering_after_serialization(complex_amounts);
1576
1577        let texts = (' '..'~')
1578            .flat_map(|i| {
1579                (' '..'~')
1580                    .map(|j| Text(format!("{i}{j}")))
1581                    .collect::<Vec<_>>()
1582            })
1583            .collect::<Vec<_>>();
1584        keeps_ordering_after_serialization(texts);
1585
1586        // bitcoin structures are not lexicographically sortable so we cannot
1587        // test them here. in future we may crate a wrapper type that is
1588        // lexicographically sortable to use when needed
1589    }
1590
1591    #[test]
1592    fn test_bitcoin_consensus_encoding() {
1593        // encodings should follow the bitcoin consensus encoding
1594        let txid = bitcoin::Txid::from_str(
1595            "51f7ed2f23e58cc6e139e715e9ce304a1e858416edc9079dd7b74fa8d2efc09a",
1596        )
1597        .unwrap();
1598        test_roundtrip_expected(
1599            &txid,
1600            &[
1601                154, 192, 239, 210, 168, 79, 183, 215, 157, 7, 201, 237, 22, 132, 133, 30, 74, 48,
1602                206, 233, 21, 231, 57, 225, 198, 140, 229, 35, 47, 237, 247, 81,
1603            ],
1604        );
1605        let transaction: Vec<u8> = FromHex::from_hex(
1606            "02000000000101d35b66c54cf6c09b81a8d94cd5d179719cd7595c258449452a9305ab9b12df250200000000fdffffff020cd50a0000000000160014ae5d450b71c04218e6e81c86fcc225882d7b7caae695b22100000000160014f60834ef165253c571b11ce9fa74e46692fc5ec10248304502210092062c609f4c8dc74cd7d4596ecedc1093140d90b3fd94b4bdd9ad3e102ce3bc02206bb5a6afc68d583d77d5d9bcfb6252a364d11a307f3418be1af9f47f7b1b3d780121026e5628506ecd33242e5ceb5fdafe4d3066b5c0f159b3c05a621ef65f177ea28600000000"
1607        ).unwrap();
1608        let transaction =
1609            bitcoin::Transaction::from_bytes(&transaction, &ModuleDecoderRegistry::default())
1610                .unwrap();
1611        test_roundtrip_expected(
1612            &transaction,
1613            &[
1614                2, 0, 0, 0, 0, 1, 1, 211, 91, 102, 197, 76, 246, 192, 155, 129, 168, 217, 76, 213,
1615                209, 121, 113, 156, 215, 89, 92, 37, 132, 73, 69, 42, 147, 5, 171, 155, 18, 223,
1616                37, 2, 0, 0, 0, 0, 253, 255, 255, 255, 2, 12, 213, 10, 0, 0, 0, 0, 0, 22, 0, 20,
1617                174, 93, 69, 11, 113, 192, 66, 24, 230, 232, 28, 134, 252, 194, 37, 136, 45, 123,
1618                124, 170, 230, 149, 178, 33, 0, 0, 0, 0, 22, 0, 20, 246, 8, 52, 239, 22, 82, 83,
1619                197, 113, 177, 28, 233, 250, 116, 228, 102, 146, 252, 94, 193, 2, 72, 48, 69, 2,
1620                33, 0, 146, 6, 44, 96, 159, 76, 141, 199, 76, 215, 212, 89, 110, 206, 220, 16, 147,
1621                20, 13, 144, 179, 253, 148, 180, 189, 217, 173, 62, 16, 44, 227, 188, 2, 32, 107,
1622                181, 166, 175, 198, 141, 88, 61, 119, 213, 217, 188, 251, 98, 82, 163, 100, 209,
1623                26, 48, 127, 52, 24, 190, 26, 249, 244, 127, 123, 27, 61, 120, 1, 33, 2, 110, 86,
1624                40, 80, 110, 205, 51, 36, 46, 92, 235, 95, 218, 254, 77, 48, 102, 181, 192, 241,
1625                89, 179, 192, 90, 98, 30, 246, 95, 23, 126, 162, 134, 0, 0, 0, 0,
1626            ],
1627        );
1628        let blockhash = bitcoin::BlockHash::from_str(
1629            "0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2",
1630        )
1631        .unwrap();
1632        test_roundtrip_expected(
1633            &blockhash,
1634            &[
1635                242, 96, 118, 76, 42, 229, 64, 214, 67, 122, 136, 166, 217, 0, 30, 46, 143, 168,
1636                248, 168, 189, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1637            ],
1638        );
1639    }
1640}