Skip to content

Commit 99544ff

Browse files
committed
Merge rust-bitcoin#4998: primitives: Implement decoding traits
39bf86b primitives: Implement decoders (Tobin C. Harding) 63af008 Use scriptPubkey instead of script public key (Tobin C. Harding) Pull request description: Things that need careful attention please: - The state machine in `TransactionDecoder` - The `WitnessDecoder::empty` kludge ACKs for top commit: apoelstra: ACK 39bf86b; successfully ran local tests Tree-SHA512: e04c6eb9e4b675dd71f65607339d42c5610315a4b9b0d7a88d8191a86af4696277a0042a714bf0236d17374543f5544d813def927c0023a00b259452b7507fca
2 parents 3c5954e + 39bf86b commit 99544ff

File tree

13 files changed

+1540
-28
lines changed

13 files changed

+1540
-28
lines changed

Cargo-minimal.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ dependencies = [
142142
"bitcoin-units",
143143
"bitcoin_hashes 0.16.0",
144144
"hex-conservative 0.3.0",
145+
"hex_lit",
145146
"serde",
146147
"serde_json",
147148
]

Cargo-recent.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ dependencies = [
141141
"bitcoin-units",
142142
"bitcoin_hashes 0.16.0",
143143
"hex-conservative 0.3.0",
144+
"hex_lit",
144145
"serde",
145146
"serde_json",
146147
]

