bitcoin/consensus/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Bitcoin consensus.
4//!
5//! This module defines structures, functions, and traits that are needed to
6//! conform to Bitcoin consensus.
7//!
8
9pub mod encode;
10pub mod params;
11#[cfg(feature = "serde")]
12pub mod serde;
13#[cfg(feature = "bitcoinconsensus")]
14pub mod validation;
15
16use core::fmt;
17
18use internals::write_err;
19use io::{BufRead, Read};
20
21use crate::consensus;
22
23#[rustfmt::skip]                // Keep public re-exports separate.
24#[doc(inline)]
25pub use self::{
26    encode::{deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt},
27    params::Params,
28};
29
30#[cfg(feature = "bitcoinconsensus")]
31#[doc(inline)]
32pub use self::validation::{
33    verify_script, verify_script_with_flags, verify_transaction, verify_transaction_with_flags,
34};
35
36struct IterReader<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> {
37    iterator: core::iter::Fuse<I>,
38    buf: Option<u8>,
39    error: Option<E>,
40}
41
42impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> IterReader<E, I> {
43    pub(crate) fn new(iterator: I) -> Self {
44        IterReader { iterator: iterator.fuse(), buf: None, error: None }
45    }
46
47    fn decode<T: Decodable>(mut self) -> Result<T, DecodeError<E>> {
48        let result = T::consensus_decode(&mut self);
49        match (result, self.error) {
50            (Ok(_), None) if self.iterator.next().is_some() => Err(DecodeError::TooManyBytes),
51            (Ok(value), None) => Ok(value),
52            (Ok(_), Some(error)) => panic!("{} silently ate the error: {:?}", core::any::type_name::<T>(), error),
53
54            (Err(consensus::encode::Error::Io(io_error)), Some(de_error)) if io_error.kind() == io::ErrorKind::Other && io_error.get_ref().is_none() => Err(DecodeError::Other(de_error)),
55            (Err(consensus_error), None) => Err(DecodeError::Consensus(consensus_error)),
56            (Err(consensus::encode::Error::Io(io_error)), de_error) => panic!("Unexpected IO error {:?} returned from {}::consensus_decode(), deserialization error: {:?}", io_error, core::any::type_name::<T>(), de_error),
57            (Err(consensus_error), Some(de_error)) => panic!("{} should've returned `Other` IO error because of deserialization error {:?} but it returned consensus error {:?} instead", core::any::type_name::<T>(), de_error, consensus_error),
58        }
59    }
60}
61
62impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> Read for IterReader<E, I> {
63    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
64        let mut count = 0;
65        if buf.is_empty() {
66            return Ok(0);
67        }
68
69        if let Some(first) = self.buf.take() {
70            buf[0] = first;
71            buf = &mut buf[1..];
72            count += 1;
73        }
74        for (dst, src) in buf.iter_mut().zip(&mut self.iterator) {
75            match src {
76                Ok(byte) => *dst = byte,
77                Err(error) => {
78                    self.error = Some(error);
79                    return Err(io::ErrorKind::Other.into());
80                }
81            }
82            // bounded by the length of buf
83            count += 1;
84        }
85        Ok(count)
86    }
87}
88
89impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> BufRead for IterReader<E, I> {
90    fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
91        // matching on reference rather than using `ref` confuses borrow checker
92        if let Some(ref byte) = self.buf {
93            Ok(core::slice::from_ref(byte))
94        } else {
95            match self.iterator.next() {
96                Some(Ok(byte)) => {
97                    self.buf = Some(byte);
98                    Ok(core::slice::from_ref(self.buf.as_ref().expect("we've just filled it")))
99                }
100                Some(Err(error)) => {
101                    self.error = Some(error);
102                    Err(io::ErrorKind::Other.into())
103                }
104                None => Ok(&[]),
105            }
106        }
107    }
108
109    fn consume(&mut self, len: usize) {
110        debug_assert!(len <= 1);
111        if len > 0 {
112            self.buf = None;
113        }
114    }
115}
116
117/// Error when consensus decoding from an `[IterReader]`.
118#[derive(Debug)]
119pub enum DecodeError<E> {
120    /// Attempted to decode an object from an iterator that yielded too many bytes.
121    TooManyBytes,
122    /// Invalid consensus encoding.
123    Consensus(consensus::encode::Error),
124    /// Other decoding error.
125    Other(E),
126}
127
128internals::impl_from_infallible!(DecodeError<E>);
129
130impl<E: fmt::Debug> fmt::Display for DecodeError<E> {
131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132        use DecodeError::*;
133
134        match *self {
135            TooManyBytes =>
136                write!(f, "attempted to decode object from an iterator that yielded too many bytes"),
137            Consensus(ref e) => write_err!(f, "invalid consensus encoding"; e),
138            Other(ref other) => write!(f, "other decoding error: {:?}", other),
139        }
140    }
141}
142
143#[cfg(feature = "std")]
144impl<E: fmt::Debug> std::error::Error for DecodeError<E> {
145    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
146        use DecodeError::*;
147
148        match *self {
149            TooManyBytes => None,
150            Consensus(ref e) => Some(e),
151            Other(_) => None, // TODO: Is this correct?
152        }
153    }
154}