From 3f25da996a01cd37e11cac0bdcbc1cbc04803c31 Mon Sep 17 00:00:00 2001 From: Ramana Venkata Date: Wed, 9 Sep 2020 05:09:03 +0530 Subject: [PATCH] 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. --- zebra-chain/src/block/header.rs | 16 ++-------------- zebra-chain/src/block/tests/vectors.rs | 24 +----------------------- zebra-consensus/src/block.rs | 2 +- zebra-consensus/src/block/check.rs | 20 ++++++++++++++++++++ zebra-consensus/src/block/tests.rs | 19 +++++++++++++++++++ 5 files changed, 43 insertions(+), 38 deletions(-) diff --git a/zebra-chain/src/block/header.rs b/zebra-chain/src/block/header.rs index eb29dcb0..0dac000b 100644 --- a/zebra-chain/src/block/header.rs +++ b/zebra-chain/src/block/header.rs @@ -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) -> Result<(), Error> { let two_hours_in_the_future = now .checked_add_signed(Duration::hours(2)) diff --git a/zebra-chain/src/block/tests/vectors.rs b/zebra-chain/src/block/tests/vectors.rs index ef3656fb..2c30a218 100644 --- a/zebra-chain/src/block/tests/vectors.rs +++ b/zebra-chain/src/block/tests/vectors.rs @@ -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::::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 diff --git a/zebra-consensus/src/block.rs b/zebra-consensus/src/block.rs index 57815230..5234103c 100644 --- a/zebra-consensus/src/block.rs +++ b/zebra-consensus/src/block.rs @@ -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: diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index b3c46a3e..b4f54ba7 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -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) -> Result<(), Error> { + header.is_time_valid_at(now) +} diff --git a/zebra-consensus/src/block/tests.rs b/zebra-consensus/src/block/tests.rs index 5f276e65..a417fa52 100644 --- a/zebra-consensus/src/block/tests.rs +++ b/zebra-consensus/src/block/tests.rs @@ -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::::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"); +}