Skip to content

Commit

Permalink
Round-trip the PoWLimit through the compact representation
Browse files Browse the repository at this point in the history
`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.
  • Loading branch information
teor2345 committed Nov 12, 2020
1 parent 8f83816 commit b2a9ea6
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
11 changes: 10 additions & 1 deletion zebra-chain/src/work/difficulty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
38 changes: 38 additions & 0 deletions zebra-chain/src/work/difficulty/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit b2a9ea6

Please sign in to comment.