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