- Returns early when there is no Heartwood activation height when creating or updating HistoryTree
- Updates `check::legacy_chain()` to accept and compare an optional NU5 activation height - Replaces `.map()` with `.filter_map()` in `NetworkUpgrade::target_spacings()` - Updates some `expect()` messages when unwrapping return value of `NetworkUpgrade.activation_height()` - Adds TODOs for updating `.mandatory_checkpoint_height()` method - Removes TODO for calling `.expect()` when getting NU5 activation height - Updates `Network.sapling_activation_height()` to return None instead of panicking when missing Sapling activation height - Updates calls to `.sapling_activation_height()` to return errors or use `Height(1)` at the minimum birthday height when there's no Sapling activation height
This commit is contained in:
parent
7a756f73c9
commit
301900435b
|
@ -260,8 +260,9 @@ impl Default for LedgerState {
|
||||||
let default_override = LedgerStateOverride::default();
|
let default_override = LedgerStateOverride::default();
|
||||||
|
|
||||||
let most_recent_nu = NetworkUpgrade::current(&default_network, Height::MAX);
|
let most_recent_nu = NetworkUpgrade::current(&default_network, Height::MAX);
|
||||||
let most_recent_activation_height =
|
let most_recent_activation_height = most_recent_nu
|
||||||
most_recent_nu.activation_height(&default_network).unwrap();
|
.activation_height(&default_network)
|
||||||
|
.expect("should have an activation height in default networks");
|
||||||
|
|
||||||
LedgerState {
|
LedgerState {
|
||||||
height: most_recent_activation_height,
|
height: most_recent_activation_height,
|
||||||
|
@ -467,8 +468,10 @@ impl Block {
|
||||||
let current_height = block.coinbase_height().unwrap();
|
let current_height = block.coinbase_height().unwrap();
|
||||||
let heartwood_height = NetworkUpgrade::Heartwood
|
let heartwood_height = NetworkUpgrade::Heartwood
|
||||||
.activation_height(¤t.network)
|
.activation_height(¤t.network)
|
||||||
.unwrap();
|
.expect("should have an activation height in default networks");
|
||||||
let nu5_height = NetworkUpgrade::Nu5.activation_height(¤t.network);
|
let nu5_height = NetworkUpgrade::Nu5
|
||||||
|
.activation_height(¤t.network)
|
||||||
|
.expect("should have an activation height in default networks");
|
||||||
|
|
||||||
match current_height.cmp(&heartwood_height) {
|
match current_height.cmp(&heartwood_height) {
|
||||||
std::cmp::Ordering::Less => {
|
std::cmp::Ordering::Less => {
|
||||||
|
@ -491,7 +494,7 @@ impl Block {
|
||||||
Some(tree) => tree.hash().unwrap_or_else(|| [0u8; 32].into()),
|
Some(tree) => tree.hash().unwrap_or_else(|| [0u8; 32].into()),
|
||||||
None => [0u8; 32].into(),
|
None => [0u8; 32].into(),
|
||||||
};
|
};
|
||||||
if nu5_height.is_some() && current_height >= nu5_height.unwrap() {
|
if current_height >= nu5_height {
|
||||||
// From zebra-state/src/service/check.rs
|
// From zebra-state/src/service/check.rs
|
||||||
let auth_data_root = block.auth_data_root();
|
let auth_data_root = block.auth_data_root();
|
||||||
let hash_block_commitments =
|
let hash_block_commitments =
|
||||||
|
@ -696,7 +699,11 @@ impl Arbitrary for Commitment {
|
||||||
fn arbitrary_with(_args: ()) -> Self::Strategy {
|
fn arbitrary_with(_args: ()) -> Self::Strategy {
|
||||||
(any::<[u8; 32]>(), any::<Network>(), any::<Height>())
|
(any::<[u8; 32]>(), any::<Network>(), any::<Height>())
|
||||||
.prop_map(|(commitment_bytes, network, block_height)| {
|
.prop_map(|(commitment_bytes, network, block_height)| {
|
||||||
if block_height == Heartwood.activation_height(&network).unwrap() {
|
if block_height
|
||||||
|
== Heartwood
|
||||||
|
.activation_height(&network)
|
||||||
|
.expect("should have an activation height in default networks")
|
||||||
|
{
|
||||||
Commitment::ChainHistoryActivationReserved
|
Commitment::ChainHistoryActivationReserved
|
||||||
} else {
|
} else {
|
||||||
Commitment::from_bytes(commitment_bytes, &network, block_height)
|
Commitment::from_bytes(commitment_bytes, &network, block_height)
|
||||||
|
|
|
@ -223,7 +223,7 @@ fn block_test_vectors_height(network: Network) {
|
||||||
if height
|
if height
|
||||||
>= Sapling
|
>= Sapling
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("sapling activation height is set")
|
.expect("sapling activation height is set on default network")
|
||||||
.0
|
.0
|
||||||
{
|
{
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -25,7 +25,7 @@ proptest! {
|
||||||
let (chain_tip, mock_chain_tip_sender) = MockChainTip::new();
|
let (chain_tip, mock_chain_tip_sender) = MockChainTip::new();
|
||||||
let blossom_activation_height = NetworkUpgrade::Blossom
|
let blossom_activation_height = NetworkUpgrade::Blossom
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("Blossom activation height is missing");
|
.expect("Blossom activation height is missing on default network");
|
||||||
|
|
||||||
block_heights.sort();
|
block_heights.sort();
|
||||||
let current_height = block_heights[0];
|
let current_height = block_heights[0];
|
||||||
|
|
|
@ -428,9 +428,11 @@ impl HistoryTree {
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
) -> Result<Self, HistoryTreeError> {
|
) -> Result<Self, HistoryTreeError> {
|
||||||
let heartwood_height = NetworkUpgrade::Heartwood
|
let Some(heartwood_height) = NetworkUpgrade::Heartwood.activation_height(network) else {
|
||||||
.activation_height(network)
|
// Return early if there is no Heartwood activation height.
|
||||||
.expect("Heartwood height is known");
|
return Ok(HistoryTree(None));
|
||||||
|
};
|
||||||
|
|
||||||
match block
|
match block
|
||||||
.coinbase_height()
|
.coinbase_height()
|
||||||
.expect("must have height")
|
.expect("must have height")
|
||||||
|
|
|
@ -35,7 +35,10 @@ fn push_and_prune_for_network_upgrade(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
||||||
|
|
||||||
let height = network_upgrade.activation_height(&network).unwrap().0;
|
let height = network_upgrade
|
||||||
|
.activation_height(&network)
|
||||||
|
.expect("network upgrade activation height is missing on default network")
|
||||||
|
.0;
|
||||||
|
|
||||||
// Load first block (activation block of the given network upgrade)
|
// Load first block (activation block of the given network upgrade)
|
||||||
let first_block = Arc::new(
|
let first_block = Arc::new(
|
||||||
|
@ -118,7 +121,10 @@ fn upgrade() -> Result<()> {
|
||||||
fn upgrade_for_network_upgrade(network: Network, network_upgrade: NetworkUpgrade) -> Result<()> {
|
fn upgrade_for_network_upgrade(network: Network, network_upgrade: NetworkUpgrade) -> Result<()> {
|
||||||
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
||||||
|
|
||||||
let height = network_upgrade.activation_height(&network).unwrap().0;
|
let height = network_upgrade
|
||||||
|
.activation_height(&network)
|
||||||
|
.expect("network upgrade activation height is missing on default network")
|
||||||
|
.0;
|
||||||
|
|
||||||
// Load previous block (the block before the activation block of the given network upgrade)
|
// Load previous block (the block before the activation block of the given network upgrade)
|
||||||
let block_prev = Arc::new(
|
let block_prev = Arc::new(
|
||||||
|
|
|
@ -267,6 +267,12 @@ impl Network {
|
||||||
//
|
//
|
||||||
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - Support constructing pre-Canopy coinbase tx and block templates and return `Height::MAX` instead of panicking
|
||||||
|
// when Canopy activation height is `None` (#8434)
|
||||||
|
// - Add semantic block validation during the ZIP-212 grace period and update this method to return the lesser of
|
||||||
|
// `canopy_activation + ZIP_212_GRACE_PERIOD_DURATION` or the NU5 activation height. (#8430)
|
||||||
|
|
||||||
let canopy_activation = NetworkUpgrade::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");
|
||||||
|
@ -296,10 +302,8 @@ impl Network {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Sapling activation height for this network.
|
/// Returns the Sapling activation height for this network.
|
||||||
pub fn sapling_activation_height(&self) -> Height {
|
pub fn sapling_activation_height(&self) -> Option<Height> {
|
||||||
super::NetworkUpgrade::Sapling
|
super::NetworkUpgrade::Sapling.activation_height(self)
|
||||||
.activation_height(self)
|
|
||||||
.expect("Sapling activation height needs to be set")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ proptest! {
|
||||||
|
|
||||||
let canopy_activation = NetworkUpgrade::Canopy
|
let canopy_activation = NetworkUpgrade::Canopy
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is set");
|
.expect("Canopy activation height is set on default networks");
|
||||||
|
|
||||||
let grace_period_end_height = (canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
let grace_period_end_height = (canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
||||||
.expect("ZIP-212 grace period ends in a valid block height");
|
.expect("ZIP-212 grace period ends in a valid block height");
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn activates_network_upgrades_correctly() {
|
||||||
|
|
||||||
let genesis_activation_height = NetworkUpgrade::Genesis
|
let genesis_activation_height = NetworkUpgrade::Genesis
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("must return an activation height");
|
.expect("must always return an activation height for Genesis network upgrade");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
genesis_activation_height,
|
genesis_activation_height,
|
||||||
|
@ -123,7 +123,7 @@ fn activates_network_upgrades_correctly() {
|
||||||
for nu in NETWORK_UPGRADES_IN_ORDER.into_iter().skip(1) {
|
for nu in NETWORK_UPGRADES_IN_ORDER.into_iter().skip(1) {
|
||||||
let activation_height = nu
|
let activation_height = nu
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("must return an activation height");
|
.expect("must return an activation height for all network upgrades when there's an NU5 activation height");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
activation_height, Height(expected_activation_height),
|
activation_height, Height(expected_activation_height),
|
||||||
|
|
|
@ -402,14 +402,10 @@ impl NetworkUpgrade {
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |(upgrade, spacing_seconds)| {
|
.filter_map(move |(upgrade, spacing_seconds)| {
|
||||||
let activation_height = upgrade
|
let activation_height = upgrade.activation_height(network)?;
|
||||||
.activation_height(network)
|
|
||||||
.expect("missing activation height for target spacing change");
|
|
||||||
|
|
||||||
let target_spacing = Duration::seconds(spacing_seconds);
|
let target_spacing = Duration::seconds(spacing_seconds);
|
||||||
|
Some((activation_height, target_spacing))
|
||||||
(activation_height, target_spacing)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn activation_consistent(network: Network) {
|
||||||
for &network_upgrade in network_upgrades {
|
for &network_upgrade in network_upgrades {
|
||||||
let height = network_upgrade
|
let height = network_upgrade
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("activations must have a height");
|
.expect("activations must have a height on default networks");
|
||||||
assert!(NetworkUpgrade::is_activation_height(&network, height));
|
assert!(NetworkUpgrade::is_activation_height(&network, height));
|
||||||
|
|
||||||
if height > block::Height(0) {
|
if height > block::Height(0) {
|
||||||
|
|
|
@ -21,7 +21,10 @@ fn tree() -> Result<()> {
|
||||||
fn tree_for_network_upgrade(network: &Network, network_upgrade: NetworkUpgrade) -> Result<()> {
|
fn tree_for_network_upgrade(network: &Network, network_upgrade: NetworkUpgrade) -> Result<()> {
|
||||||
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
||||||
|
|
||||||
let height = network_upgrade.activation_height(network).unwrap().0;
|
let height = network_upgrade
|
||||||
|
.activation_height(network)
|
||||||
|
.expect("must have activation height on default network")
|
||||||
|
.0;
|
||||||
|
|
||||||
// Load Block 0 (activation block of the given network upgrade)
|
// Load Block 0 (activation block of the given network upgrade)
|
||||||
let block0 = Arc::new(
|
let block0 = Arc::new(
|
||||||
|
|
|
@ -62,7 +62,7 @@ fn incremental_roots_with_blocks_for_network(network: Network) -> Result<()> {
|
||||||
|
|
||||||
let height = NetworkUpgrade::Sapling
|
let height = NetworkUpgrade::Sapling
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.unwrap()
|
.expect("must have activation height on default network")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
// Build empty note commitment tree
|
// Build empty note commitment tree
|
||||||
|
|
|
@ -92,7 +92,7 @@ fn incremental_roots_with_blocks_for_network(network: Network) -> Result<()> {
|
||||||
// Load the Genesis height.
|
// Load the Genesis height.
|
||||||
let genesis_height = NetworkUpgrade::Genesis
|
let genesis_height = NetworkUpgrade::Genesis
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.unwrap()
|
.expect("must have activation height on default network")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
// Load the Genesis block.
|
// Load the Genesis block.
|
||||||
|
|
|
@ -352,7 +352,7 @@ fn fake_v5_round_trip_for_network(network: Network) {
|
||||||
|
|
||||||
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("a valid height")
|
.expect("must have activation height on default network")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
// skip blocks that are before overwinter as they will not have a valid consensus branch id
|
// skip blocks that are before overwinter as they will not have a valid consensus branch id
|
||||||
|
@ -500,7 +500,7 @@ fn fake_v5_librustzcash_round_trip_for_network(network: Network) {
|
||||||
|
|
||||||
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
||||||
.activation_height(&network)
|
.activation_height(&network)
|
||||||
.expect("a valid height")
|
.expect("must have activation height on default network")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
let nu5_activation_height = NetworkUpgrade::Nu5
|
let nu5_activation_height = NetworkUpgrade::Nu5
|
||||||
|
|
|
@ -155,7 +155,7 @@ pub fn subsidy_is_valid(block: &Block, network: &Network) -> Result<(), BlockErr
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(network)
|
||||||
.expect("Canopy activation height is known");
|
.expect("Canopy activation height is required for semantic block validation");
|
||||||
|
|
||||||
if height < SLOW_START_INTERVAL {
|
if height < SLOW_START_INTERVAL {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
|
|
|
@ -25,7 +25,9 @@ pub fn funding_stream_values(
|
||||||
height: Height,
|
height: Height,
|
||||||
network: &Network,
|
network: &Network,
|
||||||
) -> Result<HashMap<FundingStreamReceiver, Amount<NonNegative>>, Error> {
|
) -> Result<HashMap<FundingStreamReceiver, Amount<NonNegative>>, Error> {
|
||||||
let canopy_height = Canopy.activation_height(network).unwrap();
|
let canopy_height = Canopy
|
||||||
|
.activation_height(network)
|
||||||
|
.expect("requires Canopy activation height");
|
||||||
let mut results = HashMap::new();
|
let mut results = HashMap::new();
|
||||||
|
|
||||||
if height >= canopy_height {
|
if height >= canopy_height {
|
||||||
|
|
|
@ -230,7 +230,7 @@ impl ParameterSubsidy for Network {
|
||||||
match self {
|
match self {
|
||||||
Network::Mainnet => NetworkUpgrade::Canopy
|
Network::Mainnet => NetworkUpgrade::Canopy
|
||||||
.activation_height(self)
|
.activation_height(self)
|
||||||
.expect("canopy activation height should be available"),
|
.expect("Canopy activation height should be available"),
|
||||||
// TODO: Check what zcashd does here, consider adding a field to `testnet::Parameters` to make this configurable.
|
// TODO: Check what zcashd does here, consider adding a field to `testnet::Parameters` to make this configurable.
|
||||||
Network::Testnet(_params) => FIRST_HALVING_TESTNET,
|
Network::Testnet(_params) => FIRST_HALVING_TESTNET,
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,7 +356,6 @@ pub fn coinbase_expiry_height(
|
||||||
) -> Result<(), TransactionError> {
|
) -> Result<(), TransactionError> {
|
||||||
let expiry_height = coinbase.expiry_height();
|
let expiry_height = coinbase.expiry_height();
|
||||||
|
|
||||||
// TODO: replace `if let` with `expect` after NU5 mainnet activation
|
|
||||||
if let Some(nu5_activation_height) = NetworkUpgrade::Nu5.activation_height(network) {
|
if let Some(nu5_activation_height) = NetworkUpgrade::Nu5.activation_height(network) {
|
||||||
// # Consensus
|
// # Consensus
|
||||||
//
|
//
|
||||||
|
|
|
@ -88,7 +88,9 @@ async fn test_mocked_rpc_response_data_for_network(network: Network, random_port
|
||||||
.expect_request_that(|req| matches!(req, ScanRequest::Info))
|
.expect_request_that(|req| matches!(req, ScanRequest::Info))
|
||||||
.await
|
.await
|
||||||
.respond(ScanResponse::Info {
|
.respond(ScanResponse::Info {
|
||||||
min_sapling_birthday_height: network.sapling_activation_height(),
|
min_sapling_birthday_height: network
|
||||||
|
.sapling_activation_height()
|
||||||
|
.expect("must have Sapling activation height for default network"),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,10 @@ async fn test_mocked_getinfo_for_network(
|
||||||
// test the response
|
// test the response
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_info_response.into_inner().min_sapling_birthday_height,
|
get_info_response.into_inner().min_sapling_birthday_height,
|
||||||
network.sapling_activation_height().0,
|
network
|
||||||
|
.sapling_activation_height()
|
||||||
|
.expect("must have Sapling activation height for default network")
|
||||||
|
.0,
|
||||||
"get_info response min sapling height should match network sapling activation height"
|
"get_info response min sapling height should match network sapling activation height"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -396,7 +399,9 @@ async fn call_get_info(
|
||||||
.expect_request_that(|req| matches!(req, ScanRequest::Info))
|
.expect_request_that(|req| matches!(req, ScanRequest::Info))
|
||||||
.await
|
.await
|
||||||
.respond(ScanResponse::Info {
|
.respond(ScanResponse::Info {
|
||||||
min_sapling_birthday_height: network.sapling_activation_height(),
|
min_sapling_birthday_height: network
|
||||||
|
.sapling_activation_height()
|
||||||
|
.expect("must have Sapling activation height for default network"),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,10 @@ impl Service<Request> for ScanService {
|
||||||
|
|
||||||
return async move {
|
return async move {
|
||||||
Ok(Response::Info {
|
Ok(Response::Info {
|
||||||
min_sapling_birthday_height: db.network().sapling_activation_height(),
|
min_sapling_birthday_height: db
|
||||||
|
.network()
|
||||||
|
.sapling_activation_height()
|
||||||
|
.ok_or("missing Sapling activation height")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
|
@ -78,7 +78,9 @@ impl ScanTask {
|
||||||
let mut new_keys = HashMap::new();
|
let mut new_keys = HashMap::new();
|
||||||
let mut new_result_senders = HashMap::new();
|
let mut new_result_senders = HashMap::new();
|
||||||
let mut new_result_receivers = Vec::new();
|
let mut new_result_receivers = Vec::new();
|
||||||
let sapling_activation_height = network.sapling_activation_height();
|
let sapling_activation_height = network.sapling_activation_height().ok_or(eyre!(
|
||||||
|
"must have Sapling activation height for default network"
|
||||||
|
))?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let cmd = match cmd_receiver.try_recv() {
|
let cmd = match cmd_receiver.try_recv() {
|
||||||
|
|
|
@ -79,7 +79,9 @@ pub async fn start(
|
||||||
mut cmd_receiver: tokio::sync::mpsc::Receiver<ScanTaskCommand>,
|
mut cmd_receiver: tokio::sync::mpsc::Receiver<ScanTaskCommand>,
|
||||||
) -> Result<(), Report> {
|
) -> Result<(), Report> {
|
||||||
let network = storage.network();
|
let network = storage.network();
|
||||||
let sapling_activation_height = network.sapling_activation_height();
|
let sapling_activation_height = network
|
||||||
|
.sapling_activation_height()
|
||||||
|
.ok_or(eyre!("missing Sapling activation height"))?;
|
||||||
|
|
||||||
info!(?network, "starting scan task");
|
info!(?network, "starting scan task");
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
scan::{get_min_height, scan_height_and_store_results, wait_for_height, State, CHECK_INTERVAL},
|
scan::{get_min_height, scan_height_and_store_results, wait_for_height, State, CHECK_INTERVAL},
|
||||||
storage::Storage,
|
storage::Storage,
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::Report;
|
use color_eyre::eyre::{eyre, Report};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::{mpsc::Sender, watch},
|
sync::{mpsc::Sender, watch},
|
||||||
task::JoinHandle,
|
task::JoinHandle,
|
||||||
|
@ -88,7 +88,10 @@ pub async fn scan_range(
|
||||||
storage: Storage,
|
storage: Storage,
|
||||||
subscribed_keys_receiver: watch::Receiver<Arc<HashMap<String, Sender<ScanResult>>>>,
|
subscribed_keys_receiver: watch::Receiver<Arc<HashMap<String, Sender<ScanResult>>>>,
|
||||||
) -> Result<(), Report> {
|
) -> Result<(), Report> {
|
||||||
let sapling_activation_height = storage.network().sapling_activation_height();
|
let sapling_activation_height = storage
|
||||||
|
.network()
|
||||||
|
.sapling_activation_height()
|
||||||
|
.ok_or(eyre!("missing Sapling activation height"))?;
|
||||||
// Do not scan and notify if we are below sapling activation height.
|
// Do not scan and notify if we are below sapling activation height.
|
||||||
wait_for_height(
|
wait_for_height(
|
||||||
sapling_activation_height,
|
sapling_activation_height,
|
||||||
|
|
|
@ -213,7 +213,10 @@ impl Storage {
|
||||||
sapling_key: &SaplingScanningKey,
|
sapling_key: &SaplingScanningKey,
|
||||||
birthday_height: Option<Height>,
|
birthday_height: Option<Height>,
|
||||||
) {
|
) {
|
||||||
let min_birthday_height = self.network().sapling_activation_height();
|
let min_birthday_height = self
|
||||||
|
.network()
|
||||||
|
.sapling_activation_height()
|
||||||
|
.unwrap_or(Height(1));
|
||||||
|
|
||||||
// The birthday height must be at least the minimum height for that pool.
|
// The birthday height must be at least the minimum height for that pool.
|
||||||
let birthday_height = birthday_height
|
let birthday_height = birthday_height
|
||||||
|
|
|
@ -170,7 +170,9 @@ fn scanning_fake_blocks_store_key_and_results() -> Result<()> {
|
||||||
.expect("height is stored")
|
.expect("height is stored")
|
||||||
.next()
|
.next()
|
||||||
.expect("height is not maximum"),
|
.expect("height is not maximum"),
|
||||||
network.sapling_activation_height()
|
network
|
||||||
|
.sapling_activation_height()
|
||||||
|
.expect("should have Sapling activation height on default networks")
|
||||||
);
|
);
|
||||||
|
|
||||||
let nf = Nullifier([7; 32]);
|
let nf = Nullifier([7; 32]);
|
||||||
|
|
|
@ -423,9 +423,7 @@ impl StateService {
|
||||||
let timer = CodeTimer::start();
|
let timer = CodeTimer::start();
|
||||||
|
|
||||||
if let Some(tip) = state.best_tip() {
|
if let Some(tip) = state.best_tip() {
|
||||||
let nu5_activation_height = NetworkUpgrade::Nu5
|
let nu5_activation_height = NetworkUpgrade::Nu5.activation_height(network);
|
||||||
.activation_height(network)
|
|
||||||
.expect("NU5 activation height is set");
|
|
||||||
|
|
||||||
if let Err(error) = check::legacy_chain(
|
if let Err(error) = check::legacy_chain(
|
||||||
nu5_activation_height,
|
nu5_activation_height,
|
||||||
|
|
|
@ -306,7 +306,7 @@ fn difficulty_threshold_and_time_are_valid(
|
||||||
/// `max_legacy_chain_blocks` should be [`MAX_LEGACY_CHAIN_BLOCKS`](crate::constants::MAX_LEGACY_CHAIN_BLOCKS).
|
/// `max_legacy_chain_blocks` should be [`MAX_LEGACY_CHAIN_BLOCKS`](crate::constants::MAX_LEGACY_CHAIN_BLOCKS).
|
||||||
/// They are only changed from the defaults for testing.
|
/// They are only changed from the defaults for testing.
|
||||||
pub(crate) fn legacy_chain<I>(
|
pub(crate) fn legacy_chain<I>(
|
||||||
nu5_activation_height: block::Height,
|
nu5_activation_height: Option<block::Height>,
|
||||||
ancestors: I,
|
ancestors: I,
|
||||||
network: &Network,
|
network: &Network,
|
||||||
max_legacy_chain_blocks: usize,
|
max_legacy_chain_blocks: usize,
|
||||||
|
@ -323,11 +323,7 @@ where
|
||||||
//
|
//
|
||||||
// If the cached tip is close to NU5 activation, but there aren't any V5 transactions in the
|
// If the cached tip is close to NU5 activation, but there aren't any V5 transactions in the
|
||||||
// chain yet, we could reach MAX_BLOCKS_TO_CHECK in Canopy, and incorrectly return an error.
|
// chain yet, we could reach MAX_BLOCKS_TO_CHECK in Canopy, and incorrectly return an error.
|
||||||
if block
|
if block.coinbase_height() < nu5_activation_height {
|
||||||
.coinbase_height()
|
|
||||||
.expect("valid blocks have coinbase heights")
|
|
||||||
< nu5_activation_height
|
|
||||||
{
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -306,7 +306,7 @@ proptest! {
|
||||||
fn some_block_less_than_network_upgrade(
|
fn some_block_less_than_network_upgrade(
|
||||||
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(4, true, UNDER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
|
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(4, true, UNDER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
|
||||||
) {
|
) {
|
||||||
let response = crate::service::check::legacy_chain(nu_activation_height, chain.into_iter().rev(), &network, TEST_LEGACY_CHAIN_LIMIT)
|
let response = crate::service::check::legacy_chain(Some(nu_activation_height), chain.into_iter().rev(), &network, TEST_LEGACY_CHAIN_LIMIT)
|
||||||
.map_err(|error| error.to_string());
|
.map_err(|error| error.to_string());
|
||||||
|
|
||||||
prop_assert_eq!(response, Ok(()));
|
prop_assert_eq!(response, Ok(()));
|
||||||
|
@ -323,7 +323,7 @@ proptest! {
|
||||||
.coinbase_height()
|
.coinbase_height()
|
||||||
.expect("chain contains valid blocks");
|
.expect("chain contains valid blocks");
|
||||||
|
|
||||||
let response = crate::service::check::legacy_chain(nu_activation_height, chain.into_iter().rev(), &network, TEST_LEGACY_CHAIN_LIMIT)
|
let response = crate::service::check::legacy_chain(Some(nu_activation_height), chain.into_iter().rev(), &network, TEST_LEGACY_CHAIN_LIMIT)
|
||||||
.map_err(|error| error.to_string());
|
.map_err(|error| error.to_string());
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
|
@ -360,7 +360,7 @@ proptest! {
|
||||||
);
|
);
|
||||||
|
|
||||||
let response = crate::service::check::legacy_chain(
|
let response = crate::service::check::legacy_chain(
|
||||||
nu_activation_height,
|
Some(nu_activation_height),
|
||||||
chain.clone().into_iter().rev(),
|
chain.clone().into_iter().rev(),
|
||||||
&network,
|
&network,
|
||||||
TEST_LEGACY_CHAIN_LIMIT,
|
TEST_LEGACY_CHAIN_LIMIT,
|
||||||
|
@ -380,7 +380,7 @@ proptest! {
|
||||||
fn at_least_one_transaction_with_valid_network_upgrade(
|
fn at_least_one_transaction_with_valid_network_upgrade(
|
||||||
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(5, true, UNDER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
|
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(5, true, UNDER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
|
||||||
) {
|
) {
|
||||||
let response = crate::service::check::legacy_chain(nu_activation_height, chain.into_iter().rev(), &network, TEST_LEGACY_CHAIN_LIMIT)
|
let response = crate::service::check::legacy_chain(Some(nu_activation_height), chain.into_iter().rev(), &network, TEST_LEGACY_CHAIN_LIMIT)
|
||||||
.map_err(|error| error.to_string());
|
.map_err(|error| error.to_string());
|
||||||
|
|
||||||
prop_assert_eq!(response, Ok(()));
|
prop_assert_eq!(response, Ok(()));
|
||||||
|
|
Loading…
Reference in New Issue