Merge branch 'main' into bump-chrono
This commit is contained in:
commit
5de5072c72
|
@ -151,7 +151,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4.1.2
|
||||
- name: actionlint
|
||||
uses: reviewdog/action-actionlint@v1.43.0
|
||||
uses: reviewdog/action-actionlint@v1.44.0
|
||||
with:
|
||||
level: warning
|
||||
fail_on_error: false
|
||||
|
|
|
@ -281,7 +281,7 @@ jobs:
|
|||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal
|
||||
|
||||
- name: Install cargo-machete
|
||||
uses: baptiste0928/cargo-install@v3.0.1
|
||||
uses: baptiste0928/cargo-install@v3.1.0
|
||||
with:
|
||||
crate: cargo-machete
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ jobs:
|
|||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal
|
||||
|
||||
- name: Install cargo-release
|
||||
uses: baptiste0928/cargo-install@v3.0.1
|
||||
uses: baptiste0928/cargo-install@v3.1.0
|
||||
with:
|
||||
crate: cargo-release
|
||||
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
//! Randomised property testing for [`Block`]s.
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use proptest::{
|
||||
arbitrary::{any, Arbitrary},
|
||||
prelude::*,
|
||||
};
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::{
|
||||
amount::NonNegative,
|
||||
block,
|
||||
fmt::{HexDebug, SummaryDebug},
|
||||
history_tree::HistoryTree,
|
||||
parameters::{
|
||||
Network,
|
||||
NetworkUpgrade::{self, *},
|
||||
GENESIS_PREVIOUS_BLOCK_HASH,
|
||||
},
|
||||
parameters::{NetworkUpgrade::*, GENESIS_PREVIOUS_BLOCK_HASH},
|
||||
serialization,
|
||||
transaction::arbitrary::MAX_ARBITRARY_ITEMS,
|
||||
transparent::{
|
||||
|
|
|
@ -2,21 +2,19 @@
|
|||
|
||||
use std::{env, io::ErrorKind};
|
||||
|
||||
use proptest::{arbitrary::any, prelude::*, test_runner::Config};
|
||||
use proptest::{prelude::*, test_runner::Config};
|
||||
|
||||
use hex::{FromHex, ToHex};
|
||||
|
||||
use zebra_test::prelude::*;
|
||||
|
||||
use crate::{
|
||||
parameters::{Network, GENESIS_PREVIOUS_BLOCK_HASH},
|
||||
parameters::GENESIS_PREVIOUS_BLOCK_HASH,
|
||||
serialization::{SerializationError, ZcashDeserializeInto, ZcashSerialize},
|
||||
LedgerState,
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
arbitrary::{allow_all_transparent_coinbase_spends, PREVOUTS_CHAIN_HEIGHT},
|
||||
serialize::MAX_BLOCK_BYTES,
|
||||
*,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{convert::TryFrom, io};
|
||||
use std::io;
|
||||
|
||||
use halo2::pasta::pallas;
|
||||
use reddsa::orchard::SpendAuth;
|
||||
|
|
|
@ -7,7 +7,7 @@ use group::{
|
|||
use halo2::pasta::pallas;
|
||||
use reddsa::{orchard::SpendAuth, Signature, SigningKey, VerificationKey, VerificationKeyBytes};
|
||||
|
||||
use proptest::{arbitrary::any, array, collection::vec, prelude::*};
|
||||
use proptest::{array, collection::vec, prelude::*};
|
||||
|
||||
use super::{
|
||||
keys::*, note, tree, Action, AuthorizedAction, Flags, NoteCommitment, ValueCommitment,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use halo2::pasta::pallas;
|
||||
use reddsa::{self, orchard::Binding, orchard::SpendAuth, Signature};
|
||||
use reddsa::{orchard::Binding, orchard::SpendAuth, Signature};
|
||||
|
||||
use crate::{
|
||||
amount::{Amount, NegativeAllowed},
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::{
|
|||
};
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use bridgetree::{self, NonEmptyFrontier};
|
||||
use bridgetree::NonEmptyFrontier;
|
||||
use halo2::pasta::{group::ff::PrimeField, pallas};
|
||||
use hex::ToHex;
|
||||
use incrementalmerkletree::Hashable;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::NetworkUpgrade;
|
||||
use super::{Network, NetworkUpgrade};
|
||||
|
||||
impl NetworkUpgrade {
|
||||
/// Generates network upgrades.
|
||||
|
@ -32,3 +32,13 @@ impl NetworkUpgrade {
|
|||
.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 zcash_primitives::constants;
|
||||
use zcash_primitives::{consensus as zp_consensus, constants as zp_constants};
|
||||
|
||||
use crate::{
|
||||
block::{self, Height, HeightDiff},
|
||||
parameters::NetworkUpgrade::Canopy,
|
||||
parameters::NetworkUpgrade,
|
||||
};
|
||||
|
||||
pub mod testnet;
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
@ -81,7 +78,6 @@ impl From<Network> for NetworkKind {
|
|||
|
||||
/// An enum describing the possible network choices.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize)]
|
||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||
#[serde(into = "NetworkKind")]
|
||||
pub enum Network {
|
||||
/// The production mainnet.
|
||||
|
@ -98,8 +94,8 @@ impl NetworkKind {
|
|||
/// pay-to-public-key-hash payment addresses for the network.
|
||||
pub fn b58_pubkey_address_prefix(self) -> [u8; 2] {
|
||||
match self {
|
||||
Self::Mainnet => constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||
Self::Testnet | Self::Regtest => constants::testnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||
Self::Mainnet => zp_constants::mainnet::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.
|
||||
pub fn b58_script_address_prefix(self) -> [u8; 2] {
|
||||
match self {
|
||||
Self::Mainnet => constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||
Self::Testnet | Self::Regtest => constants::testnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||
Self::Mainnet => zp_constants::mainnet::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.
|
||||
|
||||
let canopy_activation = Canopy
|
||||
let canopy_activation = NetworkUpgrade::Canopy
|
||||
.activation_height(self)
|
||||
.expect("Canopy activation height must be present for both networks");
|
||||
|
||||
|
@ -279,3 +275,70 @@ impl FromStr for Network {
|
|||
#[derive(Clone, Debug, Error)]
|
||||
#[error("Invalid network: {0}")]
|
||||
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
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
use zcash_primitives::constants as zp_constants;
|
||||
|
||||
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.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||
pub struct Parameters {}
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
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 {
|
||||
/// Creates a new [`ParametersBuilder`].
|
||||
pub fn build() -> ParametersBuilder {
|
||||
ParametersBuilder::default()
|
||||
}
|
||||
|
||||
/// Returns true if the instance of [`Parameters`] represents the default public Testnet.
|
||||
pub fn is_default_testnet(&self) -> bool {
|
||||
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 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::fmt;
|
||||
use std::ops::Bound::*;
|
||||
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use hex::{FromHex, ToHex};
|
||||
|
@ -15,6 +14,18 @@ use hex::{FromHex, ToHex};
|
|||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
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.
|
||||
///
|
||||
/// 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
|
||||
/// used by some tests.
|
||||
pub fn activation_list(&self) -> BTreeMap<block::Height, NetworkUpgrade> {
|
||||
let (mainnet_heights, testnet_heights) = {
|
||||
#[cfg(not(feature = "zebra-test"))]
|
||||
{
|
||||
(MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS)
|
||||
}
|
||||
|
||||
match self {
|
||||
// To prevent accidentally setting this somehow, only check the env var
|
||||
// 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
|
||||
|
@ -260,25 +266,19 @@ impl Network {
|
|||
// feature should only be enabled for tests:
|
||||
// https://doc.rust-lang.org/cargo/reference/features.html#resolver-version-2-command-line-flags
|
||||
#[cfg(feature = "zebra-test")]
|
||||
if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() {
|
||||
(
|
||||
FAKE_MAINNET_ACTIVATION_HEIGHTS,
|
||||
FAKE_TESTNET_ACTIVATION_HEIGHTS,
|
||||
)
|
||||
} else {
|
||||
(MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS)
|
||||
Mainnet if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() => {
|
||||
FAKE_MAINNET_ACTIVATION_HEIGHTS.iter().cloned().collect()
|
||||
}
|
||||
};
|
||||
match self {
|
||||
Mainnet => mainnet_heights,
|
||||
// TODO: Add an `activation_heights` field to `testnet::Parameters` to return here. (#7970)
|
||||
Testnet(_params) => testnet_heights,
|
||||
#[cfg(feature = "zebra-test")]
|
||||
Testnet(_) if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() => {
|
||||
FAKE_TESTNET_ACTIVATION_HEIGHTS.iter().cloned().collect()
|
||||
}
|
||||
Mainnet => MAINNET_ACTIVATION_HEIGHTS.iter().cloned().collect(),
|
||||
Testnet(params) => params.activation_heights().clone(),
|
||||
}
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkUpgrade {
|
||||
/// Returns the current network upgrade for `network` and `height`.
|
||||
pub fn current(network: &Network, height: block::Height) -> NetworkUpgrade {
|
||||
|
@ -290,11 +290,28 @@ impl NetworkUpgrade {
|
|||
.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 None if the next upgrade has not been implemented in Zebra
|
||||
/// yet.
|
||||
#[cfg(test)]
|
||||
pub fn next(network: &Network, height: block::Height) -> Option<NetworkUpgrade> {
|
||||
use std::ops::Bound::*;
|
||||
|
||||
network
|
||||
.activation_list()
|
||||
.range((Excluded(height), Unbounded))
|
||||
|
@ -302,17 +319,27 @@ impl NetworkUpgrade {
|
|||
.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
|
||||
/// 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> {
|
||||
network
|
||||
.activation_list()
|
||||
.iter()
|
||||
.filter(|(_, nu)| nu == &self)
|
||||
.find(|(_, nu)| nu == &self)
|
||||
.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
|
||||
|
|
|
@ -53,7 +53,7 @@ impl ZcashDeserialize for Bctv14Proof {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Arbitrary for Bctv14Proof {
|
||||
|
|
|
@ -65,7 +65,7 @@ impl ZcashDeserialize for Groth16Proof {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Arbitrary for Groth16Proof {
|
||||
|
|
|
@ -36,7 +36,7 @@ impl ZcashDeserialize for Halo2Proof {
|
|||
}
|
||||
}
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest::{arbitrary::Arbitrary, prelude::*};
|
||||
use proptest::prelude::*;
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Arbitrary for Halo2Proof {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
mod tests;
|
||||
|
||||
use std::{collections::BTreeMap, convert::TryInto, io, sync::Arc};
|
||||
use std::{collections::BTreeMap, io, sync::Arc};
|
||||
|
||||
use serde_big_array::BigArray;
|
||||
pub use zcash_history::{V1, V2};
|
||||
|
|
|
@ -22,29 +22,11 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh
|
|||
|
||||
let alt_height = height.0.into();
|
||||
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() {
|
||||
for output in bundle.shielded_outputs().iter() {
|
||||
let recovery = zcash_primitives::sapling::note_encryption::try_sapling_output_recovery(
|
||||
&network,
|
||||
network,
|
||||
alt_height,
|
||||
&null_sapling_ovk,
|
||||
output,
|
||||
|
|
|
@ -5,7 +5,7 @@ use jubjub::{AffinePoint, ExtendedPoint};
|
|||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaChaRng;
|
||||
|
||||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use crate::primitives::Groth16Proof;
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//! Note and value commitments.
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt, io,
|
||||
};
|
||||
use std::{fmt, io};
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use jubjub::ExtendedPoint;
|
||||
|
|
|
@ -16,7 +16,7 @@ use rand_core::{CryptoRng, RngCore};
|
|||
|
||||
use crate::{
|
||||
error::{AddressError, RandError},
|
||||
primitives::redjubjub::{self, SpendAuth},
|
||||
primitives::redjubjub::SpendAuth,
|
||||
serialization::{
|
||||
serde_helpers, ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize,
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -3,14 +3,11 @@
|
|||
//! Zebra uses a generic spend type for `V4` and `V5` transactions.
|
||||
//! The anchor change is handled using the `AnchorVariant` type trait.
|
||||
|
||||
use std::{convert::TryInto, fmt, io};
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::{
|
||||
block::MAX_BLOCK_BYTES,
|
||||
primitives::{
|
||||
redjubjub::{self, SpendAuth},
|
||||
Groth16Proof,
|
||||
},
|
||||
primitives::{redjubjub::SpendAuth, Groth16Proof},
|
||||
serialization::{
|
||||
ReadZcashExt, SerializationError, TrustedPreallocate, WriteZcashExt, ZcashDeserialize,
|
||||
ZcashDeserializeInto, ZcashSerialize,
|
||||
|
|
|
@ -8,7 +8,6 @@ use crate::{
|
|||
serialization::{ZcashDeserializeInto, ZcashSerialize},
|
||||
transaction::{LockTime, Transaction},
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
proptest! {
|
||||
/// Serialize and deserialize `Spend<PerSpendAnchor>`
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::{
|
|||
};
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use bridgetree::{self, NonEmptyFrontier};
|
||||
use bridgetree::NonEmptyFrontier;
|
||||
use hex::ToHex;
|
||||
use incrementalmerkletree::{frontier::Frontier, Hashable};
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
//! Arbitrary data generation for serialization proptests
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use proptest::{arbitrary::any, prelude::*};
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::{
|
||||
CompactSizeMessage, DateTime32, TrustedPreallocate, ZcashSerialize, MAX_PROTOCOL_MESSAGE_LEN,
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
//! - [`CompactSizeMessage`] for sizes that must be less than the network message limit, and
|
||||
//! - [`CompactSize64`] for flags, arbitrary counts, and sizes that span multiple blocks.
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use crate::serialization::{
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//! Serialization constraint helpers.
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
ops::Deref,
|
||||
};
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::serialization::SerializationError;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use proptest::{collection::size_range, prelude::*};
|
||||
|
||||
use std::{convert::TryInto, matches};
|
||||
use std::matches;
|
||||
|
||||
use crate::serialization::{
|
||||
arbitrary::max_allocation_is_big_enough, zcash_deserialize::MAX_U8_ALLOCATION,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, array, prelude::*};
|
||||
use proptest::{array, prelude::*};
|
||||
|
||||
use crate::{
|
||||
amount::{Amount, NonNegative},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
impl Arbitrary for super::EncryptedNote {
|
||||
type Parameters = ();
|
||||
|
|
|
@ -30,7 +30,9 @@ impl Network {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns blocks indexed by height in a [`BTreeMap`].
|
||||
///
|
||||
/// Returns Mainnet blocks if `self` is set to Mainnet, and Testnet blocks otherwise.
|
||||
pub fn block_map(&self) -> BTreeMap<u32, &'static [u8]> {
|
||||
if self.is_mainnet() {
|
||||
zebra_test::vectors::MAINNET_BLOCKS.clone()
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
//! Arbitrary data generation for transaction proptests
|
||||
|
||||
use std::{
|
||||
cmp::max,
|
||||
collections::HashMap,
|
||||
convert::{TryFrom, TryInto},
|
||||
ops::Neg,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{cmp::max, collections::HashMap, ops::Neg, sync::Arc};
|
||||
|
||||
use chrono::{TimeZone, Utc};
|
||||
use proptest::{
|
||||
arbitrary::any, array, collection::vec, option, prelude::*, test_runner::TestRunner,
|
||||
};
|
||||
use proptest::{array, collection::vec, option, prelude::*, test_runner::TestRunner};
|
||||
use reddsa::{orchard::Binding, Signature};
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -28,11 +28,7 @@
|
|||
//!
|
||||
//! [1]: crate::transaction::UnminedTx
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{fmt, sync::Arc};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{cmp, convert::TryFrom, fmt};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
/// A 512-byte (plaintext) memo associated with a note, as described in
|
||||
/// [protocol specification §5.5][ps].
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! Contains impls of `ZcashSerialize`, `ZcashDeserialize` for all of the
|
||||
//! transaction types, so that all of the serialization logic is in one place.
|
||||
|
||||
use std::{borrow::Borrow, convert::TryInto, io, sync::Arc};
|
||||
use std::{borrow::Borrow, io, sync::Arc};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use halo2::pasta::{group::ff::PrimeField, pallas};
|
||||
use halo2::pasta::group::ff::PrimeField;
|
||||
use hex::FromHex;
|
||||
use reddsa::{orchard::Binding, orchard::SpendAuth, Signature};
|
||||
|
||||
|
@ -12,13 +12,12 @@ use crate::{
|
|||
amount,
|
||||
block::MAX_BLOCK_BYTES,
|
||||
parameters::{OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID},
|
||||
primitives::{Groth16Proof, Halo2Proof, ZkSnarkProof},
|
||||
primitives::{Halo2Proof, ZkSnarkProof},
|
||||
serialization::{
|
||||
zcash_deserialize_external_count, zcash_serialize_empty_list,
|
||||
zcash_serialize_external_count, AtLeastOne, ReadZcashExt, SerializationError,
|
||||
TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize,
|
||||
},
|
||||
sprout,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
|
|
@ -5,11 +5,10 @@ use color_eyre::eyre::Result;
|
|||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::{
|
||||
amount::Amount,
|
||||
block::{Block, Height, MAX_BLOCK_BYTES},
|
||||
parameters::{Network, NetworkUpgrade},
|
||||
parameters::Network,
|
||||
serialization::{SerializationError, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize},
|
||||
transaction::{hash::WtxId, sighash::SigHasher, txid::TxIdBuilder, Transaction},
|
||||
transaction::{sighash::SigHasher, txid::TxIdBuilder},
|
||||
transparent::Script,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Transaction ID computation. Contains code for generating the Transaction ID
|
||||
//! from the transaction.
|
||||
use std::{convert::TryInto, io};
|
||||
use std::io;
|
||||
|
||||
use super::{Hash, Transaction};
|
||||
use crate::serialization::{sha256d, ZcashSerialize};
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
use std::{fmt, io};
|
||||
|
||||
use ripemd::{Digest, Ripemd160};
|
||||
use secp256k1::PublicKey;
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::{
|
||||
parameters::NetworkKind,
|
||||
serialization::{SerializationError, ZcashDeserialize, ZcashSerialize},
|
||||
|
@ -154,29 +150,6 @@ impl ZcashDeserialize for Address {
|
|||
}
|
||||
}
|
||||
|
||||
trait ToAddressWithNetwork {
|
||||
/// Convert `self` to an `Address`, given the current `network`.
|
||||
fn to_address(&self, network: NetworkKind) -> Address;
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for Script {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToScriptHash {
|
||||
network_kind,
|
||||
script_hash: Address::hash_payload(self.as_raw_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for PublicKey {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToPublicKeyHash {
|
||||
network_kind,
|
||||
pub_key_hash: Address::hash_payload(&self.serialize()[..]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Address {
|
||||
/// Create an address for the given public key hash and network.
|
||||
pub fn from_pub_key_hash(network_kind: NetworkKind, pub_key_hash: [u8; 20]) -> Self {
|
||||
|
@ -219,21 +192,6 @@ impl Address {
|
|||
}
|
||||
}
|
||||
|
||||
/// A hash of a transparent address payload, as used in
|
||||
/// transparent pay-to-script-hash and pay-to-publickey-hash
|
||||
/// addresses.
|
||||
///
|
||||
/// The resulting hash in both of these cases is always exactly 20
|
||||
/// bytes.
|
||||
/// <https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address>
|
||||
fn hash_payload(bytes: &[u8]) -> [u8; 20] {
|
||||
let sha_hash = Sha256::digest(bytes);
|
||||
let ripe_hash = Ripemd160::digest(sha_hash);
|
||||
let mut payload = [0u8; 20];
|
||||
payload[..].copy_from_slice(&ripe_hash[..]);
|
||||
payload
|
||||
}
|
||||
|
||||
/// Given a transparent address (P2SH or a P2PKH), create a script that can be used in a coinbase
|
||||
/// transaction output.
|
||||
pub fn create_script_from_address(&self) -> Script {
|
||||
|
@ -264,11 +222,53 @@ impl Address {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use ripemd::{Digest, Ripemd160};
|
||||
use secp256k1::PublicKey;
|
||||
use sha2::Sha256;
|
||||
|
||||
use super::*;
|
||||
|
||||
trait ToAddressWithNetwork {
|
||||
/// Convert `self` to an `Address`, given the current `network`.
|
||||
fn to_address(&self, network: NetworkKind) -> Address;
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for Script {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToScriptHash {
|
||||
network_kind,
|
||||
script_hash: Address::hash_payload(self.as_raw_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for PublicKey {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToPublicKeyHash {
|
||||
network_kind,
|
||||
pub_key_hash: Address::hash_payload(&self.serialize()[..]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Address {
|
||||
/// A hash of a transparent address payload, as used in
|
||||
/// transparent pay-to-script-hash and pay-to-publickey-hash
|
||||
/// addresses.
|
||||
///
|
||||
/// The resulting hash in both of these cases is always exactly 20
|
||||
/// bytes.
|
||||
/// <https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address>
|
||||
#[allow(dead_code)]
|
||||
fn hash_payload(bytes: &[u8]) -> [u8; 20] {
|
||||
let sha_hash = Sha256::digest(bytes);
|
||||
let ripe_hash = Ripemd160::digest(sha_hash);
|
||||
let mut payload = [0u8; 20];
|
||||
payload[..].copy_from_slice(&ripe_hash[..]);
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pubkey_mainnet() {
|
||||
let _init_guard = zebra_test::init();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use crate::{block, parameters::NetworkKind, LedgerState};
|
||||
|
||||
|
|
|
@ -95,7 +95,6 @@ mod proptests {
|
|||
use proptest::prelude::*;
|
||||
|
||||
use super::*;
|
||||
use crate::serialization::{ZcashDeserialize, ZcashSerialize};
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Unspent transparent output data structures and functions.
|
||||
|
||||
use std::{collections::HashMap, convert::TryInto};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
block::{self, Block, Height},
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
transparent,
|
||||
};
|
||||
|
||||
use std::{borrow::Borrow, collections::HashMap, convert::TryInto};
|
||||
use std::{borrow::Borrow, collections::HashMap};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use crate::{amount::MAX_MONEY, transaction::Transaction};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
impl Arbitrary for equihash::Solution {
|
||||
type Parameters = ();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
use crate::block;
|
||||
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
impl Arbitrary for CompactDifficulty {
|
||||
type Parameters = ();
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use proptest::{arbitrary::any, prelude::*};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::block;
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
use proptest::{arbitrary::any, prelude::*, test_runner::Config};
|
||||
use proptest::{prelude::*, test_runner::Config};
|
||||
|
||||
use crate::{
|
||||
block::{self, Block},
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use crate::{
|
||||
block::{Block, MAX_BLOCK_BYTES},
|
||||
serialization::{CompactSizeMessage, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||
|
||||
use std::{collections::HashSet, convert::TryFrom};
|
||||
use std::collections::HashSet;
|
||||
|
||||
use zebra_chain::{
|
||||
amount::{Amount, Error, NonNegative},
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
//! Tests for block verification
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
use color_eyre::eyre::{eyre, Report};
|
||||
use once_cell::sync::Lazy;
|
||||
use tower::{buffer::Buffer, util::BoxService};
|
||||
|
||||
use zebra_chain::{
|
||||
amount::{Amount, MAX_MONEY},
|
||||
amount::MAX_MONEY,
|
||||
block::{
|
||||
self,
|
||||
tests::generate::{
|
||||
large_multi_transaction_block, large_single_transaction_block_many_inputs,
|
||||
},
|
||||
Block, Height,
|
||||
},
|
||||
parameters::{Network, NetworkUpgrade},
|
||||
parameters::NetworkUpgrade,
|
||||
serialization::{ZcashDeserialize, ZcashDeserializeInto},
|
||||
transaction::{arbitrary::transaction_to_fake_v5, LockTime, Transaction},
|
||||
work::difficulty::{ParameterDifficulty as _, INVALID_COMPACT_DIFFICULTY},
|
||||
|
|
|
@ -5,8 +5,8 @@ use std::sync::Arc;
|
|||
use num_integer::div_ceil;
|
||||
|
||||
use zebra_chain::{
|
||||
block::{self, Block, HeightDiff, MAX_BLOCK_BYTES},
|
||||
parameters::{Network, Network::*},
|
||||
block::{Block, HeightDiff, MAX_BLOCK_BYTES},
|
||||
parameters::Network::*,
|
||||
serialization::ZcashDeserialize,
|
||||
};
|
||||
use zebra_node_services::constants::{MAX_CHECKPOINT_BYTE_COUNT, MAX_CHECKPOINT_HEIGHT_GAP};
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
//! Tests for checkpoint-based block verification
|
||||
|
||||
use std::{cmp::min, mem::drop, time::Duration};
|
||||
use std::{cmp::min, time::Duration};
|
||||
|
||||
use color_eyre::eyre::{eyre, Report};
|
||||
use futures::{
|
||||
future::TryFutureExt,
|
||||
stream::{FuturesUnordered, StreamExt},
|
||||
};
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use tokio::time::timeout;
|
||||
use tower::{Service, ServiceExt};
|
||||
use tracing_futures::Instrument;
|
||||
|
||||
use zebra_chain::{parameters::Network::*, serialization::ZcashDeserialize};
|
||||
|
|
|
@ -15,7 +15,7 @@ use tokio::sync::watch;
|
|||
use tower::{util::ServiceFn, Service};
|
||||
use tower_batch_control::{Batch, BatchControl};
|
||||
use tower_fallback::Fallback;
|
||||
use zebra_chain::primitives::ed25519::{batch, *};
|
||||
use zebra_chain::primitives::ed25519::*;
|
||||
|
||||
use crate::BoxError;
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::time::Duration;
|
|||
use color_eyre::eyre::{eyre, Report, Result};
|
||||
use futures::stream::{FuturesOrdered, StreamExt};
|
||||
use tower::ServiceExt;
|
||||
use tower_batch_control::Batch;
|
||||
|
||||
use crate::primitives::ed25519::*;
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use crate::groth16::h_sig;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -16,7 +16,7 @@ use tower::{util::ServiceFn, Service};
|
|||
use tower_batch_control::{Batch, BatchControl};
|
||||
use tower_fallback::Fallback;
|
||||
|
||||
use zebra_chain::primitives::redjubjub::{batch, *};
|
||||
use zebra_chain::primitives::redjubjub::*;
|
||||
|
||||
use crate::BoxError;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ use std::time::Duration;
|
|||
use color_eyre::eyre::{eyre, Result};
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use tower::ServiceExt;
|
||||
use tower_batch_control::Batch;
|
||||
|
||||
async fn sign_and_verify<V>(mut verifier: V, n: usize) -> Result<(), V::Error>
|
||||
where
|
||||
|
|
|
@ -7,7 +7,6 @@ use std::time::Duration;
|
|||
use color_eyre::eyre::{eyre, Result};
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use tower::ServiceExt;
|
||||
use tower_batch_control::Batch;
|
||||
|
||||
use zebra_chain::primitives::reddsa::{
|
||||
orchard::{Binding, SpendAuth},
|
||||
|
|
|
@ -4,18 +4,15 @@ use std::{sync::Arc, time::Duration};
|
|||
|
||||
use color_eyre::eyre::Report;
|
||||
use once_cell::sync::Lazy;
|
||||
use tower::{layer::Layer, timeout::TimeoutLayer, Service};
|
||||
use tower::{layer::Layer, timeout::TimeoutLayer};
|
||||
|
||||
use zebra_chain::{
|
||||
block::{self, Block},
|
||||
parameters::Network,
|
||||
block::Block,
|
||||
serialization::{ZcashDeserialize, ZcashDeserializeInto},
|
||||
};
|
||||
use zebra_state as zs;
|
||||
use zebra_test::transcript::{ExpectedTranscriptError, Transcript};
|
||||
|
||||
use crate::Config;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// The timeout we apply to each verify future during testing.
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
future::Future,
|
||||
iter::FromIterator,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
use std::{
|
||||
cmp::Reverse,
|
||||
collections::HashMap,
|
||||
iter::Extend,
|
||||
net::{IpAddr, SocketAddr},
|
||||
sync::{Arc, Mutex},
|
||||
time::Instant,
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::{
|
|||
ffi::OsString,
|
||||
io::{self, ErrorKind},
|
||||
net::{IpAddr, SocketAddr},
|
||||
string::String,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
|
@ -15,7 +14,10 @@ use tempfile::NamedTempFile;
|
|||
use tokio::{fs, io::AsyncWriteExt};
|
||||
use tracing::Span;
|
||||
|
||||
use zebra_chain::parameters::{testnet, Network, NetworkKind};
|
||||
use zebra_chain::parameters::{
|
||||
testnet::{self, ConfiguredActivationHeights},
|
||||
Network, NetworkKind,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
constants::{
|
||||
|
@ -625,12 +627,18 @@ impl<'de> Deserialize<'de> for Config {
|
|||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct DTestnetParameters {
|
||||
#[serde(default)]
|
||||
pub(super) activation_heights: ConfiguredActivationHeights,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
struct DConfig {
|
||||
listen_addr: String,
|
||||
network: NetworkKind,
|
||||
testnet_parameters: Option<testnet::Parameters>,
|
||||
testnet_parameters: Option<DTestnetParameters>,
|
||||
initial_mainnet_peers: IndexSet<String>,
|
||||
initial_testnet_peers: IndexSet<String>,
|
||||
cache_dir: CacheDir,
|
||||
|
@ -669,15 +677,17 @@ impl<'de> Deserialize<'de> for Config {
|
|||
max_connections_per_ip,
|
||||
} = 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!(
|
||||
network_kind,
|
||||
NetworkKind::Testnet,
|
||||
"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 {
|
||||
// Convert to default `Network` for a `NetworkKind` if there are no testnet parameters.
|
||||
match network_kind {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! An address-with-metadata type used in Bitcoin networking.
|
||||
|
||||
use std::{
|
||||
cmp::{max, Ord, Ordering},
|
||||
cmp::{max, Ordering},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::net::IpAddr;
|
||||
|
||||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use zebra_chain::{parameters::Network::*, serialization::DateTime32};
|
||||
|
||||
|
|
|
@ -9,11 +9,7 @@
|
|||
|
||||
use std::{borrow::Cow, collections::HashSet, fmt, pin::Pin, sync::Arc, time::Instant};
|
||||
|
||||
use futures::{
|
||||
future::{self, Either},
|
||||
prelude::*,
|
||||
stream::Stream,
|
||||
};
|
||||
use futures::{future::Either, prelude::*};
|
||||
use rand::{seq::SliceRandom, thread_rng, Rng};
|
||||
use tokio::time::{sleep, Sleep};
|
||||
use tower::{Service, ServiceExt};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Wrapper around handshake logic that also opens a TCP connection.
|
||||
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
|
|
@ -106,7 +106,7 @@ use std::{
|
|||
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
future::{Future, FutureExt, TryFutureExt},
|
||||
future::{FutureExt, TryFutureExt},
|
||||
prelude::*,
|
||||
stream::FuturesUnordered,
|
||||
task::noop_waker,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use proptest::{arbitrary::any, arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use zebra_chain::{block, transaction};
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Randomised property tests for Zebra's Zcash network protocol types.
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use bytes::BytesMut;
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Fixed test vectors for external protocol messages.
|
||||
|
||||
use std::{convert::TryInto, io::Write};
|
||||
use std::io::Write;
|
||||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! Some parts of the `zcashd` RPC documentation are outdated.
|
||||
//! So this implementation follows the `zcashd` server and `lightwalletd` client implementations.
|
||||
|
||||
use std::{collections::HashSet, default::Default, fmt::Debug, sync::Arc};
|
||||
use std::{collections::HashSet, fmt::Debug, sync::Arc};
|
||||
|
||||
use chrono::Utc;
|
||||
use futures::{stream::FuturesOrdered, FutureExt, StreamExt, TryFutureExt};
|
||||
|
|
|
@ -7,14 +7,14 @@ use jsonrpc_core::{self, BoxFuture, Error, ErrorCode, Result};
|
|||
use jsonrpc_derive::rpc;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
||||
use zcash_address::{self, unified::Encoding, TryFromAddress};
|
||||
use zcash_address::{unified::Encoding, TryFromAddress};
|
||||
|
||||
use zebra_chain::{
|
||||
amount::Amount,
|
||||
block::{self, Block, Height, TryIntoHeight},
|
||||
chain_sync_status::ChainSyncStatus,
|
||||
chain_tip::ChainTip,
|
||||
parameters::{Network, POW_AVERAGING_WINDOW},
|
||||
parameters::{Network, NetworkKind, POW_AVERAGING_WINDOW},
|
||||
primitives,
|
||||
serialization::ZcashDeserializeInto,
|
||||
transparent::{
|
||||
|
@ -449,13 +449,25 @@ where
|
|||
) -> Self {
|
||||
// Prevent loss of miner funds due to an unsupported or incorrect address type.
|
||||
if let Some(miner_address) = mining_config.miner_address.clone() {
|
||||
assert_eq!(
|
||||
miner_address.network_kind(),
|
||||
network.kind(),
|
||||
"incorrect miner address config: {miner_address} \
|
||||
network.network {network} and miner address network {} must match",
|
||||
miner_address.network_kind(),
|
||||
);
|
||||
match network.kind() {
|
||||
NetworkKind::Mainnet => assert_eq!(
|
||||
miner_address.network_kind(),
|
||||
NetworkKind::Mainnet,
|
||||
"Incorrect config: Zebra is configured to run on a Mainnet network, \
|
||||
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.
|
||||
|
|
|
@ -227,9 +227,8 @@ fn update_checksum(checksum: &mut u32, item: [u8; 32]) {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToString for LongPollId {
|
||||
/// Exact conversion from LongPollId to a string.
|
||||
fn to_string(&self) -> String {
|
||||
impl std::fmt::Display for LongPollId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let LongPollId {
|
||||
tip_height,
|
||||
tip_hash_checksum,
|
||||
|
@ -240,7 +239,8 @@ impl ToString for LongPollId {
|
|||
|
||||
// We can't do this using `serde`, because it names each field,
|
||||
// but we want a single string containing all the fields.
|
||||
format!(
|
||||
write!(
|
||||
f,
|
||||
// Height as decimal, padded with zeroes to the width of Height::MAX
|
||||
// Checksums as hex, padded with zeroes to the width of u32::MAX
|
||||
// Timestamp as decimal, padded with zeroes to the width of u32::MAX
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! cargo insta test --review -p zebra-rpc --lib -- test_rpc_response_data
|
||||
//! ```
|
||||
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use insta::dynamic_redaction;
|
||||
use tower::buffer::Buffer;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
//! Fixed test vectors for RPC methods.
|
||||
|
||||
use std::{ops::RangeInclusive, sync::Arc};
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use jsonrpc_core::ErrorCode;
|
||||
use tower::buffer::Buffer;
|
||||
|
||||
use zebra_chain::{
|
||||
|
@ -11,8 +10,7 @@ use zebra_chain::{
|
|||
chain_tip::{mock::MockChainTip, NoChainTip},
|
||||
parameters::Network::*,
|
||||
serialization::{ZcashDeserializeInto, ZcashSerialize},
|
||||
transaction::{UnminedTx, UnminedTxId},
|
||||
transparent,
|
||||
transaction::UnminedTxId,
|
||||
};
|
||||
use zebra_node_services::BoxError;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use jsonrpc_core::{Compatibility, MetaIoHandler};
|
|||
use jsonrpc_http_server::{CloseHandle, ServerBuilder};
|
||||
use tokio::task::JoinHandle;
|
||||
use tower::Service;
|
||||
use tracing::{Instrument, *};
|
||||
use tracing::*;
|
||||
|
||||
use zebra_chain::{
|
||||
block, chain_sync_status::ChainSyncStatus, chain_tip::ChainTip, parameters::Network,
|
||||
|
|
|
@ -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
|
||||
// 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 {
|
||||
sapling_commitment_tree_size: sapling_tree_size,
|
||||
// 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();
|
||||
|
||||
zcash_client_backend::scanning::scan_block(
|
||||
&network,
|
||||
network,
|
||||
block_to_compact(block, chain_metadata),
|
||||
scanning_keys.as_slice(),
|
||||
// Ignore whether notes are change from a viewer's own spends for now.
|
||||
|
|
|
@ -277,7 +277,6 @@ impl Drop for CachedFfiTransaction {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex::FromHex;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use zebra_chain::{
|
||||
parameters::{ConsensusBranchId, NetworkUpgrade::*},
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! * the Testnet minimum difficulty adjustment from ZIPs 205 and 208, and
|
||||
//! * `median-time-past`.
|
||||
|
||||
use std::{cmp::max, cmp::min, convert::TryInto};
|
||||
use std::{cmp::max, cmp::min};
|
||||
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Randomised property tests for nullifier contextual validation
|
||||
|
||||
use std::{convert::TryInto, env, sync::Arc};
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
use itertools::Itertools;
|
||||
use proptest::prelude::*;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Fixed test vectors for state contextual validation checks.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use zebra_chain::serialization::ZcashDeserializeInto;
|
||||
|
||||
use super::super::*;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Randomised proptests for scanner database formats.
|
||||
|
||||
use proptest::{arbitrary::any, prelude::*};
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::{
|
||||
service::finalized_state::arbitrary::assert_value_properties, SaplingScannedDatabaseIndex,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Randomised tests for the finalized disk format.
|
||||
|
||||
use proptest::{arbitrary::any, prelude::*};
|
||||
use proptest::prelude::*;
|
||||
|
||||
use zebra_chain::{
|
||||
amount::{Amount, NonNegative},
|
||||
|
|
|
@ -636,13 +636,11 @@ impl Chain {
|
|||
.next()
|
||||
.expect("Zebra should never reach the max height in normal operation.");
|
||||
|
||||
if self.sprout_trees_by_height.get(&next_height).is_none() {
|
||||
// TODO: Use `try_insert` once it stabilises.
|
||||
self.sprout_trees_by_height.insert(
|
||||
next_height,
|
||||
highest_removed_tree.expect("There should be a cached removed tree."),
|
||||
);
|
||||
}
|
||||
self.sprout_trees_by_height
|
||||
.entry(next_height)
|
||||
.or_insert_with(|| {
|
||||
highest_removed_tree.expect("There should be a cached removed tree.")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -839,13 +837,11 @@ impl Chain {
|
|||
.next()
|
||||
.expect("Zebra should never reach the max height in normal operation.");
|
||||
|
||||
if self.sapling_trees_by_height.get(&next_height).is_none() {
|
||||
// TODO: Use `try_insert` once it stabilises.
|
||||
self.sapling_trees_by_height.insert(
|
||||
next_height,
|
||||
highest_removed_tree.expect("There should be a cached removed tree."),
|
||||
);
|
||||
}
|
||||
self.sapling_trees_by_height
|
||||
.entry(next_height)
|
||||
.or_insert_with(|| {
|
||||
highest_removed_tree.expect("There should be a cached removed tree.")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1048,13 +1044,11 @@ impl Chain {
|
|||
.next()
|
||||
.expect("Zebra should never reach the max height in normal operation.");
|
||||
|
||||
if self.orchard_trees_by_height.get(&next_height).is_none() {
|
||||
// TODO: Use `try_insert` once it stabilises.
|
||||
self.orchard_trees_by_height.insert(
|
||||
next_height,
|
||||
highest_removed_tree.expect("There should be a cached removed tree."),
|
||||
);
|
||||
}
|
||||
self.orchard_trees_by_height
|
||||
.entry(next_height)
|
||||
.or_insert_with(|| {
|
||||
highest_removed_tree.expect("There should be a cached removed tree.")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use zebra_chain::{
|
|||
fmt::DisplayToDebug,
|
||||
history_tree::{HistoryTree, NonEmptyHistoryTree},
|
||||
parameters::NetworkUpgrade::*,
|
||||
parameters::{Network, *},
|
||||
parameters::*,
|
||||
value_balance::ValueBalance,
|
||||
LedgerState,
|
||||
};
|
||||
|
@ -611,15 +611,15 @@ fn different_blocks_different_chains() -> Result<()> {
|
|||
|
||||
// blocks, heights, hashes
|
||||
chain1.blocks = chain2.blocks.clone();
|
||||
chain1.height_by_hash = chain2.height_by_hash.clone();
|
||||
chain1.tx_loc_by_hash = chain2.tx_loc_by_hash.clone();
|
||||
chain1.height_by_hash.clone_from(&chain2.height_by_hash);
|
||||
chain1.tx_loc_by_hash.clone_from(&chain2.tx_loc_by_hash);
|
||||
|
||||
// transparent UTXOs
|
||||
chain1.created_utxos = chain2.created_utxos.clone();
|
||||
chain1.spent_utxos = chain2.spent_utxos.clone();
|
||||
chain1.created_utxos.clone_from(&chain2.created_utxos);
|
||||
chain1.spent_utxos.clone_from(&chain2.spent_utxos);
|
||||
|
||||
// note commitment trees
|
||||
chain1.sprout_trees_by_anchor = chain2.sprout_trees_by_anchor.clone();
|
||||
chain1.sprout_trees_by_anchor.clone_from(&chain2.sprout_trees_by_anchor);
|
||||
chain1.sprout_trees_by_height = chain2.sprout_trees_by_height.clone();
|
||||
chain1.sapling_trees_by_height = chain2.sapling_trees_by_height.clone();
|
||||
chain1.orchard_trees_by_height = chain2.orchard_trees_by_height.clone();
|
||||
|
@ -640,9 +640,9 @@ fn different_blocks_different_chains() -> Result<()> {
|
|||
chain1.orchard_anchors_by_height = chain2.orchard_anchors_by_height.clone();
|
||||
|
||||
// nullifiers
|
||||
chain1.sprout_nullifiers = chain2.sprout_nullifiers.clone();
|
||||
chain1.sapling_nullifiers = chain2.sapling_nullifiers.clone();
|
||||
chain1.orchard_nullifiers = chain2.orchard_nullifiers.clone();
|
||||
chain1.sprout_nullifiers.clone_from(&chain2.sprout_nullifiers);
|
||||
chain1.sapling_nullifiers.clone_from(&chain2.sapling_nullifiers);
|
||||
chain1.orchard_nullifiers.clone_from(&chain2.orchard_nullifiers);
|
||||
|
||||
// proof of work
|
||||
chain1.partial_cumulative_work = chain2.partial_cumulative_work;
|
||||
|
|
|
@ -966,6 +966,7 @@ impl<Request, Response, Error> ResponseSender<Request, Response, Error> {
|
|||
///
|
||||
/// - [`PanicAssertion`]
|
||||
/// - [`PropTestAssertion`]
|
||||
#[allow(dead_code)]
|
||||
trait AssertionType {}
|
||||
|
||||
/// Represents normal Rust assertions that panic, like [`assert_eq`].
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use hex::FromHex;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use std::{collections::BTreeMap, convert::TryInto};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
trait ReverseCollection {
|
||||
/// Return a reversed copy of this collection
|
||||
|
|
|
@ -48,10 +48,6 @@ async fn self_check() {
|
|||
assert!(t1.check(t2).await.is_ok());
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("Error")]
|
||||
struct Error;
|
||||
|
||||
const TRANSCRIPT_DATA2: [(&str, Result<&str, ExpectedTranscriptError>); 4] = [
|
||||
("req1", Ok("rsp1")),
|
||||
("req2", Ok("rsp2")),
|
||||
|
|
|
@ -41,15 +41,13 @@ use zebra_scan::{storage::Storage, Config};
|
|||
/// - The transaction fetched via RPC cannot be deserialized from raw bytes.
|
||||
#[allow(clippy::print_stdout)]
|
||||
pub fn main() {
|
||||
// TODO: Implement `zcash_primitives::consensus::Parameters` for `Network` and remove this variable (#8365).
|
||||
let network = zcash_primitives::consensus::Network::MainNetwork;
|
||||
let zebra_network = zebra_chain::parameters::Network::Mainnet;
|
||||
let storage = Storage::new(&Config::default(), &zebra_network, true);
|
||||
let network = zebra_chain::parameters::Network::Mainnet;
|
||||
let storage = Storage::new(&Config::default(), &network, true);
|
||||
// If the first memo is empty, it doesn't get printed. But we never print empty memos anyway.
|
||||
let mut prev_memo = "".to_owned();
|
||||
|
||||
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")
|
||||
.0
|
||||
.into_iter()
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
use std::{cmp::min, path::PathBuf};
|
||||
|
||||
use abscissa_core::{config, Command, FrameworkError, Runnable};
|
||||
use abscissa_core::{config, Command, FrameworkError};
|
||||
use color_eyre::eyre::{eyre, Report};
|
||||
use tokio::time::Instant;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
//!
|
||||
//! Some of the diagnostic features are optional, and need to be enabled at compile-time.
|
||||
|
||||
use abscissa_core::{config, Command, FrameworkError, Runnable};
|
||||
use abscissa_core::{config, Command, FrameworkError};
|
||||
use color_eyre::eyre::{eyre, Report};
|
||||
use futures::FutureExt;
|
||||
use tokio::{pin, select, sync::oneshot};
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
//! Inbound service tests with a fake peer set.
|
||||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
iter::{self, FromIterator},
|
||||
net::SocketAddr,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{collections::HashSet, iter, net::SocketAddr, str::FromStr, sync::Arc, time::Duration};
|
||||
|
||||
use futures::FutureExt;
|
||||
use tokio::{sync::oneshot, task::JoinHandle, time::timeout};
|
||||
|
|
|
@ -8,11 +8,10 @@ use zebra_chain::{
|
|||
amount::Amount,
|
||||
block::{Block, Height},
|
||||
parameters::Network,
|
||||
transaction::{UnminedTxId, VerifiedUnminedTx},
|
||||
};
|
||||
|
||||
use crate::components::mempool::{
|
||||
config, storage::tests::unmined_transactions_in_blocks, storage::*, Mempool,
|
||||
storage::tests::unmined_transactions_in_blocks, storage::*, Mempool,
|
||||
};
|
||||
|
||||
/// Eviction memory time used for tests. Most tests won't care about this
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Fixed test vectors for the mempool.
|
||||
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use color_eyre::Report;
|
||||
use tokio::time::{self, timeout};
|
||||
|
@ -15,12 +15,10 @@ use zebra_state::{Config as StateConfig, CHAIN_TIP_UPDATE_WAIT_LIMIT};
|
|||
use zebra_test::mock_service::{MockService, PanicAssertion};
|
||||
|
||||
use crate::components::{
|
||||
mempool::{self, storage::tests::unmined_transactions_in_blocks, *},
|
||||
mempool::{self, *},
|
||||
sync::RecentSyncLengths,
|
||||
};
|
||||
|
||||
use super::UnboxMempoolError;
|
||||
|
||||
/// A [`MockService`] representing the network service.
|
||||
type MockPeerSet = MockService<zn::Request, zn::Response, PanicAssertion>;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
convert::{self, TryFrom},
|
||||
convert,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use std::{future::Future, time::Duration};
|
||||
|
||||
use abscissa_core::{Application, Component, FrameworkError, Shutdown};
|
||||
use abscissa_core::{Component, FrameworkError, Shutdown};
|
||||
use color_eyre::Report;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ use std::{
|
|||
};
|
||||
|
||||
use color_eyre::{
|
||||
eyre::{eyre, Result, WrapErr},
|
||||
eyre::{eyre, WrapErr},
|
||||
Help,
|
||||
};
|
||||
use semver::Version;
|
||||
|
@ -480,7 +480,7 @@ fn ephemeral(cache_dir_config: EphemeralConfig, cache_dir_check: EphemeralCheck)
|
|||
let ignored_cache_dir = run_dir.path().join("state");
|
||||
if cache_dir_config == EphemeralConfig::MisconfiguredCacheDir {
|
||||
// Write a configuration that sets both the cache_dir and ephemeral options
|
||||
config.state.cache_dir = ignored_cache_dir.clone();
|
||||
config.state.cache_dir.clone_from(&ignored_cache_dir);
|
||||
}
|
||||
if cache_dir_check == EphemeralCheck::ExistingDirectory {
|
||||
// We set the cache_dir config to a newly created empty temp directory,
|
||||
|
@ -922,6 +922,69 @@ fn invalid_generated_config() -> Result<()> {
|
|||
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`.
|
||||
#[tracing::instrument]
|
||||
fn stored_configs_work() -> Result<()> {
|
||||
|
@ -2953,11 +3016,15 @@ fn scan_start_where_left() -> Result<()> {
|
|||
config.shielded_scan.sapling_keys_to_scan = keys;
|
||||
|
||||
// Add the cache dir to shielded scan, make it the same as the zebrad cache state.
|
||||
config.shielded_scan.db_config_mut().cache_dir = cache_dir.clone();
|
||||
config
|
||||
.shielded_scan
|
||||
.db_config_mut()
|
||||
.cache_dir
|
||||
.clone_from(&cache_dir);
|
||||
config.shielded_scan.db_config_mut().ephemeral = false;
|
||||
|
||||
// Add the cache dir to state.
|
||||
config.state.cache_dir = cache_dir.clone();
|
||||
config.state.cache_dir.clone_from(&cache_dir);
|
||||
config.state.ephemeral = false;
|
||||
|
||||
// Remove the scan directory before starting.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue