Add wrapper fn is_time_valid_at in zebra_consensus::block::check

This commit doesn't move the fn itself because it's tests can't
depend on `generate` code which is not exposed to other crates.
This commit is contained in:
Ramana Venkata 2020-09-09 05:09:03 +05:30 committed by teor
parent 7118e4da3c
commit 3f25da996a
5 changed files with 43 additions and 38 deletions

View File

@ -68,20 +68,8 @@ pub struct Header {
}
impl Header {
/// Check if `self.time` is less than or equal to
/// 2 hours in the future, according to the node's local clock (`now`).
///
/// This is a non-deterministic rule, as clocks vary over time, and
/// between different nodes.
///
/// "In addition, a full validator MUST NOT accept blocks with nTime
/// more than two hours in the future according to its clock. This
/// is not strictly a consensus rule because it is nondeterministic,
/// and clock time varies between nodes. Also note that a block that
/// is rejected by this rule at a given point in time may later be
/// accepted." [§7.5][7.5]
///
/// [7.5]: https://zips.z.cash/protocol/protocol.pdf#blockheader
/// TODO Inline this function in zebra_consensus::block::check see
/// https://github.com/ZcashFoundation/zebra/issues/1021 for more details
pub fn is_time_valid_at(&self, now: DateTime<Utc>) -> Result<(), Error> {
let two_hours_in_the_future = now
.checked_add_signed(Duration::hours(2))

View File

@ -1,7 +1,4 @@
use std::{
io::{Cursor, Write},
sync::Arc,
};
use std::io::{Cursor, Write};
use chrono::{DateTime, Duration, LocalResult, TimeZone, Utc};
@ -145,25 +142,6 @@ fn block_limits_single_tx() {
Block::zcash_deserialize(&data[..]).expect_err("block should not deserialize");
}
#[test]
fn time_check_past_block() {
// This block is also verified as part of the BlockVerifier service
// tests.
let block =
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_415000_BYTES[..])
.expect("block should deserialize");
let now = Utc::now();
// This check is non-deterministic, but BLOCK_MAINNET_415000 is
// a long time in the past. So it's unlikely that the test machine
// will have a clock that's far enough in the past for the test to
// fail.
block
.header
.is_time_valid_at(now)
.expect("the header time from a mainnet block should be valid");
}
/// Test wrapper for `BlockHeader.is_time_valid_at`.
///
/// Generates a block header, sets its `time` to `block_header_time`, then

View File

@ -107,7 +107,7 @@ where
// Field validity and structure checks
let now = Utc::now();
block.header.is_time_valid_at(now)?;
check::is_time_valid_at(&block.header, now)?;
check::is_coinbase_first(&block)?;
// TODO:

View File

@ -1,6 +1,7 @@
//! Consensus check functions
use super::*;
use chrono::{DateTime, Utc};
use zebra_chain::{
block::{Block, Header},
work::equihash,
@ -29,6 +30,25 @@ pub fn is_coinbase_first(block: &Block) -> Result<(), Error> {
Ok(())
}
/// Returns true if the header is valid based on its `EquihashSolution`
pub fn is_equihash_solution_valid(header: &Header) -> Result<(), equihash::Error> {
header.solution.check(&header)
}
/// Check if `header.time` is less than or equal to
/// 2 hours in the future, according to the node's local clock (`now`).
///
/// This is a non-deterministic rule, as clocks vary over time, and
/// between different nodes.
///
/// "In addition, a full validator MUST NOT accept blocks with nTime
/// more than two hours in the future according to its clock. This
/// is not strictly a consensus rule because it is nondeterministic,
/// and clock time varies between nodes. Also note that a block that
/// is rejected by this rule at a given point in time may later be
/// accepted." [§7.5][7.5]
///
/// [7.5]: https://zips.z.cash/protocol/protocol.pdf#blockheader
pub fn is_time_valid_at(header: &Header, now: DateTime<Utc>) -> Result<(), Error> {
header.is_time_valid_at(now)
}

View File

@ -2,6 +2,8 @@
use super::*;
use std::sync::Arc;
use chrono::Utc;
use color_eyre::eyre::{eyre, Report};
use once_cell::sync::Lazy;
@ -121,3 +123,20 @@ async fn check_transcripts() -> Result<(), Report> {
}
Ok(())
}
#[test]
fn time_check_past_block() {
// This block is also verified as part of the BlockVerifier service
// tests.
let block =
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_415000_BYTES[..])
.expect("block should deserialize");
let now = Utc::now();
// This check is non-deterministic, but BLOCK_MAINNET_415000 is
// a long time in the past. So it's unlikely that the test machine
// will have a clock that's far enough in the past for the test to
// fail.
check::is_time_valid_at(&block.header, now)
.expect("the header time from a mainnet block should be valid");
}