diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index 62b69d4fd..44d529ff1 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -4,6 +4,7 @@ use chrono::{DateTime, Utc}; use std::io; use crate::merkle_tree::MerkleTree; +use crate::note_commitment_tree::SaplingNoteTreeRootHash; use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; use crate::sha256d_writer::Sha256dWriter; use crate::transaction::Transaction; @@ -50,22 +51,6 @@ impl From> for MerkleRootHash { } } -/// 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 BlockHeaderHash([u8; 32]); - -impl From for BlockHeaderHash { - 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()) - } -} - /// Block header. /// /// How are blocks chained together? They are chained together via the @@ -93,10 +78,10 @@ pub struct BlockHeader { merkle_root_hash: MerkleRootHash, /// [Sapling onward] The root LEBS2OSP256(rt) of the Sapling note - /// commitment tree corresponding to the nal Sapling treestate of + /// commitment tree corresponding to the finnal Sapling treestate of /// this block. // TODO: replace type with custom SaplingRootHash or similar type - final_sapling_root_hash: [u8; 32], + final_sapling_root_hash: SaplingNoteTreeRootHash, /// The block timestamp is a Unix epoch time (UTC) when the miner /// started hashing the header (according to the miner). diff --git a/zebra-chain/src/lib.rs b/zebra-chain/src/lib.rs index 710d09934..dabff5b2d 100644 --- a/zebra-chain/src/lib.rs +++ b/zebra-chain/src/lib.rs @@ -8,6 +8,7 @@ mod merkle_tree; mod sha256d_writer; pub mod block; +pub mod note_commitment_tree; pub mod serialization; pub mod transaction; pub mod types; diff --git a/zebra-chain/src/note_commitment_tree.rs b/zebra-chain/src/note_commitment_tree.rs new file mode 100644 index 000000000..d1dc20e71 --- /dev/null +++ b/zebra-chain/src/note_commitment_tree.rs @@ -0,0 +1,66 @@ +//! Note Commitment Trees. +//! +//! A note commitment tree is an incremental Merkle tree of fixed depth +//! used to store note commitments that JoinSplit transfers or Spend +//! transfers produce. Just as the unspent transaction output set (UTXO +//! set) used in Bitcoin, it is used to express the existence of value and +//! the capability to spend it. However, unlike the UTXO set, it is not +//! the job of this tree to protect against double-spending, as it is +//! append-only. +//! +//! A root of a note commitment tree is associated with each treestate. + +use std::io; + +use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; +use crate::sha256d_writer::Sha256dWriter; + +// XXX: Depending on if we implement SproutNoteCommitmentTree or +// similar, it may be worth it to define a NoteCommitmentTree trait. + +/// Sapling Note Commitment Tree +#[derive(Default)] +pub struct SaplingNoteCommitmentTree; + +/// Sapling note commitment tree root node hash. +/// +/// The root hash in LEBS2OSP256(rt) encoding of the Sapling note +/// commitment tree corresponding to the final Sapling treestate of +/// this block. A root of a note commitment tree is associated with +/// each treestate. +pub struct SaplingNoteTreeRootHash([u8; 32]); + +impl From for SaplingNoteTreeRootHash { + fn from(sapling_note_commitment_tree: SaplingNoteCommitmentTree) -> Self { + // TODO: The Sapling note commitment tree requires a Pedersen + // hash function, not SHA256. + + // let mut hash_writer = Sha256dWriter::default(); + // sapling_note_commitment_tree + // .zcash_serialize(&mut hash_writer) + // .expect("A Sapling note committment tree must serialize."); + // Self(hash_writer.finish()) + + unimplemented!(); + } +} + +impl SaplingNoteCommitmentTree { + /// Get the Jubjub-based Pedersen hash of root node of this merkle + /// tree of commitment notes. + pub fn hash(&self) -> [u8; 32] { + unimplemented!(); + } +} + +impl ZcashSerialize for SaplingNoteCommitmentTree { + fn zcash_serialize(&self, writer: W) -> Result<(), SerializationError> { + unimplemented!(); + } +} + +impl ZcashDeserialize for SaplingNoteCommitmentTree { + fn zcash_deserialize(reader: R) -> Result { + unimplemented!(); + } +} diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 9ab4ce785..5c16c20b0 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -59,11 +59,13 @@ pub struct TransactionOutput { /// Transaction /// -/// a transaction is an encoded data structure that facilitates the +/// A transaction is an encoded data structure that facilitates the /// transfer of value between two public key addresses on the Zcash /// ecosystem. Everything is designed to ensure that transactions can /// created, propagated on the network, validated, and finally added /// to the global ledger of transactions (the blockchain). +// This is not up to date with the data included in the Zcash +// transaction format: https://zips.z.cash/protocol/protocol.pdf #[derive(Clone, Debug, Eq, PartialEq)] pub struct Transaction { /// Transaction data format version (note, this is signed).