From 36093b472156be12fe5d64bd2a903691ba927434 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 11 Aug 2020 15:19:46 -0700 Subject: [PATCH] Tweak light client root hash definition. This changes the `light_client_root_hash` field to `light_client_root_bytes` to hint that it's unparsed, and makes it public to match the rest of the `BlockHeader` fields. The `LightClientRootHash` serialization methods are hidden from the public API, so that the `LightClientRootHash` has to be constructed by the method on the `Block`. --- zebra-chain/src/block.rs | 2 +- zebra-chain/src/block/header.rs | 10 ++++++---- zebra-chain/src/block/light_client.rs | 6 +++--- zebra-chain/src/block/serialize.rs | 4 ++-- zebra-chain/src/block/tests.rs | 10 +++++----- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index a21119d94..be5414681 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -103,7 +103,7 @@ impl Block { pub fn light_client_root_hash(&self, network: Network) -> Option { match self.coinbase_height() { Some(height) => Some(LightClientRootHash::from_bytes( - self.header.light_client_root_hash, + self.header.light_client_root_bytes, network, height, )), diff --git a/zebra-chain/src/block/header.rs b/zebra-chain/src/block/header.rs index 532714a06..c0b749e9a 100644 --- a/zebra-chain/src/block/header.rs +++ b/zebra-chain/src/block/header.rs @@ -36,10 +36,12 @@ pub struct BlockHeader { /// The light client root hash. /// - /// This field is interpreted differently, based on the current - /// block height. Use `block.light_client_root_hash(network)` to get the - /// parsed `LightClientRootHash` for this block. - pub(super) light_client_root_hash: [u8; 32], + /// Unfortunately, the interpretation of this field was changed without + /// incrementing the version, so it cannot be parsed without the block height + /// and network. Use + /// [`Block::light_client_root_hash`](super::Block::light_client_root_hash) + /// to get the parsed [`LightClientRootHash`](super::LightClientRootHash). + pub light_client_root_bytes: [u8; 32], /// 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/block/light_client.rs b/zebra-chain/src/block/light_client.rs index 41b1f99b7..f526917fc 100644 --- a/zebra-chain/src/block/light_client.rs +++ b/zebra-chain/src/block/light_client.rs @@ -6,7 +6,7 @@ use crate::{Network, NetworkUpgrade, NetworkUpgrade::*}; /// Light client root hashes. /// -/// The `BlockHeader.light_client_root_hash` field is interpreted differently, +/// The `BlockHeader.light_client_root_bytes` field is interpreted differently, /// based on the current block height. The interpretation changes at or after /// network upgrades. #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -45,7 +45,7 @@ pub enum LightClientRootHash { impl LightClientRootHash { /// Returns `bytes` as the LightClientRootHash variant for `network` and /// `height`. - pub fn from_bytes( + pub(super) fn from_bytes( bytes: [u8; 32], network: Network, height: BlockHeight, @@ -64,7 +64,7 @@ impl LightClientRootHash { /// Returns the serialized bytes for this LightClientRootHash. #[allow(dead_code)] - pub fn to_bytes(self) -> [u8; 32] { + pub(super) fn to_bytes(self) -> [u8; 32] { use LightClientRootHash::*; match self { diff --git a/zebra-chain/src/block/serialize.rs b/zebra-chain/src/block/serialize.rs index 23c7c28b4..1503533a6 100644 --- a/zebra-chain/src/block/serialize.rs +++ b/zebra-chain/src/block/serialize.rs @@ -18,7 +18,7 @@ impl ZcashSerialize for BlockHeader { writer.write_u32::(self.version)?; self.previous_block_hash.zcash_serialize(&mut writer)?; writer.write_all(&self.merkle_root_hash.0[..])?; - writer.write_all(&self.light_client_root_hash[..])?; + writer.write_all(&self.light_client_root_bytes[..])?; // this is a truncating cast, rather than a saturating cast // but u32 times are valid until 2106, and our block verification time // checks should detect any truncation. @@ -66,7 +66,7 @@ impl ZcashDeserialize for BlockHeader { version, previous_block_hash: BlockHeaderHash::zcash_deserialize(&mut reader)?, merkle_root_hash: MerkleTreeRootHash(reader.read_32_bytes()?), - light_client_root_hash: reader.read_32_bytes()?, + light_client_root_bytes: reader.read_32_bytes()?, // This can't panic, because all u32 values are valid `Utc.timestamp`s time: Utc.timestamp(reader.read_u32::()? as i64, 0), difficulty_threshold: CompactDifficulty(reader.read_u32::()?), diff --git a/zebra-chain/src/block/tests.rs b/zebra-chain/src/block/tests.rs index 333e55df9..584b739e0 100644 --- a/zebra-chain/src/block/tests.rs +++ b/zebra-chain/src/block/tests.rs @@ -25,8 +25,8 @@ impl Arbitrary for LightClientRootHash { fn arbitrary_with(_args: ()) -> Self::Strategy { (any::<[u8; 32]>(), any::(), any::()) - .prop_map(|(light_client_root_hash, network, block_height)| { - LightClientRootHash::from_bytes(light_client_root_hash, network, block_height) + .prop_map(|(light_client_root_bytes, network, block_height)| { + LightClientRootHash::from_bytes(light_client_root_bytes, network, block_height) }) .boxed() } @@ -55,7 +55,7 @@ impl Arbitrary for BlockHeader { version, previous_block_hash, merkle_root_hash, - light_client_root_hash, + light_client_root_bytes, timestamp, difficulty_threshold, nonce, @@ -64,7 +64,7 @@ impl Arbitrary for BlockHeader { version, previous_block_hash, merkle_root_hash, - light_client_root_hash, + light_client_root_bytes, time: Utc.timestamp(timestamp, 0), difficulty_threshold, nonce, @@ -255,7 +255,7 @@ proptest! { let light_hash = block.light_client_root_hash(network); if let Some(light_hash) = light_hash { let light_hash_bytes = light_hash.to_bytes(); - prop_assert_eq![block.header.light_client_root_hash, light_hash_bytes]; + prop_assert_eq![block.header.light_client_root_bytes, light_hash_bytes]; } else { prop_assert_eq![block.coinbase_height(), None]; }