diff --git a/Cargo.lock b/Cargo.lock index fc12c9b3b..7c6e32b52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1432,9 +1432,8 @@ dependencies = [ "zcash_local_net", "zcash_primitives", "zcash_protocol", - "zebra-chain", "zingo-netutils", - "zingo_common_components 0.2.0 (git+https://github.com/zingolabs/zingo-common.git)", + "zingo_common_components", "zingo_test_vectors 0.0.1 (git+https://github.com/zingolabs/infrastructure.git?rev=e4714fd)", "zingolib", "zingolib_testutils", @@ -1722,7 +1721,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1981,7 +1980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -2773,7 +2772,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core", ] [[package]] @@ -3201,7 +3200,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d463f34ca3c400fde3a054da0e0b8c6ffa21e4590922f3e18281bb5eeef4cbdc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3345,9 +3344,8 @@ dependencies = [ "zcash_primitives", "zcash_protocol", "zcash_transparent", - "zebra-chain", "zingo-status", - "zingo_common_components 0.2.0 (git+https://github.com/zingolabs/zingo-common.git)", + "zingo_common_components", "zingo_test_vectors 0.0.1 (git+https://github.com/zingolabs/infrastructure.git?rev=e4714fd)", "zingolib", "zingolib_testutils", @@ -3697,7 +3695,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4652,7 +4650,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -5257,7 +5255,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -6129,7 +6127,7 @@ dependencies = [ "getrandom 0.4.1", "once_cell", "rustix 1.1.3", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -8139,7 +8137,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] @@ -8155,7 +8153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", - "windows-core 0.61.2", + "windows-core", "windows-future", "windows-link 0.1.3", "windows-numerics", @@ -8167,7 +8165,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core 0.61.2", + "windows-core", ] [[package]] @@ -8179,21 +8177,8 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-result", + "windows-strings", ] [[package]] @@ -8202,7 +8187,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core 0.61.2", + "windows-core", "windows-link 0.1.3", "windows-threading", ] @@ -8247,7 +8232,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core 0.61.2", + "windows-core", "windows-link 0.1.3", ] @@ -8260,15 +8245,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-strings" version = "0.4.2" @@ -8278,15 +8254,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -8822,7 +8789,7 @@ dependencies = [ [[package]] name = "zcash_local_net" version = "0.1.0" -source = "git+https://github.com/zingolabs/infrastructure.git?rev=e4714fd#e4714fd28ab5ef42778b0f00f9d71fd974490924" +source = "git+https://github.com/Oscar-Pepper/infrastructure.git?branch=remove_zebra_from_public_api#38650b8f50afaa1d30b65138ad5b1286947e4c24" dependencies = [ "getset", "hex", @@ -8838,8 +8805,8 @@ dependencies = [ "zebra-chain", "zebra-node-services", "zebra-rpc", - "zingo_common_components 0.2.0 (git+https://github.com/zingolabs/zingo-common.git?branch=dev)", - "zingo_test_vectors 0.0.1 (git+https://github.com/zingolabs/infrastructure.git?rev=e4714fd)", + "zingo_common_components", + "zingo_test_vectors 0.0.1 (git+https://github.com/Oscar-Pepper/infrastructure.git?branch=remove_zebra_from_public_api)", ] [[package]] @@ -9358,7 +9325,7 @@ dependencies = [ "zcash_client_backend", "zcash_keys", "zcash_protocol", - "zingo_common_components 0.2.0 (git+https://github.com/zingolabs/zingo-common.git)", + "zingo_common_components", "zingolib", "zip32", ] @@ -9432,23 +9399,20 @@ dependencies = [ [[package]] name = "zingo_common_components" version = "0.2.0" -source = "git+https://github.com/zingolabs/zingo-common.git?branch=dev#096a79e2b3eb8b12d642e3380044bac00e7c855d" -dependencies = [ - "zebra-chain", -] +source = "git+https://github.com/Oscar-Pepper/zingo-common.git?branch=remove_zebra_from_public_api#2daae0e722ff1c140e895bdb923c86d7e2763dad" [[package]] -name = "zingo_common_components" -version = "0.2.0" -source = "git+https://github.com/zingolabs/zingo-common.git#096a79e2b3eb8b12d642e3380044bac00e7c855d" +name = "zingo_test_vectors" +version = "0.0.1" +source = "git+https://github.com/zingolabs/infrastructure.git?branch=dev#a303cad31749fbf70b75219ad2368615f62fe4fa" dependencies = [ - "zebra-chain", + "bip0039 0.12.0", ] [[package]] name = "zingo_test_vectors" version = "0.0.1" -source = "git+https://github.com/zingolabs/infrastructure.git?branch=dev#a303cad31749fbf70b75219ad2368615f62fe4fa" +source = "git+https://github.com/Oscar-Pepper/infrastructure.git?branch=remove_zebra_from_public_api#38650b8f50afaa1d30b65138ad5b1286947e4c24" dependencies = [ "bip0039 0.12.0", ] @@ -9516,12 +9480,11 @@ dependencies = [ "zcash_proofs", "zcash_protocol", "zcash_transparent", - "zebra-chain", "zingo-memo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "zingo-netutils", "zingo-price", "zingo-status", - "zingo_common_components 0.2.0 (git+https://github.com/zingolabs/zingo-common.git)", + "zingo_common_components", "zingo_test_vectors 0.0.1 (git+https://github.com/zingolabs/infrastructure.git?branch=dev)", "zingolib", "zip32", @@ -9538,8 +9501,7 @@ dependencies = [ "tempfile", "zcash_local_net", "zcash_protocol", - "zebra-chain", - "zingo_common_components 0.2.0 (git+https://github.com/zingolabs/zingo-common.git)", + "zingo_common_components", "zingo_test_vectors 0.0.1 (git+https://github.com/zingolabs/infrastructure.git?rev=e4714fd)", "zingolib", "zip32", diff --git a/Cargo.toml b/Cargo.toml index 6ca588602..f494f640b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,15 +40,13 @@ zcash_keys = { version = "0.12", features = [ zcash_note_encryption = "0.4" zcash_primitives = "0.26" zcash_proofs = "0.26" -zcash_protocol = "0.7" +zcash_protocol = "0.7" # public API (TODO: remove from public API) zcash_transparent = "0.6" -# Zebra -zebra-chain = "5.0.0" - # Zingo-common zingo-netutils = "1.1.0" -zingo_common_components = { git = "https://github.com/zingolabs/zingo-common.git", version = "0.2" } +zingo_common_components = { git = "https://github.com/Oscar-Pepper/zingo-common.git", branch = "remove_zebra_from_public_api" } +# zingo_common_components = { git = "https://github.com/zingolabs/zingo-common.git", branch = "dev", version = "0.2" } # Parallel processing crossbeam-channel = "0.5" @@ -120,7 +118,7 @@ zingo-status = { path = "zingo-status" } # NOTE: for development between release # zingo-status = "0.1.0" pepper-sync = { path = "pepper-sync" } zingolib = { path = "zingolib" } -zcash_local_net = { git = "https://github.com/zingolabs/infrastructure.git", rev = "e4714fd" } +zcash_local_net = { git = "https://github.com/Oscar-Pepper/infrastructure.git", branch = "remove_zebra_from_public_api" } zingo_test_vectors = { git = "https://github.com/zingolabs/infrastructure.git", rev = "e4714fd" } [profile.test] diff --git a/darkside-tests/Cargo.toml b/darkside-tests/Cargo.toml index 1ba655636..0635aa941 100644 --- a/darkside-tests/Cargo.toml +++ b/darkside-tests/Cargo.toml @@ -10,14 +10,12 @@ chain_generic_tests = [] [dependencies] zingolib = { workspace = true, features = ["darkside_tests", "testutils"] } zingo-netutils = { workspace = true } -zingo_common_components = { workspace = true, features = ["for_test"] } +zingo_common_components = { workspace = true } zingolib_testutils = { version = "0.1.0", path = "../zingolib_testutils" } zcash_local_net.workspace = true zingo_test_vectors.workspace = true -zebra-chain = { workspace = true } - orchard = { workspace = true } sapling-crypto = { workspace = true } incrementalmerkletree = { workspace = true } diff --git a/darkside-tests/src/chain_generics.rs b/darkside-tests/src/chain_generics.rs index d7e187698..d1a8075a6 100644 --- a/darkside-tests/src/chain_generics.rs +++ b/darkside-tests/src/chain_generics.rs @@ -76,13 +76,13 @@ pub(crate) mod conduct_chain { .make_unique_data_dir_and_load_config(self.configured_activation_heights); let mut lightclient = LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(DARKSIDE_SEED.to_string()).unwrap(), no_of_accounts: NonZeroU32::try_from(1).expect("hard-coded integer"), }, 0.into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(), config, diff --git a/darkside-tests/src/utils.rs b/darkside-tests/src/utils.rs index 4b9d79557..07d48201e 100644 --- a/darkside-tests/src/utils.rs +++ b/darkside-tests/src/utils.rs @@ -329,8 +329,7 @@ pub mod scenarios { use zcash_local_net::indexer::lightwalletd::Lightwalletd; use zcash_protocol::consensus::{BlockHeight, BranchId}; use zcash_protocol::{PoolType, ShieldedProtocol}; - use zebra_chain::parameters::testnet; - use zingo_common_components::protocol::activation_heights::for_test; + use zingo_common_components::protocol::ActivationHeights; use super::{ DarksideConnector, init_darksidewalletd, update_tree_states_for_transaction, @@ -348,7 +347,7 @@ pub mod scenarios { lightwalletd: Lightwalletd, pub(crate) darkside_connector: DarksideConnector, pub(crate) client_builder: ClientBuilder, - pub(crate) configured_activation_heights: testnet::ConfiguredActivationHeights, + pub(crate) configured_activation_heights: ActivationHeights, faucet: Option, lightclients: Vec, pub(crate) staged_blockheight: BlockHeight, @@ -365,7 +364,7 @@ pub mod scenarios { darkside_connector.0.clone(), zingolib::testutils::tempfile::tempdir().unwrap(), ); - let configured_activation_heights = for_test::all_height_one_nus(); + let configured_activation_heights = ActivationHeights::default(); DarksideEnvironment { lightwalletd, darkside_connector, @@ -676,7 +675,7 @@ pub mod scenarios { pub fn get_client_builder(&self) -> &ClientBuilder { &self.client_builder } - pub fn get_activation_heights(&self) -> testnet::ConfiguredActivationHeights { + pub fn get_activation_heights(&self) -> ActivationHeights { self.configured_activation_heights } pub fn get_faucet(&mut self) -> &mut LightClient { diff --git a/darkside-tests/tests/advanced_reorg_tests.rs b/darkside-tests/tests/advanced_reorg_tests.rs index 3f5e5c4c1..f39c54740 100644 --- a/darkside-tests/tests/advanced_reorg_tests.rs +++ b/darkside-tests/tests/advanced_reorg_tests.rs @@ -15,7 +15,7 @@ use tokio::time::sleep; use zcash_local_net::indexer::Indexer; use zcash_local_net::network::localhost_uri; use zcash_protocol::consensus::BlockHeight; -use zingo_common_components::protocol::activation_heights::for_test; +use zingo_common_components::protocol::ActivationHeights; use zingolib::testutils::tempfile::TempDir; use zingolib::wallet::summary::data::SentValueTransfer; use zingolib::wallet::summary::data::ValueTransferKind; @@ -41,7 +41,7 @@ async fn reorg_changes_incoming_tx_height() { ADVANCED_REORG_TESTS_USER_WALLET.to_string(), 202, true, - for_test::all_height_one_nus(), + ActivationHeights::default(), ); light_client.sync_and_await().await.unwrap(); @@ -199,7 +199,7 @@ async fn reorg_changes_incoming_tx_index() { ADVANCED_REORG_TESTS_USER_WALLET.to_string(), 202, true, - for_test::all_height_one_nus(), + ActivationHeights::default(), ); light_client.sync_and_await().await.unwrap(); @@ -357,7 +357,7 @@ async fn reorg_expires_incoming_tx() { ADVANCED_REORG_TESTS_USER_WALLET.to_string(), 202, true, - for_test::all_height_one_nus(), + ActivationHeights::default(), ); light_client.sync_and_await().await.unwrap(); @@ -537,7 +537,7 @@ async fn reorg_changes_outgoing_tx_height() { ADVANCED_REORG_TESTS_USER_WALLET.to_string(), 202, true, - for_test::all_height_one_nus(), + ActivationHeights::default(), ); light_client.sync_and_await().await.unwrap(); @@ -792,7 +792,7 @@ async fn reorg_expires_outgoing_tx_height() { ADVANCED_REORG_TESTS_USER_WALLET.to_string(), 202, true, - for_test::all_height_one_nus(), + ActivationHeights::default(), ); let expected_initial_balance = AccountBalance { @@ -992,7 +992,7 @@ async fn reorg_changes_outgoing_tx_index() { ADVANCED_REORG_TESTS_USER_WALLET.to_string(), 202, true, - for_test::all_height_one_nus(), + ActivationHeights::default(), ); light_client.sync_and_await().await.unwrap(); diff --git a/darkside-tests/tests/tests.rs b/darkside-tests/tests/tests.rs index d730bb8bb..2d15d5f91 100644 --- a/darkside-tests/tests/tests.rs +++ b/darkside-tests/tests/tests.rs @@ -4,7 +4,7 @@ use darkside_tests::utils::update_tree_states_for_transaction; use tempfile::TempDir; use zcash_local_net::indexer::Indexer; use zcash_local_net::network::localhost_uri; -use zingo_common_components::protocol::activation_heights::for_test::all_height_one_nus; +use zingo_common_components::protocol::ActivationHeights; use zingo_test_vectors::seeds::DARKSIDE_SEED; use zingolib::get_base_address_macro; use zingolib::testutils::lightclient::from_inputs; @@ -23,7 +23,7 @@ async fn simple_sync() { prepare_darksidewalletd(server_id.clone(), true) .await .unwrap(); - let activation_heights = all_height_one_nus(); + let activation_heights = ActivationHeights::default(); let wallet_dir = TempDir::new().unwrap(); let mut light_client = ClientBuilder::new(server_id, wallet_dir).build_client( DARKSIDE_SEED.to_string(), @@ -67,7 +67,7 @@ async fn reorg_receipt_sync_generic() { .await .unwrap(); - let activation_heights = all_height_one_nus(); + let activation_heights = ActivationHeights::default(); let wallet_dir = TempDir::new().unwrap(); let mut light_client = ClientBuilder::new(server_id.clone(), wallet_dir).build_client( DARKSIDE_SEED.to_string(), @@ -129,7 +129,7 @@ async fn sent_transaction_reorged_into_mempool() { let wallet_dir = TempDir::new().unwrap(); let mut client_manager = ClientBuilder::new(server_id.clone(), wallet_dir); - let activation_heights = all_height_one_nus(); + let activation_heights = ActivationHeights::default(); let mut light_client = client_manager.build_client(DARKSIDE_SEED.to_string(), 0, true, activation_heights); let mut recipient = client_manager.build_client( diff --git a/libtonode-tests/Cargo.toml b/libtonode-tests/Cargo.toml index 2551f43ce..7c436345d 100644 --- a/libtonode-tests/Cargo.toml +++ b/libtonode-tests/Cargo.toml @@ -13,7 +13,7 @@ ci = ["zingolib/ci"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] zingolib = { workspace = true, features = ["darkside_tests", "testutils"] } -zingo_common_components = { workspace = true, features = ["for_test"] } +zingo_common_components = { workspace = true } pepper-sync = { workspace = true } zingo-status = { workspace = true } @@ -29,7 +29,6 @@ zcash_protocol = { workspace = true } zcash_transparent = { workspace = true } shardtree.workspace = true bip0039.workspace = true -zebra-chain = { workspace = true } tokio = { workspace = true, features = ["full"] } json = { workspace = true } diff --git a/libtonode-tests/tests/concrete.rs b/libtonode-tests/tests/concrete.rs index 7a7bd063d..e1d801c09 100644 --- a/libtonode-tests/tests/concrete.rs +++ b/libtonode-tests/tests/concrete.rs @@ -1,6 +1,4 @@ #![forbid(unsafe_code)] -use zingo_common_components::protocol::activation_heights::for_test; - use json::JsonValue; use zcash_address::unified::Fvk; @@ -9,7 +7,7 @@ use zcash_primitives::transaction::fees::zip317::MINIMUM_FEE; use pepper_sync::wallet::TransparentCoin; use zcash_protocol::PoolType; use zcash_protocol::value::Zatoshis; -use zebra_chain::parameters::testnet; +use zingo_common_components::protocol::ActivationHeights; use zingo_test_vectors::{BASE_HEIGHT, block_rewards, seeds::HOSPITAL_MUSEUM_SEED}; use zingolib::testutils::lightclient::from_inputs; use zingolib::utils::conversion::address_from_str; @@ -147,6 +145,7 @@ mod fast { use zcash_protocol::memo::Memo; use zcash_protocol::{PoolType, ShieldedProtocol, value::Zatoshis}; use zcash_transparent::keys::NonHardenedChildIndex; + use zingo_common_components::protocol::ActivationHeights; use zingo_status::confirmation_status::ConfirmationStatus; use zingolib::{ config::ZENNIES_FOR_ZINGO_REGTEST_ADDRESS, @@ -637,7 +636,7 @@ mod fast { Some(100_000), None, PoolType::Shielded(ShieldedProtocol::Orchard), - for_test::all_height_one_nus(), + ActivationHeights::default(), None, ) .await; @@ -795,7 +794,7 @@ mod fast { // messages let alice_to_bob = TransactionRequest::new(vec![ Payment::new( - ZcashAddress::from_str(&bob.encode(&faucet.config().chain)).unwrap(), + ZcashAddress::from_str(&bob.encode(&faucet.config().network_type())).unwrap(), Zatoshis::from_u64(1_000).unwrap(), Some(Memo::encode( &Memo::from_str(&("Alice->Bob #1\nReply to\n".to_string() + &alice)).unwrap(), @@ -809,7 +808,7 @@ mod fast { .unwrap(); let alice_to_bob_2 = TransactionRequest::new(vec![ Payment::new( - ZcashAddress::from_str(&bob.encode(&faucet.config().chain)).unwrap(), + ZcashAddress::from_str(&bob.encode(&faucet.config().network_type())).unwrap(), Zatoshis::from_u64(1_000).unwrap(), Some(Memo::encode( &Memo::from_str(&("Alice->Bob #2\nReply to\n".to_string() + &alice)).unwrap(), @@ -823,7 +822,7 @@ mod fast { .unwrap(); let alice_to_charlie = TransactionRequest::new(vec![ Payment::new( - ZcashAddress::from_str(&charlie.encode(&faucet.config().chain)).unwrap(), + ZcashAddress::from_str(&charlie.encode(&faucet.config().network_type())).unwrap(), Zatoshis::from_u64(1_000).unwrap(), Some(Memo::encode( &Memo::from_str(&("Alice->Charlie #2\nReply to\n".to_string() + &alice)) @@ -843,7 +842,7 @@ mod fast { Some(Memo::encode( &Memo::from_str( &("Charlie->Alice #2\nReply to\n".to_string() - + &charlie.encode(&faucet.config().chain)), + + &charlie.encode(&faucet.config().network_type())), ) .unwrap(), )), @@ -861,7 +860,7 @@ mod fast { Some(Memo::encode( &Memo::from_str( &("Bob->Alice #2\nReply to\n".to_string() - + &bob.encode(&faucet.config().chain)), + + &bob.encode(&faucet.config().network_type())), ) .unwrap(), )), @@ -887,11 +886,11 @@ mod fast { // Collect observations let value_transfers_bob = &recipient - .messages_containing(Some(&bob.encode(&recipient.config().chain))) + .messages_containing(Some(&bob.encode(&recipient.config().network_type()))) .await .unwrap(); let value_transfers_charlie = &recipient - .messages_containing(Some(&charlie.encode(&recipient.config().chain))) + .messages_containing(Some(&charlie.encode(&recipient.config().network_type()))) .await .unwrap(); let all_vts = &recipient.value_transfers(true).await.unwrap(); @@ -1284,7 +1283,7 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" #[tokio::test] async fn mine_to_orchard() { let (local_net, mut faucet) = - scenarios::faucet(PoolType::ORCHARD, for_test::all_height_one_nus(), None).await; + scenarios::faucet(PoolType::ORCHARD, ActivationHeights::default(), None).await; check_client_balances!(faucet, o: 1_875_000_000 s: 0 t: 0); increase_height_and_wait_for_client(&local_net, &mut faucet, 1) .await @@ -1296,7 +1295,7 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" #[tokio::test] async fn mine_to_sapling() { let (local_net, mut faucet) = - scenarios::faucet(PoolType::SAPLING, for_test::all_height_one_nus(), None).await; + scenarios::faucet(PoolType::SAPLING, ActivationHeights::default(), None).await; check_client_balances!(faucet, o: 0 s: 1_875_000_000 t: 0); increase_height_and_wait_for_client(&local_net, &mut faucet, 1) .await @@ -1307,12 +1306,9 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" /// Tests that the miner's address receives (immature) rewards from mining to the transparent pool. #[tokio::test] async fn mine_to_transparent() { - let (local_net, mut faucet, _recipient) = scenarios::faucet_recipient( - PoolType::Transparent, - for_test::all_height_one_nus(), - None, - ) - .await; + let (local_net, mut faucet, _recipient) = + scenarios::faucet_recipient(PoolType::Transparent, ActivationHeights::default(), None) + .await; let unconfirmed_balance = faucet .wallet @@ -1343,21 +1339,20 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" #[ignore] #[tokio::test] async fn sync_all_epochs() { - let configured_activation_heights = testnet::ConfiguredActivationHeights { - before_overwinter: Some(1u32), - overwinter: Some(1u32), - sapling: Some(3u32), - blossom: Some(5u32), - heartwood: Some(7u32), - canopy: Some(9u32), - nu5: Some(11u32), - nu6: Some(13u32), - nu6_1: Some(15u32), - nu7: None, - }; + let activation_heights = ActivationHeights::builder() + .set_overwinter(Some(1)) + .set_sapling(Some(3)) + .set_blossom(Some(5)) + .set_heartwood(Some(7)) + .set_canopy(Some(9)) + .set_nu5(Some(11)) + .set_nu6(Some(13)) + .set_nu6_1(Some(15)) + .set_nu7(None) + .build(); let (local_net, mut lightclient) = - scenarios::unfunded_client(configured_activation_heights, None).await; + scenarios::unfunded_client(activation_heights, None).await; increase_height_and_wait_for_client(&local_net, &mut lightclient, 14) .await .unwrap(); @@ -1365,20 +1360,20 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" #[tokio::test] async fn sync_all_epochs_from_heartwood() { - let configured_activation_heights = testnet::ConfiguredActivationHeights { - before_overwinter: Some(1u32), - overwinter: Some(1u32), - sapling: Some(1u32), - blossom: Some(1u32), - heartwood: Some(1u32), - canopy: Some(3u32), - nu5: Some(5u32), - nu6: Some(7u32), - nu6_1: Some(9u32), - nu7: None, - }; + let activation_heights = ActivationHeights::builder() + .set_overwinter(Some(1)) + .set_sapling(Some(1)) + .set_blossom(Some(1)) + .set_heartwood(Some(1)) + .set_canopy(Some(3)) + .set_nu5(Some(5)) + .set_nu6(Some(7)) + .set_nu6_1(Some(9)) + .set_nu7(None) + .build(); + let (local_net, mut lightclient) = - scenarios::unfunded_client(configured_activation_heights, None).await; + scenarios::unfunded_client(activation_heights, None).await; increase_height_and_wait_for_client(&local_net, &mut lightclient, 5) .await .unwrap(); @@ -1386,7 +1381,7 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" #[tokio::test] async fn mine_to_transparent_and_shield() { - let activation_heights = for_test::all_height_one_nus(); + let activation_heights = ActivationHeights::default(); let (local_net, mut faucet, _recipient) = scenarios::faucet_recipient(PoolType::Transparent, activation_heights, None).await; increase_height_and_wait_for_client(&local_net, &mut faucet, 100) @@ -1411,7 +1406,7 @@ tmQuMoTTjU3GFfTjrhPiBYihbTVfYmPk5Gr" #[tokio::test] async fn mine_to_transparent_and_propose_shielding() { - let activation_heights = for_test::all_height_one_nus(); + let activation_heights = ActivationHeights::default(); let (local_net, mut faucet, _recipient) = scenarios::faucet_recipient(PoolType::Transparent, activation_heights, None).await; increase_height_and_wait_for_client(&local_net, &mut faucet, 100) @@ -1456,9 +1451,10 @@ mod slow { use zcash_protocol::memo::Memo; use zcash_protocol::value::Zatoshis; use zcash_protocol::{PoolType, ShieldedProtocol}; + use zingo_common_components::protocol::ActivationHeights; use zingo_status::confirmation_status::ConfirmationStatus; use zingo_test_vectors::TEST_TXID; - use zingolib::config::ChainType; + use zingolib::config::{ChainType, ZingoConfig}; use zingolib::lightclient::error::{LightClientError, SendError}; use zingolib::testutils::lightclient::{from_inputs, get_fees_paid_by_client}; use zingolib::testutils::{ @@ -1784,21 +1780,22 @@ mod slow { false, local_net.validator().get_activation_heights().await, ); - let zingo_config = zingolib::config::load_clientconfig( - client_builder.server_id, - Some(client_builder.zingo_datadir.path().to_path_buf()), - ChainType::Regtest(local_net.validator().get_activation_heights().await), - WalletSettings { + let zingo_config = ZingoConfig::builder() + .set_indexer_uri(client_builder.server_id) + .set_network_type(ChainType::Regtest( + local_net.validator().get_activation_heights().await, + )) + .set_wallet_dir(client_builder.zingo_datadir.path().to_path_buf()) + .set_wallet_name("".to_string()) + .set_wallet_settings(WalletSettings { sync_config: SyncConfig { transparent_address_discovery: TransparentAddressDiscovery::minimal(), performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(1).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap(); + }) + .set_no_of_accounts(NonZeroU32::try_from(1).unwrap()) + .build(); let (recipient_taddr, recipient_sapling, recipient_unified) = ( get_base_address_macro!(original_recipient, "transparent"), @@ -2543,7 +2540,7 @@ TransactionSummary { // consistent with all the notes in the relevant block changing state. // NOTE that the balance doesn't give insight into the distribution across notes. let (local_net, mut faucet) = - scenarios::faucet(PoolType::SAPLING, for_test::all_height_one_nus(), None).await; + scenarios::faucet(PoolType::SAPLING, ActivationHeights::default(), None).await; let amount_to_send = 10_000; let faucet_ua = get_base_address_macro!(faucet, "unified"); @@ -2574,21 +2571,21 @@ TransactionSummary { #[tokio::test] async fn send_heartwood_sapling_funds() { - let configured_activation_heights = testnet::ConfiguredActivationHeights { - before_overwinter: Some(1u32), - overwinter: Some(1u32), - sapling: Some(1u32), - blossom: Some(1u32), - heartwood: Some(1u32), - canopy: Some(3u32), - nu5: Some(5u32), - nu6: Some(5u32), - nu6_1: Some(5u32), - nu7: None, - }; + let activation_heights = ActivationHeights::builder() + .set_overwinter(Some(1)) + .set_sapling(Some(1)) + .set_blossom(Some(1)) + .set_heartwood(Some(1)) + .set_canopy(Some(3)) + .set_nu5(Some(5)) + .set_nu6(Some(5)) + .set_nu6_1(Some(5)) + .set_nu7(None) + .build(); + let (local_net, mut faucet, mut recipient) = scenarios::faucet_recipient( PoolType::Shielded(ShieldedProtocol::Sapling), - configured_activation_heights, + activation_heights, None, ) .await; @@ -2620,7 +2617,7 @@ TransactionSummary { Some(100_000), Some(100_000), PoolType::Shielded(ShieldedProtocol::Orchard), - for_test::all_height_one_nus(), + ActivationHeights::default(), None, ) .await; @@ -2708,7 +2705,7 @@ TransactionSummary { Some(funding_value), None, PoolType::Shielded(ShieldedProtocol::Orchard), - for_test::all_height_one_nus(), + ActivationHeights::default(), None, ) .await; @@ -4341,7 +4338,7 @@ mod basic_transactions { #[tokio::test] async fn mine_to_transparent_coinbase_maturity() { let (local_net, mut faucet, _recipient) = - scenarios::faucet_recipient(PoolType::Transparent, for_test::all_height_one_nus(), None) + scenarios::faucet_recipient(PoolType::Transparent, ActivationHeights::default(), None) .await; // After 3 blocks... @@ -4577,7 +4574,7 @@ mod testnet_test { use pepper_sync::sync_status; use zingo_test_vectors::seeds::HOSPITAL_MUSEUM_SEED; use zingolib::{ - config::{ChainType, ZingoConfig}, + config::{ChainType, DEFAULT_TESTNET_LIGHTWALLETD_SERVER, ZingoConfig}, lightclient::LightClient, testutils::tempfile::TempDir, wallet::{LightWallet, WalletBase}, @@ -4595,16 +4592,23 @@ mod testnet_test { while test_count < NUM_TESTS { let wallet_dir = TempDir::new().unwrap(); - let mut config = ZingoConfig::create_testnet(); - config.wallet_dir = Some(wallet_dir.path().to_path_buf()); + let config = ZingoConfig::builder() + .set_network_type(ChainType::Testnet) + .set_indexer_uri( + (DEFAULT_TESTNET_LIGHTWALLETD_SERVER) + .parse::() + .unwrap(), + ) + .set_wallet_dir(wallet_dir.path().to_path_buf()) + .build(); let wallet = LightWallet::new( ChainType::Testnet, WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(HOSPITAL_MUSEUM_SEED).unwrap(), - no_of_accounts: config.no_of_accounts, + no_of_accounts: config.no_of_accounts(), }, 2_000_000.into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(); diff --git a/libtonode-tests/tests/sync.rs b/libtonode-tests/tests/sync.rs index 593c80c72..208b106d4 100644 --- a/libtonode-tests/tests/sync.rs +++ b/libtonode-tests/tests/sync.rs @@ -5,13 +5,14 @@ use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscov use shardtree::store::ShardStore; use zcash_local_net::validator::Validator; use zcash_protocol::consensus::BlockHeight; -use zingo_common_components::protocol::activation_heights::for_test::all_height_one_nus; +use zingo_common_components::protocol::ActivationHeights; use zingo_test_vectors::seeds::HOSPITAL_MUSEUM_SEED; +use zingolib::config::{ChainType, ZingoConfig}; use zingolib::testutils::lightclient::from_inputs::quick_send; use zingolib::testutils::paths::get_cargo_manifest_dir; use zingolib::testutils::tempfile::TempDir; use zingolib::{ - config::{DEFAULT_LIGHTWALLETD_SERVER, construct_lightwalletd_uri, load_clientconfig}, + config::{DEFAULT_LIGHTWALLETD_SERVER, construct_lightwalletd_uri}, get_base_address_macro, lightclient::LightClient, testutils::lightclient::from_inputs::{self}, @@ -30,30 +31,29 @@ async fn sync_mainnet_test() { let uri = construct_lightwalletd_uri(Some(DEFAULT_LIGHTWALLETD_SERVER.to_string())); let temp_dir = TempDir::new().unwrap(); let temp_path = temp_dir.path().to_path_buf(); - let config = load_clientconfig( - uri.clone(), - Some(temp_path), - zingolib::config::ChainType::Mainnet, - WalletSettings { + let config = ZingoConfig::builder() + .set_indexer_uri(uri.clone()) + .set_network_type(ChainType::Mainnet) + .set_wallet_dir(temp_path) + .set_wallet_name("".to_string()) + .set_wallet_settings(WalletSettings { sync_config: SyncConfig { transparent_address_discovery: TransparentAddressDiscovery::minimal(), performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(1).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap(); + }) + .set_no_of_accounts(NonZeroU32::try_from(1).unwrap()) + .build(); let mut lightclient = LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(HOSPITAL_MUSEUM_SEED.to_string()).unwrap(), no_of_accounts: NonZeroU32::try_from(1).expect("hard-coded integer"), }, 1_500_000.into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(), config, @@ -100,30 +100,29 @@ async fn sync_status() { let uri = construct_lightwalletd_uri(Some(DEFAULT_LIGHTWALLETD_SERVER.to_string())); let temp_dir = TempDir::new().unwrap(); let temp_path = temp_dir.path().to_path_buf(); - let config = load_clientconfig( - uri.clone(), - Some(temp_path), - zingolib::config::ChainType::Mainnet, - WalletSettings { + let config = ZingoConfig::builder() + .set_indexer_uri(uri.clone()) + .set_network_type(ChainType::Mainnet) + .set_wallet_dir(temp_path) + .set_wallet_name("".to_string()) + .set_wallet_settings(WalletSettings { sync_config: SyncConfig { transparent_address_discovery: TransparentAddressDiscovery::minimal(), performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(1).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap(); + }) + .set_no_of_accounts(NonZeroU32::try_from(1).unwrap()) + .build(); let mut lightclient = LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(HOSPITAL_MUSEUM_SEED.to_string()).unwrap(), no_of_accounts: NonZeroU32::try_from(1).expect("hard-coded integer"), }, 2_496_152.into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(), config, @@ -227,7 +226,7 @@ async fn store_all_checkpoints_in_verification_window_chain_cache() { #[tokio::test] async fn store_all_checkpoints_in_verification_window() { let (_local_net, lightclient) = scenarios::unfunded_client( - all_height_one_nus(), + ActivationHeights::default(), Some(get_cargo_manifest_dir().join("store_all_checkpoints_test")), ) .await; diff --git a/pepper-sync/src/sync.rs b/pepper-sync/src/sync.rs index 24680cf3d..0488b9123 100644 --- a/pepper-sync/src/sync.rs +++ b/pepper-sync/src/sync.rs @@ -659,246 +659,6 @@ where Ok(sapling_floored_bday(consensus_parameters, raw_bday) - 1) } } -#[cfg(test)] -mod test { - - mod checked_height_validation { - use zcash_protocol::consensus::BlockHeight; - use zcash_protocol::local_consensus::LocalNetwork; - const LOCAL_NETWORK: LocalNetwork = LocalNetwork { - overwinter: Some(BlockHeight::from_u32(1)), - sapling: Some(BlockHeight::from_u32(3)), - blossom: Some(BlockHeight::from_u32(3)), - heartwood: Some(BlockHeight::from_u32(3)), - canopy: Some(BlockHeight::from_u32(3)), - nu5: Some(BlockHeight::from_u32(3)), - nu6: Some(BlockHeight::from_u32(3)), - nu6_1: Some(BlockHeight::from_u32(3)), - }; - use crate::{error::SyncError, mocks::MockWalletError, sync::checked_wallet_height}; - // It's possible an error from an implementor's get_sync_state could bubble up to checked_wallet_height - // this test shows that such an error is raies wrapped in a WalletError and return as the Err variant - #[tokio::test] - async fn get_sync_state_error() { - let builder = crate::mocks::MockWalletBuilder::new(); - let test_error = "get_sync_state_error"; - let mut test_wallet = builder - .get_sync_state_patch(Box::new(|_| { - Err(MockWalletError::AnErrorVariant(test_error.to_string())) - })) - .create_mock_wallet(); - let res = - checked_wallet_height(&mut test_wallet, BlockHeight::from_u32(1), &LOCAL_NETWORK); - assert!(matches!( - res, - Err(SyncError::WalletError( - crate::mocks::MockWalletError::AnErrorVariant(ref s) - )) if s == test_error - )); - } - - mod last_known_chain_height { - use crate::{ - sync::{MAX_REORG_ALLOWANCE, ScanRange}, - wallet::SyncState, - }; - const DEFAULT_START_HEIGHT: BlockHeight = BlockHeight::from_u32(1); - const _DEFAULT_LAST_KNOWN_HEIGHT: BlockHeight = BlockHeight::from_u32(102); - const DEFAULT_CHAIN_HEIGHT: BlockHeight = BlockHeight::from_u32(110); - - use super::*; - #[tokio::test] - async fn above_allowance() { - const LAST_KNOWN_HEIGHT: BlockHeight = BlockHeight::from_u32(211); - let lkch = vec![ScanRange::from_parts( - DEFAULT_START_HEIGHT..LAST_KNOWN_HEIGHT, - crate::sync::ScanPriority::Scanned, - )]; - let state = SyncState { - scan_ranges: lkch, - ..Default::default() - }; - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder.sync_state(state).create_mock_wallet(); - let res = - checked_wallet_height(&mut test_wallet, DEFAULT_CHAIN_HEIGHT, &LOCAL_NETWORK); - if let Err(e) = res { - assert_eq!( - e.to_string(), - format!( - "wallet height {} is more than {} blocks ahead of best chain height {}", - LAST_KNOWN_HEIGHT - 1, - MAX_REORG_ALLOWANCE, - DEFAULT_CHAIN_HEIGHT - ) - ); - } else { - panic!() - } - } - #[tokio::test] - async fn above_chain_height_below_allowance() { - // The hain_height is received from the proxy - // truncate uses the wallet scan start height - // as a - let lkch = vec![ScanRange::from_parts( - BlockHeight::from_u32(6)..BlockHeight::from_u32(10), - crate::sync::ScanPriority::Scanned, - )]; - let state = SyncState { - scan_ranges: lkch, - ..Default::default() - }; - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder.sync_state(state).create_mock_wallet(); - let chain_height = BlockHeight::from_u32(4); - // This will trigger a call to truncate_wallet_data with - // chain_height and start_height inferred from the wallet. - // chain must be greater than by this time which hits the Greater cmp - // match - let res = checked_wallet_height(&mut test_wallet, chain_height, &LOCAL_NETWORK); - assert_eq!(res.unwrap(), BlockHeight::from_u32(4)); - } - #[ignore = "in progress"] - #[tokio::test] - async fn equal_or_below_chain_height_and_above_sapling() { - let lkch = vec![ScanRange::from_parts( - BlockHeight::from_u32(1)..BlockHeight::from_u32(10), - crate::sync::ScanPriority::Scanned, - )]; - let state = SyncState { - scan_ranges: lkch, - ..Default::default() - }; - let builder = crate::mocks::MockWalletBuilder::new(); - let mut _test_wallet = builder.sync_state(state).create_mock_wallet(); - } - #[ignore = "in progress"] - #[tokio::test] - async fn equal_or_below_chain_height_and_below_sapling() { - // This case requires that the wallet have a scan_start_below sapling - // which is an unexpected state. - let lkch = vec![ScanRange::from_parts( - BlockHeight::from_u32(1)..BlockHeight::from_u32(10), - crate::sync::ScanPriority::Scanned, - )]; - let state = SyncState { - scan_ranges: lkch, - ..Default::default() - }; - let builder = crate::mocks::MockWalletBuilder::new(); - let mut _test_wallet = builder.sync_state(state).create_mock_wallet(); - } - #[ignore = "in progress"] - #[tokio::test] - async fn below_sapling() { - let lkch = vec![ScanRange::from_parts( - BlockHeight::from_u32(1)..BlockHeight::from_u32(10), - crate::sync::ScanPriority::Scanned, - )]; - let state = SyncState { - scan_ranges: lkch, - ..Default::default() - }; - let builder = crate::mocks::MockWalletBuilder::new(); - let mut _test_wallet = builder.sync_state(state).create_mock_wallet(); - } - } - mod no_last_known_chain_height { - use super::*; - // If there are know scan_ranges in the SyncState - #[tokio::test] - async fn get_bday_error() { - let test_error = "get_bday_error"; - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder - .get_birthday_patch(Box::new(|_| { - Err(crate::mocks::MockWalletError::AnErrorVariant( - test_error.to_string(), - )) - })) - .create_mock_wallet(); - let res = checked_wallet_height( - &mut test_wallet, - BlockHeight::from_u32(1), - &LOCAL_NETWORK, - ); - assert!(matches!( - res, - Err(SyncError::WalletError( - crate::mocks::MockWalletError::AnErrorVariant(ref s) - )) if s == test_error - )); - } - #[ignore = "in progress"] - #[tokio::test] - async fn raw_bday_above_chain_height() { - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder - .birthday(BlockHeight::from_u32(15)) - .create_mock_wallet(); - let res = checked_wallet_height( - &mut test_wallet, - BlockHeight::from_u32(1), - &LOCAL_NETWORK, - ); - if let Err(e) = res { - assert_eq!( - e.to_string(), - format!( - "wallet height is more than {} blocks ahead of best chain height", - 15 - 1 - ) - ); - } else { - panic!() - } - } - mod sapling_height { - use super::*; - #[tokio::test] - async fn raw_bday_above() { - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder - .birthday(BlockHeight::from_u32(4)) - .create_mock_wallet(); - let res = checked_wallet_height( - &mut test_wallet, - BlockHeight::from_u32(5), - &LOCAL_NETWORK, - ); - assert_eq!(res.unwrap(), BlockHeight::from_u32(4 - 1)); - } - #[tokio::test] - async fn raw_bday_equal() { - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder - .birthday(BlockHeight::from_u32(3)) - .create_mock_wallet(); - let res = checked_wallet_height( - &mut test_wallet, - BlockHeight::from_u32(5), - &LOCAL_NETWORK, - ); - assert_eq!(res.unwrap(), BlockHeight::from_u32(3 - 1)); - } - #[tokio::test] - async fn raw_bday_below() { - let builder = crate::mocks::MockWalletBuilder::new(); - let mut test_wallet = builder - .birthday(BlockHeight::from_u32(1)) - .create_mock_wallet(); - let res = checked_wallet_height( - &mut test_wallet, - BlockHeight::from_u32(5), - &LOCAL_NETWORK, - ); - assert_eq!(res.unwrap(), BlockHeight::from_u32(3 - 1)); - } - } - } - } -} /// Creates a [`self::SyncStatus`] from the wallet's current [`crate::wallet::SyncState`]. /// If there is still nullifiers to be re-fetched when scanning is complete, the percentages will be overrided to 99% @@ -2139,3 +1899,244 @@ fn max_nullifier_map_size(performance_level: PerformanceLevel) -> Option PerformanceLevel::Maximum => None, } } + +#[cfg(test)] +mod test { + + mod checked_height_validation { + use zcash_protocol::consensus::BlockHeight; + use zcash_protocol::local_consensus::LocalNetwork; + const LOCAL_NETWORK: LocalNetwork = LocalNetwork { + overwinter: Some(BlockHeight::from_u32(1)), + sapling: Some(BlockHeight::from_u32(3)), + blossom: Some(BlockHeight::from_u32(3)), + heartwood: Some(BlockHeight::from_u32(3)), + canopy: Some(BlockHeight::from_u32(3)), + nu5: Some(BlockHeight::from_u32(3)), + nu6: Some(BlockHeight::from_u32(3)), + nu6_1: Some(BlockHeight::from_u32(3)), + }; + use crate::{error::SyncError, mocks::MockWalletError, sync::checked_wallet_height}; + // It's possible an error from an implementor's get_sync_state could bubble up to checked_wallet_height + // this test shows that such an error is raies wrapped in a WalletError and return as the Err variant + #[tokio::test] + async fn get_sync_state_error() { + let builder = crate::mocks::MockWalletBuilder::new(); + let test_error = "get_sync_state_error"; + let mut test_wallet = builder + .get_sync_state_patch(Box::new(|_| { + Err(MockWalletError::AnErrorVariant(test_error.to_string())) + })) + .create_mock_wallet(); + let res = + checked_wallet_height(&mut test_wallet, BlockHeight::from_u32(1), &LOCAL_NETWORK); + assert!(matches!( + res, + Err(SyncError::WalletError( + crate::mocks::MockWalletError::AnErrorVariant(ref s) + )) if s == test_error + )); + } + + mod last_known_chain_height { + use crate::{ + sync::{MAX_REORG_ALLOWANCE, ScanRange}, + wallet::SyncState, + }; + const DEFAULT_START_HEIGHT: BlockHeight = BlockHeight::from_u32(1); + const _DEFAULT_LAST_KNOWN_HEIGHT: BlockHeight = BlockHeight::from_u32(102); + const DEFAULT_CHAIN_HEIGHT: BlockHeight = BlockHeight::from_u32(110); + + use super::*; + #[tokio::test] + async fn above_allowance() { + const LAST_KNOWN_HEIGHT: BlockHeight = BlockHeight::from_u32(211); + let lkch = vec![ScanRange::from_parts( + DEFAULT_START_HEIGHT..LAST_KNOWN_HEIGHT, + crate::sync::ScanPriority::Scanned, + )]; + let state = SyncState { + scan_ranges: lkch, + ..Default::default() + }; + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder.sync_state(state).create_mock_wallet(); + let res = + checked_wallet_height(&mut test_wallet, DEFAULT_CHAIN_HEIGHT, &LOCAL_NETWORK); + if let Err(e) = res { + assert_eq!( + e.to_string(), + format!( + "wallet height {} is more than {} blocks ahead of best chain height {}", + LAST_KNOWN_HEIGHT - 1, + MAX_REORG_ALLOWANCE, + DEFAULT_CHAIN_HEIGHT + ) + ); + } else { + panic!() + } + } + #[tokio::test] + async fn above_chain_height_below_allowance() { + // The hain_height is received from the proxy + // truncate uses the wallet scan start height + // as a + let lkch = vec![ScanRange::from_parts( + BlockHeight::from_u32(6)..BlockHeight::from_u32(10), + crate::sync::ScanPriority::Scanned, + )]; + let state = SyncState { + scan_ranges: lkch, + ..Default::default() + }; + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder.sync_state(state).create_mock_wallet(); + let chain_height = BlockHeight::from_u32(4); + // This will trigger a call to truncate_wallet_data with + // chain_height and start_height inferred from the wallet. + // chain must be greater than by this time which hits the Greater cmp + // match + let res = checked_wallet_height(&mut test_wallet, chain_height, &LOCAL_NETWORK); + assert_eq!(res.unwrap(), BlockHeight::from_u32(4)); + } + #[ignore = "in progress"] + #[tokio::test] + async fn equal_or_below_chain_height_and_above_sapling() { + let lkch = vec![ScanRange::from_parts( + BlockHeight::from_u32(1)..BlockHeight::from_u32(10), + crate::sync::ScanPriority::Scanned, + )]; + let state = SyncState { + scan_ranges: lkch, + ..Default::default() + }; + let builder = crate::mocks::MockWalletBuilder::new(); + let mut _test_wallet = builder.sync_state(state).create_mock_wallet(); + } + #[ignore = "in progress"] + #[tokio::test] + async fn equal_or_below_chain_height_and_below_sapling() { + // This case requires that the wallet have a scan_start_below sapling + // which is an unexpected state. + let lkch = vec![ScanRange::from_parts( + BlockHeight::from_u32(1)..BlockHeight::from_u32(10), + crate::sync::ScanPriority::Scanned, + )]; + let state = SyncState { + scan_ranges: lkch, + ..Default::default() + }; + let builder = crate::mocks::MockWalletBuilder::new(); + let mut _test_wallet = builder.sync_state(state).create_mock_wallet(); + } + #[ignore = "in progress"] + #[tokio::test] + async fn below_sapling() { + let lkch = vec![ScanRange::from_parts( + BlockHeight::from_u32(1)..BlockHeight::from_u32(10), + crate::sync::ScanPriority::Scanned, + )]; + let state = SyncState { + scan_ranges: lkch, + ..Default::default() + }; + let builder = crate::mocks::MockWalletBuilder::new(); + let mut _test_wallet = builder.sync_state(state).create_mock_wallet(); + } + } + mod no_last_known_chain_height { + use super::*; + // If there are know scan_ranges in the SyncState + #[tokio::test] + async fn get_bday_error() { + let test_error = "get_bday_error"; + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder + .get_birthday_patch(Box::new(|_| { + Err(crate::mocks::MockWalletError::AnErrorVariant( + test_error.to_string(), + )) + })) + .create_mock_wallet(); + let res = checked_wallet_height( + &mut test_wallet, + BlockHeight::from_u32(1), + &LOCAL_NETWORK, + ); + assert!(matches!( + res, + Err(SyncError::WalletError( + crate::mocks::MockWalletError::AnErrorVariant(ref s) + )) if s == test_error + )); + } + #[ignore = "in progress"] + #[tokio::test] + async fn raw_bday_above_chain_height() { + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder + .birthday(BlockHeight::from_u32(15)) + .create_mock_wallet(); + let res = checked_wallet_height( + &mut test_wallet, + BlockHeight::from_u32(1), + &LOCAL_NETWORK, + ); + if let Err(e) = res { + assert_eq!( + e.to_string(), + format!( + "wallet height is more than {} blocks ahead of best chain height", + 15 - 1 + ) + ); + } else { + panic!() + } + } + mod sapling_height { + use super::*; + #[tokio::test] + async fn raw_bday_above() { + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder + .birthday(BlockHeight::from_u32(4)) + .create_mock_wallet(); + let res = checked_wallet_height( + &mut test_wallet, + BlockHeight::from_u32(5), + &LOCAL_NETWORK, + ); + assert_eq!(res.unwrap(), BlockHeight::from_u32(4 - 1)); + } + #[tokio::test] + async fn raw_bday_equal() { + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder + .birthday(BlockHeight::from_u32(3)) + .create_mock_wallet(); + let res = checked_wallet_height( + &mut test_wallet, + BlockHeight::from_u32(5), + &LOCAL_NETWORK, + ); + assert_eq!(res.unwrap(), BlockHeight::from_u32(3 - 1)); + } + #[tokio::test] + async fn raw_bday_below() { + let builder = crate::mocks::MockWalletBuilder::new(); + let mut test_wallet = builder + .birthday(BlockHeight::from_u32(1)) + .create_mock_wallet(); + let res = checked_wallet_height( + &mut test_wallet, + BlockHeight::from_u32(5), + &LOCAL_NETWORK, + ); + assert_eq!(res.unwrap(), BlockHeight::from_u32(3 - 1)); + } + } + } + } +} diff --git a/zingo-cli/Cargo.toml b/zingo-cli/Cargo.toml index ae6ef7885..742f5d008 100644 --- a/zingo-cli/Cargo.toml +++ b/zingo-cli/Cargo.toml @@ -3,12 +3,9 @@ name = "zingo-cli" version = "0.2.0" edition = "2024" -[features] -regtest = [ "zingolib/regtest", "zingo_common_components/for_test" ] - [dependencies] pepper-sync = { workspace = true } -zingo_common_components = { workspace = true, optional = true } +zingo_common_components = { workspace = true } zingolib = { workspace = true } zcash_address = { workspace = true } diff --git a/zingo-cli/README.md b/zingo-cli/README.md index 849d3b266..1a0f9a608 100644 --- a/zingo-cli/README.md +++ b/zingo-cli/README.md @@ -4,22 +4,10 @@ A command-line interface for the Zingo wallet. ## Building -### Default Build (Mainnet/Testnet) - -To build the standard zingo-cli binary that works with mainnet and testnet: +To build the zingo-cli binary from the workspace: ```bash -cargo build --release -``` - -The binary will be available at `target/release/zingo-cli`. - -### Build with Regtest Support - -To build zingo-cli with regtest support in addition to mainnet and testnet: - -```bash -cargo build --release --features regtest +cargo build --release -p zingo-cli ``` The binary will be available at `target/release/zingo-cli`. @@ -60,10 +48,7 @@ To connect to testnet: ### Regtest Mode To run in regtest mode: -1. Build the zingo-cli binary with the `regtest` feature flag enabled -```bash -cargo build --release -p zingo-cli --features regtest -``` +1. Build the zingo-cli binary. 2. Launch a validator, see details below for an example of launching zcashd and generating blocks with zcash-cli. 3. Launch an indexer/lightserver, see details below for an example of launching lightwalletd. 4. Create a wallet directory (data-dir) and run zingo-cli, @@ -136,7 +121,7 @@ mineraddress=uregtest1zkuzfv5m3yhv2j4fmvq5rjurkxenxyq8r7h4daun2zkznrjaa8ra8asgdm minetolocalwallet=0 # This is set to false so that we can mine to a wallet, other than the zcashd wallet. ``` -### Example: Zcashd Config File +### Example: Lightwalletd Config File ``` grpc-bind-addr: 127.0.0.1:9067 diff --git a/zingo-cli/src/commands.rs b/zingo-cli/src/commands.rs index d083aea29..7877e4965 100644 --- a/zingo-cli/src/commands.rs +++ b/zingo-cli/src/commands.rs @@ -23,8 +23,7 @@ use zcash_protocol::consensus::NetworkType; use zcash_protocol::value::Zatoshis; use pepper_sync::wallet::{KeyIdInterface, OrchardNote, SaplingNote, SyncMode}; -#[cfg(feature = "regtest")] -use zingo_common_components::protocol::activation_heights::for_test; +use zingo_common_components::protocol::ActivationHeights; use zingolib::data::{PollReport, proposal}; use zingolib::lightclient::LightClient; use zingolib::utils::conversion::txid_from_hex_encoded_str; @@ -91,17 +90,17 @@ impl Command for ChangeServerCommand { fn exec(&self, args: &[&str], lightclient: &mut LightClient) -> String { match args.len() { 0 => { - lightclient.set_server(http::Uri::default()); + lightclient.set_indexer_uri(http::Uri::default()); "server set".to_string() } 1 => match http::Uri::from_str(args[0]) { Ok(uri) => { - lightclient.set_server(uri); + lightclient.set_indexer_uri(uri); "server set" } Err(_) => match args[0] { "" => { - lightclient.set_server(http::Uri::default()); + lightclient.set_indexer_uri(http::Uri::default()); "server set" } _ => "invalid server uri", @@ -220,8 +219,7 @@ impl Command for ParseAddressCommand { [ zingolib::config::ChainType::Mainnet, zingolib::config::ChainType::Testnet, - #[cfg(feature = "regtest")] - zingolib::config::ChainType::Regtest(for_test::all_height_one_nus()), + zingolib::config::ChainType::Regtest(ActivationHeights::default()), ] .iter() .find_map(|chain| Address::decode(chain, address).zip(Some(*chain))) @@ -231,7 +229,6 @@ impl Command for ParseAddressCommand { let chain_name_string = match chain_name { zingolib::config::ChainType::Mainnet => "main", zingolib::config::ChainType::Testnet => "test", - #[cfg(feature = "regtest")] zingolib::config::ChainType::Regtest(_) => "regtest", _ => unreachable!("Invalid chain type"), }; diff --git a/zingo-cli/src/lib.rs b/zingo-cli/src/lib.rs index 21da59c3c..8dafaa6a8 100644 --- a/zingo-cli/src/lib.rs +++ b/zingo-cli/src/lib.rs @@ -18,7 +18,7 @@ use zcash_protocol::consensus::BlockHeight; use commands::ShortCircuitedCommand; use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; -use zingolib::config::ChainType; +use zingolib::config::{ChainType, ZingoConfig}; use zingolib::lightclient::LightClient; use zingolib::wallet::{LightWallet, WalletBase, WalletSettings}; @@ -42,11 +42,9 @@ pub fn build_clap_app() -> clap::ArgMatches { .arg(Arg::new("chain") .long("chain").short('c') .value_name("CHAIN") - .help(if cfg!(feature = "regtest") { + .help( r#"What chain to expect. One of "mainnet", "testnet", or "regtest". Defaults to "mainnet""# - } else { - r#"What chain to expect. One of "mainnet" or "testnet". Defaults to "mainnet""# - })) + )) .arg(Arg::new("seed") .short('s') .long("seed") @@ -341,7 +339,7 @@ If you don't remember the block height, you can pass '--birthday 0' to scan from log::info!("data_dir: {}", &data_dir.to_str().unwrap()); let server = zingolib::config::construct_lightwalletd_uri(server); let chaintype = if let Some(chain) = matches.get_one::("chain") { - zingolib::config::chain_from_str(chain).map_err(|e| e.to_string())? + ChainType::try_from(chain.as_str()).map_err(|e| e.to_string())? } else { ChainType::Mainnet }; @@ -383,26 +381,25 @@ pub type CommandResponse = String; pub fn startup( filled_template: &ConfigTemplate, ) -> std::io::Result<(Sender, Receiver)> { - let config = zingolib::config::load_clientconfig( - filled_template.server.clone(), - Some(filled_template.data_dir.clone()), - filled_template.chaintype, - WalletSettings { + let config = ZingoConfig::builder() + .set_indexer_uri(filled_template.server.clone()) + .set_network_type(filled_template.chaintype) + .set_wallet_dir(filled_template.data_dir.clone()) + .set_wallet_settings(WalletSettings { sync_config: SyncConfig { transparent_address_discovery: TransparentAddressDiscovery::minimal(), performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(3).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap(); + }) + .set_no_of_accounts(NonZeroU32::try_from(1).expect("hard-coded non-zero integer")) + .set_wallet_name("".to_string()) + .build(); let mut lightclient = if let Some(seed_phrase) = filled_template.seed.clone() { LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(seed_phrase).map_err(|e| { std::io::Error::new( @@ -413,7 +410,7 @@ pub fn startup( no_of_accounts: NonZeroU32::try_from(1).expect("hard-coded integer"), }, (filled_template.birthday as u32).into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .map_err(|e| std::io::Error::other(format!("Failed to create wallet. {e}")))?, config.clone(), @@ -424,17 +421,17 @@ pub fn startup( // Create client from UFVK LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Ufvk(ufvk), (filled_template.birthday as u32).into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .map_err(|e| std::io::Error::other(format!("Failed to create wallet. {e}")))?, config.clone(), false, ) .map_err(|e| std::io::Error::other(format!("Failed to create lightclient. {e}")))? - } else if config.wallet_path_exists() { + } else if config.get_wallet_path().exists() { // Open existing wallet from path LightClient::create_from_wallet_path(config.clone()) .map_err(|e| std::io::Error::other(format!("Failed to create lightclient. {e}")))? @@ -443,7 +440,7 @@ pub fn startup( println!("Creating a new wallet"); // Call the lightwalletd server to get the current block-height // Do a getinfo first, before opening the wallet - let server_uri = config.get_lightwalletd_uri(); + let server_uri = config.indexer_uri(); let chain_height = RT .block_on(async move { @@ -463,10 +460,7 @@ pub fn startup( info!("Starting Zingo-CLI"); info!("Light Client config {config:?}"); - info!( - "Lightclient connecting to {}", - config.get_lightwalletd_uri() - ); + info!("Lightclient connecting to {}", config.indexer_uri()); } if filled_template.tor_enabled { diff --git a/zingolib/Cargo.toml b/zingolib/Cargo.toml index fb6276e7e..4e059da8f 100644 --- a/zingolib/Cargo.toml +++ b/zingolib/Cargo.toml @@ -17,8 +17,7 @@ maintenance = { status = "actively-developed" } default = [] ci = [] darkside_tests = ["pepper-sync/darkside_test"] -testutils = ["portpicker", "zingo_test_vectors", "tempfile", "zingo_common_components/for_test"] -regtest = [ "zingo_common_components/for_test" ] +testutils = ["portpicker", "zingo_test_vectors", "tempfile"] [dependencies] @@ -54,9 +53,6 @@ zcash_proofs = { workspace = true, features = ["download-params"] } zcash_protocol = { workspace = true } zcash_transparent = { workspace = true } -# Zebra -zebra-chain = { workspace = true } - # Protocol zip32.workspace = true bip0039.workspace = true diff --git a/zingolib/src/config.rs b/zingolib/src/config.rs index 680f1c4b0..8c732d2e7 100644 --- a/zingolib/src/config.rs +++ b/zingolib/src/config.rs @@ -1,13 +1,11 @@ //! `ZingConfig` //! TODO: Add Crate Description Here! -#![forbid(unsafe_code)] -#![warn(missing_docs)] use std::{ io::{self, Error}, + net::ToSocketAddrs, num::NonZeroU32, path::{Path, PathBuf}, - sync::{Arc, RwLock}, }; use log::{LevelFilter, info}; @@ -23,136 +21,119 @@ use log4rs::{ encode::pattern::PatternEncoder, filter::threshold::ThresholdFilter, }; + use zcash_protocol::consensus::{ BlockHeight, MAIN_NETWORK, NetworkType, NetworkUpgrade, Parameters, TEST_NETWORK, }; -#[cfg(feature = "regtest")] -use zingo_common_components::protocol::activation_heights::for_test::all_height_one_nus; +use zingo_common_components::protocol::ActivationHeights; use crate::wallet::WalletSettings; /// TODO: Add Doc Comment Here! pub const DEVELOPER_DONATION_ADDRESS: &str = "u1w47nzy4z5g9zvm4h2s4ztpl8vrdmlclqz5sz02742zs5j3tz232u4safvv9kplg7g06wpk5fx0k0rx3r9gg4qk6nkg4c0ey57l0dyxtatqf8403xat7vyge7mmen7zwjcgvryg22khtg3327s6mqqkxnpwlnrt27kxhwg37qys2kpn2d2jl2zkk44l7j7hq9az82594u3qaescr3c9v"; +/// TODO: Add Doc Comment Here! +pub const ZENNIES_FOR_ZINGO_DONATION_ADDRESS: &str = "u1p32nu0pgev5cr0u6t4ja9lcn29kaw37xch8nyglwvp7grl07f72c46hxvw0u3q58ks43ntg324fmulc2xqf4xl3pv42s232m25vaukp05s6av9z76s3evsstax4u6f5g7tql5yqwuks9t4ef6vdayfmrsymenqtshgxzj59hdydzygesqa7pdpw463hu7afqf4an29m69kfasdwr494"; +/// TODO: Add Doc Comment Here! +pub const ZENNIES_FOR_ZINGO_TESTNET_ADDRESS: &str = "utest19zd9laj93deq4lkay48xcfyh0tjec786x6yrng38fp6zusgm0c84h3el99fngh8eks4kxv020r2h2njku6pf69anpqmjq5c3suzcjtlyhvpse0aqje09la48xk6a2cnm822s2yhuzfr47pp4dla9rakdk90g0cee070z57d3trqk87wwj4swz6uf6ts6p5z6lep3xyvueuvt7392tww"; /// Regtest address for donation in test environments pub const ZENNIES_FOR_ZINGO_REGTEST_ADDRESS: &str = "uregtest14emvr2anyul683p43d0ck55c04r65ld6f0shetcn77z8j7m64hm4ku3wguf60s75f0g3s7r7g89z22f3ff5tsfgr45efj4pe2gyg5krqp5vvl3afu0280zp9ru2379zat5y6nkqkwjxsvpq5900kchcgzaw8v8z3ggt5yymnuj9hymtv3p533fcrk2wnj48g5vg42vle08c2xtanq0e"; +/// TODO: Add Doc Comment Here! +pub const ZENNIES_FOR_ZINGO_AMOUNT: u64 = 1_000_000; +/// The lightserver that handles blockchain requests +pub const DEFAULT_LIGHTWALLETD_SERVER: &str = "https://zec.rocks:443"; +/// Used for testnet +pub const DEFAULT_TESTNET_LIGHTWALLETD_SERVER: &str = "https://testnet.zec.rocks"; +/// TODO: Add Doc Comment Here! +pub const DEFAULT_WALLET_NAME: &str = "zingo-wallet.dat"; +/// TODO: Add Doc Comment Here! +pub const DEFAULT_LOGFILE_NAME: &str = "zingo-wallet.debug.log"; /// Gets the appropriate donation address for the given chain type #[must_use] pub fn get_donation_address_for_chain(chain: &ChainType) -> &'static str { match chain { - ChainType::Testnet => ZENNIES_FOR_ZINGO_TESTNET_ADDRESS, ChainType::Mainnet => ZENNIES_FOR_ZINGO_DONATION_ADDRESS, + ChainType::Testnet => ZENNIES_FOR_ZINGO_TESTNET_ADDRESS, ChainType::Regtest(_) => ZENNIES_FOR_ZINGO_REGTEST_ADDRESS, } } /// The networks a zingolib client can run against -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ChainType { - /// Testnet - Testnet, /// Mainnet Mainnet, + /// Testnet + Testnet, /// Regtest - Regtest(zebra_chain::parameters::testnet::ConfiguredActivationHeights), + Regtest(ActivationHeights), } impl std::fmt::Display for ChainType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use ChainType::{Mainnet, Regtest, Testnet}; - let name = match self { - Testnet => "test", - Mainnet => "main", - Regtest(_) => "regtest", + let chain = match self { + ChainType::Mainnet => "mainnet", + ChainType::Testnet => "testnet", + ChainType::Regtest(_) => "regtest", }; - write!(f, "{name}") + write!(f, "{chain}") } } +// TODO: can we rework the library so we dont have implement Parameters on the public API facing ChainType? +// this trait impl exposes external (zcash_protocol) types to the public API impl Parameters for ChainType { fn network_type(&self) -> NetworkType { match self { - ChainType::Testnet => NetworkType::Test, ChainType::Mainnet => NetworkType::Main, + ChainType::Testnet => NetworkType::Test, ChainType::Regtest(_) => NetworkType::Regtest, } } fn activation_height(&self, nu: NetworkUpgrade) -> Option { - use ChainType::{Mainnet, Regtest, Testnet}; match self { - Testnet => TEST_NETWORK.activation_height(nu), - Mainnet => MAIN_NETWORK.activation_height(nu), - Regtest(activation_heights) => match nu { + ChainType::Mainnet => MAIN_NETWORK.activation_height(nu), + ChainType::Testnet => TEST_NETWORK.activation_height(nu), + ChainType::Regtest(activation_heights) => match nu { NetworkUpgrade::Overwinter => { - activation_heights.overwinter.map(BlockHeight::from_u32) + activation_heights.overwinter().map(BlockHeight::from_u32) } - NetworkUpgrade::Sapling => activation_heights.sapling.map(BlockHeight::from_u32), - NetworkUpgrade::Blossom => activation_heights.blossom.map(BlockHeight::from_u32), + NetworkUpgrade::Sapling => activation_heights.sapling().map(BlockHeight::from_u32), + NetworkUpgrade::Blossom => activation_heights.blossom().map(BlockHeight::from_u32), NetworkUpgrade::Heartwood => { - activation_heights.heartwood.map(BlockHeight::from_u32) + activation_heights.heartwood().map(BlockHeight::from_u32) } - NetworkUpgrade::Canopy => activation_heights.canopy.map(BlockHeight::from_u32), - NetworkUpgrade::Nu5 => activation_heights.nu5.map(BlockHeight::from_u32), - NetworkUpgrade::Nu6 => activation_heights.nu6.map(BlockHeight::from_u32), - NetworkUpgrade::Nu6_1 => activation_heights.nu6_1.map(BlockHeight::from_u32), + NetworkUpgrade::Canopy => activation_heights.canopy().map(BlockHeight::from_u32), + NetworkUpgrade::Nu5 => activation_heights.nu5().map(BlockHeight::from_u32), + NetworkUpgrade::Nu6 => activation_heights.nu6().map(BlockHeight::from_u32), + NetworkUpgrade::Nu6_1 => activation_heights.nu6_1().map(BlockHeight::from_u32), }, } } } -/// An error determining chain id and parameters '`ChainType`' from string. -#[derive(thiserror::Error, Debug)] -pub enum ChainFromStringError { - /// Invalid chain name. Expected one of: mainnet, testnet or regtest. - #[error("Invalid chain name '{0}'. Expected one of: mainnet, testnet or regtest.")] - UnknownChain(String), - /// "regtest" feature is not enabled. - #[error("\"regtest\" feature is not enabled.")] - RegtestFeatureNotEnabled, -} +impl TryFrom<&str> for ChainType { + type Error = InvalidChainType; -/// Converts a chain name string to a `ChainType` variant. -/// -/// # Arguments -/// * `chain_name` - The chain name as a string -/// -/// # Returns -/// * `Ok(ChainType)` - The corresponding `ChainType` variant -/// * `Err(String)` - An error message if the chain name is invalid -pub fn chain_from_str(chain_name: &str) -> Result { - match chain_name { - "testnet" => Ok(ChainType::Testnet), - "mainnet" => Ok(ChainType::Mainnet), - #[cfg(feature = "regtest")] - "regtest" => Ok(ChainType::Regtest(all_height_one_nus())), - #[cfg(not(feature = "regtest"))] - "regtest" => Err(ChainFromStringError::RegtestFeatureNotEnabled), - _ => Err(ChainFromStringError::UnknownChain(chain_name.to_string())), + fn try_from(value: &str) -> Result { + match value { + "mainnet" => Ok(ChainType::Mainnet), + "testnet" => Ok(ChainType::Testnet), + "regtest" => Ok(ChainType::Regtest(ActivationHeights::default())), + _ => Err(InvalidChainType(value.to_string())), + } } } -/// TODO: Add Doc Comment Here! -pub const ZENNIES_FOR_ZINGO_TESTNET_ADDRESS: &str = "utest19zd9laj93deq4lkay48xcfyh0tjec786x6yrng38fp6zusgm0c84h3el99fngh8eks4kxv020r2h2njku6pf69anpqmjq5c3suzcjtlyhvpse0aqje09la48xk6a2cnm822s2yhuzfr47pp4dla9rakdk90g0cee070z57d3trqk87wwj4swz6uf6ts6p5z6lep3xyvueuvt7392tww"; -/// TODO: Add Doc Comment Here! -pub const ZENNIES_FOR_ZINGO_DONATION_ADDRESS: &str = "u1p32nu0pgev5cr0u6t4ja9lcn29kaw37xch8nyglwvp7grl07f72c46hxvw0u3q58ks43ntg324fmulc2xqf4xl3pv42s232m25vaukp05s6av9z76s3evsstax4u6f5g7tql5yqwuks9t4ef6vdayfmrsymenqtshgxzj59hdydzygesqa7pdpw463hu7afqf4an29m69kfasdwr494"; -/// TODO: Add Doc Comment Here! -pub const ZENNIES_FOR_ZINGO_AMOUNT: u64 = 1_000_000; -/// The lightserver that handles blockchain requests -pub const DEFAULT_LIGHTWALLETD_SERVER: &str = "https://zec.rocks:443"; -/// Used for testnet -pub const DEFAULT_TESTNET_LIGHTWALLETD_SERVER: &str = "https://testnet.zec.rocks"; -/// TODO: Add Doc Comment Here! -pub const DEFAULT_WALLET_NAME: &str = "zingo-wallet.dat"; -/// TODO: Add Doc Comment Here! -pub const DEFAULT_LOGFILE_NAME: &str = "zingo-wallet.debug.log"; - -/// Re-export pepper-sync `SyncConfig` for use with `load_clientconfig` -/// -pub use pepper_sync::config::{SyncConfig, TransparentAddressDiscovery}; +/// Invalid chain type. +#[derive(thiserror::Error, Debug)] +#[error("Invalid chain type '{0}'. Expected one of: 'mainnet', 'testnet' or 'regtest'.")] +pub struct InvalidChainType(String); /// Creates a zingo config for lightclient construction. +#[deprecated(note = "replaced by ZingoConfig builder pattern")] pub fn load_clientconfig( lightwallet_uri: http::Uri, data_dir: Option, @@ -161,43 +142,15 @@ pub fn load_clientconfig( no_of_accounts: NonZeroU32, wallet_name: String, ) -> std::io::Result { - use std::net::ToSocketAddrs; - - let host = lightwallet_uri.host(); - let port = lightwallet_uri.port(); - - if host.is_none() || port.is_none() { - info!("Using offline mode"); - } else { - match format!( - "{}:{}", - lightwallet_uri.host().unwrap(), - lightwallet_uri.port().unwrap() - ) - .to_socket_addrs() - { - Ok(_) => { - info!("Connected to {lightwallet_uri}"); - } - Err(e) => { - info!("Couldn't resolve server: {e}"); - } - } - } - - // if id is empty, the name is the default name - let wallet_name_config = if wallet_name.is_empty() { - DEFAULT_WALLET_NAME - } else { - &wallet_name - }; + check_indexer_uri(&lightwallet_uri); + let wallet_name = wallet_name_or_default(Some(wallet_name)); + let wallet_dir = wallet_dir_or_default(data_dir, chain); - // Create a Light Client Config let config = ZingoConfig { - lightwalletd_uri: Arc::new(RwLock::new(lightwallet_uri)), - chain, - wallet_dir: data_dir, - wallet_name: wallet_name_config.into(), + indexer_uri: lightwallet_uri, + network_type: chain, + wallet_dir, + wallet_name, logfile_name: DEFAULT_LOGFILE_NAME.into(), wallet_settings, no_of_accounts, @@ -206,7 +159,10 @@ pub fn load_clientconfig( Ok(config) } -/// TODO: Add Doc Comment Here! +/// Constructs a http::Uri from a `server` string. If `server` is `None` use the `DEFAULT_LIGHTWALLETD_SERVER`. +/// If the provided string is missing the http prefix, a prefix of `http://` will be added. +/// If the provided string is missing a port, a port of `:9067` will be added. +// TODO: handle errors #[must_use] pub fn construct_lightwalletd_uri(server: Option) -> http::Uri { match server { @@ -232,206 +188,75 @@ pub fn construct_lightwalletd_uri(server: Option) -> http::Uri { .unwrap() } -/// TODO: Add Doc Comment Here! -#[derive(Clone, Debug)] -pub struct ZingoConfigBuilder { - /// TODO: Add Doc Comment Here! - pub lightwalletd_uri: Option, - /// TODO: Add Doc Comment Here! - pub chain: ChainType, - /// TODO: Add Doc Comment Here! - pub reorg_buffer_offset: Option, - /// TODO: Add Doc Comment Here! - pub monitor_mempool: Option, - /// The directory where the wallet and logfiles will be created. By default, this will be in ~/.zcash on Linux and %APPDATA%\Zcash on Windows. For mac it is in: ~/Library/Application Support/Zcash - pub wallet_dir: Option, - /// The filename of the wallet. This will be created in the `wallet_dir`. - pub wallet_name: Option, - /// The filename of the logfile. This will be created in the `wallet_dir`. - pub logfile_name: Option, - /// Wallet settings. - pub wallet_settings: WalletSettings, - /// Number of accounts - pub no_of_accounts: NonZeroU32, -} - /// Configuration data for the creation of a `LightClient`. // TODO: this config should only be used to create a lightclient, the data should then be moved into fields of // lightclient or lightwallet if it needs to retained in memory. #[derive(Clone, Debug)] pub struct ZingoConfig { - /// TODO: Add Doc Comment Here! - pub lightwalletd_uri: Arc>, - /// TODO: Add Doc Comment Here! - pub chain: ChainType, + /// The URI of the indexer the lightclient is connected to. + indexer_uri: http::Uri, + /// The network type of the blockchain the lightclient is connected to. + // TODO: change for zingo common public API safe type + network_type: ChainType, /// The directory where the wallet and logfiles will be created. By default, this will be in ~/.zcash on Linux and %APPDATA%\Zcash on Windows. - pub wallet_dir: Option, + wallet_dir: PathBuf, /// The filename of the wallet. This will be created in the `wallet_dir`. - pub wallet_name: PathBuf, + wallet_name: String, /// The filename of the logfile. This will be created in the `wallet_dir`. - pub logfile_name: PathBuf, + logfile_name: String, /// Wallet settings. - pub wallet_settings: WalletSettings, + wallet_settings: WalletSettings, /// Number of accounts - pub no_of_accounts: NonZeroU32, -} - -impl ZingoConfigBuilder { - /// Set the URI of the proxy server we download blockchain information from. - /// # Examples - /// ``` - /// use zingolib::config::ZingoConfigBuilder; - /// use http::Uri; - /// assert_eq!(ZingoConfigBuilder::default().set_lightwalletd_uri(("https://zcash.mysideoftheweb.com:19067").parse::().unwrap()).lightwalletd_uri.clone().unwrap(), "https://zcash.mysideoftheweb.com:19067"); - /// ``` - pub fn set_lightwalletd_uri(&mut self, lightwalletd_uri: http::Uri) -> &mut Self { - self.lightwalletd_uri = Some(lightwalletd_uri); - self - } - - /// Set the chain the consuming client will interact with. - /// See - /// for chain types. - /// Note "chain type" is not a formal standard. - /// # Examples - /// ``` - /// use zingolib::config::ZingoConfigBuilder; - /// use zingolib::config::ChainType::Testnet; - /// assert_eq!(ZingoConfigBuilder::default().set_chain(Testnet).create().chain, Testnet); - /// ``` - pub fn set_chain(&mut self, chain: ChainType) -> &mut Self { - self.chain = chain; - self - } - - /// Set the wallet directory where client transaction data will be stored in a wallet. - /// # Examples - /// ``` - /// use zingolib::config::ZingoConfigBuilder; - /// use tempfile::TempDir; - /// let dir = tempfile::TempDir::with_prefix("zingo_doc_test").unwrap().into_path(); - /// let config = ZingoConfigBuilder::default().set_wallet_dir(dir.clone()).create(); - /// assert_eq!(config.wallet_dir.clone().unwrap(), dir); - /// ``` - pub fn set_wallet_dir(&mut self, dir: PathBuf) -> &mut Self { - self.wallet_dir = Some(dir); - self - } - - /// TODO: Add Doc Comment Here! - pub fn set_wallet_settings(&mut self, wallet_settings: WalletSettings) -> &mut Self { - self.wallet_settings = wallet_settings; - self - } - - /// TODO: Add Doc Comment Here! - pub fn set_no_of_accounts(&mut self, no_of_accounts: NonZeroU32) -> &mut Self { - self.no_of_accounts = no_of_accounts; - self - } - - /// TODO: Add Doc Comment Here! - pub fn create(&self) -> ZingoConfig { - let lightwalletd_uri = self.lightwalletd_uri.clone().unwrap_or_default(); - ZingoConfig { - lightwalletd_uri: Arc::new(RwLock::new(lightwalletd_uri)), - chain: self.chain, - wallet_dir: self.wallet_dir.clone(), - wallet_name: DEFAULT_WALLET_NAME.into(), - logfile_name: DEFAULT_LOGFILE_NAME.into(), - wallet_settings: self.wallet_settings.clone(), - no_of_accounts: self.no_of_accounts, - } - } + no_of_accounts: NonZeroU32, } -impl Default for ZingoConfigBuilder { - fn default() -> Self { - ZingoConfigBuilder { - lightwalletd_uri: None, - monitor_mempool: None, - reorg_buffer_offset: None, - wallet_dir: None, - wallet_name: None, - logfile_name: None, - chain: ChainType::Mainnet, - wallet_settings: WalletSettings { - sync_config: pepper_sync::config::SyncConfig { - transparent_address_discovery: - pepper_sync::config::TransparentAddressDiscovery::minimal(), - performance_level: pepper_sync::config::PerformanceLevel::High, - }, - min_confirmations: NonZeroU32::try_from(3).unwrap(), - }, - no_of_accounts: NonZeroU32::try_from(1).expect("hard coded non-zero integer"), - } +impl ZingoConfig { + /// Constructs a default builder. + #[must_use] + pub fn builder() -> ZingoConfigBuilder { + ZingoConfigBuilder::default() } -} -impl ZingoConfig { - /// TODO: Add Doc Comment Here! + /// Returns indexer URI. #[must_use] - pub fn build(chain: ChainType) -> ZingoConfigBuilder { - ZingoConfigBuilder { - chain, - ..ZingoConfigBuilder::default() - } + pub fn indexer_uri(&self) -> http::Uri { + self.indexer_uri.clone() } - #[cfg(any(test, feature = "testutils"))] - /// create a `ZingoConfig` that helps a `LightClient` connect to a server. + /// Returns wallet directory. #[must_use] - pub fn create_testnet() -> ZingoConfig { - ZingoConfig::build(ChainType::Testnet) - .set_lightwalletd_uri( - (DEFAULT_TESTNET_LIGHTWALLETD_SERVER) - .parse::() - .unwrap(), - ) - .create() + pub fn network_type(&self) -> ChainType { + self.network_type } - #[cfg(any(test, feature = "testutils"))] - /// create a `ZingoConfig` that helps a `LightClient` connect to a server. + /// Returns wallet directory. #[must_use] - pub fn create_mainnet() -> ZingoConfig { - ZingoConfig::build(ChainType::Mainnet) - .set_lightwalletd_uri((DEFAULT_LIGHTWALLETD_SERVER).parse::().unwrap()) - .create() + pub fn wallet_dir(&self) -> PathBuf { + self.wallet_dir.clone() } - #[cfg(feature = "testutils")] - /// create a `ZingoConfig` that signals a `LightClient` not to connect to a server. + /// Returns wallet file name. #[must_use] - pub fn create_unconnected(chain: ChainType, dir: Option) -> ZingoConfig { - if let Some(dir) = dir { - ZingoConfig::build(chain).set_wallet_dir(dir).create() - } else { - ZingoConfig::build(chain).create() - } + pub fn wallet_name(&self) -> &str { + &self.wallet_name } - /// Convenience wrapper + /// Returns log file name. #[must_use] - pub fn sapling_activation_height(&self) -> u64 { - self.chain - .activation_height(NetworkUpgrade::Sapling) - .unwrap() - .into() + pub fn logfile_name(&self) -> &str { + &self.logfile_name } - /// TODO: Add Doc Comment Here! + /// Returns wallet settings.. #[must_use] - pub fn orchard_activation_height(&self) -> u64 { - self.chain - .activation_height(NetworkUpgrade::Nu5) - .unwrap() - .into() + pub fn wallet_settings(&self) -> WalletSettings { + self.wallet_settings.clone() } - /// TODO: Add Doc Comment Here! - pub fn set_data_dir(&mut self, dir_str: String) { - self.wallet_dir = Some(PathBuf::from(dir_str)); + /// Returns number of accounts.. + #[must_use] + pub fn no_of_accounts(&self) -> NonZeroU32 { + self.no_of_accounts } /// Build the Logging config @@ -466,63 +291,11 @@ impl ZingoConfig { .map_err(|e| Error::other(format!("{e}"))) } - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn get_zingo_wallet_dir(&self) -> Box { - #[cfg(any(target_os = "ios", target_os = "android"))] - { - PathBuf::from(&self.wallet_dir.as_ref().unwrap()).into_boxed_path() - } - - #[cfg(not(any(target_os = "ios", target_os = "android")))] - { - let mut zcash_data_location; - // If there's some --data-dir path provided, use it - if self.wallet_dir.is_some() { - zcash_data_location = PathBuf::from(&self.wallet_dir.as_ref().unwrap()); - } else { - #[cfg(any(target_os = "macos", target_os = "windows"))] - { - zcash_data_location = - dirs::data_dir().expect("Couldn't determine app data directory!"); - zcash_data_location.push("Zcash"); - } - - #[cfg(not(any(target_os = "macos", target_os = "windows")))] - { - if dirs::home_dir().is_none() { - log::info!("Couldn't determine home dir!"); - } - zcash_data_location = - dirs::home_dir().expect("Couldn't determine home directory!"); - zcash_data_location.push(".zcash"); - } - - match &self.chain { - ChainType::Testnet => zcash_data_location.push("testnet3"), - ChainType::Mainnet => {} - ChainType::Regtest(_) => zcash_data_location.push("regtest"), - } - } - - // Create directory if it doesn't exist on non-mobile platforms - match std::fs::create_dir_all(zcash_data_location.clone()) { - Ok(()) => {} - Err(e) => { - tracing::error!("Couldn't create zcash directory!\n{e}"); - panic!("Couldn't create zcash directory!"); - } - } - - zcash_data_location.into_boxed_path() - } - } - - /// TODO: Add Doc Comment Here! + /// Returns the directory that the Zcash proving parameters are located in. pub fn get_zcash_params_path(&self) -> io::Result> { #[cfg(any(target_os = "ios", target_os = "android"))] { - Ok(PathBuf::from(&self.wallet_dir.as_ref().unwrap()).into_boxed_path()) + Ok(self.wallet_dir().into_boxed_path()) } //TODO: This fn is not correct for regtest mode @@ -531,7 +304,7 @@ impl ZingoConfig { if dirs::home_dir().is_none() { return Err(io::Error::new( io::ErrorKind::InvalidData, - "Couldn't determine Home Dir", + "Couldn't determine home directory!", )); } @@ -541,78 +314,35 @@ impl ZingoConfig { } } - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn get_lightwalletd_uri(&self) -> http::Uri { - self.lightwalletd_uri - .read() - .expect("Couldn't read configured server URI!") - .clone() - } - - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn get_wallet_with_name_pathbuf(&self, wallet_name: String) -> PathBuf { - let mut wallet_location = self.get_zingo_wallet_dir().into_path_buf(); - // if id is empty, the name is the default name - if wallet_name.is_empty() { - wallet_location.push(&self.wallet_name); - } else { - wallet_location.push(wallet_name); - } - wallet_location - } - - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn get_wallet_with_name_path(&self, wallet_name: String) -> Box { - self.get_wallet_with_name_pathbuf(wallet_name) - .into_boxed_path() - } - - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn wallet_with_name_path_exists(&self, wallet_name: String) -> bool { - self.get_wallet_with_name_path(wallet_name).exists() - } - - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn get_wallet_pathbuf(&self) -> PathBuf { - let mut wallet_location = self.get_zingo_wallet_dir().into_path_buf(); - wallet_location.push(&self.wallet_name); - wallet_location - } - - /// TODO: Add Doc Comment Here! + /// Returns full path to wallet file. #[must_use] pub fn get_wallet_path(&self) -> Box { - self.get_wallet_pathbuf().into_boxed_path() - } + let mut wallet_path = self.wallet_dir(); + wallet_path.push(&self.wallet_name); - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn wallet_path_exists(&self) -> bool { - self.get_wallet_path().exists() + wallet_path.into_boxed_path() } - /// TODO: Add Doc Comment Here! - #[deprecated(note = "this method was renamed 'wallet_path_exists' for clarity")] + /// Returns full path to the log file. #[must_use] - pub fn wallet_exists(&self) -> bool { - self.wallet_path_exists() + pub fn get_log_path(&self) -> Box { + let mut log_path = self.wallet_dir(); + log_path.push(&self.logfile_name); + + log_path.into_boxed_path() } - /// TODO: Add Doc Comment Here! + /// Creates a backup file of the current wallet file in the wallet directory. + // TODO: move to lightclient or lightwallet pub fn backup_existing_wallet(&self) -> Result { - if !self.wallet_path_exists() { + if !self.get_wallet_path().exists() { return Err(format!( - "Couldn't find existing wallet to backup. Looked in {:?}", - self.get_wallet_path().to_str() + "Couldn't find existing wallet to backup. Looked in {}", + self.get_wallet_path().display() )); } - let mut backup_file_path = self.get_zingo_wallet_dir().into_path_buf(); + let mut backup_file_path = self.wallet_dir(); backup_file_path.push(format!( "zingo-wallet.backup.{}.dat", std::time::SystemTime::now() @@ -627,58 +357,264 @@ impl ZingoConfig { Ok(backup_file_str) } - /// TODO: Add Doc Comment Here! - #[must_use] - pub fn get_log_path(&self) -> Box { - let mut log_path = self.get_zingo_wallet_dir().into_path_buf(); - log_path.push(&self.logfile_name); - //tracing::info!("LogFile:\n{}", log_path.to_str().unwrap()); - - log_path.into_boxed_path() + /// TEMPORARY + // TODO: this will be removed in following PR which deconstructs config fields into lightclient and lightwallet + // this method will only be a method on lightclient. + pub(crate) fn set_indexer_uri(&mut self, indexer_uri: http::Uri) { + self.indexer_uri = indexer_uri; } } -#[cfg(test)] -mod tests { - use std::num::NonZeroU32; - - use crate::wallet::WalletSettings; - - /// Validate that the `load_clientconfig` function creates a valid config from an empty uri - #[tokio::test] - async fn test_load_clientconfig() { - rustls::crypto::ring::default_provider() - .install_default() - .expect("Ring to work as a default"); - tracing_subscriber::fmt().init(); +#[cfg(any(test, feature = "testutils"))] +impl ZingoConfig { + /// create a `ZingoConfig` that helps a `LightClient` connect to a server. + #[must_use] + pub fn create_testnet() -> ZingoConfig { + ZingoConfig::builder() + .set_network_type(ChainType::Testnet) + .set_indexer_uri( + (DEFAULT_TESTNET_LIGHTWALLETD_SERVER) + .parse::() + .unwrap(), + ) + .build() + } - let valid_uri = crate::config::construct_lightwalletd_uri(Some(String::new())); + /// create a `ZingoConfig` that helps a `LightClient` connect to a server. + #[must_use] + pub fn create_mainnet() -> ZingoConfig { + ZingoConfig::builder() + .set_network_type(ChainType::Mainnet) + .set_indexer_uri((DEFAULT_LIGHTWALLETD_SERVER).parse::().unwrap()) + .build() + } - let temp_dir = tempfile::TempDir::new().unwrap(); + /// create a `ZingoConfig` that signals a `LightClient` not to connect to a server. + #[must_use] + pub fn create_unconnected(chain: ChainType, dir: Option) -> ZingoConfig { + if let Some(dir) = dir { + ZingoConfig::builder() + .set_network_type(chain) + .set_wallet_dir(dir) + .build() + } else { + ZingoConfig::builder().set_network_type(chain).build() + } + } +} - let temp_path = temp_dir.path().to_path_buf(); +/// Builder for [`ZingoConfig`]. +#[derive(Clone, Debug)] +pub struct ZingoConfigBuilder { + indexer_uri: Option, + network_type: ChainType, + wallet_dir: Option, + wallet_name: Option, + logfile_name: Option, + wallet_settings: WalletSettings, + no_of_accounts: NonZeroU32, +} - let valid_config = crate::config::load_clientconfig( - valid_uri.clone(), - Some(temp_path), - crate::config::ChainType::Mainnet, - WalletSettings { +impl ZingoConfigBuilder { + /// Constructs a new builder for [`ZingoConfig`]. + pub fn new() -> Self { + Self { + indexer_uri: None, + wallet_dir: None, + wallet_name: None, + logfile_name: None, + network_type: ChainType::Mainnet, + wallet_settings: WalletSettings { sync_config: pepper_sync::config::SyncConfig { transparent_address_discovery: pepper_sync::config::TransparentAddressDiscovery::minimal(), performance_level: pepper_sync::config::PerformanceLevel::High, }, - min_confirmations: NonZeroU32::try_from(1).unwrap(), + min_confirmations: NonZeroU32::try_from(3).unwrap(), }, - 1.try_into().unwrap(), - "".to_string(), - ); + no_of_accounts: NonZeroU32::try_from(1).expect("hard coded non-zero integer"), + } + } + + /// Set indexer URI. + /// # Examples + /// ``` + /// use zingolib::config::ZingoConfigBuilder; + /// use http::Uri; + /// assert_eq!(ZingoConfigBuilder::default().set_lightwalletd_uri(("https://zcash.mysideoftheweb.com:19067").parse::().unwrap()).lightwalletd_uri.clone().unwrap(), "https://zcash.mysideoftheweb.com:19067"); + /// ``` + pub fn set_indexer_uri(mut self, indexer_uri: http::Uri) -> Self { + self.indexer_uri = Some(indexer_uri); + self + } - assert!(valid_config.is_ok()); + /// Set network type. + /// # Examples + /// ``` + /// use zingolib::config::ZingoConfigBuilder; + /// use zingolib::config::ChainType::Testnet; + /// assert_eq!(ZingoConfigBuilder::default().set_chain(Testnet).create().chain, Testnet); + /// ``` + pub fn set_network_type(mut self, network_type: ChainType) -> Self { + self.network_type = network_type; + self } + /// Set wallet directory. + /// # Examples + /// ``` + /// use zingolib::config::ZingoConfigBuilder; + /// use tempfile::TempDir; + /// let dir = tempfile::TempDir::with_prefix("zingo_doc_test").unwrap().into_path(); + /// let config = ZingoConfigBuilder::default().set_wallet_dir(dir.clone()).create(); + /// assert_eq!(config.wallet_dir.clone().unwrap(), dir); + /// ``` + pub fn set_wallet_dir(mut self, dir: PathBuf) -> Self { + self.wallet_dir = Some(dir); + self + } + + /// Set wallet file name. + pub fn set_wallet_name(mut self, wallet_name: String) -> Self { + self.wallet_name = Some(wallet_name); + self + } + + /// Set log file name. + pub fn set_logfile_name(mut self, logfile_name: String) -> Self { + self.logfile_name = Some(logfile_name); + self + } + + /// Set wallet settings. + pub fn set_wallet_settings(mut self, wallet_settings: WalletSettings) -> Self { + self.wallet_settings = wallet_settings; + self + } + + /// Set number of accounts. + pub fn set_no_of_accounts(mut self, no_of_accounts: NonZeroU32) -> Self { + self.no_of_accounts = no_of_accounts; + self + } + + /// Build a [`ZingoConfig`] from the builder. + pub fn build(self) -> ZingoConfig { + let wallet_dir = wallet_dir_or_default(self.wallet_dir, self.network_type); + let wallet_name = wallet_name_or_default(self.wallet_name); + let logfile_name = logfile_name_or_default(self.logfile_name); + + ZingoConfig { + indexer_uri: self.indexer_uri.clone().unwrap_or_default(), + network_type: self.network_type, + wallet_dir, + wallet_name, + logfile_name, + wallet_settings: self.wallet_settings, + no_of_accounts: self.no_of_accounts, + } + } +} + +impl Default for ZingoConfigBuilder { + fn default() -> Self { + Self::new() + } +} + +// TODO: return errors +fn check_indexer_uri(indexer_uri: &http::Uri) { + if let Some(host) = indexer_uri.host() + && let Some(port) = indexer_uri.port() + { + match format!("{}:{}", host, port,).to_socket_addrs() { + Ok(_) => { + info!("Connected to {indexer_uri}"); + } + Err(e) => { + info!("Couldn't resolve server: {e}"); + } + } + } else { + info!("Using offline mode"); + } +} + +fn wallet_name_or_default(opt_wallet_name: Option) -> String { + let wallet_name = opt_wallet_name.unwrap_or_else(|| DEFAULT_WALLET_NAME.into()); + if wallet_name.is_empty() { + DEFAULT_WALLET_NAME.into() + } else { + wallet_name + } +} + +fn logfile_name_or_default(opt_logfile_name: Option) -> String { + let logfile_name = opt_logfile_name.unwrap_or_else(|| DEFAULT_LOGFILE_NAME.into()); + if logfile_name.is_empty() { + DEFAULT_LOGFILE_NAME.into() + } else { + logfile_name + } +} + +fn wallet_dir_or_default(opt_wallet_dir: Option, chain: ChainType) -> PathBuf { + let wallet_dir: PathBuf; + #[cfg(any(target_os = "ios", target_os = "android"))] + { + // TODO: handle errors + wallet_dir = opt_wallet_dir.unwrap(); + } + + #[cfg(not(any(target_os = "ios", target_os = "android")))] + { + wallet_dir = opt_wallet_dir.clone().unwrap_or_else(|| { + let mut dir = dirs::data_dir().expect("Couldn't determine user's data directory!"); + + #[cfg(any(target_os = "macos", target_os = "windows"))] + { + dir.push("Zcash"); + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + { + dir.push(".zcash"); + } + + match chain { + ChainType::Mainnet => {} + ChainType::Testnet => dir.push("testnet3"), + ChainType::Regtest(_) => dir.push("regtest"), + } + + dir + }); + + // Create directory if it doesn't exist on non-mobile platforms + match std::fs::create_dir_all(wallet_dir.clone()) { + Ok(()) => {} + Err(e) => { + panic!("Couldn't create zcash directory!\n {e}"); + } + } + } + + wallet_dir +} + +#[cfg(test)] +mod tests { + use std::num::NonZeroU32; + + use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; + + use crate::{ + config::{ChainType, ZingoConfig}, + wallet::WalletSettings, + }; + #[tokio::test] - async fn test_load_clientconfig_serverless() { + async fn test_load_clientconfig() { rustls::crypto::ring::default_provider() .install_default() .expect("Ring to work as a default"); @@ -693,25 +629,23 @@ mod tests { let temp_path = temp_dir.path().to_path_buf(); // let temp_path_invalid = temp_dir.path().to_path_buf(); - let valid_config = crate::config::load_clientconfig( - valid_uri.clone(), - Some(temp_path), - crate::config::ChainType::Mainnet, - WalletSettings { - sync_config: pepper_sync::config::SyncConfig { - transparent_address_discovery: - pepper_sync::config::TransparentAddressDiscovery::minimal(), - performance_level: pepper_sync::config::PerformanceLevel::High, + let valid_config = ZingoConfig::builder() + .set_indexer_uri(valid_uri.clone()) + .set_network_type(ChainType::Mainnet) + .set_wallet_dir(temp_path) + .set_wallet_settings(WalletSettings { + sync_config: SyncConfig { + transparent_address_discovery: TransparentAddressDiscovery::minimal(), + performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(1).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap(); + }) + .set_no_of_accounts(NonZeroU32::try_from(1).expect("hard-coded non-zero integer")) + .set_wallet_name("".to_string()) + .build(); - assert_eq!(valid_config.get_lightwalletd_uri(), valid_uri); - assert_eq!(valid_config.chain, crate::config::ChainType::Mainnet); + assert_eq!(valid_config.indexer_uri(), valid_uri); + assert_eq!(valid_config.network_type, ChainType::Mainnet); // let invalid_config = load_clientconfig_serverless( // invalid_uri.clone(), diff --git a/zingolib/src/lightclient.rs b/zingolib/src/lightclient.rs index d29a86c2b..3cda38a58 100644 --- a/zingolib/src/lightclient.rs +++ b/zingolib/src/lightclient.rs @@ -74,12 +74,12 @@ impl LightClient { ) -> Result { Self::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::FreshEntropy { - no_of_accounts: config.no_of_accounts, + no_of_accounts: config.no_of_accounts(), }, chain_height, - config.wallet_settings.clone(), + config.wallet_settings(), )?, config, overwrite, @@ -96,12 +96,12 @@ impl LightClient { ) -> Result { #[cfg(not(any(target_os = "ios", target_os = "android")))] { - if !overwrite && config.wallet_path_exists() { + if !overwrite && config.get_wallet_path().exists() { return Err(LightClientError::FileError(std::io::Error::new( std::io::ErrorKind::AlreadyExists, format!( "Cannot save to given data directory as a wallet file already exists at:\n{}", - config.get_wallet_pathbuf().to_string_lossy() + config.get_wallet_path().display() ), ))); } @@ -120,7 +120,7 @@ impl LightClient { /// Create a `LightClient` from an existing wallet file. #[allow(clippy::result_large_err)] pub fn create_from_wallet_path(config: ZingoConfig) -> Result { - let wallet_path = if config.wallet_path_exists() { + let wallet_path = if config.get_wallet_path().exists() { config.get_wallet_path() } else { return Err(LightClientError::FileError(std::io::Error::new( @@ -135,7 +135,8 @@ impl LightClient { let buffer = BufReader::new(File::open(wallet_path).map_err(LightClientError::FileError)?); Self::create_from_wallet( - LightWallet::read(buffer, config.chain).map_err(LightClientError::FileError)?, + LightWallet::read(buffer, config.network_type()) + .map_err(LightClientError::FileError)?, config, true, ) @@ -151,14 +152,14 @@ impl LightClient { self.tor_client.as_ref() } - /// Returns URI of the server the lightclient is connected to. - pub fn server_uri(&self) -> http::Uri { - self.config.get_lightwalletd_uri() + /// Returns URI of the indexer the lightclient is connected to. + pub fn indexer_uri(&self) -> http::Uri { + self.config.indexer_uri() } - /// Set the server uri. - pub fn set_server(&self, server: http::Uri) { - *self.config.lightwalletd_uri.write().unwrap() = server; + /// Set indexer uri. + pub fn set_indexer_uri(&mut self, server: http::Uri) { + self.config.set_indexer_uri(server); } /// Creates a tor client for current price updates. @@ -168,8 +169,7 @@ impl LightClient { &mut self, tor_dir: Option, ) -> Result<(), LightClientError> { - let tor_dir = - tor_dir.unwrap_or_else(|| self.config.get_zingo_wallet_dir().to_path_buf().join("tor")); + let tor_dir = tor_dir.unwrap_or_else(|| self.config.wallet_dir().join("tor")); tokio::fs::create_dir_all(tor_dir.as_path()) .await .map_err(LightClientError::FileError)?; @@ -186,12 +186,12 @@ impl LightClient { /// Returns server information. // TODO: return concrete struct with from json impl pub async fn do_info(&self) -> String { - match crate::grpc_connector::get_info(self.server_uri()).await { + match crate::grpc_connector::get_info(self.indexer_uri()).await { Ok(i) => { let o = json::object! { "version" => i.version, "git_commit" => i.git_commit, - "server_uri" => self.server_uri().to_string(), + "server_uri" => self.indexer_uri().to_string(), "vendor" => i.vendor, "taddr_support" => i.taddr_support, "chain_name" => i.chain_name, @@ -322,7 +322,7 @@ mod tests { }; use bip0039::Mnemonic; use tempfile::TempDir; - use zingo_common_components::protocol::activation_heights::for_test; + use zingo_common_components::protocol::ActivationHeights; use zingo_test_vectors::seeds::CHIMNEY_BETTER_SEED; use crate::{lightclient::LightClient, wallet::WalletBase}; @@ -330,18 +330,19 @@ mod tests { #[tokio::test] async fn new_wallet_from_phrase() { let temp_dir = TempDir::new().unwrap(); - let config = ZingoConfig::build(ChainType::Regtest(for_test::all_height_one_nus())) + let config = ZingoConfig::builder() + .set_network_type(ChainType::Regtest(ActivationHeights::default())) .set_wallet_dir(temp_dir.path().to_path_buf()) - .create(); + .build(); let mut lc = LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(CHIMNEY_BETTER_SEED.to_string()).unwrap(), - no_of_accounts: config.no_of_accounts, + no_of_accounts: config.no_of_accounts(), }, 0.into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(), config.clone(), @@ -354,13 +355,13 @@ mod tests { let lc_file_exists_error = LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(CHIMNEY_BETTER_SEED.to_string()).unwrap(), - no_of_accounts: config.no_of_accounts, + no_of_accounts: config.no_of_accounts(), }, 0.into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(), config, diff --git a/zingolib/src/lightclient/propose.rs b/zingolib/src/lightclient/propose.rs index 3ce455bde..6502a8365 100644 --- a/zingolib/src/lightclient/propose.rs +++ b/zingolib/src/lightclient/propose.rs @@ -17,7 +17,7 @@ use crate::wallet::error::ProposeShieldError; impl LightClient { fn append_zingo_zenny_receiver(&self, receivers: &mut Vec) { - let zfz_address = get_donation_address_for_chain(&self.config().chain); + let zfz_address = get_donation_address_for_chain(&self.config().network_type()); let dev_donation_receiver = Receiver::new( crate::utils::conversion::address_from_str(zfz_address).expect("Hard coded str"), Zatoshis::from_u64(ZENNIES_FOR_ZINGO_AMOUNT).expect("Hard coded u64."), @@ -182,10 +182,10 @@ mod shielding { }; fn create_basic_client() -> LightClient { - let config = ZingoConfigBuilder::default().create(); + let config = ZingoConfigBuilder::default().build(); LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(seeds::HOSPITAL_MUSEUM_SEED.to_string()) .unwrap(), diff --git a/zingolib/src/lightclient/save.rs b/zingolib/src/lightclient/save.rs index 302e3414b..ad798aa2c 100644 --- a/zingolib/src/lightclient/save.rs +++ b/zingolib/src/lightclient/save.rs @@ -114,7 +114,7 @@ impl LightClient { // TodO: can we shred it? pub async fn do_delete(&self) -> Result<(), String> { // Check if the file exists before attempting to delete - if self.config.wallet_path_exists() { + if self.config.get_wallet_path().exists() { match remove_file(self.config.get_wallet_path()) { Ok(()) => { log::debug!("File deleted successfully!"); diff --git a/zingolib/src/lightclient/send.rs b/zingolib/src/lightclient/send.rs index 031081806..0c93316a5 100644 --- a/zingolib/src/lightclient/send.rs +++ b/zingolib/src/lightclient/send.rs @@ -160,7 +160,7 @@ impl LightClient { let mut retry_count = 0; let txid_from_server = loop { let transmission_result = crate::grpc_connector::send_transaction( - self.server_uri(), + self.indexer_uri(), transaction_bytes.clone().into_boxed_slice(), ) .await @@ -223,10 +223,14 @@ mod test { use std::num::NonZeroU32; use bip0039::Mnemonic; + use pepper_sync::config::SyncConfig; + use zingo_test_vectors::seeds::ABANDON_ART_SEED; use crate::{ - lightclient::sync::test::sync_example_wallet, + config::ZingoConfig, + lightclient::{LightClient, sync::test::sync_example_wallet}, + mocks::proposal::ProposalBuilder, testutils::chain_generics::{ conduct_chain::ConductChain as _, networked::NetworkedTestEnvironment, with_assertions, }, @@ -235,15 +239,10 @@ mod test { #[tokio::test] async fn complete_and_broadcast_unconnected_error() { - use crate::{ - config::ZingoConfigBuilder, lightclient::LightClient, mocks::proposal::ProposalBuilder, - }; - use zingo_test_vectors::seeds::ABANDON_ART_SEED; - - let config = ZingoConfigBuilder::default().create(); + let config = ZingoConfig::builder().build(); let mut lc = LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(ABANDON_ART_SEED.to_string()).unwrap(), no_of_accounts: 1.try_into().unwrap(), diff --git a/zingolib/src/lightclient/sync.rs b/zingolib/src/lightclient/sync.rs index 79bb6ce94..6512e2c0a 100644 --- a/zingolib/src/lightclient/sync.rs +++ b/zingolib/src/lightclient/sync.rs @@ -27,7 +27,7 @@ impl LightClient { )); } - let client = crate::grpc_client::get_zcb_client(self.config.get_lightwalletd_uri()).await?; + let client = crate::grpc_client::get_zcb_client(self.config.indexer_uri()).await?; let wallet_guard = self.wallet.read().await; let network = wallet_guard.network; let sync_config = wallet_guard.wallet_settings.sync_config.clone(); diff --git a/zingolib/src/testutils.rs b/zingolib/src/testutils.rs index 5a590fbb5..b55b1be08 100644 --- a/zingolib/src/testutils.rs +++ b/zingolib/src/testutils.rs @@ -66,7 +66,7 @@ pub fn build_fvk_client(fvks: &[&Fvk], config: ZingoConfig) -> LightClient { ); LightClient::create_from_wallet( LightWallet::new( - config.chain, + config.network_type(), WalletBase::Ufvk(ufvk), 0.into(), WalletSettings { diff --git a/zingolib/src/testutils/chain_generics/conduct_chain.rs b/zingolib/src/testutils/chain_generics/conduct_chain.rs index 15743dc4d..9742da117 100644 --- a/zingolib/src/testutils/chain_generics/conduct_chain.rs +++ b/zingolib/src/testutils/chain_generics/conduct_chain.rs @@ -44,7 +44,7 @@ pub trait ConductChain { /// loads a client from bytes fn load_client(&mut self, config: ZingoConfig, data: &[u8]) -> LightClient { LightClient::create_from_wallet( - LightWallet::read(data, config.chain).unwrap(), + LightWallet::read(data, config.network_type()).unwrap(), config, false, ) diff --git a/zingolib/src/testutils/lightclient.rs b/zingolib/src/testutils/lightclient.rs index 95d08fd9d..c60ed2a70 100644 --- a/zingolib/src/testutils/lightclient.rs +++ b/zingolib/src/testutils/lightclient.rs @@ -18,12 +18,15 @@ pub async fn new_client_from_save_buffer( .wallet .write() .await - .write(&mut wallet_bytes, &template_client.config.chain) + .write(&mut wallet_bytes, &template_client.config.network_type()) .map_err(LightClientError::FileError)?; //TODO: improve read/write error variants LightClient::create_from_wallet( - LightWallet::read(wallet_bytes.as_slice(), template_client.config.chain) - .map_err(LightClientError::FileError)?, + LightWallet::read( + wallet_bytes.as_slice(), + template_client.config.network_type(), + ) + .map_err(LightClientError::FileError)?, template_client.config.clone(), false, ) diff --git a/zingolib/src/wallet.rs b/zingolib/src/wallet.rs index 82d5d2cab..39b7e086e 100644 --- a/zingolib/src/wallet.rs +++ b/zingolib/src/wallet.rs @@ -40,6 +40,8 @@ pub mod sync; pub mod transaction; mod zcb_traits; +pub use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; + /// Wallet settings. #[derive(Debug, Clone)] pub struct WalletSettings { diff --git a/zingolib/src/wallet/disk/testing/examples.rs b/zingolib/src/wallet/disk/testing/examples.rs index 8a0cbb8ff..51b1a3fbc 100644 --- a/zingolib/src/wallet/disk/testing/examples.rs +++ b/zingolib/src/wallet/disk/testing/examples.rs @@ -1,15 +1,16 @@ use std::num::NonZeroU32; use bytes::Buf; - use http::Uri; -use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; + use zcash_protocol::{PoolType, ShieldedProtocol}; -use zingo_common_components::protocol::activation_heights::for_test; + +use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; +use zingo_common_components::protocol::ActivationHeights; use zingo_test_vectors::seeds; use super::super::LightWallet; -use crate::config::{ChainType, DEFAULT_LIGHTWALLETD_SERVER}; +use crate::config::{ChainType, DEFAULT_LIGHTWALLETD_SERVER, ZingoConfig}; use crate::lightclient::LightClient; use crate::wallet::WalletSettings; @@ -280,27 +281,25 @@ impl NetworkSeedVersion { // Probably should be undefined. For the purpose of these tests, I hope it doesnt matter. let lightwalletd_uri = DEFAULT_LIGHTWALLETD_SERVER.parse::().unwrap(); - crate::config::load_clientconfig( - lightwalletd_uri, - None, - crate::config::ChainType::Regtest(for_test::all_height_one_nus()), - WalletSettings { + ZingoConfig::builder() + .set_indexer_uri(lightwalletd_uri) + .set_network_type(ChainType::Regtest(ActivationHeights::default())) + .set_wallet_name("".to_string()) + .set_wallet_settings(WalletSettings { sync_config: SyncConfig { transparent_address_discovery: TransparentAddressDiscovery::minimal(), performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(1).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap() + }) + .set_no_of_accounts(NonZeroU32::try_from(1).unwrap()) + .build() } NetworkSeedVersion::Testnet(_) => crate::config::ZingoConfig::create_testnet(), NetworkSeedVersion::Mainnet(_) => crate::config::ZingoConfig::create_mainnet(), }; - let wallet = self.load_example_wallet(config.chain); + let wallet = self.load_example_wallet(config.network_type()); LightClient::create_from_wallet(wallet, config, true).unwrap() } diff --git a/zingolib/src/wallet/disk/testing/tests.rs b/zingolib/src/wallet/disk/testing/tests.rs index 1b8775d11..cb16d6298 100644 --- a/zingolib/src/wallet/disk/testing/tests.rs +++ b/zingolib/src/wallet/disk/testing/tests.rs @@ -234,12 +234,12 @@ async fn reload_wallet_from_buffer() { .wallet .write() .await - .write(&mut mid_buffer, &mid_client.config.chain) + .write(&mut mid_buffer, &mid_client.config.network_type()) .unwrap(); let config = ZingoConfig::create_testnet(); let client = LightClient::create_from_wallet( - LightWallet::read(&mid_buffer[..], config.chain).unwrap(), + LightWallet::read(&mid_buffer[..], config.network_type()).unwrap(), config, true, ) diff --git a/zingolib/src/wallet/keys/legacy/extended_transparent.rs b/zingolib/src/wallet/keys/legacy/extended_transparent.rs index 1cc2bcd7f..07b48197b 100644 --- a/zingolib/src/wallet/keys/legacy/extended_transparent.rs +++ b/zingolib/src/wallet/keys/legacy/extended_transparent.rs @@ -112,7 +112,7 @@ impl ExtendedPrivKey { .derive_private_key(KeyIndex::hardened_from_normalize_index(44).unwrap()) .unwrap() .derive_private_key( - KeyIndex::hardened_from_normalize_index(config.chain.coin_type()).unwrap(), + KeyIndex::hardened_from_normalize_index(config.network_type().coin_type()).unwrap(), ) .unwrap() .derive_private_key(KeyIndex::hardened_from_normalize_index(position).unwrap()) diff --git a/zingolib_testutils/Cargo.toml b/zingolib_testutils/Cargo.toml index 607682354..a2ffa1b17 100644 --- a/zingolib_testutils/Cargo.toml +++ b/zingolib_testutils/Cargo.toml @@ -20,7 +20,6 @@ zcash_local_net.workspace = true zingo_test_vectors.workspace = true # zcash -zebra-chain.workspace = true zcash_protocol.workspace = true # bitcoin diff --git a/zingolib_testutils/src/scenarios.rs b/zingolib_testutils/src/scenarios.rs index be3be2161..7a5015838 100644 --- a/zingolib_testutils/src/scenarios.rs +++ b/zingolib_testutils/src/scenarios.rs @@ -29,15 +29,13 @@ use zcash_local_net::logs::LogsToStdoutAndStderr; use zcash_local_net::network::localhost_uri; use zcash_local_net::process::Process; use zcash_local_net::validator::{Validator, ValidatorConfig}; -use zebra_chain::parameters::testnet::ConfiguredActivationHeights; -use zingo_common_components::protocol::activation_heights::for_test::all_height_one_nus; -use zingo_test_vectors::{FUND_OFFLOAD_ORCHARD_ONLY, seeds}; - -use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; use network_combo::DefaultIndexer; use network_combo::DefaultValidator; -use zingolib::config::{ChainType, ZingoConfig, load_clientconfig}; +use pepper_sync::config::{PerformanceLevel, SyncConfig, TransparentAddressDiscovery}; +use zingo_common_components::protocol::ActivationHeights; +use zingo_test_vectors::{FUND_OFFLOAD_ORCHARD_ONLY, seeds}; +use zingolib::config::{ChainType, ZingoConfig}; use zingolib::get_base_address_macro; use zingolib::lightclient::LightClient; use zingolib::lightclient::error::LightClientError; @@ -47,6 +45,7 @@ use zingolib::testutils::sync_to_target_height; use zingolib::wallet::WalletBase; use zingolib::wallet::keys::unified::ReceiverSelection; use zingolib::wallet::{LightWallet, WalletSettings}; + /// Default regtest network processes for testing and zingo-cli regtest mode #[cfg(feature = "test_zainod_zcashd")] #[allow(missing_docs)] @@ -88,7 +87,7 @@ pub mod network_combo { pub async fn launch_test( indexer_listen_port: Option, mine_to_pool: PoolType, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, chain_cache: Option, ) -> LocalNet where @@ -154,7 +153,7 @@ impl ClientBuilder { pub fn make_unique_data_dir_and_load_config( &mut self, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, ) -> ZingoConfig { //! Each client requires a unique `data_dir`, we use the //! `client_number` counter for this. @@ -171,31 +170,30 @@ impl ClientBuilder { pub fn create_clientconfig( &self, conf_path: PathBuf, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, ) -> ZingoConfig { std::fs::create_dir(&conf_path).unwrap(); - load_clientconfig( - self.server_id.clone(), - Some(conf_path), - ChainType::Regtest(configured_activation_heights), - WalletSettings { + ZingoConfig::builder() + .set_indexer_uri(self.server_id.clone()) + .set_network_type(ChainType::Regtest(configured_activation_heights)) + .set_wallet_dir(conf_path) + .set_wallet_name("".to_string()) + .set_wallet_settings(WalletSettings { sync_config: SyncConfig { transparent_address_discovery: TransparentAddressDiscovery::minimal(), performance_level: PerformanceLevel::High, }, min_confirmations: NonZeroU32::try_from(1).unwrap(), - }, - 1.try_into().unwrap(), - "".to_string(), - ) - .unwrap() + }) + .set_no_of_accounts(NonZeroU32::try_from(1).unwrap()) + .build() } /// TODO: Add Doc Comment Here! pub fn build_faucet( &mut self, overwrite: bool, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, ) -> LightClient { //! A "faucet" is a lightclient that receives mining rewards self.build_client( @@ -212,17 +210,17 @@ impl ClientBuilder { mnemonic_phrase: String, birthday: u64, overwrite: bool, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, ) -> LightClient { let config = self.make_unique_data_dir_and_load_config(configured_activation_heights); let mut wallet = LightWallet::new( - config.chain, + config.network_type(), WalletBase::Mnemonic { mnemonic: Mnemonic::from_phrase(mnemonic_phrase).unwrap(), no_of_accounts: 1.try_into().unwrap(), }, (birthday as u32).into(), - config.wallet_settings.clone(), + config.wallet_settings(), ) .unwrap(); wallet @@ -235,7 +233,7 @@ impl ClientBuilder { /// TODO: Add Doc Comment Here! pub async fn unfunded_client( - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, chain_cache: Option, ) -> (LocalNet, LightClient) { let (local_net, mut client_builder) = custom_clients( @@ -259,7 +257,7 @@ pub async fn unfunded_client( /// TODO: Add Doc Comment Here! pub async fn unfunded_client_default() -> (LocalNet, LightClient) { - unfunded_client(all_height_one_nus(), None).await + unfunded_client(ActivationHeights::default(), None).await } /// Many scenarios need to start with spendable funds. This setup provides @@ -274,7 +272,7 @@ pub async fn unfunded_client_default() -> (LocalNet, ) -> (LocalNet, LightClient) { let (local_net, mut client_builder) = @@ -293,13 +291,13 @@ pub async fn faucet( /// TODO: Add Doc Comment Here! pub async fn faucet_default() -> (LocalNet, LightClient) { - faucet(PoolType::ORCHARD, all_height_one_nus(), None).await + faucet(PoolType::ORCHARD, ActivationHeights::default(), None).await } /// TODO: Add Doc Comment Here! pub async fn faucet_recipient( mine_to_pool: PoolType, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, chain_cache: Option, ) -> ( LocalNet, @@ -333,7 +331,7 @@ pub async fn faucet_recipient_default() -> ( LightClient, LightClient, ) { - faucet_recipient(PoolType::ORCHARD, all_height_one_nus(), None).await + faucet_recipient(PoolType::ORCHARD, ActivationHeights::default(), None).await } /// TODO: Add Doc Comment Here! @@ -342,7 +340,7 @@ pub async fn faucet_funded_recipient( sapling_funds: Option, transparent_funds: Option, mine_to_pool: PoolType, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, chain_cache: Option, ) -> ( LocalNet, @@ -434,7 +432,7 @@ pub async fn faucet_funded_recipient_default( None, None, PoolType::ORCHARD, - all_height_one_nus(), + ActivationHeights::default(), None, ) .await; @@ -445,7 +443,7 @@ pub async fn faucet_funded_recipient_default( /// TODO: Add Doc Comment Here! pub async fn custom_clients( mine_to_pool: PoolType, - configured_activation_heights: ConfiguredActivationHeights, + configured_activation_heights: ActivationHeights, chain_cache: Option, ) -> (LocalNet, ClientBuilder) { let local_net = launch_test::( @@ -472,7 +470,7 @@ pub async fn custom_clients( pub async fn custom_clients_default() -> (LocalNet, ClientBuilder) { let (local_net, client_builder) = - custom_clients(PoolType::ORCHARD, all_height_one_nus(), None).await; + custom_clients(PoolType::ORCHARD, ActivationHeights::default(), None).await; (local_net, client_builder) } @@ -482,7 +480,7 @@ pub async fn unfunded_mobileclient() -> LocalNet( Some(20_000), PoolType::SAPLING, - all_height_one_nus(), + ActivationHeights::default(), None, ) .await