1use core::fmt;
11#[cfg(feature = "alloc")]
12use core::marker::PhantomData;
13
14#[cfg(feature = "arbitrary")]
15use arbitrary::{Arbitrary, Unstructured};
16use encoding::{ArrayDecoder, Decoder6};
17#[cfg(feature = "alloc")]
18use encoding::{Decoder2, Encoder2, PrefixedSliceEncoder, VecDecoder};
19use hashes::sha256d;
20#[cfg(feature = "alloc")]
21use hashes::HashEngine as _;
22
23#[cfg(feature = "hex")]
24use crate::hex_codec::HexPrimitive;
25#[cfg(feature = "alloc")]
26use crate::merkle_tree::WitnessMerkleNode;
27use crate::merkle_tree::{TxMerkleNode, TxMerkleNodeDecoder};
28use crate::pow::CompactTargetDecoder;
29#[cfg(feature = "alloc")]
30use crate::prelude::Vec;
31use crate::time::BlockTimeDecoder;
32use crate::{BlockTime, CompactTarget};
33#[cfg(feature = "alloc")]
34use crate::{Transaction, Wtxid};
35
36#[rustfmt::skip] #[doc(inline)]
38pub use units::block::{BlockHeight, BlockHeightDecoder, BlockHeightEncoder, BlockHeightInterval, BlockMtp, BlockMtpInterval};
39
40#[rustfmt::skip] #[cfg(feature = "alloc")]
42#[doc(no_inline)]
43pub use self::error::{BlockDecoderError, InvalidBlockError};
44#[doc(no_inline)]
45pub use self::error::{
46 BlockHashDecoderError, BlockHeightDecoderError, HeaderDecoderError,
47 TooBigForRelativeHeightError, VersionDecoderError,
48};
49#[doc(inline)]
50pub use crate::hash_types::{BlockHash, BlockHashDecoder, BlockHashEncoder, WitnessCommitment};
51
52#[cfg(feature = "alloc")]
54const WITNESS_COMMITMENT_MAGIC: [u8; 6] = [0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed];
55
56#[cfg(feature = "alloc")]
65pub trait Validation: sealed::Validation + Sync + Send + Sized + Unpin {
66 const IS_CHECKED: bool;
68}
69
70#[cfg(feature = "alloc")]
82#[derive(PartialEq, Eq, Clone, Debug)]
83pub struct Block<V = Unchecked>
84where
85 V: Validation,
86{
87 header: Header,
89 transactions: Vec<Transaction>,
91 witness_root: Option<WitnessMerkleNode>,
93 _marker: PhantomData<V>,
95}
96
97#[cfg(feature = "alloc")]
98impl Block<Unchecked> {
99 #[inline]
101 pub fn new_unchecked(header: Header, transactions: Vec<Transaction>) -> Self {
102 Self { header, transactions, witness_root: None, _marker: PhantomData::<Unchecked> }
103 }
104
105 #[must_use]
109 #[inline]
110 pub fn assume_checked(self, witness_root: Option<WitnessMerkleNode>) -> Block<Checked> {
111 Block {
112 header: self.header,
113 transactions: self.transactions,
114 witness_root,
115 _marker: PhantomData::<Checked>,
116 }
117 }
118
119 #[inline]
121 pub fn into_parts(self) -> (Header, Vec<Transaction>) { (self.header, self.transactions) }
122
123 #[inline]
125 pub fn as_parts(&self) -> (&Header, &[Transaction]) { (&self.header, &self.transactions) }
126
127 pub fn validate(self) -> Result<Block<Checked>, InvalidBlockError> {
142 if self.transactions.is_empty() {
143 return Err(InvalidBlockError::NoTransactions);
144 }
145
146 if !self.transactions[0].is_coinbase() {
147 return Err(InvalidBlockError::InvalidCoinbase);
148 }
149
150 if !self.check_merkle_root() {
151 return Err(InvalidBlockError::InvalidMerkleRoot);
152 }
153
154 match self.check_witness_commitment() {
155 (false, _) => Err(InvalidBlockError::InvalidWitnessCommitment),
156 (true, witness_root) => {
157 let block = Self::new_unchecked(self.header, self.transactions);
158 Ok(block.assume_checked(witness_root))
159 }
160 }
161 }
162
163 pub fn check_merkle_root(&self) -> bool {
165 match compute_merkle_root(&self.transactions) {
166 Some(merkle_root) => self.header.merkle_root == merkle_root,
167 None => false,
168 }
169 }
170
171 pub fn compute_witness_commitment(
173 &self,
174 witness_reserved_value: &[u8],
175 ) -> Option<(WitnessMerkleNode, WitnessCommitment)> {
176 compute_witness_root(&self.transactions).map(|witness_root| {
177 let mut encoder = sha256d::Hash::engine();
178 hashes::encode_to_engine(&witness_root, &mut encoder);
179 encoder.input(witness_reserved_value);
180 let witness_commitment = WitnessCommitment::from_byte_array(
181 sha256d::Hash::from_engine(encoder).to_byte_array(),
182 );
183 (witness_root, witness_commitment)
184 })
185 }
186
187 pub fn check_witness_commitment(&self) -> (bool, Option<WitnessMerkleNode>) {
190 if self.transactions.is_empty() {
191 return (false, None);
192 }
193
194 if self.transactions[0].is_coinbase() {
195 let coinbase = self.transactions[0].clone();
196 if let Some(commitment) = witness_commitment_from_coinbase(&coinbase) {
197 let witness_vec: Vec<_> = coinbase.inputs[0].witness.iter().collect();
199 if witness_vec.len() == 1 && witness_vec[0].len() == 32 {
200 if let Some((witness_root, witness_commitment)) =
201 self.compute_witness_commitment(witness_vec[0])
202 {
203 if commitment == witness_commitment {
204 return (true, Some(witness_root));
205 }
206 }
207 }
208
209 return (false, None);
210 }
211 }
212
213 if self.transactions.iter().all(|t| t.inputs.iter().all(|i| i.witness.is_empty())) {
215 return (true, None);
216 }
217
218 (false, None)
219 }
220}
221
222#[cfg(feature = "alloc")]
223impl Block<Checked> {
224 #[inline]
226 pub fn header(&self) -> &Header { &self.header }
227
228 #[inline]
230 pub fn transactions(&self) -> &[Transaction] { &self.transactions }
231
232 #[inline]
237 pub fn cached_witness_root(&self) -> Option<WitnessMerkleNode> { self.witness_root }
238}
239
240#[cfg(feature = "alloc")]
241impl<V: Validation> Block<V> {
242 #[inline]
244 pub fn block_hash(&self) -> BlockHash { self.header.block_hash() }
245}
246
247#[cfg(feature = "alloc")]
248impl From<Block> for BlockHash {
249 #[inline]
250 fn from(block: Block) -> Self { block.block_hash() }
251}
252
253#[cfg(feature = "alloc")]
254impl From<&Block> for BlockHash {
255 #[inline]
256 fn from(block: &Block) -> Self { block.block_hash() }
257}
258
259#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
261#[cfg(feature = "alloc")]
262pub enum Checked {}
263
264#[cfg(feature = "alloc")]
265impl Validation for Checked {
266 const IS_CHECKED: bool = true;
267}
268
269#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
271#[cfg(feature = "alloc")]
272pub enum Unchecked {}
273
274#[cfg(feature = "alloc")]
275impl Validation for Unchecked {
276 const IS_CHECKED: bool = false;
277}
278
279#[cfg(feature = "alloc")]
280mod sealed {
281 pub trait Validation {}
283 impl Validation for super::Checked {}
284 impl Validation for super::Unchecked {}
285}
286
287#[cfg(feature = "alloc")]
288#[cfg(feature = "hex")]
289impl core::str::FromStr for Block<Unchecked>
290where
291 Self: encoding::Decode,
292{
293 type Err = encoding::FromHexError<BlockDecoderError>;
294
295 fn from_str(s: &str) -> Result<Self, Self::Err> { encoding::decode_from_hex(s) }
296}
297
298#[cfg(feature = "alloc")]
299#[cfg(feature = "hex")]
300impl<V: Validation> fmt::Display for Block<V>
301where
302 Self: encoding::Encode,
303{
304 #[allow(clippy::use_self)]
305 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
306 fmt::Display::fmt(&HexPrimitive(self), f)
307 }
308}
309
310#[cfg(feature = "alloc")]
311#[cfg(feature = "hex")]
312impl<V: Validation> fmt::LowerHex for Block<V> {
313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314 fmt::LowerHex::fmt(&HexPrimitive(self), f)
315 }
316}
317
318#[cfg(feature = "alloc")]
319#[cfg(feature = "hex")]
320impl<V: Validation> fmt::UpperHex for Block<V> {
321 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
322 fmt::UpperHex::fmt(&HexPrimitive(self), f)
323 }
324}
325
326#[cfg(feature = "alloc")]
327impl<V> encoding::Encode for Block<V>
328where
329 V: Validation,
330{
331 type Encoder<'e>
332 = BlockEncoder<'e>
333 where
334 Self: 'e;
335
336 fn encoder(&self) -> Self::Encoder<'_> {
337 BlockEncoder::new(Encoder2::new(
338 self.header.encoder(),
339 PrefixedSliceEncoder::new(&self.transactions),
340 ))
341 }
342}
343
344#[cfg(feature = "alloc")]
345impl encoding::Decode for Block<Unchecked> {
346 type Decoder = BlockDecoder;
347}
348
349#[cfg(feature = "alloc")]
350encoding::encoder_newtype! {
351 #[derive(Debug, Clone)]
353 pub struct BlockEncoder<'e>(
354 Encoder2<HeaderEncoder<'e>, PrefixedSliceEncoder<'e, Transaction>>
355 );
356}
357
358#[cfg(feature = "alloc")]
359type BlockInnerDecoder = Decoder2<HeaderDecoder, VecDecoder<Transaction>>;
360
361#[cfg(feature = "alloc")]
362crate::decoder_newtype! {
363 #[derive(Debug, Clone)]
367 pub struct BlockDecoder(BlockInnerDecoder);
368
369 pub const fn new() -> Self { Self(Decoder2::new(HeaderDecoder::new(), VecDecoder::new())) }
371
372 fn end(result: Result<(Header, Vec<Transaction>), <BlockInnerDecoder as encoding::Decoder>::Error>) -> Result<Block, BlockDecoderError> {
373 let (header, transactions) = result.map_err(BlockDecoderError)?;
374 Ok(Self::Output::new_unchecked(header, transactions))
375 }
376}
377
378#[cfg(feature = "alloc")]
388pub fn compute_merkle_root(transactions: &[Transaction]) -> Option<TxMerkleNode> {
389 let hashes = transactions.iter().map(Transaction::compute_txid);
390 TxMerkleNode::calculate_root(hashes)
391}
392
393#[cfg(feature = "alloc")]
403pub fn compute_witness_root(transactions: &[Transaction]) -> Option<WitnessMerkleNode> {
404 let hashes = transactions.iter().enumerate().map(|(i, t)| {
405 if i == 0 {
406 Wtxid::COINBASE
408 } else {
409 t.compute_wtxid()
410 }
411 });
412 WitnessMerkleNode::calculate_root(hashes)
413}
414
415#[cfg(feature = "alloc")]
416fn witness_commitment_from_coinbase(coinbase: &Transaction) -> Option<WitnessCommitment> {
417 if !coinbase.is_coinbase() {
418 return None;
419 }
420
421 if let Some(pos) = coinbase.outputs.iter().rposition(|o| {
423 o.script_pubkey.len() >= 38 && o.script_pubkey.as_bytes()[0..6] == WITNESS_COMMITMENT_MAGIC
424 }) {
425 let bytes =
426 <[u8; 32]>::try_from(&coinbase.outputs[pos].script_pubkey.as_bytes()[6..38]).unwrap();
427 Some(WitnessCommitment::from_byte_array(bytes))
428 } else {
429 None
430 }
431}
432
433#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
444pub struct Header {
445 pub version: Version,
447 pub prev_blockhash: BlockHash,
449 pub merkle_root: TxMerkleNode,
451 pub time: BlockTime,
453 pub bits: CompactTarget,
455 pub nonce: u32,
457}
458
459impl Header {
460 pub const SIZE: usize = 4 + 32 + 32 + 4 + 4 + 4; pub fn block_hash(&self) -> BlockHash {
467 let hash = hashes::encode_to_hash::<_, sha256d::HashEngine>(self);
468 BlockHash::from_byte_array(hash.to_byte_array())
469 }
470}
471
472#[cfg(feature = "hex")]
473impl core::str::FromStr for Header {
474 type Err = encoding::FromHexError<HeaderDecoderError>;
475
476 fn from_str(s: &str) -> Result<Self, Self::Err> { encoding::decode_from_hex(s) }
477}
478
479#[cfg(feature = "hex")]
480impl fmt::Display for Header {
481 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482 fmt::Display::fmt(&HexPrimitive(self), f)
483 }
484}
485
486#[cfg(feature = "hex")]
487impl fmt::LowerHex for Header {
488 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489 fmt::LowerHex::fmt(&HexPrimitive(self), f)
490 }
491}
492
493#[cfg(feature = "hex")]
494impl fmt::UpperHex for Header {
495 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 fmt::UpperHex::fmt(&HexPrimitive(self), f)
497 }
498}
499
500impl fmt::Debug for Header {
501 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
502 f.debug_struct("Header")
503 .field("block_hash", &self.block_hash())
504 .field("version", &self.version)
505 .field("prev_blockhash", &self.prev_blockhash)
506 .field("merkle_root", &self.merkle_root)
507 .field("time", &self.time)
508 .field("bits", &self.bits)
509 .field("nonce", &self.nonce)
510 .finish()
511 }
512}
513
514impl encoding::Encode for Header {
515 type Encoder<'e> = HeaderEncoder<'e>;
516
517 fn encoder(&self) -> Self::Encoder<'_> {
518 HeaderEncoder::new(encoding::Encoder6::new(
519 self.version.encoder(),
520 self.prev_blockhash.encoder(),
521 self.merkle_root.encoder(),
522 self.time.encoder(),
523 self.bits.encoder(),
524 encoding::ArrayEncoder::without_length_prefix(self.nonce.to_le_bytes()),
525 ))
526 }
527}
528
529impl encoding::Decode for Header {
530 type Decoder = HeaderDecoder;
531}
532
533encoding::encoder_newtype_exact! {
534 #[derive(Debug, Clone)]
536 pub struct HeaderEncoder<'e>(
537 encoding::Encoder6<
538 VersionEncoder<'e>,
539 BlockHashEncoder<'e>,
540 crate::merkle_tree::TxMerkleNodeEncoder<'e>,
541 crate::time::BlockTimeEncoder<'e>,
542 crate::pow::CompactTargetEncoder<'e>,
543 encoding::ArrayEncoder<4>,
544 >
545 );
546}
547
548type HeaderInnerDecoder = Decoder6<
549 VersionDecoder,
550 BlockHashDecoder,
551 TxMerkleNodeDecoder,
552 BlockTimeDecoder,
553 CompactTargetDecoder,
554 encoding::ArrayDecoder<4>, >;
556
557crate::decoder_newtype! {
558 #[derive(Debug, Clone)]
560 pub struct HeaderDecoder(HeaderInnerDecoder);
561
562 pub const fn new() -> Self {
564 Self(Decoder6::new(
565 VersionDecoder::new(),
566 BlockHashDecoder::new(),
567 TxMerkleNodeDecoder::new(),
568 BlockTimeDecoder::new(),
569 CompactTargetDecoder::new(),
570 ArrayDecoder::new(),
571 ))
572 }
573
574 fn map_push_bytes_err(err: <HeaderInnerDecoder as encoding::Decoder>::Error) -> HeaderDecoderError {
575 Self::from_inner(err)
576 }
577
578 fn end(
579 result: Result<<HeaderInnerDecoder as encoding::Decoder>::Output, <HeaderInnerDecoder as encoding::Decoder>::Error>
580 ) -> Result<Header, HeaderDecoderError> {
581 let (version, prev_blockhash, merkle_root, time, bits, nonce) = result.map_err(Self::from_inner)?;
582 let nonce = u32::from_le_bytes(nonce);
583 Ok(Header { version, prev_blockhash, merkle_root, time, bits, nonce })
584 }
585}
586
587impl HeaderDecoder {
588 fn from_inner(e: <HeaderInnerDecoder as encoding::Decoder>::Error) -> HeaderDecoderError {
589 match e {
590 encoding::Decoder6Error::First(e) => HeaderDecoderError::Version(e),
591 encoding::Decoder6Error::Second(e) => HeaderDecoderError::PrevBlockhash(e),
592 encoding::Decoder6Error::Third(e) => HeaderDecoderError::MerkleRoot(e),
593 encoding::Decoder6Error::Fourth(e) => HeaderDecoderError::Time(e),
594 encoding::Decoder6Error::Fifth(e) => HeaderDecoderError::Bits(e),
595 encoding::Decoder6Error::Sixth(e) => HeaderDecoderError::Nonce(e),
596 }
597 }
598}
599
600impl From<Header> for BlockHash {
601 #[inline]
602 fn from(header: Header) -> Self { header.block_hash() }
603}
604
605impl From<&Header> for BlockHash {
606 #[inline]
607 fn from(header: &Header) -> Self { header.block_hash() }
608}
609
610#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
625pub struct Version(i32);
626
627impl Version {
628 pub const ONE: Self = Self(1);
630
631 pub const TWO: Self = Self(2);
633
634 pub const NO_SOFT_FORK_SIGNALLING: Self = Self(Self::USE_VERSION_BITS as i32);
636
637 const VERSION_BITS_MASK: u32 = 0x1FFF_FFFF;
639
640 const USE_VERSION_BITS: u32 = 0x2000_0000;
644
645 #[inline]
649 pub const fn from_consensus(v: i32) -> Self { Self(v) }
650
651 #[inline]
655 pub const fn to_consensus(self) -> i32 { self.0 }
656
657 pub fn is_signalling_soft_fork(self, bit: u8) -> bool {
662 if bit > 28 {
664 return false;
665 }
666
667 if (self.0 as u32) & !Self::VERSION_BITS_MASK != Self::USE_VERSION_BITS {
669 return false;
670 }
671
672 (self.0 as u32 & Self::VERSION_BITS_MASK) & (1 << bit) > 0
674 }
675}
676
677impl fmt::Display for Version {
678 #[inline]
679 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
680}
681
682impl fmt::LowerHex for Version {
683 #[inline]
684 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
685}
686
687impl fmt::UpperHex for Version {
688 #[inline]
689 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
690}
691
692impl fmt::Octal for Version {
693 #[inline]
694 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Octal::fmt(&self.0, f) }
695}
696
697impl fmt::Binary for Version {
698 #[inline]
699 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Binary::fmt(&self.0, f) }
700}
701
702impl Default for Version {
703 #[inline]
704 fn default() -> Self { Self::NO_SOFT_FORK_SIGNALLING }
705}
706
707impl encoding::Encode for Version {
708 type Encoder<'e> = VersionEncoder<'e>;
709 fn encoder(&self) -> Self::Encoder<'_> {
710 VersionEncoder::new(encoding::ArrayEncoder::without_length_prefix(
711 self.to_consensus().to_le_bytes(),
712 ))
713 }
714}
715
716impl encoding::Decode for Version {
717 type Decoder = VersionDecoder;
718}
719
720encoding::encoder_newtype_exact! {
721 #[derive(Debug, Clone)]
723 pub struct VersionEncoder<'e>(encoding::ArrayEncoder<4>);
724}
725
726crate::decoder_newtype! {
727 #[derive(Debug, Clone)]
729 pub struct VersionDecoder(encoding::ArrayDecoder<4>);
730
731 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
733
734 fn end(result: Result<[u8; 4], encoding::UnexpectedEofError>) -> Result<Version, VersionDecoderError> {
735 let value = result.map_err(VersionDecoderError)?;
736 let n = i32::from_le_bytes(value);
737 Ok(Version::from_consensus(n))
738 }
739}
740
741pub mod error {
743 use core::convert::Infallible;
744 use core::fmt;
745
746 use internals::write_err;
747
748 use crate::merkle_tree::TxMerkleNodeDecoderError;
749 use crate::pow::CompactTargetDecoderError;
750 use crate::time::BlockTimeDecoderError;
751
752 #[rustfmt::skip] #[doc(no_inline)]
754 pub use units::block::{BlockHeightDecoderError, TooBigForRelativeHeightError};
755 #[doc(inline)]
756 pub use crate::hash_types::BlockHashDecoderError;
757
758 #[cfg(feature = "alloc")]
760 #[derive(Debug, Clone, PartialEq, Eq)]
761 pub struct BlockDecoderError(pub(super) <super::BlockInnerDecoder as encoding::Decoder>::Error);
762
763 #[cfg(feature = "alloc")]
764 impl From<Infallible> for BlockDecoderError {
765 fn from(never: Infallible) -> Self { match never {} }
766 }
767
768 #[cfg(feature = "alloc")]
769 impl fmt::Display for BlockDecoderError {
770 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
771 write_err!(f, "block decoder error"; self.0)
772 }
773 }
774
775 #[cfg(feature = "alloc")]
776 #[cfg(feature = "std")]
777 impl std::error::Error for BlockDecoderError {
778 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
779 }
780
781 #[cfg(feature = "alloc")]
783 #[derive(Debug, Clone, PartialEq, Eq)]
784 #[non_exhaustive]
785 pub enum InvalidBlockError {
786 InvalidMerkleRoot,
788 InvalidWitnessCommitment,
790 NoTransactions,
792 InvalidCoinbase,
794 }
795
796 #[cfg(feature = "alloc")]
797 impl From<Infallible> for InvalidBlockError {
798 fn from(never: Infallible) -> Self { match never {} }
799 }
800
801 #[cfg(feature = "alloc")]
802 impl fmt::Display for InvalidBlockError {
803 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
804 match self {
805 Self::InvalidMerkleRoot =>
806 write!(f, "header Merkle root does not match the calculated Merkle root"),
807 Self::InvalidWitnessCommitment => write!(f, "the witness commitment in coinbase transaction does not match the calculated witness_root"),
808 Self::NoTransactions => write!(f, "block has no transactions (missing coinbase)"),
809 Self::InvalidCoinbase =>
810 write!(f, "the first transaction is not a valid coinbase transaction"),
811 }
812 }
813 }
814
815 #[cfg(feature = "alloc")]
816 #[cfg(feature = "std")]
817 impl std::error::Error for InvalidBlockError {
818 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
819 match self {
820 Self::InvalidMerkleRoot => None,
821 Self::InvalidWitnessCommitment => None,
822 Self::NoTransactions => None,
823 Self::InvalidCoinbase => None,
824 }
825 }
826 }
827
828 #[derive(Debug, Clone, PartialEq, Eq)]
830 #[non_exhaustive]
831 pub enum HeaderDecoderError {
832 Version(VersionDecoderError),
834 PrevBlockhash(BlockHashDecoderError),
836 MerkleRoot(TxMerkleNodeDecoderError),
838 Time(BlockTimeDecoderError),
840 Bits(CompactTargetDecoderError),
842 Nonce(encoding::UnexpectedEofError),
844 }
845
846 impl From<Infallible> for HeaderDecoderError {
847 fn from(never: Infallible) -> Self { match never {} }
848 }
849
850 impl fmt::Display for HeaderDecoderError {
851 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
852 match *self {
853 Self::Version(ref e) => write_err!(f, "header decoder error"; e),
854 Self::PrevBlockhash(ref e) => write_err!(f, "header decoder error"; e),
855 Self::MerkleRoot(ref e) => write_err!(f, "header decoder error"; e),
856 Self::Time(ref e) => write_err!(f, "header decoder error"; e),
857 Self::Bits(ref e) => write_err!(f, "header decoder error"; e),
858 Self::Nonce(ref e) => write_err!(f, "header decoder error"; e),
859 }
860 }
861 }
862
863 #[cfg(feature = "std")]
864 impl std::error::Error for HeaderDecoderError {
865 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
866 match *self {
867 Self::Version(ref e) => Some(e),
868 Self::PrevBlockhash(ref e) => Some(e),
869 Self::MerkleRoot(ref e) => Some(e),
870 Self::Time(ref e) => Some(e),
871 Self::Bits(ref e) => Some(e),
872 Self::Nonce(ref e) => Some(e),
873 }
874 }
875 }
876
877 #[derive(Debug, Clone, PartialEq, Eq)]
879 pub struct VersionDecoderError(pub(super) encoding::UnexpectedEofError);
880
881 impl From<Infallible> for VersionDecoderError {
882 fn from(never: Infallible) -> Self { match never {} }
883 }
884
885 impl fmt::Display for VersionDecoderError {
886 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
887 write_err!(f, "version decoder error"; self.0)
888 }
889 }
890
891 #[cfg(feature = "std")]
892 impl std::error::Error for VersionDecoderError {
893 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
894 }
895}
896
897#[cfg(feature = "arbitrary")]
898#[cfg(feature = "alloc")]
899impl<'a> Arbitrary<'a> for Block {
900 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
901 let header = Header::arbitrary(u)?;
902 let transactions = Vec::<Transaction>::arbitrary(u)?;
903 Ok(Self::new_unchecked(header, transactions))
904 }
905}
906
907#[cfg(feature = "arbitrary")]
908impl<'a> Arbitrary<'a> for Header {
909 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
910 Ok(Self {
911 version: Version::arbitrary(u)?,
912 prev_blockhash: BlockHash::from_byte_array(u.arbitrary()?),
913 merkle_root: TxMerkleNode::from_byte_array(u.arbitrary()?),
914 time: u.arbitrary()?,
915 bits: CompactTarget::from_consensus(u.arbitrary()?),
916 nonce: u.arbitrary()?,
917 })
918 }
919}
920
921#[cfg(feature = "arbitrary")]
922impl<'a> Arbitrary<'a> for Version {
923 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
924 let choice = u.int_in_range(0..=3)?;
926 match choice {
927 0 => Ok(Self::ONE),
928 1 => Ok(Self::TWO),
929 2 => Ok(Self::NO_SOFT_FORK_SIGNALLING),
930 _ => Ok(Self::from_consensus(u.arbitrary()?)),
931 }
932 }
933}
934
935#[cfg(test)]
936mod tests {
937 #[cfg(feature = "alloc")]
938 use alloc::string::ToString;
939 #[cfg(feature = "alloc")]
940 use alloc::{format, vec};
941 #[cfg(feature = "alloc")]
942 #[cfg(feature = "hex")]
943 use core::str::FromStr as _;
944
945 #[cfg(feature = "alloc")]
946 use encoding::Decode as _;
947 use encoding::{check_encode, Decoder as _};
948 #[cfg(feature = "hex")]
949 use hex::hex;
950 #[cfg(feature = "alloc")]
951 #[cfg(feature = "hex")]
952 #[cfg(feature = "serde")]
953 use serde::{Deserialize, Serialize};
954
955 use super::*;
956
957 fn dummy_header() -> Header {
958 Header {
959 version: Version::ONE,
960 prev_blockhash: BlockHash::from_byte_array([0x99; 32]),
961 merkle_root: TxMerkleNode::from_byte_array([0x77; 32]),
962 time: BlockTime::from(2),
963 bits: CompactTarget::from_consensus(3),
964 nonce: 4,
965 }
966 }
967
968 #[test]
969 fn version_is_not_signalling_with_invalid_bit() {
970 let arbitrary_version = Version::from_consensus(1_234_567_890);
971 assert!(!Version::is_signalling_soft_fork(arbitrary_version, 29));
973 }
974
975 #[test]
976 fn version_is_not_signalling_when_use_version_bit_not_set() {
977 let version = Version::from_consensus(0b0100_0000_0000_0000_0000_0000_0000_0000);
978 assert!(!Version::is_signalling_soft_fork(version, 1));
980 }
981
982 #[test]
983 fn version_is_signalling() {
984 let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010);
985 assert!(Version::is_signalling_soft_fork(version, 1));
986 let version = Version::from_consensus(0b0011_0000_0000_0000_0000_0000_0000_0000);
987 assert!(Version::is_signalling_soft_fork(version, 28));
988 }
989
990 #[test]
991 fn version_is_not_signalling() {
992 let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010);
993 assert!(!Version::is_signalling_soft_fork(version, 0));
994 }
995
996 #[test]
997 fn soft_fork_signalling() {
998 for i in 0..31 {
999 let version_int = (0x2000_0000u32 ^ (1 << i)) as i32;
1000 let version = Version::from_consensus(version_int);
1001 if i < 29 {
1002 assert!(version.is_signalling_soft_fork(i));
1003 } else {
1004 assert!(!version.is_signalling_soft_fork(i));
1005 }
1006 }
1007
1008 let segwit_signal = Version::from_consensus(0x2000_0000 ^ (1 << 1));
1009 assert!(!segwit_signal.is_signalling_soft_fork(0));
1010 assert!(segwit_signal.is_signalling_soft_fork(1));
1011 assert!(!segwit_signal.is_signalling_soft_fork(2));
1012 }
1013
1014 #[test]
1015 fn version_to_consensus() {
1016 let version = Version::from_consensus(1_234_567_890);
1017 assert_eq!(version.to_consensus(), 1_234_567_890);
1018 }
1019
1020 #[test]
1021 fn version_default() {
1022 let version = Version::default();
1023 assert_eq!(version.to_consensus(), Version::NO_SOFT_FORK_SIGNALLING.to_consensus());
1024 }
1025
1026 #[test]
1027 #[cfg(feature = "alloc")]
1028 fn version_display() {
1029 let version = Version(75);
1030 assert_eq!(format!("{}", version), "75");
1031 assert_eq!(format!("{:x}", version), "4b");
1032 assert_eq!(format!("{:#x}", version), "0x4b");
1033 assert_eq!(format!("{:X}", version), "4B");
1034 assert_eq!(format!("{:#X}", version), "0x4B");
1035 assert_eq!(format!("{:o}", version), "113");
1036 assert_eq!(format!("{:#o}", version), "0o113");
1037 assert_eq!(format!("{:b}", version), "1001011");
1038 assert_eq!(format!("{:#b}", version), "0b1001011");
1039 }
1040
1041 #[test]
1043 fn header_size() {
1044 let header = dummy_header();
1045
1046 let header_size = header.version.to_consensus().to_le_bytes().len()
1049 + header.prev_blockhash.as_byte_array().len()
1050 + header.merkle_root.as_byte_array().len()
1051 + header.time.to_u32().to_le_bytes().len()
1052 + header.bits.to_consensus().to_le_bytes().len()
1053 + header.nonce.to_le_bytes().len();
1054
1055 assert_eq!(header_size, Header::SIZE);
1056 }
1057
1058 #[test]
1059 #[cfg(feature = "alloc")]
1060 fn block_new_unchecked() {
1061 let header = dummy_header();
1062 let transactions = vec![];
1063 let block = Block::new_unchecked(header, transactions.clone());
1064 assert_eq!(block.header, header);
1065 assert_eq!(block.transactions, transactions);
1066 }
1067
1068 #[test]
1069 #[cfg(feature = "alloc")]
1070 fn block_assume_checked() {
1071 let header = dummy_header();
1072 let transactions = vec![];
1073 let block = Block::new_unchecked(header, transactions.clone());
1074 let witness_root = Some(WitnessMerkleNode::from_byte_array([0x88; 32]));
1075 let checked_block = block.assume_checked(witness_root);
1076 assert_eq!(checked_block.header(), &header);
1077 assert_eq!(checked_block.transactions(), &transactions);
1078 assert_eq!(checked_block.cached_witness_root(), witness_root);
1079 }
1080
1081 #[test]
1082 #[cfg(feature = "alloc")]
1083 fn block_into_parts() {
1084 let header = dummy_header();
1085 let transactions = vec![];
1086 let block = Block::new_unchecked(header, transactions.clone());
1087 let (block_header, block_transactions) = block.into_parts();
1088 assert_eq!(block_header, header);
1089 assert_eq!(block_transactions, transactions);
1090 }
1091
1092 #[test]
1093 #[cfg(feature = "alloc")]
1094 fn block_as_parts() {
1095 let header = dummy_header();
1096 let transactions = vec![];
1097 let block = Block::new_unchecked(header, transactions.clone());
1098 let (block_header, block_transactions) = block.as_parts();
1099 assert_eq!(block_header, &header);
1100 assert_eq!(block_transactions, &transactions);
1101 }
1102
1103 #[test]
1104 #[cfg(feature = "alloc")]
1105 fn block_cached_witness_root() {
1106 let header = dummy_header();
1107 let transactions = vec![];
1108 let block = Block::new_unchecked(header, transactions);
1109 let witness_root = Some(WitnessMerkleNode::from_byte_array([0x88; 32]));
1110 let checked_block = block.assume_checked(witness_root);
1111 assert_eq!(checked_block.cached_witness_root(), witness_root);
1112 }
1113
1114 #[test]
1115 #[cfg(feature = "alloc")]
1116 fn block_validation_no_transactions() {
1117 let header = dummy_header();
1118 let transactions = Vec::new(); let block = Block::new_unchecked(header, transactions);
1121 let err = block.validate().unwrap_err();
1122 assert_eq!(err, InvalidBlockError::NoTransactions);
1123 }
1124
1125 #[test]
1126 #[cfg(feature = "alloc")]
1127 fn block_validation_invalid_coinbase() {
1128 let header = dummy_header();
1129
1130 let non_coinbase_tx = Transaction {
1132 version: crate::transaction::Version::TWO,
1133 lock_time: crate::absolute::LockTime::ZERO,
1134 inputs: vec![crate::TxIn {
1135 previous_output: crate::OutPoint {
1136 txid: crate::Txid::from_byte_array([1; 32]), vout: 0,
1138 },
1139 script_sig: crate::ScriptSigBuf::new(),
1140 sequence: units::Sequence::ENABLE_LOCKTIME_AND_RBF,
1141 witness: crate::Witness::new(),
1142 }],
1143 outputs: vec![crate::TxOut {
1144 amount: units::Amount::ONE_BTC,
1145 script_pubkey: crate::ScriptPubKeyBuf::new(),
1146 }],
1147 };
1148
1149 let transactions = vec![non_coinbase_tx];
1150 let block = Block::new_unchecked(header, transactions);
1151
1152 let err = block.validate().unwrap_err();
1153 assert_eq!(err, InvalidBlockError::InvalidCoinbase);
1154 }
1155
1156 #[test]
1157 #[cfg(feature = "alloc")]
1158 fn block_decoder_read_limit() {
1159 let mut coinbase_in = crate::TxIn::EMPTY_COINBASE;
1160 coinbase_in.script_sig = crate::ScriptSigBuf::from_bytes(vec![0u8; 2]);
1161
1162 let block = Block::new_unchecked(
1163 dummy_header(),
1164 vec![Transaction {
1165 version: crate::transaction::Version::ONE,
1166 lock_time: crate::absolute::LockTime::ZERO,
1167 inputs: vec![coinbase_in],
1168 outputs: vec![crate::TxOut {
1169 amount: units::Amount::MIN,
1170 script_pubkey: crate::ScriptPubKeyBuf::new(),
1171 }],
1172 }],
1173 );
1174
1175 let bytes = encoding::encode_to_vec(&block);
1176 let mut view = bytes.as_slice();
1177
1178 let mut decoder = Block::decoder();
1179 assert!(decoder.read_limit() > 0);
1180 let status = decoder.push_bytes(&mut view).unwrap();
1181 assert!(status.is_ready());
1182 assert_eq!(decoder.read_limit(), 0);
1183 assert_eq!(decoder.end().unwrap(), block);
1184 }
1185
1186 #[test]
1187 #[cfg(feature = "alloc")]
1188 fn block_decoder_new() {
1189 let decoder = BlockDecoder::new();
1190 assert!(decoder.read_limit() > 0);
1191 }
1192
1193 #[test]
1194 #[cfg(feature = "alloc")]
1195 fn block_decoder_default() {
1196 let decoder = BlockDecoder::default();
1197 assert!(decoder.read_limit() > 0);
1198 }
1199
1200 #[test]
1201 #[cfg(feature = "alloc")]
1202 fn header_decoder_read_limit() {
1203 let header = dummy_header();
1204 let bytes = encoding::encode_to_vec(&header);
1205 let mut view = bytes.as_slice();
1206
1207 let mut decoder = Header::decoder();
1208 assert!(decoder.read_limit() > 0);
1209 let status = decoder.push_bytes(&mut view).unwrap();
1210 assert!(status.is_ready());
1211 assert_eq!(decoder.read_limit(), 0);
1212 assert_eq!(decoder.end().unwrap(), header);
1213 }
1214
1215 #[test]
1216 fn header_decoder_new() {
1217 let decoder = HeaderDecoder::new();
1218 assert!(decoder.read_limit() > 0);
1219 }
1220
1221 #[test]
1222 fn header_decoder_default() {
1223 let decoder = HeaderDecoder::default();
1224 assert!(decoder.read_limit() > 0);
1225 }
1226
1227 #[test]
1228 #[cfg(feature = "alloc")]
1229 fn block_check_witness_commitment_optional() {
1230 let mut header = dummy_header();
1232 header.merkle_root = TxMerkleNode::from_byte_array([0u8; 32]);
1233 let coinbase = Transaction {
1234 version: crate::transaction::Version::ONE,
1235 lock_time: crate::absolute::LockTime::ZERO,
1236 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1237 outputs: vec![],
1238 };
1239
1240 let transactions = vec![coinbase];
1241 let block = Block::new_unchecked(header, transactions);
1242
1243 let result = block.check_witness_commitment();
1244 assert_eq!(result, (true, None));
1245 }
1246
1247 #[test]
1248 #[cfg(feature = "alloc")]
1249 fn block_rejects_empty_coinbase_witness_commitment() {
1250 let mut script = Vec::from(WITNESS_COMMITMENT_MAGIC);
1251 script.extend_from_slice(&[0; 32]);
1252
1253 let coinbase = Transaction {
1254 version: crate::transaction::Version::ONE,
1255 lock_time: crate::absolute::LockTime::ZERO,
1256 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1257 outputs: vec![crate::TxOut {
1258 amount: units::Amount::ZERO,
1259 script_pubkey: crate::script::ScriptBuf::from_bytes(script),
1260 }],
1261 };
1262
1263 let transactions = vec![coinbase];
1264 let mut header = dummy_header();
1265 header.merkle_root = compute_merkle_root(&transactions).unwrap();
1266
1267 let block = Block::new_unchecked(header, transactions);
1268 assert_eq!(block.check_witness_commitment(), (false, None));
1269 assert!(matches!(block.validate(), Err(InvalidBlockError::InvalidWitnessCommitment)));
1270 }
1271
1272 #[test]
1273 #[cfg(feature = "alloc")]
1274 fn block_block_hash() {
1275 let header = dummy_header();
1276 let transactions = vec![];
1277 let block = Block::new_unchecked(header, transactions);
1278 assert_eq!(block.block_hash(), header.block_hash());
1279 }
1280
1281 #[test]
1282 fn block_hash_from_header() {
1283 let header = dummy_header();
1284 let block_hash = header.block_hash();
1285 assert_eq!(block_hash, BlockHash::from(header));
1286 }
1287
1288 #[test]
1289 fn block_hash_from_header_ref() {
1290 let header = dummy_header();
1291 let block_hash: BlockHash = BlockHash::from(&header);
1292 assert_eq!(block_hash, header.block_hash());
1293 }
1294
1295 #[test]
1296 #[cfg(feature = "alloc")]
1297 fn block_hash_from_block() {
1298 let header = dummy_header();
1299 let transactions = vec![];
1300 let block = Block::new_unchecked(header, transactions);
1301 let block_hash: BlockHash = BlockHash::from(block);
1302 assert_eq!(block_hash, header.block_hash());
1303 }
1304
1305 #[test]
1306 #[cfg(feature = "alloc")]
1307 fn block_hash_from_block_ref() {
1308 let header = dummy_header();
1309 let transactions = vec![];
1310 let block = Block::new_unchecked(header, transactions);
1311 let block_hash: BlockHash = BlockHash::from(&block);
1312 assert_eq!(block_hash, header.block_hash());
1313 }
1314
1315 #[test]
1316 #[cfg(feature = "alloc")]
1317 fn header_debug() {
1318 let header = dummy_header();
1319 let expected = format!(
1320 "Header {{ block_hash: {:?}, version: {:?}, prev_blockhash: {:?}, merkle_root: {:?}, time: {:?}, bits: {:?}, nonce: {:?} }}",
1321 header.block_hash(),
1322 header.version,
1323 header.prev_blockhash,
1324 header.merkle_root,
1325 header.time,
1326 header.bits,
1327 header.nonce
1328 );
1329 assert_eq!(format!("{:?}", header), expected);
1330 }
1331
1332 #[test]
1333 #[cfg(feature = "hex")]
1334 #[cfg(feature = "alloc")]
1335 fn header_display() {
1336 let seconds: u32 = 1_653_195_600; let header = Header {
1339 version: Version::TWO,
1340 prev_blockhash: BlockHash::from_byte_array([0xab; 32]),
1341 merkle_root: TxMerkleNode::from_byte_array([0xcd; 32]),
1342 time: BlockTime::from(seconds),
1343 bits: CompactTarget::from_consensus(0xbeef),
1344 nonce: 0xcafe,
1345 };
1346
1347 let want = concat!(
1348 "02000000", "abababababababababababababababababababababababababababababababab", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "50c38962", "efbe0000", "feca0000", );
1355 assert_eq!(want.len(), 160);
1356 assert_eq!(format!("{}", header), want);
1357
1358 let want = format!("{:.20}", want);
1360 let got = format!("{:.20}", header);
1361 assert_eq!(got, want);
1362
1363 let want = format!("{:.0}", want);
1364 let got = format!("{:.0}", header);
1365 assert_eq!(got, want);
1366 }
1367
1368 #[test]
1369 #[cfg(feature = "hex")]
1370 #[cfg(feature = "alloc")]
1371 fn header_hex() {
1372 let header = dummy_header();
1373
1374 let lower_hex = concat!(
1375 "01000000", "9999999999999999999999999999999999999999999999999999999999999999", "7777777777777777777777777777777777777777777777777777777777777777", "02000000", "03000000", "04000000", );
1382
1383 assert_eq!(lower_hex, format!("{:x}", header));
1385 assert_eq!(lower_hex, format!("{}", header));
1386
1387 let upper_hex = lower_hex.to_ascii_uppercase();
1389 assert_eq!(upper_hex, format!("{:X}", header));
1390
1391 assert_eq!(format!("{:>164}", lower_hex), format!("{:>164x}", header));
1393 assert_eq!(format!("{:<164}", lower_hex), format!("{:<164x}", header));
1394 assert_eq!(format!("{:^164}", lower_hex), format!("{:^164x}", header));
1395 assert_eq!(format!("{:_>164}", lower_hex), format!("{:_>164x}", header));
1396
1397 let lower_hex_alt = format!("0x{}", lower_hex);
1399 assert_eq!(lower_hex_alt, format!("{:#x}", header));
1400 assert_eq!(format!("0X{}", upper_hex), format!("{:#X}", header));
1401
1402 assert_eq!(format!("{:>166}", lower_hex_alt), format!("{:>#166x}", header));
1404 assert_eq!(format!("{:<166}", lower_hex_alt), format!("{:<#166x}", header));
1405 assert_eq!(format!("{:^166}", lower_hex_alt), format!("{:^#166x}", header));
1406
1407 assert_eq!(format!("{:>.20}", lower_hex_alt), format!("{:>#.20x}", header));
1409 assert_eq!(format!("{:<.20}", lower_hex_alt), format!("{:<#.20x}", header));
1410 assert_eq!(format!("{:^.20}", lower_hex_alt), format!("{:^#.20x}", header));
1411 }
1412
1413 #[test]
1414 #[cfg(feature = "hex")]
1415 #[cfg(feature = "alloc")]
1416 fn header_from_hex_str_round_trip() {
1417 let header = dummy_header();
1419
1420 let lower_hex_header = format!("{:x}", header);
1421 let upper_hex_header = format!("{:X}", header);
1422
1423 let parsed_lower = Header::from_str(&lower_hex_header).unwrap();
1425 let parsed_upper = Header::from_str(&upper_hex_header).unwrap();
1426
1427 assert_eq!(header, parsed_lower);
1429 assert_eq!(header, parsed_upper);
1430 }
1431
1432 #[cfg(feature = "alloc")]
1433 fn dummy_block() -> Block {
1434 let header = Header {
1435 version: Version::ONE,
1436 #[rustfmt::skip]
1437 prev_blockhash: BlockHash::from_byte_array([
1438 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1439 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1440 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1441 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1442 ]),
1443 #[rustfmt::skip]
1444 merkle_root: TxMerkleNode::from_byte_array([
1445 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1446 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1447 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1448 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1449 ]),
1450 time: BlockTime::from(1_742_979_600), bits: CompactTarget::from_consensus(12_345_678),
1452 nonce: 1024,
1453 };
1454
1455 let block: u32 = 741_521;
1456 let transactions = vec![Transaction {
1457 version: crate::transaction::Version::ONE,
1458 lock_time: units::absolute::LockTime::from_height(block).unwrap(),
1459 inputs: vec![crate::transaction::TxIn {
1460 previous_output: crate::transaction::OutPoint::COINBASE_PREVOUT,
1461 script_sig: crate::script::ScriptSigBuf::from_bytes(vec![0x51, 0x51]),
1463 sequence: crate::sequence::Sequence::MAX,
1464 witness: crate::witness::Witness::new(),
1465 }],
1466 outputs: vec![crate::transaction::TxOut {
1467 amount: units::Amount::ONE_SAT,
1468 script_pubkey: crate::script::ScriptPubKeyBuf::new(),
1469 }],
1470 }];
1471 Block::new_unchecked(header, transactions)
1472 }
1473
1474 #[test]
1475 #[cfg(feature = "hex")]
1476 #[cfg(feature = "alloc")]
1477 fn block_hex() {
1478 let header = dummy_header();
1479 let transactions = vec![Transaction {
1480 version: crate::transaction::Version::ONE,
1481 lock_time: crate::locktime::absolute::LockTime::ZERO,
1482 inputs: vec![],
1483 outputs: vec![],
1484 }];
1485 let block = Block::new_unchecked(header, transactions);
1486
1487 let want = "010000009999999999999999999999999999999999999999999999999999999999999999777777777777777777777777777777777777777777777777777777777777777702000000030000000400000001010000000001000000000000";
1490
1491 assert_eq!(format!("{}", block), want);
1492 assert_eq!(format!("{:x}", block), want);
1493 assert_eq!(format!("0x{want}"), format!("{:#x}", block));
1494 assert_eq!(format!("0X{}", want.to_ascii_uppercase()), format!("{:#X}", block));
1495 assert_eq!(format!("{:>166}", format!("0x{want}")), format!("{:>#166x}", block));
1496 assert_eq!(format!("{:.20}", want), format!("{:.20x}", block));
1497
1498 let want =
1500 want.chars().map(|chr| chr.to_ascii_uppercase()).collect::<alloc::string::String>();
1501 assert_eq!(want, format!("{:X}", block));
1502 }
1503
1504 #[test]
1505 #[cfg(feature = "hex")]
1506 #[cfg(feature = "alloc")]
1507 fn block_from_hex_str_round_trip() {
1508 let block = dummy_block();
1509
1510 let lower_hex_block = format!("{:x}", block);
1511 let upper_hex_block = format!("{:X}", block);
1512
1513 let parsed_lower = Block::from_str(&lower_hex_block).unwrap();
1514 let parsed_upper = Block::from_str(&upper_hex_block).unwrap();
1515
1516 assert_eq!(parsed_lower, block);
1517 assert_eq!(parsed_upper, block);
1518 }
1519
1520 #[test]
1521 #[cfg(feature = "alloc")]
1522 fn block_decode() {
1523 let original = dummy_block();
1524
1525 let encoded = encoding::encode_to_vec(&original);
1526 let decoded: Block = encoding::decode_from_slice(encoded.as_slice()).unwrap();
1527
1528 assert_eq!(decoded, original);
1529 }
1530
1531 #[test]
1533 #[cfg(feature = "alloc")]
1534 #[cfg(feature = "hex")]
1535 fn merkle_tree_hash_collision() {
1536 const BLOCK_128461_HEX: &str = "01000000166208c96de305f2a304130a1b53727abf8fb77e8a3cfe2a831e000000000000d4fd086755b4d46221362a09a4228bed60d729d22362b87803ff44b72c138ec04a8ce94d2194261af9551f720701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08042194261a026005ffffffff018076242a01000000434104390e51c3d66d5ee10327395872e33bc232e9e1660225c9f88fa594fdcdcd785d86b1152fb380a63cdf57d8cf2345a55878412a6864656b158704e0b734b3fd9dac000000000100000001f591edc180a889b21a45b6bd5b5e0017d4137dae9695703107ac1e6e878c9f02000000008b483045022100e066df28b29bf18bfcd8da11ea576a6f502f59e7b1d37e2e849ee4648008962b022023be840ec01ffa6860b5577bf0b8546541f40c287eb57b8b421a1396c7aea583014104add16286f51f68cee1b436d0c29a41a59fa8bd224eb6bec34b073512303c70fc3d630cb4952416ef02340c56bee2eef294659b4023ea8a3d90a297bdb54321f9ffffffff02508470b5000000001976a91472579bbeaeca0802fde07ce88f946b64da63989388ac40aeeb02000000001976a914d2a7410246b5ece345aa821af89bff0b6fa3bcaa88ac0000000001000000016197cb143d4cef51389076fdee3f62c294b65bc9aff217a6c71b9dd987e22754000000008c493046022100bf174e942e4619f4e470b5d8b1c0c8ded9e2f7a6616c073c5ab05cc9d699ede3022100a642fa9d0bcc89523635f9468e4813a120b233a249678de0ebf7ba398a4205f6014104122979c0ac1c3af2aa84b4c1d6a9b3b6fa491827f1a2ba37c4b58bdecd644438da715497a44b16aedbadbd18cf9765cdb36851284f643ed743c4365798dd314affffffff02c0404384000000001976a91443cd8fbad7421a53f9e899a2c9761259705d465b88acc0f4f50e000000001976a9142f6c963506b0a2c93a09a92171957e9e7e11a7a388ac00000000010000000228a11f953c26d558a8299ad9dc61279d7abc9a4059820b614bf403c05e471c481d0000008b48304502205baff189016e6fee8e0faa9eebdc8f150d2d3815007719ceccabd995607bb0b0022100f4cc49ef0b29561e976bf6f6f7ae135f665b8dd38a67634bb6bbe74c0da9c1f7014104dd5920aedc3f79ace9c8061f3724812f5b218ea81d175dd990071175874d6c79025f9db516ab23975e510645aabc4ee699cc5c24358a403d15a7736a504399f8ffffffff191b06773a7cec0bb30539f185edbf1d139f9756071c6ae395c1c29f3e2484f6010000008c493046022100c7123436476f923cd8dacbe132f5128b529baa194c9aedc570402d8d2d7902ac02210094e6974695265d96d5859ab493df00c90b62a84dcc33a05753aea23b38c249670141041d878bc5438ff439490e71d059e6b687e511336c0aa53e0d129663c91db71cfe20008891f1e4780bf1139ec9c9e81bfd2e3ea9009608a78d96a5a3a5bf7812baffffffff0200093d00000000001976a914fd0d4c3d0963db8358bd01ba6f386d4c5ef2e30288ac0084d717000000001976a914dcb1e8e699eb9f07a1ddfd5d764aa74359ddd93088ac00000000010000000118e2286c42643e6146669b0f5ee35454fe256aac2b1401dbeefd941f2e6d2074000000008b483045022100edec1c5078fed29d808282d62f167eb3f0ea6a6655f3869c12eca9c63d8463c2022031a3ae430be137932059b4a3e3fb7f1e1f2a05065dbc47c3142972de45c76daa01410423162e5ac10ec46c4a142fea3197cc66e614b9f28f014882ebc8271c4ab6022e474ccdc246445dd2479f9de217e8aaf4d770da15aff1078d329c02e0f4de8d77ffffffff02b00ac165000000001976a914f543a7f0dfcd621a05c646810ba94da791ed14c488ac80de8002000000001976a9144763f6309b3aca0bff49ed6365ffbd791b1afc5d88ac0000000001000000014e3632994e6cbcae4122bf9e8de242aa1d7c13bf6d045392fa69fa92353f13cf000000008c493046022100c6879938322e9945dae2404a2b104b534df7fdab5927a30a57a12418d619c3b8022100c53331f402010cbdc8297d7a827154e42263fc2f6cef6e56b85bbc061d5e30810141047e717e70b8c5e928bc2c482662dbe9007113f7a5fb0360da1d2f193add960fed97ab3163e85c02b127829d694ab4a796326918d4f639d0b19345f7558406667dffffffff0270c8b165000000001976a9146c908731300d5c0a4215ba3bb3041b4f313d14f688ac40420f00000000001976a91457b01e2a6bf178a10a0e36cd3e301a41ac58b68b88ac000000000100000001a2e94f26db15d7098104a3616b650cc7490eca961a23111c12c3d94f593ab3bc000000008c493046022100b355076f2c956d7565d44fdf589ebdbdff70abcd806c71845b47d31c3579cbc00221008352a03c5276ba481ae92a2327307ad1ce9b234be7386c105fb914ceb9c63341014104872ee8390f11c8ac309df772362614ff7c99f98e1fd68888c5e8765d630c93ae86fcd33922b17f5da490ea14a9f9002ef4e7fb11166ba399f9794296ca02e401ffffffff02f07d5460000000001976a914ff1da11fbd50b9906e78c694169c19902d2ee20388ac804a5d05000000001976a91444d5774b8277c59a07ed9dce1225e2d24a3faab188ac00000000";
1539 let bytes = hex::decode_to_array::<1948>(BLOCK_128461_HEX).unwrap();
1540 let valid_block: Block<Unchecked> = encoding::decode_from_slice(&bytes).unwrap();
1541 let (header, mut transactions) = valid_block.clone().into_parts();
1542 transactions.push(transactions[6].clone());
1543 let forged_block = Block::new_unchecked(header, transactions);
1544
1545 assert!(valid_block.validate().is_ok());
1546 assert!(forged_block.validate().is_err());
1547 }
1548
1549 #[test]
1550 #[cfg(feature = "alloc")]
1551 fn witness_commitment_from_coinbase_simple() {
1552 let mut pubkey_bytes = [0; 38];
1554 pubkey_bytes[0..6].copy_from_slice(&WITNESS_COMMITMENT_MAGIC);
1555 let witness_commitment =
1556 WitnessCommitment::from_byte_array(pubkey_bytes[6..38].try_into().unwrap());
1557 let commitment_script = crate::script::ScriptBuf::from_bytes(pubkey_bytes.to_vec());
1558
1559 let tx = Transaction {
1561 version: crate::transaction::Version::ONE,
1562 lock_time: crate::absolute::LockTime::ZERO,
1563 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1564 outputs: vec![crate::TxOut {
1565 amount: units::Amount::MIN,
1566 script_pubkey: commitment_script,
1567 }],
1568 };
1569
1570 let extracted = witness_commitment_from_coinbase(&tx);
1572 assert_eq!(extracted, Some(witness_commitment));
1573 }
1574
1575 #[test]
1576 #[cfg(feature = "alloc")]
1577 fn witness_commitment_from_non_coinbase_returns_none() {
1578 let tx = Transaction {
1579 version: crate::transaction::Version::ONE,
1580 lock_time: crate::absolute::LockTime::ZERO,
1581 inputs: vec![crate::TxIn {
1582 previous_output: crate::OutPoint {
1583 txid: crate::Txid::from_byte_array([1; 32]),
1584 vout: 0,
1585 },
1586 script_sig: crate::ScriptSigBuf::new(),
1587 sequence: units::Sequence::ENABLE_LOCKTIME_AND_RBF,
1588 witness: crate::Witness::new(),
1589 }],
1590 outputs: vec![crate::TxOut {
1591 amount: units::Amount::MIN,
1592 script_pubkey: crate::ScriptPubKeyBuf::new(),
1593 }],
1594 };
1595
1596 assert!(witness_commitment_from_coinbase(&tx).is_none());
1597 }
1598
1599 #[test]
1600 #[cfg(feature = "alloc")]
1601 fn block_check_witness_commitment_empty_script_pubkey() {
1602 let mut txin = crate::TxIn::EMPTY_COINBASE;
1603 let push = [11_u8];
1604 txin.witness.push(push);
1605
1606 let tx = Transaction {
1607 version: crate::transaction::Version::ONE,
1608 lock_time: crate::absolute::LockTime::ZERO,
1609 inputs: vec![txin],
1610 outputs: vec![crate::TxOut {
1611 amount: units::Amount::MIN,
1612 script_pubkey: crate::script::ScriptBuf::new(),
1614 }],
1615 };
1616
1617 let block = Block::new_unchecked(dummy_header(), vec![tx]);
1618 let result = block.check_witness_commitment();
1619 assert_eq!(result, (false, None)); }
1621
1622 #[test]
1623 #[cfg(feature = "alloc")]
1624 fn block_check_witness_commitment_non_coinbase() {
1625 let tx = Transaction {
1626 version: crate::transaction::Version::ONE,
1627 lock_time: crate::absolute::LockTime::ZERO,
1628 inputs: vec![crate::TxIn {
1629 previous_output: crate::OutPoint {
1630 txid: crate::Txid::from_byte_array([1; 32]),
1631 vout: 0,
1632 },
1633 script_sig: crate::ScriptSigBuf::new(),
1634 sequence: units::Sequence::ENABLE_LOCKTIME_AND_RBF,
1635 witness: crate::Witness::from_slice(&[&[11_u8; 32][..]]),
1636 }],
1637 outputs: vec![crate::TxOut {
1638 amount: units::Amount::MIN,
1639 script_pubkey: crate::ScriptPubKeyBuf::new(),
1640 }],
1641 };
1642
1643 let block = Block::new_unchecked(dummy_header(), vec![tx]);
1644 assert_eq!(block.check_witness_commitment(), (false, None));
1645 }
1646
1647 #[test]
1648 #[cfg(feature = "alloc")]
1649 fn block_check_witness_commitment_no_transactions() {
1650 let empty_block = Block::new_unchecked(dummy_header(), vec![]);
1652 let result = empty_block.check_witness_commitment();
1653 assert_eq!(result, (false, None));
1654 }
1655
1656 #[test]
1657 #[cfg(feature = "alloc")]
1658 #[cfg(feature = "hex")]
1659 fn block_check_witness_commitment_with_witness() {
1660 let mut txin = crate::TxIn::EMPTY_COINBASE;
1661 let witness_bytes: [u8; 32] = [11u8; 32];
1663 txin.witness.push(witness_bytes);
1664
1665 let script_pubkey_bytes = hex::decode_to_array::<38>(
1667 "6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb",
1668 )
1669 .unwrap();
1670 let tx1 = Transaction {
1671 version: crate::transaction::Version::ONE,
1672 lock_time: crate::absolute::LockTime::ZERO,
1673 inputs: vec![txin],
1674 outputs: vec![crate::TxOut {
1675 amount: units::Amount::MIN,
1676 script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()),
1677 }],
1678 };
1679
1680 let tx2 = Transaction {
1681 version: crate::transaction::Version::ONE,
1682 lock_time: crate::absolute::LockTime::ZERO,
1683 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1684 outputs: vec![crate::TxOut {
1685 amount: units::Amount::MIN,
1686 script_pubkey: crate::script::ScriptBuf::new(),
1687 }],
1688 };
1689
1690 let block = Block::new_unchecked(dummy_header(), vec![tx1, tx2]);
1691 let result = block.check_witness_commitment();
1692
1693 let exp_bytes = hex::decode_to_array::<32>(
1694 "fb848679079938b249a12f14b72d56aeb116df79254e17cdf72b46523bcb49db",
1695 )
1696 .unwrap();
1697 let expected = WitnessMerkleNode::from_byte_array(exp_bytes);
1698 assert_eq!(result, (true, Some(expected)));
1699 }
1700
1701 #[test]
1702 #[cfg(feature = "alloc")]
1703 #[cfg(feature = "hex")]
1704 fn block_check_witness_commitment_invalid_witness() {
1705 let mut txin = crate::TxIn::EMPTY_COINBASE;
1706 let witness_bytes: [u8; 32] = [11u8; 32];
1707 txin.witness.push(witness_bytes);
1709 txin.witness.push([12u8]);
1710
1711 let script_pubkey_bytes = hex::decode_to_array::<38>(
1712 "6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb",
1713 )
1714 .unwrap();
1715 let tx1 = Transaction {
1716 version: crate::transaction::Version::ONE,
1717 lock_time: crate::absolute::LockTime::ZERO,
1718 inputs: vec![txin],
1719 outputs: vec![crate::TxOut {
1720 amount: units::Amount::MIN,
1721 script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()),
1722 }],
1723 };
1724
1725 let tx2 = Transaction {
1726 version: crate::transaction::Version::ONE,
1727 lock_time: crate::absolute::LockTime::ZERO,
1728 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1729 outputs: vec![crate::TxOut {
1730 amount: units::Amount::MIN,
1731 script_pubkey: crate::script::ScriptBuf::new(),
1732 }],
1733 };
1734
1735 let mut header = dummy_header();
1736 let transactions = vec![tx1, tx2];
1737 header.merkle_root = compute_merkle_root(&transactions).unwrap();
1738
1739 let block = Block::new_unchecked(header, transactions);
1740 assert_eq!(block.check_witness_commitment(), (false, None));
1741 assert!(matches!(block.validate(), Err(InvalidBlockError::InvalidWitnessCommitment)));
1742 }
1743
1744 #[test]
1745 #[cfg(feature = "alloc")]
1746 #[cfg(feature = "hex")]
1747 fn block_check_witness_commitment_invalid_commitment() {
1748 let mut txin = crate::TxIn::EMPTY_COINBASE;
1749 txin.witness.push([11u8; 32]);
1750
1751 let mut script_pubkey_bytes = hex::decode_to_array::<38>(
1752 "6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb",
1753 )
1754 .unwrap();
1755 script_pubkey_bytes[37] ^= 1;
1756
1757 let tx1 = Transaction {
1758 version: crate::transaction::Version::ONE,
1759 lock_time: crate::absolute::LockTime::ZERO,
1760 inputs: vec![txin],
1761 outputs: vec![crate::TxOut {
1762 amount: units::Amount::MIN,
1763 script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()),
1764 }],
1765 };
1766
1767 let tx2 = Transaction {
1768 version: crate::transaction::Version::ONE,
1769 lock_time: crate::absolute::LockTime::ZERO,
1770 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1771 outputs: vec![crate::TxOut {
1772 amount: units::Amount::MIN,
1773 script_pubkey: crate::script::ScriptBuf::new(),
1774 }],
1775 };
1776
1777 let block = Block::new_unchecked(dummy_header(), vec![tx1, tx2]);
1778 assert_eq!(block.check_witness_commitment(), (false, None));
1779 }
1780
1781 #[test]
1782 fn version_encoder_emits_consensus_bytes() {
1783 let version = Version::from_consensus(123_456_789);
1784
1785 check_encode(&version, &version.to_consensus().to_le_bytes());
1786 }
1787
1788 #[test]
1789 fn version_decoder_end_and_read_limit() {
1790 let mut decoder = VersionDecoder::new();
1791 let bytes_arr = Version::TWO.to_consensus().to_le_bytes();
1792 let mut bytes = bytes_arr.as_slice();
1793
1794 assert!(decoder.read_limit() > 0);
1795
1796 let status = decoder.push_bytes(&mut bytes).unwrap();
1797 assert!(status.is_ready());
1798 assert!(bytes.is_empty());
1799
1800 assert_eq!(decoder.read_limit(), 0);
1801 let decoded = decoder.end().unwrap();
1802 assert_eq!(decoded, Version::TWO);
1803 }
1804
1805 #[test]
1806 fn version_decoder_default_roundtrip() {
1807 let version = Version::from_consensus(123_456_789);
1808 let mut decoder = VersionDecoder::default();
1809 let consensus = version.to_consensus().to_le_bytes();
1810 let mut bytes = consensus.as_slice();
1811 decoder.push_bytes(&mut bytes).unwrap();
1812
1813 assert_eq!(decoder.end().unwrap(), version);
1814 }
1815
1816 #[test]
1817 #[cfg(feature = "alloc")]
1818 fn version_decodable_decoder() {
1819 let decoder = Version::decoder();
1820 assert!(decoder.read_limit() > 0);
1821 }
1822
1823 #[test]
1824 #[cfg(feature = "alloc")]
1825 fn block_decoder_error() {
1826 fn is_first(err: &BlockDecoderError) -> bool {
1827 match err.0 {
1828 encoding::Decoder2Error::First(_) => true,
1829 encoding::Decoder2Error::Second(_) => false,
1830 }
1831 }
1832
1833 fn is_second(err: &BlockDecoderError) -> bool {
1834 match err.0 {
1835 encoding::Decoder2Error::First(_) => false,
1836 encoding::Decoder2Error::Second(_) => true,
1837 }
1838 }
1839
1840 let err_first = Block::decoder().end().unwrap_err();
1841 assert!(is_first(&err_first));
1842 assert!(!is_second(&err_first));
1843 assert!(!err_first.to_string().is_empty());
1844 #[cfg(feature = "std")]
1845 assert!(std::error::Error::source(&err_first).is_some());
1846
1847 let mut bytes = encoding::encode_to_vec(&dummy_header());
1850 bytes.push(1u8);
1851 let mut view = bytes.as_slice();
1852
1853 let mut decoder = Block::decoder();
1854 assert!(decoder.push_bytes(&mut view).unwrap().needs_more());
1855 assert!(view.is_empty());
1856
1857 let err_second = decoder.end().unwrap_err();
1858 assert!(is_second(&err_second));
1859 assert!(!is_first(&err_second));
1860 assert!(!err_second.to_string().is_empty());
1861 #[cfg(feature = "std")]
1862 assert!(std::error::Error::source(&err_second).is_some());
1863 }
1864
1865 #[test]
1866 #[cfg(feature = "alloc")]
1867 fn header_decoder_error() {
1868 let header_bytes = encoding::encode_to_vec(&dummy_header());
1869 let lengths = [0usize, 4, 36, 68, 72, 76];
1871
1872 for &len in &lengths {
1873 let mut decoder = Header::decoder();
1874 let mut slice = header_bytes[..len].as_ref();
1875 decoder.push_bytes(&mut slice).unwrap();
1876 let err = decoder.end().unwrap_err();
1877 match len {
1878 0 => assert!(matches!(err, HeaderDecoderError::Version(_))),
1879 4 => assert!(matches!(err, HeaderDecoderError::PrevBlockhash(_))),
1880 36 => assert!(matches!(err, HeaderDecoderError::MerkleRoot(_))),
1881 68 => assert!(matches!(err, HeaderDecoderError::Time(_))),
1882 72 => assert!(matches!(err, HeaderDecoderError::Bits(_))),
1883 76 => assert!(matches!(err, HeaderDecoderError::Nonce(_))),
1884 _ => unreachable!(),
1885 }
1886 assert!(!err.to_string().is_empty());
1887 #[cfg(feature = "std")]
1888 assert!(std::error::Error::source(&err).is_some());
1889 }
1890 }
1891
1892 #[test]
1893 #[cfg(feature = "alloc")]
1894 fn invalid_block_error() {
1895 #[cfg(feature = "std")]
1896 use std::error::Error as _;
1897
1898 let variants = [
1899 InvalidBlockError::InvalidMerkleRoot,
1900 InvalidBlockError::InvalidWitnessCommitment,
1901 InvalidBlockError::NoTransactions,
1902 InvalidBlockError::InvalidCoinbase,
1903 ];
1904
1905 for variant in variants {
1906 assert!(!variant.to_string().is_empty());
1907 #[cfg(feature = "std")]
1908 assert!(variant.source().is_none());
1909 }
1910 }
1911
1912 #[test]
1913 #[cfg(feature = "alloc")]
1914 fn version_decoder_error() {
1915 let err = VersionDecoder::new().end().unwrap_err();
1916 assert!(!err.to_string().is_empty());
1917 #[cfg(feature = "std")]
1918 assert!(std::error::Error::source(&err).is_some());
1919 }
1920
1921 #[test]
1922 #[cfg(feature = "alloc")]
1923 #[cfg(feature = "hex")]
1924 fn parse_block_error() {
1925 let err = Block::from_str("00").unwrap_err();
1926 assert!(!err.to_string().is_empty());
1927 #[cfg(feature = "std")]
1928 assert!(std::error::Error::source(&err).is_some());
1929 }
1930
1931 #[test]
1932 #[cfg(feature = "alloc")]
1933 #[cfg(feature = "hex")]
1934 fn parse_header_error() {
1935 let err = Header::from_str("00").unwrap_err();
1936 assert!(!err.to_string().is_empty());
1937 #[cfg(feature = "std")]
1938 assert!(std::error::Error::source(&err).is_some());
1939 }
1940
1941 #[cfg(feature = "alloc")]
1943 #[cfg(feature = "hex")]
1944 #[cfg(feature = "serde")]
1945 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1946 struct Adt {
1947 #[serde(with = "encoding::serde_as_consensus")]
1948 header: Header,
1949 #[serde(with = "encoding::serde_as_consensus")]
1950 block: Block,
1951 }
1952
1953 #[test]
1954 #[cfg(feature = "alloc")]
1955 #[cfg(feature = "hex")]
1956 #[cfg(feature = "serde")]
1957 fn can_serde_as_consensus_json() {
1958 let orig = Adt { header: dummy_header(), block: dummy_block() };
1959
1960 let json = serde_json::to_string(&orig).expect("failed to serialize");
1961
1962 let want = "{\"header\":\"0100000099999999999999999999999999999999999999999999999999999999999999997777777777777777777777777777777777777777777777777777777777777777020000000300000004000000\",\"block\":\"01000000dcbadcbadcbadcbadcbadcbadcbadcbadcbadcbadcbadcbadcbadcbadcbadcbaabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd10c2e3674e61bc00000400000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff0101000000000000000091500b00\"}";
1963 assert_eq!(json, want);
1964
1965 let roundtrip: Adt = serde_json::from_str(&json).expect("failed to deserialize");
1966 assert_eq!(roundtrip, orig);
1967 }
1968
1969 #[test]
1970 #[cfg(feature = "alloc")]
1971 #[cfg(feature = "hex")]
1972 #[cfg(feature = "serde")]
1973 fn can_serde_as_consensus_bincode() {
1974 let orig = Adt { header: dummy_header(), block: dummy_block() };
1975
1976 let bytes = bincode::serialize(&orig).expect("failed to serialize");
1978
1979 let roundtrip: Adt = bincode::deserialize(&bytes).expect("failed to deserialize");
1980 assert_eq!(roundtrip, orig);
1981 }
1982
1983 #[test]
1984 #[cfg(feature = "alloc")]
1985 #[cfg(feature = "hex")]
1986 fn block_version() {
1987 let block = hex!("ffffff7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1988 let decode: Result<Block<Unchecked>, _> = encoding::decode_from_slice(&block);
1989 assert!(decode.is_ok());
1990
1991 let real_decode = decode.unwrap().assume_checked(None);
1992 assert_eq!(real_decode.header().version, Version::from_consensus(2_147_483_647));
1993
1994 let block2 = hex!("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1995 let decode2: Result<Block<Unchecked>, _> = encoding::decode_from_slice(&block2);
1996 assert!(decode2.is_ok());
1997 let real_decode2 = decode2.unwrap().assume_checked(None);
1998 assert_eq!(real_decode2.header().version, Version::from_consensus(-2_147_483_648));
1999 }
2000}