add(consensus): Add `activation_heights` field to `NetworkParameters` and implement `Parameters` for `Network` (#8383)
* minor cleanup and rename * Adds an empty NetworkParameters struct to Network::Testnet variant, updates production code. * Updates tests * Adds `NetworkKind` and uses it instead of `Network` in `HistoryTreeParts` and `transparent::Address` * Adds a [network.testnet_parameters] section to the config, uses `NetworkKind` as zebra_network::Config::network field type, and converts 'Network' to `NetworkKind` before serializing * Applies some suggestions from code review * Applies suggestions from code review * returns b58 prefix constants directly to remove From<NetworkKind> impl for zcash_primitives::consensus::Network * Applies more suggestions from code review. * moves conversions to zcash_primitives::consensus::Network to where they're used. * Apply suggestions from code review Co-authored-by: Marek <mail@marek.onl> * rename `network` variables and method names typed as NetworkKind to `network_kind` * use only test block heights for the network associated with them * Applies more suggestions from code review. * Rename `NetworkParameters` to `Parameters` and move it a new `testnet` module * adds activation heights field * updates stored test config, adds a quicker test for checking that stored configs can be parsed, adds an intermediate representation of activation heights * implement Parameters for Network * Passes &Network directly instead of converting to zp_consensus::Network where there were conversions * fixes a bad merge (removes a network conversion in zcash_note_encryption) * Adds a test for the Parameters impl for zebra_chain::Network * fixes doc links * - Makes the `activation_heights` config field optional by adding a #[serde(default)] - Panics if a non-zero activation height is provided for the `Genesis` network upgrade - Always sets the `Genesis` and `BeforeOverwinter` network upgrade activation heights to 0 and 1, `BeforeOverwinter` could be overwritten by a later network upgrade - Makes the `activation_heights` field on `Parameters` private, adds/uses an accessor method instead, and adds a builder struct and `build()` method * small refactor of activation_heights() method * check that activation heights are in the right order * Updates `NetworkUpgrade::activation_height()` to return the height of the next NetworkUpgrade if it doesn't find the activation height of `&self` * checks that the miner address is of TestnetKind on Regtest and update assertion message * Adds a DNetworkUpgradeActivationHeights struct for better control over how activation heights can be configured * moves all ordered network upgrades to a constant, adds a no_duplicates test, moves struct with activation heights outside deserialization impl and accepts it in `ParametersBuilder::activation_heights()` instead of a Vec * panics if any network upgrades are configured to activate at Height(0) because it's reserved for Genesis * Simplifies the `ParametersBuilder::activation_heights()` method and removes an unnecessary test. * Adds Sapling HRPs as fields on testnet params. (#8398) * Applies suggestions from code review. * Update zebra-chain/src/parameters/network_upgrade.rs Co-authored-by: Marek <mail@marek.onl> --------- Co-authored-by: Marek <mail@marek.onl>
This commit is contained in:
parent
887d4a2457
commit
f8c153991b
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
|
||||||
use super::NetworkUpgrade;
|
use super::{Network, NetworkUpgrade};
|
||||||
|
|
||||||
impl NetworkUpgrade {
|
impl NetworkUpgrade {
|
||||||
/// Generates network upgrades.
|
/// Generates network upgrades.
|
||||||
|
|
@ -32,3 +32,13 @@ impl NetworkUpgrade {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Arbitrary for Network {
|
||||||
|
type Parameters = ();
|
||||||
|
|
||||||
|
fn arbitrary_with(_args: ()) -> Self::Strategy {
|
||||||
|
prop_oneof![Just(Self::Mainnet), Just(Self::new_default_testnet())].boxed()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Strategy = BoxedStrategy<Self>;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,15 @@ use std::{fmt, str::FromStr, sync::Arc};
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use zcash_primitives::constants;
|
use zcash_primitives::{consensus as zp_consensus, constants as zp_constants};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
block::{self, Height, HeightDiff},
|
block::{self, Height, HeightDiff},
|
||||||
parameters::NetworkUpgrade::Canopy,
|
parameters::NetworkUpgrade,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod testnet;
|
pub mod testnet;
|
||||||
|
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
|
||||||
use proptest_derive::Arbitrary;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
|
@ -81,7 +78,6 @@ impl From<Network> for NetworkKind {
|
||||||
|
|
||||||
/// An enum describing the possible network choices.
|
/// An enum describing the possible network choices.
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize)]
|
||||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
|
||||||
#[serde(into = "NetworkKind")]
|
#[serde(into = "NetworkKind")]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
/// The production mainnet.
|
/// The production mainnet.
|
||||||
|
|
@ -98,8 +94,8 @@ impl NetworkKind {
|
||||||
/// pay-to-public-key-hash payment addresses for the network.
|
/// pay-to-public-key-hash payment addresses for the network.
|
||||||
pub fn b58_pubkey_address_prefix(self) -> [u8; 2] {
|
pub fn b58_pubkey_address_prefix(self) -> [u8; 2] {
|
||||||
match self {
|
match self {
|
||||||
Self::Mainnet => constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
|
Self::Mainnet => zp_constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||||
Self::Testnet | Self::Regtest => constants::testnet::B58_PUBKEY_ADDRESS_PREFIX,
|
Self::Testnet | Self::Regtest => zp_constants::testnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,8 +103,8 @@ impl NetworkKind {
|
||||||
/// payment addresses for the network.
|
/// payment addresses for the network.
|
||||||
pub fn b58_script_address_prefix(self) -> [u8; 2] {
|
pub fn b58_script_address_prefix(self) -> [u8; 2] {
|
||||||
match self {
|
match self {
|
||||||
Self::Mainnet => constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
|
Self::Mainnet => zp_constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||||
Self::Testnet | Self::Regtest => constants::testnet::B58_SCRIPT_ADDRESS_PREFIX,
|
Self::Testnet | Self::Regtest => zp_constants::testnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,7 +227,7 @@ impl Network {
|
||||||
//
|
//
|
||||||
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
||||||
|
|
||||||
let canopy_activation = Canopy
|
let canopy_activation = NetworkUpgrade::Canopy
|
||||||
.activation_height(self)
|
.activation_height(self)
|
||||||
.expect("Canopy activation height must be present for both networks");
|
.expect("Canopy activation height must be present for both networks");
|
||||||
|
|
||||||
|
|
@ -279,3 +275,70 @@ impl FromStr for Network {
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
#[error("Invalid network: {0}")]
|
#[error("Invalid network: {0}")]
|
||||||
pub struct InvalidNetworkError(String);
|
pub struct InvalidNetworkError(String);
|
||||||
|
|
||||||
|
impl zp_consensus::Parameters for Network {
|
||||||
|
fn activation_height(
|
||||||
|
&self,
|
||||||
|
nu: zcash_primitives::consensus::NetworkUpgrade,
|
||||||
|
) -> Option<zcash_primitives::consensus::BlockHeight> {
|
||||||
|
let target_nu = match nu {
|
||||||
|
zp_consensus::NetworkUpgrade::Overwinter => NetworkUpgrade::Overwinter,
|
||||||
|
zp_consensus::NetworkUpgrade::Sapling => NetworkUpgrade::Sapling,
|
||||||
|
zp_consensus::NetworkUpgrade::Blossom => NetworkUpgrade::Blossom,
|
||||||
|
zp_consensus::NetworkUpgrade::Heartwood => NetworkUpgrade::Heartwood,
|
||||||
|
zp_consensus::NetworkUpgrade::Canopy => NetworkUpgrade::Canopy,
|
||||||
|
zp_consensus::NetworkUpgrade::Nu5 => NetworkUpgrade::Nu5,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Heights are hard-coded below Height::MAX or checked when the config is parsed.
|
||||||
|
target_nu
|
||||||
|
.activation_height(self)
|
||||||
|
.map(|Height(h)| zp_consensus::BlockHeight::from_u32(h))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coin_type(&self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Network::Mainnet => zp_constants::mainnet::COIN_TYPE,
|
||||||
|
// The regtest cointype reuses the testnet cointype,
|
||||||
|
// See <https://github.com/satoshilabs/slips/blob/master/slip-0044.md>
|
||||||
|
Network::Testnet(_) => zp_constants::testnet::COIN_TYPE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn address_network(&self) -> Option<zcash_address::Network> {
|
||||||
|
match self {
|
||||||
|
Network::Mainnet => Some(zcash_address::Network::Main),
|
||||||
|
// TODO: Check if network is `Regtest` first, and if it is, return `zcash_address::Network::Regtest`
|
||||||
|
Network::Testnet(_params) => Some(zcash_address::Network::Test),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hrp_sapling_extended_spending_key(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Network::Mainnet => zp_constants::mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||||
|
Network::Testnet(params) => params.hrp_sapling_extended_spending_key(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hrp_sapling_extended_full_viewing_key(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Network::Mainnet => zp_constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||||
|
Network::Testnet(params) => params.hrp_sapling_extended_full_viewing_key(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hrp_sapling_payment_address(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Network::Mainnet => zp_constants::mainnet::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||||
|
Network::Testnet(params) => params.hrp_sapling_payment_address(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b58_pubkey_address_prefix(&self) -> [u8; 2] {
|
||||||
|
self.kind().b58_pubkey_address_prefix()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b58_script_address_prefix(&self) -> [u8; 2] {
|
||||||
|
self.kind().b58_script_address_prefix()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,220 @@
|
||||||
//! Types and implementation for Testnet consensus parameters
|
//! Types and implementation for Testnet consensus parameters
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
use zcash_primitives::constants as zp_constants;
|
||||||
use proptest_derive::Arbitrary;
|
|
||||||
|
use crate::{
|
||||||
|
block::Height,
|
||||||
|
parameters::{
|
||||||
|
network_upgrade::TESTNET_ACTIVATION_HEIGHTS, Network, NetworkUpgrade,
|
||||||
|
NETWORK_UPGRADES_IN_ORDER,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Configurable activation heights for Regtest and configured Testnets.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct ConfiguredActivationHeights {
|
||||||
|
/// Activation height for `BeforeOverwinter` network upgrade.
|
||||||
|
pub before_overwinter: Option<u32>,
|
||||||
|
/// Activation height for `Overwinter` network upgrade.
|
||||||
|
pub overwinter: Option<u32>,
|
||||||
|
/// Activation height for `Sapling` network upgrade.
|
||||||
|
pub sapling: Option<u32>,
|
||||||
|
/// Activation height for `Blossom` network upgrade.
|
||||||
|
pub blossom: Option<u32>,
|
||||||
|
/// Activation height for `Heartwood` network upgrade.
|
||||||
|
pub heartwood: Option<u32>,
|
||||||
|
/// Activation height for `Canopy` network upgrade.
|
||||||
|
pub canopy: Option<u32>,
|
||||||
|
/// Activation height for `NU5` network upgrade.
|
||||||
|
#[serde(rename = "NU5")]
|
||||||
|
pub nu5: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder for the [`Parameters`] struct.
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
|
pub struct ParametersBuilder {
|
||||||
|
/// The network upgrade activation heights for this network, see [`Parameters::activation_heights`] for more details.
|
||||||
|
activation_heights: BTreeMap<Height, NetworkUpgrade>,
|
||||||
|
/// Sapling extended spending key human-readable prefix for this network
|
||||||
|
hrp_sapling_extended_spending_key: String,
|
||||||
|
/// Sapling extended full viewing key human-readable prefix for this network
|
||||||
|
hrp_sapling_extended_full_viewing_key: String,
|
||||||
|
/// Sapling payment address human-readable prefix for this network
|
||||||
|
hrp_sapling_payment_address: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ParametersBuilder {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
// # Correctness
|
||||||
|
//
|
||||||
|
// `Genesis` network upgrade activation height must always be 0
|
||||||
|
activation_heights: [
|
||||||
|
(Height(0), NetworkUpgrade::Genesis),
|
||||||
|
// TODO: Find out if `BeforeOverwinter` must always be active at Height(1), remove it here if it's not required.
|
||||||
|
(Height(1), NetworkUpgrade::BeforeOverwinter),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
hrp_sapling_extended_spending_key:
|
||||||
|
zp_constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY.to_string(),
|
||||||
|
hrp_sapling_extended_full_viewing_key:
|
||||||
|
zp_constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY.to_string(),
|
||||||
|
hrp_sapling_payment_address: zp_constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS
|
||||||
|
.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParametersBuilder {
|
||||||
|
/// Checks that the provided network upgrade activation heights are in the correct order, then
|
||||||
|
/// sets them as the new network upgrade activation heights.
|
||||||
|
pub fn activation_heights(
|
||||||
|
mut self,
|
||||||
|
ConfiguredActivationHeights {
|
||||||
|
// TODO: Find out if `BeforeOverwinter` is required at Height(1), allow for
|
||||||
|
// configuring its activation height if it's not required to be at Height(1)
|
||||||
|
before_overwinter: _,
|
||||||
|
overwinter,
|
||||||
|
sapling,
|
||||||
|
blossom,
|
||||||
|
heartwood,
|
||||||
|
canopy,
|
||||||
|
nu5,
|
||||||
|
}: ConfiguredActivationHeights,
|
||||||
|
) -> Self {
|
||||||
|
use NetworkUpgrade::*;
|
||||||
|
|
||||||
|
// # Correctness
|
||||||
|
//
|
||||||
|
// These must be in order so that later network upgrades overwrite prior ones
|
||||||
|
// if multiple network upgrades are configured with the same activation height.
|
||||||
|
let activation_heights: BTreeMap<_, _> = overwinter
|
||||||
|
.into_iter()
|
||||||
|
.map(|h| (h, Overwinter))
|
||||||
|
.chain(sapling.into_iter().map(|h| (h, Sapling)))
|
||||||
|
.chain(blossom.into_iter().map(|h| (h, Blossom)))
|
||||||
|
.chain(heartwood.into_iter().map(|h| (h, Heartwood)))
|
||||||
|
.chain(canopy.into_iter().map(|h| (h, Canopy)))
|
||||||
|
.chain(nu5.into_iter().map(|h| (h, Nu5)))
|
||||||
|
.filter(|&(_, nu)| nu != NetworkUpgrade::BeforeOverwinter)
|
||||||
|
.map(|(h, nu)| (h.try_into().expect("activation height must be valid"), nu))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let network_upgrades: Vec<_> = activation_heights.iter().map(|(_h, &nu)| nu).collect();
|
||||||
|
|
||||||
|
// Check that the provided network upgrade activation heights are in the same order by height as the default testnet activation heights
|
||||||
|
let mut activation_heights_iter = activation_heights.iter();
|
||||||
|
for expected_network_upgrade in NETWORK_UPGRADES_IN_ORDER {
|
||||||
|
if !network_upgrades.contains(&expected_network_upgrade) {
|
||||||
|
continue;
|
||||||
|
} else if let Some((&height, &network_upgrade)) = activation_heights_iter.next() {
|
||||||
|
assert_ne!(
|
||||||
|
height,
|
||||||
|
Height(0),
|
||||||
|
"Height(0) is reserved for the `Genesis` upgrade"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
network_upgrade == expected_network_upgrade,
|
||||||
|
"network upgrades must be activated in order, the correct order is {NETWORK_UPGRADES_IN_ORDER:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Correctness
|
||||||
|
//
|
||||||
|
// Height(0) must be reserved for the `NetworkUpgrade::Genesis`.
|
||||||
|
self.activation_heights.split_off(&Height(2));
|
||||||
|
self.activation_heights.extend(activation_heights);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the builder to a [`Parameters`] struct
|
||||||
|
pub fn finish(self) -> Parameters {
|
||||||
|
let Self {
|
||||||
|
activation_heights,
|
||||||
|
hrp_sapling_extended_spending_key,
|
||||||
|
hrp_sapling_extended_full_viewing_key,
|
||||||
|
hrp_sapling_payment_address,
|
||||||
|
} = self;
|
||||||
|
Parameters {
|
||||||
|
activation_heights,
|
||||||
|
hrp_sapling_extended_spending_key,
|
||||||
|
hrp_sapling_extended_full_viewing_key,
|
||||||
|
hrp_sapling_payment_address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the builder to a configured [`Network::Testnet`]
|
||||||
|
pub fn to_network(self) -> Network {
|
||||||
|
Network::new_configured_testnet(self.finish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Network consensus parameters for test networks such as Regtest and the default Testnet.
|
/// Network consensus parameters for test networks such as Regtest and the default Testnet.
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
pub struct Parameters {
|
||||||
pub struct Parameters {}
|
/// The network upgrade activation heights for this network.
|
||||||
|
///
|
||||||
|
/// Note: This value is ignored by `Network::activation_list()` when `zebra-chain` is
|
||||||
|
/// compiled with the `zebra-test` feature flag AND the `TEST_FAKE_ACTIVATION_HEIGHTS`
|
||||||
|
/// environment variable is set.
|
||||||
|
activation_heights: BTreeMap<Height, NetworkUpgrade>,
|
||||||
|
/// Sapling extended spending key human-readable prefix for this network
|
||||||
|
hrp_sapling_extended_spending_key: String,
|
||||||
|
/// Sapling extended full viewing key human-readable prefix for this network
|
||||||
|
hrp_sapling_extended_full_viewing_key: String,
|
||||||
|
/// Sapling payment address human-readable prefix for this network
|
||||||
|
hrp_sapling_payment_address: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Parameters {
|
||||||
|
/// Returns an instance of the default public testnet [`Parameters`].
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
activation_heights: TESTNET_ACTIVATION_HEIGHTS.iter().cloned().collect(),
|
||||||
|
hrp_sapling_extended_spending_key:
|
||||||
|
zp_constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY.to_string(),
|
||||||
|
hrp_sapling_extended_full_viewing_key:
|
||||||
|
zp_constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY.to_string(),
|
||||||
|
hrp_sapling_payment_address: zp_constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS
|
||||||
|
.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parameters {
|
impl Parameters {
|
||||||
|
/// Creates a new [`ParametersBuilder`].
|
||||||
|
pub fn build() -> ParametersBuilder {
|
||||||
|
ParametersBuilder::default()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the instance of [`Parameters`] represents the default public Testnet.
|
/// Returns true if the instance of [`Parameters`] represents the default public Testnet.
|
||||||
pub fn is_default_testnet(&self) -> bool {
|
pub fn is_default_testnet(&self) -> bool {
|
||||||
self == &Self::default()
|
self == &Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the network upgrade activation heights
|
||||||
|
pub fn activation_heights(&self) -> &BTreeMap<Height, NetworkUpgrade> {
|
||||||
|
&self.activation_heights
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `hrp_sapling_extended_spending_key` field
|
||||||
|
pub fn hrp_sapling_extended_spending_key(&self) -> &str {
|
||||||
|
&self.hrp_sapling_extended_spending_key
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `hrp_sapling_extended_full_viewing_key` field
|
||||||
|
pub fn hrp_sapling_extended_full_viewing_key(&self) -> &str {
|
||||||
|
&self.hrp_sapling_extended_full_viewing_key
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `hrp_sapling_payment_address` field
|
||||||
|
pub fn hrp_sapling_payment_address(&self) -> &str {
|
||||||
|
&self.hrp_sapling_payment_address
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
mod prop;
|
mod prop;
|
||||||
|
mod vectors;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
//! Fixed test vectors for the network consensus parameters.
|
||||||
|
|
||||||
|
use zcash_primitives::consensus::{self as zp_consensus, Parameters};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
block::Height,
|
||||||
|
parameters::{
|
||||||
|
testnet::{self, ConfiguredActivationHeights},
|
||||||
|
Network, NetworkUpgrade, NETWORK_UPGRADES_IN_ORDER,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Checks that every method in the `Parameters` impl for `zebra_chain::Network` has the same output
|
||||||
|
/// as the Parameters impl for `zcash_primitives::consensus::Network` on Mainnet and the default Testnet.
|
||||||
|
#[test]
|
||||||
|
fn check_parameters_impl() {
|
||||||
|
let zp_network_upgrades = [
|
||||||
|
zp_consensus::NetworkUpgrade::Overwinter,
|
||||||
|
zp_consensus::NetworkUpgrade::Sapling,
|
||||||
|
zp_consensus::NetworkUpgrade::Blossom,
|
||||||
|
zp_consensus::NetworkUpgrade::Heartwood,
|
||||||
|
zp_consensus::NetworkUpgrade::Canopy,
|
||||||
|
zp_consensus::NetworkUpgrade::Nu5,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (network, zp_network) in [
|
||||||
|
(Network::Mainnet, zp_consensus::Network::MainNetwork),
|
||||||
|
(
|
||||||
|
Network::new_default_testnet(),
|
||||||
|
zp_consensus::Network::TestNetwork,
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
for nu in zp_network_upgrades {
|
||||||
|
let activation_height = network
|
||||||
|
.activation_height(nu)
|
||||||
|
.expect("must have activation height for past network upgrades");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
activation_height,
|
||||||
|
zp_network
|
||||||
|
.activation_height(nu)
|
||||||
|
.expect("must have activation height for past network upgrades"),
|
||||||
|
"Parameters::activation_heights() outputs must match"
|
||||||
|
);
|
||||||
|
|
||||||
|
let activation_height: u32 = activation_height.into();
|
||||||
|
|
||||||
|
for height in (activation_height - 1)..=(activation_height + 1) {
|
||||||
|
for nu in zp_network_upgrades {
|
||||||
|
let height = zp_consensus::BlockHeight::from_u32(height);
|
||||||
|
assert_eq!(
|
||||||
|
network.is_nu_active(nu, height),
|
||||||
|
zp_network.is_nu_active(nu, height),
|
||||||
|
"Parameters::is_nu_active() outputs must match",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
network.coin_type(),
|
||||||
|
zp_network.coin_type(),
|
||||||
|
"Parameters::coin_type() outputs must match"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
network.hrp_sapling_extended_spending_key(),
|
||||||
|
zp_network.hrp_sapling_extended_spending_key(),
|
||||||
|
"Parameters::hrp_sapling_extended_spending_key() outputs must match"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
network.hrp_sapling_extended_full_viewing_key(),
|
||||||
|
zp_network.hrp_sapling_extended_full_viewing_key(),
|
||||||
|
"Parameters::hrp_sapling_extended_full_viewing_key() outputs must match"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
network.hrp_sapling_payment_address(),
|
||||||
|
zp_network.hrp_sapling_payment_address(),
|
||||||
|
"Parameters::hrp_sapling_payment_address() outputs must match"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
network.b58_pubkey_address_prefix(),
|
||||||
|
zp_network.b58_pubkey_address_prefix(),
|
||||||
|
"Parameters::b58_pubkey_address_prefix() outputs must match"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
network.b58_script_address_prefix(),
|
||||||
|
zp_network.b58_script_address_prefix(),
|
||||||
|
"Parameters::b58_script_address_prefix() outputs must match"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks that `NetworkUpgrade::activation_height()` returns the activation height of the next
|
||||||
|
/// network upgrade if it doesn't find an activation height for a prior network upgrade, and that the
|
||||||
|
/// `Genesis` upgrade is always at `Height(0)`.
|
||||||
|
#[test]
|
||||||
|
fn activates_network_upgrades_correctly() {
|
||||||
|
let expected_activation_height = 1;
|
||||||
|
let network = testnet::Parameters::build()
|
||||||
|
.activation_heights(ConfiguredActivationHeights {
|
||||||
|
nu5: Some(expected_activation_height),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.to_network();
|
||||||
|
|
||||||
|
let genesis_activation_height = NetworkUpgrade::Genesis
|
||||||
|
.activation_height(&network)
|
||||||
|
.expect("must return an activation height");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
genesis_activation_height,
|
||||||
|
Height(0),
|
||||||
|
"activation height for all networks after Genesis and BeforeOverwinter should match NU5 activation height"
|
||||||
|
);
|
||||||
|
|
||||||
|
for nu in NETWORK_UPGRADES_IN_ORDER.into_iter().skip(1) {
|
||||||
|
let activation_height = nu
|
||||||
|
.activation_height(&network)
|
||||||
|
.expect("must return an activation height");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
activation_height, Height(expected_activation_height),
|
||||||
|
"activation height for all networks after Genesis and BeforeOverwinter \
|
||||||
|
should match NU5 activation height, network_upgrade: {nu}, activation_height: {activation_height:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,6 @@ use crate::parameters::{Network, Network::*};
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Bound::*;
|
|
||||||
|
|
||||||
use chrono::{DateTime, Duration, Utc};
|
use chrono::{DateTime, Duration, Utc};
|
||||||
use hex::{FromHex, ToHex};
|
use hex::{FromHex, ToHex};
|
||||||
|
|
@ -15,6 +14,18 @@ use hex::{FromHex, ToHex};
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
use proptest_derive::Arbitrary;
|
use proptest_derive::Arbitrary;
|
||||||
|
|
||||||
|
/// A list of network upgrades in the order that they must be activated.
|
||||||
|
pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 8] = [
|
||||||
|
Genesis,
|
||||||
|
BeforeOverwinter,
|
||||||
|
Overwinter,
|
||||||
|
Sapling,
|
||||||
|
Blossom,
|
||||||
|
Heartwood,
|
||||||
|
Canopy,
|
||||||
|
Nu5,
|
||||||
|
];
|
||||||
|
|
||||||
/// A Zcash network upgrade.
|
/// A Zcash network upgrade.
|
||||||
///
|
///
|
||||||
/// Network upgrades can change the Zcash network protocol or consensus rules in
|
/// Network upgrades can change the Zcash network protocol or consensus rules in
|
||||||
|
|
@ -242,12 +253,7 @@ impl Network {
|
||||||
/// and it's a test build, this returns a list of fake activation heights
|
/// and it's a test build, this returns a list of fake activation heights
|
||||||
/// used by some tests.
|
/// used by some tests.
|
||||||
pub fn activation_list(&self) -> BTreeMap<block::Height, NetworkUpgrade> {
|
pub fn activation_list(&self) -> BTreeMap<block::Height, NetworkUpgrade> {
|
||||||
let (mainnet_heights, testnet_heights) = {
|
match self {
|
||||||
#[cfg(not(feature = "zebra-test"))]
|
|
||||||
{
|
|
||||||
(MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// To prevent accidentally setting this somehow, only check the env var
|
// To prevent accidentally setting this somehow, only check the env var
|
||||||
// when being compiled for tests. We can't use cfg(test) since the
|
// when being compiled for tests. We can't use cfg(test) since the
|
||||||
// test that uses this is in zebra-state, and cfg(test) is not
|
// test that uses this is in zebra-state, and cfg(test) is not
|
||||||
|
|
@ -260,25 +266,19 @@ impl Network {
|
||||||
// feature should only be enabled for tests:
|
// feature should only be enabled for tests:
|
||||||
// https://doc.rust-lang.org/cargo/reference/features.html#resolver-version-2-command-line-flags
|
// https://doc.rust-lang.org/cargo/reference/features.html#resolver-version-2-command-line-flags
|
||||||
#[cfg(feature = "zebra-test")]
|
#[cfg(feature = "zebra-test")]
|
||||||
if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() {
|
Mainnet if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() => {
|
||||||
(
|
FAKE_MAINNET_ACTIVATION_HEIGHTS.iter().cloned().collect()
|
||||||
FAKE_MAINNET_ACTIVATION_HEIGHTS,
|
|
||||||
FAKE_TESTNET_ACTIVATION_HEIGHTS,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS)
|
|
||||||
}
|
}
|
||||||
};
|
#[cfg(feature = "zebra-test")]
|
||||||
match self {
|
Testnet(_) if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() => {
|
||||||
Mainnet => mainnet_heights,
|
FAKE_TESTNET_ACTIVATION_HEIGHTS.iter().cloned().collect()
|
||||||
// TODO: Add an `activation_heights` field to `testnet::Parameters` to return here. (#7970)
|
}
|
||||||
Testnet(_params) => testnet_heights,
|
Mainnet => MAINNET_ACTIVATION_HEIGHTS.iter().cloned().collect(),
|
||||||
|
Testnet(params) => params.activation_heights().clone(),
|
||||||
}
|
}
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkUpgrade {
|
impl NetworkUpgrade {
|
||||||
/// Returns the current network upgrade for `network` and `height`.
|
/// Returns the current network upgrade for `network` and `height`.
|
||||||
pub fn current(network: &Network, height: block::Height) -> NetworkUpgrade {
|
pub fn current(network: &Network, height: block::Height) -> NetworkUpgrade {
|
||||||
|
|
@ -290,11 +290,28 @@ impl NetworkUpgrade {
|
||||||
.expect("every height has a current network upgrade")
|
.expect("every height has a current network upgrade")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the next expected network upgrade after this network upgrade
|
||||||
|
pub fn next_upgrade(self) -> Option<Self> {
|
||||||
|
match self {
|
||||||
|
Genesis => Some(BeforeOverwinter),
|
||||||
|
BeforeOverwinter => Some(Overwinter),
|
||||||
|
Overwinter => Some(Sapling),
|
||||||
|
Sapling => Some(Blossom),
|
||||||
|
Blossom => Some(Heartwood),
|
||||||
|
Heartwood => Some(Canopy),
|
||||||
|
Canopy => Some(Nu5),
|
||||||
|
Nu5 => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the next network upgrade for `network` and `height`.
|
/// Returns the next network upgrade for `network` and `height`.
|
||||||
///
|
///
|
||||||
/// Returns None if the next upgrade has not been implemented in Zebra
|
/// Returns None if the next upgrade has not been implemented in Zebra
|
||||||
/// yet.
|
/// yet.
|
||||||
|
#[cfg(test)]
|
||||||
pub fn next(network: &Network, height: block::Height) -> Option<NetworkUpgrade> {
|
pub fn next(network: &Network, height: block::Height) -> Option<NetworkUpgrade> {
|
||||||
|
use std::ops::Bound::*;
|
||||||
|
|
||||||
network
|
network
|
||||||
.activation_list()
|
.activation_list()
|
||||||
.range((Excluded(height), Unbounded))
|
.range((Excluded(height), Unbounded))
|
||||||
|
|
@ -302,17 +319,27 @@ impl NetworkUpgrade {
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the activation height for this network upgrade on `network`.
|
/// Returns the activation height for this network upgrade on `network`, or
|
||||||
|
///
|
||||||
|
/// Returns the activation height of the first network upgrade that follows
|
||||||
|
/// this network upgrade if there is no activation height for this network upgrade
|
||||||
|
/// such as on Regtest or a configured Testnet where multiple network upgrades have the
|
||||||
|
/// same activation height, or if one is omitted when others that follow it are included.
|
||||||
///
|
///
|
||||||
/// Returns None if this network upgrade is a future upgrade, and its
|
/// Returns None if this network upgrade is a future upgrade, and its
|
||||||
/// activation height has not been set yet.
|
/// activation height has not been set yet.
|
||||||
|
///
|
||||||
|
/// Returns None if this network upgrade has not been configured on a Testnet or Regtest.
|
||||||
pub fn activation_height(&self, network: &Network) -> Option<block::Height> {
|
pub fn activation_height(&self, network: &Network) -> Option<block::Height> {
|
||||||
network
|
network
|
||||||
.activation_list()
|
.activation_list()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, nu)| nu == &self)
|
.find(|(_, nu)| nu == &self)
|
||||||
.map(|(height, _)| *height)
|
.map(|(height, _)| *height)
|
||||||
.next()
|
.or_else(|| {
|
||||||
|
self.next_upgrade()
|
||||||
|
.and_then(|next_nu| next_nu.activation_height(network))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `height` is the activation height of any network upgrade
|
/// Returns `true` if `height` is the activation height of any network upgrade
|
||||||
|
|
|
||||||
|
|
@ -22,29 +22,11 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh
|
||||||
|
|
||||||
let alt_height = height.0.into();
|
let alt_height = height.0.into();
|
||||||
let null_sapling_ovk = zcash_primitives::keys::OutgoingViewingKey([0u8; 32]);
|
let null_sapling_ovk = zcash_primitives::keys::OutgoingViewingKey([0u8; 32]);
|
||||||
let network = match network {
|
|
||||||
Network::Mainnet => zcash_primitives::consensus::Network::MainNetwork,
|
|
||||||
Network::Testnet(params) => {
|
|
||||||
// # Correctness:
|
|
||||||
//
|
|
||||||
// There are differences between the `TestNetwork` parameters and those returned by
|
|
||||||
// `CRegTestParams()` in zcashd, so this function can't return `TestNetwork` unless
|
|
||||||
// Zebra is using the default public Testnet.
|
|
||||||
//
|
|
||||||
// TODO: Remove this conversion by implementing `zcash_primitives::consensus::Parameters`
|
|
||||||
// for `Network` (#8365).
|
|
||||||
assert!(
|
|
||||||
params.is_default_testnet(),
|
|
||||||
"could not convert configured testnet to zcash_primitives::consensus::Network"
|
|
||||||
);
|
|
||||||
zcash_primitives::consensus::Network::TestNetwork
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(bundle) = alt_tx.sapling_bundle() {
|
if let Some(bundle) = alt_tx.sapling_bundle() {
|
||||||
for output in bundle.shielded_outputs().iter() {
|
for output in bundle.shielded_outputs().iter() {
|
||||||
let recovery = zcash_primitives::sapling::note_encryption::try_sapling_output_recovery(
|
let recovery = zcash_primitives::sapling::note_encryption::try_sapling_output_recovery(
|
||||||
&network,
|
network,
|
||||||
alt_height,
|
alt_height,
|
||||||
&null_sapling_ovk,
|
&null_sapling_ovk,
|
||||||
output,
|
output,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ use tempfile::NamedTempFile;
|
||||||
use tokio::{fs, io::AsyncWriteExt};
|
use tokio::{fs, io::AsyncWriteExt};
|
||||||
use tracing::Span;
|
use tracing::Span;
|
||||||
|
|
||||||
use zebra_chain::parameters::{testnet, Network, NetworkKind};
|
use zebra_chain::parameters::{
|
||||||
|
testnet::{self, ConfiguredActivationHeights},
|
||||||
|
Network, NetworkKind,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::{
|
constants::{
|
||||||
|
|
@ -624,12 +627,18 @@ impl<'de> Deserialize<'de> for Config {
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct DTestnetParameters {
|
||||||
|
#[serde(default)]
|
||||||
|
pub(super) activation_heights: ConfiguredActivationHeights,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(deny_unknown_fields, default)]
|
#[serde(deny_unknown_fields, default)]
|
||||||
struct DConfig {
|
struct DConfig {
|
||||||
listen_addr: String,
|
listen_addr: String,
|
||||||
network: NetworkKind,
|
network: NetworkKind,
|
||||||
testnet_parameters: Option<testnet::Parameters>,
|
testnet_parameters: Option<DTestnetParameters>,
|
||||||
initial_mainnet_peers: IndexSet<String>,
|
initial_mainnet_peers: IndexSet<String>,
|
||||||
initial_testnet_peers: IndexSet<String>,
|
initial_testnet_peers: IndexSet<String>,
|
||||||
cache_dir: CacheDir,
|
cache_dir: CacheDir,
|
||||||
|
|
@ -668,15 +677,17 @@ impl<'de> Deserialize<'de> for Config {
|
||||||
max_connections_per_ip,
|
max_connections_per_ip,
|
||||||
} = DConfig::deserialize(deserializer)?;
|
} = DConfig::deserialize(deserializer)?;
|
||||||
|
|
||||||
let network = if let Some(network_params) = testnet_parameters {
|
// TODO: Panic here if the initial testnet peers are the default initial testnet peers.
|
||||||
// TODO: Panic here if the initial testnet peers are the default initial testnet peers.
|
let network = if let Some(DTestnetParameters { activation_heights }) = testnet_parameters {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
network_kind,
|
network_kind,
|
||||||
NetworkKind::Testnet,
|
NetworkKind::Testnet,
|
||||||
"set network to 'Testnet' to use configured testnet parameters"
|
"set network to 'Testnet' to use configured testnet parameters"
|
||||||
);
|
);
|
||||||
|
|
||||||
Network::new_configured_testnet(network_params)
|
testnet::Parameters::build()
|
||||||
|
.activation_heights(activation_heights)
|
||||||
|
.to_network()
|
||||||
} else {
|
} else {
|
||||||
// Convert to default `Network` for a `NetworkKind` if there are no testnet parameters.
|
// Convert to default `Network` for a `NetworkKind` if there are no testnet parameters.
|
||||||
match network_kind {
|
match network_kind {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use zebra_chain::{
|
||||||
block::{self, Block, Height, TryIntoHeight},
|
block::{self, Block, Height, TryIntoHeight},
|
||||||
chain_sync_status::ChainSyncStatus,
|
chain_sync_status::ChainSyncStatus,
|
||||||
chain_tip::ChainTip,
|
chain_tip::ChainTip,
|
||||||
parameters::{Network, POW_AVERAGING_WINDOW},
|
parameters::{Network, NetworkKind, POW_AVERAGING_WINDOW},
|
||||||
primitives,
|
primitives,
|
||||||
serialization::ZcashDeserializeInto,
|
serialization::ZcashDeserializeInto,
|
||||||
transparent::{
|
transparent::{
|
||||||
|
|
@ -449,13 +449,25 @@ where
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Prevent loss of miner funds due to an unsupported or incorrect address type.
|
// Prevent loss of miner funds due to an unsupported or incorrect address type.
|
||||||
if let Some(miner_address) = mining_config.miner_address.clone() {
|
if let Some(miner_address) = mining_config.miner_address.clone() {
|
||||||
assert_eq!(
|
match network.kind() {
|
||||||
miner_address.network_kind(),
|
NetworkKind::Mainnet => assert_eq!(
|
||||||
network.kind(),
|
miner_address.network_kind(),
|
||||||
"incorrect miner address config: {miner_address} \
|
NetworkKind::Mainnet,
|
||||||
network.network {network} and miner address network {} must match",
|
"Incorrect config: Zebra is configured to run on a Mainnet network, \
|
||||||
miner_address.network_kind(),
|
which implies the configured mining address needs to be for Mainnet, \
|
||||||
);
|
but the provided address is for {}.",
|
||||||
|
miner_address.network_kind(),
|
||||||
|
),
|
||||||
|
// `Regtest` uses `Testnet` transparent addresses.
|
||||||
|
network_kind @ (NetworkKind::Testnet | NetworkKind::Regtest) => assert_eq!(
|
||||||
|
miner_address.network_kind(),
|
||||||
|
NetworkKind::Testnet,
|
||||||
|
"Incorrect config: Zebra is configured to run on a {network_kind} network, \
|
||||||
|
which implies the configured mining address needs to be for Testnet, \
|
||||||
|
but the provided address is for {}.",
|
||||||
|
miner_address.network_kind(),
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A limit on the configured extra coinbase data, regardless of the current block height.
|
// A limit on the configured extra coinbase data, regardless of the current block height.
|
||||||
|
|
|
||||||
|
|
@ -384,25 +384,6 @@ pub fn scan_block<K: ScanningKey>(
|
||||||
// TODO: Implement a check that returns early when the block height is below the Sapling
|
// TODO: Implement a check that returns early when the block height is below the Sapling
|
||||||
// activation height.
|
// activation height.
|
||||||
|
|
||||||
let network = match network {
|
|
||||||
Network::Mainnet => zcash_primitives::consensus::Network::MainNetwork,
|
|
||||||
Network::Testnet(params) => {
|
|
||||||
// # Correctness:
|
|
||||||
//
|
|
||||||
// There are differences between the `TestNetwork` parameters and those returned by
|
|
||||||
// `CRegTestParams()` in zcashd, so this function can't return `TestNetwork` unless
|
|
||||||
// Zebra is using the default public Testnet.
|
|
||||||
//
|
|
||||||
// TODO: Remove this conversion by implementing `zcash_primitives::consensus::Parameters`
|
|
||||||
// for `Network` (#8365).
|
|
||||||
assert!(
|
|
||||||
params.is_default_testnet(),
|
|
||||||
"could not convert configured testnet to zcash_primitives::consensus::Network"
|
|
||||||
);
|
|
||||||
zcash_primitives::consensus::Network::TestNetwork
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let chain_metadata = ChainMetadata {
|
let chain_metadata = ChainMetadata {
|
||||||
sapling_commitment_tree_size: sapling_tree_size,
|
sapling_commitment_tree_size: sapling_tree_size,
|
||||||
// Orchard is not supported at the moment so the tree size can be 0.
|
// Orchard is not supported at the moment so the tree size can be 0.
|
||||||
|
|
@ -417,7 +398,7 @@ pub fn scan_block<K: ScanningKey>(
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
zcash_client_backend::scanning::scan_block(
|
zcash_client_backend::scanning::scan_block(
|
||||||
&network,
|
network,
|
||||||
block_to_compact(block, chain_metadata),
|
block_to_compact(block, chain_metadata),
|
||||||
scanning_keys.as_slice(),
|
scanning_keys.as_slice(),
|
||||||
// Ignore whether notes are change from a viewer's own spends for now.
|
// Ignore whether notes are change from a viewer's own spends for now.
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,13 @@ use zebra_scan::{storage::Storage, Config};
|
||||||
/// - The transaction fetched via RPC cannot be deserialized from raw bytes.
|
/// - The transaction fetched via RPC cannot be deserialized from raw bytes.
|
||||||
#[allow(clippy::print_stdout)]
|
#[allow(clippy::print_stdout)]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
// TODO: Implement `zcash_primitives::consensus::Parameters` for `Network` and remove this variable (#8365).
|
let network = zebra_chain::parameters::Network::Mainnet;
|
||||||
let network = zcash_primitives::consensus::Network::MainNetwork;
|
let storage = Storage::new(&Config::default(), &network, true);
|
||||||
let zebra_network = zebra_chain::parameters::Network::Mainnet;
|
|
||||||
let storage = Storage::new(&Config::default(), &zebra_network, true);
|
|
||||||
// If the first memo is empty, it doesn't get printed. But we never print empty memos anyway.
|
// If the first memo is empty, it doesn't get printed. But we never print empty memos anyway.
|
||||||
let mut prev_memo = "".to_owned();
|
let mut prev_memo = "".to_owned();
|
||||||
|
|
||||||
for (key, _) in storage.sapling_keys_last_heights().iter() {
|
for (key, _) in storage.sapling_keys_last_heights().iter() {
|
||||||
let dfvk = sapling_key_to_scan_block_keys(key, &zebra_network)
|
let dfvk = sapling_key_to_scan_block_keys(key, &network)
|
||||||
.expect("Scanning key from the storage should be valid")
|
.expect("Scanning key from the storage should be valid")
|
||||||
.0
|
.0
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
|
|
@ -922,6 +922,69 @@ fn invalid_generated_config() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test all versions of `zebrad.toml` we have stored can be parsed by the latest `zebrad`.
|
||||||
|
#[tracing::instrument]
|
||||||
|
#[test]
|
||||||
|
fn stored_configs_parsed_correctly() -> Result<()> {
|
||||||
|
let old_configs_dir = configs_dir();
|
||||||
|
use abscissa_core::Application;
|
||||||
|
use zebrad::application::ZebradApp;
|
||||||
|
|
||||||
|
tracing::info!(?old_configs_dir, "testing older config parsing");
|
||||||
|
|
||||||
|
for config_file in old_configs_dir
|
||||||
|
.read_dir()
|
||||||
|
.expect("read_dir call failed")
|
||||||
|
.flatten()
|
||||||
|
{
|
||||||
|
let config_file_path = config_file.path();
|
||||||
|
let config_file_name = config_file_path
|
||||||
|
.file_name()
|
||||||
|
.expect("config files must have a file name")
|
||||||
|
.to_str()
|
||||||
|
.expect("config file names are valid unicode");
|
||||||
|
|
||||||
|
if config_file_name.starts_with('.') || config_file_name.starts_with('#') {
|
||||||
|
// Skip editor files and other invalid config paths
|
||||||
|
tracing::info!(
|
||||||
|
?config_file_path,
|
||||||
|
"skipping hidden/temporary config file path"
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore files starting with getblocktemplate prefix
|
||||||
|
// if we were not built with the getblocktemplate-rpcs feature.
|
||||||
|
#[cfg(not(feature = "getblocktemplate-rpcs"))]
|
||||||
|
if config_file_name.starts_with(GET_BLOCK_TEMPLATE_CONFIG_PREFIX) {
|
||||||
|
tracing::info!(
|
||||||
|
?config_file_path,
|
||||||
|
"skipping getblocktemplate-rpcs config file path"
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore files starting with shieldedscan prefix
|
||||||
|
// if we were not built with the shielded-scan feature.
|
||||||
|
#[cfg(not(feature = "shielded-scan"))]
|
||||||
|
if config_file_name.starts_with(SHIELDED_SCAN_CONFIG_PREFIX) {
|
||||||
|
tracing::info!(?config_file_path, "skipping shielded-scan config file path");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::info!(
|
||||||
|
?config_file_path,
|
||||||
|
"testing old config can be parsed by current zebrad"
|
||||||
|
);
|
||||||
|
|
||||||
|
ZebradApp::default()
|
||||||
|
.load_config(&config_file_path)
|
||||||
|
.expect("config should parse");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Test all versions of `zebrad.toml` we have stored can be parsed by the latest `zebrad`.
|
/// Test all versions of `zebrad.toml` we have stored can be parsed by the latest `zebrad`.
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
fn stored_configs_work() -> Result<()> {
|
fn stored_configs_work() -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,14 @@ max_connections_per_ip = 1
|
||||||
network = "Testnet"
|
network = "Testnet"
|
||||||
peerset_initial_target_size = 25
|
peerset_initial_target_size = 25
|
||||||
|
|
||||||
[network.testnet_parameters]
|
[network.testnet_parameters.activation_heights]
|
||||||
|
BeforeOverwinter = 1
|
||||||
|
Overwinter = 207_500
|
||||||
|
Sapling = 280_000
|
||||||
|
Blossom = 584_000
|
||||||
|
Heartwood = 903_800
|
||||||
|
Canopy = 1_028_500
|
||||||
|
NU5 = 1_842_420
|
||||||
|
|
||||||
[rpc]
|
[rpc]
|
||||||
debug_force_finished_sync = false
|
debug_force_finished_sync = false
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue