diff --git a/zebra-chain/src/work/difficulty.rs b/zebra-chain/src/work/difficulty.rs index 846583eb8..119a97c3c 100644 --- a/zebra-chain/src/work/difficulty.rs +++ b/zebra-chain/src/work/difficulty.rs @@ -280,7 +280,16 @@ impl ExpandedDifficulty { Network::Testnet => (U256::one() << 251) - 1, }; - limit.into() + // `zcashd` converts the PoWLimit into a compact representation before + // using it to perform difficulty filter checks. + // + // The Zcash specification converts to compact for the default difficulty + // filter, but not for testnet minimum difficulty blocks. (ZIP 205 and + // ZIP 208 don't specify this conversion either.) See #1277 for details. + ExpandedDifficulty(limit) + .to_compact() + .to_expanded() + .expect("difficulty limits are valid expanded values") } /// Calculate the CompactDifficulty for an expanded difficulty. diff --git a/zebra-chain/src/work/difficulty/tests/vectors.rs b/zebra-chain/src/work/difficulty/tests/vectors.rs index 9379c88a9..bb4488b35 100644 --- a/zebra-chain/src/work/difficulty/tests/vectors.rs +++ b/zebra-chain/src/work/difficulty/tests/vectors.rs @@ -318,6 +318,44 @@ fn block_difficulty() -> Result<(), Report> { Ok(()) } +/// Test that the genesis block threshold is PowLimit +#[test] +fn genesis_block_difficulty() -> Result<(), Report> { + genesis_block_difficulty_for_network(Network::Mainnet)?; + genesis_block_difficulty_for_network(Network::Testnet)?; + + Ok(()) +} + +#[spandoc::spandoc] +fn genesis_block_difficulty_for_network(network: Network) -> Result<(), Report> { + zebra_test::init(); + + let block = match network { + Network::Mainnet => zebra_test::vectors::MAINNET_BLOCKS.get(&0), + Network::Testnet => zebra_test::vectors::TESTNET_BLOCKS.get(&0), + }; + + let block = block.expect("test vectors contain the genesis block"); + let block = Block::zcash_deserialize(&block[..]).expect("block test vector should deserialize"); + let hash = block.hash(); + + /// SPANDOC: Calculate the threshold for the genesis block {?network} + let threshold = block + .header + .difficulty_threshold + .to_expanded() + .expect("Chain blocks have valid difficulty thresholds."); + + /// SPANDOC: Check the genesis PoWLimit {?network, ?threshold, ?hash} + { + assert_eq!(threshold, ExpandedDifficulty::target_difficulty_limit(network), + "genesis block difficulty thresholds must be equal to the PoWLimit"); + } + + Ok(()) +} + /// Test ExpandedDifficulty ordering #[test] #[spandoc::spandoc]