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`.
This commit is contained in:
Henry de Valence 2020-08-11 15:19:46 -07:00 committed by Deirdre Connolly
parent aa922564b4
commit 36093b4721
5 changed files with 17 additions and 15 deletions

View File

@ -103,7 +103,7 @@ impl Block {
pub fn light_client_root_hash(&self, network: Network) -> Option<LightClientRootHash> {
match self.coinbase_height() {
Some(height) => Some(LightClientRootHash::from_bytes(
self.header.light_client_root_hash,
self.header.light_client_root_bytes,
network,
height,
)),

View File

@ -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).

View File

@ -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 {

View File

@ -18,7 +18,7 @@ impl ZcashSerialize for BlockHeader {
writer.write_u32::<LittleEndian>(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::<LittleEndian>()? as i64, 0),
difficulty_threshold: CompactDifficulty(reader.read_u32::<LittleEndian>()?),

View File

@ -25,8 +25,8 @@ impl Arbitrary for LightClientRootHash {
fn arbitrary_with(_args: ()) -> Self::Strategy {
(any::<[u8; 32]>(), any::<Network>(), any::<BlockHeight>())
.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];
}