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:
parent
7118e4da3c
commit
3f25da996a
|
|
@ -68,20 +68,8 @@ pub struct Header {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Header {
|
impl Header {
|
||||||
/// Check if `self.time` is less than or equal to
|
/// TODO Inline this function in zebra_consensus::block::check see
|
||||||
/// 2 hours in the future, according to the node's local clock (`now`).
|
/// https://github.com/ZcashFoundation/zebra/issues/1021 for more details
|
||||||
///
|
|
||||||
/// 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(&self, now: DateTime<Utc>) -> Result<(), Error> {
|
pub fn is_time_valid_at(&self, now: DateTime<Utc>) -> Result<(), Error> {
|
||||||
let two_hours_in_the_future = now
|
let two_hours_in_the_future = now
|
||||||
.checked_add_signed(Duration::hours(2))
|
.checked_add_signed(Duration::hours(2))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
use std::{
|
use std::io::{Cursor, Write};
|
||||||
io::{Cursor, Write},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use chrono::{DateTime, Duration, LocalResult, TimeZone, Utc};
|
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");
|
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`.
|
/// Test wrapper for `BlockHeader.is_time_valid_at`.
|
||||||
///
|
///
|
||||||
/// Generates a block header, sets its `time` to `block_header_time`, then
|
/// Generates a block header, sets its `time` to `block_header_time`, then
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ where
|
||||||
|
|
||||||
// Field validity and structure checks
|
// Field validity and structure checks
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
block.header.is_time_valid_at(now)?;
|
check::is_time_valid_at(&block.header, now)?;
|
||||||
check::is_coinbase_first(&block)?;
|
check::is_coinbase_first(&block)?;
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! Consensus check functions
|
//! Consensus check functions
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
block::{Block, Header},
|
block::{Block, Header},
|
||||||
work::equihash,
|
work::equihash,
|
||||||
|
|
@ -29,6 +30,25 @@ pub fn is_coinbase_first(block: &Block) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the header is valid based on its `EquihashSolution`
|
||||||
pub fn is_equihash_solution_valid(header: &Header) -> Result<(), equihash::Error> {
|
pub fn is_equihash_solution_valid(header: &Header) -> Result<(), equihash::Error> {
|
||||||
header.solution.check(&header)
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use color_eyre::eyre::{eyre, Report};
|
use color_eyre::eyre::{eyre, Report};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
@ -121,3 +123,20 @@ async fn check_transcripts() -> Result<(), Report> {
|
||||||
}
|
}
|
||||||
Ok(())
|
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");
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue