feature: Add light_client_root_hash(network) to Block
* use the right variant in LightClientRootHash::from_bytes() * make block.header.light_client_root_hash pub(super) * add tests for LightClientRootHash and block.light_client_root_hash
This commit is contained in:
parent
ee6f0de14d
commit
7afd76f5fb
|
|
@ -18,9 +18,11 @@ use proptest_derive::Arbitrary;
|
||||||
|
|
||||||
use crate::transaction::Transaction;
|
use crate::transaction::Transaction;
|
||||||
use crate::types::BlockHeight;
|
use crate::types::BlockHeight;
|
||||||
|
use crate::Network;
|
||||||
|
|
||||||
pub use hash::BlockHeaderHash;
|
pub use hash::BlockHeaderHash;
|
||||||
pub use header::BlockHeader;
|
pub use header::BlockHeader;
|
||||||
|
pub use light_client::LightClientRootHash;
|
||||||
|
|
||||||
/// A block in your blockchain.
|
/// A block in your blockchain.
|
||||||
///
|
///
|
||||||
|
|
@ -91,6 +93,23 @@ impl Block {
|
||||||
pub fn hash(&self) -> BlockHeaderHash {
|
pub fn hash(&self) -> BlockHeaderHash {
|
||||||
BlockHeaderHash::from(self)
|
BlockHeaderHash::from(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the parsed light client root hash for this block.
|
||||||
|
///
|
||||||
|
/// The interpretation of the light client root hash depends on the
|
||||||
|
/// configured `network`, and this block's height.
|
||||||
|
///
|
||||||
|
/// Returns None if this block does not have a block height.
|
||||||
|
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,
|
||||||
|
network,
|
||||||
|
height,
|
||||||
|
)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Block> for BlockHeaderHash {
|
impl<'a> From<&'a Block> for BlockHeaderHash {
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,9 @@ pub struct BlockHeader {
|
||||||
/// The light client root hash.
|
/// The light client root hash.
|
||||||
///
|
///
|
||||||
/// This field is interpreted differently, based on the current
|
/// This field is interpreted differently, based on the current
|
||||||
/// block height. See LightClientRootHash for details.
|
/// block height. Use `block.light_client_root_hash(network)` to get the
|
||||||
pub light_client_root_hash: [u8; 32],
|
/// parsed `LightClientRootHash` for this block.
|
||||||
|
pub(super) light_client_root_hash: [u8; 32],
|
||||||
|
|
||||||
/// 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).
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::note_commitment_tree::SaplingNoteTreeRootHash;
|
use crate::note_commitment_tree::SaplingNoteTreeRootHash;
|
||||||
use crate::types::BlockHeight;
|
use crate::types::BlockHeight;
|
||||||
use crate::Network;
|
use crate::{Network, NetworkUpgrade, NetworkUpgrade::*};
|
||||||
|
|
||||||
/// Light client root hashes.
|
/// Light client root hashes.
|
||||||
///
|
///
|
||||||
|
|
@ -50,12 +50,20 @@ impl LightClientRootHash {
|
||||||
network: Network,
|
network: Network,
|
||||||
height: BlockHeight,
|
height: BlockHeight,
|
||||||
) -> LightClientRootHash {
|
) -> LightClientRootHash {
|
||||||
// TODO(teor): use the correct network upgrade here, after moving the
|
use LightClientRootHash::*;
|
||||||
// network upgrades from zebra-consensus to zebra-chain.
|
|
||||||
LightClientRootHash::PreSaplingReserved(bytes)
|
match NetworkUpgrade::current(network, height) {
|
||||||
|
Genesis | BeforeOverwinter | Overwinter => PreSaplingReserved(bytes),
|
||||||
|
Sapling | Blossom => FinalSaplingRoot(SaplingNoteTreeRootHash(bytes)),
|
||||||
|
Heartwood if Some(height) == Heartwood.activation_height(network) => {
|
||||||
|
ChainHistoryActivationReserved(bytes)
|
||||||
|
}
|
||||||
|
Heartwood | Canopy => ChainHistoryRoot(ChainHistoryMmrRootHash(bytes)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the serialized bytes for this LightClientRootHash.
|
/// Returns the serialized bytes for this LightClientRootHash.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn to_bytes(self) -> [u8; 32] {
|
pub fn to_bytes(self) -> [u8; 32] {
|
||||||
use LightClientRootHash::*;
|
use LightClientRootHash::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,14 @@ proptest! {
|
||||||
|
|
||||||
prop_assert_eq![header, other_header];
|
prop_assert_eq![header, other_header];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn light_client_roundtrip(bytes in any::<[u8; 32]>(), network in any::<Network>(), block_height in any::<BlockHeight>()) {
|
||||||
|
let light_hash = LightClientRootHash::from_bytes(bytes, network, block_height);
|
||||||
|
let other_bytes = light_hash.to_bytes();
|
||||||
|
|
||||||
|
prop_assert_eq![bytes, other_bytes];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proptest! {
|
proptest! {
|
||||||
|
|
@ -239,12 +247,22 @@ proptest! {
|
||||||
.unwrap_or(16)))]
|
.unwrap_or(16)))]
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn block_roundtrip(block in any::<Block>()) {
|
fn block_roundtrip(block in any::<Block>(), network in any::<Network>()) {
|
||||||
let bytes = block.zcash_serialize_to_vec()?;
|
let bytes = block.zcash_serialize_to_vec()?;
|
||||||
let bytes = &mut bytes.as_slice();
|
let bytes = &mut bytes.as_slice();
|
||||||
|
|
||||||
|
// Check the light client root hash
|
||||||
|
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];
|
||||||
|
} else {
|
||||||
|
prop_assert_eq![block.coinbase_height(), None];
|
||||||
|
}
|
||||||
|
|
||||||
// Check the block size limit
|
// Check the block size limit
|
||||||
if bytes.len() <= MAX_BLOCK_BYTES as _ {
|
if bytes.len() <= MAX_BLOCK_BYTES as _ {
|
||||||
|
// Check deserialization
|
||||||
let other_block = bytes.zcash_deserialize_into()?;
|
let other_block = bytes.zcash_deserialize_into()?;
|
||||||
|
|
||||||
prop_assert_eq![block, other_block];
|
prop_assert_eq![block, other_block];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue