Merge pull request #1250 from zcash/zcs-orchard-testing
zcash_client_sqlite: Run single-shielded-pool tests on Orchard
This commit is contained in:
commit
0d4a730e9e
|
@ -12,6 +12,7 @@ jobs:
|
||||||
matrix.extra_flags != 'NOT_A_PUZZLE' && format(' with --features {0}', matrix.extra_flags) || ''
|
matrix.extra_flags != 'NOT_A_PUZZLE' && format(' with --features {0}', matrix.extra_flags) || ''
|
||||||
}}
|
}}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
continue-on-error: ${{ matrix.extra_flags != 'NOT_A_PUZZLE' }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest-8cores, windows-latest-8cores, macOS-latest]
|
os: [ubuntu-latest-8cores, windows-latest-8cores, macOS-latest]
|
||||||
|
|
|
@ -3069,6 +3069,7 @@ dependencies = [
|
||||||
"pasta_curves",
|
"pasta_curves",
|
||||||
"proptest",
|
"proptest",
|
||||||
"prost",
|
"prost",
|
||||||
|
"rand_chacha",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"regex",
|
"regex",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
|
@ -3101,21 +3102,6 @@ dependencies = [
|
||||||
"nonempty",
|
"nonempty",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zcash_extensions"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"blake2b_simd",
|
|
||||||
"ff",
|
|
||||||
"jubjub",
|
|
||||||
"orchard",
|
|
||||||
"rand_core",
|
|
||||||
"sapling-crypto",
|
|
||||||
"zcash_address",
|
|
||||||
"zcash_primitives",
|
|
||||||
"zcash_proofs",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_history"
|
name = "zcash_history"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
|
@ -7,7 +7,8 @@ members = [
|
||||||
"components/zcash_protocol",
|
"components/zcash_protocol",
|
||||||
"zcash_client_backend",
|
"zcash_client_backend",
|
||||||
"zcash_client_sqlite",
|
"zcash_client_sqlite",
|
||||||
"zcash_extensions",
|
# Disabled until we replace the `zfutures` feature flag with a compiler flag.
|
||||||
|
# "zcash_extensions",
|
||||||
"zcash_history",
|
"zcash_history",
|
||||||
"zcash_keys",
|
"zcash_keys",
|
||||||
"zcash_primitives",
|
"zcash_primitives",
|
||||||
|
@ -108,6 +109,7 @@ lazy_static = "1"
|
||||||
assert_matches = "1.5"
|
assert_matches = "1.5"
|
||||||
criterion = "0.4"
|
criterion = "0.4"
|
||||||
proptest = "1"
|
proptest = "1"
|
||||||
|
rand_chacha = "0.3"
|
||||||
rand_xorshift = "0.3"
|
rand_xorshift = "0.3"
|
||||||
|
|
||||||
# ZIP 32
|
# ZIP 32
|
||||||
|
|
|
@ -83,6 +83,7 @@ pasta_curves.workspace = true
|
||||||
shardtree = { workspace = true, features = ["legacy-api", "test-dependencies"] }
|
shardtree = { workspace = true, features = ["legacy-api", "test-dependencies"] }
|
||||||
nonempty.workspace = true
|
nonempty.workspace = true
|
||||||
proptest.workspace = true
|
proptest.workspace = true
|
||||||
|
rand_chacha.workspace = true
|
||||||
rand_core.workspace = true
|
rand_core.workspace = true
|
||||||
regex = "1.4"
|
regex = "1.4"
|
||||||
tempfile = "3.5.0"
|
tempfile = "3.5.0"
|
||||||
|
@ -90,11 +91,14 @@ zcash_keys = { workspace = true, features = ["test-dependencies"] }
|
||||||
zcash_note_encryption.workspace = true
|
zcash_note_encryption.workspace = true
|
||||||
zcash_proofs = { workspace = true, features = ["bundled-prover"] }
|
zcash_proofs = { workspace = true, features = ["bundled-prover"] }
|
||||||
zcash_primitives = { workspace = true, features = ["test-dependencies"] }
|
zcash_primitives = { workspace = true, features = ["test-dependencies"] }
|
||||||
|
zcash_protocol = { workspace = true, features = ["local-consensus"] }
|
||||||
zcash_client_backend = { workspace = true, features = ["test-dependencies", "unstable-serialization", "unstable-spanning-tree"] }
|
zcash_client_backend = { workspace = true, features = ["test-dependencies", "unstable-serialization", "unstable-spanning-tree"] }
|
||||||
zcash_address = { workspace = true, features = ["test-dependencies"] }
|
zcash_address = { workspace = true, features = ["test-dependencies"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["multicore"]
|
default = ["multicore"]
|
||||||
|
unstable-nu6 = ["zcash_primitives/unstable-nu6"]
|
||||||
|
zfuture = ["zcash_primitives/zfuture"]
|
||||||
|
|
||||||
## Enables multithreading support for creating proofs and building subtrees.
|
## Enables multithreading support for creating proofs and building subtrees.
|
||||||
multicore = ["maybe-rayon/threads", "zcash_primitives/multicore"]
|
multicore = ["maybe-rayon/threads", "zcash_primitives/multicore"]
|
||||||
|
|
|
@ -111,6 +111,8 @@ pub(crate) const PRUNING_DEPTH: u32 = 100;
|
||||||
pub(crate) const VERIFY_LOOKAHEAD: u32 = 10;
|
pub(crate) const VERIFY_LOOKAHEAD: u32 = 10;
|
||||||
|
|
||||||
pub(crate) const SAPLING_TABLES_PREFIX: &str = "sapling";
|
pub(crate) const SAPLING_TABLES_PREFIX: &str = "sapling";
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
pub(crate) const ORCHARD_TABLES_PREFIX: &str = "orchard";
|
||||||
|
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
pub(crate) const UA_TRANSPARENT: bool = false;
|
pub(crate) const UA_TRANSPARENT: bool = false;
|
||||||
|
|
|
@ -7,7 +7,8 @@ use std::fs::File;
|
||||||
|
|
||||||
use nonempty::NonEmpty;
|
use nonempty::NonEmpty;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use rand_core::{CryptoRng, OsRng, RngCore};
|
use rand_chacha::ChaChaRng;
|
||||||
|
use rand_core::{CryptoRng, RngCore, SeedableRng};
|
||||||
use rusqlite::{params, Connection};
|
use rusqlite::{params, Connection};
|
||||||
use secrecy::{Secret, SecretVec};
|
use secrecy::{Secret, SecretVec};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
@ -50,7 +51,7 @@ use zcash_client_backend::{
|
||||||
use zcash_note_encryption::Domain;
|
use zcash_note_encryption::Domain;
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
consensus::{self, BlockHeight, Network, NetworkUpgrade, Parameters},
|
consensus::{self, BlockHeight, NetworkUpgrade, Parameters},
|
||||||
memo::{Memo, MemoBytes},
|
memo::{Memo, MemoBytes},
|
||||||
transaction::{
|
transaction::{
|
||||||
components::{amount::NonNegativeAmount, sapling::zip212_enforcement},
|
components::{amount::NonNegativeAmount, sapling::zip212_enforcement},
|
||||||
|
@ -59,6 +60,7 @@ use zcash_primitives::{
|
||||||
},
|
},
|
||||||
zip32::DiversifierIndex,
|
zip32::DiversifierIndex,
|
||||||
};
|
};
|
||||||
|
use zcash_protocol::local_consensus::LocalNetwork;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chain::init::init_cache_database,
|
chain::init::init_cache_database,
|
||||||
|
@ -98,18 +100,33 @@ pub(crate) mod pool;
|
||||||
|
|
||||||
/// A builder for a `zcash_client_sqlite` test.
|
/// A builder for a `zcash_client_sqlite` test.
|
||||||
pub(crate) struct TestBuilder<Cache> {
|
pub(crate) struct TestBuilder<Cache> {
|
||||||
network: Network,
|
network: LocalNetwork,
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
test_account_birthday: Option<AccountBirthday>,
|
test_account_birthday: Option<AccountBirthday>,
|
||||||
|
rng: ChaChaRng,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestBuilder<()> {
|
impl TestBuilder<()> {
|
||||||
/// Constructs a new test.
|
/// Constructs a new test.
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
TestBuilder {
|
TestBuilder {
|
||||||
network: Network::TestNetwork,
|
// Use a fake network where Sapling through NU5 activate at the same height.
|
||||||
|
// We pick 100,000 to be large enough to handle any hard-coded test offsets.
|
||||||
|
network: LocalNetwork {
|
||||||
|
overwinter: Some(BlockHeight::from_u32(1)),
|
||||||
|
sapling: Some(BlockHeight::from_u32(100_000)),
|
||||||
|
blossom: Some(BlockHeight::from_u32(100_000)),
|
||||||
|
heartwood: Some(BlockHeight::from_u32(100_000)),
|
||||||
|
canopy: Some(BlockHeight::from_u32(100_000)),
|
||||||
|
nu5: Some(BlockHeight::from_u32(100_000)),
|
||||||
|
#[cfg(feature = "unstable-nu6")]
|
||||||
|
nu6: None,
|
||||||
|
#[cfg(feature = "zfuture")]
|
||||||
|
z_future: None,
|
||||||
|
},
|
||||||
cache: (),
|
cache: (),
|
||||||
test_account_birthday: None,
|
test_account_birthday: None,
|
||||||
|
rng: ChaChaRng::seed_from_u64(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +136,7 @@ impl TestBuilder<()> {
|
||||||
network: self.network,
|
network: self.network,
|
||||||
cache: BlockCache::new(),
|
cache: BlockCache::new(),
|
||||||
test_account_birthday: self.test_account_birthday,
|
test_account_birthday: self.test_account_birthday,
|
||||||
|
rng: self.rng,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,12 +147,13 @@ impl TestBuilder<()> {
|
||||||
network: self.network,
|
network: self.network,
|
||||||
cache: FsBlockCache::new(),
|
cache: FsBlockCache::new(),
|
||||||
test_account_birthday: self.test_account_birthday,
|
test_account_birthday: self.test_account_birthday,
|
||||||
|
rng: self.rng,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Cache> TestBuilder<Cache> {
|
impl<Cache> TestBuilder<Cache> {
|
||||||
pub(crate) fn with_test_account<F: FnOnce(&Network) -> AccountBirthday>(
|
pub(crate) fn with_test_account<F: FnOnce(&LocalNetwork) -> AccountBirthday>(
|
||||||
mut self,
|
mut self,
|
||||||
birthday: F,
|
birthday: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -162,6 +181,7 @@ impl<Cache> TestBuilder<Cache> {
|
||||||
_data_file: data_file,
|
_data_file: data_file,
|
||||||
db_data,
|
db_data,
|
||||||
test_account,
|
test_account,
|
||||||
|
rng: self.rng,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,13 +235,14 @@ pub(crate) struct TestState<Cache> {
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
latest_cached_block: Option<CachedBlock>,
|
latest_cached_block: Option<CachedBlock>,
|
||||||
_data_file: NamedTempFile,
|
_data_file: NamedTempFile,
|
||||||
db_data: WalletDb<Connection, Network>,
|
db_data: WalletDb<Connection, LocalNetwork>,
|
||||||
test_account: Option<(
|
test_account: Option<(
|
||||||
SecretVec<u8>,
|
SecretVec<u8>,
|
||||||
AccountId,
|
AccountId,
|
||||||
UnifiedSpendingKey,
|
UnifiedSpendingKey,
|
||||||
AccountBirthday,
|
AccountBirthday,
|
||||||
)>,
|
)>,
|
||||||
|
rng: ChaChaRng,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Cache: TestCache> TestState<Cache>
|
impl<Cache: TestCache> TestState<Cache>
|
||||||
|
@ -291,6 +312,7 @@ where
|
||||||
value,
|
value,
|
||||||
initial_sapling_tree_size,
|
initial_sapling_tree_size,
|
||||||
initial_orchard_tree_size,
|
initial_orchard_tree_size,
|
||||||
|
&mut self.rng,
|
||||||
);
|
);
|
||||||
let res = self.cache.insert(&cb);
|
let res = self.cache.insert(&cb);
|
||||||
|
|
||||||
|
@ -332,6 +354,7 @@ where
|
||||||
value,
|
value,
|
||||||
cached_block.sapling_end_size,
|
cached_block.sapling_end_size,
|
||||||
cached_block.orchard_end_size,
|
cached_block.orchard_end_size,
|
||||||
|
&mut self.rng,
|
||||||
);
|
);
|
||||||
let res = self.cache.insert(&cb);
|
let res = self.cache.insert(&cb);
|
||||||
|
|
||||||
|
@ -383,6 +406,7 @@ where
|
||||||
tx,
|
tx,
|
||||||
cached_block.sapling_end_size,
|
cached_block.sapling_end_size,
|
||||||
cached_block.orchard_end_size,
|
cached_block.orchard_end_size,
|
||||||
|
&mut self.rng,
|
||||||
);
|
);
|
||||||
let res = self.cache.insert(&cb);
|
let res = self.cache.insert(&cb);
|
||||||
|
|
||||||
|
@ -460,17 +484,17 @@ where
|
||||||
|
|
||||||
impl<Cache> TestState<Cache> {
|
impl<Cache> TestState<Cache> {
|
||||||
/// Exposes an immutable reference to the test's [`WalletDb`].
|
/// Exposes an immutable reference to the test's [`WalletDb`].
|
||||||
pub(crate) fn wallet(&self) -> &WalletDb<Connection, Network> {
|
pub(crate) fn wallet(&self) -> &WalletDb<Connection, LocalNetwork> {
|
||||||
&self.db_data
|
&self.db_data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exposes a mutable reference to the test's [`WalletDb`].
|
/// Exposes a mutable reference to the test's [`WalletDb`].
|
||||||
pub(crate) fn wallet_mut(&mut self) -> &mut WalletDb<Connection, Network> {
|
pub(crate) fn wallet_mut(&mut self) -> &mut WalletDb<Connection, LocalNetwork> {
|
||||||
&mut self.db_data
|
&mut self.db_data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exposes the network in use.
|
/// Exposes the network in use.
|
||||||
pub(crate) fn network(&self) -> Network {
|
pub(crate) fn network(&self) -> LocalNetwork {
|
||||||
self.db_data.params
|
self.db_data.params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,6 +525,14 @@ impl<Cache> TestState<Cache> {
|
||||||
.and_then(|(_, _, usk, _)| usk.to_unified_full_viewing_key().sapling().cloned())
|
.and_then(|(_, _, usk, _)| usk.to_unified_full_viewing_key().sapling().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Exposes the test account's Sapling DFVK, if enabled via [`TestBuilder::with_test_account`].
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
pub(crate) fn test_account_orchard(&self) -> Option<orchard::keys::FullViewingKey> {
|
||||||
|
self.test_account
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|(_, _, usk, _)| usk.to_unified_full_viewing_key().orchard().cloned())
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes [`create_spend_to_address`] with the given arguments.
|
/// Invokes [`create_spend_to_address`] with the given arguments.
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
|
@ -561,7 +593,7 @@ impl<Cache> TestState<Cache> {
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
InputsT: InputSelector<InputSource = WalletDb<Connection, Network>>,
|
InputsT: InputSelector<InputSource = WalletDb<Connection, LocalNetwork>>,
|
||||||
{
|
{
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
let params = self.network();
|
let params = self.network();
|
||||||
|
@ -597,7 +629,7 @@ impl<Cache> TestState<Cache> {
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
InputsT: InputSelector<InputSource = WalletDb<Connection, Network>>,
|
InputsT: InputSelector<InputSource = WalletDb<Connection, LocalNetwork>>,
|
||||||
{
|
{
|
||||||
let params = self.network();
|
let params = self.network();
|
||||||
propose_transfer::<_, _, _, Infallible>(
|
propose_transfer::<_, _, _, Infallible>(
|
||||||
|
@ -673,7 +705,7 @@ impl<Cache> TestState<Cache> {
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
InputsT: ShieldingSelector<InputSource = WalletDb<Connection, Network>>,
|
InputsT: ShieldingSelector<InputSource = WalletDb<Connection, LocalNetwork>>,
|
||||||
{
|
{
|
||||||
let params = self.network();
|
let params = self.network();
|
||||||
propose_shielding::<_, _, _, Infallible>(
|
propose_shielding::<_, _, _, Infallible>(
|
||||||
|
@ -737,7 +769,7 @@ impl<Cache> TestState<Cache> {
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
InputsT: ShieldingSelector<InputSource = WalletDb<Connection, Network>>,
|
InputsT: ShieldingSelector<InputSource = WalletDb<Connection, LocalNetwork>>,
|
||||||
{
|
{
|
||||||
let params = self.network();
|
let params = self.network();
|
||||||
let prover = test_prover();
|
let prover = test_prover();
|
||||||
|
@ -1128,10 +1160,8 @@ fn fake_compact_block<P: consensus::Parameters, Fvk: TestFvk>(
|
||||||
value: NonNegativeAmount,
|
value: NonNegativeAmount,
|
||||||
initial_sapling_tree_size: u32,
|
initial_sapling_tree_size: u32,
|
||||||
initial_orchard_tree_size: u32,
|
initial_orchard_tree_size: u32,
|
||||||
|
mut rng: impl RngCore + CryptoRng,
|
||||||
) -> (CompactBlock, Fvk::Nullifier) {
|
) -> (CompactBlock, Fvk::Nullifier) {
|
||||||
// Create a fake Note for the account
|
|
||||||
let mut rng = OsRng;
|
|
||||||
|
|
||||||
// Create a fake CompactBlock containing the note
|
// Create a fake CompactBlock containing the note
|
||||||
let mut ctx = fake_compact_tx(&mut rng);
|
let mut ctx = fake_compact_tx(&mut rng);
|
||||||
let nf = fvk.add_output(
|
let nf = fvk.add_output(
|
||||||
|
@ -1150,6 +1180,7 @@ fn fake_compact_block<P: consensus::Parameters, Fvk: TestFvk>(
|
||||||
prev_hash,
|
prev_hash,
|
||||||
initial_sapling_tree_size,
|
initial_sapling_tree_size,
|
||||||
initial_orchard_tree_size,
|
initial_orchard_tree_size,
|
||||||
|
rng,
|
||||||
);
|
);
|
||||||
(cb, nf)
|
(cb, nf)
|
||||||
}
|
}
|
||||||
|
@ -1162,6 +1193,7 @@ fn fake_compact_block_from_tx(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
initial_sapling_tree_size: u32,
|
initial_sapling_tree_size: u32,
|
||||||
initial_orchard_tree_size: u32,
|
initial_orchard_tree_size: u32,
|
||||||
|
rng: impl RngCore,
|
||||||
) -> CompactBlock {
|
) -> CompactBlock {
|
||||||
// Create a fake CompactTx containing the transaction.
|
// Create a fake CompactTx containing the transaction.
|
||||||
let mut ctx = CompactTx {
|
let mut ctx = CompactTx {
|
||||||
|
@ -1192,6 +1224,7 @@ fn fake_compact_block_from_tx(
|
||||||
prev_hash,
|
prev_hash,
|
||||||
initial_sapling_tree_size,
|
initial_sapling_tree_size,
|
||||||
initial_orchard_tree_size,
|
initial_orchard_tree_size,
|
||||||
|
rng,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,8 +1241,8 @@ fn fake_compact_block_spending<P: consensus::Parameters, Fvk: TestFvk>(
|
||||||
value: NonNegativeAmount,
|
value: NonNegativeAmount,
|
||||||
initial_sapling_tree_size: u32,
|
initial_sapling_tree_size: u32,
|
||||||
initial_orchard_tree_size: u32,
|
initial_orchard_tree_size: u32,
|
||||||
|
mut rng: impl RngCore + CryptoRng,
|
||||||
) -> CompactBlock {
|
) -> CompactBlock {
|
||||||
let mut rng = OsRng;
|
|
||||||
let mut ctx = fake_compact_tx(&mut rng);
|
let mut ctx = fake_compact_tx(&mut rng);
|
||||||
|
|
||||||
// Create a fake spend and a fake Note for the change
|
// Create a fake spend and a fake Note for the change
|
||||||
|
@ -1291,6 +1324,7 @@ fn fake_compact_block_spending<P: consensus::Parameters, Fvk: TestFvk>(
|
||||||
prev_hash,
|
prev_hash,
|
||||||
initial_sapling_tree_size,
|
initial_sapling_tree_size,
|
||||||
initial_orchard_tree_size,
|
initial_orchard_tree_size,
|
||||||
|
rng,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,8 +1334,8 @@ fn fake_compact_block_from_compact_tx(
|
||||||
prev_hash: BlockHash,
|
prev_hash: BlockHash,
|
||||||
initial_sapling_tree_size: u32,
|
initial_sapling_tree_size: u32,
|
||||||
initial_orchard_tree_size: u32,
|
initial_orchard_tree_size: u32,
|
||||||
|
mut rng: impl RngCore,
|
||||||
) -> CompactBlock {
|
) -> CompactBlock {
|
||||||
let mut rng = OsRng;
|
|
||||||
let mut cb = CompactBlock {
|
let mut cb = CompactBlock {
|
||||||
hash: {
|
hash: {
|
||||||
let mut hash = vec![0; 32];
|
let mut hash = vec![0; 32];
|
||||||
|
@ -1428,7 +1462,7 @@ pub(crate) fn input_selector(
|
||||||
change_memo: Option<&str>,
|
change_memo: Option<&str>,
|
||||||
fallback_change_pool: ShieldedProtocol,
|
fallback_change_pool: ShieldedProtocol,
|
||||||
) -> GreedyInputSelector<
|
) -> GreedyInputSelector<
|
||||||
WalletDb<rusqlite::Connection, Network>,
|
WalletDb<rusqlite::Connection, LocalNetwork>,
|
||||||
standard::SingleOutputChangeStrategy,
|
standard::SingleOutputChangeStrategy,
|
||||||
> {
|
> {
|
||||||
let change_memo = change_memo.map(|m| MemoBytes::from(m.parse::<Memo>().unwrap()));
|
let change_memo = change_memo.map(|m| MemoBytes::from(m.parse::<Memo>().unwrap()));
|
||||||
|
@ -1440,7 +1474,7 @@ pub(crate) fn input_selector(
|
||||||
// Checks that a protobuf proposal serialized from the provided proposal value correctly parses to
|
// Checks that a protobuf proposal serialized from the provided proposal value correctly parses to
|
||||||
// the same proposal value.
|
// the same proposal value.
|
||||||
fn check_proposal_serialization_roundtrip(
|
fn check_proposal_serialization_roundtrip(
|
||||||
db_data: &WalletDb<rusqlite::Connection, Network>,
|
db_data: &WalletDb<rusqlite::Connection, LocalNetwork>,
|
||||||
proposal: &Proposal<StandardFeeRule, ReceivedNoteId>,
|
proposal: &Proposal<StandardFeeRule, ReceivedNoteId>,
|
||||||
) {
|
) {
|
||||||
let proposal_proto = proposal::Proposal::from_standard_proposal(&db_data.params, proposal);
|
let proposal_proto = proposal::Proposal::from_standard_proposal(&db_data.params, proposal);
|
||||||
|
|
|
@ -46,7 +46,8 @@ use crate::{
|
||||||
error::SqliteClientError,
|
error::SqliteClientError,
|
||||||
testing::{input_selector, AddressType, BlockCache, TestBuilder, TestState},
|
testing::{input_selector, AddressType, BlockCache, TestBuilder, TestState},
|
||||||
wallet::{
|
wallet::{
|
||||||
block_max_scanned, commitment_tree, parse_scope, scanning::tests::test_with_canopy_birthday,
|
block_max_scanned, commitment_tree, parse_scope,
|
||||||
|
scanning::tests::test_with_nu5_birthday_offset,
|
||||||
},
|
},
|
||||||
AccountId, NoteId, ReceivedNoteId,
|
AccountId, NoteId, ReceivedNoteId,
|
||||||
};
|
};
|
||||||
|
@ -147,7 +148,7 @@ pub(crate) fn send_single_step_proposed_transfer<T: ShieldedPoolTester>() {
|
||||||
h
|
h
|
||||||
);
|
);
|
||||||
|
|
||||||
let to_extsk = T::sk(&[]);
|
let to_extsk = T::sk(&[0xf5; 32]);
|
||||||
let to: Address = T::sk_default_address(&to_extsk);
|
let to: Address = T::sk_default_address(&to_extsk);
|
||||||
let request = zip321::TransactionRequest::new(vec![Payment {
|
let request = zip321::TransactionRequest::new(vec![Payment {
|
||||||
recipient_address: to,
|
recipient_address: to,
|
||||||
|
@ -522,7 +523,7 @@ pub(crate) fn spend_fails_on_unverified_notes<T: ShieldedPoolTester>() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Spend fails because there are insufficient verified notes
|
// Spend fails because there are insufficient verified notes
|
||||||
let extsk2 = T::sk(&[]);
|
let extsk2 = T::sk(&[0xf5; 32]);
|
||||||
let to = T::sk_default_address(&extsk2);
|
let to = T::sk_default_address(&extsk2);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
st.propose_standard_transfer::<Infallible>(
|
st.propose_standard_transfer::<Infallible>(
|
||||||
|
@ -643,7 +644,7 @@ pub(crate) fn spend_fails_on_locked_notes<T: ShieldedPoolTester>() {
|
||||||
assert_eq!(st.get_spendable_balance(account, 1), value);
|
assert_eq!(st.get_spendable_balance(account, 1), value);
|
||||||
|
|
||||||
// Send some of the funds to another address, but don't mine the tx.
|
// Send some of the funds to another address, but don't mine the tx.
|
||||||
let extsk2 = T::sk(&[]);
|
let extsk2 = T::sk(&[0xf5; 32]);
|
||||||
let to = T::sk_default_address(&extsk2);
|
let to = T::sk_default_address(&extsk2);
|
||||||
let min_confirmations = NonZeroU32::new(1).unwrap();
|
let min_confirmations = NonZeroU32::new(1).unwrap();
|
||||||
let proposal = st
|
let proposal = st
|
||||||
|
@ -774,7 +775,7 @@ pub(crate) fn ovk_policy_prevents_recovery_from_chain<T: ShieldedPoolTester>() {
|
||||||
assert_eq!(st.get_total_balance(account), value);
|
assert_eq!(st.get_total_balance(account), value);
|
||||||
assert_eq!(st.get_spendable_balance(account, 1), value);
|
assert_eq!(st.get_spendable_balance(account, 1), value);
|
||||||
|
|
||||||
let extsk2 = T::sk(&[]);
|
let extsk2 = T::sk(&[0xf5; 32]);
|
||||||
let addr2 = T::sk_default_address(&extsk2);
|
let addr2 = T::sk_default_address(&extsk2);
|
||||||
|
|
||||||
// TODO: This test was originally written to use the pre-zip-313 fee rule
|
// TODO: This test was originally written to use the pre-zip-313 fee rule
|
||||||
|
@ -1226,7 +1227,8 @@ pub(crate) fn shield_transparent<T: ShieldedPoolTester>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn birthday_in_anchor_shard<T: ShieldedPoolTester>() {
|
pub(crate) fn birthday_in_anchor_shard<T: ShieldedPoolTester>() {
|
||||||
let (mut st, dfvk, birthday, _) = test_with_canopy_birthday::<T>();
|
// Use a non-zero birthday offset because Sapling and NU5 are activated at the same height.
|
||||||
|
let (mut st, dfvk, birthday, _) = test_with_nu5_birthday_offset::<T>(76);
|
||||||
|
|
||||||
// Set up the following situation:
|
// Set up the following situation:
|
||||||
//
|
//
|
||||||
|
@ -1267,7 +1269,7 @@ pub(crate) fn birthday_in_anchor_shard<T: ShieldedPoolTester>() {
|
||||||
let initial_orchard_tree_size = 0;
|
let initial_orchard_tree_size = 0;
|
||||||
|
|
||||||
// Generate 9 blocks that have no value for us, starting at the birthday height.
|
// Generate 9 blocks that have no value for us, starting at the birthday height.
|
||||||
let not_our_key = T::sk_to_fvk(&T::sk(&[]));
|
let not_our_key = T::sk_to_fvk(&T::sk(&[0xf5; 32]));
|
||||||
let not_our_value = NonNegativeAmount::const_from_u64(10000);
|
let not_our_value = NonNegativeAmount::const_from_u64(10000);
|
||||||
st.generate_block_at(
|
st.generate_block_at(
|
||||||
birthday.height(),
|
birthday.height(),
|
||||||
|
@ -1346,7 +1348,7 @@ pub(crate) fn checkpoint_gaps<T: ShieldedPoolTester>() {
|
||||||
|
|
||||||
// Create a gap of 10 blocks having no shielded outputs, then add a block that doesn't
|
// Create a gap of 10 blocks having no shielded outputs, then add a block that doesn't
|
||||||
// belong to us so that we can get a checkpoint in the tree.
|
// belong to us so that we can get a checkpoint in the tree.
|
||||||
let not_our_key = T::sk_to_fvk(&T::sk(&[]));
|
let not_our_key = T::sk_to_fvk(&T::sk(&[0xf5; 32]));
|
||||||
let not_our_value = NonNegativeAmount::const_from_u64(10000);
|
let not_our_value = NonNegativeAmount::const_from_u64(10000);
|
||||||
st.generate_block_at(
|
st.generate_block_at(
|
||||||
birthday.height() + 10,
|
birthday.height() + 10,
|
||||||
|
|
|
@ -127,6 +127,8 @@ use {
|
||||||
|
|
||||||
pub mod commitment_tree;
|
pub mod commitment_tree;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
pub(crate) mod orchard;
|
||||||
pub(crate) mod sapling;
|
pub(crate) mod sapling;
|
||||||
pub(crate) mod scanning;
|
pub(crate) mod scanning;
|
||||||
|
|
||||||
|
|
|
@ -1111,6 +1111,52 @@ mod tests {
|
||||||
ShardTree::new(store, m)
|
ShardTree::new(store, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
mod orchard {
|
||||||
|
use super::new_tree;
|
||||||
|
use crate::wallet::orchard::tests::OrchardPoolTester;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn append() {
|
||||||
|
super::check_append(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn root_hashes() {
|
||||||
|
super::check_root_hashes(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn witnesses() {
|
||||||
|
super::check_witnesses(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn witness_consistency() {
|
||||||
|
super::check_witness_consistency(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_rewind() {
|
||||||
|
super::check_checkpoint_rewind(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_mark() {
|
||||||
|
super::check_remove_mark(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rewind_remove_mark() {
|
||||||
|
super::check_rewind_remove_mark(new_tree::<OrchardPoolTester>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn put_shard_roots() {
|
||||||
|
super::put_shard_roots::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sapling_append() {
|
fn sapling_append() {
|
||||||
check_append(new_tree::<SaplingPoolTester>);
|
check_append(new_tree::<SaplingPoolTester>);
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) mod tests {
|
||||||
|
use incrementalmerkletree::{Hashable, Level};
|
||||||
|
use orchard::{
|
||||||
|
keys::{FullViewingKey, SpendingKey},
|
||||||
|
note_encryption::OrchardDomain,
|
||||||
|
tree::MerkleHashOrchard,
|
||||||
|
};
|
||||||
|
use shardtree::error::ShardTreeError;
|
||||||
|
use zcash_client_backend::{
|
||||||
|
data_api::{
|
||||||
|
chain::CommitmentTreeRoot, DecryptedTransaction, WalletCommitmentTrees, WalletSummary,
|
||||||
|
},
|
||||||
|
wallet::{Note, ReceivedNote},
|
||||||
|
};
|
||||||
|
use zcash_keys::{
|
||||||
|
address::{Address, UnifiedAddress},
|
||||||
|
keys::UnifiedSpendingKey,
|
||||||
|
};
|
||||||
|
use zcash_note_encryption::try_output_recovery_with_ovk;
|
||||||
|
use zcash_primitives::transaction::Transaction;
|
||||||
|
use zcash_protocol::{consensus::BlockHeight, memo::MemoBytes, ShieldedProtocol};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
error::SqliteClientError,
|
||||||
|
testing::{
|
||||||
|
self,
|
||||||
|
pool::{OutputRecoveryError, ShieldedPoolTester},
|
||||||
|
TestState,
|
||||||
|
},
|
||||||
|
wallet::commitment_tree,
|
||||||
|
ORCHARD_TABLES_PREFIX,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) struct OrchardPoolTester;
|
||||||
|
impl ShieldedPoolTester for OrchardPoolTester {
|
||||||
|
const SHIELDED_PROTOCOL: ShieldedProtocol = ShieldedProtocol::Orchard;
|
||||||
|
const TABLES_PREFIX: &'static str = ORCHARD_TABLES_PREFIX;
|
||||||
|
|
||||||
|
type Sk = SpendingKey;
|
||||||
|
type Fvk = FullViewingKey;
|
||||||
|
type MerkleTreeHash = MerkleHashOrchard;
|
||||||
|
|
||||||
|
fn test_account_fvk<Cache>(st: &TestState<Cache>) -> Self::Fvk {
|
||||||
|
st.test_account_orchard().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usk_to_sk(usk: &UnifiedSpendingKey) -> &Self::Sk {
|
||||||
|
usk.orchard()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sk(seed: &[u8]) -> Self::Sk {
|
||||||
|
let mut account = zip32::AccountId::ZERO;
|
||||||
|
loop {
|
||||||
|
if let Ok(sk) = SpendingKey::from_zip32_seed(seed, 1, account) {
|
||||||
|
break sk;
|
||||||
|
}
|
||||||
|
account = account.next().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sk_to_fvk(sk: &Self::Sk) -> Self::Fvk {
|
||||||
|
sk.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sk_default_address(sk: &Self::Sk) -> Address {
|
||||||
|
Self::fvk_default_address(&Self::sk_to_fvk(sk))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fvk_default_address(fvk: &Self::Fvk) -> Address {
|
||||||
|
UnifiedAddress::from_receivers(
|
||||||
|
Some(fvk.address_at(0u32, zip32::Scope::External)),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fvks_equal(a: &Self::Fvk, b: &Self::Fvk) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_tree_leaf() -> Self::MerkleTreeHash {
|
||||||
|
MerkleHashOrchard::empty_leaf()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_tree_root(level: Level) -> Self::MerkleTreeHash {
|
||||||
|
MerkleHashOrchard::empty_root(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn put_subtree_roots<Cache>(
|
||||||
|
st: &mut TestState<Cache>,
|
||||||
|
start_index: u64,
|
||||||
|
roots: &[CommitmentTreeRoot<Self::MerkleTreeHash>],
|
||||||
|
) -> Result<(), ShardTreeError<commitment_tree::Error>> {
|
||||||
|
st.wallet_mut()
|
||||||
|
.put_orchard_subtree_roots(start_index, roots)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_subtree_index(s: &WalletSummary<crate::AccountId>) -> u64 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_spendable_notes<Cache>(
|
||||||
|
st: &TestState<Cache>,
|
||||||
|
account: crate::AccountId,
|
||||||
|
target_value: zcash_protocol::value::Zatoshis,
|
||||||
|
anchor_height: BlockHeight,
|
||||||
|
exclude: &[crate::ReceivedNoteId],
|
||||||
|
) -> Result<Vec<ReceivedNote<crate::ReceivedNoteId, Note>>, SqliteClientError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decrypted_pool_outputs_count(
|
||||||
|
d_tx: &DecryptedTransaction<'_, crate::AccountId>,
|
||||||
|
) -> usize {
|
||||||
|
d_tx.orchard_outputs().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_decrypted_pool_memos(
|
||||||
|
d_tx: &DecryptedTransaction<'_, crate::AccountId>,
|
||||||
|
mut f: impl FnMut(&MemoBytes),
|
||||||
|
) {
|
||||||
|
for output in d_tx.orchard_outputs() {
|
||||||
|
f(output.memo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_output_recovery<Cache>(
|
||||||
|
_: &TestState<Cache>,
|
||||||
|
_: BlockHeight,
|
||||||
|
tx: &Transaction,
|
||||||
|
fvk: &Self::Fvk,
|
||||||
|
) -> Result<Option<(Note, Address, MemoBytes)>, OutputRecoveryError> {
|
||||||
|
for action in tx.orchard_bundle().unwrap().actions() {
|
||||||
|
// Find the output that decrypts with the external OVK
|
||||||
|
let result = try_output_recovery_with_ovk(
|
||||||
|
&OrchardDomain::for_action(action),
|
||||||
|
&fvk.to_ovk(zip32::Scope::External),
|
||||||
|
action,
|
||||||
|
action.cv_net(),
|
||||||
|
&action.encrypted_note().out_ciphertext,
|
||||||
|
);
|
||||||
|
|
||||||
|
if result.is_some() {
|
||||||
|
return Ok(result.map(|(note, addr, memo)| {
|
||||||
|
(
|
||||||
|
Note::Orchard(note),
|
||||||
|
UnifiedAddress::from_receivers(Some(addr), None, None)
|
||||||
|
.unwrap()
|
||||||
|
.into(),
|
||||||
|
MemoBytes::from_bytes(&memo).expect("correct length"),
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn send_single_step_proposed_transfer() {
|
||||||
|
testing::pool::send_single_step_proposed_transfer::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
fn send_multi_step_proposed_transfer() {
|
||||||
|
testing::pool::send_multi_step_proposed_transfer::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
|
fn create_to_address_fails_on_incorrect_usk() {
|
||||||
|
testing::pool::create_to_address_fails_on_incorrect_usk::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
|
fn proposal_fails_with_no_blocks() {
|
||||||
|
testing::pool::proposal_fails_with_no_blocks::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn spend_fails_on_unverified_notes() {
|
||||||
|
testing::pool::spend_fails_on_unverified_notes::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn spend_fails_on_locked_notes() {
|
||||||
|
testing::pool::spend_fails_on_locked_notes::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ovk_policy_prevents_recovery_from_chain() {
|
||||||
|
testing::pool::ovk_policy_prevents_recovery_from_chain::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn spend_succeeds_to_t_addr_zero_change() {
|
||||||
|
testing::pool::spend_succeeds_to_t_addr_zero_change::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn change_note_spends_succeed() {
|
||||||
|
testing::pool::change_note_spends_succeed::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn external_address_change_spends_detected_in_restore_from_seed() {
|
||||||
|
testing::pool::external_address_change_spends_detected_in_restore_from_seed::<
|
||||||
|
OrchardPoolTester,
|
||||||
|
>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn zip317_spend() {
|
||||||
|
testing::pool::zip317_spend::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
fn shield_transparent() {
|
||||||
|
testing::pool::shield_transparent::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn birthday_in_anchor_shard() {
|
||||||
|
testing::pool::birthday_in_anchor_shard::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_gaps() {
|
||||||
|
testing::pool::checkpoint_gaps::<OrchardPoolTester>()
|
||||||
|
}
|
||||||
|
}
|
|
@ -565,11 +565,20 @@ pub(crate) mod tests {
|
||||||
VERIFY_LOOKAHEAD,
|
VERIFY_LOOKAHEAD,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
use crate::wallet::orchard::tests::OrchardPoolTester;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sapling_scan_complete() {
|
fn sapling_scan_complete() {
|
||||||
scan_complete::<SaplingPoolTester>();
|
scan_complete::<SaplingPoolTester>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
#[test]
|
||||||
|
fn orchard_scan_complete() {
|
||||||
|
scan_complete::<OrchardPoolTester>();
|
||||||
|
}
|
||||||
|
|
||||||
fn scan_complete<T: ShieldedPoolTester>() {
|
fn scan_complete<T: ShieldedPoolTester>() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
|
@ -699,14 +708,16 @@ pub(crate) mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn test_with_canopy_birthday<T: ShieldedPoolTester>(
|
pub(crate) fn test_with_nu5_birthday_offset<T: ShieldedPoolTester>(
|
||||||
|
offset: u32,
|
||||||
) -> (TestState<BlockCache>, T::Fvk, AccountBirthday, u32) {
|
) -> (TestState<BlockCache>, T::Fvk, AccountBirthday, u32) {
|
||||||
let st = TestBuilder::new()
|
let st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_test_account(|network| {
|
.with_test_account(|network| {
|
||||||
// We use Canopy activation as an arbitrary birthday height that's greater than Sapling
|
// We set the Sapling frontier at the birthday height to be 1234 notes
|
||||||
// activation. We set the Canopy Sapling frontier to be 1234 notes into the second shard.
|
// into the second shard.
|
||||||
let birthday_height = network.activation_height(NetworkUpgrade::Canopy).unwrap();
|
let birthday_height =
|
||||||
|
network.activation_height(NetworkUpgrade::Nu5).unwrap() + offset;
|
||||||
let sapling_frontier_position = Position::from((0x1 << 16) + 1234);
|
let sapling_frontier_position = Position::from((0x1 << 16) + 1234);
|
||||||
let sapling_frontier = Frontier::from_parts(
|
let sapling_frontier = Frontier::from_parts(
|
||||||
sapling_frontier_position,
|
sapling_frontier_position,
|
||||||
|
@ -736,10 +747,17 @@ pub(crate) mod tests {
|
||||||
create_account_creates_ignored_range::<SaplingPoolTester>();
|
create_account_creates_ignored_range::<SaplingPoolTester>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
#[test]
|
||||||
|
fn orchard_create_account_creates_ignored_range() {
|
||||||
|
create_account_creates_ignored_range::<OrchardPoolTester>();
|
||||||
|
}
|
||||||
|
|
||||||
fn create_account_creates_ignored_range<T: ShieldedPoolTester>() {
|
fn create_account_creates_ignored_range<T: ShieldedPoolTester>() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
let (st, _, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
// Use a non-zero birthday offset because Sapling and NU5 are activated at the same height.
|
||||||
|
let (st, _, birthday, sap_active) = test_with_nu5_birthday_offset::<T>(76);
|
||||||
let birthday_height = birthday.height().into();
|
let birthday_height = birthday.height().into();
|
||||||
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
|
@ -799,10 +817,17 @@ pub(crate) mod tests {
|
||||||
update_chain_tip_with_no_subtree_roots::<SaplingPoolTester>();
|
update_chain_tip_with_no_subtree_roots::<SaplingPoolTester>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
#[test]
|
||||||
|
fn orchard_update_chain_tip_with_no_subtree_roots() {
|
||||||
|
update_chain_tip_with_no_subtree_roots::<OrchardPoolTester>();
|
||||||
|
}
|
||||||
|
|
||||||
fn update_chain_tip_with_no_subtree_roots<T: ShieldedPoolTester>() {
|
fn update_chain_tip_with_no_subtree_roots<T: ShieldedPoolTester>() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
let (mut st, _, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
// Use a non-zero birthday offset because Sapling and NU5 are activated at the same height.
|
||||||
|
let (mut st, _, birthday, sap_active) = test_with_nu5_birthday_offset::<T>(76);
|
||||||
|
|
||||||
// Set up the following situation:
|
// Set up the following situation:
|
||||||
//
|
//
|
||||||
|
@ -834,10 +859,17 @@ pub(crate) mod tests {
|
||||||
update_chain_tip_when_never_scanned::<SaplingPoolTester>();
|
update_chain_tip_when_never_scanned::<SaplingPoolTester>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
#[test]
|
||||||
|
fn orchard_update_chain_tip_when_never_scanned() {
|
||||||
|
update_chain_tip_when_never_scanned::<OrchardPoolTester>();
|
||||||
|
}
|
||||||
|
|
||||||
fn update_chain_tip_when_never_scanned<T: ShieldedPoolTester>() {
|
fn update_chain_tip_when_never_scanned<T: ShieldedPoolTester>() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
let (mut st, _, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
// Use a non-zero birthday offset because Sapling and NU5 are activated at the same height.
|
||||||
|
let (mut st, _, birthday, sap_active) = test_with_nu5_birthday_offset::<T>(76);
|
||||||
|
|
||||||
// Set up the following situation:
|
// Set up the following situation:
|
||||||
//
|
//
|
||||||
|
@ -883,11 +915,18 @@ pub(crate) mod tests {
|
||||||
update_chain_tip_unstable_max_scanned::<SaplingPoolTester>();
|
update_chain_tip_unstable_max_scanned::<SaplingPoolTester>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
#[test]
|
||||||
|
fn orchard_update_chain_tip_unstable_max_scanned() {
|
||||||
|
update_chain_tip_unstable_max_scanned::<OrchardPoolTester>();
|
||||||
|
}
|
||||||
|
|
||||||
fn update_chain_tip_unstable_max_scanned<T: ShieldedPoolTester>() {
|
fn update_chain_tip_unstable_max_scanned<T: ShieldedPoolTester>() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
|
// Use a non-zero birthday offset because Sapling and NU5 are activated at the same height.
|
||||||
// this birthday is 1234 notes into the second shard
|
// this birthday is 1234 notes into the second shard
|
||||||
let (mut st, dfvk, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
let (mut st, dfvk, birthday, sap_active) = test_with_nu5_birthday_offset::<T>(76);
|
||||||
|
|
||||||
// Set up the following situation:
|
// Set up the following situation:
|
||||||
//
|
//
|
||||||
|
@ -1015,10 +1054,17 @@ pub(crate) mod tests {
|
||||||
update_chain_tip_stable_max_scanned::<SaplingPoolTester>();
|
update_chain_tip_stable_max_scanned::<SaplingPoolTester>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
#[test]
|
||||||
|
fn orchard_update_chain_tip_stable_max_scanned() {
|
||||||
|
update_chain_tip_stable_max_scanned::<OrchardPoolTester>();
|
||||||
|
}
|
||||||
|
|
||||||
fn update_chain_tip_stable_max_scanned<T: ShieldedPoolTester>() {
|
fn update_chain_tip_stable_max_scanned<T: ShieldedPoolTester>() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
let (mut st, dfvk, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
// Use a non-zero birthday offset because Sapling and NU5 are activated at the same height.
|
||||||
|
let (mut st, dfvk, birthday, sap_active) = test_with_nu5_birthday_offset::<T>(76);
|
||||||
|
|
||||||
// Set up the following situation:
|
// Set up the following situation:
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue