Skip to content

Commit

Permalink
Format commitments and nonces as hex
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Jan 16, 2023
1 parent b060408 commit cbed2c2
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 25 deletions.
2 changes: 1 addition & 1 deletion zebra-chain/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl Block {
None => Err(CommitmentError::MissingBlockHeight {
block_hash: self.hash(),
}),
Some(height) => Commitment::from_bytes(self.header.commitment_bytes, network, height),
Some(height) => Commitment::from_bytes(*self.header.commitment_bytes, network, height),
}
}

Expand Down
20 changes: 11 additions & 9 deletions zebra-chain/src/block/arbitrary.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
//! Randomised property testing for [`Block`]s.
use std::{collections::HashMap, sync::Arc};

use proptest::{
arbitrary::{any, Arbitrary},
prelude::*,
};

use std::{collections::HashMap, sync::Arc};

use crate::{
amount::NonNegative,
block,
fmt::SummaryDebug,
fmt::{HexDebug, SummaryDebug},
history_tree::HistoryTree,
parameters::{
Network,
Expand Down Expand Up @@ -482,13 +482,13 @@ impl Block {
// needs to be well-formed, i.e. smaller than 𝑞_J, so we
// arbitrarily set it to 1.
let block_header = Arc::make_mut(&mut block.header);
block_header.commitment_bytes = [0u8; 32];
block_header.commitment_bytes = [0u8; 32].into();
block_header.commitment_bytes[0] = 1;
}
std::cmp::Ordering::Equal => {
// The Heartwood activation block has a hardcoded all-zeroes commitment.
let block_header = Arc::make_mut(&mut block.header);
block_header.commitment_bytes = [0u8; 32];
block_header.commitment_bytes = [0u8; 32].into();
}
std::cmp::Ordering::Greater => {
// Set the correct commitment bytes according to the network upgrade.
Expand All @@ -505,10 +505,12 @@ impl Block {
&auth_data_root,
);
let block_header = Arc::make_mut(&mut block.header);
block_header.commitment_bytes = hash_block_commitments.into();
block_header.commitment_bytes =
hash_block_commitments.bytes_in_serialized_order().into();
} else {
let block_header = Arc::make_mut(&mut block.header);
block_header.commitment_bytes = history_tree_root.into();
block_header.commitment_bytes =
history_tree_root.bytes_in_serialized_order().into();
}
}
}
Expand Down Expand Up @@ -723,10 +725,10 @@ impl Arbitrary for Header {
(4u32..(i32::MAX as u32)),
any::<Hash>(),
any::<merkle::Root>(),
any::<[u8; 32]>(),
any::<HexDebug<[u8; 32]>>(),
serialization::arbitrary::datetime_u32(),
any::<CompactDifficulty>(),
any::<[u8; 32]>(),
any::<HexDebug<[u8; 32]>>(),
any::<equihash::Solution>(),
)
.prop_map(
Expand Down
48 changes: 46 additions & 2 deletions zebra-chain/src/block/commitment.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! The Commitment enum, used for the corresponding block header field.
use std::fmt;

use hex::{FromHex, ToHex};
use thiserror::Error;

Expand Down Expand Up @@ -97,6 +99,8 @@ pub(crate) const CHAIN_HISTORY_ACTIVATION_RESERVED: [u8; 32] = [0; 32];

impl Commitment {
/// Returns `bytes` as the Commitment variant for `network` and `height`.
//
// TODO: rename as from_bytes_in_serialized_order()
pub(super) fn from_bytes(
bytes: [u8; 32],
network: Network,
Expand Down Expand Up @@ -126,6 +130,8 @@ impl Commitment {
}

/// Returns the serialized bytes for this Commitment.
//
// TODO: refactor as bytes_in_serialized_order(&self)
#[cfg(test)]
pub(super) fn to_bytes(self) -> [u8; 32] {
use Commitment::*;
Expand All @@ -145,9 +151,23 @@ impl Commitment {
// - add methods for maintaining the MMR peaks, and calculating the root
// hash from the current set of peaks
// - move to a separate file
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub struct ChainHistoryMmrRootHash([u8; 32]);

impl fmt::Display for ChainHistoryMmrRootHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.encode_hex::<String>())
}
}

impl fmt::Debug for ChainHistoryMmrRootHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("ChainHistoryMmrRootHash")
.field(&self.encode_hex::<String>())
.finish()
}
}

impl From<[u8; 32]> for ChainHistoryMmrRootHash {
fn from(hash: [u8; 32]) -> Self {
ChainHistoryMmrRootHash(hash)
Expand Down Expand Up @@ -183,6 +203,11 @@ impl ChainHistoryMmrRootHash {

ChainHistoryMmrRootHash(internal_byte_order)
}

/// Returns the serialized bytes for this Commitment.
pub fn bytes_in_serialized_order(&self) -> [u8; 32] {
self.0
}
}

impl ToHex for &ChainHistoryMmrRootHash {
Expand Down Expand Up @@ -222,9 +247,23 @@ impl FromHex for ChainHistoryMmrRootHash {
/// - the transaction authorising data in this block.
///
/// Introduced in NU5.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub struct ChainHistoryBlockTxAuthCommitmentHash([u8; 32]);

impl fmt::Display for ChainHistoryBlockTxAuthCommitmentHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.encode_hex::<String>())
}
}

impl fmt::Debug for ChainHistoryBlockTxAuthCommitmentHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("ChainHistoryBlockTxAuthCommitmentHash")
.field(&self.encode_hex::<String>())
.finish()
}
}

impl From<[u8; 32]> for ChainHistoryBlockTxAuthCommitmentHash {
fn from(hash: [u8; 32]) -> Self {
ChainHistoryBlockTxAuthCommitmentHash(hash)
Expand Down Expand Up @@ -292,6 +331,11 @@ impl ChainHistoryBlockTxAuthCommitmentHash {

ChainHistoryBlockTxAuthCommitmentHash(internal_byte_order)
}

/// Returns the serialized bytes for this Commitment.
pub fn bytes_in_serialized_order(&self) -> [u8; 32] {
self.0
}
}

impl ToHex for &ChainHistoryBlockTxAuthCommitmentHash {
Expand Down
5 changes: 3 additions & 2 deletions zebra-chain/src/block/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use chrono::{DateTime, Duration, Utc};
use thiserror::Error;

use crate::{
fmt::HexDebug,
serialization::{TrustedPreallocate, MAX_PROTOCOL_MESSAGE_LEN},
work::{difficulty::CompactDifficulty, equihash::Solution},
};
Expand Down Expand Up @@ -58,7 +59,7 @@ pub struct Header {
/// this field cannot be parsed without the network and height. Use
/// [`Block::commitment`](super::Block::commitment) to get the parsed
/// [`Commitment`](super::Commitment).
pub commitment_bytes: [u8; 32],
pub commitment_bytes: HexDebug<[u8; 32]>,

/// The block timestamp is a Unix epoch time (UTC) when the miner
/// started hashing the header (according to the miner).
Expand All @@ -77,7 +78,7 @@ pub struct Header {
/// An arbitrary field that miners can change to modify the header
/// hash in order to produce a hash less than or equal to the
/// target threshold.
pub nonce: [u8; 32],
pub nonce: HexDebug<[u8; 32]>,

/// The Equihash solution.
pub solution: Solution,
Expand Down
7 changes: 3 additions & 4 deletions zebra-chain/src/block/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use chrono::{TimeZone, Utc};

use crate::{
block::{header::ZCASH_BLOCK_VERSION, merkle, Block, CountedHeader, Hash, Header},
serialization::{
CompactSizeMessage, ReadZcashExt, SerializationError, ZcashDeserialize,
ZcashDeserializeInto, ZcashSerialize,
},
work::{difficulty::CompactDifficulty, equihash},
};

use super::{header::ZCASH_BLOCK_VERSION, merkle, Block, CountedHeader, Hash, Header};

/// The maximum size of a Zcash block, in bytes.
///
/// Post-Sapling, this is also the maximum size of a transaction
Expand Down Expand Up @@ -85,7 +84,7 @@ impl ZcashDeserialize for Header {
version,
previous_block_hash: Hash::zcash_deserialize(&mut reader)?,
merkle_root: merkle::Root(reader.read_32_bytes()?),
commitment_bytes: reader.read_32_bytes()?,
commitment_bytes: reader.read_32_bytes()?.into(),
// This can't panic, because all u32 values are valid `Utc.timestamp`s
time: Utc
.timestamp_opt(reader.read_u32::<LittleEndian>()?.into(), 0)
Expand All @@ -94,7 +93,7 @@ impl ZcashDeserialize for Header {
"out-of-range number of seconds and/or invalid nanosecond",
))?,
difficulty_threshold: CompactDifficulty(reader.read_u32::<LittleEndian>()?),
nonce: reader.read_32_bytes()?,
nonce: reader.read_32_bytes()?.into(),
solution: equihash::Solution::zcash_deserialize(reader)?,
})
}
Expand Down
2 changes: 1 addition & 1 deletion zebra-chain/src/block/tests/prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ proptest! {
let commitment = block.commitment(network);
if let Ok(commitment) = commitment {
let commitment_bytes = commitment.to_bytes();
prop_assert_eq![block.header.commitment_bytes, commitment_bytes];
prop_assert_eq![block.header.commitment_bytes.0, commitment_bytes];
}

// Check the block size limit
Expand Down
35 changes: 35 additions & 0 deletions zebra-chain/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,38 @@ where

type Strategy = BoxedStrategy<Self>;
}

/// Wrapper to override `Debug`, redirecting it to hex-encode the type.
/// The type must be hex-encodable.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
#[serde(transparent)]
pub struct HexDebug<T: AsRef<[u8]>>(pub T);

impl<T: AsRef<[u8]>> fmt::Debug for HexDebug<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple(std::any::type_name::<T>())
.field(&hex::encode(self.as_ref()))
.finish()
}
}