primitives/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ serde = { version = "1.0.195", default-features = false, features = ["derive", "
3636
[dev-dependencies]
3737
serde_json = "1.0.68"
3838
bincode = "1.3.1"
39+
hex_lit = "0.1.1"
3940

4041
[package.metadata.docs.rs]
4142
all-features = true

primitives/src/block.rs

Lines changed: 205 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,28 @@
77
//! module describes structures and functions needed to describe
88
//! these blocks and the blockchain.
99
10+
use core::convert::Infallible;
1011
use core::fmt;
1112
#[cfg(feature = "alloc")]
1213
use core::marker::PhantomData;
1314

1415
#[cfg(feature = "arbitrary")]
1516
use arbitrary::{Arbitrary, Unstructured};
16-
use encoding::{CompactSizeEncoder, Encodable, Encoder2, SliceEncoder};
17+
use encoding::Encodable;
18+
#[cfg(feature = "alloc")]
19+
use encoding::{CompactSizeEncoder, Decodable, Decoder, Decoder6, Encoder2, SliceEncoder};
1720
use hashes::{sha256d, HashEngine as _};
21+
use internals::write_err;
1822

23+
#[cfg(feature = "alloc")]
24+
use crate::pow::{CompactTargetDecoder, CompactTargetDecoderError};
1925
#[cfg(feature = "alloc")]
2026
use crate::prelude::Vec;
27+
#[cfg(feature = "alloc")]
28+
use crate::transaction::{TxMerkleNodeDecoder, TxMerkleNodeDecoderError};
2129
use crate::{BlockTime, CompactTarget, TxMerkleNode};
2230
#[cfg(feature = "alloc")]
23-
use crate::{Transaction, WitnessMerkleNode};
31+
use crate::{BlockTimeDecoder, BlockTimeDecoderError, Transaction, WitnessMerkleNode};
2432

2533
#[rustfmt::skip] // Keep public re-exports separate.
2634
#[doc(inline)]
@@ -30,7 +38,9 @@ pub use units::block::{BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInter
3038
pub use units::block::TooBigForRelativeHeightError;
3139

3240
#[doc(inline)]
33-
pub use crate::hash_types::{BlockHash, BlockHashEncoder, WitnessCommitment};
41+
pub use crate::hash_types::{
42+
BlockHash, BlockHashDecoder, BlockHashDecoderError, BlockHashEncoder, WitnessCommitment,
43+
};
3444

3545
/// Marker for whether or not a block has been validated.
3646
///
@@ -295,6 +305,139 @@ impl Encodable for Header {
295305
}
296306
}
297307

308+
/// The decoder for the [`Header`] type.
309+
#[cfg(feature = "alloc")]
310+
pub struct HeaderDecoder(
311+
Decoder6<
312+
VersionDecoder,
313+
BlockHashDecoder,
314+
TxMerkleNodeDecoder,
315+
BlockTimeDecoder,
316+
CompactTargetDecoder,
317+
encoding::ArrayDecoder<4>, // Nonce
318+
HeaderDecoderError,
319+
>,
320+
);
321+
322+
#[cfg(feature = "alloc")]
323+
impl Decoder for HeaderDecoder {
324+
type Output = Header;
325+
type Error = HeaderDecoderError;
326+
327+
#[inline]
328+
fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
329+
self.0.push_bytes(bytes)
330+
}
331+
332+
#[inline]
333+
fn end(self) -> Result<Self::Output, Self::Error> {
334+
let (version, prev_blockhash, merkle_root, time, bits, nonce) = self.0.end()?;
335+
let nonce = u32::from_le_bytes(nonce);
336+
Ok(Header { version, prev_blockhash, merkle_root, time, bits, nonce })
337+
}
338+
339+
#[inline]
340+
fn read_limit(&self) -> usize { self.0.read_limit() }
341+
}
342+
343+
#[cfg(feature = "alloc")]
344+
impl Decodable for Header {
345+
type Decoder = HeaderDecoder;
346+
fn decoder() -> Self::Decoder {
347+
HeaderDecoder(Decoder6::new(
348+
VersionDecoder::new(),
349+
BlockHashDecoder::new(),
350+
TxMerkleNodeDecoder::new(),
351+
BlockTimeDecoder::new(),
352+
CompactTargetDecoder::new(),
353+
encoding::ArrayDecoder::new(),
354+
))
355+
}
356+
}
357+
358+
/// An error consensus decoding a `Header`.
359+
#[cfg(feature = "alloc")]
360+
#[derive(Debug, Clone, PartialEq, Eq)]
361+
#[non_exhaustive]
362+
pub enum HeaderDecoderError {
363+
/// Error while decoding the `version`.
364+
Version(VersionDecoderError),
365+
/// Error while decoding the `prev_blockhash`.
366+
PrevBlockhash(BlockHashDecoderError),
367+
/// Error while decoding the `merkle_root`.
368+
MerkleRoot(TxMerkleNodeDecoderError),
369+
/// Error while decoding the `time`.
370+
Time(BlockTimeDecoderError),
371+
/// Error while decoding the `bits`.
372+
Bits(CompactTargetDecoderError),
373+
/// Error while decoding the `nonce`.
374+
Nonce(encoding::UnexpectedEofError),
375+
}
376+
377+
#[cfg(feature = "alloc")]
378+
impl From<Infallible> for HeaderDecoderError {
379+
fn from(never: Infallible) -> Self { match never {} }
380+
}
381+
382+
#[cfg(feature = "alloc")]
383+
impl From<VersionDecoderError> for HeaderDecoderError {
384+
fn from(e: VersionDecoderError) -> Self { Self::Version(e) }
385+
}
386+
387+
#[cfg(feature = "alloc")]
388+
impl From<BlockHashDecoderError> for HeaderDecoderError {
389+
fn from(e: BlockHashDecoderError) -> Self { Self::PrevBlockhash(e) }
390+
}
391+
392+
#[cfg(feature = "alloc")]
393+
impl From<TxMerkleNodeDecoderError> for HeaderDecoderError {
394+
fn from(e: TxMerkleNodeDecoderError) -> Self { Self::MerkleRoot(e) }
395+
}
396+
397+
#[cfg(feature = "alloc")]
398+
impl From<BlockTimeDecoderError> for HeaderDecoderError {
399+
fn from(e: BlockTimeDecoderError) -> Self { Self::Time(e) }
400+
}
401+
402+
#[cfg(feature = "alloc")]
403+
impl From<CompactTargetDecoderError> for HeaderDecoderError {
404+
fn from(e: CompactTargetDecoderError) -> Self { Self::Bits(e) }
405+
}
406+
407+
#[cfg(feature = "alloc")]
408+
impl From<encoding::UnexpectedEofError> for HeaderDecoderError {
409+
fn from(e: encoding::UnexpectedEofError) -> Self { Self::Nonce(e) }
410+
}
411+
412+
#[cfg(feature = "alloc")]
413+
impl fmt::Display for HeaderDecoderError {
414+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415+
match *self {
416+
Self::Version(ref e) => write_err!(f, "header decoder error"; e),
417+
Self::PrevBlockhash(ref e) => write_err!(f, "header decoder error"; e),
418+
Self::MerkleRoot(ref e) => write_err!(f, "header decoder error"; e),
419+
Self::Time(ref e) => write_err!(f, "header decoder error"; e),
420+
Self::Bits(ref e) => write_err!(f, "header decoder error"; e),
421+
Self::Nonce(ref e) => write_err!(f, "header decoder error"; e),
422+
}
423+
}
424+
}
425+
426+
#[cfg(feature = "std")]
427+
#[cfg(feature = "alloc")]
428+
impl std::error::Error for HeaderDecoderError {
429+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
430+
match *self {
431+
Self::Version(ref e) => Some(e),
432+
Self::PrevBlockhash(ref e) => Some(e),
433+
Self::MerkleRoot(ref e) => Some(e),
434+
Self::Time(ref e) => Some(e),
435+
Self::Bits(ref e) => Some(e),
436+
Self::Nonce(ref e) => Some(e),
437+
}
438+
}
439+
}
440+
298441
impl From<Header> for BlockHash {
299442
#[inline]
300443
fn from(header: Header) -> BlockHash { header.block_hash() }
@@ -391,6 +534,65 @@ impl Encodable for Version {
391534
}
392535
}
393536

