1pub 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
39pub 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
83pub trait Encodable {
85 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error>;
90
91 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 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 bytes.encode_hex()
108 }
109
110 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 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
133pub const MAX_DECODE_SIZE: usize = 16_000_000;
136
137pub trait Decodable: Sized {
139 #[inline]
174 fn consensus_decode_from_finite_reader<R: std::io::Read>(
175 r: &mut R,
176 modules: &ModuleDecoderRegistry,
177 ) -> Result<Self, DecodeError> {
178 Self::consensus_decode(r, modules)
183 }
184
185 #[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 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
367pub 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
379pub 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#[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
418pub 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
423pub 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
440pub 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}
446pub 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 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 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 let cap_len = cmp::min(8_000 / mem::size_of::<T>() as u64, len);
512
513 let mut v: Self = (0..cap_len)
516 .map(|_| T::consensus_decode_from_finite_reader(d, modules))
517 .collect::<Result<Self, DecodeError>>()?;
518
519 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 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 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 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
604unsafe 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 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 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 #[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
1004pub 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
1015struct 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 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 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
1092pub struct CountWrite<W> {
1098 inner: W,
1099 count: u64,
1100}
1101
1102impl<W> CountWrite<W> {
1103 pub fn count(&self) -> u64 {
1105 self.count
1106 }
1107
1108 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#[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 pub fn decoded(self) -> Option<T> {
1166 match self {
1167 Self::Raw { .. } => None,
1168 Self::Decoded(v) => Some(v),
1169 }
1170 }
1171
1172 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 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 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 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 }
1590
1591 #[test]
1592 fn test_bitcoin_consensus_encoding() {
1593 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}