use std::{collections::BTreeMap, ops::RangeBounds};
use crate::{
amount::Amount,
block::Block,
parameters::Network,
serialization::ZcashDeserializeInto,
transaction::{UnminedTx, VerifiedUnminedTx},
};
use zebra_test::vectors::{
BLOCK_MAINNET_1046400_BYTES, BLOCK_MAINNET_653599_BYTES, BLOCK_MAINNET_982681_BYTES,
BLOCK_TESTNET_1116000_BYTES, BLOCK_TESTNET_583999_BYTES, BLOCK_TESTNET_925483_BYTES,
CONTINUOUS_MAINNET_BLOCKS, CONTINUOUS_TESTNET_BLOCKS, MAINNET_BLOCKS,
MAINNET_FINAL_SAPLING_ROOTS, MAINNET_FINAL_SPROUT_ROOTS,
SAPLING_FINAL_ROOT_MAINNET_1046400_BYTES, SAPLING_FINAL_ROOT_TESTNET_1116000_BYTES,
TESTNET_BLOCKS, TESTNET_FINAL_SAPLING_ROOTS, TESTNET_FINAL_SPROUT_ROOTS,
};
impl Network {
pub fn is_mainnet(&self) -> bool {
matches!(self, Network::Mainnet)
}
pub fn block_iter(&self) -> std::collections::btree_map::Iter<'static, u32, &'static [u8]> {
if self.is_mainnet() {
MAINNET_BLOCKS.iter()
} else {
TESTNET_BLOCKS.iter()
}
}
pub fn unmined_transactions_in_blocks(
&self,
block_height_range: impl RangeBounds<u32>,
) -> impl DoubleEndedIterator<Item = VerifiedUnminedTx> {
let blocks = self.block_iter();
let selected_blocks = blocks
.filter(move |(&height, _)| block_height_range.contains(&height))
.map(|(_, block)| {
block
.zcash_deserialize_into::<Block>()
.expect("block test vector is structurally valid")
});
selected_blocks
.flat_map(|block| block.transactions)
.map(UnminedTx::from)
.filter_map(|transaction| {
VerifiedUnminedTx::new(
transaction,
Amount::try_from(1_000_000).expect("invalid value"),
0,
)
.ok()
})
}
pub fn block_map(&self) -> BTreeMap<u32, &'static [u8]> {
if self.is_mainnet() {
zebra_test::vectors::MAINNET_BLOCKS.clone()
} else {
zebra_test::vectors::TESTNET_BLOCKS.clone()
}
}
pub fn gen_block(&self) -> std::option::Option<&&[u8]> {
if self.is_mainnet() {
MAINNET_BLOCKS.get(&0)
} else {
TESTNET_BLOCKS.get(&0)
}
}
pub fn test_block(&self, main_height: u32, test_height: u32) -> Option<Block> {
match (self.is_mainnet(), main_height, test_height) {
(true, 653_599, _) => BLOCK_MAINNET_653599_BYTES.zcash_deserialize_into().ok(),
(true, 982_681, _) => BLOCK_MAINNET_982681_BYTES.zcash_deserialize_into().ok(),
(false, _, 583_999) => BLOCK_TESTNET_583999_BYTES.zcash_deserialize_into().ok(),
(false, _, 925_483) => BLOCK_TESTNET_925483_BYTES.zcash_deserialize_into().ok(),
_ => None,
}
}
pub fn blockchain_iter(&self) -> std::collections::btree_map::Iter<'_, u32, &[u8]> {
if self.is_mainnet() {
CONTINUOUS_MAINNET_BLOCKS.iter()
} else {
CONTINUOUS_TESTNET_BLOCKS.iter()
}
}
pub fn blockchain_map(&self) -> &BTreeMap<u32, &'static [u8]> {
if self.is_mainnet() {
&CONTINUOUS_MAINNET_BLOCKS
} else {
&CONTINUOUS_TESTNET_BLOCKS
}
}
pub fn block_sapling_roots_iter(
&self,
) -> (
std::collections::btree_map::Iter<'_, u32, &[u8]>,
std::collections::BTreeMap<u32, &[u8; 32]>,
) {
if self.is_mainnet() {
(MAINNET_BLOCKS.iter(), MAINNET_FINAL_SAPLING_ROOTS.clone())
} else {
(TESTNET_BLOCKS.iter(), TESTNET_FINAL_SAPLING_ROOTS.clone())
}
}
pub fn block_sapling_roots_map(
&self,
) -> (
&std::collections::BTreeMap<u32, &'static [u8]>,
&std::collections::BTreeMap<u32, &'static [u8; 32]>,
) {
if self.is_mainnet() {
(&*MAINNET_BLOCKS, &*MAINNET_FINAL_SAPLING_ROOTS)
} else {
(&*TESTNET_BLOCKS, &*TESTNET_FINAL_SAPLING_ROOTS)
}
}
pub fn test_block_sapling_roots(
&self,
main_height: u32,
test_height: u32,
) -> Option<(&[u8], [u8; 32])> {
match (self.is_mainnet(), main_height, test_height) {
(true, 1_046_400, _) => Some((
&BLOCK_MAINNET_1046400_BYTES[..],
*SAPLING_FINAL_ROOT_MAINNET_1046400_BYTES,
)),
(false, _, 1_116_000) => Some((
&BLOCK_TESTNET_1116000_BYTES[..],
*SAPLING_FINAL_ROOT_TESTNET_1116000_BYTES,
)),
_ => None,
}
}
pub fn block_sprout_roots_height(
&self,
) -> (
&std::collections::BTreeMap<u32, &'static [u8]>,
&std::collections::BTreeMap<u32, &'static [u8; 32]>,
u32,
) {
const MAINNET_FIRST_JOINSPLIT_HEIGHT: u32 = 396;
const TESTNET_FIRST_JOINSPLIT_HEIGHT: u32 = 2259;
if self.is_mainnet() {
(
&*MAINNET_BLOCKS,
&*MAINNET_FINAL_SPROUT_ROOTS,
MAINNET_FIRST_JOINSPLIT_HEIGHT,
)
} else {
(
&*TESTNET_BLOCKS,
&*TESTNET_FINAL_SPROUT_ROOTS,
TESTNET_FIRST_JOINSPLIT_HEIGHT,
)
}
}
}