Merge pull request #915 from nuttycom/sbs/pre_birthday_test_refactor
Test refactorings in preparation for #907
This commit is contained in:
commit
31e5a5188e
|
@ -11,6 +11,7 @@ and this library adheres to Rust's notion of
|
||||||
- `impl Eq for zcash_client_backend::zip321::{Payment, TransactionRequest}`
|
- `impl Eq for zcash_client_backend::zip321::{Payment, TransactionRequest}`
|
||||||
- `impl Debug` for `zcash_client_backend::{data_api::wallet::input_selection::Proposal, wallet::ReceivedSaplingNote}`
|
- `impl Debug` for `zcash_client_backend::{data_api::wallet::input_selection::Proposal, wallet::ReceivedSaplingNote}`
|
||||||
- `zcash_client_backend::data_api`:
|
- `zcash_client_backend::data_api`:
|
||||||
|
- `AccountBirthday`
|
||||||
- `BlockMetadata`
|
- `BlockMetadata`
|
||||||
- `NoteId`
|
- `NoteId`
|
||||||
- `NullifierQuery` for use with `WalletRead::get_sapling_nullifiers`
|
- `NullifierQuery` for use with `WalletRead::get_sapling_nullifiers`
|
||||||
|
@ -28,6 +29,8 @@ and this library adheres to Rust's notion of
|
||||||
- `ScanError`
|
- `ScanError`
|
||||||
- `impl<K: ScanningKey> ScanningKey for &K`
|
- `impl<K: ScanningKey> ScanningKey for &K`
|
||||||
- `impl ScanningKey for (zip32::Scope, sapling::SaplingIvk, sapling::NullifierDerivingKey)`
|
- `impl ScanningKey for (zip32::Scope, sapling::SaplingIvk, sapling::NullifierDerivingKey)`
|
||||||
|
- Test utility functions `zcash_client_backend::keys::UnifiedSpendingKey::{default_address,
|
||||||
|
default_transparent_address}` are now available under the `test-dependencies` feature flag.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- MSRV is now 1.65.0.
|
- MSRV is now 1.65.0.
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
use incrementalmerkletree::Retention;
|
use incrementalmerkletree::{frontier::Frontier, Retention};
|
||||||
use secrecy::SecretVec;
|
use secrecy::SecretVec;
|
||||||
use shardtree::{error::ShardTreeError, store::ShardStore, ShardTree};
|
use shardtree::{error::ShardTreeError, store::ShardStore, ShardTree};
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
|
@ -12,7 +12,7 @@ use zcash_primitives::{
|
||||||
consensus::BlockHeight,
|
consensus::BlockHeight,
|
||||||
legacy::TransparentAddress,
|
legacy::TransparentAddress,
|
||||||
memo::{Memo, MemoBytes},
|
memo::{Memo, MemoBytes},
|
||||||
sapling,
|
sapling::{self, Node, NOTE_COMMITMENT_TREE_DEPTH},
|
||||||
transaction::{
|
transaction::{
|
||||||
components::{amount::Amount, OutPoint},
|
components::{amount::Amount, OutPoint},
|
||||||
Transaction, TxId,
|
Transaction, TxId,
|
||||||
|
@ -466,6 +466,43 @@ impl SentTransactionOutput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A data structure used to set the birthday height for an account, and ensure that the initial
|
||||||
|
/// note commitment tree state is recorded at that height.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct AccountBirthday {
|
||||||
|
height: BlockHeight,
|
||||||
|
sapling_frontier: Frontier<Node, NOTE_COMMITMENT_TREE_DEPTH>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccountBirthday {
|
||||||
|
/// Constructs a new [`AccountBirthday`] from its constituent parts.
|
||||||
|
///
|
||||||
|
/// * `height`: The birthday height of the account. This is defined as the height of the last
|
||||||
|
/// block that is known to contain no transactions sent to addresses belonging to the account.
|
||||||
|
/// * `sapling_frontier`: The Sapling note commitment tree frontier as of the end of the block
|
||||||
|
/// at `height`.
|
||||||
|
pub fn from_parts(
|
||||||
|
height: BlockHeight,
|
||||||
|
sapling_frontier: Frontier<Node, NOTE_COMMITMENT_TREE_DEPTH>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
height,
|
||||||
|
sapling_frontier,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Sapling note commitment tree frontier as of the end of the block at
|
||||||
|
/// [`Self::height`].
|
||||||
|
pub fn sapling_frontier(&self) -> &Frontier<Node, NOTE_COMMITMENT_TREE_DEPTH> {
|
||||||
|
&self.sapling_frontier
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the birthday height of the account.
|
||||||
|
pub fn height(&self) -> BlockHeight {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This trait encapsulates the write capabilities required to update stored
|
/// This trait encapsulates the write capabilities required to update stored
|
||||||
/// wallet data.
|
/// wallet data.
|
||||||
pub trait WalletWrite: WalletRead {
|
pub trait WalletWrite: WalletRead {
|
||||||
|
|
|
@ -14,6 +14,9 @@ use {
|
||||||
zcash_primitives::legacy::keys::{self as legacy, IncomingViewingKey},
|
zcash_primitives::legacy::keys::{self as legacy, IncomingViewingKey},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "test-dependencies", feature = "transparent-inputs"))]
|
||||||
|
use zcash_primitives::legacy::TransparentAddress;
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use {
|
use {
|
||||||
byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt},
|
byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt},
|
||||||
|
@ -336,6 +339,20 @@ impl UnifiedSpendingKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "test-dependencies")]
|
||||||
|
pub fn default_address(&self) -> (UnifiedAddress, DiversifierIndex) {
|
||||||
|
self.to_unified_full_viewing_key().default_address()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "test-dependencies", feature = "transparent-inputs"))]
|
||||||
|
pub fn default_transparent_address(&self) -> (TransparentAddress, u32) {
|
||||||
|
self.transparent()
|
||||||
|
.to_account_pubkey()
|
||||||
|
.derive_external_ivk()
|
||||||
|
.unwrap()
|
||||||
|
.default_address()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [ZIP 316](https://zips.z.cash/zip-0316) unified full viewing key.
|
/// A [ZIP 316](https://zips.z.cash/zip-0316) unified full viewing key.
|
||||||
|
|
|
@ -60,6 +60,7 @@ tempfile = "3.5.0"
|
||||||
zcash_note_encryption = "0.4"
|
zcash_note_encryption = "0.4"
|
||||||
zcash_proofs = { version = "0.12", path = "../zcash_proofs" }
|
zcash_proofs = { version = "0.12", path = "../zcash_proofs" }
|
||||||
zcash_primitives = { version = "0.12", path = "../zcash_primitives", features = ["test-dependencies"] }
|
zcash_primitives = { version = "0.12", path = "../zcash_primitives", features = ["test-dependencies"] }
|
||||||
|
zcash_client_backend = { version = "0.9", path = "../zcash_client_backend", features = ["test-dependencies"] }
|
||||||
zcash_address = { version = "0.3", path = "../components/zcash_address", features = ["test-dependencies"] }
|
zcash_address = { version = "0.3", path = "../components/zcash_address", features = ["test-dependencies"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -345,7 +345,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
testing::{AddressType, TestBuilder},
|
testing::{birthday_at_sapling_activation, AddressType, TestBuilder},
|
||||||
wallet::{get_balance, truncate_to_height},
|
wallet::{get_balance, truncate_to_height},
|
||||||
AccountId,
|
AccountId,
|
||||||
};
|
};
|
||||||
|
@ -354,8 +354,7 @@ mod tests {
|
||||||
fn valid_chain_states() {
|
fn valid_chain_states() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
@ -388,8 +387,7 @@ mod tests {
|
||||||
fn invalid_chain_cache_disconnected() {
|
fn invalid_chain_cache_disconnected() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
@ -440,8 +438,7 @@ mod tests {
|
||||||
fn data_db_truncation() {
|
fn data_db_truncation() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
@ -501,10 +498,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scan_cached_blocks_allows_blocks_out_of_order() {
|
fn scan_cached_blocks_allows_blocks_out_of_order() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new().with_block_cache().build();
|
||||||
.with_block_cache()
|
|
||||||
.with_seed(Secret::new(vec![]))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let seed = Secret::new([0u8; 32].to_vec());
|
let seed = Secret::new([0u8; 32].to_vec());
|
||||||
|
@ -564,8 +558,7 @@ mod tests {
|
||||||
fn scan_cached_blocks_finds_received_notes() {
|
fn scan_cached_blocks_finds_received_notes() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
@ -607,8 +600,7 @@ mod tests {
|
||||||
fn scan_cached_blocks_finds_change_notes() {
|
fn scan_cached_blocks_finds_change_notes() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
@ -653,8 +645,7 @@ mod tests {
|
||||||
fn scan_cached_blocks_detects_spends_out_of_order() {
|
fn scan_cached_blocks_detects_spends_out_of_order() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
|
|
@ -1087,7 +1087,10 @@ extern crate assert_matches;
|
||||||
mod tests {
|
mod tests {
|
||||||
use zcash_client_backend::data_api::{WalletRead, WalletWrite};
|
use zcash_client_backend::data_api::{WalletRead, WalletWrite};
|
||||||
|
|
||||||
use crate::{testing::TestBuilder, AccountId};
|
use crate::{
|
||||||
|
testing::{birthday_at_sapling_activation, TestBuilder},
|
||||||
|
AccountId,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use zcash_primitives::{consensus::Parameters, transaction::components::Amount};
|
use zcash_primitives::{consensus::Parameters, transaction::components::Amount};
|
||||||
|
@ -1100,7 +1103,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub(crate) fn get_next_available_address() {
|
pub(crate) fn get_next_available_address() {
|
||||||
let mut st = TestBuilder::new().with_test_account().build();
|
let mut st = TestBuilder::new()
|
||||||
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
|
.build();
|
||||||
|
|
||||||
let account = AccountId::from(0);
|
let account = AccountId::from(0);
|
||||||
let current_addr = st.wallet().get_current_address(account).unwrap();
|
let current_addr = st.wallet().get_current_address(account).unwrap();
|
||||||
|
@ -1117,17 +1122,15 @@ mod tests {
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
#[test]
|
#[test]
|
||||||
fn transparent_receivers() {
|
fn transparent_receivers() {
|
||||||
use secrecy::Secret;
|
// Add an account to the wallet.
|
||||||
|
|
||||||
let st = TestBuilder::new()
|
let st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Add an account to the wallet.
|
let (_, usk, _) = st.test_account().unwrap();
|
||||||
let (ufvk, taddr) = st.test_account().unwrap();
|
let ufvk = usk.to_unified_full_viewing_key();
|
||||||
let taddr = taddr.unwrap();
|
let (taddr, _) = usk.default_transparent_address();
|
||||||
|
|
||||||
let receivers = st.wallet().get_transparent_receivers(0.into()).unwrap();
|
let receivers = st.wallet().get_transparent_receivers(0.into()).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::{collections::HashMap, num::NonZeroU32};
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -8,26 +8,26 @@ use std::fs::File;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
use rusqlite::{params, Connection};
|
use rusqlite::{params, Connection};
|
||||||
use secrecy::SecretVec;
|
use secrecy::Secret;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
use zcash_client_backend::data_api::wallet::create_spend_to_address;
|
|
||||||
use zcash_client_backend::{
|
use zcash_client_backend::{
|
||||||
address::RecipientAddress,
|
address::RecipientAddress,
|
||||||
data_api::{
|
data_api::{
|
||||||
self,
|
self,
|
||||||
chain::{scan_cached_blocks, BlockSource},
|
chain::{scan_cached_blocks, BlockSource},
|
||||||
wallet::{
|
wallet::{
|
||||||
create_proposed_transaction,
|
create_proposed_transaction, create_spend_to_address,
|
||||||
input_selection::{GreedyInputSelectorError, InputSelector, Proposal},
|
input_selection::{GreedyInputSelectorError, InputSelector, Proposal},
|
||||||
propose_transfer, spend,
|
propose_transfer, spend,
|
||||||
},
|
},
|
||||||
|
AccountBirthday, WalletWrite,
|
||||||
},
|
},
|
||||||
keys::{sapling, UnifiedFullViewingKey, UnifiedSpendingKey},
|
keys::UnifiedSpendingKey,
|
||||||
proto::compact_formats::{
|
proto::compact_formats::{
|
||||||
self as compact, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
self as compact, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||||
},
|
},
|
||||||
|
@ -37,7 +37,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::{BlockHeight, Network, NetworkUpgrade, Parameters},
|
consensus::{self, BlockHeight, Network, NetworkUpgrade, Parameters},
|
||||||
legacy::TransparentAddress,
|
legacy::TransparentAddress,
|
||||||
memo::MemoBytes,
|
memo::MemoBytes,
|
||||||
sapling::{
|
sapling::{
|
||||||
|
@ -54,54 +54,50 @@ use zcash_primitives::{
|
||||||
zip32::{sapling::DiversifiableFullViewingKey, DiversifierIndex},
|
zip32::{sapling::DiversifiableFullViewingKey, DiversifierIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
use zcash_client_backend::data_api::wallet::{propose_shielding, shield_transparent_funds};
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
use zcash_primitives::{
|
|
||||||
legacy, legacy::keys::IncomingViewingKey, transaction::components::amount::NonNegativeAmount,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chain::init::init_cache_database,
|
chain::init::init_cache_database,
|
||||||
error::SqliteClientError,
|
error::SqliteClientError,
|
||||||
wallet::{
|
wallet::{commitment_tree, init::init_wallet_db, sapling::tests::test_prover},
|
||||||
commitment_tree,
|
|
||||||
init::{init_accounts_table, init_wallet_db},
|
|
||||||
sapling::tests::test_prover,
|
|
||||||
},
|
|
||||||
AccountId, ReceivedNoteId, WalletDb,
|
AccountId, ReceivedNoteId, WalletDb,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::BlockDb;
|
use super::BlockDb;
|
||||||
|
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
use {
|
||||||
|
zcash_client_backend::data_api::wallet::{propose_shielding, shield_transparent_funds},
|
||||||
|
zcash_primitives::transaction::components::amount::NonNegativeAmount,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use crate::{
|
use crate::{
|
||||||
chain::{init::init_blockmeta_db, BlockMeta},
|
chain::{init::init_blockmeta_db, BlockMeta},
|
||||||
FsBlockDb,
|
FsBlockDb,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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,
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
seed: Option<SecretVec<u8>>,
|
test_account_birthday: Option<AccountBirthday>,
|
||||||
with_test_account: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
cache: (),
|
cache: (),
|
||||||
seed: None,
|
test_account_birthday: None,
|
||||||
with_test_account: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a [`BlockDb`] cache to the test.
|
/// Adds a [`BlockDb`] cache to the test.
|
||||||
pub(crate) fn with_block_cache(self) -> TestBuilder<BlockCache> {
|
pub(crate) fn with_block_cache(self) -> TestBuilder<BlockCache> {
|
||||||
TestBuilder {
|
TestBuilder {
|
||||||
|
network: self.network,
|
||||||
cache: BlockCache::new(),
|
cache: BlockCache::new(),
|
||||||
seed: self.seed,
|
test_account_birthday: self.test_account_birthday,
|
||||||
with_test_account: self.with_test_account,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,43 +105,37 @@ impl TestBuilder<()> {
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
pub(crate) fn with_fs_block_cache(self) -> TestBuilder<FsBlockCache> {
|
pub(crate) fn with_fs_block_cache(self) -> TestBuilder<FsBlockCache> {
|
||||||
TestBuilder {
|
TestBuilder {
|
||||||
|
network: self.network,
|
||||||
cache: FsBlockCache::new(),
|
cache: FsBlockCache::new(),
|
||||||
seed: self.seed,
|
test_account_birthday: self.test_account_birthday,
|
||||||
with_test_account: self.with_test_account,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Cache> TestBuilder<Cache> {
|
impl<Cache> TestBuilder<Cache> {
|
||||||
/// Gives the test knowledge of the wallet seed for initialization.
|
pub(crate) fn with_test_account<F: FnOnce(&Network) -> AccountBirthday>(
|
||||||
pub(crate) fn with_seed(mut self, seed: SecretVec<u8>) -> Self {
|
mut self,
|
||||||
// TODO remove
|
birthday: F,
|
||||||
self.seed = Some(seed);
|
) -> Self {
|
||||||
self
|
self.test_account_birthday = Some(birthday(&self.network));
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn with_test_account(mut self) -> Self {
|
|
||||||
self.with_test_account = true;
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the state for this test.
|
/// Builds the state for this test.
|
||||||
pub(crate) fn build(self) -> TestState<Cache> {
|
pub(crate) fn build(self) -> TestState<Cache> {
|
||||||
let params = network();
|
|
||||||
|
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), params).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), self.network).unwrap();
|
||||||
init_wallet_db(&mut db_data, self.seed).unwrap();
|
init_wallet_db(&mut db_data, None).unwrap();
|
||||||
|
|
||||||
let test_account = if self.with_test_account {
|
let test_account = if let Some(birthday) = self.test_account_birthday {
|
||||||
// Add an account to the wallet
|
let seed = Secret::new(vec![0u8; 32]);
|
||||||
Some(init_test_accounts_table_ufvk(&mut db_data))
|
let (account, usk) = db_data.create_account(&seed).unwrap();
|
||||||
|
Some((account, usk, birthday))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
TestState {
|
TestState {
|
||||||
params,
|
|
||||||
cache: self.cache,
|
cache: self.cache,
|
||||||
latest_cached_block: None,
|
latest_cached_block: None,
|
||||||
_data_file: data_file,
|
_data_file: data_file,
|
||||||
|
@ -157,12 +147,11 @@ impl<Cache> TestBuilder<Cache> {
|
||||||
|
|
||||||
/// The state for a `zcash_client_sqlite` test.
|
/// The state for a `zcash_client_sqlite` test.
|
||||||
pub(crate) struct TestState<Cache> {
|
pub(crate) struct TestState<Cache> {
|
||||||
params: Network,
|
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
latest_cached_block: Option<(BlockHeight, BlockHash, u32)>,
|
latest_cached_block: Option<(BlockHeight, BlockHash, u32)>,
|
||||||
_data_file: NamedTempFile,
|
_data_file: NamedTempFile,
|
||||||
db_data: WalletDb<Connection, Network>,
|
db_data: WalletDb<Connection, Network>,
|
||||||
test_account: Option<(UnifiedFullViewingKey, Option<TransparentAddress>)>,
|
test_account: Option<(AccountId, UnifiedSpendingKey, AccountBirthday)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Cache: TestCache> TestState<Cache>
|
impl<Cache: TestCache> TestState<Cache>
|
||||||
|
@ -186,7 +175,7 @@ where
|
||||||
let (height, prev_hash, initial_sapling_tree_size) = self
|
let (height, prev_hash, initial_sapling_tree_size) = self
|
||||||
.latest_cached_block
|
.latest_cached_block
|
||||||
.map(|(prev_height, prev_hash, end_size)| (prev_height + 1, prev_hash, end_size))
|
.map(|(prev_height, prev_hash, end_size)| (prev_height + 1, prev_hash, end_size))
|
||||||
.unwrap_or_else(|| (sapling_activation_height(), BlockHash([0; 32]), 0));
|
.unwrap_or_else(|| (self.sapling_activation_height(), BlockHash([0; 32]), 0));
|
||||||
|
|
||||||
let (res, nf) = self.generate_block_at(
|
let (res, nf) = self.generate_block_at(
|
||||||
height,
|
height,
|
||||||
|
@ -215,6 +204,7 @@ where
|
||||||
initial_sapling_tree_size: u32,
|
initial_sapling_tree_size: u32,
|
||||||
) -> (Cache::InsertResult, Nullifier) {
|
) -> (Cache::InsertResult, Nullifier) {
|
||||||
let (cb, nf) = fake_compact_block(
|
let (cb, nf) = fake_compact_block(
|
||||||
|
&self.network(),
|
||||||
height,
|
height,
|
||||||
prev_hash,
|
prev_hash,
|
||||||
dfvk,
|
dfvk,
|
||||||
|
@ -246,9 +236,10 @@ where
|
||||||
let (height, prev_hash, initial_sapling_tree_size) = self
|
let (height, prev_hash, initial_sapling_tree_size) = self
|
||||||
.latest_cached_block
|
.latest_cached_block
|
||||||
.map(|(prev_height, prev_hash, end_size)| (prev_height + 1, prev_hash, end_size))
|
.map(|(prev_height, prev_hash, end_size)| (prev_height + 1, prev_hash, end_size))
|
||||||
.unwrap_or_else(|| (sapling_activation_height(), BlockHash([0; 32]), 0));
|
.unwrap_or_else(|| (self.sapling_activation_height(), BlockHash([0; 32]), 0));
|
||||||
|
|
||||||
let cb = fake_compact_block_spending(
|
let cb = fake_compact_block_spending(
|
||||||
|
&self.network(),
|
||||||
height,
|
height,
|
||||||
prev_hash,
|
prev_hash,
|
||||||
note,
|
note,
|
||||||
|
@ -271,8 +262,7 @@ where
|
||||||
|
|
||||||
/// Invokes [`scan_cached_blocks`] with the given arguments, expecting success.
|
/// Invokes [`scan_cached_blocks`] with the given arguments, expecting success.
|
||||||
pub(crate) fn scan_cached_blocks(&mut self, from_height: BlockHeight, limit: usize) {
|
pub(crate) fn scan_cached_blocks(&mut self, from_height: BlockHeight, limit: usize) {
|
||||||
self.try_scan_cached_blocks(from_height, limit)
|
assert_matches!(self.try_scan_cached_blocks(from_height, limit), Ok(_));
|
||||||
.expect("should succeed for this test");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes [`scan_cached_blocks`] with the given arguments.
|
/// Invokes [`scan_cached_blocks`] with the given arguments.
|
||||||
|
@ -288,7 +278,7 @@ where
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
scan_cached_blocks(
|
scan_cached_blocks(
|
||||||
&self.params,
|
&self.network(),
|
||||||
self.cache.block_source(),
|
self.cache.block_source(),
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
from_height,
|
from_height,
|
||||||
|
@ -308,11 +298,21 @@ impl<Cache> TestState<Cache> {
|
||||||
&mut self.db_data
|
&mut self.db_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Exposes the network in use.
|
||||||
|
pub(crate) fn network(&self) -> Network {
|
||||||
|
self.db_data.params
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method for obtaining the Sapling activation height for the network under test.
|
||||||
|
pub(crate) fn sapling_activation_height(&self) -> BlockHeight {
|
||||||
|
self.db_data
|
||||||
|
.params
|
||||||
|
.activation_height(NetworkUpgrade::Sapling)
|
||||||
|
.expect("Sapling activation height must be known.")
|
||||||
|
}
|
||||||
|
|
||||||
/// Exposes the test account, if enabled via [`TestBuilder::with_test_account`].
|
/// Exposes the test account, if enabled via [`TestBuilder::with_test_account`].
|
||||||
#[cfg(feature = "unstable")]
|
pub(crate) fn test_account(&self) -> Option<(AccountId, UnifiedSpendingKey, AccountBirthday)> {
|
||||||
pub(crate) fn test_account(
|
|
||||||
&self,
|
|
||||||
) -> Option<(UnifiedFullViewingKey, Option<TransparentAddress>)> {
|
|
||||||
self.test_account.as_ref().cloned()
|
self.test_account.as_ref().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ impl<Cache> TestState<Cache> {
|
||||||
pub(crate) fn test_account_sapling(&self) -> Option<DiversifiableFullViewingKey> {
|
pub(crate) fn test_account_sapling(&self) -> Option<DiversifiableFullViewingKey> {
|
||||||
self.test_account
|
self.test_account
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|(ufvk, _)| ufvk.sapling().unwrap().clone())
|
.and_then(|(_, usk, _)| usk.to_unified_full_viewing_key().sapling().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes [`create_spend_to_address`] with the given arguments.
|
/// Invokes [`create_spend_to_address`] with the given arguments.
|
||||||
|
@ -344,9 +344,10 @@ impl<Cache> TestState<Cache> {
|
||||||
ReceivedNoteId,
|
ReceivedNoteId,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
|
let params = self.network();
|
||||||
create_spend_to_address(
|
create_spend_to_address(
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
&self.params,
|
¶ms,
|
||||||
test_prover(),
|
test_prover(),
|
||||||
usk,
|
usk,
|
||||||
to,
|
to,
|
||||||
|
@ -379,9 +380,10 @@ impl<Cache> TestState<Cache> {
|
||||||
where
|
where
|
||||||
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
||||||
{
|
{
|
||||||
|
let params = self.network();
|
||||||
spend(
|
spend(
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
&self.params,
|
¶ms,
|
||||||
test_prover(),
|
test_prover(),
|
||||||
input_selector,
|
input_selector,
|
||||||
usk,
|
usk,
|
||||||
|
@ -412,9 +414,10 @@ impl<Cache> TestState<Cache> {
|
||||||
where
|
where
|
||||||
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
||||||
{
|
{
|
||||||
|
let params = self.network();
|
||||||
propose_transfer::<_, _, _, Infallible>(
|
propose_transfer::<_, _, _, Infallible>(
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
&self.params,
|
¶ms,
|
||||||
spend_from_account,
|
spend_from_account,
|
||||||
input_selector,
|
input_selector,
|
||||||
request,
|
request,
|
||||||
|
@ -444,9 +447,10 @@ impl<Cache> TestState<Cache> {
|
||||||
where
|
where
|
||||||
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
||||||
{
|
{
|
||||||
|
let params = self.network();
|
||||||
propose_shielding::<_, _, _, Infallible>(
|
propose_shielding::<_, _, _, Infallible>(
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
&self.params,
|
¶ms,
|
||||||
input_selector,
|
input_selector,
|
||||||
shielding_threshold,
|
shielding_threshold,
|
||||||
from_addrs,
|
from_addrs,
|
||||||
|
@ -475,9 +479,10 @@ impl<Cache> TestState<Cache> {
|
||||||
where
|
where
|
||||||
FeeRuleT: FeeRule,
|
FeeRuleT: FeeRule,
|
||||||
{
|
{
|
||||||
|
let params = self.network();
|
||||||
create_proposed_transaction::<_, _, Infallible, _>(
|
create_proposed_transaction::<_, _, Infallible, _>(
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
&self.params,
|
¶ms,
|
||||||
test_prover(),
|
test_prover(),
|
||||||
usk,
|
usk,
|
||||||
ovk_policy,
|
ovk_policy,
|
||||||
|
@ -511,9 +516,10 @@ impl<Cache> TestState<Cache> {
|
||||||
where
|
where
|
||||||
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
InputsT: InputSelector<DataSource = WalletDb<Connection, Network>>,
|
||||||
{
|
{
|
||||||
|
let params = self.network();
|
||||||
shield_transparent_funds(
|
shield_transparent_funds(
|
||||||
&mut self.db_data,
|
&mut self.db_data,
|
||||||
&self.params,
|
¶ms,
|
||||||
test_prover(),
|
test_prover(),
|
||||||
input_selector,
|
input_selector,
|
||||||
shielding_threshold,
|
shielding_threshold,
|
||||||
|
@ -525,63 +531,15 @@ impl<Cache> TestState<Cache> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mainnet")]
|
|
||||||
pub(crate) fn network() -> Network {
|
|
||||||
Network::MainNetwork
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mainnet"))]
|
|
||||||
pub(crate) fn network() -> Network {
|
|
||||||
Network::TestNetwork
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "mainnet")]
|
|
||||||
pub(crate) fn sapling_activation_height() -> BlockHeight {
|
|
||||||
Network::MainNetwork
|
|
||||||
.activation_height(NetworkUpgrade::Sapling)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mainnet"))]
|
|
||||||
pub(crate) fn sapling_activation_height() -> BlockHeight {
|
|
||||||
Network::TestNetwork
|
|
||||||
.activation_height(NetworkUpgrade::Sapling)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn init_test_accounts_table_ufvk(
|
pub(crate) fn birthday_at_sapling_activation<P: consensus::Parameters>(
|
||||||
db_data: &mut WalletDb<rusqlite::Connection, Network>,
|
params: &P,
|
||||||
) -> (UnifiedFullViewingKey, Option<TransparentAddress>) {
|
) -> AccountBirthday {
|
||||||
let seed = [0u8; 32];
|
use incrementalmerkletree::frontier::Frontier;
|
||||||
let account = AccountId::from(0);
|
AccountBirthday::from_parts(
|
||||||
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
params.activation_height(NetworkUpgrade::Sapling).unwrap(),
|
||||||
let dfvk = extsk.to_diversifiable_full_viewing_key();
|
Frontier::empty(),
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
let (tkey, taddr) = {
|
|
||||||
let tkey = legacy::keys::AccountPrivKey::from_seed(&network(), &seed, account)
|
|
||||||
.unwrap()
|
|
||||||
.to_account_pubkey();
|
|
||||||
let taddr = tkey.derive_external_ivk().unwrap().default_address().0;
|
|
||||||
(Some(tkey), Some(taddr))
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
|
||||||
let taddr = None;
|
|
||||||
|
|
||||||
let ufvk = UnifiedFullViewingKey::new(
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
tkey,
|
|
||||||
Some(dfvk),
|
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let ufvks = HashMap::from([(account, ufvk.clone())]);
|
|
||||||
init_accounts_table(db_data, &ufvks).unwrap();
|
|
||||||
|
|
||||||
(ufvk, taddr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -593,7 +551,8 @@ pub(crate) enum AddressType {
|
||||||
|
|
||||||
/// Create a fake CompactBlock at the given height, containing a single output paying
|
/// Create a fake CompactBlock at the given height, containing a single output paying
|
||||||
/// an address. Returns the CompactBlock and the nullifier for the new note.
|
/// an address. Returns the CompactBlock and the nullifier for the new note.
|
||||||
pub(crate) fn fake_compact_block(
|
pub(crate) fn fake_compact_block<P: consensus::Parameters>(
|
||||||
|
params: &P,
|
||||||
height: BlockHeight,
|
height: BlockHeight,
|
||||||
prev_hash: BlockHash,
|
prev_hash: BlockHash,
|
||||||
dfvk: &DiversifiableFullViewingKey,
|
dfvk: &DiversifiableFullViewingKey,
|
||||||
|
@ -609,7 +568,7 @@ pub(crate) fn fake_compact_block(
|
||||||
|
|
||||||
// Create a fake Note for the account
|
// Create a fake Note for the account
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let rseed = generate_random_rseed(&network(), height, &mut rng);
|
let rseed = generate_random_rseed(params, height, &mut rng);
|
||||||
let note = Note::from_parts(to, NoteValue::from_raw(value.into()), rseed);
|
let note = Note::from_parts(to, NoteValue::from_raw(value.into()), rseed);
|
||||||
let encryptor = sapling_note_encryption::<_, Network>(
|
let encryptor = sapling_note_encryption::<_, Network>(
|
||||||
Some(dfvk.fvk().ovk),
|
Some(dfvk.fvk().ovk),
|
||||||
|
@ -655,7 +614,9 @@ pub(crate) fn fake_compact_block(
|
||||||
|
|
||||||
/// Create a fake CompactBlock at the given height, spending a single note from the
|
/// Create a fake CompactBlock at the given height, spending a single note from the
|
||||||
/// given address.
|
/// given address.
|
||||||
pub(crate) fn fake_compact_block_spending(
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub(crate) fn fake_compact_block_spending<P: consensus::Parameters>(
|
||||||
|
params: &P,
|
||||||
height: BlockHeight,
|
height: BlockHeight,
|
||||||
prev_hash: BlockHash,
|
prev_hash: BlockHash,
|
||||||
(nf, in_value): (Nullifier, Amount),
|
(nf, in_value): (Nullifier, Amount),
|
||||||
|
@ -665,7 +626,7 @@ pub(crate) fn fake_compact_block_spending(
|
||||||
initial_sapling_tree_size: u32,
|
initial_sapling_tree_size: u32,
|
||||||
) -> CompactBlock {
|
) -> CompactBlock {
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let rseed = generate_random_rseed(&network(), height, &mut rng);
|
let rseed = generate_random_rseed(params, height, &mut rng);
|
||||||
|
|
||||||
// Create a fake CompactBlock containing the note
|
// Create a fake CompactBlock containing the note
|
||||||
let cspend = CompactSaplingSpend { nf: nf.to_vec() };
|
let cspend = CompactSaplingSpend { nf: nf.to_vec() };
|
||||||
|
@ -700,7 +661,7 @@ pub(crate) fn fake_compact_block_spending(
|
||||||
// Create a fake Note for the change
|
// Create a fake Note for the change
|
||||||
ctx.outputs.push({
|
ctx.outputs.push({
|
||||||
let change_addr = dfvk.default_address().1;
|
let change_addr = dfvk.default_address().1;
|
||||||
let rseed = generate_random_rseed(&network(), height, &mut rng);
|
let rseed = generate_random_rseed(params, height, &mut rng);
|
||||||
let note = Note::from_parts(
|
let note = Note::from_parts(
|
||||||
change_addr,
|
change_addr,
|
||||||
NoteValue::from_raw((in_value - value).unwrap().into()),
|
NoteValue::from_raw((in_value - value).unwrap().into()),
|
||||||
|
|
|
@ -1577,7 +1577,10 @@ mod tests {
|
||||||
|
|
||||||
use zcash_client_backend::data_api::WalletRead;
|
use zcash_client_backend::data_api::WalletRead;
|
||||||
|
|
||||||
use crate::{testing::TestBuilder, AccountId};
|
use crate::{
|
||||||
|
testing::{birthday_at_sapling_activation, TestBuilder},
|
||||||
|
AccountId,
|
||||||
|
};
|
||||||
|
|
||||||
use super::get_balance;
|
use super::get_balance;
|
||||||
|
|
||||||
|
@ -1595,8 +1598,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_database_has_no_balance() {
|
fn empty_database_has_no_balance() {
|
||||||
let st = TestBuilder::new()
|
let st = TestBuilder::new()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// The account should be empty
|
// The account should be empty
|
||||||
|
|
|
@ -985,14 +985,14 @@ mod tests {
|
||||||
};
|
};
|
||||||
use shardtree::ShardTree;
|
use shardtree::ShardTree;
|
||||||
use zcash_client_backend::data_api::chain::CommitmentTreeRoot;
|
use zcash_client_backend::data_api::chain::CommitmentTreeRoot;
|
||||||
use zcash_primitives::consensus::BlockHeight;
|
use zcash_primitives::consensus::{BlockHeight, Network};
|
||||||
|
|
||||||
use super::SqliteShardStore;
|
use super::SqliteShardStore;
|
||||||
use crate::{testing, wallet::init::init_wallet_db, WalletDb, SAPLING_TABLES_PREFIX};
|
use crate::{wallet::init::init_wallet_db, WalletDb, SAPLING_TABLES_PREFIX};
|
||||||
|
|
||||||
fn new_tree(m: usize) -> ShardTree<SqliteShardStore<rusqlite::Connection, String, 3>, 4, 3> {
|
fn new_tree(m: usize) -> ShardTree<SqliteShardStore<rusqlite::Connection, String, 3>, 4, 3> {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
data_file.keep().unwrap();
|
data_file.keep().unwrap();
|
||||||
|
|
||||||
init_wallet_db(&mut db_data, None).unwrap();
|
init_wallet_db(&mut db_data, None).unwrap();
|
||||||
|
@ -1040,7 +1040,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn put_shard_roots() {
|
fn put_shard_roots() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
data_file.keep().unwrap();
|
data_file.keep().unwrap();
|
||||||
|
|
||||||
init_wallet_db(&mut db_data, None).unwrap();
|
init_wallet_db(&mut db_data, None).unwrap();
|
||||||
|
|
|
@ -386,37 +386,29 @@ mod tests {
|
||||||
|
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
consensus::{BlockHeight, BranchId, NetworkUpgrade, Parameters},
|
consensus::{self, BlockHeight, BranchId, Network, NetworkUpgrade, Parameters},
|
||||||
transaction::{TransactionData, TxVersion},
|
transaction::{TransactionData, TxVersion},
|
||||||
zip32::sapling::ExtendedFullViewingKey,
|
zip32::sapling::ExtendedFullViewingKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::SqliteClientError,
|
error::SqliteClientError, testing::TestBuilder, wallet::scanning::priority_code, AccountId,
|
||||||
testing::{self, network},
|
WalletDb,
|
||||||
wallet::scanning::priority_code,
|
|
||||||
AccountId, WalletDb,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{init_accounts_table, init_blocks_table, init_wallet_db};
|
use super::{init_accounts_table, init_blocks_table, init_wallet_db};
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::wallet::{self, pool_code, PoolType},
|
||||||
wallet::{self, pool_code, PoolType},
|
|
||||||
WalletWrite,
|
|
||||||
},
|
|
||||||
zcash_address::test_vectors,
|
zcash_address::test_vectors,
|
||||||
zcash_primitives::{
|
zcash_client_backend::data_api::WalletWrite,
|
||||||
consensus::Network, legacy::keys as transparent, zip32::DiversifierIndex,
|
zcash_primitives::{legacy::keys as transparent, zip32::DiversifierIndex},
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_schema() {
|
fn verify_schema() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let st = TestBuilder::new().build();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
|
||||||
init_wallet_db(&mut db_data, None).unwrap();
|
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
let re = Regex::new(r"\s+").unwrap();
|
let re = Regex::new(r"\s+").unwrap();
|
||||||
|
@ -569,7 +561,8 @@ mod tests {
|
||||||
)",
|
)",
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut tables_query = db_data
|
let mut tables_query = st
|
||||||
|
.wallet()
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT sql FROM sqlite_schema WHERE type = 'table' ORDER BY tbl_name")
|
.prepare("SELECT sql FROM sqlite_schema WHERE type = 'table' ORDER BY tbl_name")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -609,7 +602,7 @@ mod tests {
|
||||||
AND (scan_queue.block_range_end - 1) >= shard.subtree_end_height
|
AND (scan_queue.block_range_end - 1) >= shard.subtree_end_height
|
||||||
)
|
)
|
||||||
WHERE scan_queue.priority > {}",
|
WHERE scan_queue.priority > {}",
|
||||||
u32::from(testing::network().activation_height(NetworkUpgrade::Sapling).unwrap()),
|
u32::from(st.network().activation_height(NetworkUpgrade::Sapling).unwrap()),
|
||||||
priority_code(&ScanPriority::Scanned),
|
priority_code(&ScanPriority::Scanned),
|
||||||
),
|
),
|
||||||
// v_transactions
|
// v_transactions
|
||||||
|
@ -750,7 +743,8 @@ mod tests {
|
||||||
OR sapling_received_notes.is_change = 0".to_owned(),
|
OR sapling_received_notes.is_change = 0".to_owned(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut views_query = db_data
|
let mut views_query = st
|
||||||
|
.wallet()
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT sql FROM sqlite_schema WHERE type = 'view' ORDER BY tbl_name")
|
.prepare("SELECT sql FROM sqlite_schema WHERE type = 'view' ORDER BY tbl_name")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -768,7 +762,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_migrate_from_0_3_0() {
|
fn init_migrate_from_0_3_0() {
|
||||||
fn init_0_3_0<P>(
|
fn init_0_3_0<P: consensus::Parameters>(
|
||||||
wdb: &mut WalletDb<rusqlite::Connection, P>,
|
wdb: &mut WalletDb<rusqlite::Connection, P>,
|
||||||
extfvk: &ExtendedFullViewingKey,
|
extfvk: &ExtendedFullViewingKey,
|
||||||
account: AccountId,
|
account: AccountId,
|
||||||
|
@ -852,11 +846,11 @@ mod tests {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let address = encode_payment_address(
|
let address = encode_payment_address(
|
||||||
testing::network().hrp_sapling_payment_address(),
|
wdb.params.hrp_sapling_payment_address(),
|
||||||
&extfvk.default_address().1,
|
&extfvk.default_address().1,
|
||||||
);
|
);
|
||||||
let extfvk = encode_extended_full_viewing_key(
|
let extfvk = encode_extended_full_viewing_key(
|
||||||
testing::network().hrp_sapling_extended_full_viewing_key(),
|
wdb.params.hrp_sapling_extended_full_viewing_key(),
|
||||||
extfvk,
|
extfvk,
|
||||||
);
|
);
|
||||||
wdb.conn.execute(
|
wdb.conn.execute(
|
||||||
|
@ -872,19 +866,21 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
|
|
||||||
let seed = [0xab; 32];
|
let seed = [0xab; 32];
|
||||||
let account = AccountId::from(0);
|
let account = AccountId::from(0);
|
||||||
let secret_key = sapling::spending_key(&seed, testing::network().coin_type(), account);
|
let secret_key = sapling::spending_key(&seed, db_data.params.coin_type(), account);
|
||||||
let extfvk = secret_key.to_extended_full_viewing_key();
|
let extfvk = secret_key.to_extended_full_viewing_key();
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
|
||||||
init_0_3_0(&mut db_data, &extfvk, account).unwrap();
|
init_0_3_0(&mut db_data, &extfvk, account).unwrap();
|
||||||
init_wallet_db(&mut db_data, Some(Secret::new(seed.to_vec()))).unwrap();
|
init_wallet_db(&mut db_data, Some(Secret::new(seed.to_vec()))).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_migrate_from_autoshielding_poc() {
|
fn init_migrate_from_autoshielding_poc() {
|
||||||
fn init_autoshielding<P>(
|
fn init_autoshielding<P: consensus::Parameters>(
|
||||||
wdb: &mut WalletDb<rusqlite::Connection, P>,
|
wdb: &mut WalletDb<rusqlite::Connection, P>,
|
||||||
extfvk: &ExtendedFullViewingKey,
|
extfvk: &ExtendedFullViewingKey,
|
||||||
account: AccountId,
|
account: AccountId,
|
||||||
|
@ -984,11 +980,11 @@ mod tests {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let address = encode_payment_address(
|
let address = encode_payment_address(
|
||||||
testing::network().hrp_sapling_payment_address(),
|
wdb.params.hrp_sapling_payment_address(),
|
||||||
&extfvk.default_address().1,
|
&extfvk.default_address().1,
|
||||||
);
|
);
|
||||||
let extfvk = encode_extended_full_viewing_key(
|
let extfvk = encode_extended_full_viewing_key(
|
||||||
testing::network().hrp_sapling_extended_full_viewing_key(),
|
wdb.params.hrp_sapling_extended_full_viewing_key(),
|
||||||
extfvk,
|
extfvk,
|
||||||
);
|
);
|
||||||
wdb.conn.execute(
|
wdb.conn.execute(
|
||||||
|
@ -1038,19 +1034,21 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
|
|
||||||
let seed = [0xab; 32];
|
let seed = [0xab; 32];
|
||||||
let account = AccountId::from(0);
|
let account = AccountId::from(0);
|
||||||
let secret_key = sapling::spending_key(&seed, testing::network().coin_type(), account);
|
let secret_key = sapling::spending_key(&seed, db_data.params.coin_type(), account);
|
||||||
let extfvk = secret_key.to_extended_full_viewing_key();
|
let extfvk = secret_key.to_extended_full_viewing_key();
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
|
||||||
init_autoshielding(&mut db_data, &extfvk, account).unwrap();
|
init_autoshielding(&mut db_data, &extfvk, account).unwrap();
|
||||||
init_wallet_db(&mut db_data, Some(Secret::new(seed.to_vec()))).unwrap();
|
init_wallet_db(&mut db_data, Some(Secret::new(seed.to_vec()))).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_migrate_from_main_pre_migrations() {
|
fn init_migrate_from_main_pre_migrations() {
|
||||||
fn init_main<P>(
|
fn init_main<P: consensus::Parameters>(
|
||||||
wdb: &mut WalletDb<rusqlite::Connection, P>,
|
wdb: &mut WalletDb<rusqlite::Connection, P>,
|
||||||
ufvk: &UnifiedFullViewingKey,
|
ufvk: &UnifiedFullViewingKey,
|
||||||
account: AccountId,
|
account: AccountId,
|
||||||
|
@ -1150,9 +1148,9 @@ mod tests {
|
||||||
[],
|
[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let ufvk_str = ufvk.encode(&testing::network());
|
let ufvk_str = ufvk.encode(&wdb.params);
|
||||||
let address_str =
|
let address_str =
|
||||||
RecipientAddress::Unified(ufvk.default_address().0).encode(&testing::network());
|
RecipientAddress::Unified(ufvk.default_address().0).encode(&wdb.params);
|
||||||
wdb.conn.execute(
|
wdb.conn.execute(
|
||||||
"INSERT INTO accounts (account, ufvk, address, transparent_address)
|
"INSERT INTO accounts (account, ufvk, address, transparent_address)
|
||||||
VALUES (?, ?, ?, '')",
|
VALUES (?, ?, ?, '')",
|
||||||
|
@ -1168,7 +1166,7 @@ mod tests {
|
||||||
{
|
{
|
||||||
let taddr =
|
let taddr =
|
||||||
RecipientAddress::Transparent(*ufvk.default_address().0.transparent().unwrap())
|
RecipientAddress::Transparent(*ufvk.default_address().0.transparent().unwrap())
|
||||||
.encode(&testing::network());
|
.encode(&wdb.params);
|
||||||
wdb.conn.execute(
|
wdb.conn.execute(
|
||||||
"INSERT INTO blocks (height, hash, time, sapling_tree) VALUES (0, 0, 0, x'000000')",
|
"INSERT INTO blocks (height, hash, time, sapling_tree) VALUES (0, 0, 0, x'000000')",
|
||||||
[],
|
[],
|
||||||
|
@ -1186,12 +1184,13 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
|
|
||||||
let seed = [0xab; 32];
|
let seed = [0xab; 32];
|
||||||
let account = AccountId::from(0);
|
let account = AccountId::from(0);
|
||||||
let secret_key =
|
let secret_key = UnifiedSpendingKey::from_seed(&db_data.params, &seed, account).unwrap();
|
||||||
UnifiedSpendingKey::from_seed(&testing::network(), &seed, account).unwrap();
|
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
|
||||||
init_main(
|
init_main(
|
||||||
&mut db_data,
|
&mut db_data,
|
||||||
&secret_key.to_unified_full_viewing_key(),
|
&secret_key.to_unified_full_viewing_key(),
|
||||||
|
@ -1204,7 +1203,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn init_accounts_table_only_works_once() {
|
fn init_accounts_table_only_works_once() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap();
|
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap();
|
||||||
|
|
||||||
// We can call the function as many times as we want with no data
|
// We can call the function as many times as we want with no data
|
||||||
|
@ -1215,13 +1214,13 @@ mod tests {
|
||||||
let account = AccountId::from(0);
|
let account = AccountId::from(0);
|
||||||
|
|
||||||
// First call with data should initialise the accounts table
|
// First call with data should initialise the accounts table
|
||||||
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
let extsk = sapling::spending_key(&seed, db_data.params.coin_type(), account);
|
||||||
let dfvk = extsk.to_diversifiable_full_viewing_key();
|
let dfvk = extsk.to_diversifiable_full_viewing_key();
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(
|
let ufvk = UnifiedFullViewingKey::new(
|
||||||
Some(
|
Some(
|
||||||
transparent::AccountPrivKey::from_seed(&network(), &seed, account)
|
transparent::AccountPrivKey::from_seed(&db_data.params, &seed, account)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_account_pubkey(),
|
.to_account_pubkey(),
|
||||||
),
|
),
|
||||||
|
@ -1243,8 +1242,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_accounts_table_allows_no_gaps() {
|
fn init_accounts_table_allows_no_gaps() {
|
||||||
|
let params = Network::TestNetwork;
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), params).unwrap();
|
||||||
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap();
|
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap();
|
||||||
|
|
||||||
// allow sequential initialization
|
// allow sequential initialization
|
||||||
|
@ -1253,7 +1253,7 @@ mod tests {
|
||||||
ids.iter()
|
ids.iter()
|
||||||
.map(|a| {
|
.map(|a| {
|
||||||
let account = AccountId::from(*a);
|
let account = AccountId::from(*a);
|
||||||
UnifiedSpendingKey::from_seed(&network(), &seed, account)
|
UnifiedSpendingKey::from_seed(¶ms, &seed, account)
|
||||||
.map(|k| (account, k.to_unified_full_viewing_key()))
|
.map(|k| (account, k.to_unified_full_viewing_key()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
|
@ -1273,7 +1273,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn init_blocks_table_only_works_once() {
|
fn init_blocks_table_only_works_once() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap();
|
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap();
|
||||||
|
|
||||||
// First call with data should initialise the blocks table
|
// First call with data should initialise the blocks table
|
||||||
|
@ -1300,14 +1300,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn init_accounts_table_stores_correct_address() {
|
fn init_accounts_table_stores_correct_address() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
init_wallet_db(&mut db_data, None).unwrap();
|
init_wallet_db(&mut db_data, None).unwrap();
|
||||||
|
|
||||||
let seed = [0u8; 32];
|
let seed = [0u8; 32];
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let account_id = AccountId::from(0);
|
let account_id = AccountId::from(0);
|
||||||
let usk = UnifiedSpendingKey::from_seed(&testing::network(), &seed, account_id).unwrap();
|
let usk = UnifiedSpendingKey::from_seed(&db_data.params, &seed, account_id).unwrap();
|
||||||
let ufvk = usk.to_unified_full_viewing_key();
|
let ufvk = usk.to_unified_full_viewing_key();
|
||||||
let expected_address = ufvk.sapling().unwrap().default_address().1;
|
let expected_address = ufvk.sapling().unwrap().default_address().1;
|
||||||
let ufvks = HashMap::from([(account_id, ufvk)]);
|
let ufvks = HashMap::from([(account_id, ufvk)]);
|
||||||
|
|
|
@ -283,10 +283,9 @@ mod tests {
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
use zcash_client_backend::keys::UnifiedSpendingKey;
|
use zcash_client_backend::keys::UnifiedSpendingKey;
|
||||||
use zcash_primitives::zip32::AccountId;
|
use zcash_primitives::{consensus::Network, zip32::AccountId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
testing,
|
|
||||||
wallet::init::{init_wallet_db_internal, migrations::addresses_table},
|
wallet::init::{init_wallet_db_internal, migrations::addresses_table},
|
||||||
WalletDb,
|
WalletDb,
|
||||||
};
|
};
|
||||||
|
@ -310,19 +309,19 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn transaction_views() {
|
fn transaction_views() {
|
||||||
|
let network = Network::TestNetwork;
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), network).unwrap();
|
||||||
init_wallet_db_internal(&mut db_data, None, &[addresses_table::MIGRATION_ID]).unwrap();
|
init_wallet_db_internal(&mut db_data, None, &[addresses_table::MIGRATION_ID]).unwrap();
|
||||||
let usk =
|
let usk =
|
||||||
UnifiedSpendingKey::from_seed(&testing::network(), &[0u8; 32][..], AccountId::from(0))
|
UnifiedSpendingKey::from_seed(&network, &[0u8; 32][..], AccountId::from(0)).unwrap();
|
||||||
.unwrap();
|
|
||||||
let ufvk = usk.to_unified_full_viewing_key();
|
let ufvk = usk.to_unified_full_viewing_key();
|
||||||
|
|
||||||
db_data
|
db_data
|
||||||
.conn
|
.conn
|
||||||
.execute(
|
.execute(
|
||||||
"INSERT INTO accounts (account, ufvk) VALUES (0, ?)",
|
"INSERT INTO accounts (account, ufvk) VALUES (0, ?)",
|
||||||
params![ufvk.encode(&testing::network())],
|
params![ufvk.encode(&network)],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -402,8 +401,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
fn migrate_from_wm2() {
|
fn migrate_from_wm2() {
|
||||||
|
let network = Network::TestNetwork;
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), network).unwrap();
|
||||||
init_wallet_db_internal(
|
init_wallet_db_internal(
|
||||||
&mut db_data,
|
&mut db_data,
|
||||||
None,
|
None,
|
||||||
|
@ -440,8 +440,7 @@ mod tests {
|
||||||
tx.write(&mut tx_bytes).unwrap();
|
tx.write(&mut tx_bytes).unwrap();
|
||||||
|
|
||||||
let usk =
|
let usk =
|
||||||
UnifiedSpendingKey::from_seed(&testing::network(), &[0u8; 32][..], AccountId::from(0))
|
UnifiedSpendingKey::from_seed(&network, &[0u8; 32][..], AccountId::from(0)).unwrap();
|
||||||
.unwrap();
|
|
||||||
let ufvk = usk.to_unified_full_viewing_key();
|
let ufvk = usk.to_unified_full_viewing_key();
|
||||||
let (ua, _) = ufvk.default_address();
|
let (ua, _) = ufvk.default_address();
|
||||||
let taddr = ufvk
|
let taddr = ufvk
|
||||||
|
@ -451,11 +450,11 @@ mod tests {
|
||||||
.ok()
|
.ok()
|
||||||
.map(|k| k.derive_address(0).unwrap())
|
.map(|k| k.derive_address(0).unwrap())
|
||||||
})
|
})
|
||||||
.map(|a| a.encode(&testing::network()));
|
.map(|a| a.encode(&network));
|
||||||
|
|
||||||
db_data.conn.execute(
|
db_data.conn.execute(
|
||||||
"INSERT INTO accounts (account, ufvk, address, transparent_address) VALUES (0, ?, ?, ?)",
|
"INSERT INTO accounts (account, ufvk, address, transparent_address) VALUES (0, ?, ?, ?)",
|
||||||
params![ufvk.encode(&testing::network()), ua.encode(&testing::network()), &taddr]
|
params![ufvk.encode(&network), ua.encode(&network), &taddr]
|
||||||
).unwrap();
|
).unwrap();
|
||||||
db_data
|
db_data
|
||||||
.conn
|
.conn
|
||||||
|
|
|
@ -233,10 +233,9 @@ mod tests {
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
use zcash_client_backend::keys::UnifiedSpendingKey;
|
use zcash_client_backend::keys::UnifiedSpendingKey;
|
||||||
use zcash_primitives::zip32::AccountId;
|
use zcash_primitives::{consensus::Network, zip32::AccountId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
testing,
|
|
||||||
wallet::init::{init_wallet_db_internal, migrations::v_transactions_net},
|
wallet::init::{init_wallet_db_internal, migrations::v_transactions_net},
|
||||||
WalletDb,
|
WalletDb,
|
||||||
};
|
};
|
||||||
|
@ -244,19 +243,19 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn received_notes_nullable_migration() {
|
fn received_notes_nullable_migration() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
init_wallet_db_internal(&mut db_data, None, &[v_transactions_net::MIGRATION_ID]).unwrap();
|
init_wallet_db_internal(&mut db_data, None, &[v_transactions_net::MIGRATION_ID]).unwrap();
|
||||||
|
|
||||||
// Create an account in the wallet
|
// Create an account in the wallet
|
||||||
let usk0 =
|
let usk0 =
|
||||||
UnifiedSpendingKey::from_seed(&testing::network(), &[0u8; 32][..], AccountId::from(0))
|
UnifiedSpendingKey::from_seed(&db_data.params, &[0u8; 32][..], AccountId::from(0))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ufvk0 = usk0.to_unified_full_viewing_key();
|
let ufvk0 = usk0.to_unified_full_viewing_key();
|
||||||
db_data
|
db_data
|
||||||
.conn
|
.conn
|
||||||
.execute(
|
.execute(
|
||||||
"INSERT INTO accounts (account, ufvk) VALUES (0, ?)",
|
"INSERT INTO accounts (account, ufvk) VALUES (0, ?)",
|
||||||
params![ufvk0.encode(&testing::network())],
|
params![ufvk0.encode(&db_data.params)],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -212,10 +212,9 @@ mod tests {
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
use zcash_client_backend::keys::UnifiedSpendingKey;
|
use zcash_client_backend::keys::UnifiedSpendingKey;
|
||||||
use zcash_primitives::zip32::AccountId;
|
use zcash_primitives::{consensus::Network, zip32::AccountId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
testing,
|
|
||||||
wallet::init::{init_wallet_db_internal, migrations::add_transaction_views},
|
wallet::init::{init_wallet_db_internal, migrations::add_transaction_views},
|
||||||
WalletDb,
|
WalletDb,
|
||||||
};
|
};
|
||||||
|
@ -223,32 +222,32 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn v_transactions_net() {
|
fn v_transactions_net() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
let data_file = NamedTempFile::new().unwrap();
|
||||||
let mut db_data = WalletDb::for_path(data_file.path(), testing::network()).unwrap();
|
let mut db_data = WalletDb::for_path(data_file.path(), Network::TestNetwork).unwrap();
|
||||||
init_wallet_db_internal(&mut db_data, None, &[add_transaction_views::MIGRATION_ID])
|
init_wallet_db_internal(&mut db_data, None, &[add_transaction_views::MIGRATION_ID])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create two accounts in the wallet.
|
// Create two accounts in the wallet.
|
||||||
let usk0 =
|
let usk0 =
|
||||||
UnifiedSpendingKey::from_seed(&testing::network(), &[0u8; 32][..], AccountId::from(0))
|
UnifiedSpendingKey::from_seed(&db_data.params, &[0u8; 32][..], AccountId::from(0))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ufvk0 = usk0.to_unified_full_viewing_key();
|
let ufvk0 = usk0.to_unified_full_viewing_key();
|
||||||
db_data
|
db_data
|
||||||
.conn
|
.conn
|
||||||
.execute(
|
.execute(
|
||||||
"INSERT INTO accounts (account, ufvk) VALUES (0, ?)",
|
"INSERT INTO accounts (account, ufvk) VALUES (0, ?)",
|
||||||
params![ufvk0.encode(&testing::network())],
|
params![ufvk0.encode(&db_data.params)],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let usk1 =
|
let usk1 =
|
||||||
UnifiedSpendingKey::from_seed(&testing::network(), &[1u8; 32][..], AccountId::from(1))
|
UnifiedSpendingKey::from_seed(&db_data.params, &[1u8; 32][..], AccountId::from(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ufvk1 = usk1.to_unified_full_viewing_key();
|
let ufvk1 = usk1.to_unified_full_viewing_key();
|
||||||
db_data
|
db_data
|
||||||
.conn
|
.conn
|
||||||
.execute(
|
.execute(
|
||||||
"INSERT INTO accounts (account, ufvk) VALUES (1, ?)",
|
"INSERT INTO accounts (account, ufvk) VALUES (1, ?)",
|
||||||
params![ufvk1.encode(&testing::network())],
|
params![ufvk1.encode(&db_data.params)],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -439,7 +439,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::SqliteClientError,
|
error::SqliteClientError,
|
||||||
testing::{self, network, AddressType, BlockCache, TestBuilder, TestState},
|
testing::{AddressType, BlockCache, TestBuilder, TestState},
|
||||||
wallet::{commitment_tree, get_balance, get_balance_at},
|
wallet::{commitment_tree, get_balance, get_balance_at},
|
||||||
AccountId, NoteId, ReceivedNoteId,
|
AccountId, NoteId, ReceivedNoteId,
|
||||||
};
|
};
|
||||||
|
@ -532,7 +532,7 @@ pub(crate) mod tests {
|
||||||
let ufvks = [(account, usk.to_unified_full_viewing_key())]
|
let ufvks = [(account, usk.to_unified_full_viewing_key())]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
let decrypted_outputs = decrypt_transaction(&testing::network(), h + 1, &tx, &ufvks);
|
let decrypted_outputs = decrypt_transaction(&st.network(), h + 1, &tx, &ufvks);
|
||||||
assert_eq!(decrypted_outputs.len(), 2);
|
assert_eq!(decrypted_outputs.len(), 2);
|
||||||
|
|
||||||
let mut found_tx_change_memo = false;
|
let mut found_tx_change_memo = false;
|
||||||
|
@ -609,7 +609,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_to_address_fails_on_incorrect_usk() {
|
fn create_to_address_fails_on_incorrect_usk() {
|
||||||
let mut st = TestBuilder::new().with_seed(Secret::new(vec![])).build();
|
let mut st = TestBuilder::new().build();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let seed = Secret::new([0u8; 32].to_vec());
|
let seed = Secret::new([0u8; 32].to_vec());
|
||||||
|
@ -619,7 +619,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
// Create a USK that doesn't exist in the wallet
|
// Create a USK that doesn't exist in the wallet
|
||||||
let acct1 = AccountId::from(1);
|
let acct1 = AccountId::from(1);
|
||||||
let usk1 = UnifiedSpendingKey::from_seed(&network(), &[1u8; 32], acct1).unwrap();
|
let usk1 = UnifiedSpendingKey::from_seed(&st.network(), &[1u8; 32], acct1).unwrap();
|
||||||
|
|
||||||
// Attempting to spend with a USK that is not in the wallet results in an error
|
// Attempting to spend with a USK that is not in the wallet results in an error
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
|
@ -778,10 +778,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_to_address_fails_on_locked_notes() {
|
fn create_to_address_fails_on_locked_notes() {
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new().with_block_cache().build();
|
||||||
.with_block_cache()
|
|
||||||
.with_seed(Secret::new(vec![]))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let seed = Secret::new([0u8; 32].to_vec());
|
let seed = Secret::new([0u8; 32].to_vec());
|
||||||
|
@ -900,7 +897,7 @@ pub(crate) mod tests {
|
||||||
let to = addr2.into();
|
let to = addr2.into();
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
let send_and_recover_with_policy = |test: &mut TestState<BlockCache>,
|
let send_and_recover_with_policy = |st: &mut TestState<BlockCache>,
|
||||||
ovk_policy|
|
ovk_policy|
|
||||||
-> Result<
|
-> Result<
|
||||||
Option<(Note, PaymentAddress, MemoBytes)>,
|
Option<(Note, PaymentAddress, MemoBytes)>,
|
||||||
|
@ -912,7 +909,7 @@ pub(crate) mod tests {
|
||||||
ReceivedNoteId,
|
ReceivedNoteId,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
let txid = test.create_spend_to_address(
|
let txid = st.create_spend_to_address(
|
||||||
&usk,
|
&usk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(15000).unwrap(),
|
Amount::from_u64(15000).unwrap(),
|
||||||
|
@ -922,7 +919,7 @@ pub(crate) mod tests {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Fetch the transaction from the database
|
// Fetch the transaction from the database
|
||||||
let raw_tx: Vec<_> = test
|
let raw_tx: Vec<_> = st
|
||||||
.wallet()
|
.wallet()
|
||||||
.conn
|
.conn
|
||||||
.query_row(
|
.query_row(
|
||||||
|
@ -937,7 +934,7 @@ pub(crate) mod tests {
|
||||||
for output in tx.sapling_bundle().unwrap().shielded_outputs() {
|
for output in tx.sapling_bundle().unwrap().shielded_outputs() {
|
||||||
// Find the output that decrypts with the external OVK
|
// Find the output that decrypts with the external OVK
|
||||||
let result = try_sapling_output_recovery(
|
let result = try_sapling_output_recovery(
|
||||||
&network(),
|
&st.network(),
|
||||||
h1,
|
h1,
|
||||||
&dfvk.to_ovk(Scope::External),
|
&dfvk.to_ovk(Scope::External),
|
||||||
output,
|
output,
|
||||||
|
|
|
@ -739,6 +739,7 @@ mod tests {
|
||||||
|
|
||||||
use incrementalmerkletree::{Hashable, Level};
|
use incrementalmerkletree::{Hashable, Level};
|
||||||
use secrecy::Secret;
|
use secrecy::Secret;
|
||||||
|
|
||||||
use zcash_client_backend::data_api::{
|
use zcash_client_backend::data_api::{
|
||||||
chain::CommitmentTreeRoot,
|
chain::CommitmentTreeRoot,
|
||||||
scanning::{ScanPriority, ScanRange},
|
scanning::{ScanPriority, ScanRange},
|
||||||
|
@ -752,7 +753,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
testing::{sapling_activation_height, AddressType, TestBuilder},
|
testing::{birthday_at_sapling_activation, AddressType, TestBuilder},
|
||||||
wallet::{init::init_blocks_table, scanning::suggest_scan_ranges},
|
wallet::{init::init_blocks_table, scanning::suggest_scan_ranges},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1085,11 +1086,11 @@ mod tests {
|
||||||
|
|
||||||
let mut st = TestBuilder::new()
|
let mut st = TestBuilder::new()
|
||||||
.with_block_cache()
|
.with_block_cache()
|
||||||
.with_seed(Secret::new(vec![]))
|
.with_test_account(birthday_at_sapling_activation)
|
||||||
.with_test_account()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let dfvk = st.test_account_sapling().unwrap();
|
let dfvk = st.test_account_sapling().unwrap();
|
||||||
|
let sapling_activation_height = st.sapling_activation_height();
|
||||||
|
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
// In the following, we don't care what the root hashes are, they just need to be
|
// In the following, we don't care what the root hashes are, they just need to be
|
||||||
|
@ -1098,15 +1099,15 @@ mod tests {
|
||||||
0,
|
0,
|
||||||
&[
|
&[
|
||||||
CommitmentTreeRoot::from_parts(
|
CommitmentTreeRoot::from_parts(
|
||||||
sapling_activation_height() + 100,
|
sapling_activation_height + 100,
|
||||||
Node::empty_root(Level::from(0))
|
Node::empty_root(Level::from(0))
|
||||||
),
|
),
|
||||||
CommitmentTreeRoot::from_parts(
|
CommitmentTreeRoot::from_parts(
|
||||||
sapling_activation_height() + 200,
|
sapling_activation_height + 200,
|
||||||
Node::empty_root(Level::from(1))
|
Node::empty_root(Level::from(1))
|
||||||
),
|
),
|
||||||
CommitmentTreeRoot::from_parts(
|
CommitmentTreeRoot::from_parts(
|
||||||
sapling_activation_height() + 300,
|
sapling_activation_height + 300,
|
||||||
Node::empty_root(Level::from(2))
|
Node::empty_root(Level::from(2))
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1118,7 +1119,7 @@ mod tests {
|
||||||
// of 10 blocks. After `scan_cached_blocks`, the scan queue should have a requested scan
|
// of 10 blocks. After `scan_cached_blocks`, the scan queue should have a requested scan
|
||||||
// range of 300..310 with `FoundNote` priority, 310..320 with `Scanned` priority.
|
// range of 300..310 with `FoundNote` priority, 310..320 with `Scanned` priority.
|
||||||
let initial_sapling_tree_size = (0x1 << 16) * 3 + 5;
|
let initial_sapling_tree_size = (0x1 << 16) * 3 + 5;
|
||||||
let initial_height = sapling_activation_height() + 310;
|
let initial_height = sapling_activation_height + 310;
|
||||||
|
|
||||||
let value = Amount::from_u64(50000).unwrap();
|
let value = Amount::from_u64(50000).unwrap();
|
||||||
st.generate_block_at(
|
st.generate_block_at(
|
||||||
|
@ -1141,7 +1142,7 @@ mod tests {
|
||||||
st.scan_cached_blocks(initial_height, 10);
|
st.scan_cached_blocks(initial_height, 10);
|
||||||
|
|
||||||
// Verify the that adjacent range needed to make the note spendable has been prioritized.
|
// Verify the that adjacent range needed to make the note spendable has been prioritized.
|
||||||
let sap_active = u32::from(sapling_activation_height());
|
let sap_active = u32::from(sapling_activation_height);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
st.wallet().suggest_scan_ranges(),
|
st.wallet().suggest_scan_ranges(),
|
||||||
Ok(scan_ranges) if scan_ranges == vec![
|
Ok(scan_ranges) if scan_ranges == vec![
|
||||||
|
@ -1162,7 +1163,7 @@ mod tests {
|
||||||
// future.
|
// future.
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
st.wallet_mut()
|
st.wallet_mut()
|
||||||
.update_chain_tip(sapling_activation_height() + 340),
|
.update_chain_tip(sapling_activation_height + 340),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1179,7 +1180,7 @@ mod tests {
|
||||||
// Now simulate a jump ahead more than 100 blocks.
|
// Now simulate a jump ahead more than 100 blocks.
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
st.wallet_mut()
|
st.wallet_mut()
|
||||||
.update_chain_tip(sapling_activation_height() + 450),
|
.update_chain_tip(sapling_activation_height + 450),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1196,23 +1197,21 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_blocks_table_creates_ignored_range() {
|
fn create_account_creates_ignored_range() {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
let mut st = TestBuilder::new().with_seed(Secret::new(vec![])).build();
|
let mut st = TestBuilder::new().build();
|
||||||
|
|
||||||
let sap_active = st
|
let sap_active = st.sapling_activation_height();
|
||||||
.wallet()
|
|
||||||
.params
|
// We use Canopy activation as an arbitrary birthday height that's greater than Sapling
|
||||||
.activation_height(NetworkUpgrade::Sapling)
|
// activation.
|
||||||
.unwrap();
|
|
||||||
// Initialise the blocks table. We use Canopy activation as an arbitrary birthday height
|
|
||||||
// that's greater than Sapling activation.
|
|
||||||
let birthday_height = st
|
let birthday_height = st
|
||||||
.wallet()
|
.network()
|
||||||
.params
|
|
||||||
.activation_height(NetworkUpgrade::Canopy)
|
.activation_height(NetworkUpgrade::Canopy)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// call `init_blocks_table` to initialize the scan queue
|
||||||
init_blocks_table(
|
init_blocks_table(
|
||||||
st.wallet_mut(),
|
st.wallet_mut(),
|
||||||
birthday_height,
|
birthday_height,
|
||||||
|
@ -1222,6 +1221,10 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let seed = Secret::new(vec![0u8; 32]);
|
||||||
|
let (_, usk) = st.wallet_mut().create_account(&seed).unwrap();
|
||||||
|
let _dfvk = usk.to_unified_full_viewing_key().sapling().unwrap().clone();
|
||||||
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
// The range up to and including the wallet's birthday height is ignored.
|
// The range up to and including the wallet's birthday height is ignored.
|
||||||
scan_range(
|
scan_range(
|
||||||
|
@ -1289,9 +1292,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
assert_matches!(
|
let actual = suggest_scan_ranges(&st.wallet().conn, Ignored).unwrap();
|
||||||
suggest_scan_ranges(&st.wallet().conn, Ignored),
|
assert_eq!(actual, expected);
|
||||||
Ok(scan_ranges) if scan_ranges == expected
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue