bitcoincash/blockdata/
block.rs

1// Written in 2014 by Andrew Poelstra <apoelstra@wpsoftware.net>
2// SPDX-License-Identifier: CC0-1.0
3
4//! Bitcoin blocks.
5//!
6//! A block is a bundle of transactions with a proof-of-work attached,
7//! which commits to an earlier block to form the blockchain. This
8//! module describes structures and functions needed to describe
9//! these blocks and the blockchain.
10//!
11
12use crate::prelude::*;
13
14use core::fmt;
15
16use crate::util;
17use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork};
18use crate::util::hash::bitcoin_merkle_root;
19use crate::hashes::{Hash, HashEngine};
20use crate::hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment};
21use crate::util::uint::Uint256;
22use crate::consensus::encode::Encodable;
23use crate::network::constants::Network;
24use crate::blockdata::transaction::Transaction;
25use crate::blockdata::constants::{max_target, WITNESS_SCALE_FACTOR};
26use crate::blockdata::script;
27use crate::VarInt;
28use crate::internal_macros::impl_consensus_encoding;
29
30/// Bitcoin block header.
31///
32/// Contains all the block's information except the actual transactions, but
33/// including a root of a [merkle tree] commiting to all transactions in the block.
34///
35/// [merkle tree]: https://en.wikipedia.org/wiki/Merkle_tree
36///
37/// ### Bitcoin Core References
38///
39/// * [CBlockHeader definition](https://github.com/bitcoin/bitcoin/blob/345457b542b6a980ccfbc868af0970a6f91d1b82/src/primitives/block.h#L20)
40#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
43pub struct BlockHeader {
44    /// Originally protocol version, but repurposed for soft-fork signaling.
45    ///
46    /// ### Relevant BIPs
47    ///
48    /// * [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage)
49    /// * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)
50    pub version: i32,
51    /// Reference to the previous block in the chain.
52    pub prev_blockhash: BlockHash,
53    /// The root hash of the merkle tree of transactions in the block.
54    pub merkle_root: TxMerkleNode,
55    /// The timestamp of the block, as claimed by the miner.
56    pub time: u32,
57    /// The target value below which the blockhash must lie, encoded as a
58    /// a float (with well-defined rounding, of course).
59    pub bits: u32,
60    /// The nonce, selected to obtain a low enough blockhash.
61    pub nonce: u32,
62}
63
64impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
65
66impl BlockHeader {
67    /// Returns the block hash.
68    pub fn block_hash(&self) -> BlockHash {
69        let mut engine = BlockHash::engine();
70        self.consensus_encode(&mut engine).expect("engines don't error");
71        BlockHash::from_engine(engine)
72    }
73
74    /// Computes the target [0, T] that a blockhash must land in to be valid.
75    pub fn target(&self) -> Uint256 {
76        Self::u256_from_compact_target(self.bits)
77    }
78
79    /// Computes the target value in [`Uint256`] format, from a compact representation.
80    ///
81    /// [`Uint256`]: ../../util/uint/struct.Uint256.html
82    ///
83    /// ```
84    /// use bitcoincash::blockdata::block::BlockHeader;
85    ///
86    /// assert_eq!(0x1d00ffff,
87    ///     BlockHeader::compact_target_from_u256(
88    ///         &BlockHeader::u256_from_compact_target(0x1d00ffff)
89    ///     )
90    /// );
91    /// ```
92    pub fn u256_from_compact_target(bits: u32) -> Uint256 {
93        // This is a floating-point "compact" encoding originally used by
94        // OpenSSL, which satoshi put into consensus code, so we're stuck
95        // with it. The exponent needs to have 3 subtracted from it, hence
96        // this goofy decoding code:
97        let (mant, expt) = {
98            let unshifted_expt = bits >> 24;
99            if unshifted_expt <= 3 {
100                ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0)
101            } else {
102                (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3))
103            }
104        };
105
106        // The mantissa is signed but may not be negative
107        if mant > 0x7FFFFF {
108            Default::default()
109        } else {
110            Uint256::from_u64(mant as u64).unwrap() << (expt as usize)
111        }
112    }
113
114    /// Computes the target value in float format from Uint256 format.
115    pub fn compact_target_from_u256(value: &Uint256) -> u32 {
116        let mut size = (value.bits() + 7) / 8;
117        let mut compact = if size <= 3 {
118            (value.low_u64() << (8 * (3 - size))) as u32
119        } else {
120            let bn = *value >> (8 * (size - 3));
121            bn.low_u32()
122        };
123
124        if (compact & 0x00800000) != 0 {
125            compact >>= 8;
126            size += 1;
127        }
128
129        compact | (size << 24) as u32
130    }
131
132    /// Computes the popular "difficulty" measure for mining.
133    pub fn difficulty(&self, network: Network) -> u64 {
134        (max_target(network) / self.target()).low_u64()
135    }
136
137    /// Checks that the proof-of-work for the block is valid, returning the block hash.
138    pub fn validate_pow(&self, required_target: &Uint256) -> Result<BlockHash, util::Error> {
139        let target = &self.target();
140        if target != required_target {
141            return Err(BlockBadTarget);
142        }
143        let block_hash = self.block_hash();
144        let mut ret = [0u64; 4];
145        util::endian::bytes_to_u64_slice_le(block_hash.as_inner(), &mut ret);
146        let hash = &Uint256(ret);
147        if hash <= target { Ok(block_hash) } else { Err(BlockBadProofOfWork) }
148    }
149
150    /// Returns the total work of the block.
151    pub fn work(&self) -> Uint256 {
152        // 2**256 / (target + 1) == ~target / (target+1) + 1    (eqn shamelessly stolen from bitcoind)
153        let mut ret = !self.target();
154        let mut ret1 = self.target();
155        ret1.increment();
156        ret = ret / ret1;
157        ret.increment();
158        ret
159    }
160}
161
162/// Bitcoin block.
163///
164/// A collection of transactions with an attached proof of work.
165///
166/// See [Bitcoin Wiki: Block][wiki-block] for more information.
167///
168/// [wiki-block]: https://en.bitcoin.it/wiki/Block
169///
170/// ### Bitcoin Core References
171///
172/// * [CBlock definition](https://github.com/bitcoin/bitcoin/blob/345457b542b6a980ccfbc868af0970a6f91d1b82/src/primitives/block.h#L62)
173#[derive(PartialEq, Eq, Clone, Debug)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
176pub struct Block {
177    /// The block header
178    pub header: BlockHeader,
179    /// List of transactions contained in the block
180    pub txdata: Vec<Transaction>
181}
182
183impl_consensus_encoding!(Block, header, txdata);
184
185impl Block {
186    /// Returns the block hash.
187    pub fn block_hash(&self) -> BlockHash {
188        self.header.block_hash()
189    }
190
191    /// check if merkle root of header matches merkle root of the transaction list
192    pub fn check_merkle_root(&self) -> bool {
193        match self.compute_merkle_root() {
194            Some(merkle_root) => self.header.merkle_root == merkle_root,
195            None => false,
196        }
197    }
198
199    /// Checks if witness commitment in coinbase matches the transaction list.
200    pub fn check_witness_commitment(&self) -> bool {
201        const MAGIC: [u8; 6] = [0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed];
202        // Witness commitment is optional if there are no transactions using SegWit in the block.
203        if self.txdata.iter().all(|t| t.input.iter().all(|i| i.witness.is_empty())) {
204            return true;
205        }
206
207        if self.txdata.is_empty() {
208            return false;
209        }
210
211        let coinbase = &self.txdata[0];
212        if !coinbase.is_coin_base() {
213            return false;
214        }
215
216        // Commitment is in the last output that starts with magic bytes.
217        if let Some(pos) = coinbase.output.iter()
218            .rposition(|o| o.script_pubkey.len () >= 38 && o.script_pubkey[0..6] ==  MAGIC)
219        {
220            let commitment = WitnessCommitment::from_slice(&coinbase.output[pos].script_pubkey.as_bytes()[6..38]).unwrap();
221            // Witness reserved value is in coinbase input witness.
222            let witness_vec: Vec<_> = coinbase.input[0].witness.iter().collect();
223            if witness_vec.len() == 1 && witness_vec[0].len() == 32 {
224                if let Some(witness_root) = self.witness_root() {
225                    return commitment == Self::compute_witness_commitment(&witness_root, witness_vec[0]);
226                }
227            }
228        }
229
230        false
231    }
232
233    /// Computes the transaction merkle root.
234    pub fn compute_merkle_root(&self) -> Option<TxMerkleNode> {
235        let hashes = self.txdata.iter().map(|obj| obj.txid().as_hash());
236        bitcoin_merkle_root(hashes).map(|h| h.into())
237    }
238
239    /// Calculate the transaction merkle root.
240    #[deprecated(since = "0.28.0", note = "Please use `block::compute_merkle_root` instead.")]
241    pub fn merkle_root(&self) -> Option<TxMerkleNode> {
242        self.compute_merkle_root()
243    }
244
245    /// Computes the witness commitment for the block's transaction list.
246    pub fn compute_witness_commitment(witness_root: &WitnessMerkleNode, witness_reserved_value: &[u8]) -> WitnessCommitment {
247        let mut encoder = WitnessCommitment::engine();
248        witness_root.consensus_encode(&mut encoder).expect("engines don't error");
249        encoder.input(witness_reserved_value);
250        WitnessCommitment::from_engine(encoder)
251    }
252
253    /// Computes the merkle root of transactions hashed for witness.
254    pub fn witness_root(&self) -> Option<WitnessMerkleNode> {
255        let hashes = self.txdata.iter().enumerate().map(|(i, t)| {
256            if i == 0 {
257                // Replace the first hash with zeroes.
258                Wtxid::all_zeros().as_hash()
259            } else {
260                t.wtxid().as_hash()
261            }
262        });
263        bitcoin_merkle_root(hashes).map(|h| h.into())
264    }
265
266    /// base_size == size of header + size of encoded transaction count.
267    fn base_size(&self) -> usize {
268        80 + VarInt(self.txdata.len() as u64).len()
269    }
270
271    /// Returns the size of the block.
272    #[deprecated(since = "0.28.0", note = "Please use `block::size` instead.")]
273    pub fn get_size(&self) -> usize {
274        self.size()
275    }
276
277    /// Returns the size of the block.
278    ///
279    /// size == size of header + size of encoded transaction count + total size of transactions.
280    pub fn size(&self) -> usize {
281        let txs_size: usize = self.txdata.iter().map(Transaction::size).sum();
282        self.base_size() + txs_size
283    }
284
285    /// Returns the strippedsize of the block.
286    #[deprecated(since = "0.28.0", note = "Please use `transaction::strippedsize` instead.")]
287    pub fn get_strippedsize(&self) -> usize {
288        self.strippedsize()
289    }
290
291    /// Returns the strippedsize of the block.
292    pub fn strippedsize(&self) -> usize {
293        let txs_size: usize = self.txdata.iter().map(Transaction::strippedsize).sum();
294        self.base_size() + txs_size
295    }
296
297    /// Returns the weight of the block.
298    #[deprecated(since = "0.28.0", note = "Please use `transaction::weight` instead.")]
299    pub fn get_weight(&self) -> usize {
300        self.weight()
301    }
302
303    /// Returns the weight of the block.
304    pub fn weight(&self) -> usize {
305        let base_weight = WITNESS_SCALE_FACTOR * self.base_size();
306        let txs_weight: usize = self.txdata.iter().map(Transaction::weight).sum();
307        base_weight + txs_weight
308    }
309
310    /// Returns the coinbase transaction, if one is present.
311    pub fn coinbase(&self) -> Option<&Transaction> {
312        self.txdata.first()
313    }
314
315    /// Returns the block height, as encoded in the coinbase transaction according to BIP34.
316    pub fn bip34_block_height(&self) -> Result<u64, Bip34Error> {
317        // Citing the spec:
318        // Add height as the first item in the coinbase transaction's scriptSig,
319        // and increase block version to 2. The format of the height is
320        // "serialized CScript" -- first byte is number of bytes in the number
321        // (will be 0x03 on main net for the next 150 or so years with 2^23-1
322        // blocks), following bytes are little-endian representation of the
323        // number (including a sign bit). Height is the height of the mined
324        // block in the block chain, where the genesis block is height zero (0).
325
326        if self.header.version < 2 {
327            return Err(Bip34Error::Unsupported);
328        }
329
330        let cb = self.coinbase().ok_or(Bip34Error::NotPresent)?;
331        let input = cb.input.first().ok_or(Bip34Error::NotPresent)?;
332        let push = input.script_sig.instructions_minimal().next().ok_or(Bip34Error::NotPresent)?;
333        match push.map_err(|_| Bip34Error::NotPresent)? {
334            script::Instruction::PushBytes(b) if b.len() <= 8 => {
335                // Expand the push to exactly 8 bytes (LE).
336                let mut full = [0; 8];
337                full[0..b.len()].copy_from_slice(b);
338                Ok(util::endian::slice_to_u64_le(&full))
339            }
340            script::Instruction::PushBytes(b) if b.len() > 8 => {
341                Err(Bip34Error::UnexpectedPush(b.to_vec()))
342            }
343            _ => Err(Bip34Error::NotPresent),
344        }
345    }
346}
347
348/// An error when looking up a BIP34 block height.
349#[derive(Debug, Clone, PartialEq, Eq)]
350#[non_exhaustive]
351pub enum Bip34Error {
352    /// The block does not support BIP34 yet.
353    Unsupported,
354    /// No push was present where the BIP34 push was expected.
355    NotPresent,
356    /// The BIP34 push was larger than 8 bytes.
357    UnexpectedPush(Vec<u8>),
358}
359
360impl fmt::Display for Bip34Error {
361    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
362        match *self {
363            Bip34Error::Unsupported => write!(f, "block doesn't support BIP34"),
364            Bip34Error::NotPresent => write!(f, "BIP34 push not present in block's coinbase"),
365            Bip34Error::UnexpectedPush(ref p) => {
366                write!(f, "unexpected byte push of > 8 bytes: {:?}", p)
367            }
368        }
369    }
370}
371
372#[cfg(feature = "std")]
373#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
374impl std::error::Error for Bip34Error {
375    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
376        use self::Bip34Error::*;
377
378        match self {
379            Unsupported | NotPresent | UnexpectedPush(_) => None,
380        }
381    }
382}
383
384#[cfg(test)]
385mod tests {
386    use crate::hashes::hex::FromHex;
387
388    use crate::blockdata::block::{Block, BlockHeader};
389    use crate::consensus::encode::{deserialize, serialize};
390    use crate::util::uint::Uint256;
391    use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork};
392    use crate::network::constants::Network;
393
394    #[test]
395    fn test_coinbase_and_bip34() {
396        // testnet block 100,000
397        let block_hex = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3703a08601000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000";
398        let block: Block = deserialize(&Vec::<u8>::from_hex(block_hex).unwrap()).unwrap();
399
400        let cb_txid = "d574f343976d8e70d91cb278d21044dd8a396019e6db70755a0a50e4783dba38";
401        assert_eq!(block.coinbase().unwrap().txid().to_string(), cb_txid);
402
403        assert_eq!(block.bip34_block_height(), Ok(100_000));
404
405
406        // block with 9-byte bip34 push
407        let bad_hex = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3d09a08601112233445566000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000";
408        let bad: Block = deserialize(&Vec::<u8>::from_hex(bad_hex).unwrap()).unwrap();
409
410        let push = Vec::<u8>::from_hex("a08601112233445566").unwrap();
411        assert_eq!(bad.bip34_block_height(), Err(super::Bip34Error::UnexpectedPush(push)));
412    }
413
414    #[test]
415    fn block_test() {
416        // Mainnet block 00000000b0c5a240b2a61d2e75692224efd4cbecdf6eaf4cc2cf477ca7c270e7
417        let some_block = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap();
418        let cutoff_block = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap();
419
420        let prevhash = Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap();
421        let merkle = Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap();
422        let work = Uint256([0x100010001u64, 0, 0, 0]);
423
424        let decode: Result<Block, _> = deserialize(&some_block);
425        let bad_decode: Result<Block, _> = deserialize(&cutoff_block);
426
427        assert!(decode.is_ok());
428        assert!(bad_decode.is_err());
429        let real_decode = decode.unwrap();
430        assert_eq!(real_decode.header.version, 1);
431        assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash);
432        assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap());
433        assert_eq!(serialize(&real_decode.header.merkle_root), merkle);
434        assert_eq!(real_decode.header.time, 1231965655);
435        assert_eq!(real_decode.header.bits, 486604799);
436        assert_eq!(real_decode.header.nonce, 2067413810);
437        assert_eq!(real_decode.header.work(), work);
438        assert_eq!(real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), real_decode.block_hash());
439        assert_eq!(real_decode.header.difficulty(Network::Bitcoin), 1);
440        // [test] TODO: check the transaction data
441
442        assert_eq!(real_decode.size(), some_block.len());
443        assert_eq!(real_decode.strippedsize(), some_block.len());
444        assert_eq!(real_decode.weight(), some_block.len() * 4);
445
446        // should be also ok for a non-witness block as commitment is optional in that case
447        assert!(real_decode.check_witness_commitment());
448
449        assert_eq!(serialize(&real_decode), some_block);
450    }
451
452    // Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b
453    #[test]
454    fn segwit_block_test() {
455        let segwit_block = include_bytes!("../../test_data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw").to_vec();
456
457        let decode: Result<Block, _> = deserialize(&segwit_block);
458
459        let prevhash = Vec::from_hex("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000").unwrap();
460        let merkle = Vec::from_hex("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e").unwrap();
461        let work = Uint256([0x257c3becdacc64u64, 0, 0, 0]);
462
463        assert!(decode.is_ok());
464        let real_decode = decode.unwrap();
465        assert_eq!(real_decode.header.version, 0x20000000);  // VERSIONBITS but no bits set
466        assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash);
467        assert_eq!(serialize(&real_decode.header.merkle_root), merkle);
468        assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap());
469        assert_eq!(real_decode.header.time, 1472004949);
470        assert_eq!(real_decode.header.bits, 0x1a06d450);
471        assert_eq!(real_decode.header.nonce, 1879759182);
472        assert_eq!(real_decode.header.work(), work);
473        assert_eq!(real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), real_decode.block_hash());
474        assert_eq!(real_decode.header.difficulty(Network::Testnet), 2456598);
475        // [test] TODO: check the transaction data
476
477        assert_eq!(real_decode.size(), segwit_block.len());
478        assert_eq!(real_decode.strippedsize(), 4283);
479        assert_eq!(real_decode.weight(), 17168);
480
481        assert!(real_decode.check_witness_commitment());
482
483        assert_eq!(serialize(&real_decode), segwit_block);
484    }
485
486    #[test]
487    fn block_version_test() {
488        let block = Vec::from_hex("ffffff7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
489        let decode: Result<Block, _> = deserialize(&block);
490        assert!(decode.is_ok());
491        let real_decode = decode.unwrap();
492        assert_eq!(real_decode.header.version, 2147483647);
493
494        let block2 = Vec::from_hex("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
495        let decode2: Result<Block, _> = deserialize(&block2);
496        assert!(decode2.is_ok());
497        let real_decode2 = decode2.unwrap();
498        assert_eq!(real_decode2.header.version, -2147483648);
499    }
500
501    #[test]
502    fn validate_pow_test() {
503        let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap();
504        let some_header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header");
505        assert_eq!(some_header.validate_pow(&some_header.target()).unwrap(), some_header.block_hash());
506
507        // test with zero target
508        match some_header.validate_pow(&Uint256::default()) {
509            Err(BlockBadTarget) => (),
510            _ => panic!("unexpected result from validate_pow"),
511        }
512
513        // test with modified header
514        let mut invalid_header: BlockHeader = some_header;
515        invalid_header.version += 1;
516        match invalid_header.validate_pow(&invalid_header.target()) {
517            Err(BlockBadProofOfWork) => (),
518            _ => panic!("unexpected result from validate_pow"),
519        }
520    }
521
522    #[test]
523    fn compact_roundrtip_test() {
524        let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap();
525
526        let header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header");
527
528        assert_eq!(header.bits, BlockHeader::compact_target_from_u256(&header.target()));
529    }
530}
531
532#[cfg(bench)]
533mod benches {
534    use super::Block;
535    use crate::EmptyWrite;
536    use crate::consensus::{deserialize, Encodable, Decodable};
537    use test::{black_box, Bencher};
538
539    #[bench]
540    pub fn bench_stream_reader(bh: &mut Bencher) {
541        let big_block = include_bytes!("../../test_data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw");
542        assert_eq!(big_block.len(), 1_381_836);
543        let big_block = black_box(big_block);
544
545        bh.iter(|| {
546            let mut reader = &big_block[..];
547            let block = Block::consensus_decode(&mut reader).unwrap();
548            black_box(&block);
549        });
550    }
551
552    #[bench]
553    pub fn bench_block_serialize(bh: &mut Bencher) {
554        let raw_block = include_bytes!("../../test_data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw");
555
556        let block: Block = deserialize(&raw_block[..]).unwrap();
557
558        let mut data = Vec::with_capacity(raw_block.len());
559
560        bh.iter(|| {
561            let result = block.consensus_encode(&mut data);
562            black_box(&result);
563            data.clear();
564        });
565    }
566
567    #[bench]
568    pub fn bench_block_serialize_logic(bh: &mut Bencher) {
569        let raw_block = include_bytes!("../../test_data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw");
570
571        let block: Block = deserialize(&raw_block[..]).unwrap();
572
573        bh.iter(|| {
574            let size = block.consensus_encode(&mut EmptyWrite);
575            black_box(&size);
576        });
577    }
578
579    #[bench]
580    pub fn bench_block_deserialize(bh: &mut Bencher) {
581        let raw_block = include_bytes!("../../test_data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw");
582
583        bh.iter(|| {
584            let block: Block = deserialize(&raw_block[..]).unwrap();
585            black_box(&block);
586        });
587    }
588}