Document part of the block header consensus rules (#3296)
* document header version consensus rule * document nbits threshold consensus rule * document difficulty filter consensus rule * document header solution consensus rule * document header time consensus rule * document upper time limit consensus rule * document max block size consensus rule * skip genesis in conesnsus rule check * remove fixed comment Co-authored-by: teor <teor@riseup.net>
This commit is contained in:
parent
041a2693b7
commit
918a337d8b
|
@ -67,6 +67,12 @@ impl ZcashDeserialize for Header {
|
|||
"high bit was set in version field",
|
||||
));
|
||||
}
|
||||
|
||||
// # Consensus
|
||||
//
|
||||
// > The block version number MUST be greater than or equal to 4.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
if version < 4 {
|
||||
return Err(SerializationError::Parse("version must be at least 4"));
|
||||
}
|
||||
|
@ -115,6 +121,12 @@ impl ZcashSerialize for Block {
|
|||
|
||||
impl ZcashDeserialize for Block {
|
||||
fn zcash_deserialize<R: io::Read>(reader: R) -> Result<Self, SerializationError> {
|
||||
// # Consensus
|
||||
//
|
||||
// > The size of a block MUST be less than or equal to 2000000 bytes.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
//
|
||||
// If the limit is reached, we'll get an UnexpectedEof error
|
||||
let limited_reader = &mut reader.take(MAX_BLOCK_BYTES);
|
||||
Ok(Block {
|
||||
|
|
|
@ -71,13 +71,13 @@ pub fn difficulty_is_valid(
|
|||
))?;
|
||||
}
|
||||
|
||||
// The difficulty filter is also context-free.
|
||||
// # Consensus
|
||||
//
|
||||
// ZIP 205 and ZIP 208 incorrectly describe testnet minimum difficulty blocks
|
||||
// as a change to the difficulty filter. But in `zcashd`, it is implemented
|
||||
// as a change to the difficulty adjustment algorithm. So we don't need to
|
||||
// do anything special for testnet here.
|
||||
// For details, see https://github.com/zcash/zips/issues/416
|
||||
// > The block MUST pass the difficulty filter.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
//
|
||||
// The difficulty filter is also context-free.
|
||||
if hash > &difficulty_threshold {
|
||||
Err(BlockError::DifficultyFilter(
|
||||
*height,
|
||||
|
@ -92,6 +92,11 @@ pub fn difficulty_is_valid(
|
|||
|
||||
/// Returns `Ok(())` if the `EquihashSolution` is valid for `header`
|
||||
pub fn equihash_solution_is_valid(header: &Header) -> Result<(), equihash::Error> {
|
||||
// # Consensus
|
||||
//
|
||||
// > `solution` MUST represent a valid Equihash solution.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
header.solution.check(header)
|
||||
}
|
||||
|
||||
|
|
|
@ -229,14 +229,31 @@ fn difficulty_threshold_is_valid(
|
|||
let median_time_past = difficulty_adjustment.median_time_past();
|
||||
let block_time_max =
|
||||
median_time_past + Duration::seconds(difficulty::BLOCK_MAX_TIME_SINCE_MEDIAN);
|
||||
if candidate_time <= median_time_past {
|
||||
|
||||
// # Consensus
|
||||
//
|
||||
// > For each block other than the genesis block, `nTime` MUST be strictly greater
|
||||
// than the median-time-past of that block.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
let genesis_height = NetworkUpgrade::Genesis
|
||||
.activation_height(network)
|
||||
.expect("Zebra always has a genesis height available");
|
||||
|
||||
if candidate_time <= median_time_past && candidate_height != genesis_height {
|
||||
Err(ValidateContextError::TimeTooEarly {
|
||||
candidate_time,
|
||||
median_time_past,
|
||||
})?
|
||||
}
|
||||
|
||||
// The maximum time rule is only active on Testnet from a specific height
|
||||
// # Consensus
|
||||
//
|
||||
// > For each block at block height 2 or greater on Mainnet, or block height 653_606
|
||||
// or greater on Testnet, `nTime` MUST be less than or equal to the median-time-past
|
||||
// of that block plus 90*60 seconds.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
if NetworkUpgrade::is_max_block_time_enforced(network, candidate_height)
|
||||
&& candidate_time > block_time_max
|
||||
{
|
||||
|
@ -246,6 +263,11 @@ fn difficulty_threshold_is_valid(
|
|||
})?
|
||||
}
|
||||
|
||||
// # Consensus
|
||||
//
|
||||
// > For a block at block height `Height`, `nBits` MUST be equal to `ThresholdBits(Height)`.
|
||||
//
|
||||
// https://zips.z.cash/protocol/protocol.pdf#blockheader
|
||||
let expected_difficulty = difficulty_adjustment.expected_difficulty_threshold();
|
||||
if difficulty_threshold != expected_difficulty {
|
||||
Err(ValidateContextError::InvalidDifficultyThreshold {
|
||||
|
|
Loading…
Reference in New Issue