impl<T: AsRef<[u8]>> ops::Deref for HexDebug<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T: AsRef<[u8]>> ops::DerefMut for HexDebug<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl<T: AsRef<[u8]>> From<T> for HexDebug<T> {
fn from(t: T) -> Self {
Self(t)
}
}
16 changes: 15 additions & 1 deletion zebra-chain/src/transaction/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,11 +992,25 @@ impl TrustedPreallocate for transparent::Output {
/// Stores bytes that are guaranteed to be deserializable into a [`Transaction`].
///
/// Sorts in lexicographic order of the transaction's serialized data.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct SerializedTransaction {
bytes: Vec<u8>,
}

impl fmt::Display for SerializedTransaction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&hex::encode(&self.bytes))
}
}

impl fmt::Debug for SerializedTransaction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("SerializedTransaction")
.field(&hex::encode(&self.bytes))
.finish()
}
}

/// Build a [`SerializedTransaction`] by serializing a block.
impl<B: Borrow<Transaction>> From<B> for SerializedTransaction {
fn from(tx: B) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion zebra-chain/src/work/equihash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Solution {

let input = &input[0..Solution::INPUT_LENGTH];

equihash::is_valid_solution(n, k, input, nonce, solution)?;
equihash::is_valid_solution(n, k, input, nonce.as_ref(), solution)?;

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions zebra-chain/src/work/tests/prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ prop_compose! {
fn randomized_nonce(real_header: block::Header)
(fake_nonce in proptest::array::uniform32(any::<u8>())
.prop_filter("nonce must not be the actual nonce", move |fake_nonce| {
fake_nonce != &real_header.nonce
fake_nonce != &real_header.nonce.0
})
) -> Arc<block::Header> {

let mut fake_header = real_header;
fake_header.nonce = fake_nonce;
fake_header.nonce = fake_nonce.into();

Arc::new(fake_header)
}
Expand Down
2 changes: 1 addition & 1 deletion zebra-consensus/src/block/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static INVALID_HEADER_SOLUTION_TRANSCRIPT: Lazy<
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..]).unwrap();

// Change nonce to something invalid
Arc::make_mut(&mut block.header).nonce = [0; 32];
Arc::make_mut(&mut block.header).nonce = [0; 32].into();

vec![(Arc::new(block), Err(ExpectedTranscriptError::Any))]
});
Expand Down
2 changes: 1 addition & 1 deletion zebra-state/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl FakeChainHelper for Arc<Block> {

fn set_block_commitment(mut self, block_commitment: [u8; 32]) -> Arc<Block> {
let block = Arc::make_mut(&mut self);
Arc::make_mut(&mut block.header).commitment_bytes = block_commitment;
Arc::make_mut(&mut block.header).commitment_bytes = block_commitment.into();
self
}
}
Expand Down

0 comments on commit cbed2c2

Please sign in to comment.