537+
/// The decoder for the [`Version`] type.
538+
pub struct VersionDecoder(encoding::ArrayDecoder<4>);
539+
540+
impl VersionDecoder {
541+
/// Constructs a new [`Version`] decoder.
542+
pub fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
543+
}
544+
545+
impl Default for VersionDecoder {
546+
fn default() -> Self { Self::new() }
547+
}
548+
549+
impl encoding::Decoder for VersionDecoder {
550+
type Output = Version;
551+
type Error = VersionDecoderError;
552+
553+
#[inline]
554+
fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
555+
Ok(self.0.push_bytes(bytes)?)
556+
}
557+
558+
#[inline]
559+
fn end(self) -> Result<Self::Output, Self::Error> {
560+
let n = i32::from_le_bytes(self.0.end()?);
561+
Ok(Version::from_consensus(n))
562+
}
563+
564+
#[inline]
565+
fn read_limit(&self) -> usize { self.0.read_limit() }
566+
}
567+
568+
impl encoding::Decodable for Version {
569+
type Decoder = VersionDecoder;
570+
fn decoder() -> Self::Decoder { VersionDecoder(encoding::ArrayDecoder::<4>::new()) }
571+
}
572+
573+
/// An error consensus decoding an `Version`.
574+
#[derive(Debug, Clone, PartialEq, Eq)]
575+
pub struct VersionDecoderError(encoding::UnexpectedEofError);
576+
577+
impl From<Infallible> for VersionDecoderError {
578+
fn from(never: Infallible) -> Self { match never {} }
579+
}
580+
581+
impl From<encoding::UnexpectedEofError> for VersionDecoderError {
582+
fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) }
583+
}
584+
585+
impl fmt::Display for VersionDecoderError {
586+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
587+
write_err!(f, "version decoder error"; self.0)
588+
}
589+
}
590+
591+
#[cfg(feature = "std")]
592+
impl std::error::Error for VersionDecoderError {
593+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
594+
}
595+
394596
#[cfg(feature = "arbitrary")]
395597
#[cfg(feature = "alloc")]
396598
impl<'a> Arbitrary<'a> for Block {

primitives/src/hash_types/block_hash.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
//! The `BlockHash` type.
44
5-
#[cfg(not(feature = "hex"))]
5+
use core::convert::Infallible;
66
use core::fmt;
77
#[cfg(feature = "hex")]
88
use core::str;
@@ -13,6 +13,7 @@ use encoding::Encodable;
1313
use hashes::sha256d;
1414
#[cfg(feature = "hex")]
1515
use hex::FromHex as _;
16+
use internals::write_err;
1617

1718
/// A bitcoin block hash.
1819
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -41,3 +42,62 @@ impl Encodable for BlockHash {
4142
BlockHashEncoder(encoding::ArrayEncoder::without_length_prefix(self.to_byte_array()))
4243
}
4344
}
45+
46+
/// The decoder for the [`BlockHash`] type.
47+
pub struct BlockHashDecoder(encoding::ArrayDecoder<32>);
48+
49+
impl BlockHashDecoder {
50+
/// Constructs a new [`BlockHash`] decoder.
51+
pub fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
52+
}
53+
54+
impl Default for BlockHashDecoder {
55+
fn default() -> Self { Self::new() }
56+
}
57+
58+
impl encoding::Decoder for BlockHashDecoder {
59+
type Output = BlockHash;
60+
type Error = BlockHashDecoderError;
61+
62+
#[inline]
63+
fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
64+
Ok(self.0.push_bytes(bytes)?)
65+
}
66+
67+
#[inline]
68+
fn end(self) -> Result<Self::Output, Self::Error> {
69+
let a = self.0.end()?;
70+
Ok(BlockHash::from_byte_array(a))
71+
}
72+
73+
#[inline]
74+
fn read_limit(&self) -> usize { self.0.read_limit() }
75+
}
76+
77+
impl encoding::Decodable for BlockHash {
78+
type Decoder = BlockHashDecoder;
79+
fn decoder() -> Self::Decoder { BlockHashDecoder(encoding::ArrayDecoder::<32>::new()) }
80+
}
81+
82+
/// An error consensus decoding an `BlockHash`.
83+
#[derive(Debug, Clone, PartialEq, Eq)]
84+
pub struct BlockHashDecoderError(encoding::UnexpectedEofError);
85+
86+
impl From<Infallible> for BlockHashDecoderError {
87+
fn from(never: Infallible) -> Self { match never {} }
88+
}
89+
90+
impl From<encoding::UnexpectedEofError> for BlockHashDecoderError {
91+
fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) }
92+
}
93+
94+
impl fmt::Display for BlockHashDecoderError {
95+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96+
write_err!(f, "sequence decoder error"; self.0)
97+
}
98+
}
99+
100+
#[cfg(feature = "std")]
101+
impl std::error::Error for BlockHashDecoderError {
102+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
103+
}

primitives/src/hash_types/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ mod wtxid;
1919
#[rustfmt::skip] // Keep public re-exports separate.
2020
#[doc(inline)]
2121
pub use self::{
22-
block_hash::{BlockHash, BlockHashEncoder},
22+
block_hash::{BlockHash, BlockHashDecoder, BlockHashDecoderError, BlockHashEncoder},
2323
ntxid::Ntxid,
24-
transaction_merkle_node::{TxMerkleNode, TxMerkleNodeEncoder},
25-
txid::Txid,
24+
transaction_merkle_node::{TxMerkleNode, TxMerkleNodeEncoder, TxMerkleNodeDecoder, TxMerkleNodeDecoderError},
25+
txid::{Txid},
2626
wtxid::Wtxid,
2727
witness_commitment::WitnessCommitment,
2828
witness_merkle_node::WitnessMerkleNode,

0 commit comments

Comments
 (0)