Adding BlockHeader, BlockHash, MerkleRootHash, Sha256dWriter
This commit is contained in:
parent
00494d4963
commit
7340c7d9ce
|
@ -1,26 +1,62 @@
|
||||||
//! Definitions of block datastructures.
|
//! Definitions of block datastructures.
|
||||||
|
|
||||||
use crate::transaction::Transaction;
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use crate::merkle_tree::MerkleTree;
|
||||||
|
use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
|
||||||
|
use crate::sha256d_writer::Sha256dWriter;
|
||||||
|
use crate::transaction::Transaction;
|
||||||
|
|
||||||
|
/// A SHA-256d hash of a BlockHeader.
|
||||||
|
///
|
||||||
|
/// This is useful when one block header is pointing to its parent
|
||||||
|
/// block header in the block chain. ⛓️
|
||||||
|
pub struct BlockHash([u8; 32]);
|
||||||
|
|
||||||
|
impl From<BlockHeader> for BlockHash {
|
||||||
|
fn from(block_header: BlockHeader) -> Self {
|
||||||
|
let mut hash_writer = Sha256dWriter::default();
|
||||||
|
block_header
|
||||||
|
.zcash_serialize(&mut hash_writer)
|
||||||
|
.expect("Block headers must serialize.");
|
||||||
|
Self(hash_writer.finish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A SHA-256d hash of the root node of a merkle tree of SHA256-d
|
||||||
|
/// hashed transactions in a block.
|
||||||
|
pub struct MerkleRootHash([u8; 32]);
|
||||||
|
|
||||||
|
impl From<MerkleTree<Transaction>> for MerkleRootHash {
|
||||||
|
fn from(merkle_tree: MerkleTree<Transaction>) -> Self {
|
||||||
|
let mut hash_writer = Sha256dWriter::default();
|
||||||
|
merkle_tree
|
||||||
|
.zcash_serialize(&mut hash_writer)
|
||||||
|
.expect("The merkle tree of transactions must serialize.");
|
||||||
|
Self(hash_writer.finish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Block header
|
/// Block header
|
||||||
pub struct BlockHeader {
|
pub struct BlockHeader {
|
||||||
/// A SHA-256d hash in internal byte order of the previous block’s
|
/// A SHA-256d hash in internal byte order of the previous block’s
|
||||||
/// header. This ensures no previous block can be changed without
|
/// header. This ensures no previous block can be changed without
|
||||||
/// also changing this block’s header .
|
/// also changing this block’s header .
|
||||||
previous_block_hash: [u8; 32],
|
previous_block_hash: BlockHash,
|
||||||
|
|
||||||
/// A SHA-256d hash in internal byte order. The merkle root is
|
/// A SHA-256d hash in internal byte order. The merkle root is
|
||||||
/// derived from the hashes of all transactions included in this
|
/// derived from the SHA256d hashes of all transactions included
|
||||||
/// block, ensuring that none of those transactions can be modied
|
/// in this block as assembled in a binary tree, ensuring that
|
||||||
/// without modifying the header.
|
/// none of those transactions can be modied without modifying the
|
||||||
|
/// header.
|
||||||
merkle_root_hash: [u8; 32],
|
merkle_root_hash: [u8; 32],
|
||||||
|
|
||||||
/// [Sapling onward] The root LEBS2OSP256(rt) of the Sapling note
|
/// [Sapling onward] The root LEBS2OSP256(rt) of the Sapling note
|
||||||
/// commitment tree corresponding to the nal Sapling treestate of
|
/// commitment tree corresponding to the nal Sapling treestate of
|
||||||
/// this block.
|
/// this block.
|
||||||
// TODO: replace type with custom SaplingRoot or similar type
|
// TODO: replace type with custom SaplingRoot or similar type
|
||||||
// hash_final_sapling_root: [u8; 32],
|
// hash_final_sapling_root: SaplingRootHash,
|
||||||
|
|
||||||
/// The block timestamp is a Unix epoch time (UTC) when the miner
|
/// The block timestamp is a Unix epoch time (UTC) when the miner
|
||||||
/// started hashing the header (according to the miner).
|
/// started hashing the header (according to the miner).
|
||||||
|
@ -55,12 +91,24 @@ impl BlockHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ZcashSerialize for BlockHeader {
|
||||||
|
fn zcash_serialize<W: io::Write>(&self, writer: W) -> Result<(), SerializationError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ZcashDeserialize for BlockHeader {
|
||||||
|
fn zcash_deserialize<R: io::Read>(reader: R) -> Result<Self, SerializationError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A block in your blockchain.
|
/// A block in your blockchain.
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
/// First 80 bytes of the block as defined by the encoding used by
|
/// First 80 bytes of the block as defined by the encoding used by
|
||||||
/// "block" messages
|
/// "block" messages.
|
||||||
pub header: BlockHeader,
|
pub header: BlockHeader,
|
||||||
|
|
||||||
///
|
/// Block transactions.
|
||||||
pub transactions: Vec<Transaction>,
|
pub transactions: Vec<Transaction>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
|
|
||||||
|
mod merkle_tree;
|
||||||
|
mod sha256d_writer;
|
||||||
|
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod serialization;
|
pub mod serialization;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
//! A binary hash tree of SHA256d (two rounds of SHA256) hashes for
|
||||||
|
//! node values.
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
|
||||||
|
|
||||||
|
/// A binary hash tree of SHA256d (two rounds of SHA256) hashes for
|
||||||
|
/// node values.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MerkleTree<T> {
|
||||||
|
leaves: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MerkleTree<T> {
|
||||||
|
pub fn get_root(&self) -> Sha256 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ZcashSerialize for MerkleTree<T> {
|
||||||
|
fn zcash_serialize<W: io::Write>(&self, writer: W) -> Result<(), SerializationError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ZcashDeserialize for MerkleTree<T> {
|
||||||
|
fn zcash_deserialize<R: io::Read>(reader: R) -> Result<Self, SerializationError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
//! A Writer for Sha256d-related (two rounds of SHA256) types.
|
||||||
|
|
||||||
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
/// A type that lets you write out SHA256d (double-SHA256, as in two rounds).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Sha256dWriter {
|
||||||
|
hash: Sha256,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sha256dWriter {
|
||||||
|
/// Consume the Writer and produce the hash result.
|
||||||
|
pub fn finish(self) -> [u8; 32] {
|
||||||
|
let result1 = self.hash.result();
|
||||||
|
let result2 = Sha256::digest(&result1);
|
||||||
|
let mut buffer = [0u8; 32];
|
||||||
|
buffer[0..32].copy_from_slice(&result2[0..32]);
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for Sha256dWriter {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
|
self.hash.input(buf);
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
//! Newtype wrappers for primitive data types with semantic meaning.
|
//! Newtype wrappers for primitive data types with semantic meaning.
|
||||||
|
|
||||||
/// A 4-byte checksum using truncated double SHA256.
|
/// A 4-byte checksum using truncated double-SHA256 (two rounds of SHA256).
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Sha256dChecksum(pub [u8; 4]);
|
pub struct Sha256dChecksum(pub [u8; 4]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue