change(chain): Remove `Copy` trait impl from `Network` (#8354)
* removed derive copy from network, address and ledgerstate * changed is_max_block_time_enforced to accept ref * changed NetworkUpgrade::Current to accept ref * changed NetworkUpgrade::Next to accept ref * changed NetworkUpgrade::IsActivationHeight to accept ref * changed NetworkUpgrade::TargetSpacingForHeight to accept ref * changed NetworkUpgrade::TargetSpacings to accept ref * changed NetworkUpgrade::MinimumDifficultySpacing_forHeight to accept ref * changed NetworkUpgrade::IsTestnetMinDifficultyBlock to accept ref * changed NetworkUpgrade::AveragingWindowTimespanForHeight to accept ref * changed NetworkUpgrade::ActivationHeight to accept ref * changed sapling_activation_height to accept ref * fixed lifetime for target_spacings * fixed sapling_activation_height * changed transaction_to_fake_v5 and fake_v5_transactions_for_network to accept ref to network * changed Input::vec_strategy to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_history.rs to accept ref to network * changed functions in zebra-chain/src/history_tree.rs to accept ref to network * changed functions in zebra-chain/src/history_tree.rs to accept ref to network * changed functions in zebra-chain/src/primitives/address.rs to accept ref to network * changed functions in zebra-chain/src/primitives/viewing_key* to accept ref to network * changed functions in zebra-chain/src/transparent/address.rs to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_primitives.rs to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_note_encryption.rs to accept ref to network * changed functions in zebra-chain/src/primitives/history_tree* to accept ref to network * changed functions in zebra-chain/src/block* to accept ref to network * fixed errors in zebra-chain::parameters::network * fixed errors in zebra-chain::parameters::network * fixed errors in zebra-chain * changed NonEmptyHistoryTree and InnerHistoryTree to hold value instead of ref * changed NonEmptyHistoryTree and InnerHistoryTree to hold value instead of ref * fixed errors in zebra-chain/src/block/arbitrary.rs * finished fixing errors in zebra-chain - all crate tests pass * changed functions in zebra-state::service::finalized_state to accept &Network * changed functions in zebra-state::service::non_finalized_state to accept &Network * zebra-state tests run but fail with overflow error * zebra-state tests all pass * converted zebra-network -- all crate tests pass * applied all requested changes from review * converted zebra-consensus -- all crate tests pass * converted zebra-scan -- all crate tests pass * converted zebra-rpc -- all crate tests pass * converted zebra-grpc -- all crate tests pass * converted zebrad -- all crate tests pass * applied all requested changes from review * fixed all clippy errors * fixed build error in zebrad/src/components/mempool/crawler.rs
This commit is contained in:
parent
0c77b40ccc
commit
4579722833
|
@ -98,7 +98,7 @@ impl Block {
|
||||||
///
|
///
|
||||||
/// Returns an error if this block does not have a block height,
|
/// Returns an error if this block does not have a block height,
|
||||||
/// or if the commitment value is structurally invalid.
|
/// or if the commitment value is structurally invalid.
|
||||||
pub fn commitment(&self, network: Network) -> Result<Commitment, CommitmentError> {
|
pub fn commitment(&self, network: &Network) -> Result<Commitment, CommitmentError> {
|
||||||
match self.coinbase_height() {
|
match self.coinbase_height() {
|
||||||
None => Err(CommitmentError::MissingBlockHeight {
|
None => Err(CommitmentError::MissingBlockHeight {
|
||||||
block_hash: self.hash(),
|
block_hash: self.hash(),
|
||||||
|
@ -121,7 +121,7 @@ impl Block {
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn check_transaction_network_upgrade_consistency(
|
pub fn check_transaction_network_upgrade_consistency(
|
||||||
&self,
|
&self,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Result<(), error::BlockError> {
|
) -> Result<(), error::BlockError> {
|
||||||
let block_nu =
|
let block_nu =
|
||||||
NetworkUpgrade::current(network, self.coinbase_height().expect("a valid height"));
|
NetworkUpgrade::current(network, self.coinbase_height().expect("a valid height"));
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl Arbitrary for Height {
|
||||||
type Strategy = BoxedStrategy<Self>;
|
type Strategy = BoxedStrategy<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
/// The configuration data for proptest when generating arbitrary chains
|
/// The configuration data for proptest when generating arbitrary chains
|
||||||
pub struct LedgerState {
|
pub struct LedgerState {
|
||||||
|
@ -245,7 +245,7 @@ impl LedgerState {
|
||||||
if let Some(network_upgrade_override) = self.network_upgrade_override {
|
if let Some(network_upgrade_override) = self.network_upgrade_override {
|
||||||
network_upgrade_override
|
network_upgrade_override
|
||||||
} else {
|
} else {
|
||||||
NetworkUpgrade::current(self.network, self.height)
|
NetworkUpgrade::current(&self.network, self.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,9 +268,9 @@ impl Default for LedgerState {
|
||||||
let default_network = Network::default();
|
let default_network = Network::default();
|
||||||
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.activation_height(default_network).unwrap();
|
most_recent_nu.activation_height(&default_network).unwrap();
|
||||||
|
|
||||||
LedgerState {
|
LedgerState {
|
||||||
height: most_recent_activation_height,
|
height: most_recent_activation_height,
|
||||||
|
@ -290,7 +290,7 @@ impl Default for LedgerStateOverride {
|
||||||
let default_network = Network::default();
|
let default_network = Network::default();
|
||||||
|
|
||||||
// TODO: dynamically select any future network upgrade (#1974)
|
// TODO: dynamically select any future network upgrade (#1974)
|
||||||
let nu5_activation_height = Nu5.activation_height(default_network);
|
let nu5_activation_height = Nu5.activation_height(&default_network);
|
||||||
let nu5_override = if nu5_activation_height.is_some() {
|
let nu5_override = if nu5_activation_height.is_some() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -348,12 +348,14 @@ impl Arbitrary for Block {
|
||||||
type Parameters = LedgerState;
|
type Parameters = LedgerState;
|
||||||
|
|
||||||
fn arbitrary_with(ledger_state: Self::Parameters) -> Self::Strategy {
|
fn arbitrary_with(ledger_state: Self::Parameters) -> Self::Strategy {
|
||||||
let transactions_strategy =
|
let transactions_strategy = {
|
||||||
|
let ledger_state = ledger_state.clone();
|
||||||
// Generate a random number transactions. A coinbase tx is always generated, so if
|
// Generate a random number transactions. A coinbase tx is always generated, so if
|
||||||
// `transaction_count` is zero, the block will contain only the coinbase tx.
|
// `transaction_count` is zero, the block will contain only the coinbase tx.
|
||||||
(0..MAX_ARBITRARY_ITEMS).prop_flat_map(move |transaction_count| {
|
(0..MAX_ARBITRARY_ITEMS).prop_flat_map(move |transaction_count| {
|
||||||
Transaction::vec_strategy(ledger_state, transaction_count)
|
Transaction::vec_strategy(ledger_state.clone(), transaction_count)
|
||||||
});
|
})
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: if needed, fixup:
|
// TODO: if needed, fixup:
|
||||||
// - history and authorizing data commitments
|
// - history and authorizing data commitments
|
||||||
|
@ -411,7 +413,7 @@ impl Block {
|
||||||
|
|
||||||
// generate block strategies with the correct heights
|
// generate block strategies with the correct heights
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
vec.push((Just(current.height), Block::arbitrary_with(current)));
|
vec.push((Just(current.height), Block::arbitrary_with(current.clone())));
|
||||||
current.height.0 += 1;
|
current.height.0 += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,9 +475,9 @@ impl Block {
|
||||||
if generate_valid_commitments {
|
if generate_valid_commitments {
|
||||||
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(current.network)
|
.activation_height(¤t.network)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let nu5_height = NetworkUpgrade::Nu5.activation_height(current.network);
|
let nu5_height = NetworkUpgrade::Nu5.activation_height(¤t.network);
|
||||||
|
|
||||||
match current_height.cmp(&heartwood_height) {
|
match current_height.cmp(&heartwood_height) {
|
||||||
std::cmp::Ordering::Less => {
|
std::cmp::Ordering::Less => {
|
||||||
|
@ -520,16 +522,16 @@ impl Block {
|
||||||
if let Some(history_tree) = history_tree.as_mut() {
|
if let Some(history_tree) = history_tree.as_mut() {
|
||||||
history_tree
|
history_tree
|
||||||
.push(
|
.push(
|
||||||
current.network,
|
¤t.network,
|
||||||
Arc::new(block.clone()),
|
Arc::new(block.clone()),
|
||||||
sapling_tree.root(),
|
&sapling_tree.root(),
|
||||||
orchard_tree.root(),
|
&orchard_tree.root(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
history_tree = Some(
|
history_tree = Some(
|
||||||
HistoryTree::from_block(
|
HistoryTree::from_block(
|
||||||
current.network,
|
¤t.network,
|
||||||
Arc::new(block.clone()),
|
Arc::new(block.clone()),
|
||||||
&sapling_tree.root(),
|
&sapling_tree.root(),
|
||||||
&orchard_tree.root(),
|
&orchard_tree.root(),
|
||||||
|
@ -703,10 +705,10 @@ 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).unwrap() {
|
||||||
Commitment::ChainHistoryActivationReserved
|
Commitment::ChainHistoryActivationReserved
|
||||||
} else {
|
} else {
|
||||||
Commitment::from_bytes(commitment_bytes, network, block_height)
|
Commitment::from_bytes(commitment_bytes, &network, block_height)
|
||||||
.expect("unexpected failure in from_bytes parsing")
|
.expect("unexpected failure in from_bytes parsing")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl Commitment {
|
||||||
// TODO: rename as from_bytes_in_serialized_order()
|
// TODO: rename as from_bytes_in_serialized_order()
|
||||||
pub(super) fn from_bytes(
|
pub(super) fn from_bytes(
|
||||||
bytes: [u8; 32],
|
bytes: [u8; 32],
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: block::Height,
|
height: block::Height,
|
||||||
) -> Result<Commitment, CommitmentError> {
|
) -> Result<Commitment, CommitmentError> {
|
||||||
use Commitment::*;
|
use Commitment::*;
|
||||||
|
|
|
@ -81,7 +81,7 @@ proptest! {
|
||||||
|
|
||||||
// just skip the test if the bytes don't parse, because there's nothing
|
// just skip the test if the bytes don't parse, because there's nothing
|
||||||
// to compare with
|
// to compare with
|
||||||
if let Ok(commitment) = Commitment::from_bytes(bytes, network, block_height) {
|
if let Ok(commitment) = Commitment::from_bytes(bytes, &network, block_height) {
|
||||||
let other_bytes = commitment.to_bytes();
|
let other_bytes = commitment.to_bytes();
|
||||||
|
|
||||||
prop_assert_eq![bytes, other_bytes];
|
prop_assert_eq![bytes, other_bytes];
|
||||||
|
@ -104,7 +104,7 @@ proptest! {
|
||||||
let bytes = block.zcash_serialize_to_vec()?;
|
let bytes = block.zcash_serialize_to_vec()?;
|
||||||
|
|
||||||
// Check the block commitment
|
// Check the block commitment
|
||||||
let commitment = block.commitment(network);
|
let commitment = block.commitment(&network);
|
||||||
if let Ok(commitment) = commitment {
|
if let Ok(commitment) = commitment {
|
||||||
let commitment_bytes = commitment.to_bytes();
|
let commitment_bytes = commitment.to_bytes();
|
||||||
prop_assert_eq![block.header.commitment_bytes.0, commitment_bytes];
|
prop_assert_eq![block.header.commitment_bytes.0, commitment_bytes];
|
||||||
|
|
|
@ -222,7 +222,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")
|
||||||
.0
|
.0
|
||||||
{
|
{
|
||||||
|
@ -260,7 +260,7 @@ fn block_commitment(network: Network) {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block is structurally valid");
|
.expect("block is structurally valid");
|
||||||
|
|
||||||
let commitment = block.commitment(network).unwrap_or_else(|_| {
|
let commitment = block.commitment(&network).unwrap_or_else(|_| {
|
||||||
panic!("unexpected structurally invalid block commitment at {network} {height}")
|
panic!("unexpected structurally invalid block commitment at {network} {height}")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ pub trait ChainTip {
|
||||||
/// and the height of the best tip.
|
/// and the height of the best tip.
|
||||||
fn estimate_network_chain_tip_height(
|
fn estimate_network_chain_tip_height(
|
||||||
&self,
|
&self,
|
||||||
network: Network,
|
network: &Network,
|
||||||
now: DateTime<Utc>,
|
now: DateTime<Utc>,
|
||||||
) -> Option<block::Height> {
|
) -> Option<block::Height> {
|
||||||
let (current_height, current_block_time) = self.best_tip_height_and_block_time()?;
|
let (current_height, current_block_time) = self.best_tip_height_and_block_time()?;
|
||||||
|
@ -110,7 +110,7 @@ pub trait ChainTip {
|
||||||
/// Returns `None` if the state is empty.
|
/// Returns `None` if the state is empty.
|
||||||
fn estimate_distance_to_network_chain_tip(
|
fn estimate_distance_to_network_chain_tip(
|
||||||
&self,
|
&self,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Option<(block::HeightDiff, block::Height)> {
|
) -> Option<(block::HeightDiff, block::Height)> {
|
||||||
let (current_height, current_block_time) = self.best_tip_height_and_block_time()?;
|
let (current_height, current_block_time) = self.best_tip_height_and_block_time()?;
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl ChainTip for MockChainTip {
|
||||||
|
|
||||||
fn estimate_distance_to_network_chain_tip(
|
fn estimate_distance_to_network_chain_tip(
|
||||||
&self,
|
&self,
|
||||||
_network: Network,
|
_network: &Network,
|
||||||
) -> Option<(block::HeightDiff, block::Height)> {
|
) -> Option<(block::HeightDiff, block::Height)> {
|
||||||
self.estimated_distance_to_network_chain_tip
|
self.estimated_distance_to_network_chain_tip
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl NetworkChainTipHeightEstimator {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
current_block_time: DateTime<Utc>,
|
current_block_time: DateTime<Utc>,
|
||||||
current_height: block::Height,
|
current_height: block::Height,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut target_spacings = NetworkUpgrade::target_spacings(network);
|
let mut target_spacings = NetworkUpgrade::target_spacings(network);
|
||||||
let (_genesis_height, initial_target_spacing) =
|
let (_genesis_height, initial_target_spacing) =
|
||||||
|
|
|
@ -24,7 +24,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");
|
||||||
|
|
||||||
block_heights.sort();
|
block_heights.sort();
|
||||||
|
@ -50,13 +50,13 @@ proptest! {
|
||||||
|
|
||||||
let time_displacement = calculate_time_displacement(
|
let time_displacement = calculate_time_displacement(
|
||||||
time_displacement_factor,
|
time_displacement_factor,
|
||||||
NetworkUpgrade::current(network, network_height),
|
NetworkUpgrade::current(&network, network_height),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mock_local_time = current_block_time + estimated_time_difference + time_displacement;
|
let mock_local_time = current_block_time + estimated_time_difference + time_displacement;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
chain_tip.estimate_network_chain_tip_height(network, mock_local_time),
|
chain_tip.estimate_network_chain_tip_height(&network, mock_local_time),
|
||||||
Some(network_height)
|
Some(network_height)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl NonEmptyHistoryTree {
|
||||||
/// The parameters must come from the values of [`NonEmptyHistoryTree::size`],
|
/// The parameters must come from the values of [`NonEmptyHistoryTree::size`],
|
||||||
/// [`NonEmptyHistoryTree::peaks`] and [`NonEmptyHistoryTree::current_height`] of a HistoryTree.
|
/// [`NonEmptyHistoryTree::peaks`] and [`NonEmptyHistoryTree::current_height`] of a HistoryTree.
|
||||||
pub fn from_cache(
|
pub fn from_cache(
|
||||||
network: Network,
|
network: &Network,
|
||||||
size: u32,
|
size: u32,
|
||||||
peaks: BTreeMap<u32, Entry>,
|
peaks: BTreeMap<u32, Entry>,
|
||||||
current_height: Height,
|
current_height: Height,
|
||||||
|
@ -114,7 +114,7 @@ impl NonEmptyHistoryTree {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
network,
|
network: network.clone(),
|
||||||
network_upgrade,
|
network_upgrade,
|
||||||
inner,
|
inner,
|
||||||
size,
|
size,
|
||||||
|
@ -130,7 +130,7 @@ impl NonEmptyHistoryTree {
|
||||||
/// (ignored for pre-Orchard blocks).
|
/// (ignored for pre-Orchard blocks).
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn from_block(
|
pub fn from_block(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
|
@ -169,7 +169,7 @@ impl NonEmptyHistoryTree {
|
||||||
let mut peaks = BTreeMap::new();
|
let mut peaks = BTreeMap::new();
|
||||||
peaks.insert(0u32, entry);
|
peaks.insert(0u32, entry);
|
||||||
Ok(NonEmptyHistoryTree {
|
Ok(NonEmptyHistoryTree {
|
||||||
network,
|
network: network.clone(),
|
||||||
network_upgrade,
|
network_upgrade,
|
||||||
inner: tree,
|
inner: tree,
|
||||||
size: 1,
|
size: 1,
|
||||||
|
@ -208,11 +208,11 @@ impl NonEmptyHistoryTree {
|
||||||
self.current_height
|
self.current_height
|
||||||
);
|
);
|
||||||
|
|
||||||
let network_upgrade = NetworkUpgrade::current(self.network, height);
|
let network_upgrade = NetworkUpgrade::current(&self.network, height);
|
||||||
if network_upgrade != self.network_upgrade {
|
if network_upgrade != self.network_upgrade {
|
||||||
// This is the activation block of a network upgrade.
|
// This is the activation block of a network upgrade.
|
||||||
// Create a new tree.
|
// Create a new tree.
|
||||||
let new_tree = Self::from_block(self.network, block, sapling_root, orchard_root)?;
|
let new_tree = Self::from_block(&self.network, block, sapling_root, orchard_root)?;
|
||||||
// Replaces self with the new tree
|
// Replaces self with the new tree
|
||||||
*self = new_tree;
|
*self = new_tree;
|
||||||
assert_eq!(self.network_upgrade, network_upgrade);
|
assert_eq!(self.network_upgrade, network_upgrade);
|
||||||
|
@ -328,7 +328,7 @@ impl NonEmptyHistoryTree {
|
||||||
self.inner = match self.inner {
|
self.inner = match self.inner {
|
||||||
InnerHistoryTree::PreOrchard(_) => {
|
InnerHistoryTree::PreOrchard(_) => {
|
||||||
InnerHistoryTree::PreOrchard(Tree::<PreOrchard>::new_from_cache(
|
InnerHistoryTree::PreOrchard(Tree::<PreOrchard>::new_from_cache(
|
||||||
self.network,
|
&self.network,
|
||||||
self.network_upgrade,
|
self.network_upgrade,
|
||||||
self.size,
|
self.size,
|
||||||
&self.peaks,
|
&self.peaks,
|
||||||
|
@ -337,7 +337,7 @@ impl NonEmptyHistoryTree {
|
||||||
}
|
}
|
||||||
InnerHistoryTree::OrchardOnward(_) => {
|
InnerHistoryTree::OrchardOnward(_) => {
|
||||||
InnerHistoryTree::OrchardOnward(Tree::<OrchardOnward>::new_from_cache(
|
InnerHistoryTree::OrchardOnward(Tree::<OrchardOnward>::new_from_cache(
|
||||||
self.network,
|
&self.network,
|
||||||
self.network_upgrade,
|
self.network_upgrade,
|
||||||
self.size,
|
self.size,
|
||||||
&self.peaks,
|
&self.peaks,
|
||||||
|
@ -373,7 +373,7 @@ impl NonEmptyHistoryTree {
|
||||||
|
|
||||||
/// Return the network where this tree is used.
|
/// Return the network where this tree is used.
|
||||||
pub fn network(&self) -> Network {
|
pub fn network(&self) -> Network {
|
||||||
self.network
|
self.network.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ impl Clone for NonEmptyHistoryTree {
|
||||||
let tree = match self.inner {
|
let tree = match self.inner {
|
||||||
InnerHistoryTree::PreOrchard(_) => InnerHistoryTree::PreOrchard(
|
InnerHistoryTree::PreOrchard(_) => InnerHistoryTree::PreOrchard(
|
||||||
Tree::<PreOrchard>::new_from_cache(
|
Tree::<PreOrchard>::new_from_cache(
|
||||||
self.network,
|
&self.network,
|
||||||
self.network_upgrade,
|
self.network_upgrade,
|
||||||
self.size,
|
self.size,
|
||||||
&self.peaks,
|
&self.peaks,
|
||||||
|
@ -392,7 +392,7 @@ impl Clone for NonEmptyHistoryTree {
|
||||||
),
|
),
|
||||||
InnerHistoryTree::OrchardOnward(_) => InnerHistoryTree::OrchardOnward(
|
InnerHistoryTree::OrchardOnward(_) => InnerHistoryTree::OrchardOnward(
|
||||||
Tree::<OrchardOnward>::new_from_cache(
|
Tree::<OrchardOnward>::new_from_cache(
|
||||||
self.network,
|
&self.network,
|
||||||
self.network_upgrade,
|
self.network_upgrade,
|
||||||
self.size,
|
self.size,
|
||||||
&self.peaks,
|
&self.peaks,
|
||||||
|
@ -402,7 +402,7 @@ impl Clone for NonEmptyHistoryTree {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
NonEmptyHistoryTree {
|
NonEmptyHistoryTree {
|
||||||
network: self.network,
|
network: self.network.clone(),
|
||||||
network_upgrade: self.network_upgrade,
|
network_upgrade: self.network_upgrade,
|
||||||
inner: tree,
|
inner: tree,
|
||||||
size: self.size,
|
size: self.size,
|
||||||
|
@ -423,7 +423,7 @@ impl HistoryTree {
|
||||||
/// If the block is pre-Heartwood, it returns an empty history tree.
|
/// If the block is pre-Heartwood, it returns an empty history tree.
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn from_block(
|
pub fn from_block(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
|
@ -450,10 +450,10 @@ impl HistoryTree {
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn push(
|
pub fn push(
|
||||||
&mut self,
|
&mut self,
|
||||||
network: Network,
|
network: &Network,
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
sapling_root: sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
) -> Result<(), HistoryTreeError> {
|
) -> Result<(), HistoryTreeError> {
|
||||||
let heartwood_height = NetworkUpgrade::Heartwood
|
let heartwood_height = NetworkUpgrade::Heartwood
|
||||||
.activation_height(network)
|
.activation_height(network)
|
||||||
|
@ -472,9 +472,9 @@ impl HistoryTree {
|
||||||
std::cmp::Ordering::Equal => {
|
std::cmp::Ordering::Equal => {
|
||||||
let tree = Some(NonEmptyHistoryTree::from_block(
|
let tree = Some(NonEmptyHistoryTree::from_block(
|
||||||
network,
|
network,
|
||||||
block.clone(),
|
block,
|
||||||
&sapling_root,
|
sapling_root,
|
||||||
&orchard_root,
|
orchard_root,
|
||||||
)?);
|
)?);
|
||||||
// Replace the current object with the new tree
|
// Replace the current object with the new tree
|
||||||
*self = HistoryTree(tree);
|
*self = HistoryTree(tree);
|
||||||
|
@ -483,7 +483,7 @@ impl HistoryTree {
|
||||||
self.0
|
self.0
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("history tree must exist Heartwood-onward")
|
.expect("history tree must exist Heartwood-onward")
|
||||||
.push(block.clone(), &sapling_root, &orchard_root)?;
|
.push(block.clone(), sapling_root, orchard_root)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -35,7 +35,7 @@ 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).unwrap().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(
|
||||||
|
@ -47,7 +47,7 @@ fn push_and_prune_for_network_upgrade(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check its commitment
|
// Check its commitment
|
||||||
let first_commitment = first_block.commitment(network)?;
|
let first_commitment = first_block.commitment(&network)?;
|
||||||
if network_upgrade == NetworkUpgrade::Heartwood {
|
if network_upgrade == NetworkUpgrade::Heartwood {
|
||||||
// Heartwood is the only upgrade that has a reserved value.
|
// Heartwood is the only upgrade that has a reserved value.
|
||||||
// (For other upgrades we could compare with the expected commitment,
|
// (For other upgrades we could compare with the expected commitment,
|
||||||
|
@ -59,7 +59,7 @@ fn push_and_prune_for_network_upgrade(
|
||||||
let first_sapling_root =
|
let first_sapling_root =
|
||||||
sapling::tree::Root::try_from(**sapling_roots.get(&height).expect("test vector exists"))?;
|
sapling::tree::Root::try_from(**sapling_roots.get(&height).expect("test vector exists"))?;
|
||||||
let mut tree = NonEmptyHistoryTree::from_block(
|
let mut tree = NonEmptyHistoryTree::from_block(
|
||||||
network,
|
&network,
|
||||||
first_block,
|
first_block,
|
||||||
&first_sapling_root,
|
&first_sapling_root,
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
|
@ -82,7 +82,7 @@ fn push_and_prune_for_network_upgrade(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check its commitment
|
// Check its commitment
|
||||||
let second_commitment = second_block.commitment(network)?;
|
let second_commitment = second_block.commitment(&network)?;
|
||||||
assert_eq!(second_commitment, Commitment::ChainHistoryRoot(first_root));
|
assert_eq!(second_commitment, Commitment::ChainHistoryRoot(first_root));
|
||||||
|
|
||||||
// Append second block to history tree
|
// Append second block to history tree
|
||||||
|
@ -117,7 +117,7 @@ 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).unwrap().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(
|
||||||
|
@ -134,7 +134,7 @@ fn upgrade_for_network_upgrade(network: Network, network_upgrade: NetworkUpgrade
|
||||||
let sapling_root_prev =
|
let sapling_root_prev =
|
||||||
sapling::tree::Root::try_from(**sapling_roots.get(&height).expect("test vector exists"))?;
|
sapling::tree::Root::try_from(**sapling_roots.get(&height).expect("test vector exists"))?;
|
||||||
let mut tree = NonEmptyHistoryTree::from_block(
|
let mut tree = NonEmptyHistoryTree::from_block(
|
||||||
network,
|
&network,
|
||||||
block_prev,
|
block_prev,
|
||||||
&sapling_root_prev,
|
&sapling_root_prev,
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
|
|
|
@ -52,7 +52,7 @@ mod tests;
|
||||||
const ZIP_212_GRACE_PERIOD_DURATION: HeightDiff = 32_256;
|
const ZIP_212_GRACE_PERIOD_DURATION: HeightDiff = 32_256;
|
||||||
|
|
||||||
/// An enum describing the possible network choices.
|
/// An enum describing the possible network choices.
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
/// The production mainnet.
|
/// The production mainnet.
|
||||||
|
@ -68,13 +68,13 @@ impl Network {
|
||||||
/// Returns the human-readable prefix for Base58Check-encoded transparent
|
/// Returns the human-readable prefix for Base58Check-encoded transparent
|
||||||
/// pay-to-public-key-hash payment addresses for the network.
|
/// pay-to-public-key-hash payment addresses for the network.
|
||||||
pub fn b58_pubkey_address_prefix(&self) -> [u8; 2] {
|
pub fn b58_pubkey_address_prefix(&self) -> [u8; 2] {
|
||||||
<ZcashPrimitivesNetwork>::from(*self).b58_pubkey_address_prefix()
|
<ZcashPrimitivesNetwork>::from(self).b58_pubkey_address_prefix()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the human-readable prefix for Base58Check-encoded transparent pay-to-script-hash
|
/// Returns the human-readable prefix for Base58Check-encoded transparent pay-to-script-hash
|
||||||
/// payment addresses for the network.
|
/// payment addresses for the network.
|
||||||
pub fn b58_script_address_prefix(&self) -> [u8; 2] {
|
pub fn b58_script_address_prefix(&self) -> [u8; 2] {
|
||||||
<ZcashPrimitivesNetwork>::from(*self).b58_script_address_prefix()
|
<ZcashPrimitivesNetwork>::from(self).b58_script_address_prefix()
|
||||||
}
|
}
|
||||||
/// Returns true if the maximum block time rule is active for `network` and `height`.
|
/// Returns true if the maximum block time rule is active for `network` and `height`.
|
||||||
///
|
///
|
||||||
|
@ -84,7 +84,7 @@ impl Network {
|
||||||
/// Returns false otherwise.
|
/// Returns false otherwise.
|
||||||
///
|
///
|
||||||
/// Part of the consensus rules at <https://zips.z.cash/protocol/protocol.pdf#blockheader>
|
/// Part of the consensus rules at <https://zips.z.cash/protocol/protocol.pdf#blockheader>
|
||||||
pub fn is_max_block_time_enforced(self, height: block::Height) -> bool {
|
pub fn is_max_block_time_enforced(&self, height: block::Height) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Network::Mainnet => true,
|
Network::Mainnet => true,
|
||||||
Network::Testnet => height >= super::TESTNET_MAX_TIME_START_HEIGHT,
|
Network::Testnet => height >= super::TESTNET_MAX_TIME_START_HEIGHT,
|
||||||
|
@ -92,8 +92,8 @@ impl Network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Network> for &'static str {
|
impl From<&Network> for &'static str {
|
||||||
fn from(network: Network) -> &'static str {
|
fn from(network: &Network) -> &'static str {
|
||||||
match network {
|
match network {
|
||||||
Network::Mainnet => "Mainnet",
|
Network::Mainnet => "Mainnet",
|
||||||
Network::Testnet => "Testnet",
|
Network::Testnet => "Testnet",
|
||||||
|
@ -101,12 +101,6 @@ impl From<Network> for &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Network> for &'static str {
|
|
||||||
fn from(network: &Network) -> &'static str {
|
|
||||||
(*network).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Network {
|
impl fmt::Display for Network {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str(self.into())
|
f.write_str(self.into())
|
||||||
|
@ -139,7 +133,7 @@ impl Network {
|
||||||
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
||||||
|
|
||||||
let canopy_activation = Canopy
|
let canopy_activation = 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");
|
||||||
|
|
||||||
(canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
(canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
||||||
|
@ -166,7 +160,7 @@ 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) -> Height {
|
||||||
super::NetworkUpgrade::Sapling
|
super::NetworkUpgrade::Sapling
|
||||||
.activation_height(self)
|
.activation_height(self)
|
||||||
.expect("Sapling activation height needs to be set")
|
.expect("Sapling activation height needs to be set")
|
||||||
|
|
|
@ -18,7 +18,7 @@ proptest! {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
let grace_period_end_height = (canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
let grace_period_end_height = (canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
||||||
|
|
|
@ -280,7 +280,7 @@ impl Network {
|
||||||
}
|
}
|
||||||
impl NetworkUpgrade {
|
impl NetworkUpgrade {
|
||||||
/// Returns the current network upgrade for `network` and `height`.
|
/// Returns the current network upgrade for `network` and `height`.
|
||||||
pub fn current(network: Network, height: block::Height) -> NetworkUpgrade {
|
pub fn current(network: &Network, height: block::Height) -> NetworkUpgrade {
|
||||||
network
|
network
|
||||||
.activation_list()
|
.activation_list()
|
||||||
.range(..=height)
|
.range(..=height)
|
||||||
|
@ -293,7 +293,7 @@ impl NetworkUpgrade {
|
||||||
///
|
///
|
||||||
/// Returns None if the next upgrade has not been implemented in Zebra
|
/// Returns None if the next upgrade has not been implemented in Zebra
|
||||||
/// yet.
|
/// yet.
|
||||||
pub fn next(network: Network, height: block::Height) -> Option<NetworkUpgrade> {
|
pub fn next(network: &Network, height: block::Height) -> Option<NetworkUpgrade> {
|
||||||
network
|
network
|
||||||
.activation_list()
|
.activation_list()
|
||||||
.range((Excluded(height), Unbounded))
|
.range((Excluded(height), Unbounded))
|
||||||
|
@ -305,7 +305,7 @@ impl NetworkUpgrade {
|
||||||
///
|
///
|
||||||
/// Returns None if this network upgrade is a future upgrade, and its
|
/// Returns None if this network upgrade is a future upgrade, and its
|
||||||
/// activation height has not been set yet.
|
/// activation height has not been set yet.
|
||||||
pub fn activation_height(&self, network: Network) -> Option<block::Height> {
|
pub fn activation_height(&self, network: &Network) -> Option<block::Height> {
|
||||||
network
|
network
|
||||||
.activation_list()
|
.activation_list()
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -319,7 +319,7 @@ impl NetworkUpgrade {
|
||||||
///
|
///
|
||||||
/// Use [`NetworkUpgrade::activation_height`] to get the specific network
|
/// Use [`NetworkUpgrade::activation_height`] to get the specific network
|
||||||
/// upgrade.
|
/// upgrade.
|
||||||
pub fn is_activation_height(network: Network, height: block::Height) -> bool {
|
pub fn is_activation_height(network: &Network, height: block::Height) -> bool {
|
||||||
network.activation_list().contains_key(&height)
|
network.activation_list().contains_key(&height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,12 +358,14 @@ impl NetworkUpgrade {
|
||||||
/// Returns the target block spacing for `network` and `height`.
|
/// Returns the target block spacing for `network` and `height`.
|
||||||
///
|
///
|
||||||
/// See [`NetworkUpgrade::target_spacing`] for details.
|
/// See [`NetworkUpgrade::target_spacing`] for details.
|
||||||
pub fn target_spacing_for_height(network: Network, height: block::Height) -> Duration {
|
pub fn target_spacing_for_height(network: &Network, height: block::Height) -> Duration {
|
||||||
NetworkUpgrade::current(network, height).target_spacing()
|
NetworkUpgrade::current(network, height).target_spacing()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all the target block spacings for `network` and the heights where they start.
|
/// Returns all the target block spacings for `network` and the heights where they start.
|
||||||
pub fn target_spacings(network: Network) -> impl Iterator<Item = (block::Height, Duration)> {
|
pub fn target_spacings(
|
||||||
|
network: &Network,
|
||||||
|
) -> impl Iterator<Item = (block::Height, Duration)> + '_ {
|
||||||
[
|
[
|
||||||
(NetworkUpgrade::Genesis, PRE_BLOSSOM_POW_TARGET_SPACING),
|
(NetworkUpgrade::Genesis, PRE_BLOSSOM_POW_TARGET_SPACING),
|
||||||
(
|
(
|
||||||
|
@ -388,7 +390,7 @@ impl NetworkUpgrade {
|
||||||
///
|
///
|
||||||
/// Based on <https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network>
|
/// Based on <https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network>
|
||||||
pub fn minimum_difficulty_spacing_for_height(
|
pub fn minimum_difficulty_spacing_for_height(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: block::Height,
|
height: block::Height,
|
||||||
) -> Option<Duration> {
|
) -> Option<Duration> {
|
||||||
match (network, height) {
|
match (network, height) {
|
||||||
|
@ -417,7 +419,7 @@ impl NetworkUpgrade {
|
||||||
/// check for the time gap. This function implements the correct "greater than"
|
/// check for the time gap. This function implements the correct "greater than"
|
||||||
/// check.
|
/// check.
|
||||||
pub fn is_testnet_min_difficulty_block(
|
pub fn is_testnet_min_difficulty_block(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block_height: block::Height,
|
block_height: block::Height,
|
||||||
block_time: DateTime<Utc>,
|
block_time: DateTime<Utc>,
|
||||||
previous_block_time: DateTime<Utc>,
|
previous_block_time: DateTime<Utc>,
|
||||||
|
@ -443,7 +445,7 @@ impl NetworkUpgrade {
|
||||||
///
|
///
|
||||||
/// See [`NetworkUpgrade::averaging_window_timespan`] for details.
|
/// See [`NetworkUpgrade::averaging_window_timespan`] for details.
|
||||||
pub fn averaging_window_timespan_for_height(
|
pub fn averaging_window_timespan_for_height(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: block::Height,
|
height: block::Height,
|
||||||
) -> Duration {
|
) -> Duration {
|
||||||
NetworkUpgrade::current(network, height).averaging_window_timespan()
|
NetworkUpgrade::current(network, height).averaging_window_timespan()
|
||||||
|
@ -472,7 +474,7 @@ impl ConsensusBranchId {
|
||||||
/// Returns the current consensus branch id for `network` and `height`.
|
/// Returns the current consensus branch id for `network` and `height`.
|
||||||
///
|
///
|
||||||
/// Returns None if the network has no branch id at this height.
|
/// Returns None if the network has no branch id at this height.
|
||||||
pub fn current(network: Network, height: block::Height) -> Option<ConsensusBranchId> {
|
pub fn current(network: &Network, height: block::Height) -> Option<ConsensusBranchId> {
|
||||||
NetworkUpgrade::current(network, height).branch_id()
|
NetworkUpgrade::current(network, height).branch_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,15 +49,15 @@ fn activation_extremes(network: Network) {
|
||||||
network.activation_list().get(&block::Height(0)),
|
network.activation_list().get(&block::Height(0)),
|
||||||
Some(&Genesis)
|
Some(&Genesis)
|
||||||
);
|
);
|
||||||
assert_eq!(Genesis.activation_height(network), Some(block::Height(0)));
|
assert_eq!(Genesis.activation_height(&network), Some(block::Height(0)));
|
||||||
assert!(NetworkUpgrade::is_activation_height(
|
assert!(NetworkUpgrade::is_activation_height(
|
||||||
network,
|
&network,
|
||||||
block::Height(0)
|
block::Height(0)
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(NetworkUpgrade::current(network, block::Height(0)), Genesis);
|
assert_eq!(NetworkUpgrade::current(&network, block::Height(0)), Genesis);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NetworkUpgrade::next(network, block::Height(0)),
|
NetworkUpgrade::next(&network, block::Height(0)),
|
||||||
Some(BeforeOverwinter)
|
Some(BeforeOverwinter)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -66,25 +66,25 @@ fn activation_extremes(network: Network) {
|
||||||
Some(&BeforeOverwinter)
|
Some(&BeforeOverwinter)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BeforeOverwinter.activation_height(network),
|
BeforeOverwinter.activation_height(&network),
|
||||||
Some(block::Height(1))
|
Some(block::Height(1))
|
||||||
);
|
);
|
||||||
assert!(NetworkUpgrade::is_activation_height(
|
assert!(NetworkUpgrade::is_activation_height(
|
||||||
network,
|
&network,
|
||||||
block::Height(1)
|
block::Height(1)
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NetworkUpgrade::current(network, block::Height(1)),
|
NetworkUpgrade::current(&network, block::Height(1)),
|
||||||
BeforeOverwinter
|
BeforeOverwinter
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NetworkUpgrade::next(network, block::Height(1)),
|
NetworkUpgrade::next(&network, block::Height(1)),
|
||||||
Some(Overwinter)
|
Some(Overwinter)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(!NetworkUpgrade::is_activation_height(
|
assert!(!NetworkUpgrade::is_activation_height(
|
||||||
network,
|
&network,
|
||||||
block::Height(2)
|
block::Height(2)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -95,15 +95,15 @@ fn activation_extremes(network: Network) {
|
||||||
Some(&Genesis)
|
Some(&Genesis)
|
||||||
);
|
);
|
||||||
assert!(!NetworkUpgrade::is_activation_height(
|
assert!(!NetworkUpgrade::is_activation_height(
|
||||||
network,
|
&network,
|
||||||
block::Height::MAX
|
block::Height::MAX
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
NetworkUpgrade::current(network, block::Height::MAX),
|
NetworkUpgrade::current(&network, block::Height::MAX),
|
||||||
Genesis
|
Genesis
|
||||||
);
|
);
|
||||||
assert_eq!(NetworkUpgrade::next(network, block::Height::MAX), None);
|
assert_eq!(NetworkUpgrade::next(&network, block::Height::MAX), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -126,28 +126,31 @@ 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");
|
||||||
assert!(NetworkUpgrade::is_activation_height(network, height));
|
assert!(NetworkUpgrade::is_activation_height(&network, height));
|
||||||
|
|
||||||
if height > block::Height(0) {
|
if height > block::Height(0) {
|
||||||
// Genesis is immediately followed by BeforeOverwinter,
|
// Genesis is immediately followed by BeforeOverwinter,
|
||||||
// but the other network upgrades have multiple blocks between them
|
// but the other network upgrades have multiple blocks between them
|
||||||
assert!(!NetworkUpgrade::is_activation_height(
|
assert!(!NetworkUpgrade::is_activation_height(
|
||||||
network,
|
&network,
|
||||||
(height + 1).unwrap()
|
(height + 1).unwrap()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(NetworkUpgrade::current(network, height), network_upgrade);
|
assert_eq!(NetworkUpgrade::current(&network, height), network_upgrade);
|
||||||
// Network upgrades don't repeat
|
// Network upgrades don't repeat
|
||||||
assert_ne!(NetworkUpgrade::next(network, height), Some(network_upgrade));
|
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
NetworkUpgrade::next(network, block::Height(height.0 + 1)),
|
NetworkUpgrade::next(&network, height),
|
||||||
Some(network_upgrade)
|
Some(network_upgrade)
|
||||||
);
|
);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
NetworkUpgrade::next(network, block::Height::MAX),
|
NetworkUpgrade::next(&network, block::Height(height.0 + 1)),
|
||||||
|
Some(network_upgrade)
|
||||||
|
);
|
||||||
|
assert_ne!(
|
||||||
|
NetworkUpgrade::next(&network, block::Height::MAX),
|
||||||
Some(network_upgrade)
|
Some(network_upgrade)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +189,7 @@ fn branch_id_extremes(network: Network) {
|
||||||
NetworkUpgrade::branch_id_list().get(&BeforeOverwinter),
|
NetworkUpgrade::branch_id_list().get(&BeforeOverwinter),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
assert_eq!(ConsensusBranchId::current(network, block::Height(0)), None);
|
assert_eq!(ConsensusBranchId::current(&network, block::Height(0)), None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NetworkUpgrade::branch_id_list().get(&Overwinter).cloned(),
|
NetworkUpgrade::branch_id_list().get(&Overwinter).cloned(),
|
||||||
Overwinter.branch_id()
|
Overwinter.branch_id()
|
||||||
|
@ -195,11 +198,12 @@ fn branch_id_extremes(network: Network) {
|
||||||
// We assume that the last upgrade we know about continues forever
|
// We assume that the last upgrade we know about continues forever
|
||||||
// (even if we suspect that won't be true)
|
// (even if we suspect that won't be true)
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
NetworkUpgrade::branch_id_list().get(&NetworkUpgrade::current(network, block::Height::MAX)),
|
NetworkUpgrade::branch_id_list()
|
||||||
|
.get(&NetworkUpgrade::current(&network, block::Height::MAX)),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
ConsensusBranchId::current(network, block::Height::MAX),
|
ConsensusBranchId::current(&network, block::Height::MAX),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -222,12 +226,12 @@ fn branch_id_consistent(network: Network) {
|
||||||
let network_upgrades: HashSet<&NetworkUpgrade> = branch_id_list.keys().collect();
|
let network_upgrades: HashSet<&NetworkUpgrade> = branch_id_list.keys().collect();
|
||||||
|
|
||||||
for &network_upgrade in network_upgrades {
|
for &network_upgrade in network_upgrades {
|
||||||
let height = network_upgrade.activation_height(network);
|
let height = network_upgrade.activation_height(&network);
|
||||||
|
|
||||||
// Skip network upgrades that don't have activation heights yet
|
// Skip network upgrades that don't have activation heights yet
|
||||||
if let Some(height) = height {
|
if let Some(height) = height {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ConsensusBranchId::current(network, height),
|
ConsensusBranchId::current(&network, height),
|
||||||
network_upgrade.branch_id()
|
network_upgrade.branch_id()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,8 @@ impl TryFrom<zcash_address::Network> for Network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Network> for zcash_address::Network {
|
impl From<&Network> for zcash_address::Network {
|
||||||
fn from(network: Network) -> Self {
|
fn from(network: &Network) -> Self {
|
||||||
match network {
|
match network {
|
||||||
Network::Mainnet => zcash_address::Network::Main,
|
Network::Mainnet => zcash_address::Network::Main,
|
||||||
Network::Testnet => zcash_address::Network::Test,
|
Network::Testnet => zcash_address::Network::Test,
|
||||||
|
@ -71,7 +71,7 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
data: [u8; 20],
|
data: [u8; 20],
|
||||||
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
||||||
Ok(Self::Transparent(transparent::Address::from_pub_key_hash(
|
Ok(Self::Transparent(transparent::Address::from_pub_key_hash(
|
||||||
network.try_into()?,
|
&network.try_into()?,
|
||||||
data,
|
data,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
data: [u8; 20],
|
data: [u8; 20],
|
||||||
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
||||||
Ok(Self::Transparent(transparent::Address::from_script_hash(
|
Ok(Self::Transparent(transparent::Address::from_script_hash(
|
||||||
network.try_into()?,
|
&network.try_into()?,
|
||||||
data,
|
data,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
network: zcash_address::Network,
|
network: zcash_address::Network,
|
||||||
unified_address: zcash_address::unified::Address,
|
unified_address: zcash_address::unified::Address,
|
||||||
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
||||||
let network = network.try_into()?;
|
let network = &network.try_into()?;
|
||||||
let mut orchard = None;
|
let mut orchard = None;
|
||||||
let mut sapling = None;
|
let mut sapling = None;
|
||||||
let mut transparent = None;
|
let mut transparent = None;
|
||||||
|
@ -144,7 +144,7 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self::Unified {
|
Ok(Self::Unified {
|
||||||
network,
|
network: network.clone(),
|
||||||
unified_address,
|
unified_address,
|
||||||
orchard,
|
orchard,
|
||||||
sapling,
|
sapling,
|
||||||
|
@ -158,7 +158,7 @@ impl Address {
|
||||||
pub fn network(&self) -> Network {
|
pub fn network(&self) -> Network {
|
||||||
match &self {
|
match &self {
|
||||||
Self::Transparent(address) => address.network(),
|
Self::Transparent(address) => address.network(),
|
||||||
Self::Sapling { network, .. } | Self::Unified { network, .. } => *network,
|
Self::Sapling { network, .. } | Self::Unified { network, .. } => network.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ impl Address {
|
||||||
Self::Transparent(address) => Some(address.to_string()),
|
Self::Transparent(address) => Some(address.to_string()),
|
||||||
Self::Sapling { address, network } => {
|
Self::Sapling { address, network } => {
|
||||||
let data = address.to_bytes();
|
let data = address.to_bytes();
|
||||||
let address = ZcashAddress::from_sapling((*network).into(), data);
|
let address = ZcashAddress::from_sapling(network.into(), data);
|
||||||
Some(address.encode())
|
Some(address.encode())
|
||||||
}
|
}
|
||||||
Self::Unified { .. } => None,
|
Self::Unified { .. } => None,
|
||||||
|
|
|
@ -25,19 +25,19 @@ impl ViewingKey {
|
||||||
/// Accepts an encoded Sapling viewing key to decode
|
/// Accepts an encoded Sapling viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`ViewingKey`] if successful, or None otherwise
|
/// Returns a [`ViewingKey`] if successful, or None otherwise
|
||||||
fn parse_sapling(sapling_key: &str, network: Network) -> Option<Self> {
|
fn parse_sapling(sapling_key: &str, network: &Network) -> Option<Self> {
|
||||||
SaplingViewingKey::parse(sapling_key, network).map(Self::Sapling)
|
SaplingViewingKey::parse(sapling_key, network).map(Self::Sapling)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accepts an encoded Orchard viewing key to decode
|
/// Accepts an encoded Orchard viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`ViewingKey`] if successful, or None otherwise
|
/// Returns a [`ViewingKey`] if successful, or None otherwise
|
||||||
fn parse_orchard(sapling_key: &str, network: Network) -> Option<Self> {
|
fn parse_orchard(sapling_key: &str, network: &Network) -> Option<Self> {
|
||||||
OrchardViewingKey::parse(sapling_key, network).map(Self::Orchard)
|
OrchardViewingKey::parse(sapling_key, network).map(Self::Orchard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an encoded viewing key and returns it as a [`ViewingKey`] type.
|
/// Parses an encoded viewing key and returns it as a [`ViewingKey`] type.
|
||||||
pub fn parse(key: &str, network: Network) -> Option<Self> {
|
pub fn parse(key: &str, network: &Network) -> Option<Self> {
|
||||||
Self::parse_sapling(key, network).or_else(|| Self::parse_orchard(key, network))
|
Self::parse_sapling(key, network).or_else(|| Self::parse_orchard(key, network))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ impl OrchardViewingKey {
|
||||||
/// Accepts an encoded Orchard viewing key to decode
|
/// Accepts an encoded Orchard viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`OrchardViewingKey`] if successful, or None otherwise
|
/// Returns a [`OrchardViewingKey`] if successful, or None otherwise
|
||||||
pub fn parse(_key: &str, _network: Network) -> Option<Self> {
|
pub fn parse(_key: &str, _network: &Network) -> Option<Self> {
|
||||||
// TODO: parse Orchard viewing keys
|
// TODO: parse Orchard viewing keys
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl SaplingViewingKey {
|
||||||
/// Accepts an encoded Sapling extended full viewing key to decode
|
/// Accepts an encoded Sapling extended full viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
|
/// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
|
||||||
fn parse_extended_full_viewing_key(sapling_key: &str, network: Network) -> Option<Self> {
|
fn parse_extended_full_viewing_key(sapling_key: &str, network: &Network) -> Option<Self> {
|
||||||
decode_extended_full_viewing_key(network.sapling_efvk_hrp(), sapling_key)
|
decode_extended_full_viewing_key(network.sapling_efvk_hrp(), sapling_key)
|
||||||
// this should fail often, so a debug-level log is okay
|
// this should fail often, so a debug-level log is okay
|
||||||
.map_err(|err| debug!(?err, "could not decode Sapling extended full viewing key"))
|
.map_err(|err| debug!(?err, "could not decode Sapling extended full viewing key"))
|
||||||
|
@ -38,7 +38,10 @@ impl SaplingViewingKey {
|
||||||
/// Accepts an encoded Sapling diversifiable full viewing key to decode
|
/// Accepts an encoded Sapling diversifiable full viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
|
/// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
|
||||||
fn parse_diversifiable_full_viewing_key(_sapling_key: &str, _network: Network) -> Option<Self> {
|
fn parse_diversifiable_full_viewing_key(
|
||||||
|
_sapling_key: &str,
|
||||||
|
_network: &Network,
|
||||||
|
) -> Option<Self> {
|
||||||
// TODO: Parse Sapling diversifiable full viewing key
|
// TODO: Parse Sapling diversifiable full viewing key
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -46,7 +49,7 @@ impl SaplingViewingKey {
|
||||||
/// Accepts an encoded Sapling full viewing key to decode
|
/// Accepts an encoded Sapling full viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`SaplingViewingKey::Fvk`] if successful, or None otherwise
|
/// Returns a [`SaplingViewingKey::Fvk`] if successful, or None otherwise
|
||||||
fn parse_full_viewing_key(_sapling_key: &str, _network: Network) -> Option<Self> {
|
fn parse_full_viewing_key(_sapling_key: &str, _network: &Network) -> Option<Self> {
|
||||||
// TODO: Parse Sapling full viewing key
|
// TODO: Parse Sapling full viewing key
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -54,7 +57,7 @@ impl SaplingViewingKey {
|
||||||
/// Accepts an encoded Sapling incoming viewing key to decode
|
/// Accepts an encoded Sapling incoming viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`SaplingViewingKey::Ivk`] if successful, or None otherwise
|
/// Returns a [`SaplingViewingKey::Ivk`] if successful, or None otherwise
|
||||||
fn parse_incoming_viewing_key(_sapling_key: &str, _network: Network) -> Option<Self> {
|
fn parse_incoming_viewing_key(_sapling_key: &str, _network: &Network) -> Option<Self> {
|
||||||
// TODO: Parse Sapling incoming viewing key
|
// TODO: Parse Sapling incoming viewing key
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -62,7 +65,7 @@ impl SaplingViewingKey {
|
||||||
/// Accepts an encoded Sapling viewing key to decode
|
/// Accepts an encoded Sapling viewing key to decode
|
||||||
///
|
///
|
||||||
/// Returns a [`SaplingViewingKey`] if successful, or None otherwise
|
/// Returns a [`SaplingViewingKey`] if successful, or None otherwise
|
||||||
pub(super) fn parse(key: &str, network: Network) -> Option<Self> {
|
pub(super) fn parse(key: &str, network: &Network) -> Option<Self> {
|
||||||
// TODO: Try types with prefixes first if some don't have prefixes?
|
// TODO: Try types with prefixes first if some don't have prefixes?
|
||||||
Self::parse_extended_full_viewing_key(key, network)
|
Self::parse_extended_full_viewing_key(key, network)
|
||||||
.or_else(|| Self::parse_diversifiable_full_viewing_key(key, network))
|
.or_else(|| Self::parse_diversifiable_full_viewing_key(key, network))
|
||||||
|
|
|
@ -10,6 +10,6 @@ pub const ZECPAGES_SAPLING_VIEWING_KEY: &str = "zxviews1q0duytgcqqqqpqre26wkl45g
|
||||||
fn parses_sapling_efvk_correctly() {
|
fn parses_sapling_efvk_correctly() {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
ViewingKey::parse(ZECPAGES_SAPLING_VIEWING_KEY, Network::Mainnet)
|
ViewingKey::parse(ZECPAGES_SAPLING_VIEWING_KEY, &Network::Mainnet)
|
||||||
.expect("should parse hard-coded viewing key successfully");
|
.expect("should parse hard-coded viewing key successfully");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub trait Version: zcash_history::Version {
|
||||||
/// Convert a Block into the NodeData for this version.
|
/// Convert a Block into the NodeData for this version.
|
||||||
fn block_to_history_node(
|
fn block_to_history_node(
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
) -> Self::NodeData;
|
) -> Self::NodeData;
|
||||||
|
@ -75,7 +75,7 @@ impl Entry {
|
||||||
/// (ignored for V1 trees).
|
/// (ignored for V1 trees).
|
||||||
fn new_leaf<V: Version>(
|
fn new_leaf<V: Version>(
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -106,7 +106,7 @@ impl<V: Version> Tree<V> {
|
||||||
/// Will panic if `peaks` is empty.
|
/// Will panic if `peaks` is empty.
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn new_from_cache(
|
pub fn new_from_cache(
|
||||||
network: Network,
|
network: &Network,
|
||||||
network_upgrade: NetworkUpgrade,
|
network_upgrade: NetworkUpgrade,
|
||||||
length: u32,
|
length: u32,
|
||||||
peaks: &BTreeMap<u32, Entry>,
|
peaks: &BTreeMap<u32, Entry>,
|
||||||
|
@ -127,7 +127,7 @@ impl<V: Version> Tree<V> {
|
||||||
}
|
}
|
||||||
let inner = zcash_history::Tree::new(length, peaks_vec, extra_vec);
|
let inner = zcash_history::Tree::new(length, peaks_vec, extra_vec);
|
||||||
Ok(Tree {
|
Ok(Tree {
|
||||||
network,
|
network: network.clone(),
|
||||||
network_upgrade,
|
network_upgrade,
|
||||||
inner,
|
inner,
|
||||||
})
|
})
|
||||||
|
@ -140,7 +140,7 @@ impl<V: Version> Tree<V> {
|
||||||
/// (ignored for V1 trees).
|
/// (ignored for V1 trees).
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn new_from_block(
|
pub fn new_from_block(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
|
@ -182,7 +182,7 @@ impl<V: Version> Tree<V> {
|
||||||
let height = block
|
let height = block
|
||||||
.coinbase_height()
|
.coinbase_height()
|
||||||
.expect("block must have coinbase height during contextual verification");
|
.expect("block must have coinbase height during contextual verification");
|
||||||
let network_upgrade = NetworkUpgrade::current(self.network, height);
|
let network_upgrade = NetworkUpgrade::current(&self.network, height);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
network_upgrade == self.network_upgrade,
|
network_upgrade == self.network_upgrade,
|
||||||
|
@ -191,7 +191,7 @@ impl<V: Version> Tree<V> {
|
||||||
self.network_upgrade
|
self.network_upgrade
|
||||||
);
|
);
|
||||||
|
|
||||||
let node_data = V::block_to_history_node(block, self.network, sapling_root, orchard_root);
|
let node_data = V::block_to_history_node(block, &self.network, sapling_root, orchard_root);
|
||||||
let appended = self.inner.append_leaf(node_data)?;
|
let appended = self.inner.append_leaf(node_data)?;
|
||||||
|
|
||||||
let mut new_nodes = Vec::new();
|
let mut new_nodes = Vec::new();
|
||||||
|
@ -233,7 +233,7 @@ impl Version for zcash_history::V1 {
|
||||||
/// `orchard_root` is ignored.
|
/// `orchard_root` is ignored.
|
||||||
fn block_to_history_node(
|
fn block_to_history_node(
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
_orchard_root: &orchard::tree::Root,
|
_orchard_root: &orchard::tree::Root,
|
||||||
) -> Self::NodeData {
|
) -> Self::NodeData {
|
||||||
|
@ -300,7 +300,7 @@ impl Version for V2 {
|
||||||
/// `orchard_root` is the root of the Orchard note commitment tree of the block.
|
/// `orchard_root` is the root of the Orchard note commitment tree of the block.
|
||||||
fn block_to_history_node(
|
fn block_to_history_node(
|
||||||
block: Arc<Block>,
|
block: Arc<Block>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
sapling_root: &sapling::tree::Root,
|
sapling_root: &sapling::tree::Root,
|
||||||
orchard_root: &orchard::tree::Root,
|
orchard_root: &orchard::tree::Root,
|
||||||
) -> Self::NodeData {
|
) -> Self::NodeData {
|
||||||
|
|
|
@ -11,14 +11,14 @@ use eyre::Result;
|
||||||
/// and its next block.
|
/// and its next block.
|
||||||
#[test]
|
#[test]
|
||||||
fn tree() -> Result<()> {
|
fn tree() -> Result<()> {
|
||||||
tree_for_network_upgrade(Network::Mainnet, NetworkUpgrade::Heartwood)?;
|
tree_for_network_upgrade(&Network::Mainnet, NetworkUpgrade::Heartwood)?;
|
||||||
tree_for_network_upgrade(Network::Testnet, NetworkUpgrade::Heartwood)?;
|
tree_for_network_upgrade(&Network::Testnet, NetworkUpgrade::Heartwood)?;
|
||||||
tree_for_network_upgrade(Network::Mainnet, NetworkUpgrade::Canopy)?;
|
tree_for_network_upgrade(&Network::Mainnet, NetworkUpgrade::Canopy)?;
|
||||||
tree_for_network_upgrade(Network::Testnet, NetworkUpgrade::Canopy)?;
|
tree_for_network_upgrade(&Network::Testnet, NetworkUpgrade::Canopy)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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).unwrap().0;
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
///
|
///
|
||||||
/// If passed a network/height without matching consensus branch ID (pre-Overwinter),
|
/// If passed a network/height without matching consensus branch ID (pre-Overwinter),
|
||||||
/// since `librustzcash` won't be able to parse it.
|
/// since `librustzcash` won't be able to parse it.
|
||||||
pub fn decrypts_successfully(transaction: &Transaction, network: Network, height: Height) -> bool {
|
pub fn decrypts_successfully(transaction: &Transaction, network: &Network, height: Height) -> bool {
|
||||||
let network_upgrade = NetworkUpgrade::current(network, height);
|
let network_upgrade = NetworkUpgrade::current(network, height);
|
||||||
let alt_tx = convert_tx_to_librustzcash(transaction, network_upgrade)
|
let alt_tx = convert_tx_to_librustzcash(transaction, network_upgrade)
|
||||||
.expect("zcash_primitives and Zebra transaction formats must be compatible");
|
.expect("zcash_primitives and Zebra transaction formats must be compatible");
|
||||||
|
|
|
@ -319,7 +319,7 @@ pub(crate) fn auth_digest(trans: &Transaction) -> AuthDigest {
|
||||||
/// Returns None if the address type is not valid or unrecognized.
|
/// Returns None if the address type is not valid or unrecognized.
|
||||||
pub(crate) fn transparent_output_address(
|
pub(crate) fn transparent_output_address(
|
||||||
output: &transparent::Output,
|
output: &transparent::Output,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Option<transparent::Address> {
|
) -> Option<transparent::Address> {
|
||||||
let tx_out = zp_tx::components::TxOut::try_from(output)
|
let tx_out = zp_tx::components::TxOut::try_from(output)
|
||||||
.expect("zcash_primitives and Zebra transparent output formats must be compatible");
|
.expect("zcash_primitives and Zebra transparent output formats must be compatible");
|
||||||
|
@ -337,8 +337,8 @@ pub(crate) fn transparent_output_address(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Network> for zcash_primitives::consensus::Network {
|
impl From<&Network> for zcash_primitives::consensus::Network {
|
||||||
fn from(network: Network) -> Self {
|
fn from(network: &Network) -> Self {
|
||||||
match network {
|
match network {
|
||||||
Network::Mainnet => zcash_primitives::consensus::Network::MainNetwork,
|
Network::Mainnet => zcash_primitives::consensus::Network::MainNetwork,
|
||||||
Network::Testnet => zcash_primitives::consensus::Network::TestNetwork,
|
Network::Testnet => zcash_primitives::consensus::Network::TestNetwork,
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn incremental_roots_with_blocks_for_network(network: Network) -> Result<()> {
|
||||||
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
let (blocks, sapling_roots) = network.block_sapling_roots_map();
|
||||||
|
|
||||||
let height = NetworkUpgrade::Sapling
|
let height = NetworkUpgrade::Sapling
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,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()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl Transaction {
|
||||||
/// Generate a proptest strategy for V1 Transactions
|
/// Generate a proptest strategy for V1 Transactions
|
||||||
pub fn v1_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
pub fn v1_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
||||||
(
|
(
|
||||||
transparent::Input::vec_strategy(ledger_state, MAX_ARBITRARY_ITEMS),
|
transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS),
|
||||||
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
||||||
any::<LockTime>(),
|
any::<LockTime>(),
|
||||||
)
|
)
|
||||||
|
@ -61,7 +61,7 @@ impl Transaction {
|
||||||
/// Generate a proptest strategy for V2 Transactions
|
/// Generate a proptest strategy for V2 Transactions
|
||||||
pub fn v2_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
pub fn v2_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
||||||
(
|
(
|
||||||
transparent::Input::vec_strategy(ledger_state, MAX_ARBITRARY_ITEMS),
|
transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS),
|
||||||
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
||||||
any::<LockTime>(),
|
any::<LockTime>(),
|
||||||
option::of(any::<JoinSplitData<Bctv14Proof>>()),
|
option::of(any::<JoinSplitData<Bctv14Proof>>()),
|
||||||
|
@ -80,7 +80,7 @@ impl Transaction {
|
||||||
/// Generate a proptest strategy for V3 Transactions
|
/// Generate a proptest strategy for V3 Transactions
|
||||||
pub fn v3_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
pub fn v3_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
||||||
(
|
(
|
||||||
transparent::Input::vec_strategy(ledger_state, MAX_ARBITRARY_ITEMS),
|
transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS),
|
||||||
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
||||||
any::<LockTime>(),
|
any::<LockTime>(),
|
||||||
any::<block::Height>(),
|
any::<block::Height>(),
|
||||||
|
@ -101,7 +101,7 @@ impl Transaction {
|
||||||
/// Generate a proptest strategy for V4 Transactions
|
/// Generate a proptest strategy for V4 Transactions
|
||||||
pub fn v4_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
pub fn v4_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
||||||
(
|
(
|
||||||
transparent::Input::vec_strategy(ledger_state, MAX_ARBITRARY_ITEMS),
|
transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS),
|
||||||
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
||||||
any::<LockTime>(),
|
any::<LockTime>(),
|
||||||
any::<block::Height>(),
|
any::<block::Height>(),
|
||||||
|
@ -146,7 +146,7 @@ impl Transaction {
|
||||||
NetworkUpgrade::branch_id_strategy(),
|
NetworkUpgrade::branch_id_strategy(),
|
||||||
any::<LockTime>(),
|
any::<LockTime>(),
|
||||||
any::<block::Height>(),
|
any::<block::Height>(),
|
||||||
transparent::Input::vec_strategy(ledger_state, MAX_ARBITRARY_ITEMS),
|
transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS),
|
||||||
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
||||||
option::of(any::<sapling::ShieldedData<sapling::SharedAnchor>>()),
|
option::of(any::<sapling::ShieldedData<sapling::SharedAnchor>>()),
|
||||||
option::of(any::<orchard::ShieldedData>()),
|
option::of(any::<orchard::ShieldedData>()),
|
||||||
|
@ -196,7 +196,7 @@ impl Transaction {
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> BoxedStrategy<Vec<Arc<Self>>> {
|
) -> BoxedStrategy<Vec<Arc<Self>>> {
|
||||||
// TODO: fixup coinbase miner subsidy
|
// TODO: fixup coinbase miner subsidy
|
||||||
let coinbase = Transaction::arbitrary_with(ledger_state).prop_map(Arc::new);
|
let coinbase = Transaction::arbitrary_with(ledger_state.clone()).prop_map(Arc::new);
|
||||||
ledger_state.has_coinbase = false;
|
ledger_state.has_coinbase = false;
|
||||||
let remainder = vec(
|
let remainder = vec(
|
||||||
Transaction::arbitrary_with(ledger_state).prop_map(Arc::new),
|
Transaction::arbitrary_with(ledger_state).prop_map(Arc::new),
|
||||||
|
@ -787,7 +787,7 @@ impl Arbitrary for Transaction {
|
||||||
Self::v4_strategy(ledger_state)
|
Self::v4_strategy(ledger_state)
|
||||||
}
|
}
|
||||||
NetworkUpgrade::Nu5 => prop_oneof![
|
NetworkUpgrade::Nu5 => prop_oneof![
|
||||||
Self::v4_strategy(ledger_state),
|
Self::v4_strategy(ledger_state.clone()),
|
||||||
Self::v5_strategy(ledger_state)
|
Self::v5_strategy(ledger_state)
|
||||||
]
|
]
|
||||||
.boxed(),
|
.boxed(),
|
||||||
|
@ -859,7 +859,7 @@ impl Arbitrary for VerifiedUnminedTx {
|
||||||
/// converting sapling shielded data from v4 to v5 if possible.
|
/// converting sapling shielded data from v4 to v5 if possible.
|
||||||
pub fn transaction_to_fake_v5(
|
pub fn transaction_to_fake_v5(
|
||||||
trans: &Transaction,
|
trans: &Transaction,
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: block::Height,
|
height: block::Height,
|
||||||
) -> Transaction {
|
) -> Transaction {
|
||||||
use Transaction::*;
|
use Transaction::*;
|
||||||
|
@ -993,7 +993,7 @@ fn sapling_spend_v4_to_fake_v5(
|
||||||
|
|
||||||
/// Iterate over V4 transactions in the block test vectors for the specified `network`.
|
/// Iterate over V4 transactions in the block test vectors for the specified `network`.
|
||||||
pub fn test_transactions(
|
pub fn test_transactions(
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> impl DoubleEndedIterator<Item = (block::Height, Arc<Transaction>)> {
|
) -> impl DoubleEndedIterator<Item = (block::Height, Arc<Transaction>)> {
|
||||||
let blocks = network.block_iter();
|
let blocks = network.block_iter();
|
||||||
|
|
||||||
|
@ -1005,7 +1005,7 @@ pub fn test_transactions(
|
||||||
/// These transactions are converted from non-V5 transactions that exist in the provided network
|
/// These transactions are converted from non-V5 transactions that exist in the provided network
|
||||||
/// blocks.
|
/// blocks.
|
||||||
pub fn fake_v5_transactions_for_network<'b>(
|
pub fn fake_v5_transactions_for_network<'b>(
|
||||||
network: Network,
|
network: &'b Network,
|
||||||
blocks: impl DoubleEndedIterator<Item = (&'b u32, &'b &'static [u8])> + 'b,
|
blocks: impl DoubleEndedIterator<Item = (&'b u32, &'b &'static [u8])> + 'b,
|
||||||
) -> impl DoubleEndedIterator<Item = Transaction> + 'b {
|
) -> impl DoubleEndedIterator<Item = Transaction> + 'b {
|
||||||
transactions_from_blocks(blocks)
|
transactions_from_blocks(blocks)
|
||||||
|
|
|
@ -12,7 +12,7 @@ impl Transaction {
|
||||||
/// Returns a new version 5 coinbase transaction for `network` and `height`,
|
/// Returns a new version 5 coinbase transaction for `network` and `height`,
|
||||||
/// which contains the specified `outputs`.
|
/// which contains the specified `outputs`.
|
||||||
pub fn new_v5_coinbase(
|
pub fn new_v5_coinbase(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
outputs: impl IntoIterator<Item = (Amount<NonNegative>, transparent::Script)>,
|
outputs: impl IntoIterator<Item = (Amount<NonNegative>, transparent::Script)>,
|
||||||
extra_coinbase_data: Vec<u8>,
|
extra_coinbase_data: Vec<u8>,
|
||||||
|
@ -109,7 +109,7 @@ impl Transaction {
|
||||||
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
pub fn new_v4_coinbase(
|
pub fn new_v4_coinbase(
|
||||||
_network: Network,
|
_network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
outputs: impl IntoIterator<Item = (Amount<NonNegative>, transparent::Script)>,
|
outputs: impl IntoIterator<Item = (Amount<NonNegative>, transparent::Script)>,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
|
|
|
@ -150,13 +150,13 @@ fn transaction_valid_network_upgrade_strategy() -> Result<()> {
|
||||||
// Update with new transaction versions as needed
|
// Update with new transaction versions as needed
|
||||||
let strategy = LedgerState::coinbase_strategy(None, 5, true).prop_flat_map(|ledger_state| {
|
let strategy = LedgerState::coinbase_strategy(None, 5, true).prop_flat_map(|ledger_state| {
|
||||||
(
|
(
|
||||||
Just(ledger_state.network),
|
Just(ledger_state.network.clone()),
|
||||||
Block::arbitrary_with(ledger_state),
|
Block::arbitrary_with(ledger_state),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
proptest!(|((network, block) in strategy)| {
|
proptest!(|((network, block) in strategy)| {
|
||||||
block.check_transaction_network_upgrade_consistency(network)?;
|
block.check_transaction_network_upgrade_consistency(&network)?;
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -352,7 +352,7 @@ fn fake_v5_round_trip_for_network(network: Network) {
|
||||||
let block_iter = network.block_iter();
|
let block_iter = network.block_iter();
|
||||||
|
|
||||||
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("a valid height")
|
.expect("a valid height")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
@ -380,7 +380,7 @@ fn fake_v5_round_trip_for_network(network: Network) {
|
||||||
.transactions
|
.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(AsRef::as_ref)
|
.map(AsRef::as_ref)
|
||||||
.map(|t| arbitrary::transaction_to_fake_v5(t, network, Height(*height)))
|
.map(|t| arbitrary::transaction_to_fake_v5(t, &network, Height(*height)))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -500,12 +500,12 @@ fn fake_v5_librustzcash_round_trip_for_network(network: Network) {
|
||||||
let block_iter = network.block_iter();
|
let block_iter = network.block_iter();
|
||||||
|
|
||||||
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
let overwinter_activation_height = NetworkUpgrade::Overwinter
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("a valid height")
|
.expect("a valid height")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
let nu5_activation_height = NetworkUpgrade::Nu5
|
let nu5_activation_height = NetworkUpgrade::Nu5
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.unwrap_or(Height::MAX_EXPIRY_HEIGHT)
|
.unwrap_or(Height::MAX_EXPIRY_HEIGHT)
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
@ -525,7 +525,7 @@ fn fake_v5_librustzcash_round_trip_for_network(network: Network) {
|
||||||
.transactions
|
.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(AsRef::as_ref)
|
.map(AsRef::as_ref)
|
||||||
.map(|t| arbitrary::transaction_to_fake_v5(t, network, Height(*height)))
|
.map(|t| arbitrary::transaction_to_fake_v5(t, &network, Height(*height)))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -940,7 +940,7 @@ fn binding_signatures_for_network(network: Network) {
|
||||||
let block_iter = network.block_iter();
|
let block_iter = network.block_iter();
|
||||||
|
|
||||||
for (height, bytes) in block_iter {
|
for (height, bytes) in block_iter {
|
||||||
let upgrade = NetworkUpgrade::current(network, Height(*height));
|
let upgrade = NetworkUpgrade::current(&network, Height(*height));
|
||||||
|
|
||||||
let block = bytes
|
let block = bytes
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
|
|
|
@ -426,7 +426,7 @@ impl Output {
|
||||||
/// Return the destination address from a transparent output.
|
/// Return the destination address from a transparent output.
|
||||||
///
|
///
|
||||||
/// Returns None if the address type is not valid or unrecognized.
|
/// Returns None if the address type is not valid or unrecognized.
|
||||||
pub fn address(&self, network: Network) -> Option<Address> {
|
pub fn address(&self, network: &Network) -> Option<Address> {
|
||||||
zcash_primitives::transparent_output_address(self, network)
|
zcash_primitives::transparent_output_address(self, network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ use proptest::prelude::*;
|
||||||
///
|
///
|
||||||
/// <https://zips.z.cash/protocol/protocol.pdf#transparentaddrencoding>
|
/// <https://zips.z.cash/protocol/protocol.pdf#transparentaddrencoding>
|
||||||
#[derive(
|
#[derive(
|
||||||
Copy, Clone, Eq, PartialEq, Hash, serde_with::SerializeDisplay, serde_with::DeserializeFromStr,
|
Clone, Eq, PartialEq, Hash, serde_with::SerializeDisplay, serde_with::DeserializeFromStr,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
any(test, feature = "proptest-impl"),
|
any(test, feature = "proptest-impl"),
|
||||||
|
@ -183,26 +183,26 @@ impl ToAddressWithNetwork for PublicKey {
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
/// Create an address for the given public key hash and network.
|
/// Create an address for the given public key hash and network.
|
||||||
pub fn from_pub_key_hash(network: Network, pub_key_hash: [u8; 20]) -> Self {
|
pub fn from_pub_key_hash(network: &Network, pub_key_hash: [u8; 20]) -> Self {
|
||||||
Self::PayToPublicKeyHash {
|
Self::PayToPublicKeyHash {
|
||||||
network,
|
network: network.clone(),
|
||||||
pub_key_hash,
|
pub_key_hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an address for the given script hash and network.
|
/// Create an address for the given script hash and network.
|
||||||
pub fn from_script_hash(network: Network, script_hash: [u8; 20]) -> Self {
|
pub fn from_script_hash(network: &Network, script_hash: [u8; 20]) -> Self {
|
||||||
Self::PayToScriptHash {
|
Self::PayToScriptHash {
|
||||||
network,
|
network: network.clone(),
|
||||||
script_hash,
|
script_hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the network for this address.
|
/// Returns the network for this address.
|
||||||
pub fn network(&self) -> Network {
|
pub fn network(&self) -> Network {
|
||||||
match *self {
|
match self {
|
||||||
Address::PayToScriptHash { network, .. } => network,
|
Address::PayToScriptHash { network, .. } => network.clone(),
|
||||||
Address::PayToPublicKeyHash { network, .. } => network,
|
Address::PayToPublicKeyHash { network, .. } => network.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use super::{CoinbaseData, Input, OutPoint, Script, GENESIS_COINBASE_DATA};
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
/// Construct a strategy for creating valid-ish vecs of Inputs.
|
/// Construct a strategy for creating valid-ish vecs of Inputs.
|
||||||
pub fn vec_strategy(ledger_state: LedgerState, max_size: usize) -> BoxedStrategy<Vec<Self>> {
|
pub fn vec_strategy(ledger_state: &LedgerState, max_size: usize) -> BoxedStrategy<Vec<Self>> {
|
||||||
if ledger_state.has_coinbase {
|
if ledger_state.has_coinbase {
|
||||||
Self::arbitrary_with(Some(ledger_state.height))
|
Self::arbitrary_with(Some(ledger_state.height))
|
||||||
.prop_map(|input| vec![input])
|
.prop_map(|input| vec![input])
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn input_coinbase_vecs_only_have_coinbase_input() -> Result<()> {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
let strategy = LedgerState::coinbase_strategy(None, None, false)
|
let strategy = LedgerState::coinbase_strategy(None, None, false)
|
||||||
.prop_flat_map(|ledger_state| Input::vec_strategy(ledger_state, MAX_ARBITRARY_ITEMS));
|
.prop_flat_map(|ledger_state| Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS));
|
||||||
|
|
||||||
proptest!(|(inputs in strategy.prop_map(SummaryDebug))| {
|
proptest!(|(inputs in strategy.prop_map(SummaryDebug))| {
|
||||||
let len = inputs.len();
|
let len = inputs.len();
|
||||||
|
|
|
@ -64,17 +64,17 @@ fn get_transparent_output_address() -> Result<()> {
|
||||||
// for the prefixes.
|
// for the prefixes.
|
||||||
|
|
||||||
// Script hash 1b8a9bda4b62cd0d0582b55455d0778c86f8628f
|
// Script hash 1b8a9bda4b62cd0d0582b55455d0778c86f8628f
|
||||||
let addr = transparent_output_address(&transaction.outputs()[0], Network::Mainnet)
|
let addr = transparent_output_address(&transaction.outputs()[0], &Network::Mainnet)
|
||||||
.expect("should return address");
|
.expect("should return address");
|
||||||
assert_eq!(addr.to_string(), "t3M5FDmPfWNRG3HRLddbicsuSCvKuk9hxzZ");
|
assert_eq!(addr.to_string(), "t3M5FDmPfWNRG3HRLddbicsuSCvKuk9hxzZ");
|
||||||
let addr = transparent_output_address(&transaction.outputs()[0], Network::Testnet)
|
let addr = transparent_output_address(&transaction.outputs()[0], &Network::Testnet)
|
||||||
.expect("should return address");
|
.expect("should return address");
|
||||||
assert_eq!(addr.to_string(), "t294SGSVoNq2daz15ZNbmAW65KQZ5e3nN5G");
|
assert_eq!(addr.to_string(), "t294SGSVoNq2daz15ZNbmAW65KQZ5e3nN5G");
|
||||||
// Public key hash e4ff5512ffafe9287992a1cd177ca6e408e03003
|
// Public key hash e4ff5512ffafe9287992a1cd177ca6e408e03003
|
||||||
let addr = transparent_output_address(&transaction.outputs()[1], Network::Mainnet)
|
let addr = transparent_output_address(&transaction.outputs()[1], &Network::Mainnet)
|
||||||
.expect("should return address");
|
.expect("should return address");
|
||||||
assert_eq!(addr.to_string(), "t1ekRwsd4LaSsd6NXgsx66q2HxQWTLCF44y");
|
assert_eq!(addr.to_string(), "t1ekRwsd4LaSsd6NXgsx66q2HxQWTLCF44y");
|
||||||
let addr = transparent_output_address(&transaction.outputs()[1], Network::Testnet)
|
let addr = transparent_output_address(&transaction.outputs()[1], &Network::Testnet)
|
||||||
.expect("should return address");
|
.expect("should return address");
|
||||||
assert_eq!(addr.to_string(), "tmWbBGi7TjExNmLZyMcFpxVh3ZPbGrpbX3H");
|
assert_eq!(addr.to_string(), "tmWbBGi7TjExNmLZyMcFpxVh3ZPbGrpbX3H");
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ fn get_transparent_output_address_with_blocks_for_network(network: Network) {
|
||||||
|
|
||||||
for (idx, tx) in block.transactions.iter().enumerate() {
|
for (idx, tx) in block.transactions.iter().enumerate() {
|
||||||
for output in tx.outputs() {
|
for output in tx.outputs() {
|
||||||
let addr = output.address(network);
|
let addr = output.address(&network);
|
||||||
if addr.is_none() && idx == 0 && output.lock_script.as_raw_bytes()[0] == 0x21 {
|
if addr.is_none() && idx == 0 && output.lock_script.as_raw_bytes()[0] == 0x21 {
|
||||||
// There are a bunch of coinbase transactions with pay-to-pubkey scripts
|
// There are a bunch of coinbase transactions with pay-to-pubkey scripts
|
||||||
// which we don't support; skip them
|
// which we don't support; skip them
|
||||||
|
|
|
@ -454,7 +454,7 @@ fn check_testnet_minimum_difficulty_block(height: block::Height) -> Result<(), R
|
||||||
// threshold, as documented in ZIP-205 and ZIP-208:
|
// threshold, as documented in ZIP-205 and ZIP-208:
|
||||||
// https://zips.z.cash/zip-0205#change-to-difficulty-adjustment-on-testnet
|
// https://zips.z.cash/zip-0205#change-to-difficulty-adjustment-on-testnet
|
||||||
// https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-testnet
|
// https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-testnet
|
||||||
match NetworkUpgrade::minimum_difficulty_spacing_for_height(Network::Testnet, height) {
|
match NetworkUpgrade::minimum_difficulty_spacing_for_height(&Network::Testnet, height) {
|
||||||
None => Err(eyre!("the minimum difficulty rule is not active"))?,
|
None => Err(eyre!("the minimum difficulty rule is not active"))?,
|
||||||
Some(spacing) if (time_gap <= spacing) => Err(eyre!(
|
Some(spacing) if (time_gap <= spacing) => Err(eyre!(
|
||||||
"minimum difficulty block times must be more than 6 target spacing intervals apart"
|
"minimum difficulty block times must be more than 6 target spacing intervals apart"
|
||||||
|
|
|
@ -108,9 +108,9 @@ where
|
||||||
V::Future: Send + 'static,
|
V::Future: Send + 'static,
|
||||||
{
|
{
|
||||||
/// Creates a new SemanticBlockVerifier
|
/// Creates a new SemanticBlockVerifier
|
||||||
pub fn new(network: Network, state_service: S, transaction_verifier: V) -> Self {
|
pub fn new(network: &Network, state_service: S, transaction_verifier: V) -> Self {
|
||||||
Self {
|
Self {
|
||||||
network,
|
network: network.clone(),
|
||||||
state_service,
|
state_service,
|
||||||
transaction_verifier,
|
transaction_verifier,
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ where
|
||||||
fn call(&mut self, request: Request) -> Self::Future {
|
fn call(&mut self, request: Request) -> Self::Future {
|
||||||
let mut state_service = self.state_service.clone();
|
let mut state_service = self.state_service.clone();
|
||||||
let mut transaction_verifier = self.transaction_verifier.clone();
|
let mut transaction_verifier = self.transaction_verifier.clone();
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
|
|
||||||
let block = request.block();
|
let block = request.block();
|
||||||
|
|
||||||
|
@ -180,11 +180,11 @@ where
|
||||||
// > acceptance rules (excluding the check for a valid proof-of-work).
|
// > acceptance rules (excluding the check for a valid proof-of-work).
|
||||||
// <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
|
// <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
|
||||||
if request.is_proposal() {
|
if request.is_proposal() {
|
||||||
check::difficulty_threshold_is_valid(&block.header, network, &height, &hash)?;
|
check::difficulty_threshold_is_valid(&block.header, &network, &height, &hash)?;
|
||||||
} else {
|
} else {
|
||||||
// Do the difficulty checks first, to raise the threshold for
|
// Do the difficulty checks first, to raise the threshold for
|
||||||
// attacks that use any other fields.
|
// attacks that use any other fields.
|
||||||
check::difficulty_is_valid(&block.header, network, &height, &hash)?;
|
check::difficulty_is_valid(&block.header, &network, &height, &hash)?;
|
||||||
check::equihash_solution_is_valid(&block.header)?;
|
check::equihash_solution_is_valid(&block.header)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ where
|
||||||
let transaction_hashes: Arc<[_]> =
|
let transaction_hashes: Arc<[_]> =
|
||||||
block.transactions.iter().map(|t| t.hash()).collect();
|
block.transactions.iter().map(|t| t.hash()).collect();
|
||||||
|
|
||||||
check::merkle_root_validity(network, &block, &transaction_hashes)?;
|
check::merkle_root_validity(&network, &block, &transaction_hashes)?;
|
||||||
|
|
||||||
// Since errors cause an early exit, try to do the
|
// Since errors cause an early exit, try to do the
|
||||||
// quick checks first.
|
// quick checks first.
|
||||||
|
@ -205,12 +205,12 @@ where
|
||||||
check::time_is_valid_at(&block.header, now, &height, &hash)
|
check::time_is_valid_at(&block.header, now, &height, &hash)
|
||||||
.map_err(VerifyBlockError::Time)?;
|
.map_err(VerifyBlockError::Time)?;
|
||||||
let coinbase_tx = check::coinbase_is_first(&block)?;
|
let coinbase_tx = check::coinbase_is_first(&block)?;
|
||||||
check::subsidy_is_valid(&block, network)?;
|
check::subsidy_is_valid(&block, &network)?;
|
||||||
|
|
||||||
// Now do the slower checks
|
// Now do the slower checks
|
||||||
|
|
||||||
// Check compatibility with ZIP-212 shielded Sapling and Orchard coinbase output decryption
|
// Check compatibility with ZIP-212 shielded Sapling and Orchard coinbase output decryption
|
||||||
tx::check::coinbase_outputs_are_decryptable(&coinbase_tx, network, height)?;
|
tx::check::coinbase_outputs_are_decryptable(&coinbase_tx, &network, height)?;
|
||||||
|
|
||||||
// Send transactions to the transaction verifier to be checked
|
// Send transactions to the transaction verifier to be checked
|
||||||
let mut async_checks = FuturesUnordered::new();
|
let mut async_checks = FuturesUnordered::new();
|
||||||
|
@ -277,7 +277,7 @@ where
|
||||||
hash,
|
hash,
|
||||||
source: amount_error,
|
source: amount_error,
|
||||||
})?;
|
})?;
|
||||||
check::miner_fees_are_valid(&block, network, block_miner_fees)?;
|
check::miner_fees_are_valid(&block, &network, block_miner_fees)?;
|
||||||
|
|
||||||
// Finally, submit the block for contextual verification.
|
// Finally, submit the block for contextual verification.
|
||||||
let new_outputs = Arc::into_inner(known_utxos)
|
let new_outputs = Arc::into_inner(known_utxos)
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn coinbase_is_first(block: &Block) -> Result<Arc<transaction::Transaction>,
|
||||||
/// If the header difficulty threshold is invalid, returns an error containing `height` and `hash`.
|
/// If the header difficulty threshold is invalid, returns an error containing `height` and `hash`.
|
||||||
pub fn difficulty_threshold_is_valid(
|
pub fn difficulty_threshold_is_valid(
|
||||||
header: &Header,
|
header: &Header,
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: &Height,
|
height: &Height,
|
||||||
hash: &Hash,
|
hash: &Hash,
|
||||||
) -> Result<ExpandedDifficulty, BlockError> {
|
) -> Result<ExpandedDifficulty, BlockError> {
|
||||||
|
@ -86,7 +86,7 @@ pub fn difficulty_threshold_is_valid(
|
||||||
*height,
|
*height,
|
||||||
*hash,
|
*hash,
|
||||||
difficulty_threshold,
|
difficulty_threshold,
|
||||||
network,
|
network.clone(),
|
||||||
network.target_difficulty_limit(),
|
network.target_difficulty_limit(),
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ pub fn difficulty_threshold_is_valid(
|
||||||
/// If the block is invalid, returns an error containing `height` and `hash`.
|
/// If the block is invalid, returns an error containing `height` and `hash`.
|
||||||
pub fn difficulty_is_valid(
|
pub fn difficulty_is_valid(
|
||||||
header: &Header,
|
header: &Header,
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: &Height,
|
height: &Height,
|
||||||
hash: &Hash,
|
hash: &Hash,
|
||||||
) -> Result<(), BlockError> {
|
) -> Result<(), BlockError> {
|
||||||
|
@ -123,7 +123,7 @@ pub fn difficulty_is_valid(
|
||||||
*height,
|
*height,
|
||||||
*hash,
|
*hash,
|
||||||
difficulty_threshold,
|
difficulty_threshold,
|
||||||
network,
|
network.clone(),
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ pub fn equihash_solution_is_valid(header: &Header) -> Result<(), equihash::Error
|
||||||
/// Returns `Ok(())` if the block subsidy in `block` is valid for `network`
|
/// Returns `Ok(())` if the block subsidy in `block` is valid for `network`
|
||||||
///
|
///
|
||||||
/// [3.9]: https://zips.z.cash/protocol/protocol.pdf#subsidyconcepts
|
/// [3.9]: https://zips.z.cash/protocol/protocol.pdf#subsidyconcepts
|
||||||
pub fn subsidy_is_valid(block: &Block, network: Network) -> Result<(), BlockError> {
|
pub fn subsidy_is_valid(block: &Block, network: &Network) -> Result<(), BlockError> {
|
||||||
let height = block.coinbase_height().ok_or(SubsidyError::NoCoinbase)?;
|
let height = block.coinbase_height().ok_or(SubsidyError::NoCoinbase)?;
|
||||||
let coinbase = block.transactions.first().ok_or(SubsidyError::NoCoinbase)?;
|
let coinbase = block.transactions.first().ok_or(SubsidyError::NoCoinbase)?;
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ pub fn subsidy_is_valid(block: &Block, network: Network) -> Result<(), BlockErro
|
||||||
subsidy::funding_streams::funding_stream_address(height, network, receiver);
|
subsidy::funding_streams::funding_stream_address(height, network, receiver);
|
||||||
|
|
||||||
let has_expected_output =
|
let has_expected_output =
|
||||||
subsidy::funding_streams::filter_outputs_by_address(coinbase, address)
|
subsidy::funding_streams::filter_outputs_by_address(coinbase, &address)
|
||||||
.iter()
|
.iter()
|
||||||
.map(zebra_chain::transparent::Output::value)
|
.map(zebra_chain::transparent::Output::value)
|
||||||
.any(|value| value == expected_amount);
|
.any(|value| value == expected_amount);
|
||||||
|
@ -210,7 +210,7 @@ pub fn subsidy_is_valid(block: &Block, network: Network) -> Result<(), BlockErro
|
||||||
/// [7.1.2]: https://zips.z.cash/protocol/protocol.pdf#txnconsensus
|
/// [7.1.2]: https://zips.z.cash/protocol/protocol.pdf#txnconsensus
|
||||||
pub fn miner_fees_are_valid(
|
pub fn miner_fees_are_valid(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
network: Network,
|
network: &Network,
|
||||||
block_miner_fees: Amount<NonNegative>,
|
block_miner_fees: Amount<NonNegative>,
|
||||||
) -> Result<(), BlockError> {
|
) -> Result<(), BlockError> {
|
||||||
let height = block.coinbase_height().ok_or(SubsidyError::NoCoinbase)?;
|
let height = block.coinbase_height().ok_or(SubsidyError::NoCoinbase)?;
|
||||||
|
@ -289,7 +289,7 @@ pub fn time_is_valid_at(
|
||||||
/// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus
|
/// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus
|
||||||
/// [7.6]: https://zips.z.cash/protocol/nu5.pdf#blockheader
|
/// [7.6]: https://zips.z.cash/protocol/nu5.pdf#blockheader
|
||||||
pub fn merkle_root_validity(
|
pub fn merkle_root_validity(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block: &Block,
|
block: &Block,
|
||||||
transaction_hashes: &[transaction::Hash],
|
transaction_hashes: &[transaction::Hash],
|
||||||
) -> Result<(), BlockError> {
|
) -> Result<(), BlockError> {
|
||||||
|
|
|
@ -23,13 +23,13 @@ mod tests;
|
||||||
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||||
pub fn funding_stream_values(
|
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).unwrap();
|
||||||
let mut results = HashMap::new();
|
let mut results = HashMap::new();
|
||||||
|
|
||||||
if height >= canopy_height {
|
if height >= canopy_height {
|
||||||
let range = FUNDING_STREAM_HEIGHT_RANGES.get(&network).unwrap();
|
let range = FUNDING_STREAM_HEIGHT_RANGES.get(network).unwrap();
|
||||||
if range.contains(&height) {
|
if range.contains(&height) {
|
||||||
let block_subsidy = block_subsidy(height, network)?;
|
let block_subsidy = block_subsidy(height, network)?;
|
||||||
for (&receiver, &numerator) in FUNDING_STREAM_RECEIVER_NUMERATORS.iter() {
|
for (&receiver, &numerator) in FUNDING_STREAM_RECEIVER_NUMERATORS.iter() {
|
||||||
|
@ -52,7 +52,7 @@ pub fn funding_stream_values(
|
||||||
/// as described in [protocol specification §7.10][7.10]
|
/// as described in [protocol specification §7.10][7.10]
|
||||||
///
|
///
|
||||||
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
||||||
fn funding_stream_address_period(height: Height, network: Network) -> u32 {
|
fn funding_stream_address_period(height: Height, network: &Network) -> u32 {
|
||||||
// Spec equation: `address_period = floor((height - (height_for_halving(1) - post_blossom_halving_interval))/funding_stream_address_change_interval)`,
|
// Spec equation: `address_period = floor((height - (height_for_halving(1) - post_blossom_halving_interval))/funding_stream_address_change_interval)`,
|
||||||
// <https://zips.z.cash/protocol/protocol.pdf#fundingstreams>
|
// <https://zips.z.cash/protocol/protocol.pdf#fundingstreams>
|
||||||
//
|
//
|
||||||
|
@ -76,14 +76,14 @@ fn funding_stream_address_period(height: Height, network: Network) -> u32 {
|
||||||
/// as described in [protocol specification §7.10][7.10]
|
/// as described in [protocol specification §7.10][7.10]
|
||||||
///
|
///
|
||||||
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
||||||
fn funding_stream_address_index(height: Height, network: Network) -> usize {
|
fn funding_stream_address_index(height: Height, network: &Network) -> usize {
|
||||||
let num_addresses = network.num_funding_streams();
|
let num_addresses = network.num_funding_streams();
|
||||||
|
|
||||||
let index = 1u32
|
let index = 1u32
|
||||||
.checked_add(funding_stream_address_period(height, network))
|
.checked_add(funding_stream_address_period(height, network))
|
||||||
.expect("no overflow should happen in this sum")
|
.expect("no overflow should happen in this sum")
|
||||||
.checked_sub(funding_stream_address_period(
|
.checked_sub(funding_stream_address_period(
|
||||||
FUNDING_STREAM_HEIGHT_RANGES.get(&network).unwrap().start,
|
FUNDING_STREAM_HEIGHT_RANGES.get(network).unwrap().start,
|
||||||
network,
|
network,
|
||||||
))
|
))
|
||||||
.expect("no overflow should happen in this sub") as usize;
|
.expect("no overflow should happen in this sub") as usize;
|
||||||
|
@ -100,12 +100,12 @@ fn funding_stream_address_index(height: Height, network: Network) -> usize {
|
||||||
/// only use transparent addresses,
|
/// only use transparent addresses,
|
||||||
pub fn funding_stream_address(
|
pub fn funding_stream_address(
|
||||||
height: Height,
|
height: Height,
|
||||||
network: Network,
|
network: &Network,
|
||||||
receiver: FundingStreamReceiver,
|
receiver: FundingStreamReceiver,
|
||||||
) -> transparent::Address {
|
) -> transparent::Address {
|
||||||
let index = funding_stream_address_index(height, network);
|
let index = funding_stream_address_index(height, network);
|
||||||
let address = &FUNDING_STREAM_ADDRESSES
|
let address = &FUNDING_STREAM_ADDRESSES
|
||||||
.get(&network)
|
.get(network)
|
||||||
.expect("there is always another hash map as value for a given valid network")
|
.expect("there is always another hash map as value for a given valid network")
|
||||||
.get(&receiver)
|
.get(&receiver)
|
||||||
.expect("in the inner hash map there is always a vector of strings with addresses")[index];
|
.expect("in the inner hash map there is always a vector of strings with addresses")[index];
|
||||||
|
@ -127,7 +127,7 @@ pub fn funding_stream_recipient_info(
|
||||||
/// as the given lock_script as described in [protocol specification §7.10][7.10]
|
/// as the given lock_script as described in [protocol specification §7.10][7.10]
|
||||||
///
|
///
|
||||||
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
||||||
pub fn check_script_form(lock_script: &Script, address: transparent::Address) -> bool {
|
pub fn check_script_form(lock_script: &Script, address: &transparent::Address) -> bool {
|
||||||
assert!(
|
assert!(
|
||||||
address.is_script_hash(),
|
address.is_script_hash(),
|
||||||
"incorrect funding stream address constant: {address} \
|
"incorrect funding stream address constant: {address} \
|
||||||
|
@ -141,7 +141,7 @@ pub fn check_script_form(lock_script: &Script, address: transparent::Address) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new funding stream coinbase output lock script, which pays to the P2SH `address`.
|
/// Returns a new funding stream coinbase output lock script, which pays to the P2SH `address`.
|
||||||
pub fn new_coinbase_script(address: transparent::Address) -> Script {
|
pub fn new_coinbase_script(address: &transparent::Address) -> Script {
|
||||||
assert!(
|
assert!(
|
||||||
address.is_script_hash(),
|
address.is_script_hash(),
|
||||||
"incorrect coinbase script address: {address} \
|
"incorrect coinbase script address: {address} \
|
||||||
|
@ -158,7 +158,7 @@ pub fn new_coinbase_script(address: transparent::Address) -> Script {
|
||||||
/// Returns a list of outputs in `transaction`, which have a script address equal to `address`.
|
/// Returns a list of outputs in `transaction`, which have a script address equal to `address`.
|
||||||
pub fn filter_outputs_by_address(
|
pub fn filter_outputs_by_address(
|
||||||
transaction: &Transaction,
|
transaction: &Transaction,
|
||||||
address: transparent::Address,
|
address: &transparent::Address,
|
||||||
) -> Vec<transparent::Output> {
|
) -> Vec<transparent::Output> {
|
||||||
transaction
|
transaction
|
||||||
.outputs()
|
.outputs()
|
||||||
|
|
|
@ -8,7 +8,7 @@ use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_funding_stream_values() -> Result<(), Report> {
|
fn test_funding_stream_values() -> Result<(), Report> {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
let network = Network::Mainnet;
|
let network = &Network::Mainnet;
|
||||||
|
|
||||||
// funding streams not active
|
// funding streams not active
|
||||||
let canopy_height_minus1 = Canopy.activation_height(network).unwrap() - 1;
|
let canopy_height_minus1 = Canopy.activation_height(network).unwrap() - 1;
|
||||||
|
@ -44,7 +44,7 @@ fn test_funding_stream_values() -> Result<(), Report> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// funding stream period is ending
|
// funding stream period is ending
|
||||||
let range = FUNDING_STREAM_HEIGHT_RANGES.get(&network).unwrap();
|
let range = FUNDING_STREAM_HEIGHT_RANGES.get(network).unwrap();
|
||||||
let end = range.end;
|
let end = range.end;
|
||||||
let last = end - 1;
|
let last = end - 1;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ fn test_funding_stream_addresses() -> Result<(), Report> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Asserts if address is not a P2SH address.
|
// Asserts if address is not a P2SH address.
|
||||||
let _script = new_coinbase_script(address);
|
let _script = new_coinbase_script(&address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use crate::{funding_stream_values, parameters::subsidy::*};
|
||||||
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||||
///
|
///
|
||||||
/// Returns `None` if the divisor would overflow a `u64`.
|
/// Returns `None` if the divisor would overflow a `u64`.
|
||||||
pub fn halving_divisor(height: Height, network: Network) -> Option<u64> {
|
pub fn halving_divisor(height: Height, network: &Network) -> Option<u64> {
|
||||||
let blossom_height = Blossom
|
let blossom_height = Blossom
|
||||||
.activation_height(network)
|
.activation_height(network)
|
||||||
.expect("blossom activation height should be available");
|
.expect("blossom activation height should be available");
|
||||||
|
@ -64,7 +64,7 @@ pub fn halving_divisor(height: Height, network: Network) -> Option<u64> {
|
||||||
/// `BlockSubsidy(height)` as described in [protocol specification §7.8][7.8]
|
/// `BlockSubsidy(height)` as described in [protocol specification §7.8][7.8]
|
||||||
///
|
///
|
||||||
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||||
pub fn block_subsidy(height: Height, network: Network) -> Result<Amount<NonNegative>, Error> {
|
pub fn block_subsidy(height: Height, network: &Network) -> Result<Amount<NonNegative>, Error> {
|
||||||
let blossom_height = Blossom
|
let blossom_height = Blossom
|
||||||
.activation_height(network)
|
.activation_height(network)
|
||||||
.expect("blossom activation height should be available");
|
.expect("blossom activation height should be available");
|
||||||
|
@ -97,7 +97,7 @@ pub fn block_subsidy(height: Height, network: Network) -> Result<Amount<NonNegat
|
||||||
/// `MinerSubsidy(height)` as described in [protocol specification §7.8][7.8]
|
/// `MinerSubsidy(height)` as described in [protocol specification §7.8][7.8]
|
||||||
///
|
///
|
||||||
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||||
pub fn miner_subsidy(height: Height, network: Network) -> Result<Amount<NonNegative>, Error> {
|
pub fn miner_subsidy(height: Height, network: &Network) -> Result<Amount<NonNegative>, Error> {
|
||||||
let total_funding_stream_amount: Result<Amount<NonNegative>, _> =
|
let total_funding_stream_amount: Result<Amount<NonNegative>, _> =
|
||||||
funding_stream_values(height, network)?.values().sum();
|
funding_stream_values(height, network)?.values().sum();
|
||||||
|
|
||||||
|
@ -123,13 +123,13 @@ mod test {
|
||||||
fn halving_test() -> Result<(), Report> {
|
fn halving_test() -> Result<(), Report> {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
halving_for_network(Network::Mainnet)?;
|
halving_for_network(&Network::Mainnet)?;
|
||||||
halving_for_network(Network::Testnet)?;
|
halving_for_network(&Network::Testnet)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn halving_for_network(network: Network) -> Result<(), Report> {
|
fn halving_for_network(network: &Network) -> Result<(), Report> {
|
||||||
let blossom_height = Blossom.activation_height(network).unwrap();
|
let blossom_height = Blossom.activation_height(network).unwrap();
|
||||||
let first_halving_height = network.height_for_first_halving();
|
let first_halving_height = network.height_for_first_halving();
|
||||||
|
|
||||||
|
@ -249,13 +249,13 @@ mod test {
|
||||||
fn block_subsidy_test() -> Result<(), Report> {
|
fn block_subsidy_test() -> Result<(), Report> {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
block_subsidy_for_network(Network::Mainnet)?;
|
block_subsidy_for_network(&Network::Mainnet)?;
|
||||||
block_subsidy_for_network(Network::Testnet)?;
|
block_subsidy_for_network(&Network::Testnet)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_subsidy_for_network(network: Network) -> Result<(), Report> {
|
fn block_subsidy_for_network(network: &Network) -> Result<(), Report> {
|
||||||
let blossom_height = Blossom.activation_height(network).unwrap();
|
let blossom_height = Blossom.activation_height(network).unwrap();
|
||||||
let first_halving_height = network.height_for_first_halving();
|
let first_halving_height = network.height_for_first_halving();
|
||||||
|
|
||||||
|
|
|
@ -139,12 +139,12 @@ async fn check_transcripts() -> Result<(), Report> {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
let state_service = zebra_state::init_test(network);
|
let state_service = zebra_state::init_test(&network);
|
||||||
|
|
||||||
let transaction = transaction::Verifier::new(network, state_service.clone());
|
let transaction = transaction::Verifier::new(&network, state_service.clone());
|
||||||
let transaction = Buffer::new(BoxService::new(transaction), 1);
|
let transaction = Buffer::new(BoxService::new(transaction), 1);
|
||||||
let block_verifier = Buffer::new(
|
let block_verifier = Buffer::new(
|
||||||
SemanticBlockVerifier::new(network, state_service.clone(), transaction),
|
SemanticBlockVerifier::new(&network, state_service.clone(), transaction),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ fn difficulty_is_valid_for_network(network: Network) -> Result<(), Report> {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block is structurally valid");
|
.expect("block is structurally valid");
|
||||||
|
|
||||||
check::difficulty_is_valid(&block.header, network, &Height(height), &block.hash())
|
check::difficulty_is_valid(&block.header, &network, &Height(height), &block.hash())
|
||||||
.expect("the difficulty from a historical block should be valid");
|
.expect("the difficulty from a historical block should be valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ fn difficulty_validation_failure() -> Result<(), Report> {
|
||||||
|
|
||||||
// Validate the block
|
// Validate the block
|
||||||
let result =
|
let result =
|
||||||
check::difficulty_is_valid(&block.header, Network::Mainnet, &height, &hash).unwrap_err();
|
check::difficulty_is_valid(&block.header, &Network::Mainnet, &height, &hash).unwrap_err();
|
||||||
let expected = BlockError::InvalidDifficulty(height, hash);
|
let expected = BlockError::InvalidDifficulty(height, hash);
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ fn difficulty_validation_failure() -> Result<(), Report> {
|
||||||
|
|
||||||
// Validate the block as if it is a mainnet block
|
// Validate the block as if it is a mainnet block
|
||||||
let result =
|
let result =
|
||||||
check::difficulty_is_valid(&block.header, Network::Mainnet, &height, &hash).unwrap_err();
|
check::difficulty_is_valid(&block.header, &Network::Mainnet, &height, &hash).unwrap_err();
|
||||||
let expected = BlockError::TargetDifficultyLimit(
|
let expected = BlockError::TargetDifficultyLimit(
|
||||||
height,
|
height,
|
||||||
hash,
|
hash,
|
||||||
|
@ -255,7 +255,7 @@ fn difficulty_validation_failure() -> Result<(), Report> {
|
||||||
let difficulty_threshold = block.header.difficulty_threshold.to_expanded().unwrap();
|
let difficulty_threshold = block.header.difficulty_threshold.to_expanded().unwrap();
|
||||||
|
|
||||||
// Validate the block
|
// Validate the block
|
||||||
let result = check::difficulty_is_valid(&block.header, Network::Mainnet, &height, &bad_hash)
|
let result = check::difficulty_is_valid(&block.header, &Network::Mainnet, &height, &bad_hash)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
let expected =
|
let expected =
|
||||||
BlockError::DifficultyFilter(height, bad_hash, difficulty_threshold, Network::Mainnet);
|
BlockError::DifficultyFilter(height, bad_hash, difficulty_threshold, Network::Mainnet);
|
||||||
|
@ -301,12 +301,13 @@ fn subsidy_is_valid_for_network(network: Network) -> Result<(), Report> {
|
||||||
.expect("block is structurally valid");
|
.expect("block is structurally valid");
|
||||||
|
|
||||||
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 known");
|
||||||
|
|
||||||
// TODO: first halving, second halving, third halving, and very large halvings
|
// TODO: first halving, second halving, third halving, and very large halvings
|
||||||
if block::Height(height) >= canopy_activation_height {
|
if block::Height(height) >= canopy_activation_height {
|
||||||
check::subsidy_is_valid(&block, network).expect("subsidies should pass for this block");
|
check::subsidy_is_valid(&block, &network)
|
||||||
|
.expect("subsidies should pass for this block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +335,7 @@ fn coinbase_validation_failure() -> Result<(), Report> {
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
// Validate the block using subsidy_is_valid
|
// Validate the block using subsidy_is_valid
|
||||||
let result = check::subsidy_is_valid(&block, network).unwrap_err();
|
let result = check::subsidy_is_valid(&block, &network).unwrap_err();
|
||||||
let expected = BlockError::Transaction(TransactionError::Subsidy(SubsidyError::NoCoinbase));
|
let expected = BlockError::Transaction(TransactionError::Subsidy(SubsidyError::NoCoinbase));
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
|
@ -353,7 +354,7 @@ fn coinbase_validation_failure() -> Result<(), Report> {
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
// Validate the block using subsidy_is_valid
|
// Validate the block using subsidy_is_valid
|
||||||
let result = check::subsidy_is_valid(&block, network).unwrap_err();
|
let result = check::subsidy_is_valid(&block, &network).unwrap_err();
|
||||||
let expected = BlockError::Transaction(TransactionError::Subsidy(SubsidyError::NoCoinbase));
|
let expected = BlockError::Transaction(TransactionError::Subsidy(SubsidyError::NoCoinbase));
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
|
@ -378,7 +379,7 @@ fn coinbase_validation_failure() -> Result<(), Report> {
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
// Validate the block using subsidy_is_valid, which does not detect this error
|
// Validate the block using subsidy_is_valid, which does not detect this error
|
||||||
check::subsidy_is_valid(&block, network)
|
check::subsidy_is_valid(&block, &network)
|
||||||
.expect("subsidy does not check for extra coinbase transactions");
|
.expect("subsidy does not check for extra coinbase transactions");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -398,7 +399,7 @@ fn funding_stream_validation_for_network(network: Network) -> Result<(), Report>
|
||||||
let block_iter = network.block_iter();
|
let block_iter = network.block_iter();
|
||||||
|
|
||||||
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 known");
|
||||||
|
|
||||||
for (&height, block) in block_iter {
|
for (&height, block) in block_iter {
|
||||||
|
@ -406,7 +407,7 @@ fn funding_stream_validation_for_network(network: Network) -> Result<(), Report>
|
||||||
let block = Block::zcash_deserialize(&block[..]).expect("block should deserialize");
|
let block = Block::zcash_deserialize(&block[..]).expect("block should deserialize");
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
let result = check::subsidy_is_valid(&block, network);
|
let result = check::subsidy_is_valid(&block, &network);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,7 +451,7 @@ fn funding_stream_validation_failure() -> Result<(), Report> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validate it
|
// Validate it
|
||||||
let result = check::subsidy_is_valid(&block, network);
|
let result = check::subsidy_is_valid(&block, &network);
|
||||||
let expected = Err(BlockError::Transaction(TransactionError::Subsidy(
|
let expected = Err(BlockError::Transaction(TransactionError::Subsidy(
|
||||||
SubsidyError::FundingStreamNotFound,
|
SubsidyError::FundingStreamNotFound,
|
||||||
)));
|
)));
|
||||||
|
@ -480,7 +481,7 @@ fn miner_fees_validation_for_network(network: Network) -> Result<(), Report> {
|
||||||
let miner_fees = Amount::try_from(MAX_MONEY / 2).unwrap();
|
let miner_fees = Amount::try_from(MAX_MONEY / 2).unwrap();
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
let result = check::miner_fees_are_valid(&block, network, miner_fees);
|
let result = check::miner_fees_are_valid(&block, &network, miner_fees);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,7 +502,7 @@ fn miner_fees_validation_failure() -> Result<(), Report> {
|
||||||
let miner_fees = Amount::zero();
|
let miner_fees = Amount::zero();
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
let result = check::miner_fees_are_valid(&block, network, miner_fees);
|
let result = check::miner_fees_are_valid(&block, &network, miner_fees);
|
||||||
|
|
||||||
let expected = Err(BlockError::Transaction(TransactionError::Subsidy(
|
let expected = Err(BlockError::Transaction(TransactionError::Subsidy(
|
||||||
SubsidyError::InvalidMinerFees,
|
SubsidyError::InvalidMinerFees,
|
||||||
|
@ -569,7 +570,7 @@ fn merkle_root_is_valid_for_network(network: Network) -> Result<(), Report> {
|
||||||
.map(|tx| tx.hash())
|
.map(|tx| tx.hash())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
check::merkle_root_validity(network, &block, &transaction_hashes)
|
check::merkle_root_validity(&network, &block, &transaction_hashes)
|
||||||
.expect("merkle root should be valid for this block");
|
.expect("merkle root should be valid for this block");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +588,7 @@ fn merkle_root_fake_v5_for_network(network: Network) -> Result<(), Report> {
|
||||||
// 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
|
||||||
if *height
|
if *height
|
||||||
< NetworkUpgrade::Overwinter
|
< NetworkUpgrade::Overwinter
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("a valid overwinter activation height")
|
.expect("a valid overwinter activation height")
|
||||||
.0
|
.0
|
||||||
{
|
{
|
||||||
|
@ -599,7 +600,7 @@ fn merkle_root_fake_v5_for_network(network: Network) -> Result<(), Report> {
|
||||||
.transactions
|
.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(AsRef::as_ref)
|
.map(AsRef::as_ref)
|
||||||
.map(|t| transaction_to_fake_v5(t, network, Height(*height)))
|
.map(|t| transaction_to_fake_v5(t, &network, Height(*height)))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -616,7 +617,7 @@ fn merkle_root_fake_v5_for_network(network: Network) -> Result<(), Report> {
|
||||||
// but we also need to test against zcashd test vectors.
|
// but we also need to test against zcashd test vectors.
|
||||||
Arc::make_mut(&mut block.header).merkle_root = transaction_hashes.iter().cloned().collect();
|
Arc::make_mut(&mut block.header).merkle_root = transaction_hashes.iter().cloned().collect();
|
||||||
|
|
||||||
check::merkle_root_validity(network, &block, &transaction_hashes)
|
check::merkle_root_validity(&network, &block, &transaction_hashes)
|
||||||
.expect("merkle root should be valid for this block");
|
.expect("merkle root should be valid for this block");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,13 +683,13 @@ fn legacy_sigops_count_for_historic_blocks() {
|
||||||
fn transaction_expiration_height_validation() -> Result<(), Report> {
|
fn transaction_expiration_height_validation() -> Result<(), Report> {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
transaction_expiration_height_for_network(Network::Mainnet)?;
|
transaction_expiration_height_for_network(&Network::Mainnet)?;
|
||||||
transaction_expiration_height_for_network(Network::Testnet)?;
|
transaction_expiration_height_for_network(&Network::Testnet)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_expiration_height_for_network(network: Network) -> Result<(), Report> {
|
fn transaction_expiration_height_for_network(network: &Network) -> Result<(), Report> {
|
||||||
let block_iter = network.block_iter();
|
let block_iter = network.block_iter();
|
||||||
|
|
||||||
for (&height, block) in block_iter {
|
for (&height, block) in block_iter {
|
||||||
|
|
|
@ -203,7 +203,7 @@ where
|
||||||
/// `tower::Buffer` service.
|
/// `tower::Buffer` service.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
network: Network,
|
network: &Network,
|
||||||
initial_tip: Option<(block::Height, block::Hash)>,
|
initial_tip: Option<(block::Height, block::Hash)>,
|
||||||
state_service: S,
|
state_service: S,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -232,7 +232,7 @@ where
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn from_list(
|
pub(crate) fn from_list(
|
||||||
list: impl IntoIterator<Item = (block::Height, block::Hash)>,
|
list: impl IntoIterator<Item = (block::Height, block::Hash)>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
initial_tip: Option<(block::Height, block::Hash)>,
|
initial_tip: Option<(block::Height, block::Hash)>,
|
||||||
state_service: S,
|
state_service: S,
|
||||||
) -> Result<Self, VerifyCheckpointError> {
|
) -> Result<Self, VerifyCheckpointError> {
|
||||||
|
@ -253,7 +253,7 @@ where
|
||||||
/// hard-coded checkpoint lists. See that function for more details.
|
/// hard-coded checkpoint lists. See that function for more details.
|
||||||
pub(crate) fn from_checkpoint_list(
|
pub(crate) fn from_checkpoint_list(
|
||||||
checkpoint_list: CheckpointList,
|
checkpoint_list: CheckpointList,
|
||||||
network: Network,
|
network: &Network,
|
||||||
initial_tip: Option<(block::Height, block::Hash)>,
|
initial_tip: Option<(block::Height, block::Hash)>,
|
||||||
state_service: S,
|
state_service: S,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -273,7 +273,7 @@ where
|
||||||
|
|
||||||
let verifier = CheckpointVerifier {
|
let verifier = CheckpointVerifier {
|
||||||
checkpoint_list,
|
checkpoint_list,
|
||||||
network,
|
network: network.clone(),
|
||||||
initial_tip_hash,
|
initial_tip_hash,
|
||||||
state_service,
|
state_service,
|
||||||
queued: BTreeMap::new(),
|
queued: BTreeMap::new(),
|
||||||
|
@ -595,14 +595,14 @@ where
|
||||||
.ok_or(VerifyCheckpointError::CoinbaseHeight { hash })?;
|
.ok_or(VerifyCheckpointError::CoinbaseHeight { hash })?;
|
||||||
self.check_height(height)?;
|
self.check_height(height)?;
|
||||||
|
|
||||||
crate::block::check::difficulty_is_valid(&block.header, self.network, &height, &hash)?;
|
crate::block::check::difficulty_is_valid(&block.header, &self.network, &height, &hash)?;
|
||||||
crate::block::check::equihash_solution_is_valid(&block.header)?;
|
crate::block::check::equihash_solution_is_valid(&block.header)?;
|
||||||
|
|
||||||
// don't do precalculation until the block passes basic difficulty checks
|
// don't do precalculation until the block passes basic difficulty checks
|
||||||
let block = CheckpointVerifiedBlock::with_hash(block, hash);
|
let block = CheckpointVerifiedBlock::with_hash(block, hash);
|
||||||
|
|
||||||
crate::block::check::merkle_root_validity(
|
crate::block::check::merkle_root_validity(
|
||||||
self.network,
|
&self.network,
|
||||||
&block.block,
|
&block.block,
|
||||||
&block.transaction_hashes,
|
&block.transaction_hashes,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -45,9 +45,9 @@ async fn single_item_checkpoint_list() -> Result<(), Report> {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
let mut checkpoint_verifier =
|
let mut checkpoint_verifier =
|
||||||
CheckpointVerifier::from_list(genesis_checkpoint_list, Mainnet, None, state_service)
|
CheckpointVerifier::from_list(genesis_checkpoint_list, &Mainnet, None, state_service)
|
||||||
.map_err(|e| eyre!(e))?;
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -124,9 +124,9 @@ async fn multi_item_checkpoint_list() -> Result<(), Report> {
|
||||||
.map(|(_block, height, hash)| (*height, *hash))
|
.map(|(_block, height, hash)| (*height, *hash))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
let mut checkpoint_verifier =
|
let mut checkpoint_verifier =
|
||||||
CheckpointVerifier::from_list(checkpoint_list, Mainnet, None, state_service)
|
CheckpointVerifier::from_list(checkpoint_list, &Mainnet, None, state_service)
|
||||||
.map_err(|e| eyre!(e))?;
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -268,10 +268,10 @@ async fn continuous_blockchain(
|
||||||
let initial_tip = restart_height.map(|block::Height(height)| {
|
let initial_tip = restart_height.map(|block::Height(height)| {
|
||||||
(blockchain[height as usize].1, blockchain[height as usize].2)
|
(blockchain[height as usize].1, blockchain[height as usize].2)
|
||||||
});
|
});
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
let mut checkpoint_verifier = CheckpointVerifier::from_list(
|
let mut checkpoint_verifier = CheckpointVerifier::from_list(
|
||||||
checkpoint_list,
|
checkpoint_list,
|
||||||
network,
|
&network,
|
||||||
initial_tip,
|
initial_tip,
|
||||||
state_service.clone(),
|
state_service.clone(),
|
||||||
)
|
)
|
||||||
|
@ -437,9 +437,9 @@ async fn block_higher_than_max_checkpoint_fail() -> Result<(), Report> {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
let mut checkpoint_verifier =
|
let mut checkpoint_verifier =
|
||||||
CheckpointVerifier::from_list(genesis_checkpoint_list, Mainnet, None, state_service)
|
CheckpointVerifier::from_list(genesis_checkpoint_list, &Mainnet, None, state_service)
|
||||||
.map_err(|e| eyre!(e))?;
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -511,9 +511,9 @@ async fn wrong_checkpoint_hash_fail() -> Result<(), Report> {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
let mut checkpoint_verifier =
|
let mut checkpoint_verifier =
|
||||||
CheckpointVerifier::from_list(genesis_checkpoint_list, Mainnet, None, state_service)
|
CheckpointVerifier::from_list(genesis_checkpoint_list, &Mainnet, None, state_service)
|
||||||
.map_err(|e| eyre!(e))?;
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -684,9 +684,9 @@ async fn checkpoint_drop_cancel() -> Result<(), Report> {
|
||||||
.map(|(_block, height, hash)| (*height, *hash))
|
.map(|(_block, height, hash)| (*height, *hash))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
let mut checkpoint_verifier =
|
let mut checkpoint_verifier =
|
||||||
CheckpointVerifier::from_list(checkpoint_list, Mainnet, None, state_service)
|
CheckpointVerifier::from_list(checkpoint_list, &Mainnet, None, state_service)
|
||||||
.map_err(|e| eyre!(e))?;
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -767,9 +767,9 @@ async fn hard_coded_mainnet() -> Result<(), Report> {
|
||||||
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
||||||
let hash0 = block0.hash();
|
let hash0 = block0.hash();
|
||||||
|
|
||||||
let state_service = zebra_state::init_test(Mainnet);
|
let state_service = zebra_state::init_test(&Mainnet);
|
||||||
// Use the hard-coded checkpoint list
|
// Use the hard-coded checkpoint list
|
||||||
let mut checkpoint_verifier = CheckpointVerifier::new(Network::Mainnet, None, state_service);
|
let mut checkpoint_verifier = CheckpointVerifier::new(&Network::Mainnet, None, state_service);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
checkpoint_verifier.previous_checkpoint_height(),
|
checkpoint_verifier.previous_checkpoint_height(),
|
||||||
|
|
|
@ -224,7 +224,7 @@ impl ParameterSubsidy for Network {
|
||||||
// <https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams>
|
// <https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams>
|
||||||
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"),
|
||||||
Network::Testnet => FIRST_HALVING_TESTNET,
|
Network::Testnet => FIRST_HALVING_TESTNET,
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,7 @@ where
|
||||||
#[instrument(skip(state_service))]
|
#[instrument(skip(state_service))]
|
||||||
pub async fn init<S>(
|
pub async fn init<S>(
|
||||||
config: Config,
|
config: Config,
|
||||||
network: Network,
|
network: &Network,
|
||||||
mut state_service: S,
|
mut state_service: S,
|
||||||
) -> (
|
) -> (
|
||||||
Buffer<BoxService<Request, block::Hash, RouterError>, Request>,
|
Buffer<BoxService<Request, block::Hash, RouterError>, Request>,
|
||||||
|
@ -240,8 +240,14 @@ where
|
||||||
|
|
||||||
// Make sure the state contains the known best chain checkpoints, in a separate thread.
|
// Make sure the state contains the known best chain checkpoints, in a separate thread.
|
||||||
|
|
||||||
let checkpoint_state_service = state_service.clone();
|
let (checkpoint_state_service, checkpoint_sync, network_clone) = {
|
||||||
let checkpoint_sync = config.checkpoint_sync;
|
let checkpoint_state_service = state_service.clone();
|
||||||
|
let checkpoint_sync = config.checkpoint_sync;
|
||||||
|
let network_clone = network.clone();
|
||||||
|
|
||||||
|
(checkpoint_state_service, checkpoint_sync, network_clone)
|
||||||
|
};
|
||||||
|
|
||||||
let state_checkpoint_verify_handle = tokio::task::spawn(
|
let state_checkpoint_verify_handle = tokio::task::spawn(
|
||||||
// TODO: move this into an async function?
|
// TODO: move this into an async function?
|
||||||
async move {
|
async move {
|
||||||
|
@ -263,7 +269,7 @@ where
|
||||||
// > activation block hashes given in § 3.12 ‘Mainnet and Testnet’ on p. 20.
|
// > activation block hashes given in § 3.12 ‘Mainnet and Testnet’ on p. 20.
|
||||||
//
|
//
|
||||||
// <https://zips.z.cash/protocol/protocol.pdf#blockchain>
|
// <https://zips.z.cash/protocol/protocol.pdf#blockchain>
|
||||||
let full_checkpoints = network.checkpoint_list();
|
let full_checkpoints = network_clone.checkpoint_list();
|
||||||
let mut already_warned = false;
|
let mut already_warned = false;
|
||||||
|
|
||||||
for (height, checkpoint_hash) in full_checkpoints.iter() {
|
for (height, checkpoint_hash) in full_checkpoints.iter() {
|
||||||
|
@ -360,7 +366,7 @@ where
|
||||||
|
|
||||||
/// Parses the checkpoint list for `network` and `config`.
|
/// Parses the checkpoint list for `network` and `config`.
|
||||||
/// Returns the checkpoint list and maximum checkpoint height.
|
/// Returns the checkpoint list and maximum checkpoint height.
|
||||||
pub fn init_checkpoint_list(config: Config, network: Network) -> (CheckpointList, Height) {
|
pub fn init_checkpoint_list(config: Config, network: &Network) -> (CheckpointList, Height) {
|
||||||
// TODO: Zebra parses the checkpoint list three times at startup.
|
// TODO: Zebra parses the checkpoint list three times at startup.
|
||||||
// Instead, cache the checkpoint list for each `network`.
|
// Instead, cache the checkpoint list for each `network`.
|
||||||
let list = network.checkpoint_list();
|
let list = network.checkpoint_list();
|
||||||
|
|
|
@ -65,13 +65,13 @@ async fn verifiers_from_network(
|
||||||
+ Clone
|
+ Clone
|
||||||
+ 'static,
|
+ 'static,
|
||||||
) {
|
) {
|
||||||
let state_service = zs::init_test(network);
|
let state_service = zs::init_test(&network);
|
||||||
let (
|
let (
|
||||||
block_verifier_router,
|
block_verifier_router,
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_groth16_download_handle,
|
_groth16_download_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = crate::router::init(Config::default(), network, state_service.clone()).await;
|
) = crate::router::init(Config::default(), &network, state_service.clone()).await;
|
||||||
|
|
||||||
// We can drop the download task handle here, because:
|
// We can drop the download task handle here, because:
|
||||||
// - if the download task fails, the tests will panic, and
|
// - if the download task fails, the tests will panic, and
|
||||||
|
@ -172,7 +172,7 @@ async fn verify_checkpoint(config: Config) -> Result<(), Report> {
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_groth16_download_handle,
|
_groth16_download_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = super::init(config.clone(), network, zs::init_test(network)).await;
|
) = super::init(config.clone(), &network, zs::init_test(&network)).await;
|
||||||
|
|
||||||
// Add a timeout layer
|
// Add a timeout layer
|
||||||
let block_verifier_router =
|
let block_verifier_router =
|
||||||
|
|
|
@ -73,9 +73,9 @@ where
|
||||||
ZS::Future: Send + 'static,
|
ZS::Future: Send + 'static,
|
||||||
{
|
{
|
||||||
/// Create a new transaction verifier.
|
/// Create a new transaction verifier.
|
||||||
pub fn new(network: Network, state: ZS) -> Self {
|
pub fn new(network: &Network, state: ZS) -> Self {
|
||||||
Self {
|
Self {
|
||||||
network,
|
network: network.clone(),
|
||||||
state: Timeout::new(state, UTXO_LOOKUP_TIMEOUT),
|
state: Timeout::new(state, UTXO_LOOKUP_TIMEOUT),
|
||||||
script_verifier: script::Verifier,
|
script_verifier: script::Verifier,
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ impl Request {
|
||||||
/// The network upgrade to consider for the verification.
|
/// The network upgrade to consider for the verification.
|
||||||
///
|
///
|
||||||
/// This is based on the block height from the request, and the supplied `network`.
|
/// This is based on the block height from the request, and the supplied `network`.
|
||||||
pub fn upgrade(&self, network: Network) -> NetworkUpgrade {
|
pub fn upgrade(&self, network: &Network) -> NetworkUpgrade {
|
||||||
NetworkUpgrade::current(network, self.height())
|
NetworkUpgrade::current(network, self.height())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ where
|
||||||
// TODO: break up each chunk into its own method
|
// TODO: break up each chunk into its own method
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
let script_verifier = self.script_verifier;
|
let script_verifier = self.script_verifier;
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
let state = self.state.clone();
|
let state = self.state.clone();
|
||||||
|
|
||||||
let tx = req.transaction();
|
let tx = req.transaction();
|
||||||
|
@ -321,7 +321,7 @@ where
|
||||||
|
|
||||||
// Validate `nExpiryHeight` consensus rules
|
// Validate `nExpiryHeight` consensus rules
|
||||||
if tx.is_coinbase() {
|
if tx.is_coinbase() {
|
||||||
check::coinbase_expiry_height(&req.height(), &tx, network)?;
|
check::coinbase_expiry_height(&req.height(), &tx, &network)?;
|
||||||
} else {
|
} else {
|
||||||
check::non_coinbase_expiry_height(&req.height(), &tx)?;
|
check::non_coinbase_expiry_height(&req.height(), &tx)?;
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ where
|
||||||
|
|
||||||
// [Canopy onward]: `vpub_old` MUST be zero.
|
// [Canopy onward]: `vpub_old` MUST be zero.
|
||||||
// https://zips.z.cash/protocol/protocol.pdf#joinsplitdesc
|
// https://zips.z.cash/protocol/protocol.pdf#joinsplitdesc
|
||||||
check::disabled_add_to_sprout_pool(&tx, req.height(), network)?;
|
check::disabled_add_to_sprout_pool(&tx, req.height(), &network)?;
|
||||||
|
|
||||||
check::spend_conflicts(&tx)?;
|
check::spend_conflicts(&tx)?;
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ where
|
||||||
..
|
..
|
||||||
} => Self::verify_v4_transaction(
|
} => Self::verify_v4_transaction(
|
||||||
&req,
|
&req,
|
||||||
network,
|
&network,
|
||||||
script_verifier,
|
script_verifier,
|
||||||
cached_ffi_transaction.clone(),
|
cached_ffi_transaction.clone(),
|
||||||
joinsplit_data,
|
joinsplit_data,
|
||||||
|
@ -408,7 +408,7 @@ where
|
||||||
..
|
..
|
||||||
} => Self::verify_v5_transaction(
|
} => Self::verify_v5_transaction(
|
||||||
&req,
|
&req,
|
||||||
network,
|
&network,
|
||||||
script_verifier,
|
script_verifier,
|
||||||
cached_ffi_transaction.clone(),
|
cached_ffi_transaction.clone(),
|
||||||
sapling_shielded_data,
|
sapling_shielded_data,
|
||||||
|
@ -616,7 +616,7 @@ where
|
||||||
/// - the `sapling_shielded_data` in the transaction
|
/// - the `sapling_shielded_data` in the transaction
|
||||||
fn verify_v4_transaction(
|
fn verify_v4_transaction(
|
||||||
request: &Request,
|
request: &Request,
|
||||||
network: Network,
|
network: &Network,
|
||||||
script_verifier: script::Verifier,
|
script_verifier: script::Verifier,
|
||||||
cached_ffi_transaction: Arc<CachedFfiTransaction>,
|
cached_ffi_transaction: Arc<CachedFfiTransaction>,
|
||||||
joinsplit_data: &Option<transaction::JoinSplitData<Groth16Proof>>,
|
joinsplit_data: &Option<transaction::JoinSplitData<Groth16Proof>>,
|
||||||
|
@ -708,7 +708,7 @@ where
|
||||||
/// - the orchard shielded data of the transaction, if any
|
/// - the orchard shielded data of the transaction, if any
|
||||||
fn verify_v5_transaction(
|
fn verify_v5_transaction(
|
||||||
request: &Request,
|
request: &Request,
|
||||||
network: Network,
|
network: &Network,
|
||||||
script_verifier: script::Verifier,
|
script_verifier: script::Verifier,
|
||||||
cached_ffi_transaction: Arc<CachedFfiTransaction>,
|
cached_ffi_transaction: Arc<CachedFfiTransaction>,
|
||||||
sapling_shielded_data: &Option<sapling::ShieldedData<sapling::SharedAnchor>>,
|
sapling_shielded_data: &Option<sapling::ShieldedData<sapling::SharedAnchor>>,
|
||||||
|
@ -782,7 +782,7 @@ where
|
||||||
/// Returns script verification responses via the `utxo_sender`.
|
/// Returns script verification responses via the `utxo_sender`.
|
||||||
fn verify_transparent_inputs_and_outputs(
|
fn verify_transparent_inputs_and_outputs(
|
||||||
request: &Request,
|
request: &Request,
|
||||||
network: Network,
|
network: &Network,
|
||||||
script_verifier: script::Verifier,
|
script_verifier: script::Verifier,
|
||||||
cached_ffi_transaction: Arc<CachedFfiTransaction>,
|
cached_ffi_transaction: Arc<CachedFfiTransaction>,
|
||||||
) -> Result<AsyncChecks, TransactionError> {
|
) -> Result<AsyncChecks, TransactionError> {
|
||||||
|
|
|
@ -212,7 +212,7 @@ pub fn joinsplit_has_vpub_zero(tx: &Transaction) -> Result<(), TransactionError>
|
||||||
pub fn disabled_add_to_sprout_pool(
|
pub fn disabled_add_to_sprout_pool(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
height: Height,
|
height: Height,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Result<(), TransactionError> {
|
) -> Result<(), TransactionError> {
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(network)
|
||||||
|
@ -325,7 +325,7 @@ where
|
||||||
/// <https://github.com/ZcashFoundation/zebra/issues/3027>
|
/// <https://github.com/ZcashFoundation/zebra/issues/3027>
|
||||||
pub fn coinbase_outputs_are_decryptable(
|
pub fn coinbase_outputs_are_decryptable(
|
||||||
transaction: &Transaction,
|
transaction: &Transaction,
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
) -> Result<(), TransactionError> {
|
) -> Result<(), TransactionError> {
|
||||||
// The consensus rule only applies to Heartwood onward.
|
// The consensus rule only applies to Heartwood onward.
|
||||||
|
@ -352,7 +352,7 @@ pub fn coinbase_outputs_are_decryptable(
|
||||||
pub fn coinbase_expiry_height(
|
pub fn coinbase_expiry_height(
|
||||||
block_height: &Height,
|
block_height: &Height,
|
||||||
coinbase: &Transaction,
|
coinbase: &Transaction,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Result<(), TransactionError> {
|
) -> Result<(), TransactionError> {
|
||||||
let expiry_height = coinbase.expiry_height();
|
let expiry_height = coinbase.expiry_height();
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ fn v5_fake_transactions() -> Result<(), Report> {
|
||||||
];
|
];
|
||||||
|
|
||||||
for (network, blocks) in networks {
|
for (network, blocks) in networks {
|
||||||
for transaction in fake_v5_transactions_for_network(network, blocks) {
|
for transaction in fake_v5_transactions_for_network(&network, blocks) {
|
||||||
match check::has_inputs_and_outputs(&transaction) {
|
match check::has_inputs_and_outputs(&transaction) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(TransactionError::NoInputs) | Err(TransactionError::NoOutputs) => (),
|
Err(TransactionError::NoInputs) | Err(TransactionError::NoOutputs) => (),
|
||||||
|
@ -67,7 +67,7 @@ fn v5_fake_transactions() -> Result<(), Report> {
|
||||||
fn fake_v5_transaction_with_orchard_actions_has_inputs_and_outputs() {
|
fn fake_v5_transaction_with_orchard_actions_has_inputs_and_outputs() {
|
||||||
// Find a transaction with no inputs or outputs to use as base
|
// Find a transaction with no inputs or outputs to use as base
|
||||||
let mut transaction = fake_v5_transactions_for_network(
|
let mut transaction = fake_v5_transactions_for_network(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
)
|
)
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -121,7 +121,7 @@ fn fake_v5_transaction_with_orchard_actions_has_inputs_and_outputs() {
|
||||||
fn fake_v5_transaction_with_orchard_actions_has_flags() {
|
fn fake_v5_transaction_with_orchard_actions_has_flags() {
|
||||||
// Find a transaction with no inputs or outputs to use as base
|
// Find a transaction with no inputs or outputs to use as base
|
||||||
let mut transaction = fake_v5_transactions_for_network(
|
let mut transaction = fake_v5_transactions_for_network(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
)
|
)
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -164,7 +164,7 @@ fn fake_v5_transaction_with_orchard_actions_has_flags() {
|
||||||
#[test]
|
#[test]
|
||||||
fn v5_transaction_with_no_inputs_fails_validation() {
|
fn v5_transaction_with_no_inputs_fails_validation() {
|
||||||
let transaction = fake_v5_transactions_for_network(
|
let transaction = fake_v5_transactions_for_network(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
)
|
)
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -186,7 +186,7 @@ fn v5_transaction_with_no_inputs_fails_validation() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_request_with_missing_input_is_rejected() {
|
async fn mempool_request_with_missing_input_is_rejected() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let (height, tx) = transactions_from_blocks(zebra_test::vectors::MAINNET_BLOCKS.iter())
|
let (height, tx) = transactions_from_blocks(zebra_test::vectors::MAINNET_BLOCKS.iter())
|
||||||
.find(|(_, tx)| !(tx.is_coinbase() || tx.inputs().is_empty()))
|
.find(|(_, tx)| !(tx.is_coinbase() || tx.inputs().is_empty()))
|
||||||
|
@ -235,10 +235,10 @@ async fn mempool_request_with_missing_input_is_rejected() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_request_with_present_input_is_accepted() {
|
async fn mempool_request_with_present_input_is_accepted() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -302,10 +302,10 @@ async fn mempool_request_with_present_input_is_accepted() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_request_with_invalid_lock_time_is_rejected() {
|
async fn mempool_request_with_invalid_lock_time_is_rejected() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -381,10 +381,10 @@ async fn mempool_request_with_invalid_lock_time_is_rejected() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_request_with_unlocked_lock_time_is_accepted() {
|
async fn mempool_request_with_unlocked_lock_time_is_accepted() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -448,10 +448,10 @@ async fn mempool_request_with_unlocked_lock_time_is_accepted() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_request_with_lock_time_max_sequence_number_is_accepted() {
|
async fn mempool_request_with_lock_time_max_sequence_number_is_accepted() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (mut input, output, known_utxos) = mock_transparent_transfer(
|
let (mut input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -518,10 +518,10 @@ async fn mempool_request_with_lock_time_max_sequence_number_is_accepted() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_request_with_past_lock_time_is_accepted() {
|
async fn mempool_request_with_past_lock_time_is_accepted() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -597,10 +597,10 @@ async fn mempool_request_with_immature_spend_is_rejected() {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -700,10 +700,10 @@ async fn state_error_converted_correctly() {
|
||||||
use zebra_state::DuplicateNullifierError;
|
use zebra_state::DuplicateNullifierError;
|
||||||
|
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Canopy
|
let height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -798,7 +798,7 @@ async fn state_error_converted_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn v5_transaction_with_no_outputs_fails_validation() {
|
fn v5_transaction_with_no_outputs_fails_validation() {
|
||||||
let transaction = fake_v5_transactions_for_network(
|
let transaction = fake_v5_transactions_for_network(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
)
|
)
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -821,7 +821,7 @@ fn v5_transaction_with_no_outputs_fails_validation() {
|
||||||
#[test]
|
#[test]
|
||||||
fn v5_coinbase_transaction_without_enable_spends_flag_passes_validation() {
|
fn v5_coinbase_transaction_without_enable_spends_flag_passes_validation() {
|
||||||
let mut transaction = fake_v5_transactions_for_network(
|
let mut transaction = fake_v5_transactions_for_network(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
)
|
)
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -836,7 +836,7 @@ fn v5_coinbase_transaction_without_enable_spends_flag_passes_validation() {
|
||||||
#[test]
|
#[test]
|
||||||
fn v5_coinbase_transaction_with_enable_spends_flag_fails_validation() {
|
fn v5_coinbase_transaction_with_enable_spends_flag_fails_validation() {
|
||||||
let mut transaction = fake_v5_transactions_for_network(
|
let mut transaction = fake_v5_transactions_for_network(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
zebra_test::vectors::MAINNET_BLOCKS.iter(),
|
||||||
)
|
)
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -865,9 +865,9 @@ async fn v5_transaction_is_rejected_before_nu5_activation() {
|
||||||
|
|
||||||
for (network, blocks) in networks {
|
for (network, blocks) in networks {
|
||||||
let state_service = service_fn(|_| async { unreachable!("Service should not be called") });
|
let state_service = service_fn(|_| async { unreachable!("Service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let transaction = fake_v5_transactions_for_network(network, blocks)
|
let transaction = fake_v5_transactions_for_network(&network, blocks)
|
||||||
.next_back()
|
.next_back()
|
||||||
.expect("At least one fake V5 transaction in the test vectors");
|
.expect("At least one fake V5 transaction in the test vectors");
|
||||||
|
|
||||||
|
@ -876,7 +876,7 @@ async fn v5_transaction_is_rejected_before_nu5_activation() {
|
||||||
transaction: Arc::new(transaction),
|
transaction: Arc::new(transaction),
|
||||||
known_utxos: Arc::new(HashMap::new()),
|
known_utxos: Arc::new(HashMap::new()),
|
||||||
height: canopy
|
height: canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified"),
|
.expect("Canopy activation height is specified"),
|
||||||
time: DateTime::<Utc>::MAX_UTC,
|
time: DateTime::<Utc>::MAX_UTC,
|
||||||
})
|
})
|
||||||
|
@ -907,14 +907,14 @@ fn v5_transaction_is_accepted_after_nu5_activation_for_network(network: Network)
|
||||||
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
||||||
let nu5 = NetworkUpgrade::Nu5;
|
let nu5 = NetworkUpgrade::Nu5;
|
||||||
let nu5_activation_height = nu5
|
let nu5_activation_height = nu5
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("NU5 activation height is specified");
|
.expect("NU5 activation height is specified");
|
||||||
let blocks = network.block_iter();
|
let blocks = network.block_iter();
|
||||||
|
|
||||||
let state_service = service_fn(|_| async { unreachable!("Service should not be called") });
|
let state_service = service_fn(|_| async { unreachable!("Service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let mut transaction = fake_v5_transactions_for_network(network, blocks)
|
let mut transaction = fake_v5_transactions_for_network(&network, blocks)
|
||||||
.next_back()
|
.next_back()
|
||||||
.expect("At least one fake V5 transaction in the test vectors");
|
.expect("At least one fake V5 transaction in the test vectors");
|
||||||
if transaction
|
if transaction
|
||||||
|
@ -953,7 +953,7 @@ async fn v4_transaction_with_transparent_transfer_is_accepted() {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -984,7 +984,7 @@ async fn v4_transaction_with_transparent_transfer_is_accepted() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1007,10 +1007,10 @@ async fn v4_transaction_with_transparent_transfer_is_accepted() {
|
||||||
async fn v4_transaction_with_last_valid_expiry_height() {
|
async fn v4_transaction_with_last_valid_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Mainnet, state_service);
|
let verifier = Verifier::new(&Network::Mainnet, state_service);
|
||||||
|
|
||||||
let block_height = NetworkUpgrade::Canopy
|
let block_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -1054,10 +1054,10 @@ async fn v4_transaction_with_last_valid_expiry_height() {
|
||||||
async fn v4_coinbase_transaction_with_low_expiry_height() {
|
async fn v4_coinbase_transaction_with_low_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Mainnet, state_service);
|
let verifier = Verifier::new(&Network::Mainnet, state_service);
|
||||||
|
|
||||||
let block_height = NetworkUpgrade::Canopy
|
let block_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let (input, output) = mock_coinbase_transparent_output(block_height);
|
let (input, output) = mock_coinbase_transparent_output(block_height);
|
||||||
|
@ -1095,10 +1095,10 @@ async fn v4_coinbase_transaction_with_low_expiry_height() {
|
||||||
async fn v4_transaction_with_too_low_expiry_height() {
|
async fn v4_transaction_with_too_low_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Mainnet, state_service);
|
let verifier = Verifier::new(&Network::Mainnet, state_service);
|
||||||
|
|
||||||
let block_height = NetworkUpgrade::Canopy
|
let block_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
||||||
|
@ -1147,7 +1147,7 @@ async fn v4_transaction_with_too_low_expiry_height() {
|
||||||
async fn v4_transaction_with_exceeding_expiry_height() {
|
async fn v4_transaction_with_exceeding_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Mainnet, state_service);
|
let verifier = Verifier::new(&Network::Mainnet, state_service);
|
||||||
|
|
||||||
let block_height = block::Height::MAX;
|
let block_height = block::Height::MAX;
|
||||||
|
|
||||||
|
@ -1198,14 +1198,14 @@ async fn v4_transaction_with_exceeding_expiry_height() {
|
||||||
async fn v4_coinbase_transaction_with_exceeding_expiry_height() {
|
async fn v4_coinbase_transaction_with_exceeding_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Mainnet, state_service);
|
let verifier = Verifier::new(&Network::Mainnet, state_service);
|
||||||
|
|
||||||
// Use an arbitrary pre-NU5 block height.
|
// Use an arbitrary pre-NU5 block height.
|
||||||
// It can't be NU5-onward because the expiry height limit is not enforced
|
// It can't be NU5-onward because the expiry height limit is not enforced
|
||||||
// for coinbase transactions (it needs to match the block height instead),
|
// for coinbase transactions (it needs to match the block height instead),
|
||||||
// which is what is used in this test.
|
// which is what is used in this test.
|
||||||
let block_height = (NetworkUpgrade::Nu5
|
let block_height = (NetworkUpgrade::Nu5
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("NU5 height must be set")
|
.expect("NU5 height must be set")
|
||||||
- 1)
|
- 1)
|
||||||
.expect("will not underflow");
|
.expect("will not underflow");
|
||||||
|
@ -1251,7 +1251,7 @@ async fn v4_coinbase_transaction_is_accepted() {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1274,7 +1274,7 @@ async fn v4_coinbase_transaction_is_accepted() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1300,7 +1300,7 @@ async fn v4_transaction_with_transparent_transfer_is_rejected_by_the_script() {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1329,7 +1329,7 @@ async fn v4_transaction_with_transparent_transfer_is_rejected_by_the_script() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1355,7 +1355,7 @@ async fn v4_transaction_with_conflicting_transparent_spend_is_rejected() {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1384,7 +1384,7 @@ async fn v4_transaction_with_conflicting_transparent_spend_is_rejected() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1414,7 +1414,7 @@ fn v4_transaction_with_conflicting_sprout_nullifier_inside_joinsplit_is_rejected
|
||||||
let network_upgrade = NetworkUpgrade::Canopy;
|
let network_upgrade = NetworkUpgrade::Canopy;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1450,7 +1450,7 @@ fn v4_transaction_with_conflicting_sprout_nullifier_inside_joinsplit_is_rejected
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1479,7 +1479,7 @@ fn v4_transaction_with_conflicting_sprout_nullifier_across_joinsplits_is_rejecte
|
||||||
let network_upgrade = NetworkUpgrade::Canopy;
|
let network_upgrade = NetworkUpgrade::Canopy;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1521,7 +1521,7 @@ fn v4_transaction_with_conflicting_sprout_nullifier_across_joinsplits_is_rejecte
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1548,7 +1548,7 @@ async fn v5_transaction_with_transparent_transfer_is_accepted() {
|
||||||
let network_upgrade = NetworkUpgrade::Nu5;
|
let network_upgrade = NetworkUpgrade::Nu5;
|
||||||
|
|
||||||
let nu5_activation_height = network_upgrade
|
let nu5_activation_height = network_upgrade
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("NU5 activation height is specified");
|
.expect("NU5 activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1580,7 +1580,7 @@ async fn v5_transaction_with_transparent_transfer_is_accepted() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1603,10 +1603,10 @@ async fn v5_transaction_with_transparent_transfer_is_accepted() {
|
||||||
async fn v5_transaction_with_last_valid_expiry_height() {
|
async fn v5_transaction_with_last_valid_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Testnet, state_service);
|
let verifier = Verifier::new(&Network::Testnet, state_service);
|
||||||
|
|
||||||
let block_height = NetworkUpgrade::Nu5
|
let block_height = NetworkUpgrade::Nu5
|
||||||
.activation_height(Network::Testnet)
|
.activation_height(&Network::Testnet)
|
||||||
.expect("Nu5 activation height for testnet is specified");
|
.expect("Nu5 activation height for testnet is specified");
|
||||||
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -1648,10 +1648,10 @@ async fn v5_transaction_with_last_valid_expiry_height() {
|
||||||
async fn v5_coinbase_transaction_expiry_height() {
|
async fn v5_coinbase_transaction_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Testnet, state_service);
|
let verifier = Verifier::new(&Network::Testnet, state_service);
|
||||||
|
|
||||||
let block_height = NetworkUpgrade::Nu5
|
let block_height = NetworkUpgrade::Nu5
|
||||||
.activation_height(Network::Testnet)
|
.activation_height(&Network::Testnet)
|
||||||
.expect("Nu5 activation height for testnet is specified");
|
.expect("Nu5 activation height for testnet is specified");
|
||||||
|
|
||||||
let (input, output) = mock_coinbase_transparent_output(block_height);
|
let (input, output) = mock_coinbase_transparent_output(block_height);
|
||||||
|
@ -1763,10 +1763,10 @@ async fn v5_coinbase_transaction_expiry_height() {
|
||||||
async fn v5_transaction_with_too_low_expiry_height() {
|
async fn v5_transaction_with_too_low_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Testnet, state_service);
|
let verifier = Verifier::new(&Network::Testnet, state_service);
|
||||||
|
|
||||||
let block_height = NetworkUpgrade::Nu5
|
let block_height = NetworkUpgrade::Nu5
|
||||||
.activation_height(Network::Testnet)
|
.activation_height(&Network::Testnet)
|
||||||
.expect("Nu5 activation height for testnet is specified");
|
.expect("Nu5 activation height for testnet is specified");
|
||||||
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
let fund_height = (block_height - 1).expect("fake source fund block height is too small");
|
||||||
let (input, output, known_utxos) = mock_transparent_transfer(
|
let (input, output, known_utxos) = mock_transparent_transfer(
|
||||||
|
@ -1815,7 +1815,7 @@ async fn v5_transaction_with_too_low_expiry_height() {
|
||||||
async fn v5_transaction_with_exceeding_expiry_height() {
|
async fn v5_transaction_with_exceeding_expiry_height() {
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(Network::Mainnet, state_service);
|
let verifier = Verifier::new(&Network::Mainnet, state_service);
|
||||||
|
|
||||||
let block_height = block::Height::MAX;
|
let block_height = block::Height::MAX;
|
||||||
|
|
||||||
|
@ -1868,7 +1868,7 @@ async fn v5_coinbase_transaction_is_accepted() {
|
||||||
let network_upgrade = NetworkUpgrade::Nu5;
|
let network_upgrade = NetworkUpgrade::Nu5;
|
||||||
|
|
||||||
let nu5_activation_height = network_upgrade
|
let nu5_activation_height = network_upgrade
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("NU5 activation height is specified");
|
.expect("NU5 activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1893,7 +1893,7 @@ async fn v5_coinbase_transaction_is_accepted() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1920,7 +1920,7 @@ async fn v5_transaction_with_transparent_transfer_is_rejected_by_the_script() {
|
||||||
let network_upgrade = NetworkUpgrade::Nu5;
|
let network_upgrade = NetworkUpgrade::Nu5;
|
||||||
|
|
||||||
let nu5_activation_height = network_upgrade
|
let nu5_activation_height = network_upgrade
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("NU5 activation height is specified");
|
.expect("NU5 activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -1950,7 +1950,7 @@ async fn v5_transaction_with_transparent_transfer_is_rejected_by_the_script() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -1977,7 +1977,7 @@ async fn v5_transaction_with_conflicting_transparent_spend_is_rejected() {
|
||||||
let network_upgrade = NetworkUpgrade::Nu5;
|
let network_upgrade = NetworkUpgrade::Nu5;
|
||||||
|
|
||||||
let canopy_activation_height = NetworkUpgrade::Canopy
|
let canopy_activation_height = NetworkUpgrade::Canopy
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Canopy activation height is specified");
|
.expect("Canopy activation height is specified");
|
||||||
|
|
||||||
let transaction_block_height =
|
let transaction_block_height =
|
||||||
|
@ -2007,7 +2007,7 @@ async fn v5_transaction_with_conflicting_transparent_spend_is_rejected() {
|
||||||
|
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
let result = verifier
|
let result = verifier
|
||||||
.oneshot(Request::Block {
|
.oneshot(Request::Block {
|
||||||
|
@ -2037,7 +2037,7 @@ fn v4_with_signed_sprout_transfer_is_accepted() {
|
||||||
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let (height, transaction) = test_transactions(network)
|
let (height, transaction) = test_transactions(&network)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|(_, transaction)| {
|
.filter(|(_, transaction)| {
|
||||||
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
||||||
|
@ -2050,7 +2050,7 @@ fn v4_with_signed_sprout_transfer_is_accepted() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2109,7 +2109,7 @@ async fn v4_with_joinsplit_is_rejected_for_modification(
|
||||||
) {
|
) {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let (height, mut transaction) = test_transactions(network)
|
let (height, mut transaction) = test_transactions(&network)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|(_, transaction)| !transaction.is_coinbase() && transaction.inputs().is_empty())
|
.filter(|(_, transaction)| !transaction.is_coinbase() && transaction.inputs().is_empty())
|
||||||
.find(|(_, transaction)| transaction.sprout_groth16_joinsplits().next().is_some())
|
.find(|(_, transaction)| transaction.sprout_groth16_joinsplits().next().is_some())
|
||||||
|
@ -2130,7 +2130,7 @@ async fn v4_with_joinsplit_is_rejected_for_modification(
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called.") });
|
service_fn(|_| async { unreachable!("State service should not be called.") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier.
|
// Test the transaction verifier.
|
||||||
//
|
//
|
||||||
|
@ -2168,7 +2168,7 @@ fn v4_with_sapling_spends() {
|
||||||
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let (height, transaction) = test_transactions(network)
|
let (height, transaction) = test_transactions(&network)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|(_, transaction)| {
|
.filter(|(_, transaction)| {
|
||||||
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
||||||
|
@ -2181,7 +2181,7 @@ fn v4_with_sapling_spends() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2208,7 +2208,7 @@ fn v4_with_duplicate_sapling_spends() {
|
||||||
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let (height, mut transaction) = test_transactions(network)
|
let (height, mut transaction) = test_transactions(&network)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|(_, transaction)| {
|
.filter(|(_, transaction)| {
|
||||||
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
||||||
|
@ -2224,7 +2224,7 @@ fn v4_with_duplicate_sapling_spends() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2253,7 +2253,7 @@ fn v4_with_sapling_outputs_and_no_spends() {
|
||||||
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let (height, transaction) = test_transactions(network)
|
let (height, transaction) = test_transactions(&network)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|(_, transaction)| {
|
.filter(|(_, transaction)| {
|
||||||
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
!transaction.is_coinbase() && transaction.inputs().is_empty()
|
||||||
|
@ -2269,7 +2269,7 @@ fn v4_with_sapling_outputs_and_no_spends() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2297,10 +2297,10 @@ fn v5_with_sapling_spends() {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
zebra_test::MULTI_THREADED_RUNTIME.block_on(async {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
let nu5_activation = NetworkUpgrade::Nu5.activation_height(network);
|
let nu5_activation = NetworkUpgrade::Nu5.activation_height(&network);
|
||||||
|
|
||||||
let transaction =
|
let transaction =
|
||||||
fake_v5_transactions_for_network(network, zebra_test::vectors::MAINNET_BLOCKS.iter())
|
fake_v5_transactions_for_network(&network, zebra_test::vectors::MAINNET_BLOCKS.iter())
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|transaction| {
|
.filter(|transaction| {
|
||||||
!transaction.is_coinbase()
|
!transaction.is_coinbase()
|
||||||
|
@ -2318,7 +2318,7 @@ fn v5_with_sapling_spends() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2346,7 +2346,7 @@ fn v5_with_duplicate_sapling_spends() {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
|
|
||||||
let mut transaction =
|
let mut transaction =
|
||||||
fake_v5_transactions_for_network(network, zebra_test::vectors::MAINNET_BLOCKS.iter())
|
fake_v5_transactions_for_network(&network, zebra_test::vectors::MAINNET_BLOCKS.iter())
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|transaction| !transaction.is_coinbase() && transaction.inputs().is_empty())
|
.filter(|transaction| !transaction.is_coinbase() && transaction.inputs().is_empty())
|
||||||
.find(|transaction| transaction.sapling_spends_per_anchor().next().is_some())
|
.find(|transaction| transaction.sapling_spends_per_anchor().next().is_some())
|
||||||
|
@ -2362,7 +2362,7 @@ fn v5_with_duplicate_sapling_spends() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2393,7 +2393,7 @@ fn v5_with_duplicate_orchard_action() {
|
||||||
|
|
||||||
// Find a transaction with no inputs or outputs to use as base
|
// Find a transaction with no inputs or outputs to use as base
|
||||||
let mut transaction =
|
let mut transaction =
|
||||||
fake_v5_transactions_for_network(network, zebra_test::vectors::MAINNET_BLOCKS.iter())
|
fake_v5_transactions_for_network(&network, zebra_test::vectors::MAINNET_BLOCKS.iter())
|
||||||
.rev()
|
.rev()
|
||||||
.find(|transaction| {
|
.find(|transaction| {
|
||||||
transaction.inputs().is_empty()
|
transaction.inputs().is_empty()
|
||||||
|
@ -2425,7 +2425,7 @@ fn v5_with_duplicate_orchard_action() {
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
service_fn(|_| async { unreachable!("State service should not be called") });
|
service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = Verifier::new(network, state_service);
|
let verifier = Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
let result = verifier
|
let result = verifier
|
||||||
|
@ -2710,21 +2710,21 @@ fn add_to_sprout_pool_after_nu() {
|
||||||
|
|
||||||
// create a block height at canopy activation.
|
// create a block height at canopy activation.
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
let block_height = NetworkUpgrade::Canopy.activation_height(network).unwrap();
|
let block_height = NetworkUpgrade::Canopy.activation_height(&network).unwrap();
|
||||||
|
|
||||||
// create a zero amount.
|
// create a zero amount.
|
||||||
let zero = Amount::<NonNegative>::try_from(0).expect("an amount of 0 is always valid");
|
let zero = Amount::<NonNegative>::try_from(0).expect("an amount of 0 is always valid");
|
||||||
|
|
||||||
// the coinbase transaction should pass the check.
|
// the coinbase transaction should pass the check.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check::disabled_add_to_sprout_pool(&block.transactions[0], block_height, network),
|
check::disabled_add_to_sprout_pool(&block.transactions[0], block_height, &network),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
// the 2nd transaction has no joinsplits, should pass the check.
|
// the 2nd transaction has no joinsplits, should pass the check.
|
||||||
assert_eq!(block.transactions[1].joinsplit_count(), 0);
|
assert_eq!(block.transactions[1].joinsplit_count(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check::disabled_add_to_sprout_pool(&block.transactions[1], block_height, network),
|
check::disabled_add_to_sprout_pool(&block.transactions[1], block_height, &network),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2737,7 +2737,7 @@ fn add_to_sprout_pool_after_nu() {
|
||||||
assert!(vpub_old > zero);
|
assert!(vpub_old > zero);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check::disabled_add_to_sprout_pool(&block.transactions[3], block_height, network),
|
check::disabled_add_to_sprout_pool(&block.transactions[3], block_height, &network),
|
||||||
Err(TransactionError::DisabledAddToSproutPool)
|
Err(TransactionError::DisabledAddToSproutPool)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2750,7 +2750,7 @@ fn add_to_sprout_pool_after_nu() {
|
||||||
assert_eq!(vpub_old, zero);
|
assert_eq!(vpub_old, zero);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check::disabled_add_to_sprout_pool(&block.transactions[7], block_height, network),
|
check::disabled_add_to_sprout_pool(&block.transactions[7], block_height, &network),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2780,7 +2780,7 @@ fn coinbase_outputs_are_decryptable_for_historical_blocks_for_network(
|
||||||
let height = Height(*height);
|
let height = Height(*height);
|
||||||
let heartwood_onward = height
|
let heartwood_onward = height
|
||||||
>= NetworkUpgrade::Heartwood
|
>= NetworkUpgrade::Heartwood
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let coinbase_tx = block
|
let coinbase_tx = block
|
||||||
.transactions
|
.transactions
|
||||||
|
@ -2796,7 +2796,7 @@ fn coinbase_outputs_are_decryptable_for_historical_blocks_for_network(
|
||||||
// and there are relevant outputs.
|
// and there are relevant outputs.
|
||||||
tested_coinbase_txs += 1;
|
tested_coinbase_txs += 1;
|
||||||
}
|
}
|
||||||
check::coinbase_outputs_are_decryptable(coinbase_tx, network, height)
|
check::coinbase_outputs_are_decryptable(coinbase_tx, &network, height)
|
||||||
.expect("coinbase outputs must be decryptable with an all-zero key");
|
.expect("coinbase outputs must be decryptable with an all-zero key");
|
||||||
|
|
||||||
// For remaining transactions, check if existing outputs are NOT decryptable
|
// For remaining transactions, check if existing outputs are NOT decryptable
|
||||||
|
@ -2805,11 +2805,11 @@ fn coinbase_outputs_are_decryptable_for_historical_blocks_for_network(
|
||||||
let has_outputs = tx.sapling_outputs().count() > 0 || tx.orchard_actions().count() > 0;
|
let has_outputs = tx.sapling_outputs().count() > 0 || tx.orchard_actions().count() > 0;
|
||||||
if has_outputs && heartwood_onward {
|
if has_outputs && heartwood_onward {
|
||||||
tested_non_coinbase_txs += 1;
|
tested_non_coinbase_txs += 1;
|
||||||
check::coinbase_outputs_are_decryptable(tx, network, height).expect_err(
|
check::coinbase_outputs_are_decryptable(tx, &network, height).expect_err(
|
||||||
"decrypting a non-coinbase output with an all-zero key should fail",
|
"decrypting a non-coinbase output with an all-zero key should fail",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
check::coinbase_outputs_are_decryptable(tx, network, height)
|
check::coinbase_outputs_are_decryptable(tx, &network, height)
|
||||||
.expect("a transaction without outputs, or pre-Heartwood, must be considered 'decryptable'");
|
.expect("a transaction without outputs, or pre-Heartwood, must be considered 'decryptable'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2849,7 +2849,7 @@ fn coinbase_outputs_are_decryptable_for_fake_v5_blocks() {
|
||||||
for v in zebra_test::vectors::ORCHARD_NOTE_ENCRYPTION_ZERO_VECTOR.iter() {
|
for v in zebra_test::vectors::ORCHARD_NOTE_ENCRYPTION_ZERO_VECTOR.iter() {
|
||||||
// Find a transaction with no inputs or outputs to use as base
|
// Find a transaction with no inputs or outputs to use as base
|
||||||
let mut transaction =
|
let mut transaction =
|
||||||
fake_v5_transactions_for_network(network, zebra_test::vectors::TESTNET_BLOCKS.iter())
|
fake_v5_transactions_for_network(&network, zebra_test::vectors::TESTNET_BLOCKS.iter())
|
||||||
.rev()
|
.rev()
|
||||||
.find(|transaction| {
|
.find(|transaction| {
|
||||||
transaction.inputs().is_empty()
|
transaction.inputs().is_empty()
|
||||||
|
@ -2874,8 +2874,8 @@ fn coinbase_outputs_are_decryptable_for_fake_v5_blocks() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check::coinbase_outputs_are_decryptable(
|
check::coinbase_outputs_are_decryptable(
|
||||||
&transaction,
|
&transaction,
|
||||||
network,
|
&network,
|
||||||
NetworkUpgrade::Nu5.activation_height(network).unwrap(),
|
NetworkUpgrade::Nu5.activation_height(&network).unwrap(),
|
||||||
),
|
),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
@ -2891,7 +2891,7 @@ fn shielded_outputs_are_not_decryptable_for_fake_v5_blocks() {
|
||||||
for v in zebra_test::vectors::ORCHARD_NOTE_ENCRYPTION_VECTOR.iter() {
|
for v in zebra_test::vectors::ORCHARD_NOTE_ENCRYPTION_VECTOR.iter() {
|
||||||
// Find a transaction with no inputs or outputs to use as base
|
// Find a transaction with no inputs or outputs to use as base
|
||||||
let mut transaction =
|
let mut transaction =
|
||||||
fake_v5_transactions_for_network(network, zebra_test::vectors::TESTNET_BLOCKS.iter())
|
fake_v5_transactions_for_network(&network, zebra_test::vectors::TESTNET_BLOCKS.iter())
|
||||||
.rev()
|
.rev()
|
||||||
.find(|transaction| {
|
.find(|transaction| {
|
||||||
transaction.inputs().is_empty()
|
transaction.inputs().is_empty()
|
||||||
|
@ -2916,8 +2916,8 @@ fn shielded_outputs_are_not_decryptable_for_fake_v5_blocks() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check::coinbase_outputs_are_decryptable(
|
check::coinbase_outputs_are_decryptable(
|
||||||
&transaction,
|
&transaction,
|
||||||
network,
|
&network,
|
||||||
NetworkUpgrade::Nu5.activation_height(network).unwrap(),
|
NetworkUpgrade::Nu5.activation_height(&network).unwrap(),
|
||||||
),
|
),
|
||||||
Err(TransactionError::CoinbaseOutputsNotDecryptable)
|
Err(TransactionError::CoinbaseOutputsNotDecryptable)
|
||||||
);
|
);
|
||||||
|
@ -2927,10 +2927,10 @@ fn shielded_outputs_are_not_decryptable_for_fake_v5_blocks() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_zip317_error() {
|
async fn mempool_zip317_error() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Nu5
|
let height = NetworkUpgrade::Nu5
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Nu5 activation height is specified");
|
.expect("Nu5 activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
|
|
||||||
|
@ -2999,10 +2999,10 @@ async fn mempool_zip317_error() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_zip317_ok() {
|
async fn mempool_zip317_ok() {
|
||||||
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
let mut state: MockService<_, _, _, _> = MockService::build().for_prop_tests();
|
||||||
let verifier = Verifier::new(Network::Mainnet, state.clone());
|
let verifier = Verifier::new(&Network::Mainnet, state.clone());
|
||||||
|
|
||||||
let height = NetworkUpgrade::Nu5
|
let height = NetworkUpgrade::Nu5
|
||||||
.activation_height(Network::Mainnet)
|
.activation_height(&Network::Mainnet)
|
||||||
.expect("Nu5 activation height is specified");
|
.expect("Nu5 activation height is specified");
|
||||||
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
let fund_height = (height - 1).expect("fake source fund block height is too small");
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ proptest! {
|
||||||
let zero_lock_time = LockTime::Height(block::Height(0));
|
let zero_lock_time = LockTime::Height(block::Height(0));
|
||||||
|
|
||||||
let (transaction, known_utxos) = mock_transparent_transaction(
|
let (transaction, known_utxos) = mock_transparent_transaction(
|
||||||
network,
|
&network,
|
||||||
block_height,
|
block_height,
|
||||||
relative_source_fund_heights,
|
relative_source_fund_heights,
|
||||||
transaction_version,
|
transaction_version,
|
||||||
|
@ -67,7 +67,7 @@ proptest! {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
let (mut transaction, known_utxos) = mock_transparent_transaction(
|
let (mut transaction, known_utxos) = mock_transparent_transaction(
|
||||||
network,
|
&network,
|
||||||
block_height,
|
block_height,
|
||||||
relative_source_fund_heights,
|
relative_source_fund_heights,
|
||||||
transaction_version,
|
transaction_version,
|
||||||
|
@ -105,7 +105,7 @@ proptest! {
|
||||||
let lock_time = LockTime::Height(unlock_height);
|
let lock_time = LockTime::Height(unlock_height);
|
||||||
|
|
||||||
let (transaction, known_utxos) = mock_transparent_transaction(
|
let (transaction, known_utxos) = mock_transparent_transaction(
|
||||||
network,
|
&network,
|
||||||
block_height,
|
block_height,
|
||||||
relative_source_fund_heights,
|
relative_source_fund_heights,
|
||||||
transaction_version,
|
transaction_version,
|
||||||
|
@ -138,7 +138,7 @@ proptest! {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (transaction, known_utxos) = mock_transparent_transaction(
|
let (transaction, known_utxos) = mock_transparent_transaction(
|
||||||
network,
|
&network,
|
||||||
block_height,
|
block_height,
|
||||||
relative_source_fund_heights,
|
relative_source_fund_heights,
|
||||||
transaction_version,
|
transaction_version,
|
||||||
|
@ -172,7 +172,7 @@ proptest! {
|
||||||
let lock_time = LockTime::Height(unlock_height);
|
let lock_time = LockTime::Height(unlock_height);
|
||||||
|
|
||||||
let (transaction, known_utxos) = mock_transparent_transaction(
|
let (transaction, known_utxos) = mock_transparent_transaction(
|
||||||
network,
|
&network,
|
||||||
block_height,
|
block_height,
|
||||||
relative_source_fund_heights,
|
relative_source_fund_heights,
|
||||||
transaction_version,
|
transaction_version,
|
||||||
|
@ -213,7 +213,7 @@ proptest! {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (transaction, known_utxos) = mock_transparent_transaction(
|
let (transaction, known_utxos) = mock_transparent_transaction(
|
||||||
network,
|
&network,
|
||||||
block_height,
|
block_height,
|
||||||
relative_source_fund_heights,
|
relative_source_fund_heights,
|
||||||
transaction_version,
|
transaction_version,
|
||||||
|
@ -244,14 +244,14 @@ proptest! {
|
||||||
fn sapling_onwards_strategy() -> impl Strategy<Value = (Network, block::Height)> {
|
fn sapling_onwards_strategy() -> impl Strategy<Value = (Network, block::Height)> {
|
||||||
any::<Network>().prop_flat_map(|network| {
|
any::<Network>().prop_flat_map(|network| {
|
||||||
let start_height_value = NetworkUpgrade::Sapling
|
let start_height_value = NetworkUpgrade::Sapling
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.expect("Sapling to have an activation height")
|
.expect("Sapling to have an activation height")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
let end_height_value = block::Height::MAX_EXPIRY_HEIGHT.0;
|
let end_height_value = block::Height::MAX_EXPIRY_HEIGHT.0;
|
||||||
|
|
||||||
(start_height_value..=end_height_value)
|
(start_height_value..=end_height_value)
|
||||||
.prop_map(move |height_value| (network, block::Height(height_value)))
|
.prop_map(move |height_value| (network.clone(), block::Height(height_value)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ fn sapling_onwards_strategy() -> impl Strategy<Value = (Network, block::Height)>
|
||||||
/// - if any item of `relative_source_heights` is not in the range `0.0..1.0` (see
|
/// - if any item of `relative_source_heights` is not in the range `0.0..1.0` (see
|
||||||
/// [`scale_block_height`] for details)
|
/// [`scale_block_height`] for details)
|
||||||
fn mock_transparent_transaction(
|
fn mock_transparent_transaction(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block_height: block::Height,
|
block_height: block::Height,
|
||||||
relative_source_heights: Vec<f64>,
|
relative_source_heights: Vec<f64>,
|
||||||
transaction_version: u8,
|
transaction_version: u8,
|
||||||
|
@ -330,7 +330,7 @@ fn mock_transparent_transaction(
|
||||||
/// The `transaction_version` might be reduced if it is not supported by the network upgrade active
|
/// The `transaction_version` might be reduced if it is not supported by the network upgrade active
|
||||||
/// at the `block_height` of the specified `network`.
|
/// at the `block_height` of the specified `network`.
|
||||||
fn sanitize_transaction_version(
|
fn sanitize_transaction_version(
|
||||||
network: Network,
|
network: &Network,
|
||||||
transaction_version: u8,
|
transaction_version: u8,
|
||||||
block_height: block::Height,
|
block_height: block::Height,
|
||||||
) -> (u8, NetworkUpgrade) {
|
) -> (u8, NetworkUpgrade) {
|
||||||
|
@ -450,7 +450,7 @@ fn validate(
|
||||||
// Initialize the verifier
|
// Initialize the verifier
|
||||||
let state_service =
|
let state_service =
|
||||||
tower::service_fn(|_| async { unreachable!("State service should not be called") });
|
tower::service_fn(|_| async { unreachable!("State service should not be called") });
|
||||||
let verifier = transaction::Verifier::new(network, state_service);
|
let verifier = transaction::Verifier::new(&network, state_service);
|
||||||
|
|
||||||
// Test the transaction verifier
|
// Test the transaction verifier
|
||||||
verifier
|
verifier
|
||||||
|
|
|
@ -37,11 +37,11 @@ async fn test_grpc_methods_mocked() {
|
||||||
test_delete_keys_errors(client.clone()).await;
|
test_delete_keys_errors(client.clone()).await;
|
||||||
|
|
||||||
for network in Network::iter() {
|
for network in Network::iter() {
|
||||||
test_mocked_getinfo_for_network(&client, &mock_scan_service, network).await;
|
test_mocked_getinfo_for_network(&client, &mock_scan_service, &network).await;
|
||||||
test_mocked_getresults_for_network(&client, &mock_scan_service, network).await;
|
test_mocked_getresults_for_network(&client, &mock_scan_service, &network).await;
|
||||||
test_mocked_register_keys_for_network(&client, &mock_scan_service, network).await;
|
test_mocked_register_keys_for_network(&client, &mock_scan_service, &network).await;
|
||||||
test_mocked_clear_results_for_network(&client, &mock_scan_service, network).await;
|
test_mocked_clear_results_for_network(&client, &mock_scan_service, &network).await;
|
||||||
test_mocked_delete_keys_for_network(&client, &mock_scan_service, network).await;
|
test_mocked_delete_keys_for_network(&client, &mock_scan_service, &network).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ async fn test_grpc_methods_mocked() {
|
||||||
async fn test_mocked_getinfo_for_network(
|
async fn test_mocked_getinfo_for_network(
|
||||||
client: &ScannerClient<Channel>,
|
client: &ScannerClient<Channel>,
|
||||||
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) {
|
) {
|
||||||
// create request, fake results and get response
|
// create request, fake results and get response
|
||||||
let get_info_response = call_get_info(client.clone(), mock_scan_service.clone(), network).await;
|
let get_info_response = call_get_info(client.clone(), mock_scan_service.clone(), network).await;
|
||||||
|
@ -66,7 +66,7 @@ async fn test_mocked_getinfo_for_network(
|
||||||
async fn test_mocked_getresults_for_network(
|
async fn test_mocked_getresults_for_network(
|
||||||
client: &ScannerClient<Channel>,
|
client: &ScannerClient<Channel>,
|
||||||
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) {
|
) {
|
||||||
// create request, fake populated results and get response
|
// create request, fake populated results and get response
|
||||||
let get_results_response =
|
let get_results_response =
|
||||||
|
@ -114,7 +114,7 @@ async fn test_mocked_getresults_for_network(
|
||||||
async fn test_mocked_register_keys_for_network(
|
async fn test_mocked_register_keys_for_network(
|
||||||
client: &ScannerClient<Channel>,
|
client: &ScannerClient<Channel>,
|
||||||
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) {
|
) {
|
||||||
// create request, fake return value and get response
|
// create request, fake return value and get response
|
||||||
let register_keys_response =
|
let register_keys_response =
|
||||||
|
@ -132,7 +132,7 @@ async fn test_mocked_register_keys_for_network(
|
||||||
async fn test_mocked_clear_results_for_network(
|
async fn test_mocked_clear_results_for_network(
|
||||||
client: &ScannerClient<Channel>,
|
client: &ScannerClient<Channel>,
|
||||||
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) {
|
) {
|
||||||
// create request, fake results and get response
|
// create request, fake results and get response
|
||||||
let get_results_response =
|
let get_results_response =
|
||||||
|
@ -181,7 +181,7 @@ async fn test_mocked_clear_results_for_network(
|
||||||
async fn test_mocked_delete_keys_for_network(
|
async fn test_mocked_delete_keys_for_network(
|
||||||
client: &ScannerClient<Channel>,
|
client: &ScannerClient<Channel>,
|
||||||
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: &MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) {
|
) {
|
||||||
// create request, fake results and get response
|
// create request, fake results and get response
|
||||||
let register_keys_response =
|
let register_keys_response =
|
||||||
|
@ -267,9 +267,10 @@ async fn start_server_and_get_client(
|
||||||
/// Add fake populated results to the mock scan service
|
/// Add fake populated results to the mock scan service
|
||||||
async fn add_fake_populated_results(
|
async fn add_fake_populated_results(
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) {
|
) {
|
||||||
let mut mock_scan_service = mock_scan_service.clone();
|
let mut mock_scan_service = mock_scan_service.clone();
|
||||||
|
let network = network.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
||||||
let mut fake_results = BTreeMap::new();
|
let mut fake_results = BTreeMap::new();
|
||||||
|
@ -298,7 +299,7 @@ async fn add_fake_populated_results(
|
||||||
/// Add fake empty results to the mock scan service
|
/// Add fake empty results to the mock scan service
|
||||||
async fn add_fake_empty_results(
|
async fn add_fake_empty_results(
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
_network: Network,
|
_network: &Network,
|
||||||
) {
|
) {
|
||||||
let mut mock_scan_service = mock_scan_service.clone();
|
let mut mock_scan_service = mock_scan_service.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
@ -318,7 +319,7 @@ async fn add_fake_empty_results(
|
||||||
async fn call_get_results(
|
async fn call_get_results(
|
||||||
client: ScannerClient<Channel>,
|
client: ScannerClient<Channel>,
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
empty_results: bool,
|
empty_results: bool,
|
||||||
) -> tonic::Response<GetResultsResponse> {
|
) -> tonic::Response<GetResultsResponse> {
|
||||||
let get_results_response_fut = {
|
let get_results_response_fut = {
|
||||||
|
@ -380,7 +381,7 @@ async fn test_get_results_errors(mut client: ScannerClient<Channel>) {
|
||||||
async fn call_get_info(
|
async fn call_get_info(
|
||||||
client: ScannerClient<Channel>,
|
client: ScannerClient<Channel>,
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> tonic::Response<InfoReply> {
|
) -> tonic::Response<InfoReply> {
|
||||||
let get_info_response_fut = {
|
let get_info_response_fut = {
|
||||||
let mut client = client.clone();
|
let mut client = client.clone();
|
||||||
|
@ -389,6 +390,7 @@ async fn call_get_info(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mock_scan_service = mock_scan_service.clone();
|
let mut mock_scan_service = mock_scan_service.clone();
|
||||||
|
let network = network.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
mock_scan_service
|
mock_scan_service
|
||||||
.expect_request_that(|req| matches!(req, ScanRequest::Info))
|
.expect_request_that(|req| matches!(req, ScanRequest::Info))
|
||||||
|
@ -408,7 +410,7 @@ async fn call_get_info(
|
||||||
async fn call_register_keys(
|
async fn call_register_keys(
|
||||||
client: ScannerClient<Channel>,
|
client: ScannerClient<Channel>,
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
_network: Network,
|
_network: &Network,
|
||||||
) -> tonic::Response<RegisterKeysResponse> {
|
) -> tonic::Response<RegisterKeysResponse> {
|
||||||
let key_with_height = KeyWithHeight {
|
let key_with_height = KeyWithHeight {
|
||||||
key: ZECPAGES_SAPLING_VIEWING_KEY.to_string(),
|
key: ZECPAGES_SAPLING_VIEWING_KEY.to_string(),
|
||||||
|
@ -472,7 +474,7 @@ async fn test_register_keys_errors(client: ScannerClient<Channel>) {
|
||||||
async fn call_clear_results(
|
async fn call_clear_results(
|
||||||
client: ScannerClient<Channel>,
|
client: ScannerClient<Channel>,
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
_network: Network,
|
_network: &Network,
|
||||||
) -> tonic::Response<Empty> {
|
) -> tonic::Response<Empty> {
|
||||||
let clear_results_response_fut = {
|
let clear_results_response_fut = {
|
||||||
let mut client = client.clone();
|
let mut client = client.clone();
|
||||||
|
@ -525,7 +527,7 @@ async fn test_clear_results_errors(client: ScannerClient<Channel>) {
|
||||||
async fn call_delete_keys(
|
async fn call_delete_keys(
|
||||||
client: ScannerClient<Channel>,
|
client: ScannerClient<Channel>,
|
||||||
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
mock_scan_service: MockService<ScanRequest, ScanResponse, PanicAssertion>,
|
||||||
_network: Network,
|
_network: &Network,
|
||||||
) -> tonic::Response<Empty> {
|
) -> tonic::Response<Empty> {
|
||||||
let delete_keys_response_fut = {
|
let delete_keys_response_fut = {
|
||||||
let mut client = client.clone();
|
let mut client = client.clone();
|
||||||
|
|
|
@ -138,7 +138,7 @@ impl AddressBook {
|
||||||
/// Uses the supplied [`tracing::Span`] for address book operations.
|
/// Uses the supplied [`tracing::Span`] for address book operations.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
local_listener: SocketAddr,
|
local_listener: SocketAddr,
|
||||||
network: Network,
|
network: &Network,
|
||||||
max_connections_per_ip: usize,
|
max_connections_per_ip: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> AddressBook {
|
) -> AddressBook {
|
||||||
|
@ -157,7 +157,7 @@ impl AddressBook {
|
||||||
let mut new_book = AddressBook {
|
let mut new_book = AddressBook {
|
||||||
by_addr: OrderedMap::new(|meta_addr| Reverse(*meta_addr)),
|
by_addr: OrderedMap::new(|meta_addr| Reverse(*meta_addr)),
|
||||||
local_listener: canonical_socket_addr(local_listener),
|
local_listener: canonical_socket_addr(local_listener),
|
||||||
network,
|
network: network.clone(),
|
||||||
addr_limit: constants::MAX_ADDRS_IN_ADDRESS_BOOK,
|
addr_limit: constants::MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
span,
|
span,
|
||||||
address_metrics_tx,
|
address_metrics_tx,
|
||||||
|
@ -183,7 +183,7 @@ impl AddressBook {
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
pub fn new_with_addrs(
|
pub fn new_with_addrs(
|
||||||
local_listener: SocketAddr,
|
local_listener: SocketAddr,
|
||||||
network: Network,
|
network: &Network,
|
||||||
max_connections_per_ip: usize,
|
max_connections_per_ip: usize,
|
||||||
addr_limit: usize,
|
addr_limit: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -293,7 +293,7 @@ impl AddressBook {
|
||||||
// Then sanitize and shuffle
|
// Then sanitize and shuffle
|
||||||
let mut peers: Vec<MetaAddr> = peers
|
let mut peers: Vec<MetaAddr> = peers
|
||||||
.descending_values()
|
.descending_values()
|
||||||
.filter_map(|meta_addr| meta_addr.sanitize(self.network))
|
.filter_map(|meta_addr| meta_addr.sanitize(&self.network))
|
||||||
// # Security
|
// # Security
|
||||||
//
|
//
|
||||||
// Remove peers that:
|
// Remove peers that:
|
||||||
|
@ -431,7 +431,7 @@ impl AddressBook {
|
||||||
if let Some(updated) = updated {
|
if let Some(updated) = updated {
|
||||||
// Ignore invalid outbound addresses.
|
// Ignore invalid outbound addresses.
|
||||||
// (Inbound connections can be monitored via Zebra's metrics.)
|
// (Inbound connections can be monitored via Zebra's metrics.)
|
||||||
if !updated.address_is_valid_for_outbound(self.network) {
|
if !updated.address_is_valid_for_outbound(&self.network) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ impl AddressBook {
|
||||||
//
|
//
|
||||||
// Otherwise, if we got the info directly from the peer,
|
// Otherwise, if we got the info directly from the peer,
|
||||||
// store it in the address book, so we know not to reconnect.
|
// store it in the address book, so we know not to reconnect.
|
||||||
if !updated.last_known_info_is_valid_for_outbound(self.network)
|
if !updated.last_known_info_is_valid_for_outbound(&self.network)
|
||||||
&& updated.last_connection_state.is_never_attempted()
|
&& updated.last_connection_state.is_never_attempted()
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
|
@ -598,7 +598,7 @@ impl AddressBook {
|
||||||
self.by_addr
|
self.by_addr
|
||||||
.descending_values()
|
.descending_values()
|
||||||
.filter(move |peer| {
|
.filter(move |peer| {
|
||||||
peer.is_ready_for_connection_attempt(instant_now, chrono_now, self.network)
|
peer.is_ready_for_connection_attempt(instant_now, chrono_now, &self.network)
|
||||||
&& self.is_ready_for_connection_attempt_with_ip(&peer.addr.ip(), chrono_now)
|
&& self.is_ready_for_connection_attempt_with_ip(&peer.addr.ip(), chrono_now)
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -630,7 +630,7 @@ impl AddressBook {
|
||||||
self.by_addr
|
self.by_addr
|
||||||
.descending_values()
|
.descending_values()
|
||||||
.filter(move |peer| {
|
.filter(move |peer| {
|
||||||
!peer.is_ready_for_connection_attempt(instant_now, chrono_now, self.network)
|
!peer.is_ready_for_connection_attempt(instant_now, chrono_now, &self.network)
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
@ -800,7 +800,7 @@ impl Clone for AddressBook {
|
||||||
AddressBook {
|
AddressBook {
|
||||||
by_addr: self.by_addr.clone(),
|
by_addr: self.by_addr.clone(),
|
||||||
local_listener: self.local_listener,
|
local_listener: self.local_listener,
|
||||||
network: self.network,
|
network: self.network.clone(),
|
||||||
addr_limit: self.addr_limit,
|
addr_limit: self.addr_limit,
|
||||||
span: self.span.clone(),
|
span: self.span.clone(),
|
||||||
address_metrics_tx,
|
address_metrics_tx,
|
||||||
|
|
|
@ -32,7 +32,7 @@ proptest! {
|
||||||
|
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
local_listener,
|
local_listener,
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
@ -71,7 +71,7 @@ proptest! {
|
||||||
|
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
local_listener,
|
local_listener,
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
@ -110,7 +110,7 @@ proptest! {
|
||||||
|
|
||||||
let mut address_book = AddressBook::new_with_addrs(
|
let mut address_book = AddressBook::new_with_addrs(
|
||||||
local_listener,
|
local_listener,
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
addr_limit,
|
addr_limit,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
@ -133,7 +133,7 @@ proptest! {
|
||||||
|
|
||||||
let mut address_book = AddressBook::new_with_addrs(
|
let mut address_book = AddressBook::new_with_addrs(
|
||||||
local_listener,
|
local_listener,
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
addr_limit,
|
addr_limit,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
fn address_book_empty() {
|
fn address_book_empty() {
|
||||||
let address_book = AddressBook::new(
|
let address_book = AddressBook::new(
|
||||||
"0.0.0.0:0".parse().unwrap(),
|
"0.0.0.0:0".parse().unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
Span::current(),
|
Span::current(),
|
||||||
);
|
);
|
||||||
|
@ -54,7 +54,7 @@ fn address_book_peer_order() {
|
||||||
let addrs = vec![meta_addr1, meta_addr2];
|
let addrs = vec![meta_addr1, meta_addr2];
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
"0.0.0.0:0".parse().unwrap(),
|
"0.0.0.0:0".parse().unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::current(),
|
Span::current(),
|
||||||
|
@ -71,7 +71,7 @@ fn address_book_peer_order() {
|
||||||
let addrs = vec![meta_addr2, meta_addr1];
|
let addrs = vec![meta_addr2, meta_addr1];
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
"0.0.0.0:0".parse().unwrap(),
|
"0.0.0.0:0".parse().unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::current(),
|
Span::current(),
|
||||||
|
@ -91,7 +91,7 @@ fn address_book_peer_order() {
|
||||||
let addrs = vec![meta_addr1, meta_addr2];
|
let addrs = vec![meta_addr1, meta_addr2];
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
"0.0.0.0:0".parse().unwrap(),
|
"0.0.0.0:0".parse().unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::current(),
|
Span::current(),
|
||||||
|
@ -108,7 +108,7 @@ fn address_book_peer_order() {
|
||||||
let addrs = vec![meta_addr2, meta_addr1];
|
let addrs = vec![meta_addr2, meta_addr1];
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
"0.0.0.0:0".parse().unwrap(),
|
"0.0.0.0:0".parse().unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::current(),
|
Span::current(),
|
||||||
|
@ -163,7 +163,7 @@ fn test_reconnection_peers_skips_recently_updated_ip<
|
||||||
let addrs = vec![meta_addr1, meta_addr2];
|
let addrs = vec![meta_addr1, meta_addr2];
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
"0.0.0.0:0".parse().unwrap(),
|
"0.0.0.0:0".parse().unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::current(),
|
Span::current(),
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl AddressBookUpdater {
|
||||||
|
|
||||||
let address_book = AddressBook::new(
|
let address_book = AddressBook::new(
|
||||||
local_listener,
|
local_listener,
|
||||||
config.network,
|
&config.network,
|
||||||
config.max_connections_per_ip,
|
config.max_connections_per_ip,
|
||||||
span!(Level::TRACE, "address book"),
|
span!(Level::TRACE, "address book"),
|
||||||
);
|
);
|
||||||
|
|
|
@ -381,7 +381,7 @@ impl Config {
|
||||||
|
|
||||||
/// Returns the addresses in the peer list cache file, if available.
|
/// Returns the addresses in the peer list cache file, if available.
|
||||||
pub async fn load_peer_cache(&self) -> io::Result<HashSet<PeerSocketAddr>> {
|
pub async fn load_peer_cache(&self) -> io::Result<HashSet<PeerSocketAddr>> {
|
||||||
let Some(peer_cache_file) = self.cache_dir.peer_cache_file_path(self.network) else {
|
let Some(peer_cache_file) = self.cache_dir.peer_cache_file_path(&self.network) else {
|
||||||
return Ok(HashSet::new());
|
return Ok(HashSet::new());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -457,7 +457,7 @@ impl Config {
|
||||||
/// Atomic writes avoid corrupting the cache if Zebra panics or crashes, or if multiple Zebra
|
/// Atomic writes avoid corrupting the cache if Zebra panics or crashes, or if multiple Zebra
|
||||||
/// instances try to read and write the same cache file.
|
/// instances try to read and write the same cache file.
|
||||||
pub async fn update_peer_cache(&self, peer_list: HashSet<PeerSocketAddr>) -> io::Result<()> {
|
pub async fn update_peer_cache(&self, peer_list: HashSet<PeerSocketAddr>) -> io::Result<()> {
|
||||||
let Some(peer_cache_file) = self.cache_dir.peer_cache_file_path(self.network) else {
|
let Some(peer_cache_file) = self.cache_dir.peer_cache_file_path(&self.network) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl CacheDir {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the peer cache file path for `network`, if enabled.
|
/// Returns the peer cache file path for `network`, if enabled.
|
||||||
pub fn peer_cache_file_path(&self, network: Network) -> Option<PathBuf> {
|
pub fn peer_cache_file_path(&self, network: &Network) -> Option<PathBuf> {
|
||||||
Some(
|
Some(
|
||||||
self.cache_dir()?
|
self.cache_dir()?
|
||||||
.join("network")
|
.join("network")
|
||||||
|
|
|
@ -395,8 +395,8 @@ lazy_static! {
|
||||||
pub static ref INITIAL_MIN_NETWORK_PROTOCOL_VERSION: HashMap<Network, Version> = {
|
pub static ref INITIAL_MIN_NETWORK_PROTOCOL_VERSION: HashMap<Network, Version> = {
|
||||||
let mut hash_map = HashMap::new();
|
let mut hash_map = HashMap::new();
|
||||||
|
|
||||||
hash_map.insert(Mainnet, Version::min_specified_for_upgrade(Mainnet, Nu5));
|
hash_map.insert(Mainnet, Version::min_specified_for_upgrade(&Mainnet, Nu5));
|
||||||
hash_map.insert(Testnet, Version::min_specified_for_upgrade(Testnet, Nu5));
|
hash_map.insert(Testnet, Version::min_specified_for_upgrade(&Testnet, Nu5));
|
||||||
|
|
||||||
hash_map
|
hash_map
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,7 +47,7 @@ mod tests;
|
||||||
///
|
///
|
||||||
/// - `user_agent`: a valid BIP14 user-agent, e.g., the empty string.
|
/// - `user_agent`: a valid BIP14 user-agent, e.g., the empty string.
|
||||||
pub fn connect_isolated<PeerTransport>(
|
pub fn connect_isolated<PeerTransport>(
|
||||||
network: Network,
|
network: &Network,
|
||||||
data_stream: PeerTransport,
|
data_stream: PeerTransport,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
) -> impl Future<Output = Result<Client, BoxError>>
|
) -> impl Future<Output = Result<Client, BoxError>>
|
||||||
|
@ -74,7 +74,7 @@ where
|
||||||
/// This function can make the isolated connection send different responses to peers,
|
/// This function can make the isolated connection send different responses to peers,
|
||||||
/// which makes it stand out from other isolated connections from other peers.
|
/// which makes it stand out from other isolated connections from other peers.
|
||||||
pub fn connect_isolated_with_inbound<PeerTransport, InboundService>(
|
pub fn connect_isolated_with_inbound<PeerTransport, InboundService>(
|
||||||
network: Network,
|
network: &Network,
|
||||||
data_stream: PeerTransport,
|
data_stream: PeerTransport,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
inbound_service: InboundService,
|
inbound_service: InboundService,
|
||||||
|
@ -86,7 +86,7 @@ where
|
||||||
InboundService::Future: Send,
|
InboundService::Future: Send,
|
||||||
{
|
{
|
||||||
let config = Config {
|
let config = Config {
|
||||||
network,
|
network: network.clone(),
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ where
|
||||||
///
|
///
|
||||||
/// Prefer `connect_isolated_tor` if available.
|
/// Prefer `connect_isolated_tor` if available.
|
||||||
pub fn connect_isolated_tcp_direct(
|
pub fn connect_isolated_tcp_direct(
|
||||||
network: Network,
|
network: &Network,
|
||||||
addr: impl Into<PeerSocketAddr>,
|
addr: impl Into<PeerSocketAddr>,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
) -> impl Future<Output = Result<Client, BoxError>> {
|
) -> impl Future<Output = Result<Client, BoxError>> {
|
||||||
|
@ -145,7 +145,7 @@ pub fn connect_isolated_tcp_direct(
|
||||||
/// This function can make the isolated connection send different responses to peers,
|
/// This function can make the isolated connection send different responses to peers,
|
||||||
/// which makes it stand out from other isolated connections from other peers.
|
/// which makes it stand out from other isolated connections from other peers.
|
||||||
pub fn connect_isolated_tcp_direct_with_inbound<InboundService>(
|
pub fn connect_isolated_tcp_direct_with_inbound<InboundService>(
|
||||||
network: Network,
|
network: &Network,
|
||||||
addr: impl Into<PeerSocketAddr>,
|
addr: impl Into<PeerSocketAddr>,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
inbound_service: InboundService,
|
inbound_service: InboundService,
|
||||||
|
@ -156,10 +156,11 @@ where
|
||||||
InboundService::Future: Send,
|
InboundService::Future: Send,
|
||||||
{
|
{
|
||||||
let addr = addr.into();
|
let addr = addr.into();
|
||||||
|
let network = network.clone();
|
||||||
|
|
||||||
tokio::net::TcpStream::connect(*addr)
|
tokio::net::TcpStream::connect(*addr)
|
||||||
.err_into()
|
.err_into()
|
||||||
.and_then(move |tcp_stream| {
|
.and_then(move |tcp_stream| {
|
||||||
connect_isolated_with_inbound(network, tcp_stream, user_agent, inbound_service)
|
connect_isolated_with_inbound(&network, tcp_stream, user_agent, inbound_service)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,17 @@ async fn connect_isolated_sends_anonymised_version_message_tcp_net(network: Netw
|
||||||
// Connection errors are detected using the JoinHandle.
|
// Connection errors are detected using the JoinHandle.
|
||||||
// (They might also make the test hang.)
|
// (They might also make the test hang.)
|
||||||
let mut outbound_join_handle = tokio::spawn(connect_isolated_tcp_direct(
|
let mut outbound_join_handle = tokio::spawn(connect_isolated_tcp_direct(
|
||||||
network,
|
&network,
|
||||||
listen_addr,
|
listen_addr,
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
));
|
));
|
||||||
|
|
||||||
let (inbound_conn, _) = listener.accept().await.unwrap();
|
let (inbound_conn, _) = listener.accept().await.unwrap();
|
||||||
|
|
||||||
let mut inbound_stream =
|
let mut inbound_stream = Framed::new(
|
||||||
Framed::new(inbound_conn, Codec::builder().for_network(network).finish());
|
inbound_conn,
|
||||||
|
Codec::builder().for_network(&network).finish(),
|
||||||
|
);
|
||||||
|
|
||||||
check_version_message(network, &mut inbound_stream).await;
|
check_version_message(network, &mut inbound_stream).await;
|
||||||
|
|
||||||
|
@ -90,11 +92,11 @@ async fn connect_isolated_sends_anonymised_version_message_mem_net(network: Netw
|
||||||
let (inbound_stream, outbound_stream) = tokio::io::duplex(1024);
|
let (inbound_stream, outbound_stream) = tokio::io::duplex(1024);
|
||||||
|
|
||||||
let mut outbound_join_handle =
|
let mut outbound_join_handle =
|
||||||
tokio::spawn(connect_isolated(network, outbound_stream, "".to_string()));
|
tokio::spawn(connect_isolated(&network, outbound_stream, "".to_string()));
|
||||||
|
|
||||||
let mut inbound_stream = Framed::new(
|
let mut inbound_stream = Framed::new(
|
||||||
inbound_stream,
|
inbound_stream,
|
||||||
Codec::builder().for_network(network).finish(),
|
Codec::builder().for_network(&network).finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
check_version_message(network, &mut inbound_stream).await;
|
check_version_message(network, &mut inbound_stream).await;
|
||||||
|
|
|
@ -559,7 +559,7 @@ impl MetaAddr {
|
||||||
&self,
|
&self,
|
||||||
instant_now: Instant,
|
instant_now: Instant,
|
||||||
chrono_now: chrono::DateTime<Utc>,
|
chrono_now: chrono::DateTime<Utc>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.last_known_info_is_valid_for_outbound(network)
|
self.last_known_info_is_valid_for_outbound(network)
|
||||||
&& !self.was_recently_updated(instant_now, chrono_now)
|
&& !self.was_recently_updated(instant_now, chrono_now)
|
||||||
|
@ -571,8 +571,8 @@ impl MetaAddr {
|
||||||
///
|
///
|
||||||
/// Since the addresses in the address book are unique, this check can be
|
/// Since the addresses in the address book are unique, this check can be
|
||||||
/// used to permanently reject entire [`MetaAddr`]s.
|
/// used to permanently reject entire [`MetaAddr`]s.
|
||||||
pub fn address_is_valid_for_outbound(&self, network: Network) -> bool {
|
pub fn address_is_valid_for_outbound(&self, network: &Network) -> bool {
|
||||||
address_is_valid_for_outbound_connections(self.addr, network).is_ok()
|
address_is_valid_for_outbound_connections(self.addr, network.clone()).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the last known information for this peer valid for outbound
|
/// Is the last known information for this peer valid for outbound
|
||||||
|
@ -582,7 +582,7 @@ impl MetaAddr {
|
||||||
/// only be used to:
|
/// only be used to:
|
||||||
/// - reject `NeverAttempted...` [`MetaAddrChange`]s, and
|
/// - reject `NeverAttempted...` [`MetaAddrChange`]s, and
|
||||||
/// - temporarily stop outbound connections to a [`MetaAddr`].
|
/// - temporarily stop outbound connections to a [`MetaAddr`].
|
||||||
pub fn last_known_info_is_valid_for_outbound(&self, network: Network) -> bool {
|
pub fn last_known_info_is_valid_for_outbound(&self, network: &Network) -> bool {
|
||||||
let is_node = match self.services {
|
let is_node = match self.services {
|
||||||
Some(services) => services.contains(PeerServices::NODE_NETWORK),
|
Some(services) => services.contains(PeerServices::NODE_NETWORK),
|
||||||
None => true,
|
None => true,
|
||||||
|
@ -627,7 +627,7 @@ impl MetaAddr {
|
||||||
///
|
///
|
||||||
/// Returns `None` if this `MetaAddr` should not be sent to remote peers.
|
/// Returns `None` if this `MetaAddr` should not be sent to remote peers.
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
pub fn sanitize(&self, network: Network) -> Option<MetaAddr> {
|
pub fn sanitize(&self, network: &Network) -> Option<MetaAddr> {
|
||||||
if !self.last_known_info_is_valid_for_outbound(network) {
|
if !self.last_known_info_is_valid_for_outbound(network) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ impl MetaAddrChange {
|
||||||
|(addr, services, local_now)| {
|
|(addr, services, local_now)| {
|
||||||
let addr = MetaAddr::new_gossiped_meta_addr(addr, services, local_now);
|
let addr = MetaAddr::new_gossiped_meta_addr(addr, services, local_now);
|
||||||
|
|
||||||
if addr.last_known_info_is_valid_for_outbound(Mainnet) {
|
if addr.last_known_info_is_valid_for_outbound(&Mainnet) {
|
||||||
Some(addr.addr.port())
|
Some(addr.addr.port())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -42,9 +42,9 @@ proptest! {
|
||||||
fn sanitize_avoids_leaks(addr in MetaAddr::arbitrary()) {
|
fn sanitize_avoids_leaks(addr in MetaAddr::arbitrary()) {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
if let Some(sanitized) = addr.sanitize(Mainnet) {
|
if let Some(sanitized) = addr.sanitize(&Mainnet) {
|
||||||
// check that all sanitized addresses are valid for outbound
|
// check that all sanitized addresses are valid for outbound
|
||||||
prop_assert!(addr.last_known_info_is_valid_for_outbound(Mainnet));
|
prop_assert!(addr.last_known_info_is_valid_for_outbound(&Mainnet));
|
||||||
// also check the address, port, and services individually
|
// also check the address, port, and services individually
|
||||||
prop_assert!(!addr.addr.ip().is_unspecified());
|
prop_assert!(!addr.addr.ip().is_unspecified());
|
||||||
prop_assert_ne!(addr.addr.port(), 0);
|
prop_assert_ne!(addr.addr.port(), 0);
|
||||||
|
@ -117,7 +117,7 @@ proptest! {
|
||||||
let mut attempt_count: usize = 0;
|
let mut attempt_count: usize = 0;
|
||||||
|
|
||||||
for change in changes {
|
for change in changes {
|
||||||
while addr.is_ready_for_connection_attempt(instant_now, chrono_now, Mainnet) {
|
while addr.is_ready_for_connection_attempt(instant_now, chrono_now, &Mainnet) {
|
||||||
// Simulate an attempt
|
// Simulate an attempt
|
||||||
addr = if let Some(addr) = MetaAddr::new_reconnect(addr.addr)
|
addr = if let Some(addr) = MetaAddr::new_reconnect(addr.addr)
|
||||||
.apply_to_meta_addr(addr, instant_now, chrono_now) {
|
.apply_to_meta_addr(addr, instant_now, chrono_now) {
|
||||||
|
@ -158,7 +158,7 @@ proptest! {
|
||||||
|
|
||||||
let address_book = AddressBook::new_with_addrs(
|
let address_book = AddressBook::new_with_addrs(
|
||||||
local_listener,
|
local_listener,
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
@ -176,7 +176,7 @@ proptest! {
|
||||||
// regardless of where they have come from
|
// regardless of where they have come from
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
book_sanitized_local_listener.cloned(),
|
book_sanitized_local_listener.cloned(),
|
||||||
expected_local_listener.sanitize(Mainnet),
|
expected_local_listener.sanitize(&Mainnet),
|
||||||
"address book: {:?}, sanitized_addrs: {:?}, canonical_local_listener: {:?}",
|
"address book: {:?}, sanitized_addrs: {:?}, canonical_local_listener: {:?}",
|
||||||
address_book,
|
address_book,
|
||||||
sanitized_addrs,
|
sanitized_addrs,
|
||||||
|
@ -217,7 +217,7 @@ proptest! {
|
||||||
// Check address book update - return value
|
// Check address book update - return value
|
||||||
let mut address_book = AddressBook::new_with_addrs(
|
let mut address_book = AddressBook::new_with_addrs(
|
||||||
local_listener,
|
local_listener,
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
1,
|
1,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
@ -229,8 +229,8 @@ proptest! {
|
||||||
let book_contents: Vec<MetaAddr> = address_book.peers().collect();
|
let book_contents: Vec<MetaAddr> = address_book.peers().collect();
|
||||||
|
|
||||||
// Ignore the same addresses that the address book ignores
|
// Ignore the same addresses that the address book ignores
|
||||||
let expected_result = if !expected_result.address_is_valid_for_outbound(Mainnet)
|
let expected_result = if !expected_result.address_is_valid_for_outbound(&Mainnet)
|
||||||
|| ( !expected_result.last_known_info_is_valid_for_outbound(Mainnet)
|
|| ( !expected_result.last_known_info_is_valid_for_outbound(&Mainnet)
|
||||||
&& expected_result.last_connection_state.is_never_attempted())
|
&& expected_result.last_connection_state.is_never_attempted())
|
||||||
{
|
{
|
||||||
None
|
None
|
||||||
|
@ -323,7 +323,7 @@ proptest! {
|
||||||
|
|
||||||
// Only put valid addresses in the address book.
|
// Only put valid addresses in the address book.
|
||||||
// This means some tests will start with an empty address book.
|
// This means some tests will start with an empty address book.
|
||||||
let addrs = if addr.last_known_info_is_valid_for_outbound(Mainnet) {
|
let addrs = if addr.last_known_info_is_valid_for_outbound(&Mainnet) {
|
||||||
Some(addr)
|
Some(addr)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -331,7 +331,7 @@ proptest! {
|
||||||
|
|
||||||
let address_book = Arc::new(std::sync::Mutex::new(AddressBook::new_with_addrs(
|
let address_book = Arc::new(std::sync::Mutex::new(AddressBook::new_with_addrs(
|
||||||
SocketAddr::from_str("0.0.0.0:0").unwrap(),
|
SocketAddr::from_str("0.0.0.0:0").unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
MAX_ADDRS_IN_ADDRESS_BOOK,
|
MAX_ADDRS_IN_ADDRESS_BOOK,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
|
@ -371,7 +371,7 @@ proptest! {
|
||||||
LIVE_PEER_INTERVALS,
|
LIVE_PEER_INTERVALS,
|
||||||
overall_test_time,
|
overall_test_time,
|
||||||
peer_change_interval,
|
peer_change_interval,
|
||||||
addr.last_known_info_is_valid_for_outbound(Mainnet),
|
addr.last_known_info_is_valid_for_outbound(&Mainnet),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ proptest! {
|
||||||
let addr = addrs.entry(addr.addr).or_insert(*addr);
|
let addr = addrs.entry(addr.addr).or_insert(*addr);
|
||||||
let change = changes.get(change_index);
|
let change = changes.get(change_index);
|
||||||
|
|
||||||
while addr.is_ready_for_connection_attempt(instant_now, chrono_now, Mainnet) {
|
while addr.is_ready_for_connection_attempt(instant_now, chrono_now, &Mainnet) {
|
||||||
// Simulate an attempt
|
// Simulate an attempt
|
||||||
*addr = if let Some(addr) = MetaAddr::new_reconnect(addr.addr)
|
*addr = if let Some(addr) = MetaAddr::new_reconnect(addr.addr)
|
||||||
.apply_to_meta_addr(*addr, instant_now, chrono_now) {
|
.apply_to_meta_addr(*addr, instant_now, chrono_now) {
|
||||||
|
|
|
@ -48,10 +48,10 @@ fn sanitize_extremes() {
|
||||||
last_connection_state: Default::default(),
|
last_connection_state: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(min_sanitized) = min_time_entry.sanitize(Mainnet) {
|
if let Some(min_sanitized) = min_time_entry.sanitize(&Mainnet) {
|
||||||
check::sanitize_avoids_leaks(&min_time_entry, &min_sanitized);
|
check::sanitize_avoids_leaks(&min_time_entry, &min_sanitized);
|
||||||
}
|
}
|
||||||
if let Some(max_sanitized) = max_time_entry.sanitize(Mainnet) {
|
if let Some(max_sanitized) = max_time_entry.sanitize(&Mainnet) {
|
||||||
check::sanitize_avoids_leaks(&max_time_entry, &max_sanitized);
|
check::sanitize_avoids_leaks(&max_time_entry, &max_sanitized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,8 +515,8 @@ where
|
||||||
let user_agent = self.user_agent.unwrap_or_default();
|
let user_agent = self.user_agent.unwrap_or_default();
|
||||||
let our_services = self.our_services.unwrap_or_else(PeerServices::empty);
|
let our_services = self.our_services.unwrap_or_else(PeerServices::empty);
|
||||||
let relay = self.relay.unwrap_or(false);
|
let relay = self.relay.unwrap_or(false);
|
||||||
let network = config.network;
|
let network = config.network.clone();
|
||||||
let minimum_peer_version = MinimumPeerVersion::new(self.latest_chain_tip, network);
|
let minimum_peer_version = MinimumPeerVersion::new(self.latest_chain_tip, &network);
|
||||||
|
|
||||||
Ok(Handshake {
|
Ok(Handshake {
|
||||||
config,
|
config,
|
||||||
|
@ -898,7 +898,7 @@ where
|
||||||
let mut peer_conn = Framed::new(
|
let mut peer_conn = Framed::new(
|
||||||
data_stream,
|
data_stream,
|
||||||
Codec::builder()
|
Codec::builder()
|
||||||
.for_network(config.network)
|
.for_network(&config.network)
|
||||||
.with_metrics_addr_label(connected_addr.get_transient_addr_label())
|
.with_metrics_addr_label(connected_addr.get_transient_addr_label())
|
||||||
.finish(),
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,9 +35,9 @@ where
|
||||||
{
|
{
|
||||||
/// Create a new [`MinimumPeerVersion`] to track the minimum supported peer protocol version
|
/// Create a new [`MinimumPeerVersion`] to track the minimum supported peer protocol version
|
||||||
/// for the current `chain_tip` on the `network`.
|
/// for the current `chain_tip` on the `network`.
|
||||||
pub fn new(chain_tip: C, network: Network) -> Self {
|
pub fn new(chain_tip: C, network: &Network) -> Self {
|
||||||
MinimumPeerVersion {
|
MinimumPeerVersion {
|
||||||
network,
|
network: network.clone(),
|
||||||
chain_tip,
|
chain_tip,
|
||||||
current_minimum: Version::min_remote_for_height(network, None),
|
current_minimum: Version::min_remote_for_height(network, None),
|
||||||
has_changed: true,
|
has_changed: true,
|
||||||
|
@ -72,7 +72,7 @@ where
|
||||||
/// has changed.
|
/// has changed.
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
let height = self.chain_tip.best_tip_height();
|
let height = self.chain_tip.best_tip_height();
|
||||||
let new_minimum = Version::min_remote_for_height(self.network, height);
|
let new_minimum = Version::min_remote_for_height(&self.network, height);
|
||||||
|
|
||||||
if self.current_minimum != new_minimum {
|
if self.current_minimum != new_minimum {
|
||||||
self.current_minimum = new_minimum;
|
self.current_minimum = new_minimum;
|
||||||
|
@ -99,7 +99,7 @@ where
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
MinimumPeerVersion {
|
MinimumPeerVersion {
|
||||||
network: self.network,
|
network: self.network.clone(),
|
||||||
chain_tip: self.chain_tip.clone(),
|
chain_tip: self.chain_tip.clone(),
|
||||||
current_minimum: self.current_minimum,
|
current_minimum: self.current_minimum,
|
||||||
has_changed: true,
|
has_changed: true,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use super::MinimumPeerVersion;
|
||||||
mod prop;
|
mod prop;
|
||||||
|
|
||||||
impl MinimumPeerVersion<MockChainTip> {
|
impl MinimumPeerVersion<MockChainTip> {
|
||||||
pub fn with_mock_chain_tip(network: Network) -> (Self, MockChainTipSender) {
|
pub fn with_mock_chain_tip(network: &Network) -> (Self, MockChainTipSender) {
|
||||||
let (chain_tip, best_tip) = MockChainTip::new();
|
let (chain_tip, best_tip) = MockChainTip::new();
|
||||||
let minimum_peer_version = MinimumPeerVersion::new(chain_tip, network);
|
let minimum_peer_version = MinimumPeerVersion::new(chain_tip, network);
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,11 @@ proptest! {
|
||||||
block_height in any::<Option<block::Height>>(),
|
block_height in any::<Option<block::Height>>(),
|
||||||
) {
|
) {
|
||||||
let (mut minimum_peer_version, best_tip) =
|
let (mut minimum_peer_version, best_tip) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(network);
|
MinimumPeerVersion::with_mock_chain_tip(&network);
|
||||||
|
|
||||||
best_tip.send_best_tip_height(block_height);
|
best_tip.send_best_tip_height(block_height);
|
||||||
|
|
||||||
let expected_minimum_version = Version::min_remote_for_height(network, block_height);
|
let expected_minimum_version = Version::min_remote_for_height(&network, block_height);
|
||||||
|
|
||||||
prop_assert_eq!(minimum_peer_version.current(), expected_minimum_version);
|
prop_assert_eq!(minimum_peer_version.current(), expected_minimum_version);
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ proptest! {
|
||||||
block_heights in any::<Vec<Option<block::Height>>>(),
|
block_heights in any::<Vec<Option<block::Height>>>(),
|
||||||
) {
|
) {
|
||||||
let (mut minimum_peer_version, best_tip) =
|
let (mut minimum_peer_version, best_tip) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(network);
|
MinimumPeerVersion::with_mock_chain_tip(&network);
|
||||||
|
|
||||||
for block_height in block_heights {
|
for block_height in block_heights {
|
||||||
best_tip.send_best_tip_height(block_height);
|
best_tip.send_best_tip_height(block_height);
|
||||||
|
|
||||||
let expected_minimum_version = Version::min_remote_for_height(network, block_height);
|
let expected_minimum_version = Version::min_remote_for_height(&network, block_height);
|
||||||
|
|
||||||
prop_assert_eq!(minimum_peer_version.current(), expected_minimum_version);
|
prop_assert_eq!(minimum_peer_version.current(), expected_minimum_version);
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,9 @@ proptest! {
|
||||||
block_height_updates in any::<Vec<Option<Option<block::Height>>>>(),
|
block_height_updates in any::<Vec<Option<Option<block::Height>>>>(),
|
||||||
) {
|
) {
|
||||||
let (mut minimum_peer_version, best_tip) =
|
let (mut minimum_peer_version, best_tip) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(network);
|
MinimumPeerVersion::with_mock_chain_tip(&network);
|
||||||
|
|
||||||
let mut current_minimum_version = Version::min_remote_for_height(network, None);
|
let mut current_minimum_version = Version::min_remote_for_height(&network, None);
|
||||||
let mut expected_minimum_version = Some(current_minimum_version);
|
let mut expected_minimum_version = Some(current_minimum_version);
|
||||||
|
|
||||||
prop_assert_eq!(minimum_peer_version.changed(), expected_minimum_version);
|
prop_assert_eq!(minimum_peer_version.changed(), expected_minimum_version);
|
||||||
|
@ -57,7 +57,7 @@ proptest! {
|
||||||
if let Some(new_block_height) = update {
|
if let Some(new_block_height) = update {
|
||||||
best_tip.send_best_tip_height(new_block_height);
|
best_tip.send_best_tip_height(new_block_height);
|
||||||
|
|
||||||
let new_minimum_version = Version::min_remote_for_height(network, new_block_height);
|
let new_minimum_version = Version::min_remote_for_height(&network, new_block_height);
|
||||||
|
|
||||||
expected_minimum_version = if new_minimum_version != current_minimum_version {
|
expected_minimum_version = if new_minimum_version != current_minimum_version {
|
||||||
Some(new_minimum_version)
|
Some(new_minimum_version)
|
||||||
|
|
|
@ -71,7 +71,7 @@ proptest! {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Since the address book is empty, there won't be any available peers
|
// Since the address book is empty, there won't be any available peers
|
||||||
let address_book = AddressBook::new(SocketAddr::from_str("0.0.0.0:0").unwrap(), Mainnet, DEFAULT_MAX_CONNS_PER_IP, Span::none());
|
let address_book = AddressBook::new(SocketAddr::from_str("0.0.0.0:0").unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, Span::none());
|
||||||
|
|
||||||
let mut candidate_set = CandidateSet::new(Arc::new(std::sync::Mutex::new(address_book)), peer_service);
|
let mut candidate_set = CandidateSet::new(Arc::new(std::sync::Mutex::new(address_book)), peer_service);
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ proptest! {
|
||||||
unreachable!("Mock peer service is never used");
|
unreachable!("Mock peer service is never used");
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut address_book = AddressBook::new(SocketAddr::from_str("0.0.0.0:0").unwrap(), Mainnet, DEFAULT_MAX_CONNS_PER_IP, Span::none());
|
let mut address_book = AddressBook::new(SocketAddr::from_str("0.0.0.0:0").unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, Span::none());
|
||||||
address_book.extend(peers);
|
address_book.extend(peers);
|
||||||
|
|
||||||
let mut candidate_set = CandidateSet::new(Arc::new(std::sync::Mutex::new(address_book)), peer_service);
|
let mut candidate_set = CandidateSet::new(Arc::new(std::sync::Mutex::new(address_book)), peer_service);
|
||||||
|
|
|
@ -140,7 +140,7 @@ fn candidate_set_updates_are_rate_limited() {
|
||||||
|
|
||||||
let address_book = AddressBook::new(
|
let address_book = AddressBook::new(
|
||||||
SocketAddr::from_str("0.0.0.0:0").unwrap(),
|
SocketAddr::from_str("0.0.0.0:0").unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
);
|
);
|
||||||
|
@ -186,7 +186,7 @@ fn candidate_set_update_after_update_initial_is_rate_limited() {
|
||||||
|
|
||||||
let address_book = AddressBook::new(
|
let address_book = AddressBook::new(
|
||||||
SocketAddr::from_str("0.0.0.0:0").unwrap(),
|
SocketAddr::from_str("0.0.0.0:0").unwrap(),
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -174,7 +174,7 @@ where
|
||||||
handle_rx,
|
handle_rx,
|
||||||
inv_receiver,
|
inv_receiver,
|
||||||
address_metrics,
|
address_metrics,
|
||||||
MinimumPeerVersion::new(latest_chain_tip, config.network),
|
MinimumPeerVersion::new(latest_chain_tip, &config.network),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let peer_set = Buffer::new(BoxService::new(peer_set), constants::PEERSET_BUFFER_SIZE);
|
let peer_set = Buffer::new(BoxService::new(peer_set), constants::PEERSET_BUFFER_SIZE);
|
||||||
|
@ -436,7 +436,7 @@ async fn limit_initial_peers(
|
||||||
// Filter out invalid initial peers, and prioritise valid peers for initial connections.
|
// Filter out invalid initial peers, and prioritise valid peers for initial connections.
|
||||||
// (This treats initial peers the same way we treat gossiped peers.)
|
// (This treats initial peers the same way we treat gossiped peers.)
|
||||||
for peer_addr in all_peers {
|
for peer_addr in all_peers {
|
||||||
let preference = PeerPreference::new(peer_addr, config.network);
|
let preference = PeerPreference::new(peer_addr, config.network.clone());
|
||||||
|
|
||||||
match preference {
|
match preference {
|
||||||
Ok(preference) => preferred_peers
|
Ok(preference) => preferred_peers
|
||||||
|
@ -499,7 +499,7 @@ async fn limit_initial_peers(
|
||||||
pub(crate) async fn open_listener(config: &Config) -> (TcpListener, SocketAddr) {
|
pub(crate) async fn open_listener(config: &Config) -> (TcpListener, SocketAddr) {
|
||||||
// Warn if we're configured using the wrong network port.
|
// Warn if we're configured using the wrong network port.
|
||||||
if let Err(wrong_addr) =
|
if let Err(wrong_addr) =
|
||||||
address_is_valid_for_inbound_listeners(config.listen_addr, config.network)
|
address_is_valid_for_inbound_listeners(config.listen_addr, config.network.clone())
|
||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"We are configured with address {} on {:?}, but it could cause network issues. \
|
"We are configured with address {} on {:?}, but it could cause network issues. \
|
||||||
|
|
|
@ -325,7 +325,7 @@ async fn written_peer_cache_can_be_read_manually() {
|
||||||
assert!(
|
assert!(
|
||||||
!cached_peers.is_empty(),
|
!cached_peers.is_empty(),
|
||||||
"unexpected empty peer cache from manual load: {:?}",
|
"unexpected empty peer cache from manual load: {:?}",
|
||||||
config.cache_dir.peer_cache_file_path(config.network)
|
config.cache_dir.peer_cache_file_path(&config.network)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,7 +371,7 @@ async fn written_peer_cache_is_automatically_read_on_startup() {
|
||||||
assert!(
|
assert!(
|
||||||
approximate_cached_peer_count > 0,
|
approximate_cached_peer_count > 0,
|
||||||
"unexpected empty address book using cache from previous instance: {:?}",
|
"unexpected empty address book using cache from previous instance: {:?}",
|
||||||
config.cache_dir.peer_cache_file_path(config.network)
|
config.cache_dir.peer_cache_file_path(&config.network)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,7 +336,7 @@ impl PeerSetGuard {
|
||||||
.expect("Invalid local listener address");
|
.expect("Invalid local listener address");
|
||||||
let address_book = AddressBook::new(
|
let address_book = AddressBook::new(
|
||||||
local_listener,
|
local_listener,
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
DEFAULT_MAX_CONNS_PER_IP,
|
DEFAULT_MAX_CONNS_PER_IP,
|
||||||
Span::none(),
|
Span::none(),
|
||||||
);
|
);
|
||||||
|
@ -347,7 +347,7 @@ impl PeerSetGuard {
|
||||||
|
|
||||||
/// A pair of block height values, where one is before and the other is at or after an arbitrary
|
/// A pair of block height values, where one is before and the other is at or after an arbitrary
|
||||||
/// network upgrade's activation height.
|
/// network upgrade's activation height.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BlockHeightPairAcrossNetworkUpgrades {
|
pub struct BlockHeightPairAcrossNetworkUpgrades {
|
||||||
/// The network for which the block height values represent heights before and after an
|
/// The network for which the block height values represent heights before and after an
|
||||||
/// upgrade.
|
/// upgrade.
|
||||||
|
@ -374,7 +374,7 @@ impl Arbitrary for BlockHeightPairAcrossNetworkUpgrades {
|
||||||
"missing activation height for network upgrade",
|
"missing activation height for network upgrade",
|
||||||
|(network, upgrade)| {
|
|(network, upgrade)| {
|
||||||
upgrade
|
upgrade
|
||||||
.activation_height(network)
|
.activation_height(&network)
|
||||||
.map(|height| (network, height))
|
.map(|height| (network, height))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,7 +31,7 @@ proptest! {
|
||||||
let (runtime, _init_guard) = zebra_test::init_async();
|
let (runtime, _init_guard) = zebra_test::init_async();
|
||||||
|
|
||||||
let (mut minimum_peer_version, best_tip_height) =
|
let (mut minimum_peer_version, best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(network);
|
MinimumPeerVersion::with_mock_chain_tip(&network);
|
||||||
|
|
||||||
best_tip_height.send_best_tip_height(block_height);
|
best_tip_height.send_best_tip_height(block_height);
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ proptest! {
|
||||||
let (runtime, _init_guard) = zebra_test::init_async();
|
let (runtime, _init_guard) = zebra_test::init_async();
|
||||||
|
|
||||||
let (mut minimum_peer_version, best_tip_height) =
|
let (mut minimum_peer_version, best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(block_heights.network);
|
MinimumPeerVersion::with_mock_chain_tip(&block_heights.network);
|
||||||
|
|
||||||
best_tip_height.send_best_tip_height(block_heights.before_upgrade);
|
best_tip_height.send_best_tip_height(block_heights.before_upgrade);
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ proptest! {
|
||||||
// Get peers and handles
|
// Get peers and handles
|
||||||
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Build a peerset
|
// Build a peerset
|
||||||
runtime.block_on(async move {
|
runtime.block_on(async move {
|
||||||
|
@ -193,7 +193,7 @@ proptest! {
|
||||||
// Get peers and handles
|
// Get peers and handles
|
||||||
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
runtime.block_on(async move {
|
runtime.block_on(async move {
|
||||||
// Build a peerset
|
// Build a peerset
|
||||||
|
@ -264,7 +264,7 @@ proptest! {
|
||||||
// Get peers and handles
|
// Get peers and handles
|
||||||
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
runtime.block_on(async move {
|
runtime.block_on(async move {
|
||||||
// Build a peerset
|
// Build a peerset
|
||||||
|
|
|
@ -25,7 +25,7 @@ fn peer_set_ready_single_connection() {
|
||||||
// We are going to use just one peer version in this test
|
// We are going to use just one peer version in this test
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: vec![Version::min_specified_for_upgrade(
|
peer_versions: vec![Version::min_specified_for_upgrade(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
NetworkUpgrade::Nu5,
|
NetworkUpgrade::Nu5,
|
||||||
)],
|
)],
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,7 @@ fn peer_set_ready_single_connection() {
|
||||||
// Get peers and client handles of them
|
// Get peers and client handles of them
|
||||||
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// We will just use the first peer handle
|
// We will just use the first peer handle
|
||||||
let mut client_handle = handles
|
let mut client_handle = handles
|
||||||
|
@ -118,7 +118,7 @@ fn peer_set_ready_single_connection() {
|
||||||
#[test]
|
#[test]
|
||||||
fn peer_set_ready_multiple_connections() {
|
fn peer_set_ready_multiple_connections() {
|
||||||
// Use three peers with the same version
|
// Use three peers with the same version
|
||||||
let peer_version = Version::min_specified_for_upgrade(Network::Mainnet, NetworkUpgrade::Nu5);
|
let peer_version = Version::min_specified_for_upgrade(&Network::Mainnet, NetworkUpgrade::Nu5);
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: vec![peer_version, peer_version, peer_version],
|
peer_versions: vec![peer_version, peer_version, peer_version],
|
||||||
};
|
};
|
||||||
|
@ -136,7 +136,7 @@ fn peer_set_ready_multiple_connections() {
|
||||||
// Get peers and client handles of them
|
// Get peers and client handles of them
|
||||||
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Make sure we have the right number of peers
|
// Make sure we have the right number of peers
|
||||||
assert_eq!(handles.len(), 3);
|
assert_eq!(handles.len(), 3);
|
||||||
|
@ -182,7 +182,7 @@ fn peer_set_rejects_connections_past_per_ip_limit() {
|
||||||
const NUM_PEER_VERSIONS: usize = crate::constants::DEFAULT_MAX_CONNS_PER_IP + 1;
|
const NUM_PEER_VERSIONS: usize = crate::constants::DEFAULT_MAX_CONNS_PER_IP + 1;
|
||||||
|
|
||||||
// Use three peers with the same version
|
// Use three peers with the same version
|
||||||
let peer_version = Version::min_specified_for_upgrade(Network::Mainnet, NetworkUpgrade::Nu5);
|
let peer_version = Version::min_specified_for_upgrade(&Network::Mainnet, NetworkUpgrade::Nu5);
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: [peer_version; NUM_PEER_VERSIONS].into_iter().collect(),
|
peer_versions: [peer_version; NUM_PEER_VERSIONS].into_iter().collect(),
|
||||||
};
|
};
|
||||||
|
@ -200,7 +200,7 @@ fn peer_set_rejects_connections_past_per_ip_limit() {
|
||||||
// Get peers and client handles of them
|
// Get peers and client handles of them
|
||||||
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Make sure we have the right number of peers
|
// Make sure we have the right number of peers
|
||||||
assert_eq!(handles.len(), NUM_PEER_VERSIONS);
|
assert_eq!(handles.len(), NUM_PEER_VERSIONS);
|
||||||
|
@ -232,7 +232,7 @@ fn peer_set_route_inv_empty_registry() {
|
||||||
let test_hash = block::Hash([0; 32]);
|
let test_hash = block::Hash([0; 32]);
|
||||||
|
|
||||||
// Use two peers with the same version
|
// Use two peers with the same version
|
||||||
let peer_version = Version::min_specified_for_upgrade(Network::Mainnet, NetworkUpgrade::Nu5);
|
let peer_version = Version::min_specified_for_upgrade(&Network::Mainnet, NetworkUpgrade::Nu5);
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: vec![peer_version, peer_version],
|
peer_versions: vec![peer_version, peer_version],
|
||||||
};
|
};
|
||||||
|
@ -250,7 +250,7 @@ fn peer_set_route_inv_empty_registry() {
|
||||||
// Get peers and client handles of them
|
// Get peers and client handles of them
|
||||||
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Make sure we have the right number of peers
|
// Make sure we have the right number of peers
|
||||||
assert_eq!(handles.len(), 2);
|
assert_eq!(handles.len(), 2);
|
||||||
|
@ -315,7 +315,7 @@ fn peer_set_route_inv_advertised_registry_order(advertised_first: bool) {
|
||||||
let test_change = InventoryStatus::new_available(test_inv, test_peer);
|
let test_change = InventoryStatus::new_available(test_inv, test_peer);
|
||||||
|
|
||||||
// Use two peers with the same version
|
// Use two peers with the same version
|
||||||
let peer_version = Version::min_specified_for_upgrade(Network::Mainnet, NetworkUpgrade::Nu5);
|
let peer_version = Version::min_specified_for_upgrade(&Network::Mainnet, NetworkUpgrade::Nu5);
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: vec![peer_version, peer_version],
|
peer_versions: vec![peer_version, peer_version],
|
||||||
};
|
};
|
||||||
|
@ -333,7 +333,7 @@ fn peer_set_route_inv_advertised_registry_order(advertised_first: bool) {
|
||||||
// Get peers and client handles of them
|
// Get peers and client handles of them
|
||||||
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Make sure we have the right number of peers
|
// Make sure we have the right number of peers
|
||||||
assert_eq!(handles.len(), 2);
|
assert_eq!(handles.len(), 2);
|
||||||
|
@ -423,7 +423,7 @@ fn peer_set_route_inv_missing_registry_order(missing_first: bool) {
|
||||||
let test_change = InventoryStatus::new_missing(test_inv, test_peer);
|
let test_change = InventoryStatus::new_missing(test_inv, test_peer);
|
||||||
|
|
||||||
// Use two peers with the same version
|
// Use two peers with the same version
|
||||||
let peer_version = Version::min_specified_for_upgrade(Network::Mainnet, NetworkUpgrade::Nu5);
|
let peer_version = Version::min_specified_for_upgrade(&Network::Mainnet, NetworkUpgrade::Nu5);
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: vec![peer_version, peer_version],
|
peer_versions: vec![peer_version, peer_version],
|
||||||
};
|
};
|
||||||
|
@ -441,7 +441,7 @@ fn peer_set_route_inv_missing_registry_order(missing_first: bool) {
|
||||||
// Get peers and client handles of them
|
// Get peers and client handles of them
|
||||||
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Make sure we have the right number of peers
|
// Make sure we have the right number of peers
|
||||||
assert_eq!(handles.len(), 2);
|
assert_eq!(handles.len(), 2);
|
||||||
|
@ -525,7 +525,7 @@ fn peer_set_route_inv_all_missing_fail() {
|
||||||
let test_change = InventoryStatus::new_missing(test_inv, test_peer);
|
let test_change = InventoryStatus::new_missing(test_inv, test_peer);
|
||||||
|
|
||||||
// Use one peer
|
// Use one peer
|
||||||
let peer_version = Version::min_specified_for_upgrade(Network::Mainnet, NetworkUpgrade::Nu5);
|
let peer_version = Version::min_specified_for_upgrade(&Network::Mainnet, NetworkUpgrade::Nu5);
|
||||||
let peer_versions = PeerVersions {
|
let peer_versions = PeerVersions {
|
||||||
peer_versions: vec![peer_version],
|
peer_versions: vec![peer_version],
|
||||||
};
|
};
|
||||||
|
@ -543,7 +543,7 @@ fn peer_set_route_inv_all_missing_fail() {
|
||||||
// Get the peer and its client handle
|
// Get the peer and its client handle
|
||||||
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
let (discovered_peers, mut handles) = peer_versions.mock_peer_discovery();
|
||||||
let (minimum_peer_version, _best_tip_height) =
|
let (minimum_peer_version, _best_tip_height) =
|
||||||
MinimumPeerVersion::with_mock_chain_tip(Network::Mainnet);
|
MinimumPeerVersion::with_mock_chain_tip(&Network::Mainnet);
|
||||||
|
|
||||||
// Make sure we have the right number of peers
|
// Make sure we have the right number of peers
|
||||||
assert_eq!(handles.len(), 1);
|
assert_eq!(handles.len(), 1);
|
||||||
|
|
|
@ -84,8 +84,8 @@ impl Builder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure the codec for the given [`Network`].
|
/// Configure the codec for the given [`Network`].
|
||||||
pub fn for_network(mut self, network: Network) -> Self {
|
pub fn for_network(mut self, network: &Network) -> Self {
|
||||||
self.network = network;
|
self.network = network.clone();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ proptest! {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
// We require sanitization before serialization
|
// We require sanitization before serialization
|
||||||
let addr = addr.sanitize(Mainnet);
|
let addr = addr.sanitize(&Mainnet);
|
||||||
prop_assume!(addr.is_some());
|
prop_assume!(addr.is_some());
|
||||||
|
|
||||||
let addr: AddrV1 = addr.unwrap().into();
|
let addr: AddrV1 = addr.unwrap().into();
|
||||||
|
@ -115,7 +115,7 @@ proptest! {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
// We require sanitization before serialization
|
// We require sanitization before serialization
|
||||||
let addr = addr.sanitize(Mainnet);
|
let addr = addr.sanitize(&Mainnet);
|
||||||
prop_assume!(addr.is_some());
|
prop_assume!(addr.is_some());
|
||||||
|
|
||||||
let addr: AddrV1 = addr.unwrap().into();
|
let addr: AddrV1 = addr.unwrap().into();
|
||||||
|
@ -153,7 +153,7 @@ proptest! {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
// We require sanitization before serialization
|
// We require sanitization before serialization
|
||||||
let addr = addr.sanitize(Mainnet);
|
let addr = addr.sanitize(&Mainnet);
|
||||||
prop_assume!(addr.is_some());
|
prop_assume!(addr.is_some());
|
||||||
|
|
||||||
let addr: AddrV2 = addr.unwrap().into();
|
let addr: AddrV2 = addr.unwrap().into();
|
||||||
|
@ -172,7 +172,7 @@ proptest! {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
// We require sanitization before serialization
|
// We require sanitization before serialization
|
||||||
let addr = addr.sanitize(Mainnet);
|
let addr = addr.sanitize(&Mainnet);
|
||||||
prop_assume!(addr.is_some());
|
prop_assume!(addr.is_some());
|
||||||
|
|
||||||
let addr: AddrV2 = addr.unwrap().into();
|
let addr: AddrV2 = addr.unwrap().into();
|
||||||
|
|
|
@ -111,7 +111,7 @@ proptest! {
|
||||||
|
|
||||||
// We require sanitization before serialization,
|
// We require sanitization before serialization,
|
||||||
// but we also need the original address for this test
|
// but we also need the original address for this test
|
||||||
let sanitized_addr = addr.sanitize(Mainnet);
|
let sanitized_addr = addr.sanitize(&Mainnet);
|
||||||
prop_assume!(sanitized_addr.is_some());
|
prop_assume!(sanitized_addr.is_some());
|
||||||
let sanitized_addr = sanitized_addr.unwrap();
|
let sanitized_addr = sanitized_addr.unwrap();
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ proptest! {
|
||||||
|
|
||||||
// We require sanitization before serialization,
|
// We require sanitization before serialization,
|
||||||
// but we also need the original address for this test
|
// but we also need the original address for this test
|
||||||
let sanitized_addr = addr.sanitize(Mainnet);
|
let sanitized_addr = addr.sanitize(&Mainnet);
|
||||||
prop_assume!(sanitized_addr.is_some());
|
prop_assume!(sanitized_addr.is_some());
|
||||||
let sanitized_addr = sanitized_addr.unwrap();
|
let sanitized_addr = sanitized_addr.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ impl Version {
|
||||||
///
|
///
|
||||||
/// If we are incompatible with our own minimum remote protocol version.
|
/// If we are incompatible with our own minimum remote protocol version.
|
||||||
pub fn min_remote_for_height(
|
pub fn min_remote_for_height(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: impl Into<Option<block::Height>>,
|
height: impl Into<Option<block::Height>>,
|
||||||
) -> Version {
|
) -> Version {
|
||||||
let height = height.into().unwrap_or(block::Height(0));
|
let height = height.into().unwrap_or(block::Height(0));
|
||||||
|
@ -78,9 +78,9 @@ impl Version {
|
||||||
/// - during the initial block download,
|
/// - during the initial block download,
|
||||||
/// - after Zebra restarts, and
|
/// - after Zebra restarts, and
|
||||||
/// - after Zebra's local network is slow or shut down.
|
/// - after Zebra's local network is slow or shut down.
|
||||||
fn initial_min_for_network(network: Network) -> Version {
|
fn initial_min_for_network(network: &Network) -> Version {
|
||||||
*constants::INITIAL_MIN_NETWORK_PROTOCOL_VERSION
|
*constants::INITIAL_MIN_NETWORK_PROTOCOL_VERSION
|
||||||
.get(&network)
|
.get(network)
|
||||||
.expect("We always have a value for testnet or mainnet")
|
.expect("We always have a value for testnet or mainnet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ impl Version {
|
||||||
/// `height`.
|
/// `height`.
|
||||||
///
|
///
|
||||||
/// This is the minimum peer version when Zebra is close to the current tip.
|
/// This is the minimum peer version when Zebra is close to the current tip.
|
||||||
fn min_specified_for_height(network: Network, height: block::Height) -> Version {
|
fn min_specified_for_height(network: &Network, height: block::Height) -> Version {
|
||||||
let network_upgrade = NetworkUpgrade::current(network, height);
|
let network_upgrade = NetworkUpgrade::current(network, height);
|
||||||
Version::min_specified_for_upgrade(network, network_upgrade)
|
Version::min_specified_for_upgrade(network, network_upgrade)
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ impl Version {
|
||||||
/// Returns the minimum specified network protocol version for `network` and
|
/// Returns the minimum specified network protocol version for `network` and
|
||||||
/// `network_upgrade`.
|
/// `network_upgrade`.
|
||||||
pub(crate) fn min_specified_for_upgrade(
|
pub(crate) fn min_specified_for_upgrade(
|
||||||
network: Network,
|
network: &Network,
|
||||||
network_upgrade: NetworkUpgrade,
|
network_upgrade: NetworkUpgrade,
|
||||||
) -> Version {
|
) -> Version {
|
||||||
// TODO: Should we reject earlier protocol versions during our initial
|
// TODO: Should we reject earlier protocol versions during our initial
|
||||||
|
@ -196,17 +196,17 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn version_extremes_mainnet() {
|
fn version_extremes_mainnet() {
|
||||||
version_extremes(Mainnet)
|
version_extremes(&Mainnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn version_extremes_testnet() {
|
fn version_extremes_testnet() {
|
||||||
version_extremes(Testnet)
|
version_extremes(&Testnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test the min_specified_for_upgrade and min_specified_for_height functions for `network` with
|
/// Test the min_specified_for_upgrade and min_specified_for_height functions for `network` with
|
||||||
/// extreme values.
|
/// extreme values.
|
||||||
fn version_extremes(network: Network) {
|
fn version_extremes(network: &Network) {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -224,17 +224,17 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn version_consistent_mainnet() {
|
fn version_consistent_mainnet() {
|
||||||
version_consistent(Mainnet)
|
version_consistent(&Mainnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn version_consistent_testnet() {
|
fn version_consistent_testnet() {
|
||||||
version_consistent(Testnet)
|
version_consistent(&Testnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the min_specified_for_upgrade and min_specified_for_height functions
|
/// Check that the min_specified_for_upgrade and min_specified_for_height functions
|
||||||
/// are consistent for `network`.
|
/// are consistent for `network`.
|
||||||
fn version_consistent(network: Network) {
|
fn version_consistent(network: &Network) {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
let highest_network_upgrade = NetworkUpgrade::current(network, block::Height::MAX);
|
let highest_network_upgrade = NetworkUpgrade::current(network, block::Height::MAX);
|
||||||
|
|
|
@ -437,7 +437,7 @@ where
|
||||||
let rpc_impl = RpcImpl {
|
let rpc_impl = RpcImpl {
|
||||||
build_version,
|
build_version,
|
||||||
user_agent,
|
user_agent,
|
||||||
network,
|
network: network.clone(),
|
||||||
debug_force_finished_sync,
|
debug_force_finished_sync,
|
||||||
debug_like_zcashd,
|
debug_like_zcashd,
|
||||||
mempool: mempool.clone(),
|
mempool: mempool.clone(),
|
||||||
|
@ -491,7 +491,7 @@ where
|
||||||
// TODO: use a generic error constructor (#5548)
|
// TODO: use a generic error constructor (#5548)
|
||||||
#[allow(clippy::unwrap_in_result)]
|
#[allow(clippy::unwrap_in_result)]
|
||||||
fn get_blockchain_info(&self) -> Result<GetBlockChainInfo> {
|
fn get_blockchain_info(&self) -> Result<GetBlockChainInfo> {
|
||||||
let network = self.network;
|
let network = &self.network;
|
||||||
|
|
||||||
// `chain` field
|
// `chain` field
|
||||||
let chain = self.network.bip70_network_name();
|
let chain = self.network.bip70_network_name();
|
||||||
|
@ -1113,7 +1113,6 @@ where
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Fetch the block referenced by [`hash_or_height`] from the state.
|
// Fetch the block referenced by [`hash_or_height`] from the state.
|
||||||
|
|
||||||
// TODO: If this RPC is called a lot, just get the block header,
|
// TODO: If this RPC is called a lot, just get the block header,
|
||||||
// rather than the whole block.
|
// rather than the whole block.
|
||||||
let block_request = zebra_state::ReadRequest::Block(hash_or_height);
|
let block_request = zebra_state::ReadRequest::Block(hash_or_height);
|
||||||
|
|
|
@ -438,7 +438,7 @@ where
|
||||||
/// If the `mining_config` is invalid.
|
/// If the `mining_config` is invalid.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
network: Network,
|
network: &Network,
|
||||||
mining_config: crate::config::mining::Config,
|
mining_config: crate::config::mining::Config,
|
||||||
mempool: Mempool,
|
mempool: Mempool,
|
||||||
state: State,
|
state: State,
|
||||||
|
@ -448,10 +448,10 @@ where
|
||||||
address_book: AddressBook,
|
address_book: AddressBook,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Prevent loss of miner funds due to an unsupported or incorrect address type.
|
// Prevent loss of miner funds due to an unsupported or incorrect address type.
|
||||||
if let Some(miner_address) = mining_config.miner_address {
|
if let Some(miner_address) = mining_config.miner_address.clone() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
miner_address.network(),
|
miner_address.network(),
|
||||||
network,
|
network.clone(),
|
||||||
"incorrect miner address config: {miner_address} \
|
"incorrect miner address config: {miner_address} \
|
||||||
network.network {network} and miner address network {} must match",
|
network.network {network} and miner address network {} must match",
|
||||||
miner_address.network(),
|
miner_address.network(),
|
||||||
|
@ -486,7 +486,7 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
network,
|
network: network.clone(),
|
||||||
miner_address: mining_config.miner_address,
|
miner_address: mining_config.miner_address,
|
||||||
extra_coinbase_data,
|
extra_coinbase_data,
|
||||||
debug_like_zcashd,
|
debug_like_zcashd,
|
||||||
|
@ -576,8 +576,8 @@ where
|
||||||
parameters: Option<get_block_template::JsonParameters>,
|
parameters: Option<get_block_template::JsonParameters>,
|
||||||
) -> BoxFuture<Result<get_block_template::Response>> {
|
) -> BoxFuture<Result<get_block_template::Response>> {
|
||||||
// Clone Configs
|
// Clone Configs
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
let miner_address = self.miner_address;
|
let miner_address = self.miner_address.clone();
|
||||||
let debug_like_zcashd = self.debug_like_zcashd;
|
let debug_like_zcashd = self.debug_like_zcashd;
|
||||||
let extra_coinbase_data = self.extra_coinbase_data.clone();
|
let extra_coinbase_data = self.extra_coinbase_data.clone();
|
||||||
|
|
||||||
|
@ -626,7 +626,7 @@ where
|
||||||
//
|
//
|
||||||
// Optional TODO:
|
// Optional TODO:
|
||||||
// - add `async changed()` method to ChainSyncStatus (like `ChainTip`)
|
// - add `async changed()` method to ChainSyncStatus (like `ChainTip`)
|
||||||
check_synced_to_tip(network, latest_chain_tip.clone(), sync_status.clone())?;
|
check_synced_to_tip(&network, latest_chain_tip.clone(), sync_status.clone())?;
|
||||||
|
|
||||||
// TODO: return an error if we have no peers, like `zcashd` does,
|
// TODO: return an error if we have no peers, like `zcashd` does,
|
||||||
// and add a developer config that mines regardless of how many peers we have.
|
// and add a developer config that mines regardless of how many peers we have.
|
||||||
|
@ -861,9 +861,9 @@ where
|
||||||
|
|
||||||
// Randomly select some mempool transactions.
|
// Randomly select some mempool transactions.
|
||||||
let mempool_txs = zip317::select_mempool_transactions(
|
let mempool_txs = zip317::select_mempool_transactions(
|
||||||
network,
|
&network,
|
||||||
next_block_height,
|
next_block_height,
|
||||||
miner_address,
|
&miner_address,
|
||||||
mempool_txs,
|
mempool_txs,
|
||||||
debug_like_zcashd,
|
debug_like_zcashd,
|
||||||
extra_coinbase_data.clone(),
|
extra_coinbase_data.clone(),
|
||||||
|
@ -881,8 +881,8 @@ where
|
||||||
// - After this point, the template only depends on the previously fetched data.
|
// - After this point, the template only depends on the previously fetched data.
|
||||||
|
|
||||||
let response = GetBlockTemplate::new(
|
let response = GetBlockTemplate::new(
|
||||||
network,
|
&network,
|
||||||
miner_address,
|
&miner_address,
|
||||||
&chain_tip_and_local_time,
|
&chain_tip_and_local_time,
|
||||||
server_long_poll_id,
|
server_long_poll_id,
|
||||||
mempool_txs,
|
mempool_txs,
|
||||||
|
@ -988,7 +988,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mining_info(&self) -> BoxFuture<Result<get_mining_info::Response>> {
|
fn get_mining_info(&self) -> BoxFuture<Result<get_mining_info::Response>> {
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
let solution_rate_fut = self.get_network_sol_ps(None, None);
|
let solution_rate_fut = self.get_network_sol_ps(None, None);
|
||||||
async move {
|
async move {
|
||||||
Ok(get_mining_info::Response::new(
|
Ok(get_mining_info::Response::new(
|
||||||
|
@ -1062,7 +1062,7 @@ where
|
||||||
&self,
|
&self,
|
||||||
raw_address: String,
|
raw_address: String,
|
||||||
) -> BoxFuture<Result<validate_address::Response>> {
|
) -> BoxFuture<Result<validate_address::Response>> {
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let Ok(address) = raw_address
|
let Ok(address) = raw_address
|
||||||
|
@ -1107,7 +1107,7 @@ where
|
||||||
&self,
|
&self,
|
||||||
raw_address: String,
|
raw_address: String,
|
||||||
) -> BoxFuture<Result<types::z_validate_address::Response>> {
|
) -> BoxFuture<Result<types::z_validate_address::Response>> {
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let Ok(address) = raw_address
|
let Ok(address) = raw_address
|
||||||
|
@ -1148,7 +1148,7 @@ where
|
||||||
|
|
||||||
fn get_block_subsidy(&self, height: Option<u32>) -> BoxFuture<Result<BlockSubsidy>> {
|
fn get_block_subsidy(&self, height: Option<u32>) -> BoxFuture<Result<BlockSubsidy>> {
|
||||||
let latest_chain_tip = self.latest_chain_tip.clone();
|
let latest_chain_tip = self.latest_chain_tip.clone();
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let height = if let Some(height) = height {
|
let height = if let Some(height) = height {
|
||||||
|
@ -1167,7 +1167,7 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let miner = miner_subsidy(height, network).map_err(|error| Error {
|
let miner = miner_subsidy(height, &network).map_err(|error| Error {
|
||||||
code: ErrorCode::ServerError(0),
|
code: ErrorCode::ServerError(0),
|
||||||
message: error.to_string(),
|
message: error.to_string(),
|
||||||
data: None,
|
data: None,
|
||||||
|
@ -1176,7 +1176,7 @@ where
|
||||||
let founders = Amount::zero();
|
let founders = Amount::zero();
|
||||||
|
|
||||||
let funding_streams =
|
let funding_streams =
|
||||||
funding_stream_values(height, network).map_err(|error| Error {
|
funding_stream_values(height, &network).map_err(|error| Error {
|
||||||
code: ErrorCode::ServerError(0),
|
code: ErrorCode::ServerError(0),
|
||||||
message: error.to_string(),
|
message: error.to_string(),
|
||||||
data: None,
|
data: None,
|
||||||
|
@ -1184,7 +1184,7 @@ where
|
||||||
let mut funding_streams: Vec<_> = funding_streams
|
let mut funding_streams: Vec<_> = funding_streams
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(receiver, value)| {
|
.map(|(receiver, value)| {
|
||||||
let address = funding_stream_address(height, network, *receiver);
|
let address = funding_stream_address(height, &network, *receiver);
|
||||||
(*receiver, FundingStream::new(*receiver, *value, address))
|
(*receiver, FundingStream::new(*receiver, *value, address))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1208,7 +1208,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_difficulty(&self) -> BoxFuture<Result<f64>> {
|
fn get_difficulty(&self) -> BoxFuture<Result<f64>> {
|
||||||
let network = self.network;
|
let network = self.network.clone();
|
||||||
let mut state = self.state.clone();
|
let mut state = self.state.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
|
|
|
@ -113,7 +113,7 @@ where
|
||||||
Tip: ChainTip + Clone + Send + Sync + 'static,
|
Tip: ChainTip + Clone + Send + Sync + 'static,
|
||||||
SyncStatus: ChainSyncStatus + Clone + Send + Sync + 'static,
|
SyncStatus: ChainSyncStatus + Clone + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
check_synced_to_tip(network, latest_chain_tip, sync_status)?;
|
check_synced_to_tip(&network, latest_chain_tip, sync_status)?;
|
||||||
|
|
||||||
let block: Block = match block_proposal_bytes.zcash_deserialize_into() {
|
let block: Block = match block_proposal_bytes.zcash_deserialize_into() {
|
||||||
Ok(block) => block,
|
Ok(block) => block,
|
||||||
|
@ -158,7 +158,7 @@ where
|
||||||
/// Returns an error if Zebra is not synced to the consensus chain tip.
|
/// Returns an error if Zebra is not synced to the consensus chain tip.
|
||||||
/// This error might be incorrect if the local clock is skewed.
|
/// This error might be incorrect if the local clock is skewed.
|
||||||
pub fn check_synced_to_tip<Tip, SyncStatus>(
|
pub fn check_synced_to_tip<Tip, SyncStatus>(
|
||||||
network: Network,
|
network: &Network,
|
||||||
latest_chain_tip: Tip,
|
latest_chain_tip: Tip,
|
||||||
sync_status: SyncStatus,
|
sync_status: SyncStatus,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
|
@ -283,9 +283,9 @@ where
|
||||||
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
pub fn generate_coinbase_and_roots(
|
pub fn generate_coinbase_and_roots(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
mempool_txs: &[VerifiedUnminedTx],
|
mempool_txs: &[VerifiedUnminedTx],
|
||||||
history_tree: Arc<zebra_chain::history_tree::HistoryTree>,
|
history_tree: Arc<zebra_chain::history_tree::HistoryTree>,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
|
@ -319,9 +319,9 @@ pub fn generate_coinbase_and_roots(
|
||||||
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
pub fn generate_coinbase_transaction(
|
pub fn generate_coinbase_transaction(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
miner_fee: Amount<NonNegative>,
|
miner_fee: Amount<NonNegative>,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
extra_coinbase_data: Vec<u8>,
|
extra_coinbase_data: Vec<u8>,
|
||||||
|
@ -355,9 +355,9 @@ pub fn calculate_miner_fee(mempool_txs: &[VerifiedUnminedTx]) -> Amount<NonNegat
|
||||||
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
pub fn standard_coinbase_outputs(
|
pub fn standard_coinbase_outputs(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
miner_fee: Amount<NonNegative>,
|
miner_fee: Amount<NonNegative>,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
) -> Vec<(Amount<NonNegative>, transparent::Script)> {
|
) -> Vec<(Amount<NonNegative>, transparent::Script)> {
|
||||||
|
@ -393,7 +393,7 @@ pub fn standard_coinbase_outputs(
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
fn combine_coinbase_outputs(
|
fn combine_coinbase_outputs(
|
||||||
funding_streams: HashMap<FundingStreamReceiver, (Amount<NonNegative>, transparent::Address)>,
|
funding_streams: HashMap<FundingStreamReceiver, (Amount<NonNegative>, transparent::Address)>,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
miner_reward: Amount<NonNegative>,
|
miner_reward: Amount<NonNegative>,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
) -> Vec<(Amount<NonNegative>, transparent::Script)> {
|
) -> Vec<(Amount<NonNegative>, transparent::Script)> {
|
||||||
|
@ -402,7 +402,7 @@ fn combine_coinbase_outputs(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_receiver, (amount, address))| (amount, address))
|
.map(|(_receiver, (amount, address))| (amount, address))
|
||||||
.collect();
|
.collect();
|
||||||
coinbase_outputs.push((miner_reward, miner_address));
|
coinbase_outputs.push((miner_reward, miner_address.clone()));
|
||||||
|
|
||||||
let mut coinbase_outputs: Vec<(Amount<NonNegative>, transparent::Script)> = coinbase_outputs
|
let mut coinbase_outputs: Vec<(Amount<NonNegative>, transparent::Script)> = coinbase_outputs
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -223,8 +223,8 @@ impl GetBlockTemplate {
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
network: Network,
|
network: &Network,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
chain_tip_and_local_time: &GetBlockTemplateChainInfo,
|
chain_tip_and_local_time: &GetBlockTemplateChainInfo,
|
||||||
long_poll_id: LongPollId,
|
long_poll_id: LongPollId,
|
||||||
mempool_txs: Vec<VerifiedUnminedTx>,
|
mempool_txs: Vec<VerifiedUnminedTx>,
|
||||||
|
|
|
@ -37,9 +37,9 @@ use crate::methods::get_block_template_rpcs::{
|
||||||
///
|
///
|
||||||
/// [ZIP-317]: https://zips.z.cash/zip-0317#block-production
|
/// [ZIP-317]: https://zips.z.cash/zip-0317#block-production
|
||||||
pub async fn select_mempool_transactions(
|
pub async fn select_mempool_transactions(
|
||||||
network: Network,
|
network: &Network,
|
||||||
next_block_height: Height,
|
next_block_height: Height,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
mempool_txs: Vec<VerifiedUnminedTx>,
|
mempool_txs: Vec<VerifiedUnminedTx>,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
extra_coinbase_data: Vec<u8>,
|
extra_coinbase_data: Vec<u8>,
|
||||||
|
@ -115,9 +115,9 @@ pub async fn select_mempool_transactions(
|
||||||
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
|
||||||
/// in the `getblocktemplate` RPC.
|
/// in the `getblocktemplate` RPC.
|
||||||
pub fn fake_coinbase_transaction(
|
pub fn fake_coinbase_transaction(
|
||||||
network: Network,
|
network: &Network,
|
||||||
height: Height,
|
height: Height,
|
||||||
miner_address: transparent::Address,
|
miner_address: &transparent::Address,
|
||||||
like_zcashd: bool,
|
like_zcashd: bool,
|
||||||
extra_coinbase_data: Vec<u8>,
|
extra_coinbase_data: Vec<u8>,
|
||||||
) -> TransactionTemplate<NegativeOrZero> {
|
) -> TransactionTemplate<NegativeOrZero> {
|
||||||
|
|
|
@ -596,7 +596,7 @@ proptest! {
|
||||||
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
"RPC test",
|
"RPC test",
|
||||||
"RPC test",
|
"RPC test",
|
||||||
network,
|
network.clone(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
mempool.clone(),
|
mempool.clone(),
|
||||||
|
@ -615,13 +615,13 @@ proptest! {
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
info.consensus.chain_tip.0,
|
info.consensus.chain_tip.0,
|
||||||
NetworkUpgrade::current(network, block_height)
|
NetworkUpgrade::current(&network, block_height)
|
||||||
.branch_id()
|
.branch_id()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
info.consensus.next_block.0,
|
info.consensus.next_block.0,
|
||||||
NetworkUpgrade::current(network, (block_height + 1).unwrap())
|
NetworkUpgrade::current(&network, (block_height + 1).unwrap())
|
||||||
.branch_id()
|
.branch_id()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,14 +35,14 @@ async fn test_rpc_response_data() {
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
tokio::join!(
|
tokio::join!(
|
||||||
test_rpc_response_data_for_network(Mainnet),
|
test_rpc_response_data_for_network(&Mainnet),
|
||||||
test_rpc_response_data_for_network(Testnet),
|
test_rpc_response_data_for_network(&Testnet),
|
||||||
test_mocked_rpc_response_data_for_network(Mainnet),
|
test_mocked_rpc_response_data_for_network(&Mainnet),
|
||||||
test_mocked_rpc_response_data_for_network(Testnet),
|
test_mocked_rpc_response_data_for_network(&Testnet),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn test_rpc_response_data_for_network(network: Network) {
|
async fn test_rpc_response_data_for_network(network: &Network) {
|
||||||
// Create a continuous chain of mainnet and testnet blocks from genesis
|
// Create a continuous chain of mainnet and testnet blocks from genesis
|
||||||
let block_data = network.blockchain_map();
|
let block_data = network.blockchain_map();
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ async fn test_rpc_response_data_for_network(network: Network) {
|
||||||
let (rpc, _rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc, _rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
"RPC test",
|
"RPC test",
|
||||||
"/Zebra:RPC test/",
|
"/Zebra:RPC test/",
|
||||||
network,
|
network.clone(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
|
@ -320,7 +320,7 @@ async fn test_rpc_response_data_for_network(network: Network) {
|
||||||
snapshot_rpc_getaddressutxos(get_address_utxos, &settings);
|
snapshot_rpc_getaddressutxos(get_address_utxos, &settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn test_mocked_rpc_response_data_for_network(network: Network) {
|
async fn test_mocked_rpc_response_data_for_network(network: &Network) {
|
||||||
// Prepare the test harness.
|
// Prepare the test harness.
|
||||||
|
|
||||||
let mut settings = insta::Settings::clone_current();
|
let mut settings = insta::Settings::clone_current();
|
||||||
|
@ -333,7 +333,7 @@ async fn test_mocked_rpc_response_data_for_network(network: Network) {
|
||||||
let (rpc, _) = RpcImpl::new(
|
let (rpc, _) = RpcImpl::new(
|
||||||
"RPC test",
|
"RPC test",
|
||||||
"/Zebra:RPC test/",
|
"/Zebra:RPC test/",
|
||||||
network,
|
network.clone(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
mempool,
|
mempool,
|
||||||
|
@ -542,7 +542,7 @@ fn snapshot_rpc_getaddressutxos(utxos: Vec<GetAddressUtxos>, settings: &insta::S
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utility function to convert a `Network` to a lowercase string.
|
/// Utility function to convert a `Network` to a lowercase string.
|
||||||
fn network_string(network: Network) -> String {
|
fn network_string(network: &Network) -> String {
|
||||||
let mut net_suffix = network.to_string();
|
let mut net_suffix = network.to_string();
|
||||||
net_suffix.make_ascii_lowercase();
|
net_suffix.make_ascii_lowercase();
|
||||||
net_suffix
|
net_suffix
|
||||||
|
|
|
@ -51,7 +51,7 @@ use crate::methods::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn test_responses<State, ReadState>(
|
pub async fn test_responses<State, ReadState>(
|
||||||
network: Network,
|
network: &Network,
|
||||||
mempool: MockService<
|
mempool: MockService<
|
||||||
mempool::Request,
|
mempool::Request,
|
||||||
mempool::Response,
|
mempool::Response,
|
||||||
|
|
|
@ -10,14 +10,14 @@ use zebra_chain::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create a history tree with one single block for a network by using Zebra test vectors.
|
/// Create a history tree with one single block for a network by using Zebra test vectors.
|
||||||
pub fn fake_history_tree(network: Network) -> Arc<HistoryTree> {
|
pub fn fake_history_tree(network: &Network) -> Arc<HistoryTree> {
|
||||||
let (block, sapling_root) = network.test_block_sapling_roots(1046400, 1116000).unwrap();
|
let (block, sapling_root) = network.test_block_sapling_roots(1046400, 1116000).unwrap();
|
||||||
|
|
||||||
let block = Arc::<Block>::zcash_deserialize(block).expect("block should deserialize");
|
let block = Arc::<Block>::zcash_deserialize(block).expect("block should deserialize");
|
||||||
let first_sapling_root = Root::try_from(sapling_root).unwrap();
|
let first_sapling_root = Root::try_from(sapling_root).unwrap();
|
||||||
|
|
||||||
let history_tree = NonEmptyHistoryTree::from_block(
|
let history_tree = NonEmptyHistoryTree::from_block(
|
||||||
Network::Mainnet,
|
&Network::Mainnet,
|
||||||
block,
|
block,
|
||||||
&first_sapling_root,
|
&first_sapling_root,
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
|
|
|
@ -70,7 +70,7 @@ async fn rpc_getblock() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
|
@ -343,7 +343,7 @@ async fn rpc_getbestblockhash() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service, the tip will be in `NUMBER_OF_BLOCKS`.
|
// Create a populated state service, the tip will be in `NUMBER_OF_BLOCKS`.
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
|
@ -386,7 +386,7 @@ async fn rpc_getrawtransaction() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, _latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, _latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
let (latest_chain_tip, latest_chain_tip_sender) = MockChainTip::new();
|
let (latest_chain_tip, latest_chain_tip_sender) = MockChainTip::new();
|
||||||
latest_chain_tip_sender.send_best_tip_height(Height(10));
|
latest_chain_tip_sender.send_best_tip_height(Height(10));
|
||||||
|
@ -557,7 +557,7 @@ async fn rpc_getaddresstxids_invalid_arguments() {
|
||||||
|
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
"RPC test",
|
"RPC test",
|
||||||
|
@ -669,12 +669,12 @@ async fn rpc_getaddresstxids_response() {
|
||||||
|
|
||||||
// Get the address.
|
// Get the address.
|
||||||
let address = first_block_first_transaction.outputs()[1]
|
let address = first_block_first_transaction.outputs()[1]
|
||||||
.address(network)
|
.address(&network)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.to_owned(), network).await;
|
zebra_state::populated_state(blocks.to_owned(), &network).await;
|
||||||
|
|
||||||
if network == Mainnet {
|
if network == Mainnet {
|
||||||
// Exhaustively test possible block ranges for mainnet.
|
// Exhaustively test possible block ranges for mainnet.
|
||||||
|
@ -683,7 +683,7 @@ async fn rpc_getaddresstxids_response() {
|
||||||
for start in 1..=10 {
|
for start in 1..=10 {
|
||||||
for end in start..=10 {
|
for end in start..=10 {
|
||||||
rpc_getaddresstxids_response_with(
|
rpc_getaddresstxids_response_with(
|
||||||
network,
|
&network,
|
||||||
start..=end,
|
start..=end,
|
||||||
&address,
|
&address,
|
||||||
&read_state,
|
&read_state,
|
||||||
|
@ -695,7 +695,7 @@ async fn rpc_getaddresstxids_response() {
|
||||||
} else {
|
} else {
|
||||||
// Just test the full range for testnet.
|
// Just test the full range for testnet.
|
||||||
rpc_getaddresstxids_response_with(
|
rpc_getaddresstxids_response_with(
|
||||||
network,
|
&network,
|
||||||
1..=10,
|
1..=10,
|
||||||
&address,
|
&address,
|
||||||
&read_state,
|
&read_state,
|
||||||
|
@ -707,7 +707,7 @@ async fn rpc_getaddresstxids_response() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn rpc_getaddresstxids_response_with(
|
async fn rpc_getaddresstxids_response_with(
|
||||||
network: Network,
|
network: &Network,
|
||||||
range: RangeInclusive<u32>,
|
range: RangeInclusive<u32>,
|
||||||
address: &transparent::Address,
|
address: &transparent::Address,
|
||||||
read_state: &ReadStateService,
|
read_state: &ReadStateService,
|
||||||
|
@ -718,7 +718,7 @@ async fn rpc_getaddresstxids_response_with(
|
||||||
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
"RPC test",
|
"RPC test",
|
||||||
"RPC test",
|
"RPC test",
|
||||||
network,
|
network.clone(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
|
@ -808,13 +808,13 @@ async fn rpc_getaddressutxos_response() {
|
||||||
let first_block_first_transaction = &blocks[1].transactions[0];
|
let first_block_first_transaction = &blocks[1].transactions[0];
|
||||||
// get the address, this is always `t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd`
|
// get the address, this is always `t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd`
|
||||||
let address = &first_block_first_transaction.outputs()[1]
|
let address = &first_block_first_transaction.outputs()[1]
|
||||||
.address(Mainnet)
|
.address(&Mainnet)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
let rpc = RpcImpl::new(
|
let rpc = RpcImpl::new(
|
||||||
"RPC test",
|
"RPC test",
|
||||||
|
@ -864,19 +864,19 @@ async fn rpc_getblockcount() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service, the tip will be in `NUMBER_OF_BLOCKS`.
|
// Create a populated state service, the tip will be in `NUMBER_OF_BLOCKS`.
|
||||||
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
let (
|
let (
|
||||||
block_verifier_router,
|
block_verifier_router,
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_parameter_download_task_handle,
|
_parameter_download_task_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = zebra_consensus::router::init(zebra_consensus::Config::default(), Mainnet, state.clone())
|
) = zebra_consensus::router::init(zebra_consensus::Config::default(), &Mainnet, state.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -909,19 +909,19 @@ async fn rpc_getblockcount_empty_state() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create an empty state
|
// Create an empty state
|
||||||
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::init_test_services(Mainnet);
|
zebra_state::init_test_services(&Mainnet);
|
||||||
|
|
||||||
let (
|
let (
|
||||||
block_verifier_router,
|
block_verifier_router,
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_parameter_download_task_handle,
|
_parameter_download_task_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = zebra_consensus::router::init(zebra_consensus::Config::default(), Mainnet, state.clone())
|
) = zebra_consensus::router::init(zebra_consensus::Config::default(), &Mainnet, state.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -956,14 +956,14 @@ async fn rpc_getpeerinfo() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create an empty state
|
// Create an empty state
|
||||||
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::init_test_services(Mainnet);
|
zebra_state::init_test_services(&Mainnet);
|
||||||
|
|
||||||
let (
|
let (
|
||||||
block_verifier_router,
|
block_verifier_router,
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_parameter_download_task_handle,
|
_parameter_download_task_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = zebra_consensus::router::init(zebra_consensus::Config::default(), network, state.clone())
|
) = zebra_consensus::router::init(zebra_consensus::Config::default(), &network, state.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mock_peer_address = zebra_network::types::MetaAddr::new_initial_peer(
|
let mock_peer_address = zebra_network::types::MetaAddr::new_initial_peer(
|
||||||
|
@ -982,7 +982,7 @@ async fn rpc_getpeerinfo() {
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
network,
|
&network,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -1026,19 +1026,19 @@ async fn rpc_getblockhash() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
let (
|
let (
|
||||||
block_verifier_router,
|
block_verifier_router,
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_parameter_download_task_handle,
|
_parameter_download_task_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = zebra_consensus::router::init(zebra_consensus::Config::default(), Mainnet, state.clone())
|
) = zebra_consensus::router::init(zebra_consensus::Config::default(), &Mainnet, state.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -1090,11 +1090,11 @@ async fn rpc_getmininginfo() {
|
||||||
|
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -1126,11 +1126,11 @@ async fn rpc_getnetworksolps() {
|
||||||
|
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks.clone(), Mainnet).await;
|
zebra_state::populated_state(blocks.clone(), &Mainnet).await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -1224,8 +1224,10 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
|
||||||
mock_sync_status.set_is_close_to_tip(true);
|
mock_sync_status.set_is_close_to_tip(true);
|
||||||
|
|
||||||
let miner_address = match use_p2pkh {
|
let miner_address = match use_p2pkh {
|
||||||
false => Some(transparent::Address::from_script_hash(Mainnet, [0x7e; 20])),
|
false => Some(transparent::Address::from_script_hash(&Mainnet, [0x7e; 20])),
|
||||||
true => Some(transparent::Address::from_pub_key_hash(Mainnet, [0x7e; 20])),
|
true => Some(transparent::Address::from_pub_key_hash(
|
||||||
|
&Mainnet, [0x7e; 20],
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(clippy::unnecessary_struct_initialization)]
|
#[allow(clippy::unnecessary_struct_initialization)]
|
||||||
|
@ -1238,7 +1240,7 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// nu5 block height
|
// nu5 block height
|
||||||
let fake_tip_height = NetworkUpgrade::Nu5.activation_height(Mainnet).unwrap();
|
let fake_tip_height = NetworkUpgrade::Nu5.activation_height(&Mainnet).unwrap();
|
||||||
// nu5 block hash
|
// nu5 block hash
|
||||||
let fake_tip_hash =
|
let fake_tip_hash =
|
||||||
Hash::from_hex("0000000000d723156d9b65ffcf4984da7a19675ed7e2f06d9e5d5188af087bf8").unwrap();
|
Hash::from_hex("0000000000d723156d9b65ffcf4984da7a19675ed7e2f06d9e5d5188af087bf8").unwrap();
|
||||||
|
@ -1257,7 +1259,7 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
mining_config,
|
mining_config,
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state.clone(),
|
read_state.clone(),
|
||||||
|
@ -1282,7 +1284,7 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
|
||||||
cur_time: fake_cur_time,
|
cur_time: fake_cur_time,
|
||||||
min_time: fake_min_time,
|
min_time: fake_min_time,
|
||||||
max_time: fake_max_time,
|
max_time: fake_max_time,
|
||||||
history_tree: fake_history_tree(Mainnet),
|
history_tree: fake_history_tree(&Mainnet),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1508,7 +1510,7 @@ async fn rpc_submitblock_errors() {
|
||||||
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||||
// Create a populated state service
|
// Create a populated state service
|
||||||
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
let (state, read_state, latest_chain_tip, _chain_tip_change) =
|
||||||
zebra_state::populated_state(blocks, Mainnet).await;
|
zebra_state::populated_state(blocks, &Mainnet).await;
|
||||||
|
|
||||||
// Init RPCs
|
// Init RPCs
|
||||||
let (
|
let (
|
||||||
|
@ -1516,12 +1518,12 @@ async fn rpc_submitblock_errors() {
|
||||||
_transaction_verifier,
|
_transaction_verifier,
|
||||||
_parameter_download_task_handle,
|
_parameter_download_task_handle,
|
||||||
_max_checkpoint_height,
|
_max_checkpoint_height,
|
||||||
) = zebra_consensus::router::init(zebra_consensus::Config::default(), Mainnet, state.clone())
|
) = zebra_consensus::router::init(zebra_consensus::Config::default(), &Mainnet, state.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state,
|
read_state,
|
||||||
|
@ -1573,7 +1575,7 @@ async fn rpc_validateaddress() {
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
|
@ -1618,7 +1620,7 @@ async fn rpc_z_validateaddress() {
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
|
@ -1687,7 +1689,7 @@ async fn rpc_getdifficulty() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// nu5 block height
|
// nu5 block height
|
||||||
let fake_tip_height = NetworkUpgrade::Nu5.activation_height(Mainnet).unwrap();
|
let fake_tip_height = NetworkUpgrade::Nu5.activation_height(&Mainnet).unwrap();
|
||||||
// nu5 block hash
|
// nu5 block hash
|
||||||
let fake_tip_hash =
|
let fake_tip_hash =
|
||||||
Hash::from_hex("0000000000d723156d9b65ffcf4984da7a19675ed7e2f06d9e5d5188af087bf8").unwrap();
|
Hash::from_hex("0000000000d723156d9b65ffcf4984da7a19675ed7e2f06d9e5d5188af087bf8").unwrap();
|
||||||
|
@ -1705,7 +1707,7 @@ async fn rpc_getdifficulty() {
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
mining_config,
|
mining_config,
|
||||||
Buffer::new(mempool.clone(), 1),
|
Buffer::new(mempool.clone(), 1),
|
||||||
read_state.clone(),
|
read_state.clone(),
|
||||||
|
@ -1730,7 +1732,7 @@ async fn rpc_getdifficulty() {
|
||||||
cur_time: fake_cur_time,
|
cur_time: fake_cur_time,
|
||||||
min_time: fake_min_time,
|
min_time: fake_min_time,
|
||||||
max_time: fake_max_time,
|
max_time: fake_max_time,
|
||||||
history_tree: fake_history_tree(Mainnet),
|
history_tree: fake_history_tree(&Mainnet),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1756,7 +1758,7 @@ async fn rpc_getdifficulty() {
|
||||||
cur_time: fake_cur_time,
|
cur_time: fake_cur_time,
|
||||||
min_time: fake_min_time,
|
min_time: fake_min_time,
|
||||||
max_time: fake_max_time,
|
max_time: fake_max_time,
|
||||||
history_tree: fake_history_tree(Mainnet),
|
history_tree: fake_history_tree(&Mainnet),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1779,7 +1781,7 @@ async fn rpc_getdifficulty() {
|
||||||
cur_time: fake_cur_time,
|
cur_time: fake_cur_time,
|
||||||
min_time: fake_min_time,
|
min_time: fake_min_time,
|
||||||
max_time: fake_max_time,
|
max_time: fake_max_time,
|
||||||
history_tree: fake_history_tree(Mainnet),
|
history_tree: fake_history_tree(&Mainnet),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1802,7 +1804,7 @@ async fn rpc_getdifficulty() {
|
||||||
cur_time: fake_cur_time,
|
cur_time: fake_cur_time,
|
||||||
min_time: fake_min_time,
|
min_time: fake_min_time,
|
||||||
max_time: fake_max_time,
|
max_time: fake_max_time,
|
||||||
history_tree: fake_history_tree(Mainnet),
|
history_tree: fake_history_tree(&Mainnet),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1826,7 +1828,7 @@ async fn rpc_z_listunifiedreceivers() {
|
||||||
|
|
||||||
// Init RPC
|
// Init RPC
|
||||||
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc = get_block_template_rpcs::GetBlockTemplateRpcImpl::new(
|
||||||
Mainnet,
|
&Mainnet,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
MockService::build().for_unit_tests(),
|
MockService::build().for_unit_tests(),
|
||||||
|
|
|
@ -157,7 +157,7 @@ impl Runner {
|
||||||
};
|
};
|
||||||
|
|
||||||
// get spacing between blocks
|
// get spacing between blocks
|
||||||
let spacing = NetworkUpgrade::target_spacing_for_height(network, tip_height);
|
let spacing = NetworkUpgrade::target_spacing_for_height(&network, tip_height);
|
||||||
|
|
||||||
// sleep until the next block
|
// sleep until the next block
|
||||||
tokio::time::sleep(spacing.to_std().expect("should never be less than zero")).await;
|
tokio::time::sleep(spacing.to_std().expect("should never be less than zero")).await;
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl RpcServer {
|
||||||
{
|
{
|
||||||
// Initialize the getblocktemplate rpc method handler
|
// Initialize the getblocktemplate rpc method handler
|
||||||
let get_block_template_rpc_impl = GetBlockTemplateRpcImpl::new(
|
let get_block_template_rpc_impl = GetBlockTemplateRpcImpl::new(
|
||||||
network,
|
&network,
|
||||||
mining_config.clone(),
|
mining_config.clone(),
|
||||||
mempool.clone(),
|
mempool.clone(),
|
||||||
state.clone(),
|
state.clone(),
|
||||||
|
@ -171,7 +171,7 @@ impl RpcServer {
|
||||||
let (rpc_impl, rpc_tx_queue_task_handle) = RpcImpl::new(
|
let (rpc_impl, rpc_tx_queue_task_handle) = RpcImpl::new(
|
||||||
build_version.clone(),
|
build_version.clone(),
|
||||||
user_agent,
|
user_agent,
|
||||||
network,
|
network.clone(),
|
||||||
config.debug_force_finished_sync,
|
config.debug_force_finished_sync,
|
||||||
#[cfg(feature = "getblocktemplate-rpcs")]
|
#[cfg(feature = "getblocktemplate-rpcs")]
|
||||||
mining_config.debug_like_zcashd,
|
mining_config.debug_like_zcashd,
|
||||||
|
|
|
@ -10,7 +10,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (config, network) = Default::default();
|
let (config, network) = Default::default();
|
||||||
|
|
||||||
let (scan_service, _cmd_receiver) =
|
let (scan_service, _cmd_receiver) =
|
||||||
ScanService::new_with_mock_scanner(Storage::new(&config, network, false));
|
ScanService::new_with_mock_scanner(Storage::new(&config, &network, false));
|
||||||
let scan_service = ServiceBuilder::new().buffer(10).service(scan_service);
|
let scan_service = ServiceBuilder::new().buffer(10).service(scan_service);
|
||||||
|
|
||||||
// Start the gRPC server.
|
// Start the gRPC server.
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub async fn init_with_server(
|
||||||
let scan_service = ServiceBuilder::new()
|
let scan_service = ServiceBuilder::new()
|
||||||
.buffer(10)
|
.buffer(10)
|
||||||
.timeout(SCAN_SERVICE_TIMEOUT)
|
.timeout(SCAN_SERVICE_TIMEOUT)
|
||||||
.service(ScanService::new(&config, network, state, chain_tip_change).await);
|
.service(ScanService::new(&config, &network, state, chain_tip_change).await);
|
||||||
|
|
||||||
// TODO: move this to zebra-grpc init() function and include addr
|
// TODO: move this to zebra-grpc init() function and include addr
|
||||||
info!(?listen_addr, "starting scan gRPC server");
|
info!(?listen_addr, "starting scan gRPC server");
|
||||||
|
@ -58,7 +58,7 @@ pub fn spawn_init(
|
||||||
tokio::spawn(
|
tokio::spawn(
|
||||||
async move {
|
async move {
|
||||||
let storage =
|
let storage =
|
||||||
tokio::task::spawn_blocking(move || Storage::new(&config, network, false))
|
tokio::task::spawn_blocking(move || Storage::new(&config, &network, false))
|
||||||
.wait_for_panics()
|
.wait_for_panics()
|
||||||
.await;
|
.await;
|
||||||
let (_cmd_sender, cmd_receiver) = tokio::sync::mpsc::channel(1);
|
let (_cmd_sender, cmd_receiver) = tokio::sync::mpsc::channel(1);
|
||||||
|
|
|
@ -41,12 +41,13 @@ impl ScanService {
|
||||||
/// Create a new [`ScanService`].
|
/// Create a new [`ScanService`].
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
network: Network,
|
network: &Network,
|
||||||
state: scan::State,
|
state: scan::State,
|
||||||
chain_tip_change: ChainTipChange,
|
chain_tip_change: ChainTipChange,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let config = config.clone();
|
let config = config.clone();
|
||||||
let storage = tokio::task::spawn_blocking(move || Storage::new(&config, network, false))
|
let network = network.clone();
|
||||||
|
let storage = tokio::task::spawn_blocking(move || Storage::new(&config, &network, false))
|
||||||
.wait_for_panics()
|
.wait_for_panics()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ impl ScanTask {
|
||||||
SaplingScanningKey,
|
SaplingScanningKey,
|
||||||
(Vec<DiversifiableFullViewingKey>, Vec<SaplingIvk>),
|
(Vec<DiversifiableFullViewingKey>, Vec<SaplingIvk>),
|
||||||
>,
|
>,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
HashMap<
|
HashMap<
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub async fn start(
|
||||||
> = key_heights
|
> = key_heights
|
||||||
.keys()
|
.keys()
|
||||||
.map(|key| {
|
.map(|key| {
|
||||||
let parsed_keys = sapling_key_to_scan_block_keys(key, network)?;
|
let parsed_keys = sapling_key_to_scan_block_keys(key, &network)?;
|
||||||
Ok::<_, Report>((key.clone(), parsed_keys))
|
Ok::<_, Report>((key.clone(), parsed_keys))
|
||||||
})
|
})
|
||||||
.try_collect()?;
|
.try_collect()?;
|
||||||
|
@ -143,7 +143,7 @@ pub async fn start(
|
||||||
let was_parsed_keys_empty = parsed_keys.is_empty();
|
let was_parsed_keys_empty = parsed_keys.is_empty();
|
||||||
|
|
||||||
let (new_keys, new_result_senders, new_result_receivers) =
|
let (new_keys, new_result_senders, new_result_receivers) =
|
||||||
ScanTask::process_messages(&mut cmd_receiver, &mut parsed_keys, network)?;
|
ScanTask::process_messages(&mut cmd_receiver, &mut parsed_keys, &network)?;
|
||||||
|
|
||||||
subscribed_keys.extend(new_result_senders);
|
subscribed_keys.extend(new_result_senders);
|
||||||
// Drop any results senders that are closed from subscribed_keys
|
// Drop any results senders that are closed from subscribed_keys
|
||||||
|
@ -311,6 +311,7 @@ pub async fn scan_height_and_store_results(
|
||||||
let sapling_key = sapling_key.clone();
|
let sapling_key = sapling_key.clone();
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
let mut storage = storage.clone();
|
let mut storage = storage.clone();
|
||||||
|
let network = network.clone();
|
||||||
|
|
||||||
// We use a dummy size of the Sapling note commitment tree.
|
// We use a dummy size of the Sapling note commitment tree.
|
||||||
//
|
//
|
||||||
|
@ -326,9 +327,9 @@ pub async fn scan_height_and_store_results(
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let dfvk_res =
|
let dfvk_res =
|
||||||
scan_block(network, &block, sapling_tree_size, &dfvks).map_err(|e| eyre!(e))?;
|
scan_block(&network, &block, sapling_tree_size, &dfvks).map_err(|e| eyre!(e))?;
|
||||||
let ivk_res =
|
let ivk_res =
|
||||||
scan_block(network, &block, sapling_tree_size, &ivks).map_err(|e| eyre!(e))?;
|
scan_block(&network, &block, sapling_tree_size, &ivks).map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
let dfvk_res = scanned_block_to_db_result(dfvk_res);
|
let dfvk_res = scanned_block_to_db_result(dfvk_res);
|
||||||
let ivk_res = scanned_block_to_db_result(ivk_res);
|
let ivk_res = scanned_block_to_db_result(ivk_res);
|
||||||
|
@ -375,7 +376,7 @@ pub async fn scan_height_and_store_results(
|
||||||
/// - Pass the real `sapling_tree_size` parameter from the state.
|
/// - Pass the real `sapling_tree_size` parameter from the state.
|
||||||
/// - Add other prior block metadata.
|
/// - Add other prior block metadata.
|
||||||
pub fn scan_block<K: ScanningKey>(
|
pub fn scan_block<K: ScanningKey>(
|
||||||
network: Network,
|
network: &Network,
|
||||||
block: &Block,
|
block: &Block,
|
||||||
sapling_tree_size: u32,
|
sapling_tree_size: u32,
|
||||||
scanning_keys: &[K],
|
scanning_keys: &[K],
|
||||||
|
@ -419,7 +420,7 @@ pub fn scan_block<K: ScanningKey>(
|
||||||
// TODO: use `ViewingKey::parse` from zebra-chain instead
|
// TODO: use `ViewingKey::parse` from zebra-chain instead
|
||||||
pub fn sapling_key_to_scan_block_keys(
|
pub fn sapling_key_to_scan_block_keys(
|
||||||
key: &SaplingScanningKey,
|
key: &SaplingScanningKey,
|
||||||
network: Network,
|
network: &Network,
|
||||||
) -> Result<(Vec<DiversifiableFullViewingKey>, Vec<SaplingIvk>), Report> {
|
) -> Result<(Vec<DiversifiableFullViewingKey>, Vec<SaplingIvk>), Report> {
|
||||||
let efvk =
|
let efvk =
|
||||||
decode_extended_full_viewing_key(network.sapling_efvk_hrp(), key).map_err(|e| eyre!(e))?;
|
decode_extended_full_viewing_key(network.sapling_efvk_hrp(), key).map_err(|e| eyre!(e))?;
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::{service::ScanTask, tests::mock_sapling_scanning_keys};
|
||||||
async fn scan_task_processes_messages_correctly() -> Result<(), Report> {
|
async fn scan_task_processes_messages_correctly() -> Result<(), Report> {
|
||||||
let (mut mock_scan_task, mut cmd_receiver) = ScanTask::mock();
|
let (mut mock_scan_task, mut cmd_receiver) = ScanTask::mock();
|
||||||
let mut parsed_keys = HashMap::new();
|
let mut parsed_keys = HashMap::new();
|
||||||
let network = Default::default();
|
let network = &Default::default();
|
||||||
|
|
||||||
// Send some keys to be registered
|
// Send some keys to be registered
|
||||||
let num_keys = 10;
|
let num_keys = 10;
|
||||||
|
|
|
@ -23,7 +23,7 @@ use crate::{
|
||||||
/// Tests that keys are deleted correctly
|
/// Tests that keys are deleted correctly
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn scan_service_deletes_keys_correctly() -> Result<()> {
|
pub async fn scan_service_deletes_keys_correctly() -> Result<()> {
|
||||||
let mut db = new_test_storage(Network::Mainnet);
|
let mut db = new_test_storage(&Network::Mainnet);
|
||||||
|
|
||||||
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ pub async fn scan_service_deletes_keys_correctly() -> Result<()> {
|
||||||
/// Tests that keys are deleted correctly
|
/// Tests that keys are deleted correctly
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn scan_service_subscribes_to_results_correctly() -> Result<()> {
|
pub async fn scan_service_subscribes_to_results_correctly() -> Result<()> {
|
||||||
let db = new_test_storage(Network::Mainnet);
|
let db = new_test_storage(&Network::Mainnet);
|
||||||
|
|
||||||
let (mut scan_service, mut cmd_receiver) = ScanService::new_with_mock_scanner(db);
|
let (mut scan_service, mut cmd_receiver) = ScanService::new_with_mock_scanner(db);
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ pub async fn scan_service_subscribes_to_results_correctly() -> Result<()> {
|
||||||
/// Tests that results are cleared are deleted correctly
|
/// Tests that results are cleared are deleted correctly
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn scan_service_clears_results_correctly() -> Result<()> {
|
pub async fn scan_service_clears_results_correctly() -> Result<()> {
|
||||||
let mut db = new_test_storage(Network::Mainnet);
|
let mut db = new_test_storage(&Network::Mainnet);
|
||||||
|
|
||||||
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ pub async fn scan_service_clears_results_correctly() -> Result<()> {
|
||||||
/// Tests that results for key are returned correctly
|
/// Tests that results for key are returned correctly
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn scan_service_get_results_for_key_correctly() -> Result<()> {
|
pub async fn scan_service_get_results_for_key_correctly() -> Result<()> {
|
||||||
let mut db = new_test_storage(Network::Mainnet);
|
let mut db = new_test_storage(&Network::Mainnet);
|
||||||
|
|
||||||
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
let zec_pages_sapling_efvk = ZECPAGES_SAPLING_VIEWING_KEY.to_string();
|
||||||
|
|
||||||
|
@ -265,13 +265,13 @@ pub async fn scan_service_get_results_for_key_correctly() -> Result<()> {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn scan_service_registers_keys_correctly() -> Result<()> {
|
pub async fn scan_service_registers_keys_correctly() -> Result<()> {
|
||||||
for network in Network::iter() {
|
for network in Network::iter() {
|
||||||
scan_service_registers_keys_correctly_for(network).await?;
|
scan_service_registers_keys_correctly_for(&network).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn scan_service_registers_keys_correctly_for(network: Network) -> Result<()> {
|
async fn scan_service_registers_keys_correctly_for(network: &Network) -> Result<()> {
|
||||||
// Mock the state.
|
// Mock the state.
|
||||||
let (state, _, _, chain_tip_change) = zebra_state::populated_state(vec![], network).await;
|
let (state, _, _, chain_tip_change) = zebra_state::populated_state(vec![], network).await;
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ async fn scan_service_registers_keys_correctly_for(network: Network) -> Result<(
|
||||||
/// Test that the scan service with a timeout layer returns timeout errors after expected timeout
|
/// Test that the scan service with a timeout layer returns timeout errors after expected timeout
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn scan_service_timeout() -> Result<()> {
|
async fn scan_service_timeout() -> Result<()> {
|
||||||
let db = new_test_storage(Network::Mainnet);
|
let db = new_test_storage(&Network::Mainnet);
|
||||||
|
|
||||||
let (scan_service, _cmd_receiver) = ScanService::new_with_mock_scanner(db);
|
let (scan_service, _cmd_receiver) = ScanService::new_with_mock_scanner(db);
|
||||||
let mut scan_service = ServiceBuilder::new()
|
let mut scan_service = ServiceBuilder::new()
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl Storage {
|
||||||
///
|
///
|
||||||
/// This method can block while creating or reading database files, so it must be inside
|
/// This method can block while creating or reading database files, so it must be inside
|
||||||
/// spawn_blocking() in async code.
|
/// spawn_blocking() in async code.
|
||||||
pub fn new(config: &Config, network: Network, read_only: bool) -> Self {
|
pub fn new(config: &Config, network: &Network, read_only: bool) -> Self {
|
||||||
let mut storage = Self::new_db(config, network, read_only);
|
let mut storage = Self::new_db(config, network, read_only);
|
||||||
|
|
||||||
for (sapling_key, birthday) in config.sapling_keys_to_scan.iter() {
|
for (sapling_key, birthday) in config.sapling_keys_to_scan.iter() {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue