1use core::convert::Infallible;
11use core::fmt;
12#[cfg(feature = "alloc")]
13use core::marker::PhantomData;
14
15#[cfg(feature = "arbitrary")]
16use arbitrary::{Arbitrary, Unstructured};
17use encoding::Encodable;
18#[cfg(feature = "hex")]
19use encoding::EncodableByteIter;
20#[cfg(feature = "alloc")]
21use encoding::{
22 CompactSizeEncoder, Decodable, Decoder, Decoder2, Decoder6, Encoder2, SliceEncoder, VecDecoder,
23};
24use hashes::{sha256d, HashEngine as _};
25use internals::write_err;
26
27#[cfg(feature = "alloc")]
28use crate::pow::{CompactTargetDecoder, CompactTargetDecoderError};
29#[cfg(feature = "alloc")]
30use crate::prelude::Vec;
31#[cfg(feature = "alloc")]
32use crate::time::{BlockTimeDecoder, BlockTimeDecoderError};
33#[cfg(feature = "alloc")]
34use crate::transaction::{TxMerkleNodeDecoder, TxMerkleNodeDecoderError};
35use crate::{BlockTime, CompactTarget, TxMerkleNode};
36#[cfg(feature = "alloc")]
37use crate::{Transaction, WitnessMerkleNode};
38
39#[rustfmt::skip] #[doc(inline)]
41pub use units::block::{BlockHeight, BlockHeightDecoder, BlockHeightEncoder, BlockHeightInterval, BlockMtp, BlockMtpInterval};
42#[doc(no_inline)]
44pub use units::block::{BlockHeightDecoderError, TooBigForRelativeHeightError};
45
46#[doc(inline)]
47pub use crate::hash_types::{
48 BlockHash, BlockHashDecoder, BlockHashDecoderError, BlockHashEncoder, WitnessCommitment,
49};
50
51#[cfg(feature = "alloc")]
60pub trait Validation: sealed::Validation + Sync + Send + Sized + Unpin {
61 const IS_CHECKED: bool;
63}
64
65#[cfg(feature = "alloc")]
77#[derive(PartialEq, Eq, Clone, Debug)]
78pub struct Block<V = Unchecked>
79where
80 V: Validation,
81{
82 header: Header,
84 transactions: Vec<Transaction>,
86 witness_root: Option<WitnessMerkleNode>,
88 _marker: PhantomData<V>,
90}
91
92#[cfg(feature = "alloc")]
93impl Block<Unchecked> {
94 #[inline]
96 pub fn new_unchecked(header: Header, transactions: Vec<Transaction>) -> Self {
97 Self { header, transactions, witness_root: None, _marker: PhantomData::<Unchecked> }
98 }
99
100 #[must_use]
104 #[inline]
105 pub fn assume_checked(self, witness_root: Option<WitnessMerkleNode>) -> Block<Checked> {
106 Block {
107 header: self.header,
108 transactions: self.transactions,
109 witness_root,
110 _marker: PhantomData::<Checked>,
111 }
112 }
113
114 #[inline]
116 pub fn into_parts(self) -> (Header, Vec<Transaction>) { (self.header, self.transactions) }
117
118 #[inline]
120 pub fn as_parts(&self) -> (&Header, &[Transaction]) { (&self.header, &self.transactions) }
121
122 pub fn validate(self) -> Result<Block<Checked>, InvalidBlockError> {
137 if self.transactions.is_empty() {
138 return Err(InvalidBlockError::NoTransactions);
139 }
140
141 if !self.transactions[0].is_coinbase() {
142 return Err(InvalidBlockError::InvalidCoinbase);
143 }
144
145 if !self.check_merkle_root() {
146 return Err(InvalidBlockError::InvalidMerkleRoot);
147 }
148
149 match self.check_witness_commitment() {
150 (false, _) => Err(InvalidBlockError::InvalidWitnessCommitment),
151 (true, witness_root) => {
152 let block = Self::new_unchecked(self.header, self.transactions);
153 Ok(block.assume_checked(witness_root))
154 }
155 }
156 }
157
158 pub fn check_merkle_root(&self) -> bool {
160 match compute_merkle_root(&self.transactions) {
161 Some(merkle_root) => self.header.merkle_root == merkle_root,
162 None => false,
163 }
164 }
165
166 pub fn compute_witness_commitment(
168 &self,
169 witness_reserved_value: &[u8],
170 ) -> Option<(WitnessMerkleNode, WitnessCommitment)> {
171 compute_witness_root(&self.transactions).map(|witness_root| {
172 let mut encoder = sha256d::Hash::engine();
173 encoder = hashes::encode_to_engine(&witness_root, encoder);
174 encoder.input(witness_reserved_value);
175 let witness_commitment = WitnessCommitment::from_byte_array(
176 sha256d::Hash::from_engine(encoder).to_byte_array(),
177 );
178 (witness_root, witness_commitment)
179 })
180 }
181
182 pub fn check_witness_commitment(&self) -> (bool, Option<WitnessMerkleNode>) {
185 if self.transactions.is_empty() {
186 return (false, None);
187 }
188
189 if self.transactions.iter().all(|t| t.inputs.iter().all(|i| i.witness.is_empty())) {
191 return (true, 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 }
210
211 (false, None)
212 }
213}
214
215#[cfg(feature = "alloc")]
216impl Block<Checked> {
217 #[inline]
219 pub fn header(&self) -> &Header { &self.header }
220
221 #[inline]
223 pub fn transactions(&self) -> &[Transaction] { &self.transactions }
224
225 #[inline]
230 pub fn cached_witness_root(&self) -> Option<WitnessMerkleNode> { self.witness_root }
231}
232
233#[cfg(feature = "alloc")]
234impl<V: Validation> Block<V> {
235 #[inline]
237 pub fn block_hash(&self) -> BlockHash { self.header.block_hash() }
238}
239
240#[cfg(feature = "alloc")]
241impl From<Block> for BlockHash {
242 #[inline]
243 fn from(block: Block) -> Self { block.block_hash() }
244}
245
246#[cfg(feature = "alloc")]
247impl From<&Block> for BlockHash {
248 #[inline]
249 fn from(block: &Block) -> Self { block.block_hash() }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
254#[cfg(feature = "alloc")]
255pub enum Checked {}
256
257#[cfg(feature = "alloc")]
258impl Validation for Checked {
259 const IS_CHECKED: bool = true;
260}
261
262#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
264#[cfg(feature = "alloc")]
265pub enum Unchecked {}
266
267#[cfg(feature = "alloc")]
268impl Validation for Unchecked {
269 const IS_CHECKED: bool = false;
270}
271
272#[cfg(feature = "alloc")]
273mod sealed {
274 pub trait Validation {}
276 impl Validation for super::Checked {}
277 impl Validation for super::Unchecked {}
278}
279
280#[cfg(feature = "alloc")]
281encoding::encoder_newtype! {
282 pub struct BlockEncoder<'e>(
284 Encoder2<HeaderEncoder<'e>, Encoder2<CompactSizeEncoder, SliceEncoder<'e, Transaction>>>
285 );
286}
287
288#[cfg(feature = "alloc")]
289impl Encodable for Block {
290 type Encoder<'e>
291 = Encoder2<HeaderEncoder<'e>, Encoder2<CompactSizeEncoder, SliceEncoder<'e, Transaction>>>
292 where
293 Self: 'e;
294
295 fn encoder(&self) -> Self::Encoder<'_> {
296 Encoder2::new(
297 self.header.encoder(),
298 Encoder2::new(
299 CompactSizeEncoder::new(self.transactions.len()),
300 SliceEncoder::without_length_prefix(&self.transactions),
301 ),
302 )
303 }
304}
305
306#[cfg(feature = "alloc")]
307type BlockInnerDecoder = Decoder2<HeaderDecoder, VecDecoder<Transaction>>;
308
309#[cfg(feature = "alloc")]
313pub struct BlockDecoder(BlockInnerDecoder);
314
315#[cfg(feature = "alloc")]
316impl Decoder for BlockDecoder {
317 type Output = Block;
318 type Error = BlockDecoderError;
319
320 #[inline]
321 fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
322 self.0.push_bytes(bytes).map_err(BlockDecoderError)
323 }
324
325 #[inline]
326 fn end(self) -> Result<Self::Output, Self::Error> {
327 let (header, transactions) = self.0.end().map_err(BlockDecoderError)?;
328 Ok(Self::Output::new_unchecked(header, transactions))
329 }
330
331 #[inline]
332 fn read_limit(&self) -> usize { self.0.read_limit() }
333}
334
335#[cfg(feature = "alloc")]
336impl Decodable for Block {
337 type Decoder = BlockDecoder;
338 fn decoder() -> Self::Decoder {
339 BlockDecoder(Decoder2::new(Header::decoder(), VecDecoder::<Transaction>::new()))
340 }
341}
342
343#[cfg(feature = "alloc")]
345#[derive(Debug, Clone, PartialEq, Eq)]
346pub struct BlockDecoderError(<BlockInnerDecoder as Decoder>::Error);
347
348#[cfg(feature = "alloc")]
349impl From<Infallible> for BlockDecoderError {
350 fn from(never: Infallible) -> Self { match never {} }
351}
352
353#[cfg(feature = "alloc")]
354impl fmt::Display for BlockDecoderError {
355 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
356 match &self.0 {
357 encoding::Decoder2Error::First(ref e) => write_err!(f, "block decoder error"; e),
358 encoding::Decoder2Error::Second(ref e) => write_err!(f, "block decoder error"; e),
359 }
360 }
361}
362
363#[cfg(feature = "alloc")]
364#[cfg(feature = "std")]
365impl std::error::Error for BlockDecoderError {
366 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
367 match &self.0 {
368 encoding::Decoder2Error::First(ref e) => Some(e),
369 encoding::Decoder2Error::Second(ref e) => Some(e),
370 }
371 }
372}
373
374#[cfg(feature = "alloc")]
376#[derive(Debug, Clone, PartialEq, Eq)]
377#[non_exhaustive]
378pub enum InvalidBlockError {
379 InvalidMerkleRoot,
381 InvalidWitnessCommitment,
383 NoTransactions,
385 InvalidCoinbase,
387}
388
389#[cfg(feature = "alloc")]
390impl From<Infallible> for InvalidBlockError {
391 fn from(never: Infallible) -> Self { match never {} }
392}
393
394#[cfg(feature = "alloc")]
395impl fmt::Display for InvalidBlockError {
396 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
397 match self {
398 Self::InvalidMerkleRoot =>
399 write!(f, "header Merkle root does not match the calculated Merkle root"),
400 Self::InvalidWitnessCommitment => write!(f, "the witness commitment in coinbase transaction does not match the calculated witness_root"),
401 Self::NoTransactions => write!(f, "block has no transactions (missing coinbase)"),
402 Self::InvalidCoinbase =>
403 write!(f, "the first transaction is not a valid coinbase transaction"),
404 }
405 }
406}
407
408#[cfg(feature = "alloc")]
409#[cfg(feature = "std")]
410impl std::error::Error for InvalidBlockError {}
411
412#[cfg(feature = "alloc")]
422pub fn compute_merkle_root(transactions: &[Transaction]) -> Option<TxMerkleNode> {
423 let hashes = transactions.iter().map(Transaction::compute_txid);
424 TxMerkleNode::calculate_root(hashes)
425}
426
427#[cfg(feature = "alloc")]
437pub fn compute_witness_root(transactions: &[Transaction]) -> Option<WitnessMerkleNode> {
438 let hashes = transactions.iter().enumerate().map(|(i, t)| {
439 if i == 0 {
440 crate::Wtxid::COINBASE
442 } else {
443 t.compute_wtxid()
444 }
445 });
446 WitnessMerkleNode::calculate_root(hashes)
447}
448
449#[cfg(feature = "alloc")]
450fn witness_commitment_from_coinbase(coinbase: &Transaction) -> Option<WitnessCommitment> {
451 const MAGIC: [u8; 6] = [0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed];
453
454 if !coinbase.is_coinbase() {
455 return None;
456 }
457
458 if let Some(pos) = coinbase
460 .outputs
461 .iter()
462 .rposition(|o| o.script_pubkey.len() >= 38 && o.script_pubkey.as_bytes()[0..6] == MAGIC)
463 {
464 let bytes =
465 <[u8; 32]>::try_from(&coinbase.outputs[pos].script_pubkey.as_bytes()[6..38]).unwrap();
466 Some(WitnessCommitment::from_byte_array(bytes))
467 } else {
468 None
469 }
470}
471
472#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
483pub struct Header {
484 pub version: Version,
486 pub prev_blockhash: BlockHash,
488 pub merkle_root: TxMerkleNode,
490 pub time: BlockTime,
492 pub bits: CompactTarget,
494 pub nonce: u32,
496}
497
498impl Header {
499 pub const SIZE: usize = 4 + 32 + 32 + 4 + 4 + 4; pub fn block_hash(&self) -> BlockHash {
506 let bare_hash = hashes::encode_to_engine(self, sha256d::Hash::engine()).finalize();
507 BlockHash::from_byte_array(bare_hash.to_byte_array())
508 }
509}
510
511#[cfg(all(feature = "hex", feature = "alloc"))]
512impl core::str::FromStr for Header {
513 type Err = ParseHeaderError;
514
515 fn from_str(s: &str) -> Result<Self, Self::Err> {
516 crate::hex_codec::HexPrimitive::from_str(s).map_err(ParseHeaderError)
517 }
518}
519
520#[cfg(feature = "hex")]
521impl fmt::Display for Header {
522 #[allow(clippy::use_self)]
523 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
524 use hex_unstable::{fmt_hex_exact, Case};
525
526 fmt_hex_exact!(f, Header::SIZE, EncodableByteIter::new(self), Case::Lower)
527 }
528}
529
530#[cfg(all(feature = "hex", feature = "alloc"))]
531impl fmt::LowerHex for Header {
532 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
533 fmt::LowerHex::fmt(&crate::hex_codec::HexPrimitive(self), f)
534 }
535}
536
537#[cfg(all(feature = "hex", feature = "alloc"))]
538impl fmt::UpperHex for Header {
539 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
540 fmt::UpperHex::fmt(&crate::hex_codec::HexPrimitive(self), f)
541 }
542}
543
544impl fmt::Debug for Header {
545 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
546 f.debug_struct("Header")
547 .field("block_hash", &self.block_hash())
548 .field("version", &self.version)
549 .field("prev_blockhash", &self.prev_blockhash)
550 .field("merkle_root", &self.merkle_root)
551 .field("time", &self.time)
552 .field("bits", &self.bits)
553 .field("nonce", &self.nonce)
554 .finish()
555 }
556}
557
558#[cfg(all(feature = "hex", feature = "alloc"))]
560pub struct ParseHeaderError(crate::ParsePrimitiveError<Header>);
561
562#[cfg(all(feature = "hex", feature = "alloc"))]
563impl fmt::Debug for ParseHeaderError {
564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.0, f) }
565}
566
567#[cfg(all(feature = "hex", feature = "alloc"))]
568impl fmt::Display for ParseHeaderError {
569 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self, f) }
570}
571
572#[cfg(all(feature = "hex", feature = "alloc", feature = "std"))]
573impl std::error::Error for ParseHeaderError {
574 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
575 std::error::Error::source(&self.0)
576 }
577}
578
579encoding::encoder_newtype_exact! {
580 pub struct HeaderEncoder<'e>(
582 encoding::Encoder6<
583 VersionEncoder<'e>,
584 BlockHashEncoder<'e>,
585 crate::merkle_tree::TxMerkleNodeEncoder<'e>,
586 crate::time::BlockTimeEncoder<'e>,
587 crate::pow::CompactTargetEncoder<'e>,
588 encoding::ArrayEncoder<4>,
589 >
590 );
591}
592
593impl Encodable for Header {
594 type Encoder<'e> = HeaderEncoder<'e>;
595
596 fn encoder(&self) -> Self::Encoder<'_> {
597 HeaderEncoder::new(encoding::Encoder6::new(
598 self.version.encoder(),
599 self.prev_blockhash.encoder(),
600 self.merkle_root.encoder(),
601 self.time.encoder(),
602 self.bits.encoder(),
603 encoding::ArrayEncoder::without_length_prefix(self.nonce.to_le_bytes()),
604 ))
605 }
606}
607
608#[cfg(feature = "alloc")]
609type HeaderInnerDecoder = Decoder6<
610 VersionDecoder,
611 BlockHashDecoder,
612 TxMerkleNodeDecoder,
613 BlockTimeDecoder,
614 CompactTargetDecoder,
615 encoding::ArrayDecoder<4>, >;
617
618#[cfg(feature = "alloc")]
620pub struct HeaderDecoder(HeaderInnerDecoder);
621
622#[cfg(feature = "alloc")]
623impl HeaderDecoder {
624 fn from_inner(e: <HeaderInnerDecoder as Decoder>::Error) -> HeaderDecoderError {
625 match e {
626 encoding::Decoder6Error::First(e) => HeaderDecoderError::Version(e),
627 encoding::Decoder6Error::Second(e) => HeaderDecoderError::PrevBlockhash(e),
628 encoding::Decoder6Error::Third(e) => HeaderDecoderError::MerkleRoot(e),
629 encoding::Decoder6Error::Fourth(e) => HeaderDecoderError::Time(e),
630 encoding::Decoder6Error::Fifth(e) => HeaderDecoderError::Bits(e),
631 encoding::Decoder6Error::Sixth(e) => HeaderDecoderError::Nonce(e),
632 }
633 }
634}
635
636#[cfg(feature = "alloc")]
637impl Decoder for HeaderDecoder {
638 type Output = Header;
639 type Error = HeaderDecoderError;
640
641 #[inline]
642 fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
643 self.0.push_bytes(bytes).map_err(Self::from_inner)
644 }
645
646 #[inline]
647 fn end(self) -> Result<Self::Output, Self::Error> {
648 let (version, prev_blockhash, merkle_root, time, bits, nonce) =
649 self.0.end().map_err(Self::from_inner)?;
650 let nonce = u32::from_le_bytes(nonce);
651 Ok(Header { version, prev_blockhash, merkle_root, time, bits, nonce })
652 }
653
654 #[inline]
655 fn read_limit(&self) -> usize { self.0.read_limit() }
656}
657
658#[cfg(feature = "alloc")]
659impl Decodable for Header {
660 type Decoder = HeaderDecoder;
661 fn decoder() -> Self::Decoder {
662 HeaderDecoder(Decoder6::new(
663 VersionDecoder::new(),
664 BlockHashDecoder::new(),
665 TxMerkleNodeDecoder::new(),
666 BlockTimeDecoder::new(),
667 CompactTargetDecoder::new(),
668 encoding::ArrayDecoder::new(),
669 ))
670 }
671}
672
673#[cfg(feature = "alloc")]
675#[derive(Debug, Clone, PartialEq, Eq)]
676#[non_exhaustive]
677pub enum HeaderDecoderError {
678 Version(VersionDecoderError),
680 PrevBlockhash(BlockHashDecoderError),
682 MerkleRoot(TxMerkleNodeDecoderError),
684 Time(BlockTimeDecoderError),
686 Bits(CompactTargetDecoderError),
688 Nonce(encoding::UnexpectedEofError),
690}
691
692#[cfg(feature = "alloc")]
693impl From<Infallible> for HeaderDecoderError {
694 fn from(never: Infallible) -> Self { match never {} }
695}
696
697#[cfg(feature = "alloc")]
698impl fmt::Display for HeaderDecoderError {
699 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
700 match *self {
701 Self::Version(ref e) => write_err!(f, "header decoder error"; e),
702 Self::PrevBlockhash(ref e) => write_err!(f, "header decoder error"; e),
703 Self::MerkleRoot(ref e) => write_err!(f, "header decoder error"; e),
704 Self::Time(ref e) => write_err!(f, "header decoder error"; e),
705 Self::Bits(ref e) => write_err!(f, "header decoder error"; e),
706 Self::Nonce(ref e) => write_err!(f, "header decoder error"; e),
707 }
708 }
709}
710
711#[cfg(feature = "std")]
712#[cfg(feature = "alloc")]
713impl std::error::Error for HeaderDecoderError {
714 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
715 match *self {
716 Self::Version(ref e) => Some(e),
717 Self::PrevBlockhash(ref e) => Some(e),
718 Self::MerkleRoot(ref e) => Some(e),
719 Self::Time(ref e) => Some(e),
720 Self::Bits(ref e) => Some(e),
721 Self::Nonce(ref e) => Some(e),
722 }
723 }
724}
725
726impl From<Header> for BlockHash {
727 #[inline]
728 fn from(header: Header) -> Self { header.block_hash() }
729}
730
731impl From<&Header> for BlockHash {
732 #[inline]
733 fn from(header: &Header) -> Self { header.block_hash() }
734}
735
736#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
751pub struct Version(i32);
752
753impl Version {
754 pub const ONE: Self = Self(1);
756
757 pub const TWO: Self = Self(2);
759
760 pub const NO_SOFT_FORK_SIGNALLING: Self = Self(Self::USE_VERSION_BITS as i32);
762
763 const VERSION_BITS_MASK: u32 = 0x1FFF_FFFF;
765
766 const USE_VERSION_BITS: u32 = 0x2000_0000;
770
771 #[inline]
775 pub const fn from_consensus(v: i32) -> Self { Self(v) }
776
777 #[inline]
781 pub const fn to_consensus(self) -> i32 { self.0 }
782
783 pub fn is_signalling_soft_fork(self, bit: u8) -> bool {
788 if bit > 28 {
790 return false;
791 }
792
793 if (self.0 as u32) & !Self::VERSION_BITS_MASK != Self::USE_VERSION_BITS {
795 return false;
796 }
797
798 (self.0 as u32 & Self::VERSION_BITS_MASK) & (1 << bit) > 0
800 }
801}
802
803impl fmt::Display for Version {
804 #[inline]
805 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
806}
807
808impl fmt::LowerHex for Version {
809 #[inline]
810 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
811}
812
813impl fmt::UpperHex for Version {
814 #[inline]
815 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
816}
817
818impl fmt::Octal for Version {
819 #[inline]
820 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Octal::fmt(&self.0, f) }
821}
822
823impl fmt::Binary for Version {
824 #[inline]
825 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Binary::fmt(&self.0, f) }
826}
827
828impl Default for Version {
829 #[inline]
830 fn default() -> Self { Self::NO_SOFT_FORK_SIGNALLING }
831}
832
833encoding::encoder_newtype_exact! {
834 pub struct VersionEncoder<'e>(encoding::ArrayEncoder<4>);
836}
837
838impl Encodable for Version {
839 type Encoder<'e> = VersionEncoder<'e>;
840 fn encoder(&self) -> Self::Encoder<'_> {
841 VersionEncoder::new(encoding::ArrayEncoder::without_length_prefix(
842 self.to_consensus().to_le_bytes(),
843 ))
844 }
845}
846
847pub struct VersionDecoder(encoding::ArrayDecoder<4>);
849
850impl VersionDecoder {
851 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
853}
854
855impl Default for VersionDecoder {
856 fn default() -> Self { Self::new() }
857}
858
859impl encoding::Decoder for VersionDecoder {
860 type Output = Version;
861 type Error = VersionDecoderError;
862
863 #[inline]
864 fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
865 self.0.push_bytes(bytes).map_err(VersionDecoderError)
866 }
867
868 #[inline]
869 fn end(self) -> Result<Self::Output, Self::Error> {
870 let n = i32::from_le_bytes(self.0.end().map_err(VersionDecoderError)?);
871 Ok(Version::from_consensus(n))
872 }
873
874 #[inline]
875 fn read_limit(&self) -> usize { self.0.read_limit() }
876}
877
878impl encoding::Decodable for Version {
879 type Decoder = VersionDecoder;
880 fn decoder() -> Self::Decoder { VersionDecoder(encoding::ArrayDecoder::<4>::new()) }
881}
882
883#[derive(Debug, Clone, PartialEq, Eq)]
885pub struct VersionDecoderError(encoding::UnexpectedEofError);
886
887impl From<Infallible> for VersionDecoderError {
888 fn from(never: Infallible) -> Self { match never {} }
889}
890
891impl fmt::Display for VersionDecoderError {
892 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
893 write_err!(f, "version decoder error"; self.0)
894 }
895}
896
897#[cfg(feature = "std")]
898impl std::error::Error for VersionDecoderError {
899 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
900}
901
902#[cfg(feature = "arbitrary")]
903#[cfg(feature = "alloc")]
904impl<'a> Arbitrary<'a> for Block {
905 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
906 let header = Header::arbitrary(u)?;
907 let transactions = Vec::<Transaction>::arbitrary(u)?;
908 Ok(Self::new_unchecked(header, transactions))
909 }
910}
911
912#[cfg(feature = "arbitrary")]
913impl<'a> Arbitrary<'a> for Header {
914 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
915 Ok(Self {
916 version: Version::arbitrary(u)?,
917 prev_blockhash: BlockHash::from_byte_array(u.arbitrary()?),
918 merkle_root: TxMerkleNode::from_byte_array(u.arbitrary()?),
919 time: u.arbitrary()?,
920 bits: CompactTarget::from_consensus(u.arbitrary()?),
921 nonce: u.arbitrary()?,
922 })
923 }
924}
925
926#[cfg(feature = "arbitrary")]
927impl<'a> Arbitrary<'a> for Version {
928 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
929 let choice = u.int_in_range(0..=3)?;
931 match choice {
932 0 => Ok(Self::ONE),
933 1 => Ok(Self::TWO),
934 2 => Ok(Self::NO_SOFT_FORK_SIGNALLING),
935 _ => Ok(Self::from_consensus(u.arbitrary()?)),
936 }
937 }
938}
939
940#[cfg(test)]
941mod tests {
942 #[cfg(feature = "alloc")]
943 use alloc::string::ToString;
944 #[cfg(feature = "alloc")]
945 use alloc::{format, vec};
946 #[cfg(all(feature = "alloc", feature = "hex"))]
947 use core::str::FromStr as _;
948
949 use encoding::{Decoder, Encoder};
950
951 use super::*;
952
953 fn dummy_header() -> Header {
954 Header {
955 version: Version::ONE,
956 prev_blockhash: BlockHash::from_byte_array([0x99; 32]),
957 merkle_root: TxMerkleNode::from_byte_array([0x77; 32]),
958 time: BlockTime::from(2),
959 bits: CompactTarget::from_consensus(3),
960 nonce: 4,
961 }
962 }
963
964 #[test]
965 fn version_is_not_signalling_with_invalid_bit() {
966 let arbitrary_version = Version::from_consensus(1_234_567_890);
967 assert!(!Version::is_signalling_soft_fork(arbitrary_version, 29));
969 }
970
971 #[test]
972 fn version_is_not_signalling_when_use_version_bit_not_set() {
973 let version = Version::from_consensus(0b0100_0000_0000_0000_0000_0000_0000_0000);
974 assert!(!Version::is_signalling_soft_fork(version, 1));
976 }
977
978 #[test]
979 fn version_is_signalling() {
980 let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010);
981 assert!(Version::is_signalling_soft_fork(version, 1));
982 let version = Version::from_consensus(0b0011_0000_0000_0000_0000_0000_0000_0000);
983 assert!(Version::is_signalling_soft_fork(version, 28));
984 }
985
986 #[test]
987 fn version_is_not_signalling() {
988 let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010);
989 assert!(!Version::is_signalling_soft_fork(version, 0));
990 }
991
992 #[test]
993 fn version_to_consensus() {
994 let version = Version::from_consensus(1_234_567_890);
995 assert_eq!(version.to_consensus(), 1_234_567_890);
996 }
997
998 #[test]
999 fn version_default() {
1000 let version = Version::default();
1001 assert_eq!(version.to_consensus(), Version::NO_SOFT_FORK_SIGNALLING.to_consensus());
1002 }
1003
1004 #[test]
1005 #[cfg(feature = "alloc")]
1006 fn version_display() {
1007 let version = Version(75);
1008 assert_eq!(format!("{}", version), "75");
1009 assert_eq!(format!("{:x}", version), "4b");
1010 assert_eq!(format!("{:#x}", version), "0x4b");
1011 assert_eq!(format!("{:X}", version), "4B");
1012 assert_eq!(format!("{:#X}", version), "0x4B");
1013 assert_eq!(format!("{:o}", version), "113");
1014 assert_eq!(format!("{:#o}", version), "0o113");
1015 assert_eq!(format!("{:b}", version), "1001011");
1016 assert_eq!(format!("{:#b}", version), "0b1001011");
1017 }
1018
1019 #[test]
1021 fn header_size() {
1022 let header = dummy_header();
1023
1024 let header_size = header.version.to_consensus().to_le_bytes().len()
1027 + header.prev_blockhash.as_byte_array().len()
1028 + header.merkle_root.as_byte_array().len()
1029 + header.time.to_u32().to_le_bytes().len()
1030 + header.bits.to_consensus().to_le_bytes().len()
1031 + header.nonce.to_le_bytes().len();
1032
1033 assert_eq!(header_size, Header::SIZE);
1034 }
1035
1036 #[test]
1037 #[cfg(feature = "alloc")]
1038 fn block_new_unchecked() {
1039 let header = dummy_header();
1040 let transactions = vec![];
1041 let block = Block::new_unchecked(header, transactions.clone());
1042 assert_eq!(block.header, header);
1043 assert_eq!(block.transactions, transactions);
1044 }
1045
1046 #[test]
1047 #[cfg(feature = "alloc")]
1048 fn block_assume_checked() {
1049 let header = dummy_header();
1050 let transactions = vec![];
1051 let block = Block::new_unchecked(header, transactions.clone());
1052 let witness_root = Some(WitnessMerkleNode::from_byte_array([0x88; 32]));
1053 let checked_block = block.assume_checked(witness_root);
1054 assert_eq!(checked_block.header(), &header);
1055 assert_eq!(checked_block.transactions(), &transactions);
1056 assert_eq!(checked_block.cached_witness_root(), witness_root);
1057 }
1058
1059 #[test]
1060 #[cfg(feature = "alloc")]
1061 fn block_into_parts() {
1062 let header = dummy_header();
1063 let transactions = vec![];
1064 let block = Block::new_unchecked(header, transactions.clone());
1065 let (block_header, block_transactions) = block.into_parts();
1066 assert_eq!(block_header, header);
1067 assert_eq!(block_transactions, transactions);
1068 }
1069
1070 #[test]
1071 #[cfg(feature = "alloc")]
1072 fn block_cached_witness_root() {
1073 let header = dummy_header();
1074 let transactions = vec![];
1075 let block = Block::new_unchecked(header, transactions);
1076 let witness_root = Some(WitnessMerkleNode::from_byte_array([0x88; 32]));
1077 let checked_block = block.assume_checked(witness_root);
1078 assert_eq!(checked_block.cached_witness_root(), witness_root);
1079 }
1080
1081 #[test]
1082 #[cfg(feature = "alloc")]
1083 fn block_validation_no_transactions() {
1084 let header = dummy_header();
1085 let transactions = Vec::new(); let block = Block::new_unchecked(header, transactions);
1088 matches!(block.validate(), Err(InvalidBlockError::NoTransactions));
1089 }
1090
1091 #[test]
1092 #[cfg(feature = "alloc")]
1093 fn block_validation_invalid_coinbase() {
1094 let header = dummy_header();
1095
1096 let non_coinbase_tx = Transaction {
1098 version: crate::transaction::Version::TWO,
1099 lock_time: crate::absolute::LockTime::ZERO,
1100 inputs: vec![crate::TxIn {
1101 previous_output: crate::OutPoint {
1102 txid: crate::Txid::from_byte_array([1; 32]), vout: 0,
1104 },
1105 script_sig: crate::ScriptSigBuf::new(),
1106 sequence: units::Sequence::ENABLE_LOCKTIME_AND_RBF,
1107 witness: crate::Witness::new(),
1108 }],
1109 outputs: vec![crate::TxOut {
1110 amount: units::Amount::ONE_BTC,
1111 script_pubkey: crate::ScriptPubKeyBuf::new(),
1112 }],
1113 };
1114
1115 let transactions = vec![non_coinbase_tx];
1116 let block = Block::new_unchecked(header, transactions);
1117
1118 matches!(block.validate(), Err(InvalidBlockError::InvalidCoinbase));
1119 }
1120
1121 #[test]
1122 #[cfg(feature = "alloc")]
1123 fn block_decoder_read_limit() {
1124 let mut coinbase_in = crate::TxIn::EMPTY_COINBASE;
1125 coinbase_in.script_sig = crate::ScriptSigBuf::from_bytes(vec![0u8; 2]);
1126
1127 let block = Block::new_unchecked(
1128 dummy_header(),
1129 vec![Transaction {
1130 version: crate::transaction::Version::ONE,
1131 lock_time: crate::absolute::LockTime::ZERO,
1132 inputs: vec![coinbase_in],
1133 outputs: vec![crate::TxOut {
1134 amount: units::Amount::MIN,
1135 script_pubkey: crate::ScriptPubKeyBuf::new(),
1136 }],
1137 }],
1138 );
1139
1140 let bytes = encoding::encode_to_vec(&block);
1141 let mut view = bytes.as_slice();
1142
1143 let mut decoder = Block::decoder();
1144 assert!(decoder.read_limit() > 0);
1145 let needs_more = decoder.push_bytes(&mut view).unwrap();
1146 assert!(!needs_more);
1147 assert_eq!(decoder.read_limit(), 0);
1148 assert_eq!(decoder.end().unwrap(), block);
1149 }
1150
1151 #[test]
1152 #[cfg(feature = "alloc")]
1153 fn header_decoder_read_limit() {
1154 let header = dummy_header();
1155 let bytes = encoding::encode_to_vec(&header);
1156 let mut view = bytes.as_slice();
1157
1158 let mut decoder = Header::decoder();
1159 assert!(decoder.read_limit() > 0);
1160 let needs_more = decoder.push_bytes(&mut view).unwrap();
1161 assert!(!needs_more);
1162 assert_eq!(decoder.read_limit(), 0);
1163 assert_eq!(decoder.end().unwrap(), header);
1164 }
1165
1166 #[test]
1167 #[cfg(feature = "alloc")]
1168 fn block_check_witness_commitment_optional() {
1169 let mut header = dummy_header();
1171 header.merkle_root = TxMerkleNode::from_byte_array([0u8; 32]);
1172 let coinbase = Transaction {
1173 version: crate::transaction::Version::ONE,
1174 lock_time: crate::absolute::LockTime::ZERO,
1175 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1176 outputs: vec![],
1177 };
1178
1179 let transactions = vec![coinbase];
1180 let block = Block::new_unchecked(header, transactions);
1181
1182 let result = block.check_witness_commitment();
1183 assert_eq!(result, (true, None));
1184 }
1185
1186 #[test]
1187 #[cfg(feature = "alloc")]
1188 fn block_block_hash() {
1189 let header = dummy_header();
1190 let transactions = vec![];
1191 let block = Block::new_unchecked(header, transactions);
1192 assert_eq!(block.block_hash(), header.block_hash());
1193 }
1194
1195 #[test]
1196 fn block_hash_from_header() {
1197 let header = dummy_header();
1198 let block_hash = header.block_hash();
1199 assert_eq!(block_hash, BlockHash::from(header));
1200 }
1201
1202 #[test]
1203 fn block_hash_from_header_ref() {
1204 let header = dummy_header();
1205 let block_hash: BlockHash = BlockHash::from(&header);
1206 assert_eq!(block_hash, header.block_hash());
1207 }
1208
1209 #[test]
1210 #[cfg(feature = "alloc")]
1211 fn block_hash_from_block() {
1212 let header = dummy_header();
1213 let transactions = vec![];
1214 let block = Block::new_unchecked(header, transactions);
1215 let block_hash: BlockHash = BlockHash::from(block);
1216 assert_eq!(block_hash, header.block_hash());
1217 }
1218
1219 #[test]
1220 #[cfg(feature = "alloc")]
1221 fn block_hash_from_block_ref() {
1222 let header = dummy_header();
1223 let transactions = vec![];
1224 let block = Block::new_unchecked(header, transactions);
1225 let block_hash: BlockHash = BlockHash::from(&block);
1226 assert_eq!(block_hash, header.block_hash());
1227 }
1228
1229 #[test]
1230 #[cfg(feature = "alloc")]
1231 fn header_debug() {
1232 let header = dummy_header();
1233 let expected = format!(
1234 "Header {{ block_hash: {:?}, version: {:?}, prev_blockhash: {:?}, merkle_root: {:?}, time: {:?}, bits: {:?}, nonce: {:?} }}",
1235 header.block_hash(),
1236 header.version,
1237 header.prev_blockhash,
1238 header.merkle_root,
1239 header.time,
1240 header.bits,
1241 header.nonce
1242 );
1243 assert_eq!(format!("{:?}", header), expected);
1244 }
1245
1246 #[test]
1247 #[cfg(feature = "hex")]
1248 #[cfg(feature = "alloc")]
1249 fn header_display() {
1250 let seconds: u32 = 1_653_195_600; let header = Header {
1253 version: Version::TWO,
1254 prev_blockhash: BlockHash::from_byte_array([0xab; 32]),
1255 merkle_root: TxMerkleNode::from_byte_array([0xcd; 32]),
1256 time: BlockTime::from(seconds),
1257 bits: CompactTarget::from_consensus(0xbeef),
1258 nonce: 0xcafe,
1259 };
1260
1261 let want = concat!(
1262 "02000000", "abababababababababababababababababababababababababababababababab", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "50c38962", "efbe0000", "feca0000", );
1269 assert_eq!(want.len(), 160);
1270 assert_eq!(format!("{}", header), want);
1271
1272 let want = format!("{:.20}", want);
1274 let got = format!("{:.20}", header);
1275 assert_eq!(got, want);
1276 }
1277
1278 #[test]
1279 #[cfg(feature = "hex")]
1280 #[cfg(feature = "alloc")]
1281 fn header_hex() {
1282 let header = dummy_header();
1283
1284 let want = concat!(
1285 "01000000", "9999999999999999999999999999999999999999999999999999999999999999", "7777777777777777777777777777777777777777777777777777777777777777", "02000000", "03000000", "04000000", );
1292
1293 assert_eq!(want, format!("{:x}", header));
1295 assert_eq!(want, format!("{}", header));
1296
1297 let upper_encoded =
1299 want.chars().map(|chr| chr.to_ascii_uppercase()).collect::<alloc::string::String>();
1300 assert_eq!(upper_encoded, format!("{:X}", header));
1301 }
1302
1303 #[test]
1304 #[cfg(feature = "hex")]
1305 #[cfg(feature = "alloc")]
1306 fn header_from_hex_str_round_trip() {
1307 let header = dummy_header();
1309
1310 let lower_hex_header = format!("{:x}", header);
1311 let upper_hex_header = format!("{:X}", header);
1312
1313 let parsed_lower = Header::from_str(&lower_hex_header).unwrap();
1315 let parsed_upper = Header::from_str(&upper_hex_header).unwrap();
1316
1317 assert_eq!(header, parsed_lower);
1319 assert_eq!(header, parsed_upper);
1320 }
1321
1322 #[test]
1323 #[cfg(feature = "alloc")]
1324 fn block_decode() {
1325 let header = Header {
1327 version: Version::ONE,
1328 #[rustfmt::skip]
1329 prev_blockhash: BlockHash::from_byte_array([
1330 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1331 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1332 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1333 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA,
1334 ]),
1335 #[rustfmt::skip]
1336 merkle_root: TxMerkleNode::from_byte_array([
1337 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1338 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1339 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1340 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD,
1341 ]),
1342 time: BlockTime::from(1_742_979_600), bits: CompactTarget::from_consensus(12_345_678),
1344 nonce: 1024,
1345 };
1346
1347 let block: u32 = 741_521;
1348 let transactions = vec![Transaction {
1349 version: crate::transaction::Version::ONE,
1350 lock_time: units::absolute::LockTime::from_height(block).unwrap(),
1351 inputs: vec![crate::transaction::TxIn {
1352 previous_output: crate::transaction::OutPoint::COINBASE_PREVOUT,
1353 script_sig: crate::script::ScriptSigBuf::from_bytes(vec![0x51, 0x51]),
1355 sequence: crate::sequence::Sequence::MAX,
1356 witness: crate::witness::Witness::new(),
1357 }],
1358 outputs: vec![crate::transaction::TxOut {
1359 amount: units::Amount::ONE_SAT,
1360 script_pubkey: crate::script::ScriptPubKeyBuf::new(),
1361 }],
1362 }];
1363 let original_block = Block::new_unchecked(header, transactions);
1364
1365 let encoded = encoding::encode_to_vec(&original_block);
1367 let decoded_block = encoding::decode_from_slice(encoded.as_slice()).unwrap();
1368
1369 assert_eq!(original_block, decoded_block);
1370 }
1371
1372 #[test]
1374 #[cfg(all(feature = "alloc", feature = "hex"))]
1375 fn merkle_tree_hash_collision() {
1376 const BLOCK_128461_HEX: &str = "01000000166208c96de305f2a304130a1b53727abf8fb77e8a3cfe2a831e000000000000d4fd086755b4d46221362a09a4228bed60d729d22362b87803ff44b72c138ec04a8ce94d2194261af9551f720701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08042194261a026005ffffffff018076242a01000000434104390e51c3d66d5ee10327395872e33bc232e9e1660225c9f88fa594fdcdcd785d86b1152fb380a63cdf57d8cf2345a55878412a6864656b158704e0b734b3fd9dac000000000100000001f591edc180a889b21a45b6bd5b5e0017d4137dae9695703107ac1e6e878c9f02000000008b483045022100e066df28b29bf18bfcd8da11ea576a6f502f59e7b1d37e2e849ee4648008962b022023be840ec01ffa6860b5577bf0b8546541f40c287eb57b8b421a1396c7aea583014104add16286f51f68cee1b436d0c29a41a59fa8bd224eb6bec34b073512303c70fc3d630cb4952416ef02340c56bee2eef294659b4023ea8a3d90a297bdb54321f9ffffffff02508470b5000000001976a91472579bbeaeca0802fde07ce88f946b64da63989388ac40aeeb02000000001976a914d2a7410246b5ece345aa821af89bff0b6fa3bcaa88ac0000000001000000016197cb143d4cef51389076fdee3f62c294b65bc9aff217a6c71b9dd987e22754000000008c493046022100bf174e942e4619f4e470b5d8b1c0c8ded9e2f7a6616c073c5ab05cc9d699ede3022100a642fa9d0bcc89523635f9468e4813a120b233a249678de0ebf7ba398a4205f6014104122979c0ac1c3af2aa84b4c1d6a9b3b6fa491827f1a2ba37c4b58bdecd644438da715497a44b16aedbadbd18cf9765cdb36851284f643ed743c4365798dd314affffffff02c0404384000000001976a91443cd8fbad7421a53f9e899a2c9761259705d465b88acc0f4f50e000000001976a9142f6c963506b0a2c93a09a92171957e9e7e11a7a388ac00000000010000000228a11f953c26d558a8299ad9dc61279d7abc9a4059820b614bf403c05e471c481d0000008b48304502205baff189016e6fee8e0faa9eebdc8f150d2d3815007719ceccabd995607bb0b0022100f4cc49ef0b29561e976bf6f6f7ae135f665b8dd38a67634bb6bbe74c0da9c1f7014104dd5920aedc3f79ace9c8061f3724812f5b218ea81d175dd990071175874d6c79025f9db516ab23975e510645aabc4ee699cc5c24358a403d15a7736a504399f8ffffffff191b06773a7cec0bb30539f185edbf1d139f9756071c6ae395c1c29f3e2484f6010000008c493046022100c7123436476f923cd8dacbe132f5128b529baa194c9aedc570402d8d2d7902ac02210094e6974695265d96d5859ab493df00c90b62a84dcc33a05753aea23b38c249670141041d878bc5438ff439490e71d059e6b687e511336c0aa53e0d129663c91db71cfe20008891f1e4780bf1139ec9c9e81bfd2e3ea9009608a78d96a5a3a5bf7812baffffffff0200093d00000000001976a914fd0d4c3d0963db8358bd01ba6f386d4c5ef2e30288ac0084d717000000001976a914dcb1e8e699eb9f07a1ddfd5d764aa74359ddd93088ac00000000010000000118e2286c42643e6146669b0f5ee35454fe256aac2b1401dbeefd941f2e6d2074000000008b483045022100edec1c5078fed29d808282d62f167eb3f0ea6a6655f3869c12eca9c63d8463c2022031a3ae430be137932059b4a3e3fb7f1e1f2a05065dbc47c3142972de45c76daa01410423162e5ac10ec46c4a142fea3197cc66e614b9f28f014882ebc8271c4ab6022e474ccdc246445dd2479f9de217e8aaf4d770da15aff1078d329c02e0f4de8d77ffffffff02b00ac165000000001976a914f543a7f0dfcd621a05c646810ba94da791ed14c488ac80de8002000000001976a9144763f6309b3aca0bff49ed6365ffbd791b1afc5d88ac0000000001000000014e3632994e6cbcae4122bf9e8de242aa1d7c13bf6d045392fa69fa92353f13cf000000008c493046022100c6879938322e9945dae2404a2b104b534df7fdab5927a30a57a12418d619c3b8022100c53331f402010cbdc8297d7a827154e42263fc2f6cef6e56b85bbc061d5e30810141047e717e70b8c5e928bc2c482662dbe9007113f7a5fb0360da1d2f193add960fed97ab3163e85c02b127829d694ab4a796326918d4f639d0b19345f7558406667dffffffff0270c8b165000000001976a9146c908731300d5c0a4215ba3bb3041b4f313d14f688ac40420f00000000001976a91457b01e2a6bf178a10a0e36cd3e301a41ac58b68b88ac000000000100000001a2e94f26db15d7098104a3616b650cc7490eca961a23111c12c3d94f593ab3bc000000008c493046022100b355076f2c956d7565d44fdf589ebdbdff70abcd806c71845b47d31c3579cbc00221008352a03c5276ba481ae92a2327307ad1ce9b234be7386c105fb914ceb9c63341014104872ee8390f11c8ac309df772362614ff7c99f98e1fd68888c5e8765d630c93ae86fcd33922b17f5da490ea14a9f9002ef4e7fb11166ba399f9794296ca02e401ffffffff02f07d5460000000001976a914ff1da11fbd50b9906e78c694169c19902d2ee20388ac804a5d05000000001976a91444d5774b8277c59a07ed9dce1225e2d24a3faab188ac00000000";
1379 let bytes: [u8; 1948] = hex_unstable::FromHex::from_hex(BLOCK_128461_HEX).unwrap();
1380 let valid_block: Block<Unchecked> = encoding::decode_from_slice(&bytes).unwrap();
1381 let (header, mut transactions) = valid_block.clone().into_parts();
1382 transactions.push(transactions[6].clone());
1383 let forged_block = Block::new_unchecked(header, transactions);
1384
1385 assert!(valid_block.validate().is_ok());
1386 assert!(forged_block.validate().is_err());
1387 }
1388
1389 #[test]
1390 #[cfg(feature = "alloc")]
1391 fn witness_commitment_from_coinbase_simple() {
1392 let magic = [0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed];
1394 let mut pubkey_bytes = [0; 38];
1395 pubkey_bytes[0..6].copy_from_slice(&magic);
1396 let witness_commitment =
1397 WitnessCommitment::from_byte_array(pubkey_bytes[6..38].try_into().unwrap());
1398 let commitment_script = crate::script::ScriptBuf::from_bytes(pubkey_bytes.to_vec());
1399
1400 let tx = Transaction {
1402 version: crate::transaction::Version::ONE,
1403 lock_time: crate::absolute::LockTime::ZERO,
1404 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1405 outputs: vec![crate::TxOut {
1406 amount: units::Amount::MIN,
1407 script_pubkey: commitment_script,
1408 }],
1409 };
1410
1411 let extracted = witness_commitment_from_coinbase(&tx);
1413 assert_eq!(extracted, Some(witness_commitment));
1414 }
1415
1416 #[test]
1417 #[cfg(feature = "alloc")]
1418 fn witness_commitment_from_non_coinbase_returns_none() {
1419 let tx = Transaction {
1420 version: crate::transaction::Version::ONE,
1421 lock_time: crate::absolute::LockTime::ZERO,
1422 inputs: vec![crate::TxIn {
1423 previous_output: crate::OutPoint {
1424 txid: crate::Txid::from_byte_array([1; 32]),
1425 vout: 0,
1426 },
1427 script_sig: crate::ScriptSigBuf::new(),
1428 sequence: units::Sequence::ENABLE_LOCKTIME_AND_RBF,
1429 witness: crate::Witness::new(),
1430 }],
1431 outputs: vec![crate::TxOut {
1432 amount: units::Amount::MIN,
1433 script_pubkey: crate::ScriptPubKeyBuf::new(),
1434 }],
1435 };
1436
1437 assert!(witness_commitment_from_coinbase(&tx).is_none());
1438 }
1439
1440 #[test]
1441 #[cfg(feature = "alloc")]
1442 fn block_check_witness_commitment_empty_script_pubkey() {
1443 let mut txin = crate::TxIn::EMPTY_COINBASE;
1444 let push = [11_u8];
1445 txin.witness.push(push);
1446
1447 let tx = Transaction {
1448 version: crate::transaction::Version::ONE,
1449 lock_time: crate::absolute::LockTime::ZERO,
1450 inputs: vec![txin],
1451 outputs: vec![crate::TxOut {
1452 amount: units::Amount::MIN,
1453 script_pubkey: crate::script::ScriptBuf::new(),
1455 }],
1456 };
1457
1458 let block = Block::new_unchecked(dummy_header(), vec![tx]);
1459 let result = block.check_witness_commitment();
1460 assert_eq!(result, (false, None)); }
1462
1463 #[test]
1464 #[cfg(feature = "alloc")]
1465 fn block_check_witness_commitment_no_transactions() {
1466 let empty_block = Block::new_unchecked(dummy_header(), vec![]);
1468 let result = empty_block.check_witness_commitment();
1469 assert_eq!(result, (false, None));
1470 }
1471
1472 #[test]
1473 #[cfg(all(feature = "alloc", feature = "hex"))]
1474 fn block_check_witness_commitment_with_witness() {
1475 let mut txin = crate::TxIn::EMPTY_COINBASE;
1476 let witness_bytes: [u8; 32] = [11u8; 32];
1478 txin.witness.push(witness_bytes);
1479
1480 let script_pubkey_bytes: [u8; 38] = hex_unstable::FromHex::from_hex(
1482 "6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb",
1483 )
1484 .unwrap();
1485 let tx1 = Transaction {
1486 version: crate::transaction::Version::ONE,
1487 lock_time: crate::absolute::LockTime::ZERO,
1488 inputs: vec![txin],
1489 outputs: vec![crate::TxOut {
1490 amount: units::Amount::MIN,
1491 script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()),
1492 }],
1493 };
1494
1495 let tx2 = Transaction {
1496 version: crate::transaction::Version::ONE,
1497 lock_time: crate::absolute::LockTime::ZERO,
1498 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1499 outputs: vec![crate::TxOut {
1500 amount: units::Amount::MIN,
1501 script_pubkey: crate::script::ScriptBuf::new(),
1502 }],
1503 };
1504
1505 let block = Block::new_unchecked(dummy_header(), vec![tx1, tx2]);
1506 let result = block.check_witness_commitment();
1507
1508 let exp_bytes: [u8; 32] = hex_unstable::FromHex::from_hex(
1509 "fb848679079938b249a12f14b72d56aeb116df79254e17cdf72b46523bcb49db",
1510 )
1511 .unwrap();
1512 let expected = WitnessMerkleNode::from_byte_array(exp_bytes);
1513 assert_eq!(result, (true, Some(expected)));
1514 }
1515
1516 #[test]
1517 #[cfg(all(feature = "alloc", feature = "hex"))]
1518 fn block_check_witness_commitment_invalid_witness() {
1519 let mut txin = crate::TxIn::EMPTY_COINBASE;
1520 let witness_bytes: [u8; 32] = [11u8; 32];
1521 txin.witness.push(witness_bytes);
1523 txin.witness.push([12u8]);
1524
1525 let script_pubkey_bytes: [u8; 38] = hex_unstable::FromHex::from_hex(
1526 "6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb",
1527 )
1528 .unwrap();
1529 let tx1 = Transaction {
1530 version: crate::transaction::Version::ONE,
1531 lock_time: crate::absolute::LockTime::ZERO,
1532 inputs: vec![txin],
1533 outputs: vec![crate::TxOut {
1534 amount: units::Amount::MIN,
1535 script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()),
1536 }],
1537 };
1538
1539 let tx2 = Transaction {
1540 version: crate::transaction::Version::ONE,
1541 lock_time: crate::absolute::LockTime::ZERO,
1542 inputs: vec![crate::TxIn::EMPTY_COINBASE],
1543 outputs: vec![crate::TxOut {
1544 amount: units::Amount::MIN,
1545 script_pubkey: crate::script::ScriptBuf::new(),
1546 }],
1547 };
1548
1549 let mut header = dummy_header();
1550 let transactions = vec![tx1, tx2];
1551 header.merkle_root = compute_merkle_root(&transactions).unwrap();
1552
1553 let block = Block::new_unchecked(header, transactions);
1554 assert_eq!(block.check_witness_commitment(), (false, None));
1555 assert!(matches!(block.validate(), Err(InvalidBlockError::InvalidWitnessCommitment)));
1556 }
1557
1558 #[test]
1559 fn version_encoder_emits_consensus_bytes() {
1560 let version = Version::from_consensus(123_456_789);
1561 let mut encoder = version.encoder();
1562
1563 assert_eq!(encoder.current_chunk(), &version.to_consensus().to_le_bytes());
1564 assert!(!encoder.advance());
1565 }
1566
1567 #[test]
1568 fn version_decoder_end_and_read_limit() {
1569 let mut decoder = VersionDecoder::new();
1570 let bytes_arr = Version::TWO.to_consensus().to_le_bytes();
1571 let mut bytes = bytes_arr.as_slice();
1572
1573 assert!(decoder.read_limit() > 0);
1574
1575 let needs_more = decoder.push_bytes(&mut bytes).unwrap();
1576 assert!(!needs_more);
1577 assert!(bytes.is_empty());
1578
1579 assert_eq!(decoder.read_limit(), 0);
1580 let decoded = decoder.end().unwrap();
1581 assert_eq!(decoded, Version::TWO);
1582 }
1583
1584 #[test]
1585 fn version_decoder_default_roundtrip() {
1586 let version = Version::from_consensus(123_456_789);
1587 let mut decoder = VersionDecoder::default();
1588 let consensus = version.to_consensus().to_le_bytes();
1589 let mut bytes = consensus.as_slice();
1590 decoder.push_bytes(&mut bytes).unwrap();
1591
1592 assert_eq!(decoder.end().unwrap(), version);
1593 }
1594
1595 #[test]
1596 #[cfg(feature = "alloc")]
1597 fn block_decoder_error() {
1598 let err_first = Block::decoder().end().unwrap_err();
1599 assert!(matches!(err_first.0, encoding::Decoder2Error::First(_)));
1600 assert!(!err_first.to_string().is_empty());
1601 #[cfg(feature = "std")]
1602 assert!(std::error::Error::source(&err_first).is_some());
1603
1604 let mut bytes = encoding::encode_to_vec(&dummy_header());
1607 bytes.push(1u8);
1608 let mut view = bytes.as_slice();
1609
1610 let mut decoder = Block::decoder();
1611 assert!(decoder.push_bytes(&mut view).unwrap());
1612 assert!(view.is_empty());
1613
1614 let err_second = decoder.end().unwrap_err();
1615 assert!(matches!(err_second.0, encoding::Decoder2Error::Second(_)));
1616 assert!(!err_second.to_string().is_empty());
1617 #[cfg(feature = "std")]
1618 assert!(std::error::Error::source(&err_second).is_some());
1619 }
1620
1621 #[test]
1622 #[cfg(feature = "alloc")]
1623 fn header_decoder_error() {
1624 let header_bytes = encoding::encode_to_vec(&dummy_header());
1625 let lengths = [0usize, 4, 36, 68, 72, 76];
1627
1628 for &len in &lengths {
1629 let mut decoder = Header::decoder();
1630 let mut slice = header_bytes[..len].as_ref();
1631 decoder.push_bytes(&mut slice).unwrap();
1632 let err = decoder.end().unwrap_err();
1633 match len {
1634 0 => assert!(matches!(err, HeaderDecoderError::Version(_))),
1635 4 => assert!(matches!(err, HeaderDecoderError::PrevBlockhash(_))),
1636 36 => assert!(matches!(err, HeaderDecoderError::MerkleRoot(_))),
1637 68 => assert!(matches!(err, HeaderDecoderError::Time(_))),
1638 72 => assert!(matches!(err, HeaderDecoderError::Bits(_))),
1639 76 => assert!(matches!(err, HeaderDecoderError::Nonce(_))),
1640 _ => unreachable!(),
1641 }
1642 assert!(!err.to_string().is_empty());
1643 #[cfg(feature = "std")]
1644 assert!(std::error::Error::source(&err).is_some());
1645 }
1646 }
1647
1648 #[test]
1649 #[cfg(feature = "alloc")]
1650 fn invalid_block_error() {
1651 #[cfg(feature = "std")]
1652 use std::error::Error as _;
1653
1654 let variants = [
1655 InvalidBlockError::InvalidMerkleRoot,
1656 InvalidBlockError::InvalidWitnessCommitment,
1657 InvalidBlockError::NoTransactions,
1658 InvalidBlockError::InvalidCoinbase,
1659 ];
1660
1661 for variant in variants {
1662 assert!(!variant.to_string().is_empty());
1663 #[cfg(feature = "std")]
1664 assert!(variant.source().is_none());
1665 }
1666 }
1667
1668 #[test]
1669 #[cfg(feature = "alloc")]
1670 fn version_decoder_error() {
1671 let err = encoding::decode_from_slice::<Version>(&[0x01]).unwrap_err();
1672 assert!(!err.to_string().is_empty());
1673 #[cfg(feature = "std")]
1674 assert!(std::error::Error::source(&err).is_some());
1675 }
1676}