From f94033df08fb78c600e1dc5c41ee8a4ea1084989 Mon Sep 17 00:00:00 2001 From: teor Date: Fri, 28 May 2021 01:41:20 +1000 Subject: [PATCH] Make arbitrary block chains pass some genesis checks (#2208) * Clarify the finalized state assertion that checks the genesis block * Make arbitrary block chains pass some genesis checks Use the genesis previous block hash for - the first arbitrary block in each chain, and - individual arbitrary blocks. This setting can be adjusted by individual proptests as needed. --- zebra-chain/src/block/arbitrary.rs | 34 +++++++++++++++++++--- zebra-state/src/service/finalized_state.rs | 3 +- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/zebra-chain/src/block/arbitrary.rs b/zebra-chain/src/block/arbitrary.rs index 2c87ce96..4102decd 100644 --- a/zebra-chain/src/block/arbitrary.rs +++ b/zebra-chain/src/block/arbitrary.rs @@ -6,7 +6,7 @@ use proptest::{ use std::sync::Arc; use crate::{ - parameters::{Network, NetworkUpgrade}, + parameters::{Network, NetworkUpgrade, GENESIS_PREVIOUS_BLOCK_HASH}, serialization, work::{difficulty::CompactDifficulty, equihash}, }; @@ -20,6 +20,9 @@ pub struct LedgerState { /// The tip height of the block or start of the chain. /// /// To get the network upgrade, use the `network_upgrade` method. + /// + /// If `network_upgrade_override` is not set, the network upgrade is derived + /// from the height and network. pub tip_height: Height, /// The network to generate fake blocks for. @@ -38,6 +41,12 @@ pub struct LedgerState { /// For an individual transaction, make the transaction a coinbase /// transaction. pub(crate) has_coinbase: bool, + + /// Should this block have a genesis (all-zeroes) previous block hash? + /// + /// In Zebra's proptests, the previous block hash can be overriden with + /// genesis at any block height. + genesis_previous_block_hash_override: bool, } impl LedgerState { @@ -53,6 +62,14 @@ impl LedgerState { } } + /// Should this block have a genesis (all-zeroes) previous block hash? + /// + /// In Zebra's proptests, the previous block hash can be overriden with + /// genesis at any block height. + pub fn use_genesis_previous_block_hash(&self) -> bool { + self.tip_height == Height(0) || self.genesis_previous_block_hash_override + } + /// Returns a strategy for creating `LedgerState`s that always have coinbase /// transactions. pub fn coinbase_strategy() -> BoxedStrategy { @@ -79,6 +96,8 @@ impl Default for LedgerState { network, network_upgrade_override: nu5_override, has_coinbase: true, + // start each chain with a genesis previous block hash, regardless of height + genesis_previous_block_hash_override: true, } } } @@ -110,6 +129,7 @@ impl Arbitrary for LedgerState { network, network_upgrade_override, has_coinbase: require_coinbase || has_coinbase, + genesis_previous_block_hash_override: true, } }) .boxed() @@ -125,9 +145,14 @@ impl Arbitrary for Block { let transactions_strategy = Transaction::vec_strategy(ledger_state, 2); (any::
(), transactions_strategy) - .prop_map(|(header, transactions)| Self { - header, - transactions, + .prop_map(move |(mut header, transactions)| { + if ledger_state.genesis_previous_block_hash_override { + header.previous_block_hash = GENESIS_PREVIOUS_BLOCK_HASH; + } + Self { + header, + transactions, + } }) .boxed() } @@ -147,6 +172,7 @@ impl Block { for _ in 0..count { vec.push(Block::arbitrary_with(current).prop_map(Arc::new)); current.tip_height.0 += 1; + current.genesis_previous_block_hash_override = false; } vec.boxed() diff --git a/zebra-state/src/service/finalized_state.rs b/zebra-state/src/service/finalized_state.rs index d7f89c07..a418608b 100644 --- a/zebra-state/src/service/finalized_state.rs +++ b/zebra-state/src/service/finalized_state.rs @@ -198,8 +198,7 @@ impl FinalizedState { // Assert that callers (including unit tests) get the chain order correct if self.is_empty(hash_by_height) { assert_eq!( - block::Hash([0; 32]), - block.header.previous_block_hash, + GENESIS_PREVIOUS_BLOCK_HASH, block.header.previous_block_hash, "the first block added to an empty state must be a genesis block" ); assert_eq!(