Move is_equihash_solution_valid to zebra-consensus

This commit is contained in:
Ramana Venkata 2020-09-04 07:26:09 +05:30 committed by teor
parent 2a68ef5acb
commit 7118e4da3c
6 changed files with 45 additions and 36 deletions

View File

@ -1,6 +1,5 @@
use chrono::{DateTime, Duration, Utc};
use crate::serialization::ZcashSerialize;
use crate::work::{difficulty::CompactDifficulty, equihash::Solution};
use super::{merkle, Error, Hash};
@ -69,24 +68,6 @@ pub struct Header {
}
impl Header {
/// Returns true if the header is valid based on its `EquihashSolution`
pub fn is_equihash_solution_valid(&self) -> Result<(), EquihashError> {
let n = 200;
let k = 9;
let nonce = &self.nonce;
let solution = &self.solution.0;
let mut input = Vec::new();
self.zcash_serialize(&mut input)
.expect("serialization into a vec can't fail");
let input = &input[0..Solution::INPUT_LENGTH];
equihash::is_valid_solution(n, k, input, nonce, solution)?;
Ok(())
}
/// Check if `self.time` is less than or equal to
/// 2 hours in the future, according to the node's local clock (`now`).
///
@ -112,8 +93,3 @@ impl Header {
}
}
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[error("invalid equihash solution for BlockHeader")]
pub struct EquihashError(#[from] equihash::Error);

View File

@ -1,11 +1,18 @@
//! Equihash Solution and related items.
use crate::block::Header;
use crate::serialization::{
serde_helpers, ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize,
ZcashSerialize,
};
use std::{fmt, io};
/// The error type for Equihash
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[error("invalid equihash solution for BlockHeader")]
pub struct Error(#[from] equihash::Error);
/// The size of an Equihash solution in bytes (always 1344).
pub(crate) const SOLUTION_SIZE: usize = 1344;
@ -24,6 +31,25 @@ impl Solution {
/// The length of the portion of the header used as input when verifying
/// equihash solutions, in bytes
pub const INPUT_LENGTH: usize = 4 + 32 * 3 + 4 * 2;
/// Returns true if the header is valid based on its `EquihashSolution`
pub fn check(&self, block: &Header) -> Result<(), Error> {
let n = 200;
let k = 9;
let nonce = &block.nonce;
let solution = &self.0;
let mut input = Vec::new();
block
.zcash_serialize(&mut input)
.expect("serialization into a vec can't fail");
let input = &input[0..Solution::INPUT_LENGTH];
equihash::is_valid_solution(n, k, input, nonce, solution)?;
Ok(())
}
}
impl PartialEq<Solution> for Solution {

View File

@ -39,11 +39,11 @@ fn equihash_prop_test_solution() -> color_eyre::eyre::Result<()> {
for block_bytes in zebra_test::vectors::TEST_BLOCKS.iter() {
let block = Block::zcash_deserialize(&block_bytes[..])
.expect("block test vector should deserialize");
block.header.is_equihash_solution_valid()?;
block.header.solution.check(&block.header)?;
proptest!(|(fake_header in randomized_solutions(block.header))| {
fake_header
.is_equihash_solution_valid()
fake_header.solution
.check(&fake_header)
.expect_err("block header should not validate on randomized solution");
});
}
@ -71,11 +71,11 @@ fn equihash_prop_test_nonce() -> color_eyre::eyre::Result<()> {
for block_bytes in zebra_test::vectors::TEST_BLOCKS.iter() {
let block = Block::zcash_deserialize(&block_bytes[..])
.expect("block test vector should deserialize");
block.header.is_equihash_solution_valid()?;
block.header.solution.check(&block.header)?;
proptest!(|(fake_header in randomized_nonce(block.header))| {
fake_header
.is_equihash_solution_valid()
fake_header.solution
.check(&fake_header)
.expect_err("block header should not validate on randomized nonce");
});
}
@ -106,11 +106,11 @@ fn equihash_prop_test_input() -> color_eyre::eyre::Result<()> {
for block_bytes in zebra_test::vectors::TEST_BLOCKS.iter() {
let block = Block::zcash_deserialize(&block_bytes[..])
.expect("block test vector should deserialize");
block.header.is_equihash_solution_valid()?;
block.header.solution.check(&block.header)?;
proptest!(|(fake_header in randomized_input(block.header))| {
fake_header
.is_equihash_solution_valid()
fake_header.solution
.check(&fake_header)
.expect_err("equihash solution should not validate on randomized input");
});
}

View File

@ -31,7 +31,7 @@ fn equihash_solution_test_vector_is_valid() -> color_eyre::eyre::Result<()> {
let block = Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_415000_BYTES[..])
.expect("block test vector should deserialize");
block.header.is_equihash_solution_valid()?;
block.header.solution.check(&block.header)?;
Ok(())
}

View File

@ -100,7 +100,7 @@ where
if hash > difficulty_threshold {
Err("Block failed the difficulty filter: hash must be less than or equal to the difficulty threshold.")?;
}
block.header.is_equihash_solution_valid()?;
check::is_equihash_solution_valid(&block.header)?;
// Since errors cause an early exit, try to do the
// quick checks first.

View File

@ -1,7 +1,10 @@
//! Consensus check functions
use super::*;
use zebra_chain::block::Block;
use zebra_chain::{
block::{Block, Header},
work::equihash,
};
/// Check that there is exactly one coinbase transaction in `Block`, and that
/// the coinbase transaction is the first transaction in the block.
@ -25,3 +28,7 @@ pub fn is_coinbase_first(block: &Block) -> Result<(), Error> {
}
Ok(())
}
pub fn is_equihash_solution_valid(header: &Header) -> Result<(), equihash::Error> {
header.solution.check(&header)
}