Add final sapling root test vectors (#2243)
* Add sapling final root test vectors Also tidy some formatting and imports * Doc: final sapling roots can be duplicated * Reverse the byte order of final sapling root test vectors This makes the test vectors match the byte order in the block header, rather than the zcashd RPC responses. * Ignore pre-sapling block header commitments Previously, Zebra expected this reserved field to be all zeroes, but some mainnet and testnet blocks had other values. * Test structural and semantic validation of the block commitment field History roots are excluded from these tests, because they require contextual validation.
This commit is contained in:
parent
7b33278708
commit
c453fbf6f6
|
|
@ -8,7 +8,11 @@ use std::sync::Arc;
|
||||||
use crate::{
|
use crate::{
|
||||||
block,
|
block,
|
||||||
fmt::SummaryDebug,
|
fmt::SummaryDebug,
|
||||||
parameters::{Network, NetworkUpgrade, GENESIS_PREVIOUS_BLOCK_HASH},
|
parameters::{
|
||||||
|
Network,
|
||||||
|
NetworkUpgrade::{self, *},
|
||||||
|
GENESIS_PREVIOUS_BLOCK_HASH,
|
||||||
|
},
|
||||||
serialization,
|
serialization,
|
||||||
work::{difficulty::CompactDifficulty, equihash},
|
work::{difficulty::CompactDifficulty, equihash},
|
||||||
};
|
};
|
||||||
|
|
@ -171,11 +175,11 @@ impl Default for LedgerStateOverride {
|
||||||
let default_network = Network::default();
|
let default_network = Network::default();
|
||||||
|
|
||||||
// TODO: dynamically select any future network upgrade (#1974)
|
// TODO: dynamically select any future network upgrade (#1974)
|
||||||
let nu5_activation_height = NetworkUpgrade::Nu5.activation_height(default_network);
|
let nu5_activation_height = Nu5.activation_height(default_network);
|
||||||
let nu5_override = if nu5_activation_height.is_some() {
|
let nu5_override = if nu5_activation_height.is_some() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(NetworkUpgrade::Nu5)
|
Some(Nu5)
|
||||||
};
|
};
|
||||||
|
|
||||||
LedgerStateOverride {
|
LedgerStateOverride {
|
||||||
|
|
@ -205,11 +209,7 @@ impl Arbitrary for LedgerState {
|
||||||
)
|
)
|
||||||
.prop_map(move |(height, network, nu5_override, has_coinbase)| {
|
.prop_map(move |(height, network, nu5_override, has_coinbase)| {
|
||||||
// TODO: dynamically select any future network upgrade (#1974)
|
// TODO: dynamically select any future network upgrade (#1974)
|
||||||
let nu5_override = if nu5_override {
|
let nu5_override = if nu5_override { Some(Nu5) } else { None };
|
||||||
Some(NetworkUpgrade::Nu5)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
LedgerState {
|
LedgerState {
|
||||||
height: ledger_override.height_override.unwrap_or(height),
|
height: ledger_override.height_override.unwrap_or(height),
|
||||||
|
|
@ -280,15 +280,11 @@ impl Arbitrary for Commitment {
|
||||||
fn arbitrary_with(_args: ()) -> Self::Strategy {
|
fn arbitrary_with(_args: ()) -> Self::Strategy {
|
||||||
(any::<[u8; 32]>(), any::<Network>(), any::<Height>())
|
(any::<[u8; 32]>(), any::<Network>(), any::<Height>())
|
||||||
.prop_map(|(commitment_bytes, network, block_height)| {
|
.prop_map(|(commitment_bytes, network, block_height)| {
|
||||||
match Commitment::from_bytes(commitment_bytes, network, block_height) {
|
if block_height == Heartwood.activation_height(network).unwrap() {
|
||||||
Ok(commitment) => commitment,
|
Commitment::ChainHistoryActivationReserved
|
||||||
// just fix up the reserved values when they fail
|
} else {
|
||||||
Err(_) => Commitment::from_bytes(
|
Commitment::from_bytes(commitment_bytes, network, block_height)
|
||||||
super::commitment::RESERVED_BYTES,
|
.expect("unexpected failure in from_bytes parsing")
|
||||||
network,
|
|
||||||
block_height,
|
|
||||||
)
|
|
||||||
.expect("from_bytes only fails due to reserved bytes"),
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,10 @@ use super::super::block;
|
||||||
/// activation.
|
/// activation.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Commitment {
|
pub enum Commitment {
|
||||||
/// [Pre-Sapling] Reserved field.
|
/// [Pre-Sapling] "A reserved field, to be ignored."
|
||||||
///
|
///
|
||||||
/// The value of this field MUST be all zeroes.
|
/// This field is not verified.
|
||||||
///
|
PreSaplingReserved([u8; 32]),
|
||||||
/// This field is verified in `Commitment::from_bytes`.
|
|
||||||
PreSaplingReserved,
|
|
||||||
|
|
||||||
/// [Sapling and Blossom] The final Sapling treestate of this block.
|
/// [Sapling and Blossom] The final Sapling treestate of this block.
|
||||||
///
|
///
|
||||||
|
|
@ -93,7 +91,7 @@ pub enum Commitment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The required value of reserved `Commitment`s.
|
/// The required value of reserved `Commitment`s.
|
||||||
pub(crate) const RESERVED_BYTES: [u8; 32] = [0; 32];
|
pub(crate) const CHAIN_HISTORY_ACTIVATION_RESERVED: [u8; 32] = [0; 32];
|
||||||
|
|
||||||
impl Commitment {
|
impl Commitment {
|
||||||
/// Returns `bytes` as the Commitment variant for `network` and `height`.
|
/// Returns `bytes` as the Commitment variant for `network` and `height`.
|
||||||
|
|
@ -106,16 +104,10 @@ impl Commitment {
|
||||||
use CommitmentError::*;
|
use CommitmentError::*;
|
||||||
|
|
||||||
match NetworkUpgrade::current(network, height) {
|
match NetworkUpgrade::current(network, height) {
|
||||||
Genesis | BeforeOverwinter | Overwinter => {
|
Genesis | BeforeOverwinter | Overwinter => Ok(PreSaplingReserved(bytes)),
|
||||||
if bytes == RESERVED_BYTES {
|
|
||||||
Ok(PreSaplingReserved)
|
|
||||||
} else {
|
|
||||||
Err(InvalidPreSaplingReserved { actual: bytes })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Sapling | Blossom => Ok(FinalSaplingRoot(sapling::tree::Root(bytes))),
|
Sapling | Blossom => Ok(FinalSaplingRoot(sapling::tree::Root(bytes))),
|
||||||
Heartwood if Some(height) == Heartwood.activation_height(network) => {
|
Heartwood if Some(height) == Heartwood.activation_height(network) => {
|
||||||
if bytes == RESERVED_BYTES {
|
if bytes == CHAIN_HISTORY_ACTIVATION_RESERVED {
|
||||||
Ok(ChainHistoryActivationReserved)
|
Ok(ChainHistoryActivationReserved)
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidChainHistoryActivationReserved { actual: bytes })
|
Err(InvalidChainHistoryActivationReserved { actual: bytes })
|
||||||
|
|
@ -134,9 +126,9 @@ impl Commitment {
|
||||||
use Commitment::*;
|
use Commitment::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
PreSaplingReserved => RESERVED_BYTES,
|
PreSaplingReserved(bytes) => bytes,
|
||||||
FinalSaplingRoot(hash) => hash.0,
|
FinalSaplingRoot(hash) => hash.0,
|
||||||
ChainHistoryActivationReserved => RESERVED_BYTES,
|
ChainHistoryActivationReserved => CHAIN_HISTORY_ACTIVATION_RESERVED,
|
||||||
ChainHistoryRoot(hash) => hash.0,
|
ChainHistoryRoot(hash) => hash.0,
|
||||||
ChainHistoryBlockTxAuthCommitment(hash) => hash.0,
|
ChainHistoryBlockTxAuthCommitment(hash) => hash.0,
|
||||||
}
|
}
|
||||||
|
|
@ -174,15 +166,10 @@ pub struct ChainHistoryBlockTxAuthCommitmentHash([u8; 32]);
|
||||||
#[allow(dead_code, missing_docs)]
|
#[allow(dead_code, missing_docs)]
|
||||||
#[derive(Error, Debug, PartialEq)]
|
#[derive(Error, Debug, PartialEq)]
|
||||||
pub enum CommitmentError {
|
pub enum CommitmentError {
|
||||||
#[error("invalid pre-Sapling reserved committment: expected all zeroes, actual: {actual:?}")]
|
|
||||||
InvalidPreSaplingReserved {
|
|
||||||
// TODO: are these fields a security risk? If so, open a ticket to remove
|
|
||||||
// similar fields across Zebra
|
|
||||||
actual: [u8; 32],
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("invalid final sapling root: expected {expected:?}, actual: {actual:?}")]
|
#[error("invalid final sapling root: expected {expected:?}, actual: {actual:?}")]
|
||||||
InvalidFinalSaplingRoot {
|
InvalidFinalSaplingRoot {
|
||||||
|
// TODO: are these fields a security risk? If so, open a ticket to remove
|
||||||
|
// similar fields across Zebra
|
||||||
expected: [u8; 32],
|
expected: [u8; 32],
|
||||||
actual: [u8; 32],
|
actual: [u8; 32],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,22 @@
|
||||||
use std::collections::HashSet;
|
use std::{
|
||||||
use std::io::{Cursor, Write};
|
collections::HashSet,
|
||||||
|
io::{Cursor, Write},
|
||||||
|
};
|
||||||
|
|
||||||
use chrono::{DateTime, Duration, LocalResult, TimeZone, Utc};
|
use chrono::{DateTime, Duration, LocalResult, TimeZone, Utc};
|
||||||
|
|
||||||
use crate::serialization::{sha256d, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize};
|
use crate::{
|
||||||
use crate::transaction::LockTime;
|
block::{
|
||||||
|
serialize::MAX_BLOCK_BYTES, Block, BlockTimeError, Commitment::*, Hash, Header, Height,
|
||||||
|
},
|
||||||
|
parameters::{
|
||||||
|
Network::{self, *},
|
||||||
|
NetworkUpgrade::*,
|
||||||
|
},
|
||||||
|
serialization::{sha256d, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize},
|
||||||
|
transaction::LockTime,
|
||||||
|
};
|
||||||
|
|
||||||
use super::super::{serialize::MAX_BLOCK_BYTES, *};
|
|
||||||
use super::generate; // XXX this should be rewritten as strategies
|
use super::generate; // XXX this should be rewritten as strategies
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -129,20 +139,28 @@ fn block_test_vectors_unique() {
|
||||||
fn block_test_vectors_height_mainnet() {
|
fn block_test_vectors_height_mainnet() {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
block_test_vectors_height(Network::Mainnet);
|
block_test_vectors_height(Mainnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn block_test_vectors_height_testnet() {
|
fn block_test_vectors_height_testnet() {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
block_test_vectors_height(Network::Testnet);
|
block_test_vectors_height(Testnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test that the block test vector indexes match the heights in the block data,
|
||||||
|
/// and that each post-sapling block has a corresponding final sapling root.
|
||||||
fn block_test_vectors_height(network: Network) {
|
fn block_test_vectors_height(network: Network) {
|
||||||
let block_iter = match network {
|
let (block_iter, sapling_roots) = match network {
|
||||||
Network::Mainnet => zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
Mainnet => (
|
||||||
Network::Testnet => zebra_test::vectors::TESTNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
|
zebra_test::vectors::MAINNET_FINAL_SAPLING_ROOTS.clone(),
|
||||||
|
),
|
||||||
|
Testnet => (
|
||||||
|
zebra_test::vectors::TESTNET_BLOCKS.iter(),
|
||||||
|
zebra_test::vectors::TESTNET_FINAL_SAPLING_ROOTS.clone(),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
for (&height, block) in block_iter {
|
for (&height, block) in block_iter {
|
||||||
|
|
@ -154,6 +172,77 @@ fn block_test_vectors_height(network: Network) {
|
||||||
height,
|
height,
|
||||||
"deserialized height must match BTreeMap key height"
|
"deserialized height must match BTreeMap key height"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if height
|
||||||
|
>= Sapling
|
||||||
|
.activation_height(network)
|
||||||
|
.expect("sapling activation height is set")
|
||||||
|
.0
|
||||||
|
{
|
||||||
|
assert!(
|
||||||
|
sapling_roots.contains_key(&height),
|
||||||
|
"post-sapling block test vectors must have matching sapling root test vectors: missing {} {}",
|
||||||
|
network,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_commitment_mainnet() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
block_commitment(Mainnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_commitment_testnet() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
block_commitment(Testnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check that the block commitment field parses without errors.
|
||||||
|
/// For sapling and blossom blocks, also check the final sapling root value.
|
||||||
|
///
|
||||||
|
/// TODO: add chain history test vectors?
|
||||||
|
fn block_commitment(network: Network) {
|
||||||
|
let (block_iter, sapling_roots) = match network {
|
||||||
|
Mainnet => (
|
||||||
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
|
zebra_test::vectors::MAINNET_FINAL_SAPLING_ROOTS.clone(),
|
||||||
|
),
|
||||||
|
Testnet => (
|
||||||
|
zebra_test::vectors::TESTNET_BLOCKS.iter(),
|
||||||
|
zebra_test::vectors::TESTNET_FINAL_SAPLING_ROOTS.clone(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (height, block) in block_iter {
|
||||||
|
let block = block
|
||||||
|
.zcash_deserialize_into::<Block>()
|
||||||
|
.expect("block is structurally valid");
|
||||||
|
|
||||||
|
let commitment = block.commitment(network).unwrap_or_else(|_| {
|
||||||
|
panic!(
|
||||||
|
"unexpected structurally invalid block commitment at {} {}",
|
||||||
|
network, height
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
if let FinalSaplingRoot(final_sapling_root) = commitment {
|
||||||
|
let expected_final_sapling_root = *sapling_roots
|
||||||
|
.get(&height)
|
||||||
|
.expect("unexpected missing final sapling root test vector");
|
||||||
|
assert_eq!(
|
||||||
|
final_sapling_root,
|
||||||
|
expected_final_sapling_root.into(),
|
||||||
|
"unexpected invalid final sapling root commitment at {} {}",
|
||||||
|
network,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,18 @@ impl From<Root> for [u8; 32] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&[u8; 32]> for Root {
|
||||||
|
fn from(bytes: &[u8; 32]) -> Root {
|
||||||
|
(*bytes).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Root> for [u8; 32] {
|
||||||
|
fn from(root: &Root) -> Self {
|
||||||
|
(*root).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sapling Note Commitment Tree
|
/// Sapling Note Commitment Tree
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
struct NoteCommitmentTree {
|
struct NoteCommitmentTree {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,19 @@
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::{collections::BTreeMap, convert::TryInto};
|
||||||
|
|
||||||
|
trait ReverseCollection {
|
||||||
|
/// Return a reversed copy of this collection
|
||||||
|
fn rev(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReverseCollection for [u8; 32] {
|
||||||
|
fn rev(mut self) -> [u8; 32] {
|
||||||
|
self.reverse();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
||||||
|
|
@ -92,6 +104,36 @@ lazy_static! {
|
||||||
(1_180_900, BLOCK_MAINNET_1180900_BYTES.as_ref()),
|
(1_180_900, BLOCK_MAINNET_1180900_BYTES.as_ref()),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
|
||||||
|
/// Mainnet final sapling roots, indexed by height
|
||||||
|
///
|
||||||
|
/// Pre-sapling roots are all-zeroes.
|
||||||
|
/// If there are no sapling inputs or outputs in a block, the final sapling root is the same as the previous block.
|
||||||
|
pub static ref MAINNET_FINAL_SAPLING_ROOTS: BTreeMap<u32, &'static [u8; 32]> = [
|
||||||
|
// Sapling
|
||||||
|
(419_200, SAPLING_FINAL_ROOT_MAINNET_419200_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(419_201, SAPLING_FINAL_ROOT_MAINNET_419201_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// A bad version field
|
||||||
|
(434_873, SAPLING_FINAL_ROOT_MAINNET_434873_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(653_599, SAPLING_FINAL_ROOT_MAINNET_653599_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Blossom
|
||||||
|
(653_600, SAPLING_FINAL_ROOT_MAINNET_653600_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(653_601, SAPLING_FINAL_ROOT_MAINNET_653601_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(902_999, SAPLING_FINAL_ROOT_MAINNET_902999_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Heartwood
|
||||||
|
(903_000, SAPLING_FINAL_ROOT_MAINNET_903000_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(903_001, SAPLING_FINAL_ROOT_MAINNET_903001_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Shielded coinbase x3
|
||||||
|
(949_496, SAPLING_FINAL_ROOT_MAINNET_949496_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(975_066, SAPLING_FINAL_ROOT_MAINNET_975066_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(982_681, SAPLING_FINAL_ROOT_MAINNET_982681_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Last Heartwood
|
||||||
|
(1_046_399, SAPLING_FINAL_ROOT_MAINNET_1046399_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Canopy and First Coinbase Halving
|
||||||
|
(1_046_400, SAPLING_FINAL_ROOT_MAINNET_1046400_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_046_401, SAPLING_FINAL_ROOT_MAINNET_1046401_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_180_900, SAPLING_FINAL_ROOT_MAINNET_1180900_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
].iter().cloned().collect();
|
||||||
|
|
||||||
/// Testnet blocks, indexed by height
|
/// Testnet blocks, indexed by height
|
||||||
///
|
///
|
||||||
/// This is actually a bijective map, the tests ensure that values are unique.
|
/// This is actually a bijective map, the tests ensure that values are unique.
|
||||||
|
|
@ -153,6 +195,48 @@ lazy_static! {
|
||||||
(1_326_100, BLOCK_TESTNET_1326100_BYTES.as_ref()),
|
(1_326_100, BLOCK_TESTNET_1326100_BYTES.as_ref()),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
|
||||||
|
/// Testnet final sapling roots, indexed by height
|
||||||
|
///
|
||||||
|
/// Pre-sapling roots are all-zeroes.
|
||||||
|
/// If there are no sapling inputs or outputs in a block, the final sapling root is the same as the previous block.
|
||||||
|
pub static ref TESTNET_FINAL_SAPLING_ROOTS: BTreeMap<u32, &'static [u8; 32]> = [
|
||||||
|
// Sapling
|
||||||
|
(280_000, SAPLING_FINAL_ROOT_TESTNET_280000_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(280_001, SAPLING_FINAL_ROOT_TESTNET_280001_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(299_187, SAPLING_FINAL_ROOT_TESTNET_299187_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Minimum-difficulty blocks x2
|
||||||
|
// See zebra_chain's MINIMUM_DIFFICULTY_HEIGHTS for a full list
|
||||||
|
(299_188, SAPLING_FINAL_ROOT_TESTNET_299188_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(299_189, SAPLING_FINAL_ROOT_TESTNET_299189_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(299_201, SAPLING_FINAL_ROOT_TESTNET_299201_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Minimum-difficulty block
|
||||||
|
(299_202, SAPLING_FINAL_ROOT_TESTNET_299202_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(583_999, SAPLING_FINAL_ROOT_TESTNET_583999_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Blossom
|
||||||
|
(584_000, SAPLING_FINAL_ROOT_TESTNET_584000_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(584_001, SAPLING_FINAL_ROOT_TESTNET_584001_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(903_799, SAPLING_FINAL_ROOT_TESTNET_903799_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Heartwood
|
||||||
|
(903_800, SAPLING_FINAL_ROOT_TESTNET_903800_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(903_801, SAPLING_FINAL_ROOT_TESTNET_903801_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Shielded coinbase x2
|
||||||
|
(914_678, SAPLING_FINAL_ROOT_TESTNET_914678_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(925_483, SAPLING_FINAL_ROOT_TESTNET_925483_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_028_499, SAPLING_FINAL_ROOT_TESTNET_1028499_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Canopy
|
||||||
|
(1_028_500, SAPLING_FINAL_ROOT_TESTNET_1028500_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_028_501, SAPLING_FINAL_ROOT_TESTNET_1028501_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_095_000, SAPLING_FINAL_ROOT_TESTNET_1095000_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Shielded coinbase
|
||||||
|
(1_101_629, SAPLING_FINAL_ROOT_TESTNET_1101629_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// Last Pre-Halving
|
||||||
|
(1_115_999, SAPLING_FINAL_ROOT_TESTNET_1115999_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
// First Coinbase Halving
|
||||||
|
(1_116_000, SAPLING_FINAL_ROOT_TESTNET_1116000_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_116_001, SAPLING_FINAL_ROOT_TESTNET_1116001_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
(1_326_100, SAPLING_FINAL_ROOT_TESTNET_1326100_BYTES.as_ref().try_into().unwrap()),
|
||||||
|
].iter().cloned().collect();
|
||||||
|
|
||||||
// Mainnet
|
// Mainnet
|
||||||
|
|
||||||
// Genesis/BeforeOverwinter
|
// Genesis/BeforeOverwinter
|
||||||
|
|
@ -192,16 +276,16 @@ lazy_static! {
|
||||||
// zcash-cli getblock 10 0 > block-main-0-000-010.txt
|
// zcash-cli getblock 10 0 > block-main-0-000-010.txt
|
||||||
pub static ref BLOCK_MAINNET_10_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_10_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-000-010.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-000-010.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_202_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_202_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-000-202.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-000-202.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
|
||||||
/// This contains an encoding of block 202 but with an improperly encoded
|
/// This contains an encoding of block 202 but with an improperly encoded
|
||||||
/// coinbase height.
|
/// coinbase height.
|
||||||
pub static ref BAD_BLOCK_MAINNET_202_BYTES: Vec<u8> =
|
pub static ref BAD_BLOCK_MAINNET_202_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-000-202-bad.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-000-202-bad.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
|
||||||
// Overwinter transition
|
// Overwinter transition
|
||||||
// for i in 347499 347500 347501; do
|
// for i in 347499 347500 347501; do
|
||||||
|
|
@ -209,36 +293,56 @@ lazy_static! {
|
||||||
// done
|
// done
|
||||||
pub static ref BLOCK_MAINNET_347499_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_347499_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-347-499.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-347-499.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_347500_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_347500_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-347-500.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-347-500.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_347501_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_347501_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-347-501.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-347-501.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
// zcash-cli getblock 415000 0 > block-main-0-415-000.txt
|
// zcash-cli getblock 415000 0 > block-main-0-415-000.txt
|
||||||
pub static ref BLOCK_MAINNET_415000_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_415000_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-415-000.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-415-000.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
|
||||||
// Sapling transition
|
// Sapling transition
|
||||||
// for i in 419199 419200 419201; do
|
// for i in 419199 419200 419201; do
|
||||||
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
||||||
// done
|
// done
|
||||||
|
//
|
||||||
|
// zcashd provides final sapling roots in big-endian order, but Zebra stores
|
||||||
|
// that field in block order internally.
|
||||||
|
//
|
||||||
|
// for i in `cat post_sapling_mainnet_heights`; do
|
||||||
|
// zcash-cli z_gettreestate "$i" | \
|
||||||
|
// jq --arg i "$i" \
|
||||||
|
// --raw-output \
|
||||||
|
// '"pub static ref SAPLING_FINAL_ROOT_MAINNET_\($i)_BYTES: [u8; 32] = <[u8; 32]>::from_hex(\"\(.sapling.commitments.finalRoot)\").expect(\"final root bytes are in valid hex representation\").rev();"'
|
||||||
|
// done
|
||||||
pub static ref BLOCK_MAINNET_419199_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_419199_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-419-199.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-419-199.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_419200_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_419200_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-419-200.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-419-200.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_419201_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_419201_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-419-201.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-419-201.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_419200_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_419201_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("638d7e5ba37ab7921c51a4f3ae1b32d71c605a0ed9be7477928111a637f7421b")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// this one has a bad version field
|
// this one has a bad version field
|
||||||
// zcash-cli getblock 434873 0 > block-main-0-434-873.txt
|
// zcash-cli getblock 434873 0 > block-main-0-434-873.txt
|
||||||
pub static ref BLOCK_MAINNET_434873_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_434873_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-434-873.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-434-873.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_434873_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("56e33199bc41d146cb24d24a65db35101248a1d12fff33affef56f90081a9517")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Blossom transition
|
// Blossom transition
|
||||||
// for i in 653599 653600 653601; do
|
// for i in 653599 653600 653601; do
|
||||||
|
|
@ -246,29 +350,48 @@ lazy_static! {
|
||||||
// done
|
// done
|
||||||
pub static ref BLOCK_MAINNET_653599_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_653599_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-653-599.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-653-599.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_653600_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_653600_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-653-600.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-653-600.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_653601_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_653601_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-653-601.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-653-601.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_653599_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("3d532d101b9171769423a9f45a65b6312e28e7aa92b627cb81810f7a6fe21c6a")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_653600_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("3d532d101b9171769423a9f45a65b6312e28e7aa92b627cb81810f7a6fe21c6a")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_653601_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("612c62e54ef55f7bf8a60281debf1df904bf1fa6d1fa65d9656302b44ea98427")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Heartwood transition
|
// Heartwood transition
|
||||||
// i=902999
|
// i=902999
|
||||||
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
||||||
pub static ref BLOCK_MAINNET_902999_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_902999_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-902-999.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-902-999.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
// for i in 903000 903001; do
|
// for i in 903000 903001; do
|
||||||
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-00$[i%1000].txt
|
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-00$[i%1000].txt
|
||||||
// done
|
// done
|
||||||
pub static ref BLOCK_MAINNET_903000_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_903000_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-903-000.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-903-000.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_903001_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_903001_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-903-001.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-903-001.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_902999_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("49df1a6e62458b0226b9d6c0c28fb7e94d9ca840582878b10d0117fd028b4e91")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_903000_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("11e48300f0e2296d5c413340b26426eddada1155155f4e959ebe307396976c79")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_903001_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("14e3c2b8af239bc4e17486573c20824292d5e1a6670dedf58bf865159e389cce")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Shielded coinbase
|
// Shielded coinbase
|
||||||
// for i in 949496 982681; do
|
// for i in 949496 982681; do
|
||||||
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
||||||
|
|
@ -278,7 +401,7 @@ lazy_static! {
|
||||||
// First shielded coinbase block
|
// First shielded coinbase block
|
||||||
pub static ref BLOCK_MAINNET_949496_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_949496_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-949-496.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-949-496.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
// Largest shielded coinbase block so far (in bytes)
|
// Largest shielded coinbase block so far (in bytes)
|
||||||
pub static ref BLOCK_MAINNET_975066_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_975066_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-975-066.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-975-066.txt").trim())
|
||||||
|
|
@ -287,6 +410,15 @@ lazy_static! {
|
||||||
pub static ref BLOCK_MAINNET_982681_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_982681_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-0-982-681.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-0-982-681.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_949496_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("4db238913a86284f5bddb9bcfe76f96a46d097ec681aad1da846cc276bfa7263")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_975066_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("2f62381b6decd0e0f937f6aa23faa7d19444b784701be93ad7e4df31bd4da1f9")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_982681_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("4fd1cb6d1e5c479baa44fcb7c3a1c6fafdaa54c0456d254918cd63839805848d")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Canopy transition and Coinbase Halving
|
// Canopy transition and Coinbase Halving
|
||||||
// (On mainnet, Canopy happens at the same block as the first coinbase halving)
|
// (On mainnet, Canopy happens at the same block as the first coinbase halving)
|
||||||
|
|
@ -295,14 +427,25 @@ lazy_static! {
|
||||||
// done
|
// done
|
||||||
pub static ref BLOCK_MAINNET_1046399_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_1046399_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-1-046-399.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-1-046-399.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
pub static ref BLOCK_MAINNET_1046400_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_1046400_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-1-046-400.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-1-046-400.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
// Block 1046401 is 72 kB in size (currently the second-largest test vector), so we store it in binary.
|
// Block 1046401 is 72 kB in size (currently the second-largest test vector), so we store it in binary.
|
||||||
// i=1046401
|
// i=1046401
|
||||||
// zcash-cli getblock $i 0 | xxd -revert -plain > block-main-$[i/1000000]-0$[i/1000%1000]-$[i%1000].bin
|
// zcash-cli getblock $i 0 | xxd -revert -plain > block-main-$[i/1000000]-0$[i/1000%1000]-$[i%1000].bin
|
||||||
pub static ref BLOCK_MAINNET_1046401_BYTES: Vec<u8> = include_bytes!("block-main-1-046-401.bin").to_vec();
|
pub static ref BLOCK_MAINNET_1046401_BYTES: Vec<u8> =
|
||||||
|
include_bytes!("block-main-1-046-401.bin")
|
||||||
|
.to_vec();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_1046399_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("0f12c92f737e84142792bddc82e36481de4a7679d5778a27389793933c8742e1")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_1046400_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("0f12c92f737e84142792bddc82e36481de4a7679d5778a27389793933c8742e1")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_1046401_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("1cb7a61a31354384957eea0b98661e1cf85a5de8e43f0e3bef522c8b375b26cb")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// One more Canopy/Post-Halving block
|
// One more Canopy/Post-Halving block
|
||||||
// (so that we have at least 3 blocks after canopy/halving)
|
// (so that we have at least 3 blocks after canopy/halving)
|
||||||
|
|
@ -310,7 +453,10 @@ lazy_static! {
|
||||||
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
// zcash-cli getblock $i 0 > block-main-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
||||||
pub static ref BLOCK_MAINNET_1180900_BYTES: Vec<u8> =
|
pub static ref BLOCK_MAINNET_1180900_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-main-1-180-900.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-main-1-180-900.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_MAINNET_1180900_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("4a51c1b879f49637873ac4b261e9c625e16d9400b22d8aa4f27cd6fd1138ddda")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Testnet
|
// Testnet
|
||||||
|
|
||||||
|
|
@ -385,6 +531,13 @@ lazy_static! {
|
||||||
// for i in 280000 280001; do
|
// for i in 280000 280001; do
|
||||||
// zcash-cli -testnet getblock $i 0 > block-test-$[i/1000000]-$[i/1000%1000]-00$[i%1000].txt
|
// zcash-cli -testnet getblock $i 0 > block-test-$[i/1000000]-$[i/1000%1000]-00$[i%1000].txt
|
||||||
// done
|
// done
|
||||||
|
//
|
||||||
|
// for i in `cat post_sapling_testnet_heights`; do
|
||||||
|
// zcash-cli -testnet z_gettreestate "$i" | \
|
||||||
|
// jq --arg i "$i" \
|
||||||
|
// --raw-output \
|
||||||
|
// '"pub static ref SAPLING_FINAL_ROOT_TESTNET_\($i)_BYTES: [u8; 32] = <[u8; 32]>::from_hex(\"\(.sapling.commitments.finalRoot)\").expect(\"final root bytes are in valid hex representation\").rev();"'
|
||||||
|
// done
|
||||||
pub static ref BLOCK_TESTNET_279999_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_279999_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-0-279-999.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-0-279-999.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
|
@ -394,6 +547,12 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_280001_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_280001_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-0-280-001.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-0-280-001.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_280000_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_280001_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// The first minimum difficulty blocks 299188, 299189, 299202 and their previous blocks for context
|
// The first minimum difficulty blocks 299188, 299189, 299202 and their previous blocks for context
|
||||||
// (pre-Blossom minimum difficulty)
|
// (pre-Blossom minimum difficulty)
|
||||||
|
|
@ -416,6 +575,21 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_299202_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_299202_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-0-299-202.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-0-299-202.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_299187_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("6815df99f9f7ec9486a0b3a4e992ff9348dba7101c2ac91be41ceab392aa5521")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_299188_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("6815df99f9f7ec9486a0b3a4e992ff9348dba7101c2ac91be41ceab392aa5521")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_299189_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("6815df99f9f7ec9486a0b3a4e992ff9348dba7101c2ac91be41ceab392aa5521")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_299201_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("6815df99f9f7ec9486a0b3a4e992ff9348dba7101c2ac91be41ceab392aa5521")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_299202_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("6815df99f9f7ec9486a0b3a4e992ff9348dba7101c2ac91be41ceab392aa5521")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Blossom transition
|
// Blossom transition
|
||||||
// i=583999
|
// i=583999
|
||||||
|
|
@ -433,6 +607,15 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_584001_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_584001_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-0-584-001.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-0-584-001.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_583999_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("13746c0c426cdddd05f85d86231f8bc647f5b024277c606c309ef707d85fd652")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_584000_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("13746c0c426cdddd05f85d86231f8bc647f5b024277c606c309ef707d85fd652")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_584001_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("13746c0c426cdddd05f85d86231f8bc647f5b024277c606c309ef707d85fd652")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Heartwood transition
|
// Heartwood transition
|
||||||
// for i in 903799 903800 903801; do
|
// for i in 903799 903800 903801; do
|
||||||
|
|
@ -447,6 +630,16 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_903801_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_903801_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-0-903-801.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-0-903-801.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_903799_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("626444395cd5963d3dba2652ee5bd73ef57555cca4d9f0d52e887a3bf44488e2")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_903800_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("626444395cd5963d3dba2652ee5bd73ef57555cca4d9f0d52e887a3bf44488e2")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_903801_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("626444395cd5963d3dba2652ee5bd73ef57555cca4d9f0d52e887a3bf44488e2")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Shielded coinbase
|
// Shielded coinbase
|
||||||
// for i in 914678 925483; do
|
// for i in 914678 925483; do
|
||||||
// zcash-cli -testnet getblock $i 0 > block-test-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
// zcash-cli -testnet getblock $i 0 > block-test-$[i/1000000]-$[i/1000%1000]-$[i%1000].txt
|
||||||
|
|
@ -459,6 +652,12 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_925483_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_925483_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-0-925-483.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-0-925-483.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_914678_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("0ba286a3fb00d8a63b6ea52064bcc58ffb859aaa881745157d9a67d20afd7a8d")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_925483_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("271370ff86c2a9cc452334098d3337cddffc478e66a356dc0c00aebb58a4b6ac")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Canopy transition
|
// Canopy transition
|
||||||
// for i in 1028499 1028500 1028501; do
|
// for i in 1028499 1028500 1028501; do
|
||||||
|
|
@ -473,6 +672,16 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_1028501_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_1028501_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-1-028-501.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-1-028-501.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1028499_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("580adc0253cd0545250039267b7b49445ca0550df735920b7466bba1a64f7cf7")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1028500_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("580adc0253cd0545250039267b7b49445ca0550df735920b7466bba1a64f7cf7")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1028501_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("580adc0253cd0545250039267b7b49445ca0550df735920b7466bba1a64f7cf7")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// One more Canopy block
|
// One more Canopy block
|
||||||
// (so that we have at least 3 blocks from Canopy)
|
// (so that we have at least 3 blocks from Canopy)
|
||||||
// i=1095000
|
// i=1095000
|
||||||
|
|
@ -480,6 +689,10 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_1095000_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_1095000_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-1-095-000.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-1-095-000.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1095000_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("1781d73666ceb7675323130defd5fae426f1ee7d5fbb83adc9393aa8ff7e8a8d")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Shielded coinbase + Canopy
|
// Shielded coinbase + Canopy
|
||||||
// i=1101629
|
// i=1101629
|
||||||
// zcash-cli -testnet getblock $i 0 > block-test-$[i/1000000]-0$[i/1000%1000]-$[i%1000].txt
|
// zcash-cli -testnet getblock $i 0 > block-test-$[i/1000000]-0$[i/1000%1000]-$[i%1000].txt
|
||||||
|
|
@ -487,6 +700,9 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_1101629_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_1101629_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-1-101-629.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-1-101-629.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1101629_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("14c7c827cd05c73c052c2a9faa6d7fc7b45ec2e386d8894eb65c420175c43745")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// Testnet Coinbase Halving
|
// Testnet Coinbase Halving
|
||||||
// i=1115999
|
// i=1115999
|
||||||
|
|
@ -503,6 +719,15 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_1116001_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_1116001_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-1-116-001.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-1-116-001.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1115999_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("14b41a6dd7cd3c113d98f72543c4f57ff4e444bd5995366e0da420169c861f37")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1116000_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("14b41a6dd7cd3c113d98f72543c4f57ff4e444bd5995366e0da420169c861f37")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1116001_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("14b41a6dd7cd3c113d98f72543c4f57ff4e444bd5995366e0da420169c861f37")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
|
|
||||||
// One more Post-Halving block
|
// One more Post-Halving block
|
||||||
// (so that we have at least 3 blocks after the halving)
|
// (so that we have at least 3 blocks after the halving)
|
||||||
|
|
@ -511,6 +736,9 @@ lazy_static! {
|
||||||
pub static ref BLOCK_TESTNET_1326100_BYTES: Vec<u8> =
|
pub static ref BLOCK_TESTNET_1326100_BYTES: Vec<u8> =
|
||||||
<Vec<u8>>::from_hex(include_str!("block-test-1-326-100.txt").trim())
|
<Vec<u8>>::from_hex(include_str!("block-test-1-326-100.txt").trim())
|
||||||
.expect("Block bytes are in valid hex representation");
|
.expect("Block bytes are in valid hex representation");
|
||||||
|
pub static ref SAPLING_FINAL_ROOT_TESTNET_1326100_BYTES: [u8; 32] =
|
||||||
|
<[u8; 32]>::from_hex("2b30b19f4254709fe365bd0b381b2e3d9d0c933eb4dba4dd1d07f0f6e196a183")
|
||||||
|
.expect("final root bytes are in valid hex representation").rev();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -534,6 +762,8 @@ mod test {
|
||||||
block_set.len(),
|
block_set.len(),
|
||||||
"block test vectors must be unique"
|
"block test vectors must be unique"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// final sapling roots can be duplicated if a block has no sapling spends or outputs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make sure we use all the test vectors in the lists.
|
/// Make sure we use all the test vectors in the lists.
|
||||||
|
|
@ -544,8 +774,23 @@ mod test {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
BLOCKS.len() > 50,
|
MAINNET_BLOCKS.len() > 30,
|
||||||
"there should be a reasonable number of block test vectors"
|
"there should be a reasonable number of mainnet block test vectors"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
TESTNET_BLOCKS.len() > 30,
|
||||||
|
"there should be a reasonable number of testnet block test vectors"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
MAINNET_FINAL_SAPLING_ROOTS.len() > 10,
|
||||||
|
"there should be a reasonable number of mainnet final sapling root test vectors"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
TESTNET_FINAL_SAPLING_ROOTS.len() > 10,
|
||||||
|
"there should be a reasonable number of testnet final sapling root test vectors"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue