Compute and store BlockHash inside BlockHeader

This commit is contained in:
Jack Grigg 2019-05-01 00:08:54 +01:00
parent b66ac11775
commit a3b85b8fe6
No known key found for this signature in database
GPG Key ID: 9E8255172BBF9898
1 changed files with 33 additions and 6 deletions

View File

@ -2,6 +2,7 @@
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use hex; use hex;
use sha2::{Digest, Sha256};
use std::fmt; use std::fmt;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::ops::Deref; use std::ops::Deref;
@ -22,13 +23,16 @@ impl fmt::Display for BlockHash {
} }
/// A Zcash block header. /// A Zcash block header.
pub struct BlockHeader(BlockHeaderData); pub struct BlockHeader {
hash: BlockHash,
data: BlockHeaderData,
}
impl Deref for BlockHeader { impl Deref for BlockHeader {
type Target = BlockHeaderData; type Target = BlockHeaderData;
fn deref(&self) -> &BlockHeaderData { fn deref(&self) -> &BlockHeaderData {
&self.0 &self.data
} }
} }
@ -44,12 +48,31 @@ pub struct BlockHeaderData {
} }
impl BlockHeaderData { impl BlockHeaderData {
pub fn freeze(self) -> BlockHeader { pub fn freeze(self) -> io::Result<BlockHeader> {
BlockHeader(self) BlockHeader::from_data(self)
} }
} }
impl BlockHeader { impl BlockHeader {
fn from_data(data: BlockHeaderData) -> io::Result<Self> {
let mut header = BlockHeader {
hash: BlockHash([0; 32]),
data,
};
let mut raw = vec![];
header.write(&mut raw)?;
header
.hash
.0
.copy_from_slice(&Sha256::digest(&Sha256::digest(&raw)));
Ok(header)
}
/// Returns the hash of this header.
pub fn hash(&self) -> BlockHash {
self.hash
}
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> { pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let version = reader.read_i32::<LittleEndian>()?; let version = reader.read_i32::<LittleEndian>()?;
@ -70,7 +93,7 @@ impl BlockHeader {
let solution = Vector::read(&mut reader, |r| r.read_u8())?; let solution = Vector::read(&mut reader, |r| r.read_u8())?;
Ok(BlockHeader(BlockHeaderData { BlockHeader::from_data(BlockHeaderData {
version, version,
prev_block, prev_block,
merkle_root, merkle_root,
@ -79,7 +102,7 @@ impl BlockHeader {
bits, bits,
nonce, nonce,
solution, solution,
})) })
} }
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> { pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
@ -206,6 +229,10 @@ mod tests {
#[test] #[test]
fn header_read_write() { fn header_read_write() {
let header = BlockHeader::read(&HEADER_MAINNET_415000[..]).unwrap(); let header = BlockHeader::read(&HEADER_MAINNET_415000[..]).unwrap();
assert_eq!(
format!("{}", header.hash()),
"0000000001ab37793ce771262b2ffa082519aa3fe891250a1adb43baaf856168"
);
let mut encoded = Vec::with_capacity(HEADER_MAINNET_415000.len()); let mut encoded = Vec::with_capacity(HEADER_MAINNET_415000.len());
header.write(&mut encoded).unwrap(); header.write(&mut encoded).unwrap();
assert_eq!(&HEADER_MAINNET_415000[..], &encoded[..]); assert_eq!(&HEADER_MAINNET_415000[..], &encoded[..]);