From 4152d9fc0cca9cb129994e3bd8967c7613e306af Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Thu, 23 Jan 2020 09:29:54 -0500 Subject: [PATCH] Build block header from pre pow data and proof (#3178) * Implement validation and generation of block header by proof and pre pow * Optimize * handle missed ser result errors and test invalid pre_pow * switch to specific error mapping * clean import --- core/src/core/block.rs | 23 ++++++++++++++++++++++- core/tests/block.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/core/src/core/block.rs b/core/src/core/block.rs index c24df1a2b..bc15624eb 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -25,7 +25,10 @@ use crate::core::{ }; use crate::global; use crate::pow::{verify_size, Difficulty, Proof, ProofOfWork}; -use crate::ser::{self, FixedLength, PMMRable, Readable, Reader, Writeable, Writer}; +use crate::ser::{ + self, deserialize_default, serialize_default, FixedLength, PMMRable, Readable, Reader, + Writeable, Writer, +}; use chrono::naive::{MAX_DATE, MIN_DATE}; use chrono::prelude::{DateTime, NaiveDateTime, Utc}; use chrono::Duration; @@ -34,6 +37,7 @@ use std::collections::HashSet; use std::fmt; use std::iter::FromIterator; use std::sync::Arc; +use util::from_hex; use util::RwLock; use util::{secp, static_secp_instance}; @@ -350,6 +354,23 @@ impl BlockHeader { header_buf } + /// Constructs a header given pre_pow string, nonce, and proof + pub fn from_pre_pow_and_proof( + pre_pow: String, + nonce: u64, + proof: Proof, + ) -> Result { + // Convert hex pre pow string + let mut header_bytes = from_hex(pre_pow) + .map_err(|e| Error::Serialization(ser::Error::HexError(e.to_string())))?; + // Serialize and append serialized nonce and proof + serialize_default(&mut header_bytes, &nonce)?; + serialize_default(&mut header_bytes, &proof)?; + + // Deserialize header from constructed bytes + Ok(deserialize_default(&mut &header_bytes[..])?) + } + /// Total difficulty accumulated by the proof of work on this header pub fn total_difficulty(&self) -> Difficulty { self.pow.total_difficulty diff --git a/core/tests/block.rs b/core/tests/block.rs index 69a03fe0a..7b42da707 100644 --- a/core/tests/block.rs +++ b/core/tests/block.rs @@ -26,6 +26,7 @@ use crate::core::core::{ }; use crate::core::libtx::build::{self, input, output}; use crate::core::libtx::ProofBuilder; +use crate::core::pow::Proof; use crate::core::{global, ser}; use chrono::Duration; use grin_core as core; @@ -569,3 +570,36 @@ fn wrong_amount_range_proof() { _ => panic!("Bad range proof should be invalid"), } } + +#[test] +fn validate_header_proof() { + let keychain = ExtKeychain::from_random_seed(false).unwrap(); + let builder = ProofBuilder::new(&keychain); + let prev = BlockHeader::default(); + let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); + let b = new_block(vec![], &keychain, &builder, &prev, &key_id); + + let mut header_buf = vec![]; + { + let mut writer = ser::BinWriter::default(&mut header_buf); + b.header.write_pre_pow(&mut writer).unwrap(); + b.header.pow.write_pre_pow(&mut writer).unwrap(); + } + let pre_pow = util::to_hex(header_buf); + + let reconstructed = BlockHeader::from_pre_pow_and_proof( + pre_pow, + b.header.pow.nonce, + b.header.pow.proof.clone(), + ) + .unwrap(); + assert_eq!(reconstructed, b.header); + + // assert invalid pre_pow returns error + assert!(BlockHeader::from_pre_pow_and_proof( + "0xaf1678".to_string(), + b.header.pow.nonce, + b.header.pow.proof.clone(), + ) + .is_err()); +}