From 9fd20def37260fe59cbf7daebec4557ba9c6d964 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 21 Jul 2021 19:10:07 -0300 Subject: [PATCH 01/17] [wip] inject network_id --- Cargo.lock | 2 +- Cargo.toml | 6 +- rust/src/lib.rs | 259 +++++++++++++++++++++++++++++------------------- 3 files changed, 162 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c25fc05a..a88f1a1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ [[package]] name = "libzcashlc" -version = "0.0.6" +version = "0.0.7" dependencies = [ "base58", "bitvec 0.18.5", diff --git a/Cargo.toml b/Cargo.toml index b744a020..4376beb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libzcashlc" -version = "0.0.6" +version = "0.0.7" authors = ["Jack Grigg ", "Francisco Gindre ", ] @@ -50,5 +50,5 @@ zcash_primitives = {git = "https://github.com/nuttycom/librustzcash", branch = " zcash_proofs = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa" } [features] -mainnet = ["zcash_client_sqlite/mainnet", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"] -testnet = ["zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"] \ No newline at end of file +mainnet = ["zcash_client_sqlite/mainnet"] +testnet = [] \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index b01ce326..0981af62 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -43,17 +43,13 @@ use zcash_client_sqlite::{ }; use zcash_primitives::{ block::BlockHash, - consensus::{BlockHeight, BranchId, Parameters}, + consensus::{BlockHeight, BranchId, Network, Parameters}, memo::{Memo, MemoBytes}, transaction::{components::Amount, components::OutPoint, Transaction}, zip32::ExtendedFullViewingKey, legacy::TransparentAddress, }; - -#[cfg(feature = "mainnet")] -use zcash_primitives::consensus::{MainNetwork, MAIN_NETWORK}; -#[cfg(not(feature = "mainnet"))] -use zcash_primitives::consensus::{TestNetwork, TEST_NETWORK}; +use zcash_primitives::consensus::Network::{MainNetwork, TestNetwork}; use zcash_proofs::prover::LocalTxProver; use std::convert::{TryFrom, TryInto}; @@ -78,37 +74,21 @@ where } } -#[cfg(feature = "mainnet")] -pub const NETWORK: MainNetwork = MAIN_NETWORK; -#[cfg(not(feature = "mainnet"))] -pub const NETWORK: TestNetwork = TEST_NETWORK; - -#[cfg(feature = "mainnet")] fn wallet_db( db_data: *const u8, db_data_len: usize, -) -> Result, failure::Error> { + network: Network, +) -> Result, failure::Error> { let db_data = Path::new(OsStr::from_bytes(unsafe { slice::from_raw_parts(db_data, db_data_len) })); - WalletDb::for_path(db_data, NETWORK) + WalletDb::for_path(db_data, network) .map_err(|e| format_err!("Error opening wallet database connection: {}", e)) } -#[cfg(not(feature = "mainnet"))] -fn wallet_db( - db_data: *const u8, - db_data_len: usize, -) -> Result, failure::Error> { - let db_data = Path::new(OsStr::from_bytes(unsafe { - slice::from_raw_parts(db_data, db_data_len) - })); - WalletDb::for_path(db_data, NETWORK) - .map_err(|e| format_err!("Error opening wallet database connection: {}", e)) -} - -fn block_db(cache_db: *const u8, cache_db_len: usize) -> Result { +fn block_db(cache_db: *const u8, + cache_db_len: usize) -> Result { let cache_db = Path::new(OsStr::from_bytes(unsafe { slice::from_raw_parts(cache_db, cache_db_len) })); @@ -136,13 +116,18 @@ pub extern "C" fn zcashlc_clear_last_error() { /// Sets up the internal structure of the data database. #[no_mangle] -pub extern "C" fn zcashlc_init_data_database(db_data: *const u8, db_data_len: usize) -> i32 { +pub extern "C" fn zcashlc_init_data_database( + db_data: *const u8, + db_data_len: usize, + network_id: u32, +) -> i32 { let res = catch_panic(|| { + let network = parse_network(network_id)?; let db_data = Path::new(OsStr::from_bytes(unsafe { slice::from_raw_parts(db_data, db_data_len) })); - WalletDb::for_path(db_data, NETWORK) + WalletDb::for_path(db_data, network) .map(|db| init_wallet_db(&db)) .map(|_| 1) .map_err(|e| format_err!("Error while initializing data DB: {}", e)) @@ -164,9 +149,11 @@ pub extern "C" fn zcashlc_init_accounts_table( seed_len: usize, accounts: i32, capacity_ret: *mut usize, + network_id: u32, ) -> *mut *mut c_char { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let seed = unsafe { slice::from_raw_parts(seed, seed_len) }; let accounts = if accounts >= 0 { accounts as u32 @@ -175,13 +162,13 @@ pub extern "C" fn zcashlc_init_accounts_table( }; let extsks: Vec<_> = (0..accounts) - .map(|account| spending_key(&seed, NETWORK.coin_type(), AccountId(account))) + .map(|account| spending_key(&seed, network.coin_type(), AccountId(account))) .collect(); let extfvks: Vec<_> = extsks.iter().map(ExtendedFullViewingKey::from).collect(); let t_addreses: Vec<_> = (0..accounts) .map(|account| { - let tsk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), 0).unwrap(); + let tsk = derive_secret_key_from_seed(&network, &seed, AccountId(account), 0).unwrap(); derive_transparent_address_from_secret_key(&tsk) }).collect(); @@ -192,7 +179,7 @@ pub extern "C" fn zcashlc_init_accounts_table( .iter() .map(|extsk| { let encoded = encode_extended_spending_key( - NETWORK.hrp_sapling_extended_spending_key(), + network.hrp_sapling_extended_spending_key(), extsk, ); CString::new(encoded).unwrap().into_raw() @@ -216,9 +203,11 @@ pub extern "C" fn zcashlc_init_accounts_table_with_keys( db_data: *const u8, db_data_len: usize, uvks: *mut FFIUVKBoxedSlice, + network_id: u32, ) -> bool { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let s: Box = unsafe { Box::from_raw(uvks) }; @@ -230,7 +219,7 @@ pub extern "C" fn zcashlc_init_accounts_table_with_keys( for u in slice.into_iter() { let vkstr = unsafe { CStr::from_ptr(u.extfvk).to_str().unwrap() }; let extfvk = decode_extended_full_viewing_key( - NETWORK.hrp_sapling_extended_full_viewing_key(), + network.hrp_sapling_extended_full_viewing_key(), &vkstr, ) .unwrap() @@ -263,8 +252,10 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys( seed_len: usize, accounts: i32, capacity_ret: *mut usize, + network_id: u32, ) -> *mut *mut c_char { let res = catch_panic(|| { + let network = parse_network(network_id)?; let seed = slice::from_raw_parts(seed, seed_len); let accounts = if accounts > 0 { accounts as u32 @@ -273,7 +264,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys( }; let extsks: Vec<_> = (0..accounts) - .map(|account| spending_key(&seed, NETWORK.coin_type(), AccountId(account))) + .map(|account| spending_key(&seed, network.coin_type(), AccountId(account))) .collect(); // Return the ExtendedSpendingKeys for the created accounts. @@ -281,7 +272,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys( .iter() .map(|extsk| { let encoded = encode_extended_spending_key( - NETWORK.hrp_sapling_extended_spending_key(), + network.hrp_sapling_extended_spending_key(), extsk, ); CString::new(encoded).unwrap().into_raw() @@ -311,10 +302,11 @@ pub struct FFIUVKBoxedSlice { fn unified_viewing_key_new( extfvk: &ExtendedFullViewingKey, - extpub: &PublicKey) -> FFIUnifiedViewingKey { + extpub: &PublicKey, + network: Network) -> FFIUnifiedViewingKey { let encoded_extfvk = encode_extended_full_viewing_key( - NETWORK.hrp_sapling_extended_full_viewing_key(), + network.hrp_sapling_extended_full_viewing_key(), extfvk, ); let encoded_pubkey = hex::encode(&extpub.serialize()); @@ -323,7 +315,6 @@ fn unified_viewing_key_new( extfvk: CString::new(encoded_extfvk).unwrap().into_raw(), extpub: CString::new(encoded_pubkey).unwrap().into_raw() } - } fn uvk_vec_to_ffi (v: Vec) @@ -360,8 +351,10 @@ pub unsafe extern "C" fn zcashlc_derive_unified_viewing_keys_from_seed( seed: *const u8, seed_len: usize, accounts: i32, + network_id: u32, ) -> *mut FFIUVKBoxedSlice { let res = catch_panic(|| { + let network = parse_network(network_id)?; let seed = slice::from_raw_parts(seed, seed_len); let accounts = if accounts > 0 { accounts as u32 @@ -371,8 +364,8 @@ pub unsafe extern "C" fn zcashlc_derive_unified_viewing_keys_from_seed( let uvks: Vec<_> = (0..accounts) .map(|account| { - let extfvk = ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), AccountId(account))); - let extpub = derive_public_key_from_seed(&NETWORK, &seed, AccountId(account), 0).unwrap(); + let extfvk = ExtendedFullViewingKey::from(&spending_key(&seed, network.coin_type(), AccountId(account))); + let extpub = derive_public_key_from_seed(&network, &seed, AccountId(account), 0).unwrap(); unified_viewing_key_new(&extfvk, &extpub) }) .collect(); @@ -393,8 +386,10 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys( seed_len: usize, accounts: i32, capacity_ret: *mut usize, + network_id: u32, ) -> *mut *mut c_char { let res = catch_panic(|| { + let network = parse_network(network_id)?; let seed = slice::from_raw_parts(seed, seed_len); let accounts = if accounts > 0 { accounts as u32 @@ -404,7 +399,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys( let extsks: Vec<_> = (0..accounts) .map(|account| { - ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), AccountId(account))) + ExtendedFullViewingKey::from(&spending_key(&seed, network.coin_type(), AccountId(account))) }) .collect(); @@ -413,7 +408,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys( .iter() .map(|extsk| { let encoded = encode_extended_full_viewing_key( - NETWORK.hrp_sapling_extended_full_viewing_key(), + network.hrp_sapling_extended_full_viewing_key(), extsk, ); CString::new(encoded).unwrap().into_raw() @@ -434,19 +429,21 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed( seed: *const u8, seed_len: usize, account_index: i32, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { + let network = parse_network(network_id)?; let seed = slice::from_raw_parts(seed, seed_len); let account_index = if account_index >= 0 { account_index as u32 } else { return Err(format_err!("accounts argument must be greater than zero")); }; - let address = spending_key(&seed, NETWORK.coin_type(), AccountId(account_index)) + let address = spending_key(&seed, network.coin_type(), AccountId(account_index)) .default_address() .unwrap() .1; - let address_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &address); + let address_str = encode_payment_address(network.hrp_sapling_payment_address(), &address); Ok(CString::new(address_str).unwrap().into_raw()) }); unwrap_exc_or_null(res) @@ -457,13 +454,15 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed( #[no_mangle] pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_public_key( pubkey: *const c_char, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { + let network = parse_network(network_id)?; let public_key_str = CStr::from_ptr(pubkey).to_str()?; let pk = PublicKey::from_str(&public_key_str)?; let taddr = derive_transparent_address_from_public_key(&pk) - .encode(&NETWORK); + .encode(&network); Ok(CString::new(taddr).unwrap().into_raw()) }); @@ -475,11 +474,13 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_public_key( #[no_mangle] pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key( extfvk: *const c_char, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { + let network = parse_network(network_id)?; let extfvk_string = CStr::from_ptr(extfvk).to_str()?; let extfvk = match decode_extended_full_viewing_key( - NETWORK.hrp_sapling_extended_full_viewing_key(), + network.hrp_sapling_extended_full_viewing_key(), &extfvk_string, ) { Ok(Some(extfvk)) => extfvk, @@ -494,7 +495,7 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key( } }; let address = extfvk.default_address().unwrap().1; - let address_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &address); + let address_str = encode_payment_address(network.hrp_sapling_payment_address(), &address); Ok(CString::new(address_str).unwrap().into_raw()) }); unwrap_exc_or_null(res) @@ -505,11 +506,13 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key( #[no_mangle] pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key( extsk: *const c_char, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { + let network = parse_network(network_id)?; let extsk = CStr::from_ptr(extsk).to_str()?; let extfvk = match decode_extended_spending_key( - NETWORK.hrp_sapling_extended_spending_key(), + network.hrp_sapling_extended_spending_key(), &extsk, ) { Ok(Some(extsk)) => ExtendedFullViewingKey::from(&extsk), @@ -525,7 +528,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key( }; let encoded = encode_extended_full_viewing_key( - NETWORK.hrp_sapling_extended_full_viewing_key(), + network.hrp_sapling_extended_full_viewing_key(), &extfvk, ); @@ -546,9 +549,11 @@ pub extern "C" fn zcashlc_init_blocks_table( hash_hex: *const c_char, time: u32, sapling_tree_hex: *const c_char, + network_id: u32, ) -> i32 { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len,network)?; let hash = { let mut hash = hex::decode(unsafe { CStr::from_ptr(hash_hex) }.to_str()?).unwrap(); hash.reverse(); @@ -579,9 +584,11 @@ pub extern "C" fn zcashlc_get_address( db_data: *const u8, db_data_len: usize, account: i32, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let account = if account >= 0 { account as u32 } else { @@ -592,7 +599,7 @@ pub extern "C" fn zcashlc_get_address( match (&db_data).get_address(account) { Ok(Some(addr)) => { - let addr_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &addr); + let addr_str = encode_payment_address(network.hrp_sapling_payment_address(), &addr); let c_str_addr = CString::new(addr_str).unwrap(); Ok(c_str_addr.into_raw()) } @@ -610,16 +617,19 @@ pub extern "C" fn zcashlc_get_address( /// Returns false in any other case /// Errors when the provided address belongs to another network #[no_mangle] -pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_char) -> bool { +pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_char, + network_id: u32) -> bool { let res = catch_panic(|| { + let network = parse_network(network_id)?; let addr = CStr::from_ptr(address).to_str()?; - Ok(is_valid_shielded_address(&addr)) + Ok(is_valid_shielded_address(&addr, &network)) }); unwrap_exc_or(res, false) } -fn is_valid_shielded_address(address: &str) -> bool { - match RecipientAddress::decode(&NETWORK, &address) { +fn is_valid_shielded_address(address: &str, + network: &Network) -> bool { + match RecipientAddress::decode(&network, &address) { Some(addr) => match addr { RecipientAddress::Shielded(_) => true, RecipientAddress::Transparent(_) => false, @@ -631,20 +641,24 @@ fn is_valid_shielded_address(address: &str) -> bool { /// Returns true when the address is valid and transparent. /// Returns false in any other case #[no_mangle] -pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_char) -> bool { +pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_char, + network_id: u32) -> bool { let res = catch_panic(|| { + let network = parse_network(network_id)?; let addr = CStr::from_ptr(address).to_str()?; - Ok(is_valid_transparent_address(&addr)) + Ok(is_valid_transparent_address(&addr, &network)) }); unwrap_exc_or(res, false) } /// returns whether the given viewing key is valid or not #[no_mangle] -pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char) -> bool { +pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char, + network_id: u32) -> bool { let res = catch_panic(|| { + let network = parse_network(network_id)?; let vkstr = CStr::from_ptr(key).to_str()?; - match decode_extended_full_viewing_key(&NETWORK.hrp_sapling_extended_full_viewing_key(), &vkstr) { + match decode_extended_full_viewing_key(&network.hrp_sapling_extended_full_viewing_key(), &vkstr) { Ok(s) => match s { None => Ok(false), _ => Ok(true), @@ -654,8 +668,10 @@ pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char) -> boo }); unwrap_exc_or(res, false) } -fn is_valid_transparent_address(address: &str) -> bool { - match RecipientAddress::decode(&NETWORK, &address) { + +fn is_valid_transparent_address(address: &str, + network: &Network) -> bool { + match RecipientAddress::decode(&network, &address) { Some(addr) => match addr { RecipientAddress::Shielded(_) => false, RecipientAddress::Transparent(_) => true, @@ -666,9 +682,15 @@ fn is_valid_transparent_address(address: &str) -> bool { /// Returns the balance for the account, including all unspent notes that we know about. #[no_mangle] -pub extern "C" fn zcashlc_get_balance(db_data: *const u8, db_data_len: usize, account: i32) -> i64 { +pub extern "C" fn zcashlc_get_balance( + db_data: *const u8, + db_data_len: usize, + account: i32, + network_id: u32, +) -> i64 { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; if account >= 0 { let (_, max_height) = (&db_data) @@ -698,9 +720,11 @@ pub extern "C" fn zcashlc_get_verified_balance( db_data: *const u8, db_data_len: usize, account: i32, + network_id: u32, ) -> i64 { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; if account >= 0 { (&db_data) .get_target_and_anchor_heights() @@ -730,11 +754,13 @@ pub extern "C" fn zcashlc_get_verified_transparent_balance( db_data: *const u8, db_data_len: usize, address: *const c_char, + network_id: u32, ) -> i64 { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let addr = unsafe { CStr::from_ptr(address).to_str()? }; - let taddr = TransparentAddress::decode(&NETWORK, &addr).unwrap(); + let taddr = TransparentAddress::decode(&network, &addr).unwrap(); let amount = (&db_data) .get_target_and_anchor_heights() .map_err(|e| format_err!("Error while fetching anchor height: {}", e)) @@ -764,11 +790,13 @@ pub extern "C" fn zcashlc_get_total_transparent_balance( db_data: *const u8, db_data_len: usize, address: *const c_char, + network_id: u32, ) -> i64 { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let addr = unsafe { CStr::from_ptr(address).to_str()? }; - let taddr = TransparentAddress::decode(&NETWORK, &addr).unwrap(); + let taddr = TransparentAddress::decode(&network, &addr).unwrap(); let amount = (&db_data) .get_target_and_anchor_heights() .map_err(|e| format_err!("Error while fetching anchor height: {}", e)) @@ -803,9 +831,11 @@ pub extern "C" fn zcashlc_get_received_memo_as_utf8( db_data: *const u8, db_data_len: usize, id_note: i64, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let memo = (&db_data).get_memo(NoteId::ReceivedNoteId(id_note)) .map_err(|e| format_err!("An error occurred retrieving the memo, {}", e)) @@ -833,9 +863,11 @@ pub extern "C" fn zcashlc_get_sent_memo_as_utf8( db_data: *const u8, db_data_len: usize, id_note: i64, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let memo = (&db_data).get_memo(NoteId::SentNoteId(id_note)) .map_err(|e| format_err!("An error occurred retrieving the memo, {}", e)) @@ -874,16 +906,18 @@ pub extern "C" fn zcashlc_validate_combined_chain( db_cache_len: usize, db_data: *const u8, db_data_len: usize, + network_id, u32, ) -> i32 { let res = catch_panic(|| { + let network = parse_network(network_id)?; let block_db = block_db(db_cache, db_cache_len)?; - let db_data = wallet_db(db_data, db_data_len)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let validate_from = (&db_data) .get_max_height_hash() .map_err(|e| format_err!("Error while validating chain: {}", e))?; - let val_res = validate_chain(&NETWORK, &block_db, validate_from); + let val_res = validate_chain(&network, &block_db, validate_from); if let Err(e) = val_res { match e { @@ -905,12 +939,14 @@ pub extern "C" fn zcashlc_get_nearest_rewind_height( db_data: *const u8, db_data_len: usize, height: i32, + network_id: u32, ) -> i32 { let res = catch_panic(|| { if height < 100 { Ok(height) } else { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let height = BlockHeight::try_from(height)?; match get_rewind_height(&db_data) { Ok(Some(best_height)) => { @@ -937,9 +973,11 @@ pub extern "C" fn zcashlc_rewind_to_height( db_data: *const u8, db_data_len: usize, height: i32, + network_id: u32, ) -> bool { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let height = BlockHeight::try_from(height)?; rewind_to_height(&db_data, height) @@ -970,17 +1008,19 @@ pub extern "C" fn zcashlc_scan_blocks( db_data: *const u8, db_data_len: usize, scan_limit: u32, + network_id: u32, ) -> i32 { let res = catch_panic(|| { + let network = parse_network(network_id)?; let block_db = block_db(db_cache, db_cache_len)?; - let db_read = wallet_db(db_data, db_data_len)?; + let db_read = wallet_db(db_data, db_data_len, network)?; let mut db_data = db_read.get_update_ops()?; let limit = if scan_limit <= 0 { None } else { Some(scan_limit) }; - match scan_cached_blocks(&NETWORK, &block_db, &mut db_data, limit) { + match scan_cached_blocks(&network, &block_db, &mut db_data, limit) { Ok(()) => Ok(1), Err(e) => Err(format_err!("Error while scanning blocks: {}", e)), } @@ -1000,9 +1040,11 @@ pub extern "C" fn zcashlc_put_utxo( script_bytes_len: usize, value: i64, height: i32, + network_id: u32, ) -> bool { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let mut db_data = db_data.get_update_ops()?; let addr = unsafe { CStr::from_ptr(address_str).to_str()? }; @@ -1013,7 +1055,7 @@ pub extern "C" fn zcashlc_put_utxo( let script_bytes = unsafe { slice::from_raw_parts(script_bytes, script_bytes_len) }; let script = script_bytes.to_vec(); - let address = TransparentAddress::decode(&NETWORK, &addr).unwrap(); + let address = TransparentAddress::decode(&network, &addr).unwrap(); let output = WalletTransparentOutput { address: address, @@ -1036,12 +1078,14 @@ pub unsafe extern "C" fn zcashlc_clear_utxos( db_data_len: usize, taddress: *const c_char, above_height: i32, + network_id: u32, ) -> i32 { let res = catch_panic(|| { - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let mut db_data = db_data.get_update_ops()?; let addr = CStr::from_ptr(taddress).to_str()?; - let taddress = TransparentAddress::decode(&NETWORK, &addr).unwrap(); + let taddress = TransparentAddress::decode(&network, &addr).unwrap(); let height = BlockHeight::from(above_height as u32); match delete_utxos_above(&mut db_data, &taddress, height) { Ok(rows) => Ok(rows as i32), @@ -1057,14 +1101,16 @@ pub extern "C" fn zcashlc_decrypt_and_store_transaction( db_data_len: usize, tx: *const u8, tx_len: usize, + network_id: u32, ) -> i32 { let res = catch_panic(|| { - let db_read = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_read = wallet_db(db_data, db_data_len, network)?; let mut db_data = db_read.get_update_ops()?; let tx_bytes = unsafe { slice::from_raw_parts(tx, tx_len) }; let tx = Transaction::read(&tx_bytes[..])?; - match decrypt_and_store_transaction(&NETWORK, &mut db_data, &tx) { + match decrypt_and_store_transaction(&network, &mut db_data, &tx) { Ok(()) => Ok(1), Err(e) => Err(format_err!("Error while decrypting transaction: {}", e)), } @@ -1093,9 +1139,11 @@ pub extern "C" fn zcashlc_create_to_address( spend_params_len: usize, output_params: *const u8, output_params_len: usize, + network_id: u32, ) -> i64 { let res = catch_panic(|| { - let db_read = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_read = wallet_db(db_data, db_data_len, network)?; let mut db_data = db_read.get_update_ops()?; let account = if account >= 0 { account as u32 @@ -1118,7 +1166,7 @@ pub extern "C" fn zcashlc_create_to_address( })); let extsk = - match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk) + match decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), &extsk) { Ok(Some(extsk)) => extsk, Ok(None) => { @@ -1129,7 +1177,7 @@ pub extern "C" fn zcashlc_create_to_address( } }; - let to = match RecipientAddress::decode(&NETWORK, &to) { + let to = match RecipientAddress::decode(&network, &to) { Some(to) => to, None => { return Err(format_err!("PaymentAddress is for the wrong network")); @@ -1149,7 +1197,7 @@ pub extern "C" fn zcashlc_create_to_address( create_spend_to_address( &mut db_data, - &NETWORK, + &network, prover, AccountId(account), &extsk, @@ -1164,9 +1212,13 @@ pub extern "C" fn zcashlc_create_to_address( } #[no_mangle] -pub extern "C" fn zcashlc_branch_id_for_height(height: i32) -> i32 { +pub extern "C" fn zcashlc_branch_id_for_height( + height: i32, + network_id: u32, +) -> i32 { let res = catch_panic(|| { - let branch: BranchId = BranchId::for_height(&NETWORK, BlockHeight::from(height as u32)); + let network = parse_network(network_id)?; + let branch: BranchId = BranchId::for_height(&network, BlockHeight::from(height as u32)); let branch_id: u32 = u32::from(branch); Ok(branch_id as i32) }); @@ -1209,9 +1261,10 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed( seed_len: usize, account: i32, index: i32, + network_id: u32, ) -> *mut c_char { - let res = catch_panic(|| { + let network = parse_network(network_id)?; let seed = slice::from_raw_parts(seed, seed_len); let account = if account >= 0 { account as u32 @@ -1224,7 +1277,7 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed( } else { return Err(format_err!("index argument must be positive")); }; - let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index).unwrap(); + let sk = derive_secret_key_from_seed(&network, &seed, AccountId(account), index).unwrap(); let sk_wif = Wif::from_secret_key(&sk, true); Ok(CString::new(sk_wif.0.to_string()).unwrap().into_raw()) @@ -1239,9 +1292,11 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed( seed_len: usize, account: i32, index: i32, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { let seed = slice::from_raw_parts(seed, seed_len); + let network = parse_network(network_id)?; let account = if account >= 0 { account as u32 } else { @@ -1253,9 +1308,9 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed( } else { return Err(format_err!("index argument must be positive")); }; - let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index); + let sk = derive_secret_key_from_seed(&network, &seed, AccountId(account), index); let taddr = derive_transparent_address_from_secret_key(&sk.unwrap()) - .encode(&NETWORK); + .encode(&network); Ok(CString::new(taddr).unwrap().into_raw()) }); @@ -1266,9 +1321,10 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed( #[no_mangle] pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key( tsk: *const c_char, + network_id: u32, ) -> *mut c_char { let res = catch_panic(|| { - + let network = parse_network(network_id)?; let tsk_wif = CStr::from_ptr(tsk).to_str()?; let sk: SecretKey = (&Wif(tsk_wif.to_string())).try_into().expect("invalid private key WIF"); @@ -1276,7 +1332,7 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key( // derive the corresponding t-address let taddr = derive_transparent_address_from_secret_key(&sk) - .encode(&NETWORK); + .encode(&network); Ok(CString::new(taddr).unwrap().into_raw()) }); unwrap_exc_or_null(res) @@ -1324,10 +1380,11 @@ pub extern "C" fn zcashlc_shield_funds( spend_params_len: usize, output_params: *const u8, output_params_len: usize, + network_id: u32, ) -> i64 { let res = catch_panic(|| { - - let db_data = wallet_db(db_data, db_data_len)?; + let network = parse_network(network_id)?; + let db_data = wallet_db(db_data, db_data_len, network)?; let mut update_ops = (&db_data) .get_update_ops() .map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?; @@ -1351,7 +1408,7 @@ pub extern "C" fn zcashlc_shield_funds( let sk:SecretKey = (&Wif(tsk_wif.to_string())).try_into()?; let extsk = - match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk) + match decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), &extsk) { Ok(Some(extsk)) => extsk, Ok(None) => { @@ -1366,7 +1423,7 @@ pub extern "C" fn zcashlc_shield_funds( let memo_bytes = MemoBytes::from(memo); // shield_funds(&db_cache, &db_data, account, &tsk, &extsk, &memo, &spend_params, &output_params) shield_funds(&mut update_ops, - &NETWORK, + &network, LocalTxProver::new(spend_params, output_params), AccountId(account), &sk, From 0f8c588a8c1d216423e64a76c1999316611db23f Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 22 Jul 2021 11:50:54 -0300 Subject: [PATCH 02/17] Lib.rs compiles --- ZcashLightClientKit/zcashlc/zcashlc.h | 103 +++++++++++++++++--------- rust/src/lib.rs | 80 +++++++++++--------- 2 files changed, 115 insertions(+), 68 deletions(-) diff --git a/ZcashLightClientKit/zcashlc/zcashlc.h b/ZcashLightClientKit/zcashlc/zcashlc.h index 8c3e4c3a..2221124b 100644 --- a/ZcashLightClientKit/zcashlc/zcashlc.h +++ b/ZcashLightClientKit/zcashlc/zcashlc.h @@ -13,7 +13,7 @@ typedef struct { uintptr_t len; } FFIUVKBoxedSlice; -int32_t zcashlc_branch_id_for_height(int32_t height); +int32_t zcashlc_branch_id_for_height(int32_t height, uint32_t network_id); /** * Clears the record of the last error message. @@ -23,7 +23,8 @@ void zcashlc_clear_last_error(void); int32_t zcashlc_clear_utxos(const uint8_t *db_data, uintptr_t db_data_len, const char *taddress, - int32_t above_height); + int32_t above_height, + uint32_t network_id); /** * Creates a transaction paying the specified address from the given account. @@ -45,18 +46,20 @@ int64_t zcashlc_create_to_address(const uint8_t *db_data, const uint8_t *spend_params, uintptr_t spend_params_len, const uint8_t *output_params, - uintptr_t output_params_len); + uintptr_t output_params_len, + uint32_t network_id); int32_t zcashlc_decrypt_and_store_transaction(const uint8_t *db_data, uintptr_t db_data_len, const uint8_t *tx, - uintptr_t tx_len); + uintptr_t tx_len, + uint32_t network_id); /** * derives a shielded address from the given extended full viewing key. * call zcashlc_string_free with the returned pointer when done using it */ -char *zcashlc_derive_extended_full_viewing_key(const char *extsk); +char *zcashlc_derive_extended_full_viewing_key(const char *extsk, uint32_t network_id); /** * Derives Extended Full Viewing Keys from the given seed into 'accounts' number of accounts. @@ -68,7 +71,8 @@ char *zcashlc_derive_extended_full_viewing_key(const char *extsk); char **zcashlc_derive_extended_full_viewing_keys(const uint8_t *seed, uintptr_t seed_len, int32_t accounts, - uintptr_t *capacity_ret); + uintptr_t *capacity_ret, + uint32_t network_id); /** * Derives Extended Spending Keys from the given seed into 'accounts' number of accounts. @@ -80,7 +84,8 @@ char **zcashlc_derive_extended_full_viewing_keys(const uint8_t *seed, char **zcashlc_derive_extended_spending_keys(const uint8_t *seed, uintptr_t seed_len, int32_t accounts, - uintptr_t *capacity_ret); + uintptr_t *capacity_ret, + uint32_t network_id); /** * derives a shielded address from the given seed. @@ -88,24 +93,25 @@ char **zcashlc_derive_extended_spending_keys(const uint8_t *seed, */ char *zcashlc_derive_shielded_address_from_seed(const uint8_t *seed, uintptr_t seed_len, - int32_t account_index); + int32_t account_index, + uint32_t network_id); /** * derives a shielded address from the given viewing key. * call zcashlc_string_free with the returned pointer when done using it */ -char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk); +char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk, uint32_t network_id); /** * derives a shielded address from the given viewing key. * call zcashlc_string_free with the returned pointer when done using it */ -char *zcashlc_derive_transparent_address_from_public_key(const char *pubkey); +char *zcashlc_derive_transparent_address_from_public_key(const char *pubkey, uint32_t network_id); /** * Derives a transparent address from the given secret key enconded as a WIF string */ -char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk); +char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk, uint32_t network_id); /** * Derives a transparent address from the given seed @@ -113,7 +119,8 @@ char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk); char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed, uintptr_t seed_len, int32_t account, - int32_t index); + int32_t index, + uint32_t network_id); /** * TEST TEST 123 TEST @@ -124,11 +131,13 @@ char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed, char *zcashlc_derive_transparent_private_key_from_seed(const uint8_t *seed, uintptr_t seed_len, int32_t account, - int32_t index); + int32_t index, + uint32_t network_id); FFIUVKBoxedSlice *zcashlc_derive_unified_viewing_keys_from_seed(const uint8_t *seed, uintptr_t seed_len, - int32_t accounts); + int32_t accounts, + uint32_t network_id); /** * Copies the last error message into the provided allocated buffer. @@ -142,16 +151,23 @@ void zcashlc_free_uvk_array(FFIUVKBoxedSlice *uvks); * * Call `zcashlc_string_free` on the returned pointer when you are finished with it. */ -char *zcashlc_get_address(const uint8_t *db_data, uintptr_t db_data_len, int32_t account); +char *zcashlc_get_address(const uint8_t *db_data, + uintptr_t db_data_len, + int32_t account, + uint32_t network_id); /** * Returns the balance for the account, including all unspent notes that we know about. */ -int64_t zcashlc_get_balance(const uint8_t *db_data, uintptr_t db_data_len, int32_t account); +int64_t zcashlc_get_balance(const uint8_t *db_data, + uintptr_t db_data_len, + int32_t account, + uint32_t network_id); int32_t zcashlc_get_nearest_rewind_height(const uint8_t *db_data, uintptr_t db_data_len, - int32_t height); + int32_t height, + uint32_t network_id); /** * Returns the memo for a received note, if it is known and a valid UTF-8 string. @@ -163,7 +179,8 @@ int32_t zcashlc_get_nearest_rewind_height(const uint8_t *db_data, */ char *zcashlc_get_received_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_len, - int64_t id_note); + int64_t id_note, + uint32_t network_id); /** * Returns the memo for a sent note, if it is known and a valid UTF-8 string. @@ -173,7 +190,10 @@ char *zcashlc_get_received_memo_as_utf8(const uint8_t *db_data, * * Call `zcashlc_string_free` on the returned pointer when you are finished with it. */ -char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_len, int64_t id_note); +char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, + uintptr_t db_data_len, + int64_t id_note, + uint32_t network_id); /** * Returns the verified transparent balance for the address, which ignores utxos that have been @@ -181,7 +201,8 @@ char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_le */ int64_t zcashlc_get_total_transparent_balance(const uint8_t *db_data, uintptr_t db_data_len, - const char *address); + const char *address, + uint32_t network_id); /** * Returns the verified balance for the account, which ignores notes that have been @@ -189,7 +210,8 @@ int64_t zcashlc_get_total_transparent_balance(const uint8_t *db_data, */ int64_t zcashlc_get_verified_balance(const uint8_t *db_data, uintptr_t db_data_len, - int32_t account); + int32_t account, + uint32_t network_id); /** * Returns the verified transparent balance for the address, which ignores utxos that have been @@ -197,7 +219,8 @@ int64_t zcashlc_get_verified_balance(const uint8_t *db_data, */ int64_t zcashlc_get_verified_transparent_balance(const uint8_t *db_data, uintptr_t db_data_len, - const char *address); + const char *address, + uint32_t network_id); /** * Initialises the data database with the given number of accounts using the given seed. @@ -212,7 +235,8 @@ char **zcashlc_init_accounts_table(const uint8_t *db_data, const uint8_t *seed, uintptr_t seed_len, int32_t accounts, - uintptr_t *capacity_ret); + uintptr_t *capacity_ret, + uint32_t network_id); /** * Initialises the data database with the given extended full viewing keys @@ -220,7 +244,8 @@ char **zcashlc_init_accounts_table(const uint8_t *db_data, */ bool zcashlc_init_accounts_table_with_keys(const uint8_t *db_data, uintptr_t db_data_len, - FFIUVKBoxedSlice *uvks); + FFIUVKBoxedSlice *uvks, + uint32_t network_id); /** * Initialises the data database with the given block. @@ -233,30 +258,33 @@ int32_t zcashlc_init_blocks_table(const uint8_t *db_data, int32_t height, const char *hash_hex, uint32_t time, - const char *sapling_tree_hex); + const char *sapling_tree_hex, + uint32_t network_id); /** * Sets up the internal structure of the data database. */ -int32_t zcashlc_init_data_database(const uint8_t *db_data, uintptr_t db_data_len); +int32_t zcashlc_init_data_database(const uint8_t *db_data, + uintptr_t db_data_len, + uint32_t network_id); /** * Returns true when the address is valid and shielded. * Returns false in any other case * Errors when the provided address belongs to another network */ -bool zcashlc_is_valid_shielded_address(const char *address); +bool zcashlc_is_valid_shielded_address(const char *address, uint32_t network_id); /** * Returns true when the address is valid and transparent. * Returns false in any other case */ -bool zcashlc_is_valid_transparent_address(const char *address); +bool zcashlc_is_valid_transparent_address(const char *address, uint32_t network_id); /** * returns whether the given viewing key is valid or not */ -bool zcashlc_is_valid_viewing_key(const char *key); +bool zcashlc_is_valid_viewing_key(const char *key, uint32_t network_id); /** * Returns the length of the last error message to be logged. @@ -272,7 +300,8 @@ bool zcashlc_put_utxo(const uint8_t *db_data, const uint8_t *script_bytes, uintptr_t script_bytes_len, int64_t value, - int32_t height); + int32_t height, + uint32_t network_id); /** * Rewinds the data database to the given height. @@ -280,7 +309,10 @@ bool zcashlc_put_utxo(const uint8_t *db_data, * If the requested height is greater than or equal to the height of the last scanned * block, this function does nothing. */ -bool zcashlc_rewind_to_height(const uint8_t *db_data, uintptr_t db_data_len, int32_t height); +bool zcashlc_rewind_to_height(const uint8_t *db_data, + uintptr_t db_data_len, + int32_t height, + uint32_t network_id); /** * Scans new blocks added to the cache for any transactions received by the tracked @@ -302,7 +334,8 @@ int32_t zcashlc_scan_blocks(const uint8_t *db_cache, uintptr_t db_cache_len, const uint8_t *db_data, uintptr_t db_data_len, - uint32_t scan_limit); + uint32_t scan_limit, + uint32_t network_id); int64_t zcashlc_shield_funds(const uint8_t *db_data, uintptr_t db_data_len, @@ -313,7 +346,8 @@ int64_t zcashlc_shield_funds(const uint8_t *db_data, const uint8_t *spend_params, uintptr_t spend_params_len, const uint8_t *output_params, - uintptr_t output_params_len); + uintptr_t output_params_len, + uint32_t network_id); /** * Frees strings returned by other zcashlc functions. @@ -341,7 +375,8 @@ void zcashlc_string_free(char *s); int32_t zcashlc_validate_combined_chain(const uint8_t *db_cache, uintptr_t db_cache_len, const uint8_t *db_data, - uintptr_t db_data_len); + uintptr_t db_data_len, + uint32_t network_id); /** * Frees vectors of strings returned by other zcashlc functions. diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 0981af62..92a6a3ad 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -366,7 +366,7 @@ pub unsafe extern "C" fn zcashlc_derive_unified_viewing_keys_from_seed( .map(|account| { let extfvk = ExtendedFullViewingKey::from(&spending_key(&seed, network.coin_type(), AccountId(account))); let extpub = derive_public_key_from_seed(&network, &seed, AccountId(account), 0).unwrap(); - unified_viewing_key_new(&extfvk, &extpub) + unified_viewing_key_new(&extfvk, &extpub, network) }) .collect(); Ok(uvk_vec_to_ffi(uvks)) @@ -629,7 +629,7 @@ pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_cha fn is_valid_shielded_address(address: &str, network: &Network) -> bool { - match RecipientAddress::decode(&network, &address) { + match RecipientAddress::decode(network, &address) { Some(addr) => match addr { RecipientAddress::Shielded(_) => true, RecipientAddress::Transparent(_) => false, @@ -671,7 +671,7 @@ pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char, fn is_valid_transparent_address(address: &str, network: &Network) -> bool { - match RecipientAddress::decode(&network, &address) { + match RecipientAddress::decode(network, &address) { Some(addr) => match addr { RecipientAddress::Shielded(_) => false, RecipientAddress::Transparent(_) => true, @@ -906,7 +906,7 @@ pub extern "C" fn zcashlc_validate_combined_chain( db_cache_len: usize, db_data: *const u8, db_data_len: usize, - network_id, u32, + network_id: u32, ) -> i32 { let res = catch_panic(|| { let network = parse_network(network_id)?; @@ -1337,36 +1337,6 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key( }); unwrap_exc_or_null(res) } - -// -// Helper code from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs -// - -/// A trait for converting a [u8] to base58 encoded string. -pub trait ToBase58Check { - /// Converts a value of `self` to a base58 value, returning the owned string. - /// The version is a coin-specific prefix that is added. - /// The suffix is any bytes that we want to add at the end (like the "iscompressed" flag for - /// Secret key encoding) - fn to_base58check(&self, version: &[u8], suffix: &[u8]) -> String; -} -impl ToBase58Check for [u8] { - fn to_base58check(&self, version: &[u8], suffix: &[u8]) -> String { - let mut payload: Vec = Vec::new(); - payload.extend_from_slice(version); - payload.extend_from_slice(self); - payload.extend_from_slice(suffix); - - let checksum = double_sha256(&payload); - payload.append(&mut checksum[..4].to_vec()); - payload.to_base58() - } -} -pub fn double_sha256(payload: &[u8]) -> Vec { - let h1 = Sha256::digest(&payload); - let h2 = Sha256::digest(&h1); - h2.to_vec() -} #[no_mangle] pub extern "C" fn zcashlc_shield_funds( @@ -1434,3 +1404,45 @@ pub extern "C" fn zcashlc_shield_funds( }); unwrap_exc_or(res, -1) } + +// +// Utility functions +// + +fn parse_network(value: u32) -> Result { + match value { + 0 => Ok(TestNetwork), + 1 => Ok(MainNetwork), + _ => Err(format_err!("Invalid network type: {}. Expected either 0 or 1 for Testnet or Mainnet, respectively.", value)) + } +} + +// +// Helper code from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs +// + +/// A trait for converting a [u8] to base58 encoded string. +pub trait ToBase58Check { + /// Converts a value of `self` to a base58 value, returning the owned string. + /// The version is a coin-specific prefix that is added. + /// The suffix is any bytes that we want to add at the end (like the "iscompressed" flag for + /// Secret key encoding) + fn to_base58check(&self, version: &[u8], suffix: &[u8]) -> String; +} +impl ToBase58Check for [u8] { + fn to_base58check(&self, version: &[u8], suffix: &[u8]) -> String { + let mut payload: Vec = Vec::new(); + payload.extend_from_slice(version); + payload.extend_from_slice(self); + payload.extend_from_slice(suffix); + + let checksum = double_sha256(&payload); + payload.append(&mut checksum[..4].to_vec()); + payload.to_base58() + } +} +pub fn double_sha256(payload: &[u8]) -> Vec { + let h1 = Sha256::digest(&payload); + let h2 = Sha256::digest(&h1); + h2.to_vec() +} \ No newline at end of file From 31e9bdfbec6c5e82e0ead71f4dc32c15a728bad8 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 22 Jul 2021 15:18:45 -0300 Subject: [PATCH 03/17] Pass Network Id on rust welding --- .../Rust/ZcashRustBackend.swift | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/ZcashLightClientKit/Rust/ZcashRustBackend.swift b/ZcashLightClientKit/Rust/ZcashRustBackend.swift index d614f469..62b1ba1f 100644 --- a/ZcashLightClientKit/Rust/ZcashRustBackend.swift +++ b/ZcashLightClientKit/Rust/ZcashRustBackend.swift @@ -9,6 +9,9 @@ import Foundation class ZcashRustBackend: ZcashRustBackendWelding { + static var networkId: UInt32 { + ZcashSDK.isMainnet ? 1 : 0 + } static func lastError() -> RustWeldingError? { guard let message = getLastError() else { return nil } @@ -38,7 +41,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { */ static func initDataDb(dbData: URL) throws { let dbData = dbData.osStr() - guard zcashlc_init_data_database(dbData.0, dbData.1) != 0 else { + guard zcashlc_init_data_database(dbData.0, dbData.1, networkId) != 0 else { if let error = lastError() { throw throwDataDbError(error) } @@ -51,7 +54,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { return false } - guard zcashlc_is_valid_shielded_address([CChar](address.utf8CString)) else { + guard zcashlc_is_valid_shielded_address([CChar](address.utf8CString), networkId) else { if let error = lastError() { throw error } @@ -65,7 +68,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { return false } - guard zcashlc_is_valid_transparent_address([CChar](address.utf8CString)) else { + guard zcashlc_is_valid_transparent_address([CChar](address.utf8CString), networkId) else { if let error = lastError() { throw error } @@ -79,7 +82,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { return false } - guard zcashlc_is_valid_viewing_key([CChar](key.utf8CString)) else { + guard zcashlc_is_valid_viewing_key([CChar](key.utf8CString), networkId) else { if let error = lastError() { throw error } @@ -91,7 +94,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? { let dbData = dbData.osStr() var capacity = UInt(0); - let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts, &capacity) + let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts, &capacity, networkId) if extsksCStr == nil { return nil } @@ -133,7 +136,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { let slice = UnsafeMutablePointer.allocate(capacity: 1) slice.initialize(to: FFIUVKBoxedSlice(ptr: p.baseAddress, len: UInt(p.count))) - result = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, slice) + result = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, slice, networkId) slice.deinitialize(count: 1) } @@ -180,7 +183,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw RustWeldingError.malformedStringInput } - guard zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString)) != 0 else { + guard zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString), networkId) != 0 else { if let error = lastError() { throw error } @@ -191,7 +194,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func getAddress(dbData: URL, account: Int32) -> String? { let dbData = dbData.osStr() - guard let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account) else { return nil } + guard let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account, networkId) else { return nil } let address = String(validatingUTF8: addressCStr) zcashlc_string_free(addressCStr) @@ -200,12 +203,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func getBalance(dbData: URL, account: Int32) -> Int64 { let dbData = dbData.osStr() - return zcashlc_get_balance(dbData.0, dbData.1, account) + return zcashlc_get_balance(dbData.0, dbData.1, account, networkId) } static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 { let dbData = dbData.osStr() - return zcashlc_get_verified_balance(dbData.0, dbData.1, account) + return zcashlc_get_verified_balance(dbData.0, dbData.1, account, networkId) } static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 { @@ -215,7 +218,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { let dbData = dbData.osStr() - return zcashlc_get_verified_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString)) + return zcashlc_get_verified_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkId) } static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 { @@ -224,7 +227,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { } let dbData = dbData.osStr() - return zcashlc_get_total_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString)) + return zcashlc_get_total_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkId) } static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> Int32 { let dbData = dbData.osStr() @@ -233,7 +236,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw RustWeldingError.malformedStringInput } - let result = zcashlc_clear_utxos(dbData.0, dbData.1, [CChar](address.utf8CString), Int32(sinceHeight)) + let result = zcashlc_clear_utxos(dbData.0, dbData.1, [CChar](address.utf8CString), Int32(sinceHeight), networkId) guard result > 0 else { if let error = lastError() { @@ -261,7 +264,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { script, UInt(script.count), value, - Int32(height)) else { + Int32(height), + networkId) else { if let error = lastError() { throw error } @@ -279,7 +283,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { let dbData = dbData.osStr() - guard let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote) else { return nil } + guard let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote, networkId) else { return nil } let memo = String(validatingUTF8: memoCStr) zcashlc_string_free(memoCStr) @@ -289,7 +293,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { let dbData = dbData.osStr() - guard let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote) else { return nil } + guard let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote, networkId) else { return nil } let memo = String(validatingUTF8: memoCStr) zcashlc_string_free(memoCStr) @@ -299,28 +303,28 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 { let dbCache = dbCache.osStr() let dbData = dbData.osStr() - return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1) + return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkId) } static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32 { let dbData = dbData.osStr() - return zcashlc_get_nearest_rewind_height(dbData.0, dbData.1, height) + return zcashlc_get_nearest_rewind_height(dbData.0, dbData.1, height, networkId) } static func rewindToHeight(dbData: URL, height: Int32) -> Bool { let dbData = dbData.osStr() - return zcashlc_rewind_to_height(dbData.0, dbData.1, height) + return zcashlc_rewind_to_height(dbData.0, dbData.1, height, networkId) } static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32 = 0) -> Bool { let dbCache = dbCache.osStr() let dbData = dbData.osStr() - return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit) != 0 + return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit, networkId) != 0 } static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool { let dbData = dbData.osStr() - return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count)) != 0 + return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count), networkId) != 0 } static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { @@ -337,7 +341,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { spendParamsPath, UInt(spendParamsPath.lengthOfBytes(using: .utf8)), outputParamsPath, - UInt(outputParamsPath.lengthOfBytes(using: .utf8))) + UInt(outputParamsPath.lengthOfBytes(using: .utf8)), + networkId) } static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { @@ -353,7 +358,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { spendParamsPath, UInt(spendParamsPath.lengthOfBytes(using: .utf8)), outputParamsPath, - UInt(outputParamsPath.lengthOfBytes(using: .utf8))) + UInt(outputParamsPath.lengthOfBytes(using: .utf8)), + networkId) } static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String? { @@ -362,7 +368,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw RustWeldingError.malformedStringInput } - guard let extsk = zcashlc_derive_extended_full_viewing_key([CChar](spendingKey.utf8CString)) else { + guard let extsk = zcashlc_derive_extended_full_viewing_key([CChar](spendingKey.utf8CString), + networkId) else { if let error = lastError() { throw error } @@ -377,7 +384,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? { var capacity = UInt(0); - guard let extsksCStr = zcashlc_derive_extended_full_viewing_keys(seed, UInt(seed.count), accounts, &capacity) else { + guard let extsksCStr = zcashlc_derive_extended_full_viewing_keys(seed, UInt(seed.count), accounts, &capacity, networkId) else { if let error = lastError() { throw error } @@ -394,7 +401,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? { var capacity = UInt(0); - guard let extsksCStr = zcashlc_derive_extended_spending_keys(seed, UInt(seed.count), accounts, &capacity) else { + guard let extsksCStr = zcashlc_derive_extended_spending_keys(seed, UInt(seed.count), accounts, &capacity, networkId) else { if let error = lastError() { throw error } @@ -411,7 +418,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] { - guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts)) else { + guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts), networkId) else { if let error = lastError() { throw error } @@ -444,7 +451,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { } static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String? { - guard let zaddrCStr = zcashlc_derive_shielded_address_from_seed(seed, UInt(seed.count), accountIndex) else { + guard let zaddrCStr = zcashlc_derive_shielded_address_from_seed(seed, UInt(seed.count), accountIndex, networkId) else { if let error = lastError() { throw error } @@ -462,7 +469,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw RustWeldingError.malformedStringInput } - guard let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key([CChar](extfvk.utf8CString)) else { + guard let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key([CChar](extfvk.utf8CString), networkId) else { if let error = lastError() { throw error } @@ -477,7 +484,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? { - guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index)) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkId) else { if let error = lastError() { throw error } @@ -490,7 +497,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { } static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? { - guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index)) else { + guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkId) else { if let error = lastError() { throw error } @@ -506,7 +513,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw RustWeldingError.malformedStringInput } - guard let tAddrCStr = zcashlc_derive_transparent_address_from_public_key([CChar](pubkey.utf8CString)), let tAddr = String(validatingUTF8: tAddrCStr) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_public_key([CChar](pubkey.utf8CString), networkId), let tAddr = String(validatingUTF8: tAddrCStr) else { if let error = lastError() { throw error } @@ -520,7 +527,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { guard !tsk.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString)) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString), networkId) else { if let error = lastError() { throw error } @@ -532,7 +539,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { } static func consensusBranchIdFor(height: Int32) throws -> Int32 { - let branchId = zcashlc_branch_id_for_height(height) + let branchId = zcashlc_branch_id_for_height(height, networkId) guard branchId != -1 else { throw RustWeldingError.noConsensusBranchId(height: height) From d368e6d6bddeb424f1765940c5ff9276cdc7ec70 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 26 Jul 2021 20:22:30 -0300 Subject: [PATCH 04/17] Fixed All compilation errors --- Constants/ZcashSDK.swift | 242 ++++++++++++++++++ DerivationToolTests/DerivationToolTests.swift | 27 +- .../DatabaseMigrationManager.swift | 13 +- .../CompactBlockDownloadOperation.swift | 11 +- .../CompactBlockEnhancementOperation.swift | 5 +- .../Processor/CompactBlockProcessor.swift | 75 +++--- .../CompactBlockScanningOperation.swift | 16 +- .../CompactBlockValidationInformation.swift | 9 +- .../FetchUnspentTxOutputsOperation.swift | 13 +- .../Entity/TransactionEntity.swift | 6 +- .../Extensions/ZcashSDK+extensions.swift | 38 +-- ZcashLightClientKit/Initializer.swift | 25 +- .../Providers/ResourceProvider.swift | 15 +- .../Rust/ZcashRustBackend.swift | 184 +++++++------ .../Rust/ZcashRustBackendWelding.swift | 70 ++--- .../Service/LightWalletGRPCService.swift | 6 +- .../Protocolbuffer+Extensions.swift | 16 -- ZcashLightClientKit/Tool/DerivationTool.swift | 32 ++- .../PersistentTransactionManager.swift | 12 +- .../WalletTransactionEncoder.swift | 14 +- .../UIKit/Synchronizer/SDKSynchronizer.swift | 18 +- 21 files changed, 548 insertions(+), 299 deletions(-) create mode 100644 Constants/ZcashSDK.swift diff --git a/Constants/ZcashSDK.swift b/Constants/ZcashSDK.swift new file mode 100644 index 00000000..6926a588 --- /dev/null +++ b/Constants/ZcashSDK.swift @@ -0,0 +1,242 @@ +// +// ZcashSDK.swift +// ZcashLightClientKit +// +// Created by Francisco Gindre on 7/22/21. +// + +import Foundation + +public enum NetworkType { + case mainnet + case testnet + + var constants: NetworkConstants.Type { + switch self { + case .mainnet: + return ZcashSDKMainnet.self + case .testnet: + return ZcashSDKTestnet.self + } + } +} + +extension NetworkType { + static func forChainName(_ chainame: String) -> NetworkType? { + switch chainame { + case "test": + return .testnet + case "main": + return .mainnet + default: + return nil + } + } + + var networkId: UInt32 { + switch self { + case .mainnet: + return 1 + case .testnet: + return 0 + } + } +} + +/** + Constants of ZcashLightClientKit. this constants don't + */ +public class ZcashSDK { + + /** + The number of zatoshi that equal 1 ZEC. + */ + public static var ZATOSHI_PER_ZEC: BlockHeight = 100_000_000 + + /** + The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design. + */ + public static var MAX_REORG_SIZE = 100 + /** + The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled + by the rust backend but it is helpful to know what it is set to and should be kept in sync. + */ + public static var EXPIRY_OFFSET = 20 + // + // Defaults + // + /** + Default size of batches of blocks to request from the compact block service. + */ + public static var DEFAULT_BATCH_SIZE = 100 + /** + Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average + block time. + */ + public static var DEFAULT_POLL_INTERVAL: TimeInterval = 20 + /** + Default attempts at retrying. + */ + public static var DEFAULT_RETRIES: Int = 5 + /** + The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than + this before retyring. + */ + public static var DEFAULT_MAX_BACKOFF_INTERVAL: TimeInterval = 600 + /** + Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the + reorg but smaller than the theoretical max reorg size of 100. + */ + public static var DEFAULT_REWIND_DISTANCE: Int = 10 + /** + The number of blocks to allow before considering our data to be stale. This usually helps with what to do when + returning from the background and is exposed via the Synchronizer's isStale function. + */ + public static var DEFAULT_STALE_TOLERANCE: Int = 10 + + + /** + Default Name for LibRustZcash data.db + */ + public static var DEFAULT_DATA_DB_NAME = "data.db" + + /** + Default Name for Compact Block caches db + */ + public static var DEFAULT_CACHES_DB_NAME = "caches.db" + /** + Default name for pending transactions db + */ + public static var DEFAULT_PENDING_DB_NAME = "pending.db" + + /** + File name for the sapling spend params + */ + public static var SPEND_PARAM_FILE_NAME = "sapling-spend.params" + /** + File name for the sapling output params + */ + public static var OUTPUT_PARAM_FILE_NAME = "sapling-output.params" + /** + The Url that is used by default in zcashd. + We'll want to make this externally configurable, rather than baking it into the SDK but + this will do for now, since we're using a cloudfront URL that already redirects. + */ + public static var CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/" +} + +public protocol NetworkConstants { + + /** + The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks + prior to this height, at all. + */ + static var SAPLING_ACTIVATION_HEIGHT: BlockHeight { get } + + /** + Default Name for LibRustZcash data.db + */ + static var DEFAULT_DATA_DB_NAME: String { get } + /** + Default Name for Compact Block caches db + */ + static var DEFAULT_CACHES_DB_NAME: String { get } + /** + Default name for pending transactions db + */ + static var DEFAULT_PENDING_DB_NAME: String { get } + static var DEFAULT_DB_NAME_PREFIX: String { get } + + /** + fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround + for librustzcash not figuring out the tx fee from the tx itself. + */ + static var FEE_CHANGE_HEIGHT: BlockHeight { get } + + + static func defaultFee(for height: BlockHeight) -> Int64 + +} + +public extension NetworkConstants { + + static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 { + guard height >= FEE_CHANGE_HEIGHT else { return 10_000 } + + return 1_000 + } +} + +public class ZcashSDKMainnet: NetworkConstants { + + private init() {} + + /** + The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks + prior to this height, at all. + */ + public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 419_200 + + /** + Default Name for LibRustZcash data.db + */ + public static var DEFAULT_DATA_DB_NAME = "data.db" + /** + Default Name for Compact Block caches db + */ + public static var DEFAULT_CACHES_DB_NAME = "caches.db" + /** + Default name for pending transactions db + */ + public static var DEFAULT_PENDING_DB_NAME = "pending.db" + public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_" + /** + File name for the sapling spend params + */ + public static var SPEND_PARAM_FILE_NAME = "sapling-spend.params" + /** + File name for the sapling output params + */ + public static var OUTPUT_PARAM_FILE_NAME = "sapling-output.params" + /** + The Url that is used by default in zcashd. + We'll want to make this externally configurable, rather than baking it into the SDK but + this will do for now, since we're using a cloudfront URL that already redirects. + */ + public static var CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/" + + public static var isMainnet = true + + public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_077_550 +} + +public class ZcashSDKTestnet: NetworkConstants { + private init() {} + + /** + The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks + prior to this height, at all. + */ + public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 280_000 + + /** + Default Name for LibRustZcash data.db + */ + public static var DEFAULT_DATA_DB_NAME = "data.db" + /** + Default Name for Compact Block caches db + */ + public static var DEFAULT_CACHES_DB_NAME = "caches.db" + /** + Default name for pending transactions db + */ + public static var DEFAULT_PENDING_DB_NAME = "pending.db" + + public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_testnet_" + + /** + Estimated height where wallets are supposed to change the fee + */ + public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_028_500 + +} diff --git a/DerivationToolTests/DerivationToolTests.swift b/DerivationToolTests/DerivationToolTests.swift index edc4db3d..7ed29364 100644 --- a/DerivationToolTests/DerivationToolTests.swift +++ b/DerivationToolTests/DerivationToolTests.swift @@ -17,11 +17,12 @@ class DerivationToolTests: XCTestCase { let expectedViewingKey = "zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy" + let derivationTool = DerivationTool(networkType: NetworkType.mainnet) let expectedTransparentAddress = "t1dRJRY7GmyeykJnMH38mdQoaZtFhn1QmGz" func testDeriveViewingKeysFromSeed() throws { let accounts: Int = 1 let seedBytes = [UInt8](seedData) - let viewingKeys = try DerivationTool.default.deriveViewingKeys(seed: seedBytes, numberOfAccounts: accounts) + let viewingKeys = try derivationTool.deriveViewingKeys(seed: seedBytes, numberOfAccounts: accounts) XCTAssertEqual(viewingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive") @@ -34,14 +35,14 @@ class DerivationToolTests: XCTestCase { } func testDeriveViewingKeyFromSpendingKeys() throws { - XCTAssertEqual(expectedViewingKey, try DerivationTool.default.deriveViewingKey(spendingKey: expectedSpendingKey)) + XCTAssertEqual(expectedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey)) } func testDeriveSpendingKeysFromSeed() throws { let accounts: Int = 1 let seedBytes = [UInt8](seedData) - let spendingKeys = try DerivationTool.default.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: accounts) + let spendingKeys = try derivationTool.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: accounts) XCTAssertEqual(spendingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive") guard let spendingKey = spendingKeys.first else { @@ -55,44 +56,44 @@ class DerivationToolTests: XCTestCase { func testDeriveShieldedAddressFromSeed() throws { let seedBytes = [UInt8](seedData) - let shieldedAddress = try DerivationTool.default.deriveShieldedAddress(seed: seedBytes, accountIndex: 0) + let shieldedAddress = try derivationTool.deriveShieldedAddress(seed: seedBytes, accountIndex: 0) XCTAssertEqual(shieldedAddress, testRecipientAddress) } func testDeriveShieldedAddressFromViewingKey() throws { - XCTAssertEqual(try DerivationTool.default.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress) + XCTAssertEqual(try derivationTool.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress) } func testDeriveTransparentAddressFromSeed() throws { - XCTAssertEqual(try DerivationTool.default.deriveTransparentAddress(seed: [UInt8](seedData)), expectedTransparentAddress) + XCTAssertEqual(try derivationTool.deriveTransparentAddress(seed: [UInt8](seedData)), expectedTransparentAddress) } func testIsValidViewingKey() throws { - XCTAssertTrue(try DerivationTool.default.isValidExtendedViewingKey("zxviews1q0dm7hkzqqqqpqplzv3f50rl4vay8uy5zg9e92f62lqg6gzu63rljety32xy5tcyenzuu3n386ws772nm6tp4sads8n37gff6nxmyz8dn9keehmapk0spc6pzx5uxepgu52xnwzxxnuja5tv465t9asppnj3eqncu3s7g3gzg5x8ss4ypkw08xwwyj7ky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7")) + XCTAssertTrue(try derivationTool.isValidExtendedViewingKey("zxviews1q0dm7hkzqqqqpqplzv3f50rl4vay8uy5zg9e92f62lqg6gzu63rljety32xy5tcyenzuu3n386ws772nm6tp4sads8n37gff6nxmyz8dn9keehmapk0spc6pzx5uxepgu52xnwzxxnuja5tv465t9asppnj3eqncu3s7g3gzg5x8ss4ypkw08xwwyj7ky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7")) - XCTAssertFalse(try DerivationTool.default.isValidExtendedViewingKey("zxviews1q0dm7hkzky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7")) + XCTAssertFalse(try derivationTool.isValidExtendedViewingKey("zxviews1q0dm7hkzky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7")) } func testDeriveSecretKeyFromSeed() throws { - XCTAssertEqual(try DerivationTool.default.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "KwqfQoTCuQdCLvzpAEtkt1o8J62WJuZXD3cGRAf1bgmPWuLamHLo") + XCTAssertEqual(try derivationTool.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "KwqfQoTCuQdCLvzpAEtkt1o8J62WJuZXD3cGRAf1bgmPWuLamHLo") } func testDeriveUnifiedKeysFromSeed() throws { - let unifiedKeys = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1) + let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1) XCTAssertEqual(unifiedKeys.count, 1) XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) - XCTAssertEqual(expectedTransparentAddress, try DerivationTool.default.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) } func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws { - let unifiedKeys = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10) + let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10) XCTAssertEqual(unifiedKeys.count, 10) XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) - XCTAssertEqual(expectedTransparentAddress, try DerivationTool.default.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) } } diff --git a/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift b/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift index 182fd79c..9a8b36df 100644 --- a/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift +++ b/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift @@ -25,13 +25,15 @@ class MigrationManager { var cacheDb: ConnectionProvider var dataDb: ConnectionProvider var pendingDb: ConnectionProvider - + var network: NetworkType init(cacheDbConnection: ConnectionProvider, dataDbConnection: ConnectionProvider, - pendingDbConnection: ConnectionProvider) { + pendingDbConnection: ConnectionProvider, + networkType: NetworkType) { self.cacheDb = cacheDbConnection self.dataDb = dataDbConnection self.pendingDb = pendingDbConnection + self.network = networkType } static let latestDataDbMigrationVersion: Int32 = DataDbMigrations.version1.rawValue @@ -149,7 +151,7 @@ class MigrationManager { LoggerProxy.debug(message) throw StorageError.migrationFailedWithMessage(message: message) } - let derivationTool = DerivationTool.default + let derivationTool = DerivationTool(networkType: self.network) for tuple in zip(accounts, viewingKeys) { let tAddr = try derivationTool.deriveTransparentAddressFromPublicKey(tuple.1.extpub) @@ -177,7 +179,10 @@ class MigrationManager { return } - let uvks = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: accounts.count) + + let derivationTool = DerivationTool(networkType: self.network) + + let uvks = try derivationTool.deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: accounts.count) try performVersion1Migration(viewingKeys: uvks) } diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift index acf769d9..8782541e 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift @@ -90,9 +90,6 @@ class CompactBlockStreamDownloadOperation: ZcashOperation { } let latestDownloaded = try storage.latestHeight() let startHeight = max(self.startHeight ?? BlockHeight.empty(), latestDownloaded) - guard startHeight >= ZcashSDK.SAPLING_ACTIVATION_HEIGHT else { - throw CompactBlockStreamDownloadOperationError.startHeightMissing - } self.cancelable = self.service.blockStream(startHeight: startHeight, endHeight: latestHeight) { [weak self] result in switch result { @@ -181,12 +178,8 @@ class CompactBlockBatchDownloadOperation: ZcashOperation { } self.startedHandler?() do { - - guard startHeight >= ZcashSDK.SAPLING_ACTIVATION_HEIGHT else { - throw CompactBlockBatchDownloadOperationError.startHeightMissing - } - - var localDownloadedHeight = try self.storage.latestHeight() + + let localDownloadedHeight = try self.storage.latestHeight() if localDownloadedHeight != startHeight { LoggerProxy.warn("provided startHeight (\(startHeight)) differs from local latest downloaded height (\(localDownloadedHeight))") startHeight = localDownloadedHeight + 1 diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift index 7c8ba4fc..ce57db60 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift @@ -24,6 +24,7 @@ class CompactBlockEnhancementOperation: ZcashOperation { var repository: TransactionRepository var maxRetries: Int = 5 var retries: Int = 0 + private(set) var network: NetworkType weak var progressDelegate: CompactBlockProgressDelegate? private var dataDb: URL @@ -34,6 +35,7 @@ class CompactBlockEnhancementOperation: ZcashOperation { downloader: CompactBlockDownloading, repository: TransactionRepository, range: BlockRange, + networkType: NetworkType, progressDelegate: CompactBlockProgressDelegate? = nil) { rustBackend = rustWelding self.dataDb = dataDb @@ -41,6 +43,7 @@ class CompactBlockEnhancementOperation: ZcashOperation { self.repository = repository self.range = range self.progressDelegate = progressDelegate + self.network = networkType super.init() } @@ -112,7 +115,7 @@ class CompactBlockEnhancementOperation: ZcashOperation { throw error } - guard rustBackend.decryptAndStoreTransaction(dbData: dataDb, tx: rawBytes) else { + guard rustBackend.decryptAndStoreTransaction(dbData: dataDb, tx: rawBytes, networkType: network) else { if let rustError = rustBackend.lastError() { throw EnhancementError.decryptError(error: rustError) } diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index 6040af5c..bb2f3c49 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -27,7 +27,7 @@ public enum CompactBlockProcessorError: Error { case criticalError case invalidAccount case wrongConsensusBranchId(expectedLocally: ConsensusBranchID, found: ConsensusBranchID) - case networkMismatch(expected: ZcashSDK.NetworkType, found: ZcashSDK.NetworkType) + case networkMismatch(expected: NetworkType, found: NetworkType) case saplingActivationMismatch(expected: BlockHeight, found: BlockHeight) } /** @@ -228,20 +228,23 @@ public class CompactBlockProcessor { public var maxBackoffInterval = ZcashSDK.DEFAULT_MAX_BACKOFF_INTERVAL public var rewindDistance = ZcashSDK.DEFAULT_REWIND_DISTANCE public var walletBirthday: BlockHeight + private(set) var network: NetworkType private(set) var saplingActivation: BlockHeight init ( - cacheDb: URL, - dataDb: URL, - downloadBatchSize: Int, - retries: Int, - maxBackoffInterval: TimeInterval, - rewindDistance: Int, - walletBirthday: BlockHeight, - saplingActivation: BlockHeight + cacheDb: URL, + dataDb: URL, + downloadBatchSize: Int, + retries: Int, + maxBackoffInterval: TimeInterval, + rewindDistance: Int, + walletBirthday: BlockHeight, + saplingActivation: BlockHeight, + network: NetworkType ) { self.cacheDb = cacheDb self.dataDb = dataDb + self.network = network self.downloadBatchSize = downloadBatchSize self.retries = retries self.maxBackoffInterval = maxBackoffInterval @@ -250,11 +253,12 @@ public class CompactBlockProcessor { self.saplingActivation = saplingActivation } - public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT){ + public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight, networkType: NetworkType){ self.cacheDb = cacheDb self.dataDb = dataDb self.walletBirthday = walletBirthday - self.saplingActivation = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + self.saplingActivation = networkType.constants.SAPLING_ACTIVATION_HEIGHT + self.network = networkType } } /** @@ -313,7 +317,7 @@ public class CompactBlockProcessor { private var transactionRepository: TransactionRepository private var accountRepository: AccountRepository private var rustBackend: ZcashRustBackendWelding.Type - var config: Configuration = Configuration.standard { + var config: Configuration { willSet { self.stop() } @@ -348,7 +352,7 @@ public class CompactBlockProcessor { - Throws CompactBlockProcessorError.invalidConfiguration if block height is invalid or if processor is already started */ func setStartHeight(_ startHeight: BlockHeight) throws { - guard self.state == .stopped, startHeight >= ZcashSDK.SAPLING_ACTIVATION_HEIGHT else { + guard self.state == .stopped, startHeight >= config.network.constants.SAPLING_ACTIVATION_HEIGHT else { throw CompactBlockProcessorError.invalidConfiguration } @@ -387,7 +391,8 @@ public class CompactBlockProcessor { backend: initializer.rustBackend, config: Configuration(cacheDb: initializer.cacheDbURL, dataDb: initializer.dataDbURL, - walletBirthday: initializer.walletBirthday.height), + walletBirthday: initializer.walletBirthday.height, + networkType: initializer.network), repository: initializer.transactionRepository, accountRepository: initializer.accountRepository) } @@ -493,6 +498,7 @@ public class CompactBlockProcessor { do { try Self.validateServerInfo(info, saplingActivation: self.config.saplingActivation, + localNetwork: self.config.network, rustBackend: self.rustBackend) completionBlock() } catch { @@ -507,15 +513,16 @@ public class CompactBlockProcessor { static func validateServerInfo(_ info: LightWalletdInfo, saplingActivation: BlockHeight, + localNetwork: NetworkType, rustBackend: ZcashRustBackendWelding.Type) throws { // check network types - guard let remoteNetworkType = ZcashSDK.NetworkType(info.chainName) else { + guard let remoteNetworkType = NetworkType.forChainName(info.chainName) else { throw CompactBlockProcessorError.generalError(message: "Chain name does not match. Expected either 'test' or 'main' but received '\(info.chainName)'. this is probably an API or programming error") } - guard remoteNetworkType == ZcashSDK.networkType else { - throw CompactBlockProcessorError.networkMismatch(expected: ZcashSDK.networkType, found: remoteNetworkType) + guard remoteNetworkType == localNetwork else { + throw CompactBlockProcessorError.networkMismatch(expected: localNetwork, found: remoteNetworkType) } guard saplingActivation == info.saplingActivationHeight else { @@ -523,7 +530,7 @@ public class CompactBlockProcessor { } // check branch id - let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight)) + let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight), networkType: localNetwork) guard let remoteBranchID = ConsensusBranchID.fromString(info.consensusBranchID) else { @@ -564,7 +571,7 @@ public class CompactBlockProcessor { let lastDownloaded = try downloader.lastDownloadedBlockHeight() let height = Int32(height ?? lastDownloaded) - let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height) + let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height, networkType: self.config.network) guard nearestHeight > 0 else { let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error getting nearest rewind height for height: \(height)") @@ -574,7 +581,7 @@ public class CompactBlockProcessor { // FIXME: this should be done on the rust layer let rewindHeight = max(Int32(nearestHeight - 1) , Int32(config.walletBirthday)) - guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight) else { + guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network) else { let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)") fail(error) throw error @@ -649,7 +656,7 @@ public class CompactBlockProcessor { } } - let validateChainOperation = CompactBlockValidationOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb) + let validateChainOperation = CompactBlockValidationOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb, networkType: self.config.network) let downloadValidateAdapterOperation = BlockOperation { [weak validateChainOperation, weak downloadBlockOperation] in validateChainOperation?.error = downloadBlockOperation?.error @@ -698,7 +705,7 @@ public class CompactBlockProcessor { } } - let scanBlocksOperation = CompactBlockBatchScanningOperation(rustWelding: rustBackend, cacheDb: config.cacheDb, dataDb: config.dataDb, transactionRepository: transactionRepository, range: range, progressDelegate: self) + let scanBlocksOperation = CompactBlockBatchScanningOperation(rustWelding: rustBackend, cacheDb: config.cacheDb, dataDb: config.dataDb, transactionRepository: transactionRepository, range: range, networkType: self.config.network, progressDelegate: self) let validateScanningAdapterOperation = BlockOperation { [weak scanBlocksOperation, weak validateChainOperation] in scanBlocksOperation?.error = validateChainOperation?.error @@ -727,7 +734,7 @@ public class CompactBlockProcessor { } } - let enhanceOperation = CompactBlockEnhancementOperation(rustWelding: rustBackend, dataDb: config.dataDb, downloader: downloader, repository: transactionRepository, range: range.blockRange()) + let enhanceOperation = CompactBlockEnhancementOperation(rustWelding: rustBackend, dataDb: config.dataDb, downloader: downloader, repository: transactionRepository, range: range.blockRange(), networkType: self.config.network) enhanceOperation.startedHandler = { LoggerProxy.debug("Started Enhancing range: \(range)") @@ -760,7 +767,7 @@ public class CompactBlockProcessor { enhanceOperation?.error = scanBlocksOperation?.error } - let fetchOperation = FetchUnspentTxOutputsOperation(accountRepository: accountRepository, downloader: self.downloader, rustbackend: rustBackend, dataDb: config.dataDb, startHeight: config.walletBirthday) + let fetchOperation = FetchUnspentTxOutputsOperation(accountRepository: accountRepository, downloader: self.downloader, rustbackend: rustBackend, dataDb: config.dataDb, startHeight: config.walletBirthday, networkType: self.config.network) fetchOperation.startedHandler = { [weak self] in DispatchQueue.main.async { [weak self] in @@ -855,7 +862,7 @@ public class CompactBlockProcessor { // rewind let rewindHeight = determineLowerBound(errorHeight: height, consecutiveErrors: consecutiveChainValidationErrors, walletBirthday: self.config.walletBirthday) - guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight)) else { + guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network) else { fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)")) return } @@ -1053,9 +1060,12 @@ public extension CompactBlockProcessor.Configuration { /** Standard configuration for most compact block processors */ - static var standard: CompactBlockProcessor.Configuration { - let pathProvider = DefaultResourceProvider() - return CompactBlockProcessor.Configuration(cacheDb: pathProvider.cacheDbURL, dataDb: pathProvider.dataDbURL) + static func standard(for networkType: NetworkType, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration { + let pathProvider = DefaultResourceProvider(networkType: networkType) + return CompactBlockProcessor.Configuration(cacheDb: pathProvider.cacheDbURL, + dataDb: pathProvider.dataDbURL, + walletBirthday: walletBirthday, + networkType: networkType) } } @@ -1103,7 +1113,7 @@ extension CompactBlockProcessor.State: Equatable { extension CompactBlockProcessor { public func utxoCacheBalance(tAddress: String) throws -> WalletBalance { - try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress) + try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress, networkType: config.network) } } @@ -1163,7 +1173,7 @@ extension CompactBlockProcessor { guard let self = self else { return } do { - guard try self.rustBackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1) >= 0 else { + guard try self.rustBackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1, networkType: self.config.network) >= 0 else { result(.failure(CompactBlockProcessorError.generalError(message: "attempted to clear utxos but -1 was returned"))) return } @@ -1191,7 +1201,8 @@ extension CompactBlockProcessor { index: utxo.index, script: utxo.script.bytes, value: Int64(utxo.valueZat), - height: utxo.height) ? refreshed.append(utxo) : skipped.append(utxo) + height: utxo.height, + networkType: self.config.network) ? refreshed.append(utxo) : skipped.append(utxo) } catch { LoggerProxy.info("failed to put utxo - error: \(error)") skipped.append(utxo) @@ -1305,7 +1316,7 @@ extension CompactBlockProcessor { let info = try service.getInfo() - try CompactBlockProcessor.validateServerInfo(info, saplingActivation: config.saplingActivation, rustBackend: rustBackend) + try CompactBlockProcessor.validateServerInfo(info, saplingActivation: config.saplingActivation, localNetwork: config.network, rustBackend: rustBackend) // get latest block height let latestDownloadedBlockHeight: BlockHeight = max(config.walletBirthday,try downloader.lastDownloadedBlockHeight()) diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockScanningOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockScanningOperation.swift index 5ed85094..cd204943 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockScanningOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockScanningOperation.swift @@ -19,11 +19,13 @@ class CompactBlockScanningOperation: ZcashOperation { private var cacheDb: URL private var dataDb: URL private var limit: UInt32 - init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, dataDb: URL, limit: UInt32 = 0) { + private var network: NetworkType + init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, dataDb: URL, limit: UInt32 = 0, networkType: NetworkType) { rustBackend = rustWelding self.cacheDb = cacheDb self.dataDb = dataDb self.limit = limit + self.network = networkType super.init() } @@ -33,7 +35,7 @@ class CompactBlockScanningOperation: ZcashOperation { return } self.startedHandler?() - guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: limit) else { + guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: limit, networkType: network) else { self.error = self.rustBackend.lastError() ?? ZcashOperationError.unknown LoggerProxy.debug("block scanning failed with error: \(String(describing: self.error))") self.fail() @@ -112,6 +114,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation { private var batchSize: UInt32 private var blockRange: CompactBlockRange private var transactionRepository: TransactionRepository + private var network: NetworkType init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, @@ -119,6 +122,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation { transactionRepository: TransactionRepository, range: CompactBlockRange, batchSize: UInt32 = 100, + networkType: NetworkType, progressDelegate: CompactBlockProgressDelegate? = nil) { rustBackend = rustWelding self.cacheDb = cacheDb @@ -127,6 +131,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation { self.blockRange = range self.batchSize = batchSize self.progressDelegate = progressDelegate + self.network = networkType super.init() } @@ -139,7 +144,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation { do { if batchSize == 0 { let scanStartTime = Date() - guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: batchSize) else { + guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: batchSize, networkType: network) else { self.scanFailed(self.rustBackend.lastError() ?? ZcashOperationError.unknown) return } @@ -164,7 +169,10 @@ class CompactBlockBatchScanningOperation: ZcashOperation { } let previousScannedHeight = lastScannedHeight let scanStartTime = Date() - guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: batchSize) else { + guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, + dbData: self.dataDb, + limit: batchSize, + networkType: network) else { self.scanFailed(self.rustBackend.lastError() ?? ZcashOperationError.unknown) return } diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift index 81211d14..43ae3d40 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift @@ -22,11 +22,16 @@ class CompactBlockValidationOperation: ZcashOperation { private var cacheDb: URL private var dataDb: URL + private var network: NetworkType - init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, dataDb: URL) { + init(rustWelding: ZcashRustBackendWelding.Type, + cacheDb: URL, + dataDb: URL, + networkType: NetworkType) { rustBackend = rustWelding self.cacheDb = cacheDb self.dataDb = dataDb + self.network = networkType super.init() } @@ -36,7 +41,7 @@ class CompactBlockValidationOperation: ZcashOperation { return } self.startedHandler?() - let result = self.rustBackend.validateCombinedChain(dbCache: cacheDb, dbData: dataDb) + let result = self.rustBackend.validateCombinedChain(dbCache: cacheDb, dbData: dataDb, networkType: self.network) switch result { case 0: let error = CompactBlockValidationError.failedWithError(rustBackend.lastError()) diff --git a/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift b/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift index b7ba2f97..b8e504b8 100644 --- a/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift +++ b/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift @@ -22,18 +22,21 @@ class FetchUnspentTxOutputsOperation: ZcashOperation { private var downloader: CompactBlockDownloading private var rustbackend: ZcashRustBackendWelding.Type private var startHeight: BlockHeight + private var network: NetworkType private var dataDb: URL init(accountRepository: AccountRepository, downloader: CompactBlockDownloading, rustbackend: ZcashRustBackendWelding.Type, dataDb: URL, - startHeight: BlockHeight) { + startHeight: BlockHeight, + networkType: NetworkType) { self.dataDb = dataDb self.accountRepository = accountRepository self.downloader = downloader self.rustbackend = rustbackend self.startHeight = startHeight + self.network = networkType } override func main() { @@ -46,7 +49,10 @@ class FetchUnspentTxOutputsOperation: ZcashOperation { let tAddresses = try accountRepository.getAll().map({ $0.transparentAddress }) do { for tAddress in tAddresses { - guard try self.rustbackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1) >= 0 else { + guard try self.rustbackend.clearUtxos(dbData: dataDb, + address: tAddress, + sinceHeight: startHeight - 1, + networkType: network) >= 0 else { let rustError = rustbackend.lastError() ?? RustWeldingError.genericError(message: "attempted to clear utxos but -1 was returned") throw rustError @@ -80,7 +86,8 @@ class FetchUnspentTxOutputsOperation: ZcashOperation { index: utxo.index, script: utxo.script.bytes, value: Int64(utxo.valueZat), - height: utxo.height) ? refreshed.append(utxo) : skipped.append(utxo) + height: utxo.height, + networkType: network) ? refreshed.append(utxo) : skipped.append(utxo) } catch { LoggerProxy.error("failed to put utxo - error: \(error)") skipped.append(utxo) diff --git a/ZcashLightClientKit/Entity/TransactionEntity.swift b/ZcashLightClientKit/Entity/TransactionEntity.swift index 42c3e65b..f713b94d 100644 --- a/ZcashLightClientKit/Entity/TransactionEntity.swift +++ b/ZcashLightClientKit/Entity/TransactionEntity.swift @@ -57,13 +57,13 @@ public extension TransactionEntity { return true } - var anchor: BlockHeight? { + func anchor(network: NetworkType) -> BlockHeight? { if let minedHeight = self.minedHeight, minedHeight != -1 { - return max(minedHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE, ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + return max(minedHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE, network.constants.SAPLING_ACTIVATION_HEIGHT) } if let expiryHeight = self.expiryHeight, expiryHeight != -1 { - return max(expiryHeight - ZcashSDK.EXPIRY_OFFSET - ZcashSDK.DEFAULT_STALE_TOLERANCE, ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + return max(expiryHeight - ZcashSDK.EXPIRY_OFFSET - ZcashSDK.DEFAULT_STALE_TOLERANCE, network.constants.SAPLING_ACTIVATION_HEIGHT) } return nil diff --git a/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift b/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift index 65e09378..57839821 100644 --- a/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift +++ b/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift @@ -7,38 +7,8 @@ import Foundation -/** - Ideally this extension shouldn't exist. Fees should be calculated from inputs and outputs. "Perfect is the enemy of good" - */ -public extension ZcashSDK { - - /** - Returns the default fee at the time of that blockheight. - */ - static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 { - guard height >= feeChangeHeight else { return 10_000 } - - return 1_000 - } - /** - Estimated height where wallets are supposed to change the fee - */ - private static var feeChangeHeight: BlockHeight { - ZcashSDK.isMainnet ? 1_077_550 : 1_028_500 - } - - /** - minimum balance needed to do a shielding transaction - */ - static let shieldingThreshold: Int64 = 10000 - - enum NetworkType { - case mainnet - case testnet - } -} public typealias ConsensusBranchID = Int32 @@ -53,12 +23,8 @@ public extension ConsensusBranchID { } } -extension ZcashSDK { - static var networkType: NetworkType { - self.isMainnet ? .mainnet : .testnet - } -} -extension ZcashSDK.NetworkType { + +extension NetworkType { init?(_ string: String) { switch string { case "main": diff --git a/ZcashLightClientKit/Initializer.swift b/ZcashLightClientKit/Initializer.swift index 47f9ab6e..4ab61602 100644 --- a/ZcashLightClientKit/Initializer.swift +++ b/ZcashLightClientKit/Initializer.swift @@ -75,6 +75,7 @@ public class Initializer { private(set) var accountRepository: AccountRepository private(set) var storage: CompactBlockStorage private(set) var downloader: CompactBlockDownloader + private(set) var network: NetworkType private(set) public var viewingKeys: [UnifiedViewingKey] private(set) public var walletBirthday: WalletBirthday /** @@ -91,10 +92,11 @@ public class Initializer { dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, + network: NetworkType, spendParamsURL: URL, outputParamsURL: URL, viewingKeys: [UnifiedViewingKey], - walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT, + walletBirthday: BlockHeight, alias: String = "", loggerProxy: Logger? = nil) { @@ -102,6 +104,7 @@ public class Initializer { self.init(rustBackend: ZcashRustBackend.self, lowerBoundHeight: walletBirthday, + network: network, cacheDbURL: cacheDbURL, dataDbURL: dataDbURL, pendingDbURL: pendingDbURL, @@ -124,6 +127,7 @@ public class Initializer { */ init(rustBackend: ZcashRustBackendWelding.Type, lowerBoundHeight: BlockHeight, + network: NetworkType, cacheDbURL: URL, dataDbURL: URL, pendingDbURL: URL, @@ -157,6 +161,7 @@ public class Initializer { self.downloader = CompactBlockDownloader(service: service, storage: storage) self.viewingKeys = viewingKeys self.walletBirthday = WalletBirthday.birthday(with: walletBirthday) + self.network = network } /** @@ -182,7 +187,7 @@ public class Initializer { } do { - try rustBackend.initDataDb(dbData: dataDbURL) + try rustBackend.initDataDb(dbData: dataDbURL, networkType: network) } catch RustWeldingError.dataDbNotEmpty { // this is fine } catch { @@ -190,7 +195,7 @@ public class Initializer { } do { - try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree) + try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree, networkType: network) } catch RustWeldingError.dataDbNotEmpty { // this is fine } catch { @@ -202,7 +207,7 @@ public class Initializer { lowerBoundHeight = max(walletBirthday.height, lastDownloaded) do { - guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys) else { + guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys, networkType: network) else { throw rustBackend.lastError() ?? InitializerError.accountInitFailed } } catch RustWeldingError.dataDbNotEmpty { @@ -212,7 +217,9 @@ public class Initializer { } let migrationManager = MigrationManager(cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path), - dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path)) + dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), + pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path), + networkType: self.network) try migrationManager.performMigration(uvks: viewingKeys) } @@ -229,7 +236,7 @@ public class Initializer { - Parameter account: the index of the account */ public func getBalance(account index: Int = 0) -> Int64 { - rustBackend.getBalance(dbData: dataDbURL, account: Int32(index)) + rustBackend.getBalance(dbData: dataDbURL, account: Int32(index), networkType: network) } /** @@ -237,20 +244,20 @@ public class Initializer { - Parameter account: the index of the account */ public func getVerifiedBalance(account index: Int = 0) -> Int64 { - rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index)) + rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index), networkType: network) } /** checks if the provided address is a valid shielded zAddress */ public func isValidShieldedAddress(_ address: String) -> Bool { - (try? rustBackend.isValidShieldedAddress(address)) ?? false + (try? rustBackend.isValidShieldedAddress(address, networkType: network)) ?? false } /** checks if the provided address is a transparent zAddress */ public func isValidTransparentAddress(_ address: String) -> Bool { - (try? rustBackend.isValidTransparentAddress(address)) ?? false + (try? rustBackend.isValidTransparentAddress(address,networkType: network)) ?? false } func isSpendParameterPresent() -> Bool { diff --git a/ZcashLightClientKit/Providers/ResourceProvider.swift b/ZcashLightClientKit/Providers/ResourceProvider.swift index 03c62434..6e412f5a 100644 --- a/ZcashLightClientKit/Providers/ResourceProvider.swift +++ b/ZcashLightClientKit/Providers/ResourceProvider.swift @@ -21,23 +21,28 @@ public protocol ResourceProvider { Convenience provider for a data db and cache db resources. */ public struct DefaultResourceProvider: ResourceProvider { - + init(networkType: NetworkType) { + self.network = networkType + } + var network: NetworkType public var dataDbURL: URL { + let constants = network.constants do { let url = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) - return url.appendingPathComponent(ZcashSDK.DEFAULT_DATA_DB_NAME) + return url.appendingPathComponent(constants.DEFAULT_DATA_DB_NAME) } catch { - return URL(fileURLWithPath: "file://\(ZcashSDK.DEFAULT_DATA_DB_NAME)") + return URL(fileURLWithPath: "file://\(constants.DEFAULT_DATA_DB_NAME)") } } public var cacheDbURL: URL { + let constants = network.constants do { let path = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) - return path.appendingPathComponent(ZcashSDK.DEFAULT_CACHES_DB_NAME) + return path.appendingPathComponent(constants.DEFAULT_CACHES_DB_NAME) } catch { - return URL(fileURLWithPath: "file://\(ZcashSDK.DEFAULT_CACHES_DB_NAME)") + return URL(fileURLWithPath: "file://\(constants.DEFAULT_CACHES_DB_NAME)") } } diff --git a/ZcashLightClientKit/Rust/ZcashRustBackend.swift b/ZcashLightClientKit/Rust/ZcashRustBackend.swift index 62b1ba1f..44770cf5 100644 --- a/ZcashLightClientKit/Rust/ZcashRustBackend.swift +++ b/ZcashLightClientKit/Rust/ZcashRustBackend.swift @@ -9,9 +9,6 @@ import Foundation class ZcashRustBackend: ZcashRustBackendWelding { - static var networkId: UInt32 { - ZcashSDK.isMainnet ? 1 : 0 - } static func lastError() -> RustWeldingError? { guard let message = getLastError() else { return nil } @@ -39,9 +36,9 @@ class ZcashRustBackend: ZcashRustBackendWelding { /** * Sets up the internal structure of the data database. */ - static func initDataDb(dbData: URL) throws { + static func initDataDb(dbData: URL, networkType: NetworkType) throws { let dbData = dbData.osStr() - guard zcashlc_init_data_database(dbData.0, dbData.1, networkId) != 0 else { + guard zcashlc_init_data_database(dbData.0, dbData.1, networkType.networkId) != 0 else { if let error = lastError() { throw throwDataDbError(error) } @@ -49,12 +46,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { } } - static func isValidShieldedAddress(_ address: String) throws -> Bool { + static func isValidShieldedAddress(_ address: String, networkType: NetworkType) throws -> Bool { guard !address.containsCStringNullBytesBeforeStringEnding() else { return false } - guard zcashlc_is_valid_shielded_address([CChar](address.utf8CString), networkId) else { + guard zcashlc_is_valid_shielded_address([CChar](address.utf8CString), networkType.networkId) else { if let error = lastError() { throw error } @@ -63,12 +60,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { return true } - static func isValidTransparentAddress(_ address: String) throws -> Bool { + static func isValidTransparentAddress(_ address: String, networkType: NetworkType) throws -> Bool { guard !address.containsCStringNullBytesBeforeStringEnding() else { return false } - guard zcashlc_is_valid_transparent_address([CChar](address.utf8CString), networkId) else { + guard zcashlc_is_valid_transparent_address([CChar](address.utf8CString), networkType.networkId ) else { if let error = lastError() { throw error } @@ -77,12 +74,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { return true } - static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool { + static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool { guard !key.containsCStringNullBytesBeforeStringEnding() else { return false } - guard zcashlc_is_valid_viewing_key([CChar](key.utf8CString), networkId) else { + guard zcashlc_is_valid_viewing_key([CChar](key.utf8CString), networkType.networkId) else { if let error = lastError() { throw error } @@ -91,10 +88,10 @@ class ZcashRustBackend: ZcashRustBackendWelding { return true } - static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? { + static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? { let dbData = dbData.osStr() var capacity = UInt(0); - let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts, &capacity, networkId) + let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts, &capacity, networkType.networkId) if extsksCStr == nil { return nil } @@ -107,7 +104,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { return extsks } - static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool { + static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey], networkType: NetworkType) throws -> Bool { let dbData = dbData.osStr() var ffiUvks = [FFIUnifiedViewingKey]() @@ -118,6 +115,10 @@ class ZcashRustBackend: ZcashRustBackendWelding { guard !uvk.extpub.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } + + guard try self.isValidExtendedFullViewingKey(uvk.extfvk, networkType: networkType) else { + throw RustWeldingError.malformedStringInput + } let extfvkCStr = [CChar](String(uvk.extfvk).utf8CString) @@ -136,7 +137,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { let slice = UnsafeMutablePointer.allocate(capacity: 1) slice.initialize(to: FFIUVKBoxedSlice(ptr: p.baseAddress, len: UInt(p.count))) - result = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, slice, networkId) + result = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, slice, networkType.networkId) slice.deinitialize(count: 1) } @@ -150,29 +151,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { return result } -// static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool { -// let dbData = dbData.osStr() -// let viewingKeys = exfvks.map { UnsafePointer(strdup($0)) } -// -// guard exfvks.count > 0 else { -// throw RustWeldingError.malformedStringInput -// } -// -// let res = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, viewingKeys, UInt(viewingKeys.count)); -// -// viewingKeys.compactMap({ UnsafeMutablePointer(mutating: $0) }).forEach({ free($0) }) -// -// guard res else { -// if let error = lastError() { -// throw error -// } -// return false -// } -// return res -// -// } - static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) throws { + static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String, networkType: NetworkType) throws { let dbData = dbData.osStr() guard !hash.containsCStringNullBytesBeforeStringEnding() else { @@ -183,7 +163,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw RustWeldingError.malformedStringInput } - guard zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString), networkId) != 0 else { + guard zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString), networkType.networkId) != 0 else { if let error = lastError() { throw error } @@ -191,52 +171,65 @@ class ZcashRustBackend: ZcashRustBackendWelding { } } - static func getAddress(dbData: URL, account: Int32) -> String? { + static func getAddress(dbData: URL, account: Int32, networkType: NetworkType) -> String? { let dbData = dbData.osStr() - guard let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account, networkId) else { return nil } + guard let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account, networkType.networkId) else { return nil } let address = String(validatingUTF8: addressCStr) zcashlc_string_free(addressCStr) return address } - static func getBalance(dbData: URL, account: Int32) -> Int64 { + static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 { let dbData = dbData.osStr() - return zcashlc_get_balance(dbData.0, dbData.1, account, networkId) + return zcashlc_get_balance(dbData.0, dbData.1, account, networkType.networkId) } - static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 { + static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 { let dbData = dbData.osStr() - return zcashlc_get_verified_balance(dbData.0, dbData.1, account, networkId) + return zcashlc_get_verified_balance(dbData.0, dbData.1, account, networkType.networkId) } - static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 { + static func getVerifiedTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 { guard !address.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } + guard try isValidTransparentAddress(address, networkType: networkType) else { + throw RustWeldingError.unableToDeriveKeys + } + let dbData = dbData.osStr() - return zcashlc_get_verified_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkId) + return zcashlc_get_verified_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkType.networkId) } - static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 { + static func getTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 { guard !address.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } + guard try self.isValidTransparentAddress(address, networkType: networkType) else { + throw RustWeldingError.unableToDeriveKeys + } + let dbData = dbData.osStr() - return zcashlc_get_total_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkId) + return zcashlc_get_total_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkType.networkId) } - static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> Int32 { + + static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 { let dbData = dbData.osStr() guard !address.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - let result = zcashlc_clear_utxos(dbData.0, dbData.1, [CChar](address.utf8CString), Int32(sinceHeight), networkId) + guard try isValidTransparentAddress(address, networkType: networkType) else { + throw RustWeldingError.unableToDeriveKeys + } + + let result = zcashlc_clear_utxos(dbData.0, dbData.1, [CChar](address.utf8CString), Int32(sinceHeight), networkType.networkId) guard result > 0 else { if let error = lastError() { @@ -247,7 +240,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { return result } - static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool { + static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool { let dbData = dbData.osStr() @@ -265,7 +258,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { UInt(script.count), value, Int32(height), - networkId) else { + networkType.networkId) else { if let error = lastError() { throw error } @@ -274,60 +267,61 @@ class ZcashRustBackend: ZcashRustBackendWelding { return true } - static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance { - let verified = try getVerifiedTransparentBalance(dbData: dbData, address: address) - let total = try getTransparentBalance(dbData: dbData, address: address) + static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance { + let verified = try getVerifiedTransparentBalance(dbData: dbData, address: address, networkType: networkType) + let total = try getTransparentBalance(dbData: dbData, address: address, networkType: networkType) return TransparentBalance(verified: verified, total: total, address: address) } - static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { + static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? { let dbData = dbData.osStr() - guard let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote, networkId) else { return nil } + guard let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote, networkType.networkId) else { return nil } let memo = String(validatingUTF8: memoCStr) zcashlc_string_free(memoCStr) return memo } - static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { + static func getSentMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? { let dbData = dbData.osStr() - guard let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote, networkId) else { return nil } + guard let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote, networkType.networkId) else { return nil } let memo = String(validatingUTF8: memoCStr) zcashlc_string_free(memoCStr) return memo } - static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 { + static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 { let dbCache = dbCache.osStr() let dbData = dbData.osStr() - return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkId) + return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkType.networkId) } - static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32 { + static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32 { let dbData = dbData.osStr() - return zcashlc_get_nearest_rewind_height(dbData.0, dbData.1, height, networkId) + return zcashlc_get_nearest_rewind_height(dbData.0, dbData.1, height, networkType.networkId) } - static func rewindToHeight(dbData: URL, height: Int32) -> Bool { + static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool { let dbData = dbData.osStr() - return zcashlc_rewind_to_height(dbData.0, dbData.1, height, networkId) + return zcashlc_rewind_to_height(dbData.0, dbData.1, height, networkType.networkId) } - static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32 = 0) -> Bool { + static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32 = 0, networkType: NetworkType) -> Bool { let dbCache = dbCache.osStr() let dbData = dbData.osStr() - return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit, networkId) != 0 + return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit, networkType.networkId) != 0 } - static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool { + static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8], networkType: NetworkType) -> Bool { let dbData = dbData.osStr() - return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count), networkId) != 0 + return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count), networkType.networkId) != 0 } - static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { + static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 { + let dbData = dbData.osStr() let memoBytes = memo ?? "" @@ -342,10 +336,10 @@ class ZcashRustBackend: ZcashRustBackendWelding { UInt(spendParamsPath.lengthOfBytes(using: .utf8)), outputParamsPath, UInt(outputParamsPath.lengthOfBytes(using: .utf8)), - networkId) + networkType.networkId) } - static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { + static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 { let dbData = dbData.osStr() let memoBytes = memo ?? "" @@ -359,17 +353,17 @@ class ZcashRustBackend: ZcashRustBackendWelding { UInt(spendParamsPath.lengthOfBytes(using: .utf8)), outputParamsPath, UInt(outputParamsPath.lengthOfBytes(using: .utf8)), - networkId) + networkType.networkId) } - static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String? { + static func deriveExtendedFullViewingKey(_ spendingKey: String, networkType: NetworkType) throws -> String? { guard !spendingKey.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } guard let extsk = zcashlc_derive_extended_full_viewing_key([CChar](spendingKey.utf8CString), - networkId) else { + networkType.networkId) else { if let error = lastError() { throw error } @@ -382,9 +376,9 @@ class ZcashRustBackend: ZcashRustBackendWelding { return derived } - static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? { + static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? { var capacity = UInt(0); - guard let extsksCStr = zcashlc_derive_extended_full_viewing_keys(seed, UInt(seed.count), accounts, &capacity, networkId) else { + guard let extsksCStr = zcashlc_derive_extended_full_viewing_keys(seed, UInt(seed.count), accounts, &capacity, networkType.networkId) else { if let error = lastError() { throw error } @@ -399,9 +393,9 @@ class ZcashRustBackend: ZcashRustBackendWelding { return extsks } - static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? { + static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? { var capacity = UInt(0); - guard let extsksCStr = zcashlc_derive_extended_spending_keys(seed, UInt(seed.count), accounts, &capacity, networkId) else { + guard let extsksCStr = zcashlc_derive_extended_spending_keys(seed, UInt(seed.count), accounts, &capacity, networkType.networkId) else { if let error = lastError() { throw error } @@ -416,9 +410,9 @@ class ZcashRustBackend: ZcashRustBackendWelding { return extsks } - static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] { + static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedViewingKey] { - guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts), networkId) else { + guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts), networkType.networkId) else { if let error = lastError() { throw error } @@ -450,8 +444,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { return uvks } - static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String? { - guard let zaddrCStr = zcashlc_derive_shielded_address_from_seed(seed, UInt(seed.count), accountIndex, networkId) else { + static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? { + guard let zaddrCStr = zcashlc_derive_shielded_address_from_seed(seed, UInt(seed.count), accountIndex, networkType.networkId) else { if let error = lastError() { throw error } @@ -464,12 +458,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { return zAddr } - static func deriveShieldedAddressFromViewingKey(_ extfvk: String) throws -> String? { + static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? { guard !extfvk.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - guard let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key([CChar](extfvk.utf8CString), networkId) else { + guard let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key([CChar](extfvk.utf8CString), networkType.networkId) else { if let error = lastError() { throw error } @@ -482,9 +476,9 @@ class ZcashRustBackend: ZcashRustBackendWelding { return zAddr } - static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? { + static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? { - guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkId) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkType.networkId) else { if let error = lastError() { throw error } @@ -496,8 +490,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { return tAddr } - static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? { - guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkId) else { + static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? { + guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkType.networkId) else { if let error = lastError() { throw error } @@ -508,12 +502,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { return sk } - static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String { + static func derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) throws -> String { guard !pubkey.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - guard let tAddrCStr = zcashlc_derive_transparent_address_from_public_key([CChar](pubkey.utf8CString), networkId), let tAddr = String(validatingUTF8: tAddrCStr) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_public_key([CChar](pubkey.utf8CString), networkType.networkId), let tAddr = String(validatingUTF8: tAddrCStr) else { if let error = lastError() { throw error } @@ -522,12 +516,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { return tAddr } - static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? { + static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? { guard !tsk.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString), networkId) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString), networkType.networkId) else { if let error = lastError() { throw error } @@ -538,8 +532,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { return tAddr } - static func consensusBranchIdFor(height: Int32) throws -> Int32 { - let branchId = zcashlc_branch_id_for_height(height, networkId) + static func consensusBranchIdFor(height: Int32, networkType: NetworkType) throws -> Int32 { + let branchId = zcashlc_branch_id_for_height(height, networkType.networkId) guard branchId != -1 else { throw RustWeldingError.noConsensusBranchId(height: height) diff --git a/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift b/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift index b46a68c7..50ec9d14 100644 --- a/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift +++ b/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift @@ -35,25 +35,25 @@ public protocol ZcashRustBackendWelding { initializes the data db - Parameter dbData: location of the data db sql file */ - static func initDataDb(dbData: URL) throws + static func initDataDb(dbData: URL, networkType: NetworkType) throws /** - Returns: true when the address is valid and shielded. Returns false in any other case - Throws: Error when the provided address belongs to another network */ - static func isValidShieldedAddress(_ address: String) throws -> Bool + static func isValidShieldedAddress(_ address: String, networkType: NetworkType) throws -> Bool /** - Returns: true when the address is valid and transparent. false in any other case - Throws: Error when the provided address belongs to another network */ - static func isValidTransparentAddress(_ address: String) throws -> Bool + static func isValidTransparentAddress(_ address: String, networkType: NetworkType) throws -> Bool /** - Returns: true when the address is valid and transparent. false in any other case - Throws: Error when there's another problem not related to validity of the string in question */ - static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool + static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool /** initialize the accounts table from a given seed and a number of accounts @@ -62,7 +62,7 @@ public protocol ZcashRustBackendWelding { - seed: byte array of the zip32 seed - accounts: how many accounts you want to have */ - static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? + static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? /** initialize the accounts table from a set of unified viewing keys @@ -70,7 +70,7 @@ public protocol ZcashRustBackendWelding { - dbData: location of the data db - uvks: an array of UnifiedViewingKeys */ - static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool + static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey], networkType: NetworkType) throws -> Bool /** initialize the blocks table from a given checkpoint (birthday) @@ -81,7 +81,7 @@ public protocol ZcashRustBackendWelding { - time: in milliseconds from reference - saplingTree: hash of the sapling tree */ - static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) throws + static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String, networkType: NetworkType) throws /** gets the address from data db from the given account @@ -90,38 +90,38 @@ public protocol ZcashRustBackendWelding { - account: index of the given account - Returns: an optional string with the address if found */ - static func getAddress(dbData: URL, account: Int32) -> String? + static func getAddress(dbData: URL, account: Int32, networkType: NetworkType) -> String? /** get the (unverified) balance from the given account - Parameters: - dbData: location of the data db - account: index of the given account */ - static func getBalance(dbData: URL, account: Int32) -> Int64 + static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 /** get the verified balance from the given account - Parameters: - dbData: location of the data db - account: index of the given account */ - static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 + static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 /** Get the verified cached transparent balance for the given address */ - static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 + static func getVerifiedTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 /** Get the verified cached transparent balance for the given address */ - static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 + static func getTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 /** get received memo from note - Parameters: - dbData: location of the data db file - idNote: note_id of note where the memo is located */ - static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? + static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? /** get sent memo from note @@ -129,7 +129,7 @@ public protocol ZcashRustBackendWelding { - dbData: location of the data db file - idNote: note_id of note where the memo is located */ - static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? + static func getSentMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? /** Checks that the scanned blocks in the data database, when combined with the recent @@ -145,7 +145,7 @@ public protocol ZcashRustBackendWelding { * `0` if there was an error during validation unrelated to chain validity. - Important: This function does not mutate either of the databases. */ - static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 + static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 /** Returns the nearest height where a rewind is possible. Currently prunning gets rid of sapling witnesses older @@ -155,14 +155,14 @@ public protocol ZcashRustBackendWelding { - dbData: location of the data db file - height: height you would like to rewind to. */ - static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32 + static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32 /** rewinds the compact block storage to the given height. clears up all derived data as well - Parameters: - dbData: location of the data db file - height: height to rewind to. DON'T PASS ARBITRARY HEIGHT. Use getNearestRewindHeight when unsure */ - static func rewindToHeight(dbData: URL, height: Int32) -> Bool + static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool /** Scans new blocks added to the cache for any transactions received by the tracked @@ -183,7 +183,7 @@ public protocol ZcashRustBackendWelding { - limit: scan up to limit blocks. pass 0 to set no limit. returns false if fails to scan. */ - static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32) -> Bool + static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool /** puts a UTXO into the data db database @@ -196,7 +196,7 @@ public protocol ZcashRustBackendWelding { - height: the mined height for the UTXO - Returns: true if the operation succeded or false otherwise */ - static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool + static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool /** clears the cached utxos for the given address from the specified height on @@ -207,7 +207,7 @@ public protocol ZcashRustBackendWelding { - Returns: the amount of UTXOs cleared or -1 on error */ - static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight) throws -> Int32 + static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 /** Gets the balance of the previously downloaded UTXOs - Parameters: @@ -216,7 +216,7 @@ public protocol ZcashRustBackendWelding { - Returns: the wallet balance containing verified and total balance. - Throws: Rustwelding Error if something fails */ - static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance + static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance /** Scans a transaction for any information that can be decrypted by the accounts in the @@ -227,7 +227,7 @@ public protocol ZcashRustBackendWelding { - tx: the transaction to decrypt returns false if fails to decrypt. */ - static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool + static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8], networkType: NetworkType) -> Bool /** Creates a transaction to the given address from the given account @@ -241,7 +241,7 @@ public protocol ZcashRustBackendWelding { - spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located - outputParamsPath: path escaped String for the filesystem locations where the output parameters are located */ - static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 + static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 /** Creates a transaction to shield all found UTXOs in cache db. @@ -255,7 +255,7 @@ public protocol ZcashRustBackendWelding { - spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located - outputParamsPath: path escaped String for the filesystem locations where the output parameters are located */ - static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 + static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 /** Derives a full viewing key from a seed @@ -263,7 +263,7 @@ public protocol ZcashRustBackendWelding { - Returns: the derived key - Throws: RustBackendError if fatal error occurs */ - static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String? + static func deriveExtendedFullViewingKey(_ spendingKey: String, networkType: NetworkType) throws -> String? /** Derives a set of full viewing keys from a seed @@ -272,7 +272,7 @@ public protocol ZcashRustBackendWelding { - Returns: an array containing the derived keys - Throws: RustBackendError if fatal error occurs */ - static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? + static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? /** Derives a set of full viewing keys from a seed @@ -281,7 +281,7 @@ public protocol ZcashRustBackendWelding { - Returns: an array containing the spending keys - Throws: RustBackendError if fatal error occurs */ - static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? + static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? /** Derives a shielded address from a seed @@ -290,7 +290,7 @@ public protocol ZcashRustBackendWelding { - Returns: an optional String containing the Shielded address - Throws: RustBackendError if fatal error occurs */ - static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String? + static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? /** Derives a shielded address from an Extended Full Viewing Key @@ -298,7 +298,7 @@ public protocol ZcashRustBackendWelding { - Returns: an optional String containing the Shielded address - Throws: RustBackendError if fatal error occurs */ - static func deriveShieldedAddressFromViewingKey(_ extfvk: String) throws -> String? + static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? /** Derives a shielded address from an Extended Full Viewing Key @@ -306,14 +306,14 @@ public protocol ZcashRustBackendWelding { - Returns: an optional String containing the transparent address - Throws: RustBackendError if fatal error occurs */ - static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? + static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? /** Derives a transparent secret key from Seed - Parameter seed: an array of bytes containing the seed - Returns: an optional String containing the transparent secret (private) key */ - static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? + static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? /** Derives a transparent address from a secret key @@ -321,18 +321,18 @@ public protocol ZcashRustBackendWelding { - Returns: an optional String containing the transparent address. */ - static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? + static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? /** Derives a tranparent address from a public key - Parameter pubkey: public key represented as a string */ - static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String + static func derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) throws -> String - static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] + static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedViewingKey] /** Gets the consensus branch id for the given height - Parameter height: the height you what to know the branch id for */ - static func consensusBranchIdFor(height: Int32) throws -> Int32 + static func consensusBranchIdFor(height: Int32, networkType: NetworkType) throws -> Int32 } diff --git a/ZcashLightClientKit/Service/LightWalletGRPCService.swift b/ZcashLightClientKit/Service/LightWalletGRPCService.swift index cde23ee1..ebf6ff3c 100644 --- a/ZcashLightClientKit/Service/LightWalletGRPCService.swift +++ b/ZcashLightClientKit/Service/LightWalletGRPCService.swift @@ -336,7 +336,7 @@ extension LightWalletGRPCService: LightWalletService { return height } - public func fetchUTXOs(for tAddress: String, height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> [UnspentTransactionOutputEntity] { + public func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] { let arg = GetAddressUtxosArg.with { (utxoArgs) in utxoArgs.addresses = [tAddress] utxoArgs.startHeight = UInt64(height) @@ -358,7 +358,7 @@ extension LightWalletGRPCService: LightWalletService { } } - public func fetchUTXOs(for tAddress: String, height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) { + public func fetchUTXOs(for tAddress: String, height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) { queue.async { [weak self] in guard let self = self else { return } let arg = GetAddressUtxosArg.with { (utxoArgs) in @@ -394,7 +394,7 @@ extension LightWalletGRPCService: LightWalletService { } } - public func fetchUTXOs(for tAddresses: [String], height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> [UnspentTransactionOutputEntity] { + public func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] { guard tAddresses.count > 0 else { return [] // FIXME: throw a real error diff --git a/ZcashLightClientKit/Service/ProtoBuf/Extensions/Protocolbuffer+Extensions.swift b/ZcashLightClientKit/Service/ProtoBuf/Extensions/Protocolbuffer+Extensions.swift index 531a2610..0f6b4697 100644 --- a/ZcashLightClientKit/Service/ProtoBuf/Extensions/Protocolbuffer+Extensions.swift +++ b/ZcashLightClientKit/Service/ProtoBuf/Extensions/Protocolbuffer+Extensions.swift @@ -16,17 +16,11 @@ extension CompactBlockRange { extension BlockID { - static let saplingActivationHeight: UInt64 = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) - init(height: UInt64) { self = BlockID() self.height = height } - static var saplingActivation: BlockID { - BlockID(height: saplingActivationHeight) - } - init(height: BlockHeight) { self.init(height: UInt64(height)) } @@ -46,16 +40,6 @@ extension BlockRange { } } - static func sinceSaplingActivation(to height: UInt64? = nil) -> BlockRange { - var blockRange = BlockRange() - - blockRange.start = BlockID.saplingActivation - if let height = height { - blockRange.end = BlockID.init(height: height) - } - return blockRange - } - var compactBlockRange: CompactBlockRange { return Int(self.start.height) ... Int(self.end.height) } diff --git a/ZcashLightClientKit/Tool/DerivationTool.swift b/ZcashLightClientKit/Tool/DerivationTool.swift index 0c792e9b..2cf3de06 100644 --- a/ZcashLightClientKit/Tool/DerivationTool.swift +++ b/ZcashLightClientKit/Tool/DerivationTool.swift @@ -107,7 +107,11 @@ public class DerivationTool: KeyDeriving { var rustwelding: ZcashRustBackendWelding.Type = ZcashRustBackend.self - public static let `default` = DerivationTool() + var networkType: NetworkType + + public init(networkType: NetworkType) { + self.networkType = networkType + } /** Given a seed and a number of accounts, return the associated viewing keys. @@ -123,7 +127,7 @@ public class DerivationTool: KeyDeriving { } do { - guard let keys = try rustwelding.deriveExtendedFullViewingKeys(seed: seed, accounts: numberOfAccounts) else { + guard let keys = try rustwelding.deriveExtendedFullViewingKeys(seed: seed, accounts: numberOfAccounts, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return keys @@ -141,7 +145,7 @@ public class DerivationTool: KeyDeriving { */ public func deriveViewingKey(spendingKey: String) throws -> String { do { - guard let key = try rustwelding.deriveExtendedFullViewingKey(spendingKey) else { + guard let key = try rustwelding.deriveExtendedFullViewingKey(spendingKey, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return key @@ -165,7 +169,7 @@ public class DerivationTool: KeyDeriving { throw KeyDerivationErrors.invalidInput } do { - guard let keys = try rustwelding.deriveExtendedSpendingKeys(seed: seed, accounts: numberOfAccounts) else { + guard let keys = try rustwelding.deriveExtendedSpendingKeys(seed: seed, accounts: numberOfAccounts, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return keys @@ -189,7 +193,7 @@ public class DerivationTool: KeyDeriving { } do { - guard let address = try rustwelding.deriveShieldedAddressFromSeed(seed: seed, accountIndex: accountIndex) else { + guard let address = try rustwelding.deriveShieldedAddressFromSeed(seed: seed, accountIndex: accountIndex, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return address @@ -209,7 +213,7 @@ public class DerivationTool: KeyDeriving { */ public func deriveShieldedAddress(viewingKey: String) throws -> String { do { - guard let zaddr = try rustwelding.deriveShieldedAddressFromViewingKey(viewingKey) else { + guard let zaddr = try rustwelding.deriveShieldedAddressFromViewingKey(viewingKey, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return zaddr @@ -220,7 +224,7 @@ public class DerivationTool: KeyDeriving { public func deriveTransparentAddress(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String { do { - guard let zaddr = try rustwelding.deriveTransparentAddressFromSeed(seed: seed, account: account, index: index) else { + guard let zaddr = try rustwelding.deriveTransparentAddressFromSeed(seed: seed, account: account, index: index, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return zaddr @@ -234,7 +238,7 @@ public class DerivationTool: KeyDeriving { throw KeyDerivationErrors.invalidInput } do { - return try rustwelding.deriveUnifiedViewingKeyFromSeed(seed, numberOfAccounts: numberOfAccounts) + return try rustwelding.deriveUnifiedViewingKeyFromSeed(seed, numberOfAccounts: numberOfAccounts, networkType: networkType) } catch { throw KeyDerivationErrors.derivationError(underlyingError: error) } @@ -259,7 +263,7 @@ public class DerivationTool: KeyDeriving { } do { - return try rustwelding.derivedTransparentAddressFromPublicKey(pubkey) + return try rustwelding.derivedTransparentAddressFromPublicKey(pubkey, networkType: networkType) } catch { throw KeyDerivationErrors.derivationError(underlyingError: error) } @@ -273,7 +277,7 @@ public class DerivationTool: KeyDeriving { */ public func deriveTransparentPrivateKey(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String { do { - guard let sk = try rustwelding.deriveTransparentPrivateKeyFromSeed(seed: seed, account: account, index: index) else { + guard let sk = try rustwelding.deriveTransparentPrivateKeyFromSeed(seed: seed, account: account, index: index, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return sk @@ -288,7 +292,7 @@ extension DerivationTool: KeyValidation { public func isValidExtendedViewingKey(_ extvk: String) throws -> Bool { do { - return try rustwelding.isValidExtendedFullViewingKey(extvk) + return try rustwelding.isValidExtendedFullViewingKey(extvk, networkType: networkType) } catch { throw KeyDerivationErrors.derivationError(underlyingError: error) } @@ -296,7 +300,7 @@ extension DerivationTool: KeyValidation { public func isValidTransparentAddress(_ tAddress: String) throws -> Bool { do { - return try rustwelding.isValidTransparentAddress(tAddress) + return try rustwelding.isValidTransparentAddress(tAddress, networkType: networkType) } catch { throw KeyDerivationErrors.derivationError(underlyingError: error) } @@ -304,7 +308,7 @@ extension DerivationTool: KeyValidation { public func isValidShieldedAddress(_ zAddress: String) throws -> Bool { do { - return try rustwelding.isValidShieldedAddress(zAddress) + return try rustwelding.isValidShieldedAddress(zAddress, networkType: networkType) } catch { throw KeyDerivationErrors.derivationError(underlyingError: error) } @@ -318,7 +322,7 @@ extension DerivationTool: KeyValidation { */ public func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String { do { - guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk) else { + guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return tAddr diff --git a/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift b/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift index 78942706..fae3010c 100644 --- a/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift +++ b/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift @@ -24,10 +24,16 @@ class PersistentTransactionManager: OutboundTransactionManager { var encoder: TransactionEncoder var service: LightWalletService var queue: DispatchQueue - init(encoder: TransactionEncoder, service: LightWalletService, repository: PendingTransactionRepository) { + var network: NetworkType + + init(encoder: TransactionEncoder, + service: LightWalletService, + repository: PendingTransactionRepository, + networkType: NetworkType) { self.repository = repository self.encoder = encoder self.service = service + self.network = networkType self.queue = DispatchQueue.init(label: "PersistentTransactionManager.serial.queue", qos: .userInitiated) } @@ -44,7 +50,7 @@ class PersistentTransactionManager: OutboundTransactionManager { queue.async { [weak self] in guard let self = self else { return } - let derivationTool = DerivationTool() + let derivationTool = DerivationTool(networkType: self.network) guard let vk = try? derivationTool.deriveViewingKey(spendingKey: spendingKey), let zAddr = try? derivationTool.deriveShieldedAddress(viewingKey: vk) else { result(.failure(TransactionManagerError.shieldingEncodingFailed(tx: pendingTransaction, reason: "There was an error Deriving your keys"))) @@ -243,7 +249,7 @@ class PersistentTransactionManager: OutboundTransactionManager { class OutboundTransactionManagerBuilder { static func build(initializer: Initializer) throws -> OutboundTransactionManager { - return PersistentTransactionManager(encoder: TransactionEncoderbuilder.build(initializer: initializer), service: initializer.lightWalletService, repository: try PendingTransactionRepositoryBuilder.build(initializer: initializer)) + return PersistentTransactionManager(encoder: TransactionEncoderbuilder.build(initializer: initializer), service: initializer.lightWalletService, repository: try PendingTransactionRepositoryBuilder.build(initializer: initializer), networkType: initializer.network) } } diff --git a/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift b/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift index 7053538e..c90739ca 100644 --- a/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift +++ b/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift @@ -16,13 +16,15 @@ class WalletTransactionEncoder: TransactionEncoder { private var spendParamsURL: URL private var dataDbURL: URL private var cacheDbURL: URL + private var network: NetworkType init(rust: ZcashRustBackendWelding.Type, dataDb: URL, cacheDb: URL, repository: TransactionRepository, outputParams: URL, - spendParams: URL) { + spendParams: URL, + networkType: NetworkType) { self.rustBackend = rust self.dataDbURL = dataDb @@ -30,6 +32,7 @@ class WalletTransactionEncoder: TransactionEncoder { self.repository = repository self.outputParamsURL = outputParams self.spendParamsURL = spendParams + self.network = networkType self.queue = DispatchQueue(label: "wallet.transaction.encoder.serial.queue") } @@ -40,7 +43,8 @@ class WalletTransactionEncoder: TransactionEncoder { cacheDb: initializer.cacheDbURL, repository: initializer.transactionRepository, outputParams: initializer.outputParamsURL, - spendParams: initializer.spendParamsURL) + spendParams: initializer.spendParamsURL, + networkType: initializer.network) } @@ -86,7 +90,8 @@ class WalletTransactionEncoder: TransactionEncoder { value: Int64(zatoshi), memo: memo, spendParamsPath: self.spendParamsURL.path, - outputParamsPath: self.outputParamsURL.path) + outputParamsPath: self.outputParamsURL.path, + networkType: network) guard txId > 0 else { throw rustBackend.lastError() ?? RustWeldingError.genericError(message: "create spend failed") @@ -130,7 +135,8 @@ class WalletTransactionEncoder: TransactionEncoder { extsk: spendingKey, memo: memo, spendParamsPath: self.spendParamsURL.path, - outputParamsPath: self.outputParamsURL.path) + outputParamsPath: self.outputParamsURL.path, + networkType: network) guard txId > 0 else { throw rustBackend.lastError() ?? RustWeldingError.genericError(message: "create spend failed") diff --git a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift index 1a01414d..c1b827b8 100644 --- a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift +++ b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift @@ -124,9 +124,9 @@ public class SDKSynchronizer: Synchronizer { public private(set) var progress: Float = 0.0 public private(set) var blockProcessor: CompactBlockProcessor public private(set) var initializer: Initializer - public private(set)var latestScannedHeight: BlockHeight + public private(set) var latestScannedHeight: BlockHeight public private(set) var connectionState: ConnectionState - + public private(set) var network: NetworkType private var transactionManager: OutboundTransactionManager private var transactionRepository: TransactionRepository private var utxoRepository: UnspentTransactionOutputRepository @@ -159,7 +159,8 @@ public class SDKSynchronizer: Synchronizer { self.utxoRepository = utxoRepository self.blockProcessor = blockProcessor self.latestScannedHeight = (try? transactionRepository.lastScannedHeight()) ?? initializer.walletBirthday.height - self.subscribeToProcessorNotifications(self.blockProcessor) + self.network = initializer.network + self.subscribeToProcessorNotifications(blockProcessor) } deinit { @@ -443,13 +444,14 @@ public class SDKSynchronizer: Synchronizer { public func shieldFunds(spendingKey: String, transparentSecretKey: String, memo: String?, from accountIndex: Int, resultBlock: @escaping (Result) -> Void) { // let's see if there are funds to shield - let derivationTool = DerivationTool.default + let derivationTool = DerivationTool(networkType: self.network) do { let tAddr = try derivationTool.deriveTransparentAddressFromPrivateKey(transparentSecretKey) let tBalance = try utxoRepository.balance(address: tAddr, latestHeight: self.latestDownloadedHeight()) - guard tBalance.verified >= ZcashSDK.shieldingThreshold else { + // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet. + guard tBalance.verified >= self.network.constants.defaultFee(for: self.latestScannedHeight) else { resultBlock(.failure(ShieldFundsError.insuficientTransparentFunds)) return } @@ -562,7 +564,7 @@ public class SDKSynchronizer: Synchronizer { return } - initializer.lightWalletService.fetchUTXOs(for: address, height: ZcashSDK.SAPLING_ACTIVATION_HEIGHT, result: { [weak self] r in + initializer.lightWalletService.fetchUTXOs(for: address, height: network.constants.SAPLING_ACTIVATION_HEIGHT, result: { [weak self] r in guard let self = self else { return } switch r { case .success(let utxos): @@ -579,7 +581,7 @@ public class SDKSynchronizer: Synchronizer { }) } - public func refreshUTXOs(address: String, from height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT, result: @escaping (Result) -> Void) { + public func refreshUTXOs(address: String, from height: BlockHeight, result: @escaping (Result) -> Void) { self.blockProcessor.refreshUTXOs(tAddress: address, startHeight: height, result: result) } @@ -635,7 +637,7 @@ public class SDKSynchronizer: Synchronizer { height = rewindHeight case .transaction(let tx): - guard let txHeight = tx.anchor else { + guard let txHeight = tx.anchor(network: self.network) else { throw SynchronizerError.rewindErrorUnknownArchorHeight } height = txHeight From b067249b0128678a214b460293080c7df6d91f73 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 26 Jul 2021 20:56:18 -0300 Subject: [PATCH 05/17] DerivationTool tests are network agnostic --- .../DerivatioToolTestnetTests.swift | 98 +++++++++++++++++++ ...swift => DerivationToolMainnetTests.swift} | 2 +- Scripts/build_librustzcash_xcode.sh | 10 +- Scripts/generate_zcashsdk_constants.sh | 4 +- 4 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 DerivationToolTests/DerivatioToolTestnetTests.swift rename DerivationToolTests/{DerivationToolTests.swift => DerivationToolMainnetTests.swift} (99%) diff --git a/DerivationToolTests/DerivatioToolTestnetTests.swift b/DerivationToolTests/DerivatioToolTestnetTests.swift new file mode 100644 index 00000000..21b4f8ff --- /dev/null +++ b/DerivationToolTests/DerivatioToolTestnetTests.swift @@ -0,0 +1,98 @@ +// +// DerivatioToolTestnetTests.swift +// ZcashLightClientKit-Unit-DerivationToolTests +// +// Created by Francisco Gindre on 7/26/21. +// + +import XCTest +@testable import ZcashLightClientKit + +class DerivatioToolTestnetTests: XCTestCase { + var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment? + var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! + let testRecipientAddress = "ztestsapling1475xtm56czrzmleqzzlu4cxvjjfsy2p6rv78q07232cpsx5ee52k0mn5jyndq09mampkgvrxnwg" //TODO: Parameterize this from environment + + let expectedSpendingKey = "secret-extended-key-test1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6lk8xce3d4jw7s8ln5yjp6fqv2g0nzue2hc0kv5t004vklvlenncscq9flwh5vf5qnv0hnync72n7gjn70u47765v3kyrxytx50g730svvmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqe49swv" + + let expectedViewingKey = "zxviewtestsapling1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6l5smlqrckkl2x5rnrauzc4gp665q3zyw0qf2sfdsx5wpp832htfavqk72uchuuvq2dpmgk8jfaza5t5l56u66fpx0sr8ewp9s3wj2txavmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqgegsaj" + + let derivationTool = DerivationTool(networkType: NetworkType.testnet) + let expectedTransparentAddress = "tmXuTnE11JojToagTqxXUn6KvdxDE3iLKbp" + func testDeriveViewingKeysFromSeed() throws { + let accounts: Int = 1 + let seedBytes = [UInt8](seedData) + let viewingKeys = try derivationTool.deriveViewingKeys(seed: seedBytes, numberOfAccounts: accounts) + + XCTAssertEqual(viewingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive") + + guard let viewingKey = viewingKeys.first else { + XCTFail("no viewing key generated") + return + } + XCTAssertEqual(expectedViewingKey, viewingKey) + + } + + func testDeriveViewingKeyFromSpendingKeys() throws { + XCTAssertEqual(expectedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey)) + } + + func testDeriveSpendingKeysFromSeed() throws { + let accounts: Int = 1 + let seedBytes = [UInt8](seedData) + + let spendingKeys = try derivationTool.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: accounts) + XCTAssertEqual(spendingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive") + + guard let spendingKey = spendingKeys.first else { + XCTFail("no viewing key generated") + return + } + XCTAssertEqual(expectedSpendingKey, spendingKey) + + } + + func testDeriveShieldedAddressFromSeed() throws { + let seedBytes = [UInt8](seedData) + + let shieldedAddress = try derivationTool.deriveShieldedAddress(seed: seedBytes, accountIndex: 0) + XCTAssertEqual(shieldedAddress, testRecipientAddress) + } + + func testDeriveShieldedAddressFromViewingKey() throws { + XCTAssertEqual(try derivationTool.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress) + } + + func testDeriveTransparentAddressFromSeed() throws { + XCTAssertEqual(try derivationTool.deriveTransparentAddress(seed: [UInt8](seedData)), expectedTransparentAddress) + } + + func testIsValidViewingKey() throws { + XCTAssertTrue(try derivationTool.isValidExtendedViewingKey(self.expectedViewingKey)) + + XCTAssertFalse(try derivationTool.isValidExtendedViewingKey("zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy")) + } + + func testDeriveSecretKeyFromSeed() throws { + XCTAssertEqual(try derivationTool.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "L2BCTxmSDiBRb33kGFd4pwGhp9r3FZqG3LZihgTkkg1J14vwtDbq") + } + + func testDeriveUnifiedKeysFromSeed() throws { + let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1) + XCTAssertEqual(unifiedKeys.count, 1) + + XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) + + XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + } + + func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws { + let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10) + XCTAssertEqual(unifiedKeys.count, 10) + + XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) + + XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + } +} diff --git a/DerivationToolTests/DerivationToolTests.swift b/DerivationToolTests/DerivationToolMainnetTests.swift similarity index 99% rename from DerivationToolTests/DerivationToolTests.swift rename to DerivationToolTests/DerivationToolMainnetTests.swift index 7ed29364..f2336881 100644 --- a/DerivationToolTests/DerivationToolTests.swift +++ b/DerivationToolTests/DerivationToolMainnetTests.swift @@ -8,7 +8,7 @@ import XCTest import ZcashLightClientKit -class DerivationToolTests: XCTestCase { +class DerivationToolMainnetTests: XCTestCase { var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment? var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! let testRecipientAddress = "zs1vp7kvlqr4n9gpehztr76lcn6skkss9p8keqs3nv8avkdtjrcctrvmk9a7u494kluv756jeee5k0" //TODO: Parameterize this from environment diff --git a/Scripts/build_librustzcash_xcode.sh b/Scripts/build_librustzcash_xcode.sh index 651495db..4c928e2c 100755 --- a/Scripts/build_librustzcash_xcode.sh +++ b/Scripts/build_librustzcash_xcode.sh @@ -26,11 +26,11 @@ if [ existing_build_mismatch = true ]; then exit 1 fi -if is_mainnet; then - FEATURE_FLAGS="--features=mainnet" -else - FEATURE_FLAGS="--features=testnet" -fi +# if is_mainnet; then +# FEATURE_FLAGS="--features=mainnet" +# else +# FEATURE_FLAGS="--features=testnet" +# fi echo "Building Rust backend" echo "" diff --git a/Scripts/generate_zcashsdk_constants.sh b/Scripts/generate_zcashsdk_constants.sh index 82fa497f..2887f63d 100644 --- a/Scripts/generate_zcashsdk_constants.sh +++ b/Scripts/generate_zcashsdk_constants.sh @@ -19,9 +19,9 @@ echo "export ZCASH_SRC_PATH=${ZCASH_SRC_PATH}" check_environment if is_mainnet; then - SOURCERY_ARGS="--args dbprefix=ZcashSdk_mainnet_ --args ismainnet=true --args saplingActivationHeight=419_200" + SOURCERY_ARGS="--args ismainnet=true" else - SOURCERY_ARGS="--args dbprefix=ZcashSdk_testnet_ --args ismainnet=false --args saplingActivationHeight=280_000" + SOURCERY_ARGS="--args ismainnet=false" fi if [ -d $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]; then From aaf56aeeeb5a33409f9c465880d6c4083e187650 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 28 Jul 2021 13:59:10 -0300 Subject: [PATCH 06/17] Add ZcashNetwork to tests --- Constants/ZcashSDK.swift | 54 ++++---- .../CompactBlockDownloadOperation.swift | 4 +- .../Processor/CompactBlockProcessor.swift | 46 +++---- .../Entity/TransactionEntity.swift | 2 +- ZcashLightClientKit/Initializer.swift | 22 +-- .../Providers/ResourceProvider.swift | 6 +- .../PersistentTransactionManager.swift | 2 +- .../WalletTransactionEncoder.swift | 10 +- .../UIKit/Synchronizer/SDKSynchronizer.swift | 4 +- .../AdvancedReOrgTests.swift | 5 +- ZcashLightClientKitTests/BalanceTests.swift | 32 ++--- .../BlockBatchValidationTests.swift | 38 +++--- .../BlockDownloaderTests.swift | 24 ++-- .../BlockScanOperationTests.swift | 20 +-- .../BlockStreamingTest.swift | 12 +- .../CompactBlockProcessorTests.swift | 15 ++- .../CompactBlockReorgTests.swift | 11 +- .../CompactBlockStorageTests.swift | 5 +- .../DarksideSanityCheckTests.swift | 4 +- .../DownloadOperationTests.swift | 5 +- .../LightWalletServiceTests.swift | 11 +- .../NetworkUpgradeTests.swift | 11 +- ZcashLightClientKitTests/NullBytesTests.swift | 14 +- .../PagedTransactionRepositoryTests.swift | 2 +- .../PendingTransactionUpdatesTest.swift | 4 +- ZcashLightClientKitTests/ReOrgTests.swift | 28 ++-- .../RewindRescanTests.swift | 18 +-- .../SychronizerDarksideTests.swift | 4 +- .../TestCoordinator.swift | 35 +++-- .../TransactionEnhancementTests.swift | 77 ++++++----- ZcashLightClientKitTests/WalletTests.swift | 44 +++--- .../ZcashLightClientKitTests.swift | 2 +- .../ZcashRustBackendTests.swift | 31 +++-- .../utils/DarkSideWalletService.swift | 35 +++++ .../utils/MockTransactionRepository.swift | 9 +- ZcashLightClientKitTests/utils/Stubs.swift | 126 +++++++++--------- .../utils/Tests+Utils.swift | 4 + 37 files changed, 449 insertions(+), 327 deletions(-) diff --git a/Constants/ZcashSDK.swift b/Constants/ZcashSDK.swift index 6926a588..5522f400 100644 --- a/Constants/ZcashSDK.swift +++ b/Constants/ZcashSDK.swift @@ -6,17 +6,21 @@ // import Foundation +public protocol ZcashNetwork { + var networkType: NetworkType { get } + var constants: NetworkConstants.Type { get } +} public enum NetworkType { case mainnet case testnet - var constants: NetworkConstants.Type { + var networkId: UInt32 { switch self { case .mainnet: - return ZcashSDKMainnet.self + return 1 case .testnet: - return ZcashSDKTestnet.self + return 0 } } } @@ -32,17 +36,29 @@ extension NetworkType { return nil } } - - var networkId: UInt32 { - switch self { +} + +public class ZcashNetworkBuilder { + static func network(for networkType: NetworkType) -> ZcashNetwork { + switch networkType { case .mainnet: - return 1 + return ZcashMainnet() case .testnet: - return 0 + return ZcashTestnet() } } } +class ZcashTestnet: ZcashNetwork { + var networkType: NetworkType = .testnet + var constants: NetworkConstants.Type = ZcashSDKTestnetConstants.self +} + +class ZcashMainnet: ZcashNetwork { + var networkType: NetworkType = .mainnet + var constants: NetworkConstants.Type = ZcashSDKMainnetConstants.self +} + /** Constants of ZcashLightClientKit. this constants don't */ @@ -167,7 +183,7 @@ public extension NetworkConstants { } } -public class ZcashSDKMainnet: NetworkConstants { +public class ZcashSDKMainnetConstants: NetworkConstants { private init() {} @@ -189,28 +205,14 @@ public class ZcashSDKMainnet: NetworkConstants { Default name for pending transactions db */ public static var DEFAULT_PENDING_DB_NAME = "pending.db" - public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_" - /** - File name for the sapling spend params - */ - public static var SPEND_PARAM_FILE_NAME = "sapling-spend.params" - /** - File name for the sapling output params - */ - public static var OUTPUT_PARAM_FILE_NAME = "sapling-output.params" - /** - The Url that is used by default in zcashd. - We'll want to make this externally configurable, rather than baking it into the SDK but - this will do for now, since we're using a cloudfront URL that already redirects. - */ - public static var CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/" - public static var isMainnet = true + public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_" + public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_077_550 } -public class ZcashSDKTestnet: NetworkConstants { +public class ZcashSDKTestnetConstants: NetworkConstants { private init() {} /** diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift index 8782541e..d553bb4b 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift @@ -180,10 +180,12 @@ class CompactBlockBatchDownloadOperation: ZcashOperation { do { let localDownloadedHeight = try self.storage.latestHeight() - if localDownloadedHeight != startHeight { + + if localDownloadedHeight != BlockHeight.empty() && localDownloadedHeight > startHeight { LoggerProxy.warn("provided startHeight (\(startHeight)) differs from local latest downloaded height (\(localDownloadedHeight))") startHeight = localDownloadedHeight + 1 } + var currentHeight = startHeight self.progressDelegate?.progressUpdated(.download(BlockProgress(startHeight: currentHeight, targetHeight: targetHeight, progressHeight: currentHeight))) diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index bb2f3c49..c3136caf 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -228,7 +228,7 @@ public class CompactBlockProcessor { public var maxBackoffInterval = ZcashSDK.DEFAULT_MAX_BACKOFF_INTERVAL public var rewindDistance = ZcashSDK.DEFAULT_REWIND_DISTANCE public var walletBirthday: BlockHeight - private(set) var network: NetworkType + private(set) var network: ZcashNetwork private(set) var saplingActivation: BlockHeight init ( @@ -240,7 +240,7 @@ public class CompactBlockProcessor { rewindDistance: Int, walletBirthday: BlockHeight, saplingActivation: BlockHeight, - network: NetworkType + network: ZcashNetwork ) { self.cacheDb = cacheDb self.dataDb = dataDb @@ -253,12 +253,12 @@ public class CompactBlockProcessor { self.saplingActivation = saplingActivation } - public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight, networkType: NetworkType){ + public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight, network: ZcashNetwork){ self.cacheDb = cacheDb self.dataDb = dataDb self.walletBirthday = walletBirthday - self.saplingActivation = networkType.constants.SAPLING_ACTIVATION_HEIGHT - self.network = networkType + self.saplingActivation = network.constants.SAPLING_ACTIVATION_HEIGHT + self.network = network } } /** @@ -392,7 +392,7 @@ public class CompactBlockProcessor { config: Configuration(cacheDb: initializer.cacheDbURL, dataDb: initializer.dataDbURL, walletBirthday: initializer.walletBirthday.height, - networkType: initializer.network), + network: initializer.network), repository: initializer.transactionRepository, accountRepository: initializer.accountRepository) } @@ -513,7 +513,7 @@ public class CompactBlockProcessor { static func validateServerInfo(_ info: LightWalletdInfo, saplingActivation: BlockHeight, - localNetwork: NetworkType, + localNetwork: ZcashNetwork, rustBackend: ZcashRustBackendWelding.Type) throws { // check network types @@ -521,8 +521,8 @@ public class CompactBlockProcessor { throw CompactBlockProcessorError.generalError(message: "Chain name does not match. Expected either 'test' or 'main' but received '\(info.chainName)'. this is probably an API or programming error") } - guard remoteNetworkType == localNetwork else { - throw CompactBlockProcessorError.networkMismatch(expected: localNetwork, found: remoteNetworkType) + guard remoteNetworkType == localNetwork.networkType else { + throw CompactBlockProcessorError.networkMismatch(expected: localNetwork.networkType, found: remoteNetworkType) } guard saplingActivation == info.saplingActivationHeight else { @@ -530,7 +530,7 @@ public class CompactBlockProcessor { } // check branch id - let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight), networkType: localNetwork) + let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight), networkType: localNetwork.networkType) guard let remoteBranchID = ConsensusBranchID.fromString(info.consensusBranchID) else { @@ -571,7 +571,7 @@ public class CompactBlockProcessor { let lastDownloaded = try downloader.lastDownloadedBlockHeight() let height = Int32(height ?? lastDownloaded) - let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height, networkType: self.config.network) + let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height, networkType: self.config.network.networkType) guard nearestHeight > 0 else { let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error getting nearest rewind height for height: \(height)") @@ -581,7 +581,7 @@ public class CompactBlockProcessor { // FIXME: this should be done on the rust layer let rewindHeight = max(Int32(nearestHeight - 1) , Int32(config.walletBirthday)) - guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network) else { + guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network.networkType) else { let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)") fail(error) throw error @@ -656,7 +656,7 @@ public class CompactBlockProcessor { } } - let validateChainOperation = CompactBlockValidationOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb, networkType: self.config.network) + let validateChainOperation = CompactBlockValidationOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb, networkType: self.config.network.networkType) let downloadValidateAdapterOperation = BlockOperation { [weak validateChainOperation, weak downloadBlockOperation] in validateChainOperation?.error = downloadBlockOperation?.error @@ -705,7 +705,7 @@ public class CompactBlockProcessor { } } - let scanBlocksOperation = CompactBlockBatchScanningOperation(rustWelding: rustBackend, cacheDb: config.cacheDb, dataDb: config.dataDb, transactionRepository: transactionRepository, range: range, networkType: self.config.network, progressDelegate: self) + let scanBlocksOperation = CompactBlockBatchScanningOperation(rustWelding: rustBackend, cacheDb: config.cacheDb, dataDb: config.dataDb, transactionRepository: transactionRepository, range: range, networkType: self.config.network.networkType, progressDelegate: self) let validateScanningAdapterOperation = BlockOperation { [weak scanBlocksOperation, weak validateChainOperation] in scanBlocksOperation?.error = validateChainOperation?.error @@ -734,7 +734,7 @@ public class CompactBlockProcessor { } } - let enhanceOperation = CompactBlockEnhancementOperation(rustWelding: rustBackend, dataDb: config.dataDb, downloader: downloader, repository: transactionRepository, range: range.blockRange(), networkType: self.config.network) + let enhanceOperation = CompactBlockEnhancementOperation(rustWelding: rustBackend, dataDb: config.dataDb, downloader: downloader, repository: transactionRepository, range: range.blockRange(), networkType: self.config.network.networkType) enhanceOperation.startedHandler = { LoggerProxy.debug("Started Enhancing range: \(range)") @@ -767,7 +767,7 @@ public class CompactBlockProcessor { enhanceOperation?.error = scanBlocksOperation?.error } - let fetchOperation = FetchUnspentTxOutputsOperation(accountRepository: accountRepository, downloader: self.downloader, rustbackend: rustBackend, dataDb: config.dataDb, startHeight: config.walletBirthday, networkType: self.config.network) + let fetchOperation = FetchUnspentTxOutputsOperation(accountRepository: accountRepository, downloader: self.downloader, rustbackend: rustBackend, dataDb: config.dataDb, startHeight: config.walletBirthday, networkType: self.config.network.networkType) fetchOperation.startedHandler = { [weak self] in DispatchQueue.main.async { [weak self] in @@ -862,7 +862,7 @@ public class CompactBlockProcessor { // rewind let rewindHeight = determineLowerBound(errorHeight: height, consecutiveErrors: consecutiveChainValidationErrors, walletBirthday: self.config.walletBirthday) - guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network) else { + guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network.networkType) else { fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)")) return } @@ -1060,12 +1060,12 @@ public extension CompactBlockProcessor.Configuration { /** Standard configuration for most compact block processors */ - static func standard(for networkType: NetworkType, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration { - let pathProvider = DefaultResourceProvider(networkType: networkType) + static func standard(for network: ZcashNetwork, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration { + let pathProvider = DefaultResourceProvider(network: network) return CompactBlockProcessor.Configuration(cacheDb: pathProvider.cacheDbURL, dataDb: pathProvider.dataDbURL, walletBirthday: walletBirthday, - networkType: networkType) + network: network) } } @@ -1113,7 +1113,7 @@ extension CompactBlockProcessor.State: Equatable { extension CompactBlockProcessor { public func utxoCacheBalance(tAddress: String) throws -> WalletBalance { - try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress, networkType: config.network) + try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress, networkType: config.network.networkType) } } @@ -1173,7 +1173,7 @@ extension CompactBlockProcessor { guard let self = self else { return } do { - guard try self.rustBackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1, networkType: self.config.network) >= 0 else { + guard try self.rustBackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1, networkType: self.config.network.networkType) >= 0 else { result(.failure(CompactBlockProcessorError.generalError(message: "attempted to clear utxos but -1 was returned"))) return } @@ -1202,7 +1202,7 @@ extension CompactBlockProcessor { script: utxo.script.bytes, value: Int64(utxo.valueZat), height: utxo.height, - networkType: self.config.network) ? refreshed.append(utxo) : skipped.append(utxo) + networkType: self.config.network.networkType) ? refreshed.append(utxo) : skipped.append(utxo) } catch { LoggerProxy.info("failed to put utxo - error: \(error)") skipped.append(utxo) diff --git a/ZcashLightClientKit/Entity/TransactionEntity.swift b/ZcashLightClientKit/Entity/TransactionEntity.swift index f713b94d..06eff89c 100644 --- a/ZcashLightClientKit/Entity/TransactionEntity.swift +++ b/ZcashLightClientKit/Entity/TransactionEntity.swift @@ -57,7 +57,7 @@ public extension TransactionEntity { return true } - func anchor(network: NetworkType) -> BlockHeight? { + func anchor(network: ZcashNetwork) -> BlockHeight? { if let minedHeight = self.minedHeight, minedHeight != -1 { return max(minedHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE, network.constants.SAPLING_ACTIVATION_HEIGHT) } diff --git a/ZcashLightClientKit/Initializer.swift b/ZcashLightClientKit/Initializer.swift index 4ab61602..9f8c44fb 100644 --- a/ZcashLightClientKit/Initializer.swift +++ b/ZcashLightClientKit/Initializer.swift @@ -75,7 +75,7 @@ public class Initializer { private(set) var accountRepository: AccountRepository private(set) var storage: CompactBlockStorage private(set) var downloader: CompactBlockDownloader - private(set) var network: NetworkType + private(set) var network: ZcashNetwork private(set) public var viewingKeys: [UnifiedViewingKey] private(set) public var walletBirthday: WalletBirthday /** @@ -92,7 +92,7 @@ public class Initializer { dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, - network: NetworkType, + network: ZcashNetwork, spendParamsURL: URL, outputParamsURL: URL, viewingKeys: [UnifiedViewingKey], @@ -127,7 +127,7 @@ public class Initializer { */ init(rustBackend: ZcashRustBackendWelding.Type, lowerBoundHeight: BlockHeight, - network: NetworkType, + network: ZcashNetwork, cacheDbURL: URL, dataDbURL: URL, pendingDbURL: URL, @@ -187,7 +187,7 @@ public class Initializer { } do { - try rustBackend.initDataDb(dbData: dataDbURL, networkType: network) + try rustBackend.initDataDb(dbData: dataDbURL, networkType: network.networkType) } catch RustWeldingError.dataDbNotEmpty { // this is fine } catch { @@ -195,7 +195,7 @@ public class Initializer { } do { - try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree, networkType: network) + try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree, networkType: network.networkType) } catch RustWeldingError.dataDbNotEmpty { // this is fine } catch { @@ -207,7 +207,7 @@ public class Initializer { lowerBoundHeight = max(walletBirthday.height, lastDownloaded) do { - guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys, networkType: network) else { + guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys, networkType: network.networkType) else { throw rustBackend.lastError() ?? InitializerError.accountInitFailed } } catch RustWeldingError.dataDbNotEmpty { @@ -219,7 +219,7 @@ public class Initializer { let migrationManager = MigrationManager(cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path), dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path), - networkType: self.network) + networkType: self.network.networkType) try migrationManager.performMigration(uvks: viewingKeys) } @@ -236,7 +236,7 @@ public class Initializer { - Parameter account: the index of the account */ public func getBalance(account index: Int = 0) -> Int64 { - rustBackend.getBalance(dbData: dataDbURL, account: Int32(index), networkType: network) + rustBackend.getBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType) } /** @@ -244,20 +244,20 @@ public class Initializer { - Parameter account: the index of the account */ public func getVerifiedBalance(account index: Int = 0) -> Int64 { - rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index), networkType: network) + rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType) } /** checks if the provided address is a valid shielded zAddress */ public func isValidShieldedAddress(_ address: String) -> Bool { - (try? rustBackend.isValidShieldedAddress(address, networkType: network)) ?? false + (try? rustBackend.isValidShieldedAddress(address, networkType: network.networkType)) ?? false } /** checks if the provided address is a transparent zAddress */ public func isValidTransparentAddress(_ address: String) -> Bool { - (try? rustBackend.isValidTransparentAddress(address,networkType: network)) ?? false + (try? rustBackend.isValidTransparentAddress(address,networkType: network.networkType)) ?? false } func isSpendParameterPresent() -> Bool { diff --git a/ZcashLightClientKit/Providers/ResourceProvider.swift b/ZcashLightClientKit/Providers/ResourceProvider.swift index 6e412f5a..f24f5566 100644 --- a/ZcashLightClientKit/Providers/ResourceProvider.swift +++ b/ZcashLightClientKit/Providers/ResourceProvider.swift @@ -21,10 +21,10 @@ public protocol ResourceProvider { Convenience provider for a data db and cache db resources. */ public struct DefaultResourceProvider: ResourceProvider { - init(networkType: NetworkType) { - self.network = networkType + init(network: ZcashNetwork) { + self.network = network } - var network: NetworkType + var network: ZcashNetwork public var dataDbURL: URL { let constants = network.constants do { diff --git a/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift b/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift index fae3010c..e5fc2f80 100644 --- a/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift +++ b/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift @@ -249,7 +249,7 @@ class PersistentTransactionManager: OutboundTransactionManager { class OutboundTransactionManagerBuilder { static func build(initializer: Initializer) throws -> OutboundTransactionManager { - return PersistentTransactionManager(encoder: TransactionEncoderbuilder.build(initializer: initializer), service: initializer.lightWalletService, repository: try PendingTransactionRepositoryBuilder.build(initializer: initializer), networkType: initializer.network) + return PersistentTransactionManager(encoder: TransactionEncoderbuilder.build(initializer: initializer), service: initializer.lightWalletService, repository: try PendingTransactionRepositoryBuilder.build(initializer: initializer), networkType: initializer.network.networkType) } } diff --git a/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift b/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift index c90739ca..a389f413 100644 --- a/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift +++ b/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift @@ -16,7 +16,7 @@ class WalletTransactionEncoder: TransactionEncoder { private var spendParamsURL: URL private var dataDbURL: URL private var cacheDbURL: URL - private var network: NetworkType + private var networkType: NetworkType init(rust: ZcashRustBackendWelding.Type, dataDb: URL, @@ -32,7 +32,7 @@ class WalletTransactionEncoder: TransactionEncoder { self.repository = repository self.outputParamsURL = outputParams self.spendParamsURL = spendParams - self.network = networkType + self.networkType = networkType self.queue = DispatchQueue(label: "wallet.transaction.encoder.serial.queue") } @@ -44,7 +44,7 @@ class WalletTransactionEncoder: TransactionEncoder { repository: initializer.transactionRepository, outputParams: initializer.outputParamsURL, spendParams: initializer.spendParamsURL, - networkType: initializer.network) + networkType: initializer.network.networkType) } @@ -91,7 +91,7 @@ class WalletTransactionEncoder: TransactionEncoder { memo: memo, spendParamsPath: self.spendParamsURL.path, outputParamsPath: self.outputParamsURL.path, - networkType: network) + networkType: networkType) guard txId > 0 else { throw rustBackend.lastError() ?? RustWeldingError.genericError(message: "create spend failed") @@ -136,7 +136,7 @@ class WalletTransactionEncoder: TransactionEncoder { memo: memo, spendParamsPath: self.spendParamsURL.path, outputParamsPath: self.outputParamsURL.path, - networkType: network) + networkType: networkType) guard txId > 0 else { throw rustBackend.lastError() ?? RustWeldingError.genericError(message: "create spend failed") diff --git a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift index c1b827b8..5f4b10d1 100644 --- a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift +++ b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift @@ -126,7 +126,7 @@ public class SDKSynchronizer: Synchronizer { public private(set) var initializer: Initializer public private(set) var latestScannedHeight: BlockHeight public private(set) var connectionState: ConnectionState - public private(set) var network: NetworkType + public private(set) var network: ZcashNetwork private var transactionManager: OutboundTransactionManager private var transactionRepository: TransactionRepository private var utxoRepository: UnspentTransactionOutputRepository @@ -444,7 +444,7 @@ public class SDKSynchronizer: Synchronizer { public func shieldFunds(spendingKey: String, transparentSecretKey: String, memo: String?, from accountIndex: Int, resultBlock: @escaping (Result) -> Void) { // let's see if there are funds to shield - let derivationTool = DerivationTool(networkType: self.network) + let derivationTool = DerivationTool(networkType: self.network.networkType) do { let tAddr = try derivationTool.deriveTransparentAddressFromPrivateKey(transparentSecretKey) diff --git a/ZcashLightClientKitTests/AdvancedReOrgTests.swift b/ZcashLightClientKitTests/AdvancedReOrgTests.swift index 184db512..bef525e4 100644 --- a/ZcashLightClientKitTests/AdvancedReOrgTests.swift +++ b/ZcashLightClientKitTests/AdvancedReOrgTests.swift @@ -24,12 +24,15 @@ class AdvancedReOrgTests: XCTestCase { var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") let branchID = "2bb40e60" let chainName = "main" + let network = DarksideWalletDNetwork() + override func setUpWithError() throws { coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName) } diff --git a/ZcashLightClientKitTests/BalanceTests.swift b/ZcashLightClientKitTests/BalanceTests.swift index 851549f7..fb7ce46a 100644 --- a/ZcashLightClientKitTests/BalanceTests.swift +++ b/ZcashLightClientKitTests/BalanceTests.swift @@ -20,12 +20,14 @@ class BalanceTests: XCTestCase { let chainName = "main" var syncedExpectation = XCTestExpectation(description: "synced") var sentTransactionExpectation = XCTestExpectation(description: "sent") + let network: ZcashNetwork = DarksideWalletDNetwork() override func setUpWithError() throws { coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main") @@ -58,10 +60,10 @@ class BalanceTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) - let maxBalance = verifiedBalance - Int64(ZcashSDK.defaultFee()) + let maxBalance = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight)) // 3 create a transaction for the max amount possible // 4 send the transaction @@ -196,10 +198,10 @@ class BalanceTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) - let maxBalanceMinusOne = verifiedBalance - Int64(ZcashSDK.defaultFee()) - 1 + let maxBalanceMinusOne = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight)) - 1 // 3 create a transaction for the max amount possible // 4 send the transaction @@ -333,10 +335,10 @@ class BalanceTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) - let maxBalanceMinusOne = 100000 - ZcashSDK.defaultFee() + let maxBalanceMinusOne = 100000 - network.constants.defaultFee(for: defaultLatestHeight) // 3 create a transaction for the max amount possible // 4 send the transaction @@ -483,7 +485,7 @@ class BalanceTests: XCTestCase { /* there's more zatoshi to send than network fee */ - XCTAssertTrue(presendVerifiedBalance >= (Int64(ZcashSDK.MINERS_FEE_ZATOSHI) + sendAmount)) + XCTAssertTrue(presendVerifiedBalance >= (Int64(network.constants.defaultFee(for: defaultLatestHeight)) + sendAmount)) var pendingTx: PendingTransactionEntity? coordinator.synchronizer.sendToAddress(spendingKey: spendingKey, @@ -540,8 +542,8 @@ class BalanceTests: XCTestCase { wait(for: [mineExpectation], timeout: 5) - XCTAssertEqual(presendVerifiedBalance - self.sendAmount - ZcashSDK.defaultFee(),coordinator.synchronizer.initializer.getBalance()) - XCTAssertEqual(presendVerifiedBalance - self.sendAmount - ZcashSDK.defaultFee(),coordinator.synchronizer.initializer.getVerifiedBalance()) + XCTAssertEqual(presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),coordinator.synchronizer.initializer.getBalance()) + XCTAssertEqual(presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),coordinator.synchronizer.initializer.getVerifiedBalance()) guard let transaction = pendingTx else { XCTFail("pending transaction nil") @@ -629,7 +631,7 @@ class BalanceTests: XCTestCase { } let presendBalance = coordinator.synchronizer.initializer.getBalance() - XCTAssertTrue(presendBalance >= (Int64(ZcashSDK.defaultFee()) + sendAmount)) // there's more zatoshi to send than network fee + XCTAssertTrue(presendBalance >= (Int64(network.constants.defaultFee(for: defaultLatestHeight)) + sendAmount)) // there's more zatoshi to send than network fee var pendingTx: PendingTransactionEntity? @@ -667,7 +669,7 @@ class BalanceTests: XCTestCase { XCTAssertEqual(Int64(transaction.value), self.sendAmount) - XCTAssertEqual(self.coordinator.synchronizer.initializer.getBalance(), presendBalance - Int64(self.sendAmount) - ZcashSDK.defaultFee()) + XCTAssertEqual(self.coordinator.synchronizer.initializer.getBalance(), presendBalance - Int64(self.sendAmount) - network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertNil(transaction.errorCode) @@ -697,7 +699,7 @@ class BalanceTests: XCTestCase { wait(for: [mineExpectation], timeout: 5) - XCTAssertEqual(presendBalance - self.sendAmount - Int64(ZcashSDK.defaultFee()),coordinator.synchronizer.initializer.getBalance()) + XCTAssertEqual(presendBalance - self.sendAmount - Int64(network.constants.defaultFee(for: defaultLatestHeight)),coordinator.synchronizer.initializer.getBalance()) } /** @@ -869,7 +871,7 @@ class BalanceTests: XCTestCase { /* There’s a change note of value (previous note value - sent amount) */ - XCTAssertEqual(previousVerifiedBalance - self.sendAmount - ZcashSDK.defaultFee(), Int64(receivedNote.value)) + XCTAssertEqual(previousVerifiedBalance - self.sendAmount - self.network.constants.defaultFee(for: self.defaultLatestHeight), Int64(receivedNote.value)) /* @@ -1024,7 +1026,7 @@ class BalanceTests: XCTestCase { func totalBalanceValidation(totalBalance: Int64, previousTotalbalance: Int64, sentAmount: Int64) { - XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - Int64(ZcashSDK.MINERS_FEE_ZATOSHI)) + XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - Int64(network.constants.defaultFee(for: defaultLatestHeight))) } } diff --git a/ZcashLightClientKitTests/BlockBatchValidationTests.swift b/ZcashLightClientKitTests/BlockBatchValidationTests.swift index d7e7a6e4..e2db71e4 100644 --- a/ZcashLightClientKitTests/BlockBatchValidationTests.swift +++ b/ZcashLightClientKitTests/BlockBatchValidationTests.swift @@ -24,17 +24,18 @@ class BlockBatchValidationTests: XCTestCase { } func testBranchIdFailure() throws { + let network = ZcashNetworkBuilder.network(for: .mainnet) let service = MockLightWalletService(latestBlockHeight: 1210000) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = 130000 info.branch = "d34db33f" info.chainName = "main" info.buildUser = "test user" info.consensusBranchID = "d34db33f" - info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) service.mockLightDInfo = info let mockRust = MockRustBackend.self @@ -63,17 +64,18 @@ class BlockBatchValidationTests: XCTestCase { } func testBranchNetworkMismatchFailure() throws { + let network = ZcashNetworkBuilder.network(for: .mainnet) let service = MockLightWalletService(latestBlockHeight: 1210000) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = 130000 info.branch = "d34db33f" info.chainName = "test" info.buildUser = "test user" info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) service.mockLightDInfo = info let mockRust = MockRustBackend.self @@ -103,17 +105,18 @@ class BlockBatchValidationTests: XCTestCase { func testBranchNetworkTypeWrongFailure() throws { + let network = ZcashNetworkBuilder.network(for: .testnet) let service = MockLightWalletService(latestBlockHeight: 1210000) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = 130000 info.branch = "d34db33f" info.chainName = "another" info.buildUser = "test user" info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) service.mockLightDInfo = info let mockRust = MockRustBackend.self @@ -142,10 +145,11 @@ class BlockBatchValidationTests: XCTestCase { } func testSaplingActivationHeightMismatch() throws { + let network = ZcashNetworkBuilder.network(for: .mainnet) let service = MockLightWalletService(latestBlockHeight: 1210000) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = 130000 info.branch = "d34db33f" @@ -167,7 +171,7 @@ class BlockBatchValidationTests: XCTestCase { operation.errorHandler = { error in expectation.fulfill() switch error { - case CompactBlockProcessorError.saplingActivationMismatch(expected: ZcashSDK.SAPLING_ACTIVATION_HEIGHT, found: BlockHeight(info.saplingActivationHeight)): + case CompactBlockProcessorError.saplingActivationMismatch(expected: network.constants.SAPLING_ACTIVATION_HEIGHT, found: BlockHeight(info.saplingActivationHeight)): break default: XCTFail("Expected CompactBlockProcessorError.saplingActivationMismatch but found \(error)") @@ -181,20 +185,22 @@ class BlockBatchValidationTests: XCTestCase { } func testResultIsWait() throws { + let network = ZcashNetworkBuilder.network(for: .mainnet) + let expectedLatestHeight = BlockHeight(1210000) let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight) let expectedStoreLatestHeight = BlockHeight(1220000) let expectedResult = FigureNextBatchOperation.NextState.wait(latestHeight: expectedLatestHeight, latestDownloadHeight: expectedLatestHeight) let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = UInt64(expectedLatestHeight) info.branch = "d34db33f" info.chainName = "main" info.buildUser = "test user" info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) service.mockLightDInfo = info let mockRust = MockRustBackend.self @@ -207,7 +213,7 @@ class BlockBatchValidationTests: XCTestCase { startedExpectation.fulfill() } operation.errorHandler = { error in - XCTFail("this shouldn't happen") + XCTFail("this shouldn't happen: \(error)") } operation.completionHandler = { (finished, cancelled) in completedExpectation.fulfill() @@ -236,6 +242,7 @@ class BlockBatchValidationTests: XCTestCase { } func testResultProcessNew() throws { + let network = ZcashNetworkBuilder.network(for: .mainnet) let expectedLatestHeight = BlockHeight(1230000) let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight) let expectedStoreLatestHeight = BlockHeight(1220000) @@ -243,14 +250,14 @@ class BlockBatchValidationTests: XCTestCase { let expectedResult = FigureNextBatchOperation.NextState.processNewBlocks(range: CompactBlockProcessor.nextBatchBlockRange(latestHeight: expectedLatestHeight, latestDownloadedHeight: expectedStoreLatestHeight, walletBirthday: walletBirthday)) let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = UInt64(expectedLatestHeight) info.branch = "d34db33f" info.chainName = "main" info.buildUser = "test user" info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) service.mockLightDInfo = info let mockRust = MockRustBackend.self @@ -292,6 +299,7 @@ class BlockBatchValidationTests: XCTestCase { } func testResultProcessorFinished() throws { + let network = ZcashNetworkBuilder.network(for: .mainnet) let expectedLatestHeight = BlockHeight(1230000) let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight) let expectedStoreLatestHeight = BlockHeight(1230000) @@ -299,14 +307,14 @@ class BlockBatchValidationTests: XCTestCase { let expectedResult = FigureNextBatchOperation.NextState.finishProcessing(height: expectedStoreLatestHeight) let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight) let downloader = CompactBlockDownloader(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) var info = LightdInfo() info.blockHeight = UInt64(expectedLatestHeight) info.branch = "d34db33f" info.chainName = "main" info.buildUser = "test user" info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) service.mockLightDInfo = info let mockRust = MockRustBackend.self diff --git a/ZcashLightClientKitTests/BlockDownloaderTests.swift b/ZcashLightClientKitTests/BlockDownloaderTests.swift index 962304aa..f4f21bf5 100644 --- a/ZcashLightClientKitTests/BlockDownloaderTests.swift +++ b/ZcashLightClientKitTests/BlockDownloaderTests.swift @@ -14,10 +14,18 @@ class BlockDownloaderTests: XCTestCase { var service: LightWalletService! var storage: CompactBlockRepository! var cacheDB = try! __cacheDbURL() - override func setUp() { + var network = DarksideWalletDNetwork() + var darksideWalletService: DarksideWalletService! + let branchID = "2bb40e60" + let chainName = "main" + override func setUpWithError() throws { service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) storage = try! TestDbBuilder.diskCompactBlockStorage(at: cacheDB) downloader = CompactBlockDownloader(service: service, storage: storage) + darksideWalletService = DarksideWalletService(service: service as! LightWalletGRPCService) + + try FakeChainBuilder.buildChain(darksideWallet: darksideWalletService, branchID: branchID, chainName: chainName) + try darksideWalletService.applyStaged(nextLatestHeight: 663250) } override func tearDown() { @@ -32,8 +40,8 @@ class BlockDownloaderTests: XCTestCase { let expect = XCTestExpectation(description: self.description) expect.expectedFulfillmentCount = 3 - let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT - let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99 + let lowerRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + let upperRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 99 let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange)) downloader.downloadBlockRange(range) { (error) in @@ -58,8 +66,8 @@ class BlockDownloaderTests: XCTestCase { func testSmallDownload() { - let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT - let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99 + let lowerRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + let upperRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 99 let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange)) var latest: BlockHeight = 0 @@ -86,12 +94,12 @@ class BlockDownloaderTests: XCTestCase { } func testFailure() { - let awfulDownloader = CompactBlockDownloader(service: AwfulLightWalletService(latestBlockHeight: ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000), storage: ZcashConsoleFakeStorage()) + let awfulDownloader = CompactBlockDownloader(service: AwfulLightWalletService(latestBlockHeight: self.network.constants.SAPLING_ACTIVATION_HEIGHT + 1000), storage: ZcashConsoleFakeStorage()) let expect = XCTestExpectation(description: self.description) expect.expectedFulfillmentCount = 1 - let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT - let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99 + let lowerRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + let upperRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 99 let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange)) diff --git a/ZcashLightClientKitTests/BlockScanOperationTests.swift b/ZcashLightClientKitTests/BlockScanOperationTests.swift index 7256e216..19e97bab 100644 --- a/ZcashLightClientKitTests/BlockScanOperationTests.swift +++ b/ZcashLightClientKitTests/BlockScanOperationTests.swift @@ -22,7 +22,7 @@ class BlockScanOperationTests: XCTestCase { var walletBirthDay = WalletBirthday.birthday(with: 1386000) - + var network = ZcashNetworkBuilder.network(for: .testnet) var blockRepository: BlockRepository! override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. @@ -47,17 +47,17 @@ class BlockScanOperationTests: XCTestCase { func testSingleDownloadAndScanOperation() { logger = SampleLogger(logLevel: .debug) - XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL)) + XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL, networkType: network.networkType)) let downloadStartedExpect = XCTestExpectation(description: self.description + "download started") let downloadExpect = XCTestExpectation(description: self.description + "download") let scanStartedExpect = XCTestExpectation(description: self.description + "scan started") let scanExpect = XCTestExpectation(description: self.description + "scan") let latestScannedBlockExpect = XCTestExpectation(description: self.description + "latestScannedHeight") - let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) + let service = LightWalletGRPCService(endpoint: LightWalletEndpoint(address: "lightwalletd.electriccoin.co", port: 9067)) let blockCount = 100 - let range = ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... ZcashSDK.SAPLING_ACTIVATION_HEIGHT + blockCount + let range = network.constants.SAPLING_ACTIVATION_HEIGHT ... network.constants.SAPLING_ACTIVATION_HEIGHT + blockCount let downloadOperation = CompactBlockDownloadOperation(downloader: CompactBlockDownloader.sqlDownloader(service: service, at: cacheDbURL)!, range: range) - let scanOperation = CompactBlockScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL) + let scanOperation = CompactBlockScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, networkType: network.networkType) downloadOperation.startedHandler = { downloadStartedExpect.fulfill() @@ -119,13 +119,13 @@ class BlockScanOperationTests: XCTestCase { NotificationCenter.default.addObserver(self, selector: #selector(observeBenchmark(_:)), name: SDKMetrics.notificationName, object: nil) - try self.rustWelding.initDataDb(dbData: dataDbURL) - guard try self.rustWelding.initAccountsTable(dbData: self.dataDbURL, uvks: [uvk]) else { + try self.rustWelding.initDataDb(dbData: dataDbURL, networkType: network.networkType) + guard try self.rustWelding.initAccountsTable(dbData: self.dataDbURL, uvks: [uvk], networkType: network.networkType) else { XCTFail("failed to init account table") return } - try self.rustWelding.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthDay.height), hash: walletBirthDay.hash, time: walletBirthDay.time, saplingTree: walletBirthDay.tree) + try self.rustWelding.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthDay.height), hash: walletBirthDay.hash, time: walletBirthDay.time, saplingTree: walletBirthDay.tree, networkType: network.networkType) let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 100000, streamingCallTimeout: 1000000000) let storage = CompactBlockStorage(url: cacheDbURL, readonly: false) @@ -161,7 +161,7 @@ class BlockScanOperationTests: XCTestCase { } - let validationOperation = CompactBlockValidationOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL) + let validationOperation = CompactBlockValidationOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, networkType: network.networkType) validationOperation.errorHandler = { error in self.operationQueue.cancelAllOperations() XCTFail("failed with error \(error)") @@ -174,7 +174,7 @@ class BlockScanOperationTests: XCTestCase { } let transactionRepository = TransactionRepositoryBuilder.build(dataDbURL: dataDbURL) - let scanningOperation = CompactBlockBatchScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, transactionRepository: transactionRepository, range: CompactBlockRange(uncheckedBounds: (walletBirthDay.height, walletBirthDay.height + 10000)), batchSize: 1000, progressDelegate: self) + let scanningOperation = CompactBlockBatchScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, transactionRepository: transactionRepository, range: CompactBlockRange(uncheckedBounds: (walletBirthDay.height, walletBirthDay.height + 10000)), batchSize: 1000, networkType: network.networkType, progressDelegate: self) scanningOperation.completionHandler = { (finished,cancelled) in XCTAssert(finished) diff --git a/ZcashLightClientKitTests/BlockStreamingTest.swift b/ZcashLightClientKitTests/BlockStreamingTest.swift index 7cd9a5de..7aeffcb8 100644 --- a/ZcashLightClientKitTests/BlockStreamingTest.swift +++ b/ZcashLightClientKitTests/BlockStreamingTest.swift @@ -26,7 +26,7 @@ class BlockStreamingTest: XCTestCase { func testExample() throws { let expectation = XCTestExpectation(description: "blockstream expectation") - let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co", + let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: Int64.max, @@ -58,7 +58,7 @@ class BlockStreamingTest: XCTestCase { func testStreamOperation() throws { let expectation = XCTestExpectation(description: "blockstream expectation") - let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co", + let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 1000, @@ -91,7 +91,7 @@ class BlockStreamingTest: XCTestCase { func testStreamOperationCancellation() throws { let expectation = XCTestExpectation(description: "blockstream expectation") - let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co", + let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 10000, @@ -124,7 +124,7 @@ class BlockStreamingTest: XCTestCase { func testStreamOperationTimeout() throws { let expectation = XCTestExpectation(description: "blockstream expectation") let errorExpectation = XCTestExpectation(description: "blockstream error expectation") - let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co", + let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 1000, @@ -176,7 +176,7 @@ class BlockStreamingTest: XCTestCase { func testBatchOperation() throws { let expectation = XCTestExpectation(description: "blockbatch expectation") - let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co", + let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 300000, @@ -209,7 +209,7 @@ class BlockStreamingTest: XCTestCase { func testBatchOperationCancellation() throws { let expectation = XCTestExpectation(description: "blockbatch expectation") - let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co", + let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 300000, diff --git a/ZcashLightClientKitTests/CompactBlockProcessorTests.swift b/ZcashLightClientKitTests/CompactBlockProcessorTests.swift index ec362e04..ab930b60 100644 --- a/ZcashLightClientKitTests/CompactBlockProcessorTests.swift +++ b/ZcashLightClientKitTests/CompactBlockProcessorTests.swift @@ -10,7 +10,7 @@ import XCTest @testable import ZcashLightClientKit class CompactBlockProcessorTests: XCTestCase { - let processorConfig = CompactBlockProcessor.Configuration.standard + let processorConfig = CompactBlockProcessor.Configuration.standard(for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT) var processor: CompactBlockProcessor! var downloadStartedExpect: XCTestExpectation! var updatedNotificationExpectation: XCTestExpectation! @@ -18,7 +18,8 @@ class CompactBlockProcessorTests: XCTestCase { var startedScanningNotificationExpectation: XCTestExpectation! var startedValidatingNotificationExpectation: XCTestExpectation! var idleNotificationExpectation: XCTestExpectation! - let mockLatestHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 2000 + let network = ZcashNetworkBuilder.network(for: .testnet) + let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT + 2000 override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. @@ -109,15 +110,15 @@ class CompactBlockProcessorTests: XCTestCase { // test first range var latestDownloadedHeight = processorConfig.walletBirthday // this can be either this or Wallet Birthday. - var latestBlockchainHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000) + var latestBlockchainHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 1000) var expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight, upper:latestBlockchainHeight)) XCTAssertEqual(expectedBatchRange, CompactBlockProcessor.nextBatchBlockRange(latestHeight: latestBlockchainHeight, latestDownloadedHeight: latestDownloadedHeight, walletBirthday: processorConfig.walletBirthday)) // Test mid-range - latestDownloadedHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + ZcashSDK.DEFAULT_BATCH_SIZE) - latestBlockchainHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000) + latestDownloadedHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + ZcashSDK.DEFAULT_BATCH_SIZE) + latestBlockchainHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 1000) expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight + 1, upper: latestBlockchainHeight)) @@ -125,8 +126,8 @@ class CompactBlockProcessorTests: XCTestCase { // Test last batch range - latestDownloadedHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 950) - latestBlockchainHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000) + latestDownloadedHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 950) + latestBlockchainHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 1000) expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight + 1, upper: latestBlockchainHeight)) diff --git a/ZcashLightClientKitTests/CompactBlockReorgTests.swift b/ZcashLightClientKitTests/CompactBlockReorgTests.swift index 15ccd421..12ab6cb9 100644 --- a/ZcashLightClientKitTests/CompactBlockReorgTests.swift +++ b/ZcashLightClientKitTests/CompactBlockReorgTests.swift @@ -11,7 +11,7 @@ import XCTest @testable import ZcashLightClientKit class CompactBlockReorgTests: XCTestCase { - let processorConfig = CompactBlockProcessor.Configuration.standard + let processorConfig = CompactBlockProcessor.Configuration.standard(for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT) var processor: CompactBlockProcessor! var downloadStartedExpect: XCTestExpectation! var updatedNotificationExpectation: XCTestExpectation! @@ -20,7 +20,8 @@ class CompactBlockReorgTests: XCTestCase { var startedValidatingNotificationExpectation: XCTestExpectation! var idleNotificationExpectation: XCTestExpectation! var reorgNotificationExpectation: XCTestExpectation! - let mockLatestHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 2000 + let network = ZcashNetworkBuilder.network(for: .testnet) + let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT + 2000 override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. @@ -32,7 +33,7 @@ class CompactBlockReorgTests: XCTestCase { let mockBackend = MockRustBackend.self mockBackend.mockValidateCombinedChainFailAfterAttempts = 3 mockBackend.mockValidateCombinedChainKeepFailing = false - mockBackend.mockValidateCombinedChainFailureHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 320 + mockBackend.mockValidateCombinedChainFailureHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 320 processor = CompactBlockProcessor(service: service, storage: storage, @@ -69,8 +70,8 @@ class CompactBlockReorgTests: XCTestCase { XCTAssertNotNil(notification.userInfo) if let reorg = notification.userInfo?[CompactBlockProcessorNotificationKey.reorgHeight] as? BlockHeight, let rewind = notification.userInfo?[CompactBlockProcessorNotificationKey.rewindHeight] as? BlockHeight { - XCTAssertTrue( reorg == 0 || reorg > ZcashSDK.SAPLING_ACTIVATION_HEIGHT) - XCTAssertTrue( rewind == 0 || rewind > ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + XCTAssertTrue( reorg == 0 || reorg > self.network.constants.SAPLING_ACTIVATION_HEIGHT) + XCTAssertTrue( rewind == 0 || rewind > self.network.constants.SAPLING_ACTIVATION_HEIGHT) XCTAssertTrue( rewind <= reorg ) reorgNotificationExpectation.fulfill() } else { diff --git a/ZcashLightClientKitTests/CompactBlockStorageTests.swift b/ZcashLightClientKitTests/CompactBlockStorageTests.swift index 2db6595d..2a7be884 100644 --- a/ZcashLightClientKitTests/CompactBlockStorageTests.swift +++ b/ZcashLightClientKitTests/CompactBlockStorageTests.swift @@ -13,13 +13,14 @@ class CompactBlockStorageTests: XCTestCase { var compactBlockDao: CompactBlockRepository = try! TestDbBuilder.inMemoryCompactBlockStorage() + let network = ZcashNetworkBuilder.network(for: .testnet) func testEmptyStorage() { XCTAssertEqual(try! compactBlockDao.latestHeight(), BlockHeight.empty()) } func testStoreThousandBlocks() { let initialHeight = try! compactBlockDao.latestHeight() - let startHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + let startHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT let blockCount = Int(1_000) let finalHeight = startHeight + blockCount @@ -62,7 +63,7 @@ class CompactBlockStorageTests: XCTestCase { func testRewindTo() { - let startHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + let startHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT let blockCount = Int(1_000) let finalHeight = startHeight + blockCount diff --git a/ZcashLightClientKitTests/DarksideSanityCheckTests.swift b/ZcashLightClientKitTests/DarksideSanityCheckTests.swift index 8ab2b797..eb8eb4e5 100644 --- a/ZcashLightClientKitTests/DarksideSanityCheckTests.swift +++ b/ZcashLightClientKitTests/DarksideSanityCheckTests.swift @@ -22,13 +22,15 @@ class DarksideSanityCheckTests: XCTestCase { var sentTransactionExpectation = XCTestExpectation(description: "sent") var expectedReorgHeight: BlockHeight = 665188 var expectedRewindHeight: BlockHeight = 665188 + var network = DarksideWalletDNetwork() var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") override func setUpWithError() throws { coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main") try coordinator.resetBlocks(dataset: .default) diff --git a/ZcashLightClientKitTests/DownloadOperationTests.swift b/ZcashLightClientKitTests/DownloadOperationTests.swift index efdf9bf9..c618093d 100644 --- a/ZcashLightClientKitTests/DownloadOperationTests.swift +++ b/ZcashLightClientKitTests/DownloadOperationTests.swift @@ -12,7 +12,7 @@ import SQLite class DownloadOperationTests: XCTestCase { var operationQueue = OperationQueue() - + var network = ZcashNetworkBuilder.network(for: .testnet) override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. operationQueue.cancelAllOperations() @@ -25,7 +25,8 @@ class DownloadOperationTests: XCTestCase { let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() let downloader = CompactBlockDownloader(service: service, storage: storage) let blockCount = 100 - let range = ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... ZcashSDK.SAPLING_ACTIVATION_HEIGHT + blockCount + let activationHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + let range = activationHeight ... activationHeight + blockCount let downloadOperation = CompactBlockDownloadOperation(downloader: downloader, range: range) downloadOperation.completionHandler = { (finished, cancelled) in diff --git a/ZcashLightClientKitTests/LightWalletServiceTests.swift b/ZcashLightClientKitTests/LightWalletServiceTests.swift index 970d958a..d88beb2a 100644 --- a/ZcashLightClientKitTests/LightWalletServiceTests.swift +++ b/ZcashLightClientKitTests/LightWalletServiceTests.swift @@ -13,6 +13,7 @@ class LightWalletServiceTests: XCTestCase { var service: LightWalletService! var channel: Channel! + let network: ZcashNetwork = ZcashNetworkBuilder.network(for: .testnet) override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. channel = ChannelProvider().channel() @@ -39,8 +40,8 @@ class LightWalletServiceTests: XCTestCase { func testHundredBlocks() { let expect = XCTestExpectation(description: self.description) let count = 99 - let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT - let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + count + let lowerRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + let upperRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + count let blockRange = lowerRange ... upperRange service.blockRange(blockRange) { (result) in @@ -60,8 +61,8 @@ class LightWalletServiceTests: XCTestCase { } func testSyncBlockRange() { - let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT - let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99 + let lowerRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + let upperRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + 99 let blockRange = lowerRange ... upperRange do { @@ -80,7 +81,7 @@ class LightWalletServiceTests: XCTestCase { case .failure(let e): XCTFail("error: \(e)") case .success(let height): - XCTAssertTrue(height > ZcashSDK.SAPLING_ACTIVATION_HEIGHT) + XCTAssertTrue(height > self.network.constants.SAPLING_ACTIVATION_HEIGHT) } } diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index 3f71f0f5..ba0dfd9d 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -19,7 +19,8 @@ class NetworkUpgradeTests: XCTestCase { let branchID = "2bb40e60" let chainName = "main" var coordinator: TestCoordinator! - + var network = ZcashNetworkBuilder.network(for: .testnet) + override func setUpWithError() throws { // coordinator = try TestCoordinator( @@ -59,7 +60,7 @@ class NetworkUpgradeTests: XCTestCase { wait(for: [firstSyncExpectation], timeout: 120) let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() - guard verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI else { + guard verifiedBalance > network.constants.defaultFee(for: activationHeight) else { XCTFail("not enough balance to continue test") return } @@ -206,7 +207,7 @@ class NetworkUpgradeTests: XCTestCase { wait(for: [firstSyncExpectation], timeout: 120) let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: activationHeight)) @@ -296,7 +297,7 @@ class NetworkUpgradeTests: XCTestCase { wait(for: [firstSyncExpectation], timeout: 120) let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() - guard verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI else { + guard verifiedBalance > network.constants.defaultFee(for: activationHeight) else { XCTFail("balance is not enough to continue with this test") return } @@ -403,7 +404,7 @@ class NetworkUpgradeTests: XCTestCase { var p: PendingTransactionEntity? = nil // spend all the funds - let spendAmount: Int64 = postActivationBalance - Int64(ZcashSDK.MINERS_FEE_ZATOSHI) + let spendAmount: Int64 = postActivationBalance - Int64(network.constants.defaultFee(for: activationHeight)) /* send transaction to recipient address diff --git a/ZcashLightClientKitTests/NullBytesTests.swift b/ZcashLightClientKitTests/NullBytesTests.swift index 3689a1c0..ebc653f5 100644 --- a/ZcashLightClientKitTests/NullBytesTests.swift +++ b/ZcashLightClientKitTests/NullBytesTests.swift @@ -8,18 +8,18 @@ import XCTest @testable import ZcashLightClientKit class NullBytesTests: XCTestCase { - + let networkType = NetworkType.mainnet func testZaddrNullBytes() throws { let validZaddr = "zs1gqtfu59z20s9t20mxlxj86zpw6p69l0ev98uxrmlykf2nchj2dw8ny5e0l22kwmld2afc37gkfp" // this is a valid zAddr. if you send ZEC to it, you will be contributing to Human Rights Foundation. see more ways to help at https://paywithz.cash/ let ZaddrWithNullBytes = "\(validZaddr)\0something else that makes the address invalid" - XCTAssertFalse(try ZcashRustBackend.isValidShieldedAddress(ZaddrWithNullBytes)) + XCTAssertFalse(try ZcashRustBackend.isValidShieldedAddress(ZaddrWithNullBytes, networkType: networkType)) } func testTaddrNullBytes() throws { let validTAddr = "t1J5pTRzJi7j8Xw9VJTrPxPEkaigr69gKVT" // this is a valid tAddr. if you send ZEC to it, you will be contributing to Human Rights Foundation. see more ways to help at https://paywithz.cash/ let TaddrWithNullBytes = "\(validTAddr)\0fasdfasdf" - XCTAssertFalse(try ZcashRustBackend.isValidTransparentAddress(TaddrWithNullBytes)) + XCTAssertFalse(try ZcashRustBackend.isValidTransparentAddress(TaddrWithNullBytes, networkType: networkType)) } func testInitAccountTableNullBytes() throws { @@ -30,7 +30,7 @@ class NullBytesTests: XCTestCase { let wrongTree = "0161f2ff97ff6ac6a90f9bce76c11710460f4944d8695aecc7dc99e34cad0131040011015325b185e23e82562db27817be996ffade9597181244f67efc40561aeb9dde1101daeffadc9e38f755bcb55a847a1278518a0ba4a2ef33b2fe01bbb3eb242ab0070000000000011c51f9077e3f7e28e8e337eaf4bb99b41acbc853a37dcc1e172467a1c919fe4100010bb1f55481b2268ef31997dc0fb6b48a530bc17870220f156d832326c433eb0a010b3768d3bf7868a67823e022f49be67982d0588e7041c498a756024\0750065a4a0001a9e1bf4bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" let goodTree = "0161f2ff97ff6ac6a90f9bce76c11710460f4944d8695aecc7dc99e34cad0131040011015325b185e23e82562db27817be996ffade9597181244f67efc40561aeb9dde1101daeffadc9e38f755bcb55a847a1278518a0ba4a2ef33b2fe01bbb3eb242ab0070000000000011c51f9077e3f7e28e8e337eaf4bb99b41acbc853a37dcc1e172467a1c919fe4100010bb1f55481b2268ef31997dc0fb6b48a530bc17870220f156d832326c433eb0a010b3768d3bf7868a67823e022f49be67982d0588e7041c498a756024750065a4a0001a9e1bf4bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" - XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: wrongHash, time: time, saplingTree: goodTree), "InitBlocksTable with Null bytes on hash string should have failed") { (error) in + XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: wrongHash, time: time, saplingTree: goodTree, networkType: networkType), "InitBlocksTable with Null bytes on hash string should have failed") { (error) in guard let rustError = error as? RustWeldingError else { XCTFail("Expected RustWeldingError") @@ -45,7 +45,7 @@ class NullBytesTests: XCTestCase { } } - XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: goodHash, time: time, saplingTree: wrongTree), "InitBlocksTable with Null bytes on saplingTree string should have failed") { (error) in + XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: goodHash, time: time, saplingTree: wrongTree, networkType: networkType), "InitBlocksTable with Null bytes on saplingTree string should have failed") { (error) in guard let rustError = error as? RustWeldingError else { XCTFail("Expected RustWeldingError") @@ -66,7 +66,7 @@ class NullBytesTests: XCTestCase { let goodSpendingKeys = "secret-extended-key-main1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkyuegyhh5d4rdr8025nl7e0hm8r2txx3fuea5mquy3wnsr9tlajsg4wwvw0xcfk8357k4h850rgj72kt4rx3fjdz99zs9f4neda35cq8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszc7nc9vv" - XCTAssertThrowsError(try ZcashRustBackend.deriveExtendedFullViewingKey(wrongSpendingKeys),"Should have thrown an error but didn't! this is dangerous!") { (error) in + XCTAssertThrowsError(try ZcashRustBackend.deriveExtendedFullViewingKey(wrongSpendingKeys, networkType: networkType),"Should have thrown an error but didn't! this is dangerous!") { (error) in guard let rustError = error as? RustWeldingError else { XCTFail("Expected RustWeldingError") @@ -81,7 +81,7 @@ class NullBytesTests: XCTestCase { } } - XCTAssertNoThrow(try ZcashRustBackend.deriveExtendedFullViewingKey(goodSpendingKeys)) + XCTAssertNoThrow(try ZcashRustBackend.deriveExtendedFullViewingKey(goodSpendingKeys, networkType: networkType)) } diff --git a/ZcashLightClientKitTests/PagedTransactionRepositoryTests.swift b/ZcashLightClientKitTests/PagedTransactionRepositoryTests.swift index 446d965d..194a0cbb 100644 --- a/ZcashLightClientKitTests/PagedTransactionRepositoryTests.swift +++ b/ZcashLightClientKitTests/PagedTransactionRepositoryTests.swift @@ -13,7 +13,7 @@ class PagedTransactionRepositoryTests: XCTestCase { var transactionRepository: TransactionRepository! override func setUp() { - transactionRepository = MockTransactionRepository(unminedCount: 5, receivedCount: 150, sentCount: 100) + transactionRepository = MockTransactionRepository(unminedCount: 5, receivedCount: 150, sentCount: 100, network: ZcashNetworkBuilder.network(for: .testnet)) pagedTransactionRepository = PagedTransactionDAO(repository: transactionRepository) } diff --git a/ZcashLightClientKitTests/PendingTransactionUpdatesTest.swift b/ZcashLightClientKitTests/PendingTransactionUpdatesTest.swift index 7352d43a..30f34d31 100644 --- a/ZcashLightClientKitTests/PendingTransactionUpdatesTest.swift +++ b/ZcashLightClientKitTests/PendingTransactionUpdatesTest.swift @@ -23,12 +23,14 @@ class PendingTransactionUpdatesTest: XCTestCase { var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") let branchID = "2bb40e60" let chainName = "main" + let network = DarksideWalletDNetwork() override func setUpWithError() throws { coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main") } diff --git a/ZcashLightClientKitTests/ReOrgTests.swift b/ZcashLightClientKitTests/ReOrgTests.swift index e8917649..3c6e6215 100644 --- a/ZcashLightClientKitTests/ReOrgTests.swift +++ b/ZcashLightClientKitTests/ReOrgTests.swift @@ -22,23 +22,25 @@ import XCTest class ReOrgTests: XCTestCase { var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment? - let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" //TODO: Parameterize this from environment - - let sendAmount: Int64 = 1000 - var birthday: BlockHeight = 663150 - let defaultLatestHeight: BlockHeight = 663175 - var coordinator: TestCoordinator! - var syncedExpectation = XCTestExpectation(description: "synced") - var sentTransactionExpectation = XCTestExpectation(description: "sent") - var expectedReorgHeight: BlockHeight = 665188 - var expectedRewindHeight: BlockHeight = 665188 - var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") - override func setUpWithError() throws { + let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" //TODO: Parameterize this from environment + + let sendAmount: Int64 = 1000 + var birthday: BlockHeight = 663150 + let defaultLatestHeight: BlockHeight = 663175 + var coordinator: TestCoordinator! + var syncedExpectation = XCTestExpectation(description: "synced") + var sentTransactionExpectation = XCTestExpectation(description: "sent") + var expectedReorgHeight: BlockHeight = 665188 + var expectedRewindHeight: BlockHeight = 665188 + let network = DarksideWalletDNetwork() + var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") + override func setUpWithError() throws { NotificationCenter.default.addObserver(self, selector: #selector(handleReOrgNotification(_:)), name: Notification.Name.blockProcessorHandledReOrg, object: nil) coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main") try coordinator.resetBlocks(dataset: .default) diff --git a/ZcashLightClientKitTests/RewindRescanTests.swift b/ZcashLightClientKitTests/RewindRescanTests.swift index 65925611..1955d41c 100644 --- a/ZcashLightClientKitTests/RewindRescanTests.swift +++ b/ZcashLightClientKitTests/RewindRescanTests.swift @@ -23,12 +23,14 @@ class RewindRescanTests: XCTestCase { var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") let branchID = "2bb40e60" let chainName = "main" + var network = ZcashNetworkBuilder.network(for: .testnet) override func setUpWithError() throws { coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main") } @@ -68,7 +70,7 @@ class RewindRescanTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() // 2 check that there are no unconfirmed funds - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) // rewind to birthday @@ -114,12 +116,12 @@ class RewindRescanTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() // 2 check that there are no unconfirmed funds - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) // rewind to birthday let targetHeight: BlockHeight = newChaintTip - 8000 - let rewindHeight = ZcashRustBackend.getNearestRewindHeight(dbData: coordinator.databases.dataDB, height: Int32(targetHeight)) + let rewindHeight = ZcashRustBackend.getNearestRewindHeight(dbData: coordinator.databases.dataDB, height: Int32(targetHeight), networkType: network.networkType) try coordinator.synchronizer.rewind(.height(blockheight: targetHeight)) @@ -179,7 +181,7 @@ class RewindRescanTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() // 2 check that there are no unconfirmed funds - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) // rewind to transaction @@ -192,7 +194,7 @@ class RewindRescanTests: XCTestCase { // assert that after the new height is - XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),transaction.transactionEntity.anchor) + XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),transaction.transactionEntity.anchor(network: network)) let secondScanExpectation = XCTestExpectation(description: "rescan") @@ -232,10 +234,10 @@ class RewindRescanTests: XCTestCase { let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() let totalBalance = coordinator.synchronizer.initializer.getBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee()) + XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight)) XCTAssertEqual(verifiedBalance, totalBalance) - let maxBalance = verifiedBalance - Int64(ZcashSDK.defaultFee()) + let maxBalance = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight)) // 3 create a transaction for the max amount possible // 4 send the transaction diff --git a/ZcashLightClientKitTests/SychronizerDarksideTests.swift b/ZcashLightClientKitTests/SychronizerDarksideTests.swift index 932aff91..bcd7e5b4 100644 --- a/ZcashLightClientKitTests/SychronizerDarksideTests.swift +++ b/ZcashLightClientKitTests/SychronizerDarksideTests.swift @@ -23,13 +23,15 @@ class SychronizerDarksideTests: XCTestCase { var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") let branchID = "2bb40e60" let chainName = "main" + let network = DarksideWalletDNetwork() var foundTransactions = [ConfirmedTransactionEntity]() override func setUpWithError() throws { coordinator = try TestCoordinator( seed: seedPhrase, walletBirthday: birthday, - channelProvider: ChannelProvider() + channelProvider: ChannelProvider(), + network: network ) try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main") } diff --git a/ZcashLightClientKitTests/TestCoordinator.swift b/ZcashLightClientKitTests/TestCoordinator.swift index 2d3fcfb6..6bcc93f2 100644 --- a/ZcashLightClientKitTests/TestCoordinator.swift +++ b/ZcashLightClientKitTests/TestCoordinator.swift @@ -43,32 +43,36 @@ class TestCoordinator { var service: DarksideWalletService var spendingKeys: [String]? var databases: TemporaryTestDatabases - + let network: ZcashNetwork convenience init(seed: String, walletBirthday: BlockHeight, - channelProvider: ChannelProvider) throws { - guard let spendingKey = try DerivationTool.default.deriveSpendingKeys( + channelProvider: ChannelProvider, + network: ZcashNetwork) throws { + let derivationTool = DerivationTool(networkType: network.networkType) + guard let spendingKey = try derivationTool.deriveSpendingKeys( seed: TestSeed().seed(), numberOfAccounts: 1).first else { throw CoordinatorError.builderError } - guard let uvk = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed(TestSeed().seed(), numberOfAccounts: 1).first else { + guard let uvk = try derivationTool.deriveUnifiedViewingKeysFromSeed(TestSeed().seed(), numberOfAccounts: 1).first else { throw CoordinatorError.builderError } - try self.init(spendingKey: spendingKey, unifiedViewingKey: uvk, walletBirthday: walletBirthday, channelProvider: channelProvider) + try self.init(spendingKey: spendingKey, unifiedViewingKey: uvk, walletBirthday: walletBirthday, channelProvider: channelProvider, network: network) } required init( spendingKey: String, unifiedViewingKey: UnifiedViewingKey, - walletBirthday: BlockHeight, - channelProvider: ChannelProvider) throws { + walletBirthday: BlockHeight, + channelProvider: ChannelProvider, + network: ZcashNetwork) throws { self.spendingKey = spendingKey self.birthday = walletBirthday self.channelProvider = channelProvider self.databases = TemporaryDbBuilder.build() + self.network = network self.service = DarksideWalletService(service: LightWalletGRPCService(host: Constants.address, port: 9067, secure: false, singleCallTimeout: 10000, streamingCallTimeout: 1000000)) let storage = CompactBlockStorage(url: databases.cacheDB, readonly: false) try storage.createTable() @@ -90,6 +94,7 @@ class TestCoordinator { spendingKey: spendingKey, unifiedViewingKey: unifiedViewingKey, walletBirthday: WalletBirthday.birthday(with: birthday), + network: network, loggerProxy: SampleLogger(logLevel: .debug)) self.synchronizer = buildResult.synchronizer @@ -210,7 +215,8 @@ extension TestCoordinator { maxBackoffInterval: config.maxBackoffInterval, rewindDistance: config.rewindDistance, walletBirthday: config.walletBirthday, - saplingActivation: config.saplingActivation) + saplingActivation: config.saplingActivation, + network: config.network) try service.reset(saplingActivation: saplingActivation, branchID: branchID, chainName: chainName) } @@ -254,11 +260,13 @@ class TestSynchronizerBuilder { spendingKey: String, unifiedViewingKey: UnifiedViewingKey, walletBirthday: WalletBirthday, + network: ZcashNetwork, loggerProxy: Logger? = nil ) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) { let initializer = Initializer( rustBackend: rustBackend, lowerBoundHeight: lowerBoundHeight, + network: network, cacheDbURL: cacheDbURL, dataDbURL: dataDbURL, pendingDbURL: pendingDbURL, @@ -281,7 +289,8 @@ class TestSynchronizerBuilder { maxBackoffInterval: ZcashSDK.DEFAULT_MAX_BACKOFF_INTERVAL, rewindDistance: ZcashSDK.DEFAULT_REWIND_DISTANCE, walletBirthday: walletBirthday.height, - saplingActivation: lowerBoundHeight) + saplingActivation: lowerBoundHeight, + network: network) let processor = CompactBlockProcessor(service: service, storage: storage, @@ -318,13 +327,14 @@ class TestSynchronizerBuilder { outputParamsURL: URL, seedBytes: [UInt8], walletBirthday: WalletBirthday, + network: ZcashNetwork, loggerProxy: Logger? = nil ) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) { - guard let spendingKey = try DerivationTool().deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else { + guard let spendingKey = try DerivationTool(networkType: network.networkType).deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else { throw TestCoordinator.CoordinatorError.builderError } - guard let uvk = try DerivationTool().deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: 1).first else { + guard let uvk = try DerivationTool(networkType: network.networkType).deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: 1).first else { throw TestCoordinator.CoordinatorError.builderError } return try build(rustBackend: rustBackend, @@ -341,7 +351,8 @@ class TestSynchronizerBuilder { outputParamsURL: outputParamsURL, spendingKey: spendingKey, unifiedViewingKey: uvk, - walletBirthday: walletBirthday) + walletBirthday: walletBirthday, + network: network) } } diff --git a/ZcashLightClientKitTests/TransactionEnhancementTests.swift b/ZcashLightClientKitTests/TransactionEnhancementTests.swift index cfdad841..d5334e87 100644 --- a/ZcashLightClientKitTests/TransactionEnhancementTests.swift +++ b/ZcashLightClientKitTests/TransactionEnhancementTests.swift @@ -26,34 +26,12 @@ class TransactionEnhancementTests: XCTestCase { let mockLatestHeight = BlockHeight(663250) let targetLatestHeight = BlockHeight(663251) let walletBirthday = BlockHeight(663150) - + let network = DarksideWalletDNetwork() + let branchID = "2bb40e60" + let chainName = "main" override func setUpWithError() throws { logger = SampleLogger(logLevel: .debug) - - var config = CompactBlockProcessor.Configuration.standard - let rustBackend = ZcashRustBackend.self - - - let birthday = WalletBirthday.birthday(with: walletBirthday) - config.walletBirthday = birthday.height - processorConfig = config - - try? FileManager.default.removeItem(at: processorConfig.cacheDb) - try? FileManager.default.removeItem(at: processorConfig.dataDb) - - _ = rustBackend.initAccountsTable(dbData: processorConfig.dataDb, seed: TestSeed().seed(), accounts: 1) - let service = DarksideWalletService() - darksideWalletService = service - let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) - try! storage.createTable() - - downloader = CompactBlockDownloader(service: service, storage: storage) - processor = CompactBlockProcessor(service: service, - storage: storage, - backend: rustBackend, - config: processorConfig) - downloadStartedExpect = XCTestExpectation(description: self.description + " downloadStartedExpect") stopNotificationExpectation = XCTestExpectation(description: self.description + " stopNotificationExpectation") updatedNotificationExpectation = XCTestExpectation(description: self.description + " updatedNotificationExpectation") @@ -66,11 +44,39 @@ class TransactionEnhancementTests: XCTestCase { waitExpectation = XCTestExpectation(description: self.description + "waitExpectation") + let birthday = WalletBirthday.birthday(with: walletBirthday) + + let config = CompactBlockProcessor.Configuration.standard(for: self.network, walletBirthday: birthday.height) + let rustBackend = ZcashRustBackend.self + processorConfig = config + + + + try? FileManager.default.removeItem(at: processorConfig.cacheDb) + try? FileManager.default.removeItem(at: processorConfig.dataDb) + + _ = rustBackend.initAccountsTable(dbData: processorConfig.dataDb, seed: TestSeed().seed(), accounts: 1,networkType: network.networkType) + _ = try rustBackend.initDataDb(dbData: processorConfig.dataDb, networkType: network.networkType) + _ = try rustBackend.initBlocksTable(dbData: processorConfig.dataDb, height: Int32(birthday.height), hash: birthday.hash, time: birthday.time, saplingTree: birthday.tree, networkType: network.networkType) + + let service = DarksideWalletService() + darksideWalletService = service + let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) + try! storage.createTable() + + downloader = CompactBlockDownloader(service: service, storage: storage) + processor = CompactBlockProcessor(service: service, + storage: storage, + backend: rustBackend, + config: processorConfig) + + + NotificationCenter.default.addObserver(self, selector: #selector(processorFailed(_:)), name: Notification.Name.blockProcessorFailed, object: processor) } override func tearDownWithError() throws { - try! FileManager.default.removeItem(at: processorConfig.cacheDb) + try? FileManager.default.removeItem(at: processorConfig.cacheDb) try? FileManager.default.removeItem(at: processorConfig.dataDb) downloadStartedExpect.unsubscribeFromNotifications() stopNotificationExpectation.unsubscribeFromNotifications() @@ -108,28 +114,32 @@ class TransactionEnhancementTests: XCTestCase { func basicEnhancementTest(latestHeight: BlockHeight, walletBirthday: BlockHeight) throws { do { + try darksideWalletService.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName) try darksideWalletService.useDataset(DarksideDataset.beforeReOrg.rawValue) + try darksideWalletService.applyStaged(nextLatestHeight: 663200) } catch { XCTFail("Error: \(error)") return } + sleep(3) /** connect to dLWD request latest height -> receive firstLatestHeight */ - do { - print("first latest height: \(try darksideWalletService.latestBlockHeight())") - } catch { - XCTFail("Error: \(error)") - return - } - +// do { +// print("first latest height: \(try darksideWalletService.latestBlockHeight())") +// } catch { +// XCTFail("Error: \(error)") +// return +// } + /** download and sync blocks from walletBirthday to firstLatestHeight */ do { + try startProcessing() } catch { @@ -155,3 +165,4 @@ class TransactionEnhancementTests: XCTestCase { } } + diff --git a/ZcashLightClientKitTests/WalletTests.swift b/ZcashLightClientKitTests/WalletTests.swift index 14c602e1..29712a59 100644 --- a/ZcashLightClientKitTests/WalletTests.swift +++ b/ZcashLightClientKitTests/WalletTests.swift @@ -15,7 +15,8 @@ class WalletTests: XCTestCase { var dbData: URL! = nil var paramDestination: URL! = nil var cacheData: URL! = nil - + var network = ZcashNetworkBuilder.network(for: .testnet) + var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! override func setUp() { dbData = try! __dataDbURL() @@ -29,23 +30,30 @@ class WalletTests: XCTestCase { } } -// func testWalletInitialization() { -// -// let wallet = Initializer(cacheDbURL: cacheData, -// dataDbURL: dbData, -// pendingDbURL: try! TestDbBuilder.pendingTransactionsDbURL(), -// endpoint: LightWalletEndpointBuilder.default, -// spendParamsURL: try! __spendParamsURL(), -// outputParamsURL: try! __outputParamsURL() -// ) -// -// XCTAssertNoThrow(try wallet.initialize(viewingKeys: ["zxviewtestsapling1qwxyzvdmqqqqpqy3knx32fpja779wzg76kmglgguvr74g773f3aw3gy37rar6y9d37knvskz6thnea55s05cz3a7q38835hq4w58yevn763cn2wf7k2mpj247ynxpt9qm0nn39slkz5dk572hxr43pxqtg5kz3pqcj8z8uhz0l2vx8gxe90uf4pgw7ks23f0hz2hm47k9ym42cmns3tenhxzlyur2nvx68h4fmk9nrs44ymcqz434zsuxpvhklrjzn00gc43fdghn5szc5x2w"], walletBirthday: 663194)) -// -// // fileExists actually sucks, so attempting to delete the file and checking what happens is far better :) -// XCTAssertNoThrow( try FileManager.default.removeItem(at: dbData!) ) -// // TODO: Initialize cacheDB on start, will be done when Synchronizer is ready and integrated -//// XCTAssertNoThrow( try FileManager.default.removeItem(at: cacheData!) ) -// } + func testWalletInitialization() throws { + + let derivationTool = DerivationTool(networkType: network.networkType) + let uvk = try derivationTool.deriveUnifiedViewingKeysFromSeed(seedData.bytes, numberOfAccounts: 1) + let wallet = Initializer(cacheDbURL: try __cacheDbURL(), + dataDbURL: try __dataDbURL(), + pendingDbURL: try TestDbBuilder.pendingTransactionsDbURL(), + endpoint: LightWalletEndpointBuilder.default, + network: network, + spendParamsURL: try __spendParamsURL(), + outputParamsURL: try __outputParamsURL(), + viewingKeys: uvk, + walletBirthday: 663194) + + + + let synchronizer = try SDKSynchronizer(initializer: wallet) + XCTAssertNoThrow(try synchronizer.prepare()) + + // fileExists actually sucks, so attempting to delete the file and checking what happens is far better :) + XCTAssertNoThrow( try FileManager.default.removeItem(at: dbData!) ) + // TODO: Initialize cacheDB on start, will be done when Synchronizer is ready and integrated +// XCTAssertNoThrow( try FileManager.default.removeItem(at: cacheData!) ) + } } struct WalletBirthdayProvider { diff --git a/ZcashLightClientKitTests/ZcashLightClientKitTests.swift b/ZcashLightClientKitTests/ZcashLightClientKitTests.swift index 70c83ac1..f336e310 100644 --- a/ZcashLightClientKitTests/ZcashLightClientKitTests.swift +++ b/ZcashLightClientKitTests/ZcashLightClientKitTests.swift @@ -18,7 +18,7 @@ class ZcashLightClientKitTests: XCTestCase { var service: LightWalletGRPCService! override func setUp() { super.setUp() - service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) + service = LightWalletGRPCService(endpoint: LightWalletEndpoint(address: Constants.address, port: 9067)) latestBlockHeight = try! service.latestBlock().compactBlockHeight()! } diff --git a/ZcashLightClientKitTests/ZcashRustBackendTests.swift b/ZcashLightClientKitTests/ZcashRustBackendTests.swift index 88949347..88e4ef6d 100644 --- a/ZcashLightClientKitTests/ZcashRustBackendTests.swift +++ b/ZcashLightClientKitTests/ZcashRustBackendTests.swift @@ -16,6 +16,9 @@ class ZcashRustBackendTests: XCTestCase { let spendingKey = "secret-extended-key-test1qvpevftsqqqqpqy52ut2vv24a2qh7nsukew7qg9pq6djfwyc3xt5vaxuenshp2hhspp9qmqvdh0gs2ljpwxders5jkwgyhgln0drjqaguaenfhehz4esdl4kwlm5t9q0l6wmzcrvcf5ed6dqzvct3e2ge7f6qdvzhp02m7sp5a0qjssrwpdh7u6tq89hl3wchuq8ljq8r8rwd6xdwh3nry9at80z7amnj3s6ah4jevnvfr08gxpws523z95g6dmn4wm6l3658kd4xcq9rc0qn" let recipientAddress = "ztestsapling1ctuamfer5xjnnrdr3xdazenljx0mu0gutcf9u9e74tr2d3jwjnt0qllzxaplu54hgc2tyjdc2p6" let zpend: Int = 500_000 + + let networkType = NetworkType.testnet + override func setUp() { dbData = try! __dataDbURL() try? dataDbHandle.setUp() @@ -30,9 +33,9 @@ class ZcashRustBackendTests: XCTestCase { func testInitWithShortSeedAndFail() { let seed = "testreferencealice" - XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!)) + XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!, networkType: networkType)) - let _ = ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1) + let _ = ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1, networkType: networkType) XCTAssertNotNil(ZcashRustBackend.getLastError()) } @@ -41,7 +44,7 @@ class ZcashRustBackendTests: XCTestCase { let seed = Array("testreferencealicetestreferencealice".utf8) var spendingKeys: [String]? = nil - XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1) }()) + XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1, networkType: networkType) }()) XCTAssertNotNil(spendingKeys) XCTAssertFalse(spendingKeys?.first?.isEmpty ?? true) @@ -52,7 +55,7 @@ class ZcashRustBackendTests: XCTestCase { let seed = Array("testreferencealicetestreferencealice".utf8) var fullViewingKeys: [String]? = nil - XCTAssertNoThrow(try { fullViewingKeys = try ZcashRustBackend.deriveExtendedFullViewingKeys(seed: seed, accounts: 1) }()) + XCTAssertNoThrow(try { fullViewingKeys = try ZcashRustBackend.deriveExtendedFullViewingKeys(seed: seed, accounts: 1, networkType: networkType) }()) XCTAssertNotNil(fullViewingKeys) XCTAssertFalse(fullViewingKeys?.first?.isEmpty ?? true) @@ -64,7 +67,7 @@ class ZcashRustBackendTests: XCTestCase { var spendingKeys: [String]? = nil - XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1) }()) + XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1, networkType: networkType) }()) XCTAssertNotNil(spendingKeys) XCTAssertFalse(spendingKeys?.first?.isEmpty ?? true) @@ -74,7 +77,7 @@ class ZcashRustBackendTests: XCTestCase { return } - XCTAssertNoThrow(try { fullViewingKey = try ZcashRustBackend.deriveExtendedFullViewingKey(spendingKey) }()) + XCTAssertNoThrow(try { fullViewingKey = try ZcashRustBackend.deriveExtendedFullViewingKey(spendingKey, networkType: networkType) }()) XCTAssertNotNil(fullViewingKey) XCTAssertFalse(fullViewingKey?.isEmpty ?? true) @@ -86,24 +89,24 @@ class ZcashRustBackendTests: XCTestCase { return } let seed = "testreferencealicetestreferencealice" - XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!)) + XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!, networkType: networkType)) XCTAssertEqual(ZcashRustBackend.getLastError(), nil) - XCTAssertNotNil(ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1)) + XCTAssertNotNil(ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1, networkType: networkType)) XCTAssertEqual(ZcashRustBackend.getLastError(), nil) - let addr = ZcashRustBackend.getAddress(dbData: dbData!, account: 0) + let addr = ZcashRustBackend.getAddress(dbData: dbData!, account: 0, networkType: networkType) XCTAssertEqual(ZcashRustBackend.getLastError(), nil) XCTAssertEqual(addr, Optional("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc")) - XCTAssertTrue(ZcashRustBackend.scanBlocks(dbCache: cacheDb, dbData: dbData)) + XCTAssertTrue(ZcashRustBackend.scanBlocks(dbCache: cacheDb, dbData: dbData, networkType: networkType)) } func testIsValidTransparentAddressFalse() { var isValid: Bool? = nil - XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc") }()) + XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc", networkType: networkType) }()) if let valid = isValid { XCTAssertFalse(valid) @@ -117,7 +120,7 @@ class ZcashRustBackendTests: XCTestCase { func testIsValidTransparentAddressTrue() { var isValid: Bool? = nil - XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7") }()) + XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7", networkType: networkType) }()) if let valid = isValid { XCTAssertTrue(valid) @@ -129,7 +132,7 @@ class ZcashRustBackendTests: XCTestCase { func testIsValidShieldedAddressTrue() { var isValid: Bool? = nil - XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc") }()) + XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc", networkType: networkType) }()) if let valid = isValid { XCTAssertTrue(valid) @@ -141,7 +144,7 @@ class ZcashRustBackendTests: XCTestCase { func testIsValidShieldedAddressFalse() { var isValid: Bool? = nil - XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7") }()) + XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7", networkType: networkType) }()) if let valid = isValid { XCTAssertFalse(valid) diff --git a/ZcashLightClientKitTests/utils/DarkSideWalletService.swift b/ZcashLightClientKitTests/utils/DarkSideWalletService.swift index 8cae455c..3e633ffb 100644 --- a/ZcashLightClientKitTests/utils/DarkSideWalletService.swift +++ b/ZcashLightClientKitTests/utils/DarkSideWalletService.swift @@ -199,3 +199,38 @@ class DarksideWalletService: LightWalletService { } } + + +class DarksideWalletDConstants: NetworkConstants { + static var SAPLING_ACTIVATION_HEIGHT: BlockHeight { + 663150 + } + + static var DEFAULT_DATA_DB_NAME: String { + ZcashSDKMainnetConstants.DEFAULT_DATA_DB_NAME + } + + static var DEFAULT_CACHES_DB_NAME: String { + ZcashSDKMainnetConstants.DEFAULT_CACHES_DB_NAME + } + + static var DEFAULT_PENDING_DB_NAME: String { + ZcashSDKMainnetConstants.DEFAULT_PENDING_DB_NAME + } + + static var DEFAULT_DB_NAME_PREFIX: String { + ZcashSDKMainnetConstants.DEFAULT_DB_NAME_PREFIX + } + + static var FEE_CHANGE_HEIGHT: BlockHeight { + ZcashSDKMainnetConstants.FEE_CHANGE_HEIGHT + } + + +} +class DarksideWalletDNetwork: ZcashNetwork { + var constants: NetworkConstants.Type = DarksideWalletDConstants.self + + var networkType = NetworkType.mainnet + +} diff --git a/ZcashLightClientKitTests/utils/MockTransactionRepository.swift b/ZcashLightClientKitTests/utils/MockTransactionRepository.swift index 7f22dc7d..34cf7ce6 100644 --- a/ZcashLightClientKitTests/utils/MockTransactionRepository.swift +++ b/ZcashLightClientKitTests/utils/MockTransactionRepository.swift @@ -44,10 +44,15 @@ class MockTransactionRepository: TransactionRepository { receivedCount + sentCount } - init(unminedCount: Int, receivedCount: Int, sentCount: Int) { + var network: ZcashNetwork + init(unminedCount: Int, + receivedCount: Int, + sentCount: Int, + network: ZcashNetwork) { self.unminedCount = unminedCount self.receivedCount = receivedCount self.sentCount = sentCount + self.network = network } func generate() { @@ -148,7 +153,7 @@ class MockTransactionRepository: TransactionRepository { } func randomBlockHeight() -> BlockHeight { - BlockHeight.random(in: ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... 1_000_000) + BlockHeight.random(in: network.constants.SAPLING_ACTIVATION_HEIGHT ... 1_000_000) } func randomTimeInterval() -> TimeInterval { Double.random(in: Date().timeIntervalSince1970 - 1000000.0 ... Date().timeIntervalSince1970) diff --git a/ZcashLightClientKitTests/utils/Stubs.swift b/ZcashLightClientKitTests/utils/Stubs.swift index ea98abb7..93694102 100644 --- a/ZcashLightClientKitTests/utils/Stubs.swift +++ b/ZcashLightClientKitTests/utils/Stubs.swift @@ -77,104 +77,108 @@ extension LightWalletServiceMockResponse { } class MockRustBackend: ZcashRustBackendWelding { - - static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32 { + static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 { -1 } - static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight) throws -> Int32 { + + static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32 { -1 } - static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool { + static func network(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 { + -1 + } + + static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey], networkType: NetworkType) throws -> Bool { false } - static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 { + static func getVerifiedTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 { -1 } - static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 { + static func getTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 { -1 } - static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool { + static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool { false } - static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance { + static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance { throw RustWeldingError.genericError(message: "unimplemented") } - static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { + static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 { -1 } - static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { + static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 { -1 } - static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? { + static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? { throw KeyDerivationErrors.unableToDerive } - static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? { + static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? { throw KeyDerivationErrors.unableToDerive } - static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? { + static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? { throw KeyDerivationErrors.unableToDerive } - static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String { + static func derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) throws -> String { throw KeyDerivationErrors.unableToDerive } - static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] { + static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedViewingKey] { throw KeyDerivationErrors.unableToDerive } - static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool { + static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool { false } - static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8]) throws -> String? { + static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], networkType: NetworkType) throws -> String? { nil } - static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool { + static func initAccountsTable(dbData: URL, exfvks: [String], networkType: NetworkType) throws -> Bool { false } - static func deriveTransparentAddressFromSeed(seed: [UInt8]) throws -> String? { + static func deriveTransparentAddressFromSeed(seed: [UInt8], networkType: NetworkType) throws -> String? { nil } - static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? { + static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? { nil } - static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? { + static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? { nil } - static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String? { + static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? { nil } - static func deriveShieldedAddressFromViewingKey(_ extfvk: String) throws -> String? { + static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? { nil } - static func consensusBranchIdFor(height: Int32) throws -> Int32 { + static func consensusBranchIdFor(height: Int32, networkType: NetworkType) throws -> Int32 { guard let c = consensusBranchID else { - return try rustBackend.consensusBranchIdFor(height: height) + return try rustBackend.consensusBranchIdFor(height: height, networkType: networkType) } return c } - + static var networkType = NetworkType.testnet static var mockDataDb = false static var mockAcounts = false static var mockError: RustWeldingError? @@ -202,61 +206,61 @@ class MockRustBackend: ZcashRustBackendWelding { mockLastError ?? rustBackend.getLastError() } - static func isValidShieldedAddress(_ address: String) throws -> Bool { + static func isValidShieldedAddress(_ address: String, networkType: NetworkType) throws -> Bool { true } - static func isValidTransparentAddress(_ address: String) throws -> Bool { + static func isValidTransparentAddress(_ address: String, networkType: NetworkType) throws -> Bool { true } - static func initDataDb(dbData: URL) throws { + static func initDataDb(dbData: URL, networkType: NetworkType) throws { if !mockDataDb { - try rustBackend.initDataDb(dbData: dbData) + try rustBackend.initDataDb(dbData: dbData, networkType: networkType) } } - static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? { - mockAccounts ?? rustBackend.initAccountsTable(dbData: dbData, seed: seed, accounts: accounts) + static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? { + mockAccounts ?? rustBackend.initAccountsTable(dbData: dbData, seed: seed, accounts: accounts, networkType: networkType) } - static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) throws { + static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String, networkType: NetworkType) throws { if !mockDataDb { - try rustBackend.initBlocksTable(dbData: dbData, height: height, hash: hash, time: time, saplingTree: saplingTree) + try rustBackend.initBlocksTable(dbData: dbData, height: height, hash: hash, time: time, saplingTree: saplingTree, networkType: networkType) } } - static func getAddress(dbData: URL, account: Int32) -> String? { - mockAddresses?[Int(account)] ?? rustBackend.getAddress(dbData: dbData, account: account) + static func getAddress(dbData: URL, account: Int32, networkType: NetworkType) -> String? { + mockAddresses?[Int(account)] ?? rustBackend.getAddress(dbData: dbData, account: account, networkType: networkType) } - static func getBalance(dbData: URL, account: Int32) -> Int64 { - mockBalance ?? rustBackend.getBalance(dbData: dbData, account: account) + static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 { + mockBalance ?? rustBackend.getBalance(dbData: dbData, account: account, networkType: networkType) } - static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 { - mockVerifiedBalance ?? rustBackend.getVerifiedBalance(dbData: dbData, account: account) + static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 { + mockVerifiedBalance ?? rustBackend.getVerifiedBalance(dbData: dbData, account: account, networkType: networkType) } - static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { - mockMemo ?? rustBackend.getReceivedMemoAsUTF8(dbData: dbData, idNote: idNote) + static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? { + mockMemo ?? rustBackend.getReceivedMemoAsUTF8(dbData: dbData, idNote: idNote, networkType: networkType) } - static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { - mockSentMemo ?? getSentMemoAsUTF8(dbData: dbData, idNote: idNote) + static func getSentMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? { + mockSentMemo ?? getSentMemoAsUTF8(dbData: dbData, idNote: idNote, networkType: networkType) } - static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 { + static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 { if let rate = self.mockValidateCombinedChainSuccessRate { if shouldSucceed(successRate: rate) { - return validationResult(dbCache: dbCache, dbData: dbData) + return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType) } else { return Int32(mockValidateCombinedChainFailureHeight) } } else if let attempts = self.mockValidateCombinedChainFailAfterAttempts { self.mockValidateCombinedChainFailAfterAttempts = attempts - 1 if attempts > 0 { - return validationResult(dbCache: dbCache, dbData: dbData) + return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType) } else { if attempts == 0 { @@ -264,38 +268,38 @@ class MockRustBackend: ZcashRustBackendWelding { } else if attempts < 0 && mockValidateCombinedChainKeepFailing { return Int32(mockValidateCombinedChainFailureHeight) } else { - return validationResult(dbCache: dbCache, dbData: dbData) + return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType) } } } - return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData) + return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData, networkType: networkType) } - private static func validationResult(dbCache: URL, dbData: URL) -> Int32{ + private static func validationResult(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32{ if mockDataDb { return -1 } else { - return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData) + return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData, networkType: networkType) } } - static func rewindToHeight(dbData: URL, height: Int32) -> Bool { - mockDataDb ? true : rustBackend.rewindToHeight(dbData: dbData, height: height) + static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool { + mockDataDb ? true : rustBackend.rewindToHeight(dbData: dbData, height: height, networkType: networkType) } - static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32) -> Bool { + static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool { if let rate = mockScanblocksSuccessRate { if shouldSucceed(successRate: rate) { - return mockDataDb ? true : rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData) + return mockDataDb ? true : rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData, networkType: networkType) } else { return false } } - return rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData) + return rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData, networkType: Self.networkType) } - static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { + static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 { // mockCreateToAddress ?? rustBackend.createToAddress(dbData: dbData, account: account, extsk: extsk, consensusBranchId: consensusBranchId, to: to, value: value, memo: memo, spendParamsPath: spendParamsPath, outputParamsPath: outputParamsPath) -1 } @@ -305,19 +309,19 @@ class MockRustBackend: ZcashRustBackendWelding { return random <= successRate } - static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String? { + static func deriveExtendedFullViewingKey(_ spendingKey: String, networkType: NetworkType) throws -> String? { nil } - static func deriveExtendedFullViewingKeys(seed: String, accounts: Int32) throws -> [String]? { + static func deriveExtendedFullViewingKeys(seed: String, accounts: Int32, networkType: NetworkType) throws -> [String]? { nil } - static func deriveExtendedSpendingKeys(seed: String, accounts: Int32) throws -> [String]? { + static func deriveExtendedSpendingKeys(seed: String, accounts: Int32, networkType: NetworkType) throws -> [String]? { nil } - static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool { + static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8], networkType: NetworkType) -> Bool { false } diff --git a/ZcashLightClientKitTests/utils/Tests+Utils.swift b/ZcashLightClientKitTests/utils/Tests+Utils.swift index 63016291..4e9081bc 100644 --- a/ZcashLightClientKitTests/utils/Tests+Utils.swift +++ b/ZcashLightClientKitTests/utils/Tests+Utils.swift @@ -15,6 +15,10 @@ class LightWalletEndpointBuilder { static var `default`: LightWalletEndpoint { LightWalletEndpoint(address: Constants.address, port: 9067, secure: false) } + + static var publicTestnet: LightWalletEndpoint { + LightWalletEndpoint(address: "testnet.lightwalletd.com", port: 9067, secure: true) + } } class ChannelProvider { From 09ac2c587759cffbfd80d809de4006fdc7a2edf8 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 28 Jul 2021 15:46:45 -0300 Subject: [PATCH 07/17] remove WalletBirthday as generated file and add it as constants in the sdk --- Constants/WalletBirthday+Constants.swift | 19 + Constants/WalletBirthday+mainnet.swift | 463 ++++++++++++++++++ Constants/WalletBirthday+testnet.swift | 166 +++++++ Constants/ZcashSDK.swift | 2 +- .../project.pbxproj | 16 + .../ZcashLightClientSample/AppDelegate.swift | 11 +- .../Constants/Mainnet.swift | 12 + .../Constants/Testnet.swift | 12 + .../DemoAppConfig.swift | 22 +- .../DerivationToolViewController.swift | 10 +- .../GetAddressViewController.swift | 10 +- .../Get UTXOs/GetUTXOsViewController.swift | 9 +- ZcashLightClientKit/Initializer.swift | 2 +- .../BlockScanOperationTests.swift | 2 +- ZcashLightClientKitTests/ReOrgTests.swift | 4 +- .../TestCoordinator.swift | 2 +- .../TransactionEnhancementTests.swift | 4 +- 17 files changed, 730 insertions(+), 36 deletions(-) create mode 100644 Constants/WalletBirthday+Constants.swift create mode 100644 Constants/WalletBirthday+mainnet.swift create mode 100644 Constants/WalletBirthday+testnet.swift create mode 100644 Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Mainnet.swift create mode 100644 Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Testnet.swift diff --git a/Constants/WalletBirthday+Constants.swift b/Constants/WalletBirthday+Constants.swift new file mode 100644 index 00000000..2a56e009 --- /dev/null +++ b/Constants/WalletBirthday+Constants.swift @@ -0,0 +1,19 @@ +// +// WalletBirthday+Constants.swift +// ZcashLightClientKit +// +// Created by Francisco Gindre on 7/28/21. +// + +import Foundation + +public extension WalletBirthday { + static func birthday(with height: BlockHeight, network: ZcashNetwork) -> WalletBirthday { + switch network.networkType { + case .mainnet: + return mainnetBirthday(with: height) + case .testnet: + return testnetBirthday(with: height) + } + } +} diff --git a/Constants/WalletBirthday+mainnet.swift b/Constants/WalletBirthday+mainnet.swift new file mode 100644 index 00000000..2d576e48 --- /dev/null +++ b/Constants/WalletBirthday+mainnet.swift @@ -0,0 +1,463 @@ +// +// WalletBirthday+mainnet.swift +// ZcashLightClientKit +// +// Created by Francisco Gindre on 7/28/21. +// + +import Foundation + +extension WalletBirthday { + static func mainnetBirthday(with height: BlockHeight) -> WalletBirthday { + switch height { + case BlockHeight.min ..< 640_000: + return WalletBirthday( + height: 419_200, + hash: "00000000025a57200d898ac7f21e26bf29028bbe96ec46e05b2c17cc9db9e4f3", + time: 1540779337, + tree: "000000" + ) + case 640_000 ..< 643_500: + return WalletBirthday( + height: 640000, + hash: "00000000016cd930734753f5acce6274b391f14330c793e54e7bd9f942d17114", + time: 1574051743, + tree: "0165aed8451b6a6c0a66294267976be6d171f2acf83c2b5b94d976cb32062cfa6301cd5b1e5ce12e7d82d07c1b83f7746ef2be8d0c56f90f82b71a1e422a1ffb400710000142f5056f23557ba4cbc562067d43fdc07477fa740c6a13a4ed6d0667b7c1b5510000000001ee9dbe0b8d268efe7e8a88ae7b0ac91923bd71ee81bba0e35e3b9504be59aa250001a2178e94504352c0dd7d6f711b814f8a332239f688568f1719808fd1d385831e0001967ca804f328397d98bd5e1f36786a9d44b06192e70a38026909fb4ce251943e000001fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13" + ) + case 643_500 ..< 663000: + return WalletBirthday( + height: 643_500, + hash: "000000000041005fd724ff6e29bd1738bed69a4d9ca028e124029525350bd789", + time: 1574579149, + tree: "01999fc372390699b15f71d41745abe6a2ea0db4ffa8894d3c5fe30b9261a1a43a01585112668685bd6783cb01b72d17dc86c6d740c27cccf66b75e959e4e4f5ea3710019b7f6b4457a97eadbe1a39bfcc6ba0a56d37010d0d799e1e652fc29733103e04016a0b4d2705e1feb2021d80e5785608536dde05aea5ef676a5427244228b19e2d00010973d03ad5f79fcac64ab3ffbdaaac1a24b74a3617770bf960fb004cbd422439000001984bfce9361025cc38574f944a3ed7b074b3bf88cfce6f14c4a9be4d91d6dc730105871ec1e3737a39bceb00b0c2d253ff36f472e92c361e7ef360d49ea8dc4c4200000001c145105e1bf401668a8f23ca70c47ee92d23bd366072020c83d26b855eeafd6d0001fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13" + ) + case 663000 ..< 663150: + return WalletBirthday( + height: 663000, + hash: "0000000000bd422264b700bb33cab167ab42392c89db0e7c8ce30d57f346fe69", + time: 1576810013, + tree: "0102f02a8cd23e35502f8efa55893c7a145168ac3fa00d4bd032b55097bbe0335a01b57c362e3c834f2216c72ae0d8a335fd2397cc80073d0f5b29c419028bc6c94c100000000157bfd70afa37c8bf0c60c9e160d2145bdfbcf07837b0ff90bf8a5108722cc85400000000011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13" + ) + case 663150 ..< 663700: + return WalletBirthday( + height: 663150, + hash: "0000000002fd3be4c24c437bd22620901617125ec2a3a6c902ec9a6c06f734fc", + time: 1576821833, + tree: "01ec6278a1bed9e1b080fd60ef50eb17411645e3746ff129283712bc4757ecc833001001b4e1d4a26ac4a2810b57a14f4ffb69395f55dde5674ecd2462af96f9126e054701a36afb68534f640938bdffd80dfcb3f4d5e232488abbf67d049b33a761e7ed6901a16e35205fb7fe626a9b13fc43e1d2b98a9c241f99f93d5e93a735454073025401f5b9bcbf3d0e3c83f95ee79299e8aeadf30af07717bda15ffb7a3d00243b58570001fa6d4c2390e205f81d86b85ace0b48f3ce0afb78eeef3e14c70bcfd7c5f0191c0000011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13" + ) + case 663700 ..< 670000: + return WalletBirthday( + height: 663700, + hash: "0000000000d387fab4c980e9a5b42ec35a39879706398c78fbce873d61f1b26c", + time: 1576863287, + tree: "014bd3b38c782ea2e66c053afd4c29c84fa27003b71de5f9778a631558ee7a1410001001534a90ede3e8dcb7115c84e86b2d184c0f46d5b21023a7292ecfade5e956e66500000001daeb30618bfdfa00999f2989795562775c3fdf95ce279d106c0e608fedc9ea31000001686ac0ccce56b47cab1dd4fceb48812f72d6ac6fff3a2ae5a9dcf27eda409a0b011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13" + ) + case 670000 ..< 680000: + return WalletBirthday( + height: 670000, + hash: "000000000086313791aca867bf60fc7434fe2b3fc56926ef46223c6b6b05b5fd", + time: 1577338346, + tree: "01e38b18dcf2de5e9ca5c12a1329176b37219546cfabd9333a9536d2d3ef6cba3e01c159856a741f9da500a9c83935ee7323d63f589a117e66874612e70cdf7a9f4b1001db5e89b8cbf677a87375395940f4715de1bb951f05efbbc4fb34bb1990dd80600155dbaaf5b93f338d1c629fe2a77328c7609c59c6a767a6ccfcc14d3c8c7d826100000001d9e9451fe610b3374b30c711f62a29700ecd2b02e096f02085b896d3fdc3886401006895fa87a8083ae5d0d38df876e764486c67a684706f7750ee19c872dc5d2e01f5cc54720296c3379ac6fb0aa3ed6824bcc40894b3f40d9d2e2d1ed3e6080c3501e9fc6273cadcc40df45ee63984330cfe702a1e7b4c324516d1a80ebcacc4d4170125719ebec43e9148ecc5cfdb2359074badb6fc7759817f6afab999570a75a2000171b36f07e48c45e39f1cc02a99023236f1df60ae924b5ef14ddacc7885994e2b0163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13" + ) + case 680000 ..< 690000: + return WalletBirthday( + height: 680000, + hash: "0000000001f2e08db1ea7ce567a5cd745de87c2eafbd769346b8212cc922d517", + time: 1578091375, + tree: "01bc7b45da508ff7e4b3dbc1184a42a646a18ad0c73907d9462199354f3490ec00001101cf1bc2f3ef2e491a4c04cede4efa561dcb4e9c56562adaa79b96ec8e54b43643000001419a6936943299e8d695fb98c78153499682d1c332efa1fbd19ce3c996be713b01e3743cb66129e262add8996fc588df0b1a33366df4e5d618ec14d0bc8129f537000000000141b1ff5b5fdad24aafa550d42cb9f99c85f6175b3d65060079bb9638cacf654e0141754203644e6f3d5faf15f16492efec723da55b2db473b34299c5582e883e46000000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 690000 ..< 692345: + return WalletBirthday( + height: 690000, + hash: "0000000000b1e6422ecd9292951b36ebb94e8926bbd33df8445b574b4be14f79", + time: 1578845180, + tree: "0117ffc074ef0f54651b2bc78d594e5ff786d9828ae78b1db972cd479669e8dd2401cc1b37d13f3b7d1fa2ead08493d275bfca976dd482e8dd879bf62b987652f63811013d84614158c7810753cc663f7a3da757f84f77744a24490eb07ce07af1daa92e0000017472a22c4064648ff260cbec8d85c273c5cd190dab7800f4978d473322dab1200001c7a1fd3786de051015c90f39143f3cfb89f2ea8bb5155520547ecfbefcdc382a0000000001d0c515cd513b49e397bf96d895a941aed4869ff2ff925939a34572c078dc16470121c1efd29f85680334050ee2a7e0d09fde474f90e573d85b7c9d337a5465625a0000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 692345 ..< 693400: + return WalletBirthday( + height: 692345, + hash: "0000000002584662ea3fb1969a65f05cf1e0c82581b885fbd723eed6ba818e99", + time: 1579021581, + tree: "01a30b15d800be77c5c959f57466a2c6dcf3e583010c1308a6956e23ec1b4658180140ead0f57ec26315bc14ac9a03ee843f34d080f41d2a682d824a02d73569446011000001d4d84c0e533c23813285e3849abff78ff36d2fc4b82c35061aed5e20a13c1859000191e51cd5f2f0afa0de7cd18fde39feb724bdc225fc25a9c75acbae1b641a7719016c33f322bc0205623943faa2a270b2925176cfc642da9625bd567e06b13c4d14000193726f6855f49bda4fb05a256bfcb17bf6ebac59b69ef9bfa73d69ac65ab2c2e01875259d77037ad0de128f071d2b85dfefd4d14c29e3fbd573abf843ebe5d830d0001d0c515cd513b49e397bf96d895a941aed4869ff2ff925939a34572c078dc16470121c1efd29f85680334050ee2a7e0d09fde474f90e573d85b7c9d337a5465625a0000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 693400 ..< 700000: + return WalletBirthday( + height: 693400, + hash: "0000000001708386101e361d211b2a14f3571d0b81f5962b452d563444c7f06a", + time: 1579101218, + tree: "0110939e236e3f13fbf9a044dc4e8d0094b777ee950dca49cb0722556b08fbef2f0197c4a6daa51f5c699ba5f0c3e53b657e54e3d728e60edaf76b4e2215d6aa2d661100000001ef66b21ca159b57a3d54147b0011c096d20cb3aa9590becf8f026c9edadba61a01750454b0edee9cc2f1eaf6d34cb8e495679048008d8cf6c1ab4321bddb828a2901f3dab23e140f2c400b4d4b5e6003ba2c7b316721b0d2858c8e0fcd1f5acbfd4b01eb786638efecd4413cfaadc48a0275035b2d484b92e305cb086c581a07390d21000001a4711f58e3fa6f5d38e2f54ab424c3014c119629fab5ee8a4ed2814d7b17036d01d0c515cd513b49e397bf96d895a941aed4869ff2ff925939a34572c078dc16470121c1efd29f85680334050ee2a7e0d09fde474f90e573d85b7c9d337a5465625a0000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 700000 ..< 710000: + return WalletBirthday( + height: 700000, + hash: "0000000000c057d167a20ae61b1f77996bc72631dee6ffb11095f0d312230ddc", + time: 1579598443, + tree: "01c6b273aee226912526622b91e48a0ff5caf71f1f47569aff8a1c145102b02328012758ab750e1cb4f933ebca089d23ead6032151a38266aa020ae84557bb61844811016443e86acd06140aa932467bcc7235704cf95081e2e5faaf031112a9abd5f930016d1847eb52f8218773e3d2dd8eb19950dbe693484098d763010d7c338337cf68018117bb5e4ad68438572aaa55cb7d66b4b86b9d8310fbb4e36db7982dcc28591400012c4e84168b1c9a322f6035ddb5989fea843045d22182ee9ce45a6a8f6831954301abf6a411ff1708af6252bf921625f28931c567d92833d7ed2b2b14efd6b06e5001d1f934bce5476ef5d21b384c7dddfcbd8c1f630435acbf26a094bc46757f5d3501e6a69ddf114c92d39370a24e840c46ed42fc54a63986d3aa916a08c2a922c73b0001a626bb2ed07614f7228f79d5fbccf541699895842341602c639ab7516b1c9a1a0000019be74b905f0e99399af0fda6832324ceeeaf57551b11b42c73bcb7cd215ab91400000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 710000 ..< 720000: + return WalletBirthday( + height: 710000, + hash: "00000000003adcad055353d33a0962103e284bc47577c62580535a1dd6be7cf6", + time: 1580351806, + tree: "01bf61bd9326bba72206cc0ac82791fe316277907ba76773b5ae01ea7df948ae04001101200905d2485346e39f07fd989ba05211195251968d6bcb41b8280bc94733bc5d01e44932d89c5309ac906072235443f573a92dcda2acf608c1851af01dbeab19350000000001a73367559bf511fc5212ab3f0f6754a9b7ca59a3da68588e3763c801c031bd1501eb94b48e208bdbd42bb4815940b2f9f5187cc5e42c196f461f7bc6d020ed670f0001f00ddf03aca4e8c2620ff274939a1f1cd6a4eceb147e8aa6a8ba83717d60182700010576ef08575c3dd49296ba7c2ddd914715c4f9a7316da4ae8f5600dafa1b1c39019be74b905f0e99399af0fda6832324ceeeaf57551b11b42c73bcb7cd215ab91400000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 720000 ..< 730000: + return WalletBirthday( + height: 720000, + hash: "000000000225bab0e1491d6abfa4a41c174bc7d0167411e2cb2ebd960dae5158", + time: 1581104786, + tree: "0147c6af2c835328a4c17eff07f76102dc57716a13ce3d3a4f48367c3f2384fe2901e01e9b45be2ad8bedab63db1963c2b8d85e1ed20b6327cf2c55c211234e8a3351101134f80e61b548e384e87f823187d2734b07c516d48eea33a533c6cf7aa47052200000000000000017ce48111238d9e81b7e4147286578f2d686d71b1ec0cae668f567f3fef65bc0b017895f4c380f5169dcb84c7154fe6fcf72d694d30f0ba2535437b443a2cb5ae18000000013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 730000 ..< 735000: + return WalletBirthday( + height: 730000, + hash: "0000000002293b9e058e17fbc357c9b676d276eba338e033e357034c775ab320", + time: 1581858634, + tree: "019a59eba6efd060a61cde70daa7b34202e5fd55fcbf809eaf0aa3252e45810e48001101e106c6f8a17723af8793c1bd0f0e95dbcf5ef0bd80e20195422d8388db48cf24000001907e2c08367bfb45d196771ad267ec773c80ff4306aa7c4d2415ee22d211e90a00000001d72bda7061e4086bb885d6f26e39aa603a1f6db2e4fc71ae65a571c7a31ade27014df2a298ce5d7f8e88617b66ef7dc1fddd854e8dc623c3dc0faaa0eb93137d45017a48dab02dd9a014df0bd310657c3b8e854e24e1137f2ffcb1db693e38a4416d00011a5c078f7dd38704665b7270ebd90366fdd0edccdf284ca1f03c6d7e0536182800013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 735000 ..< 750000: + return WalletBirthday( + height: 735000, + hash: "00000000015c597fab53f58b9e1ededbe8bd83ca0203788e2039eceeb0d65ca6", + time: 1582235356, + tree: "0161f2ff97ff6ac6a90f9bce76c11710460f4944d8695aecc7dc99e34cad0131040011015325b185e23e82562db27817be996ffade9597181244f67efc40561aeb9dde1101daeffadc9e38f755bcb55a847a1278518a0ba4a2ef33b2fe01bbb3eb242ab0070000000000011c51f9077e3f7e28e8e337eaf4bb99b41acbc853a37dcc1e172467a1c919fe4100010bb1f55481b2268ef31997dc0fb6b48a530bc17870220f156d832326c433eb0a010b3768d3bf7868a67823e022f49be67982d0588e7041c498a756024750065a4a0001a9e1bf4bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 750000 ..< 775000: + return WalletBirthday( + height: 750000, + hash: "00000000028522f87172ecefd79b5f54547c8a756976585f29e4dc182a19c46a", + time: 1583365678, + tree: "01a069618d376feebdbf39030c254a1a3cb46d19369837e44b6ad9afb43763167300110000010c256f47b493d8d94dd5ad09a6829a0a5e346400430b222072583afad8ce847101b261be33d5db156d09fa73031e8f37b4fe4193d21c909e2c8e58d86c7e48690a016b4a7608e90189275f7bb8e70f525c333431ceaa8de9d5b119e66ce2faeb79290000017d730339d1d4bf490eda3c1fca77d7b8a769fff083318ec46a81404fef45f046013ad81619e96171627f27cd6e7755c4d8261dc7017a65753f06c6cf9a29af116201474991dfe7d598257dae28820c6058e389a897e232e737c90a5427e8f24e355e0163734115d47b641de26abf2cad5c4ac1cb438869fc91d50e66444980647aed24000000017d066851cc49b2ea0cf9fb6af00adbb1cc3a0b15cb02d39e0a66f031b2dc1f230001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 775000 ..< 800000: + return WalletBirthday( + height: 775000, + hash: "0000000001325ee365bb14184794c700485f4e40142678bba749a54ccbc91aaf", + time: 1585250621, + tree: "014f09c863f64727b7cada08271c34d1ea0ba728ad53ec979c25bcab5a902afd52001100000001a182b7bb8fd9e872892c872fc813b59bafc3b517e55a714ff7c4ae45870a1a4a00018133f585dd7c438f78ee970e97036a471897cd5cb8df897ca46b7f2ae6567b00019338310381f33bfdcfe40b56ca7aff105872e6284d2953c287891201e75a237201e99c0f7b97c5856efabcd2fb46ab456cf5d811c3c39aabbdbb40daa814bcad6701e97f12a640f75d28510cbb7d4cad99d46903017fa9caab9905c108ed13e3c62e00000001e07372caea187301a24f9dbbe3b6a8981bb4225b7f4b362b01000d4b0a0eb071011545fef7ddad5a52664dff5a73fbbb26c2cdf42aec9292349773079432d5bc46017d066851cc49b2ea0cf9fb6af00adbb1cc3a0b15cb02d39e0a66f031b2dc1f230001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 800000 ..< 820000: + return WalletBirthday( + height: 800000, + hash: "00000000013f1f4e5634e896ebdbe63dec115547c1480de0d83c64426f913c27", + time: 1587134100, + tree: "01a8689663d3c4ff2bb9aaeb7b75e66a7c68705d147bea9fe67cf7f1ffa9a071720011000196bff8c908d7015ad5df6bc5f5268a157da076c5d2ba63d222f0353c8810320100000001b0a0c048035d6f3f229bedadb2fb7688d03bc49062eae092666a8a55883afb0d000000013a365306be60039724201a594b84cb24ae09ea92a3077722da662289471f6658000184abf3f567f42573deb9e2ae56557fb6a763f16f90577ba5511b55c090eb6f2e00014da3714363acb83872f51c87fed3d42a1093420c3cb96b74ad65966ce27e8c4e0001e2bf698f5ac10b44da560d11a5e1d5c191a82a968a2be0a6948aa8748b54516001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 820000 ..< 830000: + return WalletBirthday( + height: 820000, + hash: "00000000001bde1cd7d26b21c7c0a4eccf3c16805c6e68f499398463fa91ed93", + time: 1588640783, + tree: "0127679ec6e5f7205bd7088782922da4afd0606bf5404faf74feeebe5f548d3639018f80d63358b79bdbdd5a19c6fe3c76e8542f6a1a309ed1dedad95fe3ca5016681101f1a4674cf60a7a56e52fde0a308481a4c9b77f059687b965dffcd67be7c4a83101ed990844ef4a7751262755367e6e16d5e351f190fca5f07124a8f71efee2cc1900000001e83b41c625d651681527f2a95ff2925b96f77c1311144e191da1a59303e39a4200000001f33bcadb822e6d55ba2fa044e2c790d957bc8dd7a6ea773d92114517a97ea76501e0b92e780e46114e308d615f417d051613215bc5974946a4b056013d6351f52401ae652143148288b1328e1b511803db03fbdf319ee20da5c7e49374331c525d3a0000011e76743978cad6dd5263d5a654db307368cb997b0c984ad51018d007c955972101e2bf698f5ac10b44da560d11a5e1d5c191a82a968a2be0a6948aa8748b54516001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 830000 ..< 840000: + return WalletBirthday( + height: 830000, + hash: "00000000013284f6e727ed7cb6365726a044e050d0009ca4bcfbc7bdcd80f319", + time: 1589394076, + tree: "01a6bcb9b2f15aaa3e69ca0c0688c18b8859d54c9d6388f4d5fce8f72a2bfd990d0011019bcf88f0f1cf6d4cee6b74231c9466cd13b5e5390d4e05fdb1e4f4143cdf7a4f000000000145e054aa42c1c6f9a70581e04b05a565c9e6e2faf8885e9b76afcd841228715d01a20db43a61e0bc593598bc42c7b10c31194385c8fb00543cab4d4756b3eaf9030000014bb574ca908dc46d48278d9f5039b7d93217ea00eb63f682321503fe5b42b03f0001d6bdb5e3f2e34961d6f337c416704b74d0df45349b7b50e30cfaebea4934db1b0001e3586da44e3b0d6a0776f967e86c9bb7542b070ce52a7baac5a8e2a564780743011e76743978cad6dd5263d5a654db307368cb997b0c984ad51018d007c955972101e2bf698f5ac10b44da560d11a5e1d5c191a82a968a2be0a6948aa8748b54516001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260" + ) + case 840000 ..< 850000: + return WalletBirthday( + height: 840000, + hash: "00000000000a0b9a8753dfd46e1205590d35f4d365437a0d20d29317b33743c0", + time: 1590149064, + tree: "01101f7b8112735869abc0e74dac1f272935d09725ff03cd8cb63d472e112fa82a01d635e219273ade2859554e5191898ce9a79cb80f62c272dede1c2a71e183e21e120000000000000000000000000000000000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 850000 ..< 861500: + return WalletBirthday( + height: 850000, + hash: "00000000007b5c713129e71fc1496bcc321cd6cd3efec262c9fd73eb90695faa", + time: 1590901979, + tree: "015063008b28e034d7515616a1d975646927df30ac4f13d96ecf3f7ec1ddd49b26001201ff3ab46b9dedd6374a80ddcc746a63b05f9dacd6dbd21f7e0df00ec6df0156520157bfc70827a774ac00c13012ac96a984d75c54a15605d741f647923d531021420000014d624d2cd2908d1a438f4a70ac392ba151c7167095553556f23ca5612475224001b97205b2715b57b9f04451df4474c73586e8fc438f989b057cb83c24e7c80d5d0001d0ce3df812f137bfb07e56795014bfc66297491dde457df799406286d7287e1c0001a8e22e1a09d435fcf20b2599688e7094ca46d2c273ffcdfee0ee80eb3e1e4d2901e469171a108b4c837f17a8f67f4d02ff9688acc825d2e1ce1ad3f8b24ff1346c0001a8ee7010fb0075cf00f14f7541c57cd0e18167ac8b98c1b20454d3618715811a00000000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 861500 ..< 875000: + return WalletBirthday( + height: 861500, + hash: "0000000000f1525a1691846ed82b5bde1d68f5472a88cdb46e2614a0471c2bb1", + time: 1591768624, + tree: "014c3e4b358ad1a1095473984cb037f6b3a326e7c4d6243371b96d774be49d3b6c012f872ee6f08d4348ac8784a055ceca2003b5652956970110ab8ac34662056a6812000184579254ecf2242817a5372a6c93e695d520ba6994a1549722ef6a1e06c4c241018cbbc978565f1f0505facf3761bd072a9bcf0734c49dff1f0f8a40ac0b02ae0301cdac68e2a12c011704388b381617237292c4a219b56b358999f3cf2196fff53d00000001c2fd85c8cb0e8ff63eaa7722a58aa6fbc6298afaca10e3bd3131e6cdf4f3fd1101931ad087d1cd97f85debd36de84dd1f8b3147d82e7c21bf8f68d9b444fe2c86d0001e99fdf5156ce831cafc19295c3239f54727ee3c8e6a9383da5e99f0d37384c690125cc58b7c9dcf14d773e7291fd53fb94371be34ada296701fcda2d1fa903da1f000129505087ffb37278c6371e20c51c2c5dfecc8317f6b0a676137f84467c4ba621000000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 875000 ..< 900000: + return WalletBirthday( + height: 875000, + hash: "000000000001f4b0caae8da2eed537aedd4a76d8671fa668bad870995861296a", + time: 1592786164, + tree: "019e1115ee6526f412ae2f8185b6f1e41e1288daf1c6e4629c32a12e1880211f64001201fd273a938cd5f5fcf70a758fab2d852efd000db4b6b7a8da860e8e48a5fe7614000000000001ff7f557fdde5c41e043e2fa0160e3b8a7fc0331462d1cec6fff3db133e3dc64c01a71c9ce180b19137b80b28137bb5a393bbc26b4b807faf4d57984d1f98b7fa45017d8e8e44760406694aab9880152fcf2d71a0d3967fbf001b77cd9751d61e1924019cc66c08d0b19b5fd3d69f32be1e76096ceeb1b830532eea9ec8aeea5d91076b0001c93ef42efb351f52c49ee3280457d8de5a657015eb9e5a28c6b63c020c18de13000001166bb2e71749ab956e549119ce9099df3dbb053409ff89d0d86a17d5b02d015d0000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 900000 ..< 930000: + return WalletBirthday( + height: 900000, + hash: "0000000000d99076161c66dd3e86db9f9390921cc8b0ad7d6eface3a5d8ecb1c", + time: 1594669980, + tree: "0162267b975eb64d5e602e9bfa63c56b1326e8eab6fa971847f2d4f8f27d26f90101cc33a70cde4e4e5f5347034f44b503e8660c7380e596961ccab15d7a64044371120140d08a6c2958e7283c3e95053eeb3e5cf502d5857a961e107c8b37ae00dcb30700019f7e8cf60fb1b31d852d6786fe74078ff1cae30fd982ed2ee11176f96103622301d3f9f17d782359f08d500309ded4ddc1488c86906f3bd742aa95b8de0f189524000001b64361426e35478691ef23c34cf977afab4962c0d7d1998b08ccac635149524201a73426649efdd3a6bda5f8a253a4823f8558dc16d8042ba071f13c0575a3955d0181e81df06e97ade7989e0ce8790f75f1d34e6cfeb4347205c4aaa7adf90a180e0001ecd87912a28cfbe4f34bf57bad9827e4013d8d4c8e85c48bfdd06c35eade9920010d393867f4f2bebf9f603bf827dd015aaf3a46dfa8b68d86cdce07aa4fbb97240001d3ddf137881180d7c5fd73d188c4346291168bde688643855eb3cd5f680f9c0001166bb2e71749ab956e549119ce9099df3dbb053409ff89d0d86a17d5b02d015d0000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 930000 ..< 940000: + return WalletBirthday( + height: 930000, + hash: "0000000000a5b606b5e99c3f155158993395d4b624e0ead68bdb3130fea8c720", + time: 1596931609, + tree: "012ee9cbe55d438e5fdf9fa2df34a989514d038fc50d5913303221392dc3b33257014c2cabd5f58b23406cbcde4034d5b62c3023f30ea9a0ea5ffafb66fb7e4f000e120116683075450cb081d897a78d86224019865ce7e3ead189e74286be307f43ac5c00000001b9da9a7344e04ad7be9cfbc57c89e840703264f5692060a5ea4f7c2e201f5e42000001a3db46e41c1c7e1026ee8b49b9a148f53b00a9c728f72b996c2dc8fafbe4cb2c0001bc597d37e5f726d22ddbe544885571ac89f5fc1746c3e7e198d0bbe85b77196a011439e56aa582ec419f2a0004222be95ea1762876ea33912c5830ab4e8bdc02660163a8ebc9ee4b289becb230ef62829a8c8b4820fcd11409f0b4c849190155a65f00000001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 940000 ..< 950000: + return WalletBirthday( + height: 940000, + hash: "00000000004f3d5203454e18248bc021a2afa1a30b6517f34cd9187f2b8e2489", + time: 1597685856, + tree: "01dd59466cdc00ee8ceb305d15c25ef32aa2d96b7e4536e071c1d14e67aee9ee0b001200000001defc97883745ef01fbca65d4e5c0f8e22b7714b704a1c36fe8a851fdbfe3a1160178cf44f19dda025a44490dd37b96b83758d04cfa3b26476e129173e7c70cb103000167b3485f4aefed9426fc301de1138fedf6949fc806c54acc2b86d897cb6a2041000000000103e2fcbb87cd5fb954d55d094943fbac487ecda1384a8fa7dbf61097a9755e54014104c9c36ff1a2e7eda524840463de4e2c02f10412a33dd754564d76f458c525000001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 940000 ..< 950000: + return WalletBirthday( + height: 950000, + hash: "00000000016bed6cb8b8c2c09791cee821093484fd9ba0f3faad1e78e0d21c17", + time: 1598439138, + tree: "018b0ff026a6c3d70e5592d7b42fa829ec41c5a86faa2d12cbbcdf81e039cbee5301f4decddef8e3183dac4de8d1b9aa3918d7df9293aae3c1931f99a253149fb65312019066138ebf0e6cfefbe9cd7876aada7d3f27834d604f827b56b7a56e1a7b551d0000018d080dcdf356c41f5a86d2062ca9e617965faae9b9a7ea678d3799f526a353130001a5ba52f3a03ce38d7d48afc3d2c9e6d65e90dba09b53ad3d3a5921267375de5d016b84dd3e9242073d7069f797bc81a4ccbe0d3847a3b3b4d1376d9e6d61446605015d52a3c83f77ec5c8e823143e74569c0040e1cb58d2a170ce907ae010ba29c670001be5b81f3b1b8a035bd0894392b0b78bdae4c57f206d3875b933de545f65bd93b000000018e1d474609c9c09894638a0ab3e656aadccaf7ddf12bcc6b6ece44a4cc79e1140001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 951700 ..< 960000: + return WalletBirthday( + height: 951700, + hash: "0000000000e304a23ddbddd62d5fcd7e6b236afe22e529f1ba88f4dfffce432f", + time: 1598567019, + tree: "0154365cc76299ab7ddc51a9fe6fd63babdcbcafbe6d7b293c43493e4ee4dcaa2501fcbde4337c2a268da9e63035ea372706af6c3be6a7dca7ddb39e9f2293835f381201e7134cc658434206a1fc059bec482c4ea3abdb49f51f367dcfc6c854deb573410001e6dfa615206e90b438eedc5cb42ab5b8a1444ed442581f45813fd1a810cf246e000001f8a3271cd56cf8cb3b01b446cfd1e7afeab070a1d7a356da16858ff2d1636b4d01de38353596f623ce0028520063828e4720bfb4ecfcc3fc103d78fc0cbe7af64200000001064fdef5644d3f4f27cd28df0d3b8103c4822871e2883bc09dcf419f1444c85a0000018e1d474609c9c09894638a0ab3e656aadccaf7ddf12bcc6b6ece44a4cc79e1140001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 960000 ..< 970000: + return WalletBirthday( + height: 960000, + hash: "0000000000b5b5e0ba1c01f76b8105878ea3c2f11da53cb0ec684f5d94365421", + time: 1599193083, + tree: "014695c74583a750216dbc0aec38282d86fc17b595bb45a74bbee8fdbf46b5313e01c2253474715b00c618e635815bd16fb8e6368fdaa9bf8f4a1aca34ead6a7eb1c12000000010cf46f452fc9101af9ca34ae364a1c2e20bc05d454068cf1407a2ee3e0c9ca6700000001091c0b4153defbfad723bf14e1ccd07c0258ea1fcd6e9e8cf759834112ec3036000001c2c980c0777874ce748ca549838324eb775cb2ac7a8d42793edbb05ac15c5b4201162d1417d8b9659ec93ac26ba1a888719a43ab1fe0b46a33c05c2aa55fecb41b00018e1d474609c9c09894638a0ab3e656aadccaf7ddf12bcc6b6ece44a4cc79e1140001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 970000 ..< 980000: + return WalletBirthday( + height: 970000, + hash: "0000000001dca1d101526285476ddf0eef6d238d5b01b7fae8062edfc09812c3", + time: 1599946198, + tree: "01d9e6147caab719ae68cb20d976c78437634e2c999ef3a09c6ba35086d443703d00120001019d135be7b1db088c68bd76703ec2b45066bb1761619745362e61dcf55f644601d0c8f296479a73722c2e2a260ab7017b9a9e6d084b651289cfe6d3c7a00ff54e01f853ab39dbfc81e2aabefd231d3374ff794028168c725ad465e61205692fef4b014f13b6e4475cbd004b4d95aa8205ed7338224e13627ecbb19afd1937dcbc0818000185b4f1ddee3199cd1f7913b223c01c4623cd9d0e1b47df4e36aaca7717b6331f011d6c8ec914cc312ef0962d52240308b22a647f4cbd2d7c2fd420ad5fbcae5619011e43cbb05b8efc885531367e5f611fe7ce7514131be892cce3adad02e151f72b01f0d7e0d589c7e5f8fff0bdd5037aeb5d5d818d413262758c9915ded705e40f70000101d26ff60e77e23fb86a52da565c22d76f81df7f25d543ec0e58a0d692d4be2700000110b2bfd32a99e0b982a41a6dbaebf783bdb9d6af795f5f20056ce7317d15ce1101f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 980000 ..< 998500: + return WalletBirthday( + height: 980000, + hash: "00000000005de60d31b653cdf1637f1bad62af844c6c51f38557a4e8bb74e2d7", + time: 1600700163, + tree: "0184330bda72e9596256847a9597d7d9476aa3d69d9dad2149314751e708da206601cd8a1a61df1e80514cd2c0a7faac8b8d7ce27d6d96bb63cb7c61c1f33e7c654312014098788b75f26108d93f0429202ffffb6cf9ffffd7278383e4d8ad2af642264600011c035ed934a11c1b48e24b6be9b2d483e7747dd082f06abf75f9a092b34cd33c01be00394a99bd33304fc4343cd928857ae7c09c176452f40d9815f9ff3ba3865d013bd7218072e1588aea0568198d37e0d83ba75f155c863355974c4eb864de0103019ed27335bc5452e320ec22a30cfe61508929016157ff2a555181a9a0623e725801328208bea2c5c83487effab780cdb36b4b82e6e7290b06d98817a160f3d79d2800019ed6779a1724a107807baf4dda9481fb940f50d85db701dda43a0989c2d62535000001d1e806194dbe171d4ad1ef8c73c1a469130caced0e24b04b8acef91c42be7a56000107771e04f7d6371bfda40ef9e04419a25c6563dcd359c85bd501de28c3c7f3250110b2bfd32a99e0b982a41a6dbaebf783bdb9d6af795f5f20056ce7317d15ce1101f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 998500 ..< 1000000: + return WalletBirthday( + height: 998500, + hash: "00000000014cf0915c4f105140e846c62ca6f2e321f4f717cf6762a35c6e8eb4", + time: 1602093677, + tree: "01b86ad8964b68a9a316a3038af14ac9e557a6eed614ee5d337c9fdb8887e9dc6001b71fbc815cc014a7f68648fcad5b9b72920b3d21cce406b5f593a0eab6d91f1212000001aede58c0641825b7531a8b296b9fdc7393090b87588893e8dd5160bd59b2e16300000000014fa30e43b641cf67c84cef81083b81bec3bd677f55def5c7bd948298e64690560134ac55ded091faef2ae8a1043704dfec41b1a95c4cedf1818574752bc40f2033000103ee02ae59c6688dcaadf1c4ff95e7b1a902837e4989a4c4994dce7dac6ecb20014ff8c0fe6bce02ac4ad684996bfa931d61c724015d797642819361d611ebd61201c7ae83949d9502b0eff10618124d335f046e4aae52c19ccad5567feceb342a5200000001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1000000 ..< 1010000: + return WalletBirthday( + height: 1000000, + hash: "000000000062eff9ae053020017bfef24e521a2704c5ec9ead2a4608ac70fc7a", + time: 1602206541, + tree: "01a4d1f92e2c051e039ca80b14a86d35c755d88ff9856a3c562da4ed14f77f5d0e0012000001f1ff712c8269b7eb11df56b23f8263d59bc4bb2bbc449973e1c85f399c433a0401e0e8b56e5d56de16c173d83c2d96d4e2f94ce0cbd323a53434c647deff020c08000129acf59ead19b76e487e47cf1d100e953acedc62afa6b384f91a620321b1585300018179961f79f609e6759032f3466067548244c3fe0bf31d275d1b6595bb2d486401b622d3f80d8231c44483faa2a27e96e06a2e08d099b26d15828e8f0bde0bd42001a8d1f585aeceb5c3f22ffb43014fe89db9f7efc080361d4fa4e8d596ab1224400103ee02ae59c6688dcaadf1c4ff95e7b1a902837e4989a4c4994dce7dac6ecb20014ff8c0fe6bce02ac4ad684996bfa931d61c724015d797642819361d611ebd61201c7ae83949d9502b0eff10618124d335f046e4aae52c19ccad5567feceb342a5200000001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1010000 ..< 1020000: + return WalletBirthday( + height: 1010000, + hash: "0000000000faa7ec382bf9c0c1abae839f663834f8f307a2141b1403bc85fcbb", + time: 1602960322, + tree: "01f89aad9f6ed7532fc8866580ad425ba2a63ade58b064be8448804ccf9a60fd68001201dd7166b177a37db095801301de34572e69cf151db80201ee08d677c8a1a7986f000001d30d2ef05fd6f29519da13f09623f440c0f8dcc8154c56dc7f881c77c3504f2201b3ae640c5770b95f68aa24c57c32c01713e450c63b1bc5535ebc81ef2a26b519018611a216a563b1cf44cb1b27821c076869676b7b341a5b4f2cef10e8896a364101091d319cbcb2ed9b4caef347a32268ca70012899b85cf438ecf4bd6d6700c04e01337e6de0bdb259c3bd864fec2617a2cd9e127a7e6ba4212a1a7b9ae8c65e2d1c01121f952ffbab89fac050c927d06f855f8baa39ceb1584a5144c32b45d6bbe35a0110188995758e67a4c8a9e71aaecc9a7bc94e085d189252b385eab74587424e5c0000011ed4073019f93951e17d7e19f48d922bb6f3a9aa1a4827e619e0ae791c9539240128e88325aeb1eaae03e9085f4128fb62f367aaf4a6340dadffe427c1d66aa445000001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1020000 ..< 1030000: + return WalletBirthday( + height: 1020000, + hash: "0000000000c3c4887bd6f5d3cbf9030914e6d1bdd51370ade6657e831d9e3377", + time: 1603714448, + tree: "014f6722b03c84e99cb0f198c604fec8c1c395fa726f403e239a66b124d4ee2f7200120001d6920ed4fa9340ece9cc4918f8b5aba3b0ebc5be16831e7d56e6acc93a7e73110001c6cc38510b51ef7ef6dfd1d48df4ef97de8a52f19a9964ecb53301de1057760d018c66fe955d1c4a7dbeae31896dda4cc0bc7824abdea432101fed279a628f5a4f000001935ddd089f29e35bd356a176191995f91239127eb93bff018a3447f80615a05100000182e624e6852072075532264ac2cc76bcc92327ce55e1dd464817d4c6b9637a6e018d5dcc90c3e7134891d77aee71063b8d542b337e4d43f55f0db9cef746f5a732000001bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1030000 ..< 1040000: + return WalletBirthday( + height: 1030000, + hash: "000000000216b8552281f6b73332ec873e0eb062f9b83ede4f3102af78446b7c", + time: 1604467637, + tree: "016f037481382b438c1a41d74153ee8a6131db5a9fcfa2526718e7b4fa1577e658001201622ea365daf3d6cbd5b712bb33b77764708d69f852b903f053c47569cabd930a0001e2175829e38f95f1b3415bdaa796a732d83da1b137e1b0aecfa9802b8c8e9a540001c783c98897bc46693d1d2d2891489663f0d9ff12b34f28b3db5a841236d9d76501d671aaba2921e416e7b7b81a89cb8e524cb6c49d89c575e04e0da0461799216f0001ba538b78350bfeae6538bfac75fe8709eb59bb72f6d74d64c92df41ac1e464560001ef2204037f952a1365afd291acf2361dcebda719b5e659de073ebe2f7f3eae1a01264c173c66e9b7c36ac9f7a6c928600107fa40f11b8d81862464f849885c50620189c3e3ed72b0d445f043e2d2d5ec23c693ef67b9a15488911ad35480a6041c6301f7f497a2f9ded8bb6d14d9f1bb83f43396270e1fc7e86c2c789d9b74b9d2d3070001bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1040000 ..< 1050000: + return WalletBirthday( + height: 1040000, + hash: "0000000000852680280d876e4870ca18242527eb247994047dfd4b2601fb1fd1", + time: 1605220381, + tree: "01d4ad84ae2c7072a2632e767ef7d38d6adb125d76b2780d0dc32eb607bf839b3a0012000001677d02da42c17e72416ef72a07d165a142d3ab2d1363b07219c44b220bc58843000001035218b5415347549dd0315585ee95b8b1f811d81aca93a551478e3b04d0a527015df8455e3415c857ca94d357d48e093391715644afcfec96656b0b33bbc8592e0001d722471e81e674f55400ad26e5730a88e4a63138cc741c0aa40961ec9ce8076e000001c4d6088cf30ed54a892b82679f9531247c8dcefd1501d47f45bc35095af2e7070001347a0b5c418e301923ccc684d984b80b8ac1f52888b6d6021f7fe3676eafda1201bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1050000 ..< 1060000: + return WalletBirthday( + height: 1050000, + hash: "000000000174c1aa6e70950d51e574311da9fe75b0ba66c38785c8934a00ad3d", + time: 1605974807, + tree: "019c0533c31d2d90c2ac6d8c9193bc9d57cb77ac24993a93202dd97ee8586dac72017ba6e3eae1efa5fec05a764fac9bd552caeba096e73840c4d6d71a46f3ca0f6b12016388275ca6bed5564c68f57c17aaa50e209a900b8f257b60c7e548d39946dc160000014d6580e971d6502e2ef9278cd5527f07c96ce26548d8e13e290708e517e6a40c0000000150d24a2ea34b9eeac3f79051e6ee9dbb8c482083a57ef1b1ccf5a1f164a00547000191cbb6ea3483a6a60f6598710cb210392b7469be8f650c7ea4491965e51fa51b01f0aa6de369775a9747bf7d5f034ee6a7604437f497ca45df942a45c53a99e93e0001e2aeb2d8da652922c8714924c41335140a40bd1c966dc611a9d88058839a881901347a0b5c418e301923ccc684d984b80b8ac1f52888b6d6021f7fe3676eafda1201bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1060000 ..< 1070000: + return WalletBirthday( + height: 1060000, + hash: "0000000002a74e26908b2caab798d341430d83a012aefb113d9707acd6eb5162", + time: 1606729750, + tree: "014dccd8971611a03b3698c14e48f76d2526109374c0336a4aa0c0559567fafe0a01f0875252b1ec66c1835e362c19ec570b02b47c5a284477adc599f4868535370812018c94b59acb73c782a3b3b2d9c46babb6f6ef03e413b5816794518b839bb8d360011061c3e44c652e1ba70b85886fada65fc781b202335715489e21ebd64de8d92e01af2d971d01ebf43d4f1b99f500fe0a97e2068bf1ee03ac6e309316e7be88f221000143b8807fdc7a87ce8623370eeef95140aaf315c9e9df7bbf64a4faf34f4ba213000000011fe71b62cc883a426b1b623e3df4c91cae8de566fdc9a746253d6350bc48451c0001e15174bb37ccc2ad5cba5f9f879d459bec83e975afe6304d23980c0ab87fa34a0000000001891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1070000 ..< 1080000: + return WalletBirthday( + height: 1080000, + hash: "0000000001a6faf5681b8565d50145fd84547b534c5f869e77cb802518d14341", + time: 1608237278, + tree: "01f3955ce270f5718bf68883ed37b3b9d2de8fd77be7bd95334fbedc6083f16026001200000001bd5dd7584bc157cebc9d63c7ee761ab453892482246aae3ef9db17de80b84a4b000195fa995a764f9afbd6c14984dbc72175f49f2259bcf0abc4a82ac92446532c44000168fb4180546c77370ff4175d40a29c357e5787f820e383028243ba623fce4e61017cd28108a3c64a8923444af9b7409eb5dda47d8536cf5aafc80abf62e9551b3501fc0832fb90a473de0da1ae7f62b03d547655aa82d1f279c5ab5a997d6472085901647f2444d093ad8668eac738fe0ff6b59b8191bcbc13dc53f581e64de755122a000101e8d7f1b32b8bc1ec539b93f6c2912c839a55c36c509711340a5cf6d1803a360103bcde16c3ed62026afcdeb7c33c7aae0bbaaa357e8d67a10457244bdacabf4f0001891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1080000 ..< 1090000: + return WalletBirthday( + height: 1070000, + hash: "0000000000e69217b151ca8349e3c9f0c5406877554924d7a4f90fb6434bed9d", + time: 1607482606, + tree: "01ea25320fb5dffce1469a9018d2dbcd02bc16350761c1b24ef1f7c282ff3e70070179ccaff1ff2218010dfdb5e7cd8ab67c27c0f578fc94133fa2db58cba2a1b83112013d996c5be4fa4e5d75fb2f782f02dbaec8582a86a4a404397c2ed5bbb75b1660000153c736227e8f11677599ac536a2d19a2000035609833788b19062cbe075ea20200011a38e1599c81fa7039f159cee2ef7144f23c729ac1d235d1d81ea111ba1c8e520000000001aeda840e11db19f50b7b64c54de8a389e84a5e64e8c3ea8f4861503f587d9b2301802a64566b4a1fa471e350bd86ef0409f6b4712a8fdede1c537347f41506884100000103bcde16c3ed62026afcdeb7c33c7aae0bbaaa357e8d67a10457244bdacabf4f0001891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1090000 ..< 1100000: + return WalletBirthday( + height: 1090000, + hash: "0000000000a48d9a9ec16a0ee42afba830507824086335e81290a55dfbbe0a0b", + time: 1608990684, + tree: "01bba893b54492e05be51cc957d99591f60e3c30b7bbc134f4a79e1219721d023901ed7c0412fd24ccb7919323fbfe9af815adcc0c4e29e581d5e10cf06ebc5af823120001f98603677f74513affc6586569aa76c60766b4249a25118ddcefef18698a2c6300000001dd255f2e4e75b7eef0d5b4c077025792a979fbe44e4b7fde9a1273a3c4d6450401aaf59d640c3cd74fd1cb67396250e4b536de1d300a3c17783ecfcb5ddeec9d3a0001d94a0cf0b8ea2f688b1e107cf6a013747f5f0af6543552291adda1c28668da6b0001ab131afe01856dc81300246b7df2fdc556fcf764cb3bdeea33e83507b706a0420000000185555efbf4f751c9c4a7068f9c1c3303bc33bc8bbd3847a6fa5b6d5b3d547f6101891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1100000 ..< 1110000: + return WalletBirthday( + height: 1100000, + hash: "00000000022262ee215e5b6269cf159b4c9fb89b8a38f70873dde8dbc4c64669", + time: 1609745782, + tree: "012f5514d9c08767fcc3c8c2cb6d7e00cb68ff2eb69ccc869821f3c901a495fb5c0121aab76f6b245f76d9a89c82a5ba88c6b427bf0154f1689520e8a24fefba106812000001c2965bb8fd73128357ae46fd0451ff0d34a4b391a4a7d54c8d00dc00277b5b2c0001bb34e1eb64d2bad151a251de23fe7ab0d92c0d8125fb3c3aa8ce0a772ac1f83701c45242a1ce86ebb47c2abe6ef76f814b26f56b5883e5f0c520266563633e5d5600015b9ea4977075a83dad3e5e4547f93369f81807b960fa5d0377fea025dc47fd25000000000001103bcd926a1c140a15876ce5dd6bb4e0a32172f9fde5de340bd11fdd87d696670185555efbf4f751c9c4a7068f9c1c3303bc33bc8bbd3847a6fa5b6d5b3d547f6101891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625" + ) + case 1110000 ..< 1120000: + return WalletBirthday( + height: 1110000, + hash: "00000000019dd5701deda91aee19f653d7d89983fec6253d5728b738ce1cc575", + time: 1610499871, + tree: "017f230e3a91ab56970595bc9037a6bb38b69390070076c46f9a3d364f96171701001300011ebe10c1b67824d2b71e48010a03f817d80963999e15e3b0364eeccac01e2e70011681651b3c5fe38d3c35445560b9a4599f9370e618c1e72f2b8a69efd47fc9720001ec4a3829e823478478cc46af80d6d4c6b947b422dea6b525b18986dde5698a370001b52370947e83349c731edf7c5ef43dc7f9b14ca47074dee8fd16b14c5663fe4a0001d5b32170d5ffab2c95ac01821260f970881c8a3fb5770aeac7739490135e152f0000000000000000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1120000 ..< 1130000: + return WalletBirthday( + height: 1120000, + hash: "0000000000dcdf40c671af85eec40424e0475fecb06355fb5e37efda51f5dee7", + time: 1611253575, + tree: "01da06acb487d1ceaf8db4dc5ad8183bc8b4e9a4b020188336624bcd83adb7884f0013000000000187183a83d396d7d50514a081195ee24703202e0ec9e3196eb3bdef5e34354548000001d446400bb7cf59eac909c183eb8685cf6cc4517496708ad2bffd07acc46ce524000001e240979184856d63a9bbf849eaf06963acfc861af5a44a30e82193792d58fb4100019498b9b148ee924288e2225a474f2c9a7739500cb3c4821a52679f6a0a26d41000000000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1130000 ..< 1140000: + return WalletBirthday( + height: 1130000, + hash: "000000000009bcbe15ce9e005c9ebda0a1c5213b9573ad29c3a86a1a9f3f6586", + time: 1612007546, + tree: "01cdb094138ff68752216908f08ac0978b612b5b928b1613ec79275071f1c968710013011f9339db47ecf1f7510683dc263074e79825ffb487fccdf81a9f4c748024024600012695a02e2d0d49c3cff6192b46d4c4cacbb86bbd4cd88b6bf65564070bea0f20000195556413de9fadd73e9d5ef1cfb905a021dfea4ffa2f1cb6204438c60d665b5b01c1125574436b79f9fc6364ec470f453570fe7ad0e313878b809a525224166d580199820bae76e624f5c06b7f744e6a6ed57dc03314e91aefd883648c7fe0ff1370014576446ae9961962903fbcd41c9d7ff2d8c41b77244ff39e2f1233286f95301001df16b424017aef9e9138169b7e183c2613ca6ebf9680fd27c9c280c194d0772f000001fd3610fa060d8eca861a55d6bf0042b7e11d67bdac285b4677c995f2b466276101e5f0a7191091bc4ea3b06cc6cef4644b426122d74b91cbece497f7bdaa19526401226d7b2448f34416550c5aa0730c58f1eb72ee60cb9e9d61bd66c81d31b5ef51000000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1140000 ..< 1150000: + return WalletBirthday( + height: 1140000, + hash: "00000000006d9c69d8c4d7818dd2b9b106078317c6e881eab86ba41e4a546337", + time: 1612761940, + tree: "012afd078f200a60fe586c8ebb81208bc6b656f2c24935ed9ae483606368c6101c001301e0a84c415504116132c953c1885150a6335bc3293aa17c89626e02406f944f39000000017c0a218b969475ad665bfdea14177bd73b8510d451bd1f533f29d5f86f92a14201faee45bdbbec94f64fd8b641b3e2c1c473880b14a86134d766b9ffae127f0506014815011726d11513734103e47971902e4e8c1245ab2b96107184f2978a13cb2501eecd48ee70785ed9d31c4edb6da31287fe1b42082466c787262133017fe3ab210183352b54c9e84bed4c1fb4c31dc1bf690e88aec9f477f6e00d51a4bc918cba32018b702b3a1bb47c1455d5ca00cdb6d2eb72256f421937dee7d5453e7108c8df3a00017c41a5948f315986b60909e07a15c2639fb1b13a968aaf322d654aa1e823f60b00000116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1150000 ..< 1155000: + return WalletBirthday( + height: 1150000, + hash: "00000000012e01251034b1cf6ced448544f350f023280e3118cb23863affbb58", + time: 1613515993, + tree: "01a4948b191c1169242c0dfd9c287ce1ad06a681615ec99620fa5936bb05119d3000130001e9eb3a657f63031a386c64296e66b98374a0d74280132543535eb82180a5706801e0807fba775afd5acc8714c1c33ac709faee472841c3874ad477e57a01a01a4c0000000001dd716f606210678f0ce78fa535ba46a5cd1d0f22f7b237491e0136e71e51916400012278350ab0e251df819aa820ab100a1264bf5aa73c94bf5968730fa61668996001430989441afaafa2f64683ff0424b12b5051763ff094a88a4cc96cd00f09b8650113625bb6dc4092d25f906a05fd3e2f1a7c5df03381d0e0760aebc2ad0ecf0f0b01582a57901af4736388425e1bd26fff5b23fe6c74d10b1fd7145c46e57eeed609000116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1153000 ..< 1160000: + return WalletBirthday( + height: 1153000, + hash: "0000000001d06618d059c2c1d9a0dde0369cac8af75c9520409715f2a766b259", + time: 1613742458, + tree: "017aa8d47888728be9104e9dee586acf733b86fb244c4d9abd4b23d3b8f15b5d0b0111cf472e9ddd29f30ad95cf4f0fb7e587cc589735cfc9ec5a36a11e7d3394c711301fb9760d76283fc1af4195cf7d08a1f661cd20ca5201585451e877af846aeb6010000000001dc7dabd7bcce76a04412dbc9ef145d3d10eda33b5f644738c51286e84112c00b014d1745efddec53a2c5f23adc231decbec7a03c72ab4fed682d0affaf29584403018f8c345bf75a7efb9521dfc3cd6192b05b01702fc9a88f9be949a92d9f429f6a017b5ccbfa88f3523ed78b79f0cd86b883a096fb9b829c2a13000c8dee9ac9c72c01deeb9380b9491c7e7d59075ad35b8c8b748ba7d0337a273c3ce2a4e4179c9a2000000001bf57fd5f3e010a317aae249ee1c4583acc2688c9c22f84710f0173cab1f151560116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1160000 ..< 1170000: + return WalletBirthday( + height: 1153000, + hash: "0000000001a7bb6c535053418e8e9e1620c3e5611eebcb15218a0584754e8980", + time: 1614269669, + tree: "01ab89bc17a2fae59a5170033dea2302d8825a71a0e3fdb1a01d50c44fae59cf2a00130113607db0515d576fdaa165b61e9bbebf997bbf039ceb75aa04ccb3dffe492e5f000129140c523912d51834243412016078da091020f5c02bd498cba160342d20b92101f842c5a07a703b080c4d73cfa95460265b10bbb6c7dd5ba4cc50c7e24c4f380e0000000171df72fb201bb6c7f4fb3c9e06ac94ce0eb0f8c0259719d071587c3e5a74e00b00017010f179ca3f1dbb0865b00a418114dbdd67e031e430ee1bbea1b30081f14236016068bc4c06705014dae9c2a5f86f6734b08e39fb4ebd21366531dd93c0d0561d013ecba16781a5b5f4837c648de2a32f96c3d635a3b9e3630dc1bd1b1f4276be170001bf57fd5f3e010a317aae249ee1c4583acc2688c9c22f84710f0173cab1f151560116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1170000 ..< 1180000: + return WalletBirthday( + height: 1170000, + hash: "0000000001225d341f424c445c71b13872ff89300210594f3d9d405ead56f539", + time: 1615024297, + tree: "019968e9b4725455dea88d986b33458d199353a26f1349abbe7f39c3d72f82365701abcab1e8db711ee75949326fa6a0ad302776ff40036cfb4c1c770ea430a1af51130001352edbeb2884d8ed1f39c18125493783d76f495a88fdb32c7e5d7e61de1cfd7001b6966af9deaf4512b7922f65ad099fd11f1c3d34d80c93bf4e6d9aec18686d5201727534576ffd6b0cd7146d0e3516b3c9836e9ba5965e35b35033a3add146254901851e9189feb9e5f62c2df5049c930d0438083c86958cd179543156ada7da910f01392e342052ef08587ebf642bda8e3948b437b915a5d1856d59ced86d9e640a5e01199e767f23a7d41044303fe914e98c9b059b9ce0b85b37b7fa26e43d4fb5b72d000000000000000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1180000 ..< 1190000: + return WalletBirthday( + height: 1180000, + hash: "0000000000521c0d55ce1765092caff595acb5d546147b192fa9272051f55f42", + time: 1615778593, + tree: "0102a70ba9e31d6c24be0fc283577072d815d418da5e1b14cc81923f7bed308460016d9d5c674c15bdaec54c70d528e94be910994213683e3aac2fc94092fd8b4a5b1301dce7f293aee6c2769fe616dd47d46e79b51568c8bc08c67198b20d28eaf12c6f000001ff83e392690a332103433465b2034df2ab6cf35c164149a3951bf0d2bcf2a96601d019ed97502d718643c32851eb1acf6307861a3fe0ce3174697b0c2df4568568011d8eb058dd0a73a4314e04f12a6de50dd18879ee891db5a20c890e1c707f6f01000001cda4d5ff76022119fed8ffb94b8d3a26a0db37a1a886a0f31a57d1c0ce03f106014fb59c2d5dd4cc176d226c57b48d4dfc4d200088d5b69cce675f84e885ee5c1b017d5b561bf80be788ebf12e901e4c544cad95e24d0b21e6145e1718ec9dbfe91101678fbb171e5715c63bfc888d345e755c69c6dbfc2818f05b6e6ca32211ffd44400000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1190000 ..< 1200000: + return WalletBirthday( + height: 1190000, + hash: "00000000019caeb64ab8caa12e1dcdd9a8f391b063ec252887c91526b7ac5e0c", + time: 1616531745, + tree: "017ae2fbedf5cad68ee80df0ae9caef9e0168914780bfd14eae016e2fb89068071001301c78a8f9bfddd9a1f0076048c48d1d58298ac6f4368472a39b0b240d540117c4301b58c9284084704437af784307ab0a334dc9c7aef588bf7d26491274d79c4471301b0af0fff110293b555f17d5ced0a598693ff4cde3e680d988c6ccf498846753e01bb9d0f21f621448c03ee49de4ef3bf0faa4844544f9668197ef5921164d2401601a15d695922c5441e80aa770861f91a97dd460561515d32c9d06bd3c6f98ce26f000000014a772e6ce520bcedf07793ded6148fd3415ecbdd89c3efe183b6048f1fb4791c0001e281c5ec71bc1a301ad0d285f6f1aa2552907645b02f9d43160f5354c2be7c63012b4d8d83df48c8b5c35752268eb71a428aa05103809a887fb36519dedbc8de27017b610946256293c523b36cf95ec60f2c346d866d98d1276bbaba22e46815516d000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1200000 ..< 1206000: + return WalletBirthday( + height: 1200000, + hash: "0000000000347d5011108fdcf667c93e622e8635c94e586556898e41db18d192", + time: 1617285467, + tree: "01dcc15a1314130c3ae61401ea76c0c1b32b0c44d8486fb6cb8764af9f6dc03d540132d6897fe6cbc340c786a129e69aaac499ba9ae33cebc0ae6163d02dd15db4061300000000011b153a8182d97d204f5ddf0cdbe66543d67ef3b25dac5602987d4dcb57f35c260001a3d62e7611681256eb34d5945fbbc085ccf1d04d6a507295c3c9724f6e899069017fd5efaf2ba1e3c53b0039674b6667e401c83834d53b0970c7ff3a6dad684a540001c77d47e4819c69c3a473b8e4c660bc73c2a4fc0a067e5ad21c6fba9aa031c96e00013729a1708bbe29fcd683e3e3337e8b8ded4fa6abb24cb7bef506168be7fe8a5b0001df26abb60966dedb257d90ef08aa7232474229e08e62ba390336a07c4775a7260001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1206000 ..< 1217000: + return WalletBirthday( + height: 1206000, + hash: "000000000078454a0d74d2df9ae2ca53ee37bfa21ba5d761a96dc426eb3603b8", + time: 1617738149, + tree: "01f423310ab6f632a457f8b91f6c16ba6a0c2b49297f54462e5588d1eb6aaaa0200147dbb8e70cbf50002af16e9e75ebd32c1e5f3f66b43e88001965be754ea82a3e13000001cb1695d6e381645c49c9706709438c8a40cb667b7eabbce3669f293d2738e24d00012a8f5a54b81bb34bbf0a8e8bbff5217f17a423bd379ab08a08506744a6c0272700019827b9160f8772351b07ea603a48a6085ebc61692243ae9dc6b5118c1b5be347000000014226899cc196086727c3a53560a6273406f499e19d1b57cfd6018be889630e0d000180541ee92782f67894645a8a976ccd0934e37c13fbbc7cbb501b7ba78d1a902301df26abb60966dedb257d90ef08aa7232474229e08e62ba390336a07c4775a7260001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1217000 ..< 1220000: + return WalletBirthday( + height: 1217000, + hash: "000000000101d56be0c460d0e3cd780bf4eeeee79f98b2650ed61f2461ed0e61", + time: 1618567777, + tree: "0196abe4a8e73e641c8bde7f7d4c7455fc530758e5754b513ca76bc959757d773c0013010c2a76ab6a36beee5f415d06f0c4081b2569b8268123f00ac6a6cf95818dcf11000001f913b2dfda97da60e92d1cc81d0533f87794aa1dfd50bd668ffac7cfc1c1e2090001dd5879eeb7e652f8edf6458079cf06a4189700cb2dd6faaea03179a1d24d59050116769e0bf56d11a3fab9b728e76d131b177add630475992c0272ac1f6d14815e00019e4967e62633bd0d8084f78aa945c1a50bd571c71d06098f352a9d329c4d86110001a1e452b5cdaf030e7b4a75b30cbf4a920aa502d03c4b25af22c3ba815870a14700000001ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1220000 ..< 1230000: + return WalletBirthday( + height: 1220000, + hash: "0000000000751d7ffb3aac6f6a66ed01aa4e991a96162c1749dc556e50fe6df0", + time: 1618794113, + tree: "01c3bbf34ce189a5285144c79cc37c4e76385b803947819ea8bc43b1e8eb2c020801861a52e2fb19b150b0b7c7d7f879bd1ac4fa3a11ac9763db4f837f4db048896413013ddab8738a0cc8e00e96c7487d21a9771a7986b7e1e5d5fb0348d46caa18360c01d6b0010e9664a01a47a8acc9bf073255f6fb62f617cb491b249671da85001862000000012fe6dc35a5d51af73b73854855f9861775296a9c56d6aa9455be2762a101d7390168ee29d7b083e5af0d1895b2832a4fc63a9c7b6cea37b75d17d28e6f5842ee0c0159781dcd759c87f8bc8622bc19f9a8732c06b52897bfb6e0ddcbadb111d6a95601036e008ad224efaa9833fa9e790192dad7aab0ba71bf872430f48ba6aa0d1d1b00000169bce4bc91631cf6158d978b5ce6ad03f3e4cc3317c28964b575ca736f8b4d68000001ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1230000 ..< 1240000: + return WalletBirthday( + height: 1230000, + hash: "0000000001bcfbeb53fd5e9647168265bc5fc8e8622049b9cdd07098f0f51601", + time: 1619548843, + tree: "0164566f774ea1f6d7cf21a9fbf9cb3f2e7d1e400097417822a7c233422619c3710013000001bad8de55d9adf4d4ff08f4ad172a5ee80aa0049974c5227d2b07474078f73c2a01e8d5303b72f034efacb9b9aa0697aa5568bf6116f2fdc1e528c03b76ce569c340000000000015334d52667d65b8ff3dcfb3d6ed72c46ad19ea9112813aaf344a3e614eb9012600016cad8c39b711691f2bda74017894c657555a8bf7ef913931ac4f7ba0b48a30120121c25bceccda091622bfac1b7973ffaa638abe1f334b3b56f48dc93dc549c9070001ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1240000 ..< 1250000: + return WalletBirthday( + height: 1240000, + hash: "0000000002473bf56688195f05b6f5acea0f99506fca40ae72f2ab8c1fd7390d", + time: 1620303759, + tree: "017b7c743693588568510844e4bc181d12ab6433dced0542d149cbec2b96ba526500130001cb8eccc27eb266385f9e4b880ff337b2ebdf10238dac74414fde8937dfa2264b0001bb0cb6201a0d003f1e4df17cfd4815c382ced6bf038468873495ff5c9c25412501ba626167f23eb767c229a0498b37e8322326779a3a6454ebcefd639056b3e64400013ff350f9e880271ea2c713c509491605ea24589c369262c18c417fdf1027305e0000000001849b1538147707b1c880e7eee02f29ada52e8a5a6c3a9027087493f41bd8304a00018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1250000 ..< 1255000: + return WalletBirthday( + height: 1250000, + hash: "0000000000f3d2c352c395d66866032bcb67094228dd4a27e561b1c399ea612e", + time: 1621056898, + tree: "01c9a0dd6f6dfaaafe6ae4b432c2d1c41d2a73e564c8cb6d2c5ab637c7001a2456001300000000017da32b486a8ea9f13afb93b99d2b1de69aa969e7c2fd7b9ee958bece70c08d6b000001b3a4486b176dfcedc0b3d9287c0333ff464ecbd02bac7c89bcda7932e6a0a36100010d451c18b56877b8a11cb401ab7024c82b9669ede862a53e461087f57220035001a1c5260bc4dfe010510b8135209c6f64229965f71717f1e693abdcf88a58f36700012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1255000 ..< BlockHeight.max: + return WalletBirthday( + height: 1255000, + hash: "0000000000f34f274737e653cc31122e8ba8ca9865c09b65b3c2ecfb2e9687fd", + time: 1621434019, + tree: "016f51c78a2c55fef567e8deac7cb82b1f62f9ee6f5fdea27fc6fd9d1955e30353013f25aaa8aedcf10cd63b622d8c7dc21eb7b30504f99952bbc8efb437ffc482131301d0fa036d389289e37709f7f01d09e689cf55e989ea9d07440d593f21929f960801f69330a08f076f55f5db32aab6f2d1a2ab23e52a9a4e4fbbd21b8204ff23e64d00012f1469ddab73380dc3302f1cdbefb508141e2689a83b754fd9970037eb04fe6a00000000014ba6ac078f45c360c912ef828c138e4bd7d4150cadb2a498a32ec3fe7e22cc720001638de702094b20c64bc4b046cf7724634096aa192b155d191934120653734414013027101973e524ee59f21261bbf9fc152a61856a00f876a7c2b4dec71d50e969012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + default: + return WalletBirthday( + height: 1255000, + hash: "0000000000f34f274737e653cc31122e8ba8ca9865c09b65b3c2ecfb2e9687fd", + time: 1621434019, + tree: "016f51c78a2c55fef567e8deac7cb82b1f62f9ee6f5fdea27fc6fd9d1955e30353013f25aaa8aedcf10cd63b622d8c7dc21eb7b30504f99952bbc8efb437ffc482131301d0fa036d389289e37709f7f01d09e689cf55e989ea9d07440d593f21929f960801f69330a08f076f55f5db32aab6f2d1a2ab23e52a9a4e4fbbd21b8204ff23e64d00012f1469ddab73380dc3302f1cdbefb508141e2689a83b754fd9970037eb04fe6a00000000014ba6ac078f45c360c912ef828c138e4bd7d4150cadb2a498a32ec3fe7e22cc720001638de702094b20c64bc4b046cf7724634096aa192b155d191934120653734414013027101973e524ee59f21261bbf9fc152a61856a00f876a7c2b4dec71d50e969012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + } + } +} diff --git a/Constants/WalletBirthday+testnet.swift b/Constants/WalletBirthday+testnet.swift new file mode 100644 index 00000000..15cd6a21 --- /dev/null +++ b/Constants/WalletBirthday+testnet.swift @@ -0,0 +1,166 @@ +// +// WalletBirthday+testnet.swift +// ZcashLightClientKit +// +// Created by Francisco Gindre on 7/28/21. +// + +import Foundation + +extension WalletBirthday { + static func testnetBirthday(with height: BlockHeight) -> WalletBirthday { + switch height { + case BlockHeight.min ..< 421720: + return WalletBirthday( + height: 280000, + hash: "000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a", + time: 1535262293, + tree: "000000" + ) + case 421720 ..< 425865: + return WalletBirthday( + height: 421720, + hash: "001ede53476a31a91da3313eddf4e41409fb7f4e003840700557b576024d09b4", + time: 1550762014, + tree: "015495a30aef9e18b9c774df6a9fcd583748c8bba1a6348e70f59bc9f0c2bc673b000f00000000018054b75173b577dc36f2c80dfc41f83d6716557597f74ec54436df32d4466d57000120f1825067a52ca973b07431199d5866a0d46ef231d08aa2f544665936d5b4520168d782e3d028131f59e9296c75de5a101898c5e53108e45baa223c608d6c3d3d01fb0a8d465b57c15d793c742df9470b116ddf06bd30d42123fdb7becef1fd63640001a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69" + ) + case 425865 ..< 518000: + return WalletBirthday( + height: 425865, + hash: "0011c4de26004e564347b8af218ca16cd07b08c4159b1cc9c43afa6cb8807bed", + time: 1551215770, + tree: "01881e4da7e4767ee8a144a32ab8a5719a513bb05854477773bb55e6cd7f15055201f8a99a3a5ae3528ec2fc0bda9652b6728aecb08bf364e06ac511fd6654d782720f019ef0b9bdd075c38519fa4ab8210fe7e94c609f52672796e33e3cab58b1602831000001f803bf338ff1526b2ca527288974cb9be3fe240a2eadb7507e46ba59eaddb9320129fc0148ac088a6aa509f8f64ef79fda92232020369b58a12b32c05b6f428f22015e3dd0950c442940bd015c2176f7c817f22104f54c61159727483188c539dc13000000013589be9e2d9e9e38fd78b1e8eaec5b5f5167bf7fd2b1c95c316fa366a24cac4c01a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69" + ) + case 518000 ..< 523240: + return WalletBirthday( + height: 518000, + hash: "000ba586d734c295f0bc034be229b1c96cb040f9d4929efdb5d2b187eeb238fb", + time: 1560645743, + tree: "01a4f5240a88a6eb4ffbda7961a1430506aad1a50ba011593f02c243d968feb0550010000140f91773b4ab669846e5bcb96f60e68256c49a27872a98e9d5ce50b30a0c434e0000018968663d6a7b444591de83f8a07223113f5de7e8203807adacc7677c3bcd4f420194c7ecac0ef6d702d475680ec32051fdf6368af0c459ab450009c001bcbf7a5300000001f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 523240 ..< 620000: + return WalletBirthday( + height: 523240, + hash: "00000c33da2196f0ed1bda71043f671fc69a0212e01f892653e212ab358f6b79", + time: 1561002603, + tree: "01d3e02bc1c2d66762f370b329a3063067701ad66c44b40285686bc8ff25f5616f00100154bff87bd0bda3b70a6d7754eca261de15fee3cd9bc53073a232e07fc3261e27000001a54dcaccb4c5e578aef89f2a3b4e3c3d8a487e6e904c5da5916118d721948d07000000000118fa9c6fef4963049dc7002a13bb0021d5e950591e48c9e5f2cbd1199429b80401f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 620000 ..< 680000: + return WalletBirthday( + height: 620000, + hash: "005f97953c8e1265d6b45f4435ffa32918e53e8f0025c286a4080c3eab167197", + time: 1569572035, + tree: "0170cf036ea1ea3c6e08432e18b6a372ca0b8b83671cc13ab0cf9e28c182f6c36f00100000013f3fc2c16ac4780f1c472ca65534ab08911f325a9edde5ea7f24364b47c9a95300017621b12e518cbbbdb7511ab423e0bddda412ed61ed3cff5be2140de65d6a0069010576153a5a2098812e7a028c37c3398e186f398c9b07bc199784ab97e5535c3e0000019a6ce2f0f7dbb2de493a315abf62d8ca96ccc701f116b6ddfae33870a2183d3c01c9d3564eff54ebc328eab2e4f1150c3637f4f47516f879a0cfebdf49fe7b1d5201c104705fac60a85596010e41260d07f3a64f38f37a112eaef41cd9d736edc5270145e3d4899fcd7f0f1236ae31eafb3f4b65ad6b11a17eae1729cec09bd3afa01a000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 680000 ..< 720000: + return WalletBirthday( + height: 680000, + hash: "00a4fbf54597d2f474f999576affad63f0ba2daa14c6fcd55c7eeec700107270", + time: 1573569367, + tree: "010a57f939a267f8b1e8b77288c783432e48fa95f7b22ead5e8ff46a788181453801d6457d98d3698a367aef4a2fe5675a575790d5d8081b731f979f0e64043fb7351001afaaf81d6d982b401444dbcf89e63c2583d234c1a60de17940a9b3a15f3494660001ba7acc730584a689413c44781d3b13cd497bfdca3fe27fb78cd9b50e9929906300000000000129e195df514840a20b95200b92d5b8d196b119cd6887508d8de077beffdbfe68016482af04b979e08e4e5760d55832292e55dbdd88143992f123840c8983db7b3f000001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 720000 ..< 740000: + return WalletBirthday( + height: 720000, + hash: "018b71dde8c9b1ee3e79961c6e3536c79226f5d6e79bb35c9ed28dcb8cb78b48", + time: 1575943651, + tree: "012cfde48dff4f20ddc50a7aca3746f7d77920eebc8cf4ef53feac34cb8719c03a012c668d234aaa485862e1d06e46d6d7093c2581e2b9cda90aafd691d6e325410610014f3a875476cb8159d46fec1aba18c201c268cd61b01811b7e5bf83998fb8222500011f19160cc75325c090f3eb3fa0cff2d94e43e2713c89e7b02a34f6ed08fbcd26000001edc05305223f7f2839abc1dc7d900468349577d6d6f5c182ef3a81a848753b5b0000000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 740000 ..< 760000: + return WalletBirthday( + height: 740000, + hash: "00163c394a1e545b4c777fc91474d92becdd0fe9300d38fb3563997d026a54ea", + time: 1577389695, + tree: "0135ee37f83d0b924eed58bcceb249a4977dcb21495561b97bc747a272ebe5d6580010000001fe65cfbb8a76e0d29ac94e5ada80c80b607d1addfc287754f37ddef531eb122500013a1d604d978f716fcb2887cdaa3c582a608b795ed1b3c57998cbede2be479931000108ffb0fbc6b653305b37cd5568b85112b996cd514fe97ec73f7169dae0cef05101baf5541e853483315273c25c1956d233513c3dabd8741972136b2f8f8cd89035000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 760000 ..< 780000: + return WalletBirthday( + height: 760000, + hash: "005ee769f3adbd0b24a63e8e4047200e038c38df277544d40c23ac1a88c1f37b", + time: 1578766903, + tree: "01470a1a4d29374e074f07a646b95dd89892d9b84d235a89ecc9d5a52beadce901001001311898ce56df0ddb10dc573a54ea06d11415e72602daa80c01f888fbd4a9a734018610afa4925cdb8bd4dd75a53ab69a74080322cae53c630ac02ce00b09d3171601bdfbbde5011bd6c0620ed2db3e01d5daa2ff8bb5f3b58687d265dd33a5681d530197e268c82e56dfc62aeb54586a2000766da8078f09a2d15fb558ad05664b4c5301aa204407034ba59fce0eee6518688585e96b0f10befd595b8e68a8ae15328a51017389398c5634242b03ef811f6abf224df9e6fc6d4393139e526dca4cf44dcc2c0000017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 780000 ..< 798181: + return WalletBirthday( + height: 780000, + hash: "0104238cc440b6bf05b86a1b00d794c6d88fc61b8c416124a971fb5ce94b91e6", + time: 1580205978, + tree: "011ed883b7eddb4783eee5b73ceee4c78413e1f6f9db3d88d1007f5fa62292955c001001861feaeab59bc31cd97ffc89467877abf8b9fa157bc875907eb90d6e8c723325000000000001ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 798181 ..< 800000: + return WalletBirthday( + height: 798181, + hash: "02936aa4f8b6b2caad7cca19a866158656e37edfb0f32e2a473dc278fa634b71", + time: 1581521064, + tree: "01901ef0f4221f8a02d5896fda6f78cb5578fb8e9a5361d5689bfb3b6ab92072320010000101c5d791d8748f0ab0ecdb48764de29c470cc74f5d95b5a1f8cf0830bb059b66015af654e998c75460e9c1f5ba185589c53c383167e66951cfe7684321b7a77e5c013faf6b3f21f03982ada477bfddc95b18e63683c497b2f4630ab453623c28974c01aff3253410a6601ab4b5b3626f2121cb77399c634b1774a4c63f415598d16b0c01a6158d0a1a1bec9dadc601b140a9fdfc7bdab7e232739a3cc0e0e46bbe3ef44301ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 800000 ..< 850000: + return WalletBirthday( + height: 800000, + hash: "00599614a7795bbef99a598cfee887782900fa5cd95cd59900b8d6582bdc17a5", + time: 1581643886, + tree: "011ba0f16f59489a9bf9cc46c3ed1108c1dc0ff6e40f3a38def472c3229a96925e01b0eb758757bde323a6417d98365ce8f6299b0fa3de615d6cda68689e6a81573d1001438b40ff7357432d987d6ef4826fba35d38b2db531ea842ccedd4916a6aff9580000017cd705c293895c8b4613a3de3ad3b8d43ae05fff808882db4c5e19917e2f346d00000000000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 850000 ..< 900000: + return WalletBirthday( + height: 850000, + hash: "003b66bc3528dc295193108caab868e0f3b93d13db2ddcad5486225fb2b83d83", + time: 1585012771, + tree: "01e3bd906376b563d184bfbf6616e220f895001b7ef9d26bf38c6cb5c71e57a42b001001d848adf8c38d113140bb30d306b0761da6987e25ffc0d82faa63c2764aab120301de3e6a35d09192cde3430860c70a534d7b63e95a726fab052de2a9befa3cc3320189b958fa030131bb83385a3e3a8b187a166dc1b3a02050f2d2fc20788536c30e0001cb8770ef198e7de60093a339afbc561c16c16749f9f96751c2fc58a22d0ff36f01f86ff70dd512f7075d02c5ee6e28a8824832d08025a4cfaf4c1854f1fba5da10019bcac1b44a27de2c4528fa6f4b3432913511b219cb3b29d137cac0236a3d244800000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 950000 ..< 1013250: + return WalletBirthday( + height: 950000, + hash: "0005050d2ce31b9b925c7ef4ab3d3166d5833bdcfee251294f29072a2bc0f75d", + time: 1591609525, + tree: "01f0637235c4a699d49ba996457a6c4eb7c67edd8270948065683deb19ef218363019f65a9692cefc7b90b42c1538ac1f38f7a7598549089c4561315b482f378523010000000000000018d30d0039277b05ab9e0c3990d53037c45892bf17af2d04fef40ed48c164ad2201ff5d86bbbe360e31378e783b740f8b05db2cf4246b95aa3851d22ed45554750300010cefb25743d5dd6062ef3afba438731cd5b35befc1038ecca3076fd205829e550001c19052386d8bbe3c07a1faf302281d67946cc9547e7e1890ff56b3a3ec69c0310001be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1013250 ..< 1028400: + return WalletBirthday( + height: 1013250, + hash: "0017b3c49eea14e93f69adbc7a8f24eef3e9645f92e3b8d5e4091e1d5a4824b7", + time: 1595516064, + tree: "01d45e95007f8f97fe3c6a297a9d4bca917772e545fbcbb61b4f42d8a743eae31b0010013d7b7da2e6792dbfc6360f0c13a1ba879aa51a498c6dbab87aa57cef558cc35a00000001f945c15602617327026e3e0f231daf91570b32f7bb766f65e7e82131a911cc3c0000013173e9983fbd7a396e192e520d163be06cdd28abcfeba46c59dc62a400f589080001e7d5b00f0758cd3b7407c6d13e23d1a59e3f510c3dd3a4a8fc367a5305673b3f000001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1028400 ..< 1130000: + return WalletBirthday( + height: 1028400, + hash: "0006b94b304009f8a6287aa48021aed26582ce74d387c2c452aede86566179a6", + time: 1596480151, + tree: "01ac95378779cf56f0726655d248f95d63e07316ab67651ce357b346f9a7adba300107d7544edbe7d0522fe523df2ff804fc9f33f4844dd29e86a23fc7aa1818e237100001f8779a159482fd3a28c640e6d48ddfb37a44a26a102aae3822f32d2de22a1c70011f97534315f1800961bc78fcd1495e3b8047bb227e2776080fb31be6cae14e73000000000001fe15295e017fc2b8ba4ea1b7e53dd15f19860d10e7952905b7598373e143413e00019289038516ce3d6038cebe852ab5e32f7a1966fc79a1e41c7cb6e67e5a71c33d0001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1130000 ..< 1370446: + return WalletBirthday( + height: 1130000, + hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", + time: 1603070117, + tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1370446 ..< 1414969: + return WalletBirthday( + height: 1370446, + hash: "00357a40a8d0473663f5ac32ecd4365bea097e47070b38803cbfae2b7a402233", + time: 1618587354, + tree: "01d0d36f8845f9ffad4f0a8812fbc5c4c69b45733199d7183307cb1a7d00353c0900100000017a8a6f641c487a313bb949623cca3b22b925adfef8216866aa090546bcf520000001bf48febcd2a10e51d420782990e17b746d5ce0f3292007e60a2eeb830bc46d0201ab6e0123bf72f70255ec4cacd33935b19ff834d481d67e06801073d0b8f0ea2a0121f42f607885a0158022413591af8eca7eae38b10c46e3ac81a9bfe70046e51d018229160dbe1f1d9e02d738e9d5060497e786e7434c80c32db7b8c96878e9904601034e6b1c73f09aa81f16a13cdb2188a53d8761483470f0bea01bfb84eb2cea1100018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1414969 ..< BlockHeight.max: + return WalletBirthday( + height: 1414969, + hash: "00212ba35169b77dba4eb4f5ce8c10da31a9df6dd61bb434f2f9e159d78913bd", + time: 1621459669, + tree: "01a9497fdb3add3bc2d0676f3163d94cda7c8cf8112d9dd8d2e7611b187c600a410010000143905c99f7bb45b164c636bb2443d9621db8147dba6a84a279fa8ed8f012083d00016847084e044e84059ea4b88b8af2de3f65c72adcee21522d5ee9d370d70f525b0000014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + default: + return WalletBirthday( + height: 1414969, + hash: "00212ba35169b77dba4eb4f5ce8c10da31a9df6dd61bb434f2f9e159d78913bd", + time: 1621459669, + tree: "01a9497fdb3add3bc2d0676f3163d94cda7c8cf8112d9dd8d2e7611b187c600a410010000143905c99f7bb45b164c636bb2443d9621db8147dba6a84a279fa8ed8f012083d00016847084e044e84059ea4b88b8af2de3f65c72adcee21522d5ee9d370d70f525b0000014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + } + } +} diff --git a/Constants/ZcashSDK.swift b/Constants/ZcashSDK.swift index 5522f400..d0e0e7f9 100644 --- a/Constants/ZcashSDK.swift +++ b/Constants/ZcashSDK.swift @@ -39,7 +39,7 @@ extension NetworkType { } public class ZcashNetworkBuilder { - static func network(for networkType: NetworkType) -> ZcashNetwork { + public static func network(for networkType: NetworkType) -> ZcashNetwork { switch networkType { case .mainnet: return ZcashMainnet() diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj index 2f16a2e8..de06d5a1 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj +++ b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 0D4EBA312396CFD70041B507 /* SendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4EBA302396CFD70041B507 /* SendViewController.swift */; }; 0D6CE8BD252E3C4A0005D707 /* SaplingParametersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6CE8BC252E3C4A0005D707 /* SaplingParametersViewController.swift */; }; 0D756A94236C761E009B041B /* GetAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D756A93236C761E009B041B /* GetAddressViewController.swift */; }; + 0D76121726B1D5F5001CA417 /* Mainnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D76121526B1D5ED001CA417 /* Mainnet.swift */; }; + 0D76121926B1D66D001CA417 /* Testnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D76121826B1D66D001CA417 /* Testnet.swift */; }; 0D7A4A83236CCD88001F4DD8 /* SyncBlocksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */; }; 0D7C85E523AD5A9B006878FC /* SampleStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7C85E423AD5A9B006878FC /* SampleStorage.swift */; }; 0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD3DC6238D88B100DD3EC4 /* GetBalanceViewController.swift */; }; @@ -75,6 +77,8 @@ 0D4EBA302396CFD70041B507 /* SendViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendViewController.swift; sourceTree = ""; }; 0D6CE8BC252E3C4A0005D707 /* SaplingParametersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaplingParametersViewController.swift; sourceTree = ""; }; 0D756A93236C761E009B041B /* GetAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAddressViewController.swift; sourceTree = ""; }; + 0D76121526B1D5ED001CA417 /* Mainnet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mainnet.swift; sourceTree = ""; }; + 0D76121826B1D66D001CA417 /* Testnet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Testnet.swift; sourceTree = ""; }; 0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncBlocksViewController.swift; sourceTree = ""; }; 0D7C85E423AD5A9B006878FC /* SampleStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleStorage.swift; sourceTree = ""; }; 0D8BB46C23B1DA0700D5E2A1 /* ZcashLightClientSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZcashLightClientSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -189,6 +193,15 @@ path = "Get Address"; sourceTree = ""; }; + 0D76121426B1D5D7001CA417 /* Constants */ = { + isa = PBXGroup; + children = ( + 0D76121526B1D5ED001CA417 /* Mainnet.swift */, + 0D76121826B1D66D001CA417 /* Testnet.swift */, + ); + path = Constants; + sourceTree = ""; + }; 0D7A4A81236CCCDB001F4DD8 /* Sync Blocks */ = { isa = PBXGroup; children = ( @@ -224,6 +237,7 @@ 0D907F142322CC5900D641FE /* ZcashLightClientSample */ = { isa = PBXGroup; children = ( + 0D76121426B1D5D7001CA417 /* Constants */, 0D1BE47D2581933C00F78BE3 /* Get UTXOs */, 0D1BE44F2581583D00F78BE3 /* Derivation Tool */, 0D6CE8BB252E3C1A0005D707 /* Sapling Parameters */, @@ -659,6 +673,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0D76121726B1D5F5001CA417 /* Mainnet.swift in Sources */, 0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */, 0D8BB45323B1DA0700D5E2A1 /* GetAddressViewController.swift in Sources */, 0D8BB45423B1DA0700D5E2A1 /* ViewController.swift in Sources */, @@ -684,6 +699,7 @@ 0D907F182322CC5900D641FE /* ViewController.swift in Sources */, 0DDFB33C236B743000AED892 /* LatestHeightViewController.swift in Sources */, 0DBF8F9523A80F5A0010B85F /* TransactionDetailViewController.swift in Sources */, + 0D76121926B1D66D001CA417 /* Testnet.swift in Sources */, 0DA58B942397DDD9004596EA /* TransactionsTableViewController.swift in Sources */, 0D4EBA312396CFD70041B507 /* SendViewController.swift in Sources */, 0D7A4A83236CCD88001F4DD8 /* SyncBlocksViewController.swift in Sources */, diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift index e0e46dfa..75956bac 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift @@ -33,11 +33,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if let wallet = wallet { return wallet } else { - let unifiedViewingKeys = try! DerivationTool.default.deriveUnifiedViewingKeysFromSeed(DemoAppConfig.seed, numberOfAccounts: 1) + let unifiedViewingKeys = try! DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveUnifiedViewingKeysFromSeed(DemoAppConfig.seed, numberOfAccounts: 1) let wallet = Initializer(cacheDbURL:try! __cacheDbURL(), dataDbURL: try! __dataDbURL(), pendingDbURL: try! __pendingDbURL(), endpoint: DemoAppConfig.endpoint, + network: ZCASH_NETWORK, spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), viewingKeys: unifiedViewingKeys, @@ -48,7 +49,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { try! wallet.initialize() var storage = SampleStorage.shared storage!.seed = Data(DemoAppConfig.seed) - storage!.privateKey = try! DerivationTool.default.deriveSpendingKeys(seed: DemoAppConfig.seed, numberOfAccounts: 1)[0] + storage!.privateKey = try! DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveSpendingKeys(seed: DemoAppConfig.seed, numberOfAccounts: 1)[0] self.wallet = wallet return wallet } @@ -152,15 +153,15 @@ func __documentsDirectory() throws -> URL { } func __cacheDbURL() throws -> URL { - try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_CACHES_DB_NAME, isDirectory: false) + try __documentsDirectory().appendingPathComponent(ZCASH_NETWORK.constants.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_CACHES_DB_NAME, isDirectory: false) } func __dataDbURL() throws -> URL { - try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_DATA_DB_NAME, isDirectory: false) + try __documentsDirectory().appendingPathComponent(ZCASH_NETWORK.constants.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_DATA_DB_NAME, isDirectory: false) } func __pendingDbURL() throws -> URL { - try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_PENDING_DB_NAME) + try __documentsDirectory().appendingPathComponent(ZCASH_NETWORK.constants.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_PENDING_DB_NAME) } func __spendParamsURL() throws -> URL { diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Mainnet.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Mainnet.swift new file mode 100644 index 00000000..74ac7baf --- /dev/null +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Mainnet.swift @@ -0,0 +1,12 @@ +// +// Mainnet.swift +// ZcashLightClientSample +// +// Created by Francisco Gindre on 7/28/21. +// Copyright © 2021 Electric Coin Company. All rights reserved. +// + +import Foundation +import ZcashLightClientKit + +let ZCASH_NETWORK = ZcashNetworkBuilder.network(for: .mainnet) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Testnet.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Testnet.swift new file mode 100644 index 00000000..9bb44e5e --- /dev/null +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Constants/Testnet.swift @@ -0,0 +1,12 @@ +// +// Testnet.swift +// ZcashLightClientSample +// +// Created by Francisco Gindre on 7/28/21. +// Copyright © 2021 Electric Coin Company. All rights reserved. +// + +import Foundation +import ZcashLightClientKit + +let ZCASH_NETWORK = ZcashNetworkBuilder.network(for: .testnet) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift index 3b950ed4..2e184714 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift @@ -13,17 +13,15 @@ struct DemoAppConfig { static var host = ZcashSDK.isMainnet ? "lightwalletd.electriccoin.co" : "lightwalletd.testnet.electriccoin.co" static var port: Int = 9067 static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 935000 : 1386000 - static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet + static var seed = try! Mnemonic.deterministicSeedBytes(from: "live combine flight accident slow soda mind bright absent bid hen shy decade biology amazing mix enlist ensure biology rhythm snap duty soap armor") static var address: String { "\(host):\(port)" } - static var processorConfig: CompactBlockProcessor.Configuration { - var config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL()) - config.walletBirthday = self.birthdayHeight - return config - } + static var processorConfig: CompactBlockProcessor.Configuration = { + CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), walletBirthday: Self.birthdayHeight, network: ZCASH_NETWORK) + }() static var endpoint: LightWalletEndpoint { return LightWalletEndpoint(address: self.host, port: self.port, secure: true) @@ -31,7 +29,13 @@ struct DemoAppConfig { } -enum ZcashNetwork { - case mainNet - case testNet +extension ZcashSDK { + static var isMainnet: Bool { + switch ZCASH_NETWORK.networkType { + case .mainnet: + return true + case .testnet: + return false + } + } } diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Derivation Tool/DerivationToolViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Derivation Tool/DerivationToolViewController.swift index e0f9925e..48dc7420 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Derivation Tool/DerivationToolViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Derivation Tool/DerivationToolViewController.swift @@ -81,19 +81,19 @@ class DerivationToolViewController: UIViewController { } func deriveFrom(seedPhrase: String) throws { - let seedBytes = try Mnemonic.deterministicSeedBytes(from: seedPhrase) - guard let spendingKey = try DerivationTool.default.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else { + let derivationTool = DerivationTool(networkType: ZCASH_NETWORK.networkType) + guard let spendingKey = try derivationTool.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else { throw DerivationErrors.couldNotDeriveSpendingKeys(underlyingError: DerivationErrors.unknown) } - guard let viewingKey = try DerivationTool.default.deriveViewingKeys(seed: seedBytes, numberOfAccounts: 1).first else { + guard let viewingKey = try derivationTool.deriveViewingKeys(seed: seedBytes, numberOfAccounts: 1).first else { throw DerivationErrors.couldNotDeriveViewingKeys(underlyingError: DerivationErrors.unknown) } - let shieldedAddress = try DerivationTool.default.deriveShieldedAddress(viewingKey: viewingKey) + let shieldedAddress = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey) - let transparentAddress = try DerivationTool.default.deriveTransparentAddress(seed: seedBytes) + let transparentAddress = try derivationTool.deriveTransparentAddress(seed: seedBytes) updateLabels(spendingKey: spendingKey, diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Get Address/GetAddressViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Get Address/GetAddressViewController.swift index 6d5137cd..25478855 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Get Address/GetAddressViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Get Address/GetAddressViewController.swift @@ -15,11 +15,11 @@ class GetAddressViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - + let derivationTool = DerivationTool(networkType: ZCASH_NETWORK.networkType) // Do any additional setup after loading the view. - zAddressLabel.text = (try? DerivationTool.default.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)) ?? "No Addresses found" - tAddressLabel.text = (try? DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)) ?? "could not derive t-address" + zAddressLabel.text = (try? derivationTool.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)) ?? "No Addresses found" + tAddressLabel.text = (try? derivationTool.deriveTransparentAddress(seed: DemoAppConfig.seed)) ?? "could not derive t-address" spendingKeyLabel.text = SampleStorage.shared.privateKey ?? "No Spending Key found" zAddressLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(addressTapped(_:)))) zAddressLabel.isUserInteractionEnabled = true @@ -60,7 +60,7 @@ class GetAddressViewController: UIViewController { @IBAction func addressTapped(_ gesture: UIGestureRecognizer) { loggerProxy.event("copied to clipboard") - UIPasteboard.general.string = try? DerivationTool.default.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0) + UIPasteboard.general.string = try? DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0) let alert = UIAlertController(title: "", message: "Address Copied to clipboard", preferredStyle: UIAlertController.Style.alert) alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)) self.present(alert, animated: true, completion: nil) @@ -68,7 +68,7 @@ class GetAddressViewController: UIViewController { @IBAction func tAddressTapped(_ gesture: UIGestureRecognizer) { loggerProxy.event("copied to clipboard") - UIPasteboard.general.string = try? DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed) + UIPasteboard.general.string = try? DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveTransparentAddress(seed: DemoAppConfig.seed) let alert = UIAlertController(title: "", message: "Address Copied to clipboard", preferredStyle: UIAlertController.Style.alert) alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)) self.present(alert, animated: true, completion: nil) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift index 31c40eac..d9276eaa 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift @@ -26,10 +26,10 @@ class GetUTXOsViewController: UIViewController { } func updateUI() { - let tAddress = try! DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed) + let tAddress = try! DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveTransparentAddress(seed: DemoAppConfig.seed) self.transparentAddressLabel.text = tAddress - let balance = try! AppDelegate.shared.sharedSynchronizer.getTransparentBalance(address: tAddress) + let balance = try! AppDelegate.shared.sharedSynchronizer.getTransparentBalance(accountIndex: 0) self.totalBalanceLabel.text = String(balance.total.asHumanReadableZecBalance()) self.verifiedBalanceLabel.text = String(balance.verified.asHumanReadableZecBalance()) @@ -38,9 +38,10 @@ class GetUTXOsViewController: UIViewController { @IBAction func shieldFunds(_ sender: Any) { do { let seed = DemoAppConfig.seed - let sk = try DerivationTool.default.deriveSpendingKeys(seed: seed, numberOfAccounts: 1).first! + let derivationTool = DerivationTool(networkType: ZCASH_NETWORK.networkType) + let sk = try derivationTool.deriveSpendingKeys(seed: seed, numberOfAccounts: 1).first! - let tsk = try DerivationTool.default.deriveTransparentPrivateKey(seed: seed) + let tsk = try derivationTool.deriveTransparentPrivateKey(seed: seed) KRProgressHUD.showMessage("🛡 Shielding 🛡") AppDelegate.shared.sharedSynchronizer.shieldFunds(spendingKey: sk, transparentSecretKey: tsk, memo: "shielding is fun!", from: 0) { (result) in DispatchQueue.main.async { diff --git a/ZcashLightClientKit/Initializer.swift b/ZcashLightClientKit/Initializer.swift index 9f8c44fb..487c4897 100644 --- a/ZcashLightClientKit/Initializer.swift +++ b/ZcashLightClientKit/Initializer.swift @@ -160,7 +160,7 @@ public class Initializer { self.storage = storage self.downloader = CompactBlockDownloader(service: service, storage: storage) self.viewingKeys = viewingKeys - self.walletBirthday = WalletBirthday.birthday(with: walletBirthday) + self.walletBirthday = WalletBirthday.birthday(with: walletBirthday, network: network) self.network = network } diff --git a/ZcashLightClientKitTests/BlockScanOperationTests.swift b/ZcashLightClientKitTests/BlockScanOperationTests.swift index 19e97bab..100de753 100644 --- a/ZcashLightClientKitTests/BlockScanOperationTests.swift +++ b/ZcashLightClientKitTests/BlockScanOperationTests.swift @@ -20,7 +20,7 @@ class BlockScanOperationTests: XCTestCase { extpub: "02075a7f5f7507d64022dad5954849f216b0f1b09b2d588be663d8e7faeb5aaf61") - var walletBirthDay = WalletBirthday.birthday(with: 1386000) + var walletBirthDay = WalletBirthday.birthday(with: 1386000, network: ZcashNetworkBuilder.network(for: .testnet)) var network = ZcashNetworkBuilder.network(for: .testnet) var blockRepository: BlockRepository! diff --git a/ZcashLightClientKitTests/ReOrgTests.swift b/ZcashLightClientKitTests/ReOrgTests.swift index 3c6e6215..71e8bd73 100644 --- a/ZcashLightClientKitTests/ReOrgTests.swift +++ b/ZcashLightClientKitTests/ReOrgTests.swift @@ -77,7 +77,7 @@ class ReOrgTests: XCTestCase { let mockLatestHeight = BlockHeight(663200) let targetLatestHeight = BlockHeight(663202) let reOrgHeight = BlockHeight(663195) - let walletBirthday = WalletBirthday.birthday(with: 663150).height + let walletBirthday = WalletBirthday.birthday(with: 663150, network: network).height try basicReOrgTest(baseDataset: .beforeReOrg, reorgDataset: .afterSmallReorg, @@ -91,7 +91,7 @@ class ReOrgTests: XCTestCase { let mockLatestHeight = BlockHeight(663200) let targetLatestHeight = BlockHeight(663250) let reOrgHeight = BlockHeight(663180) - let walletBirthday = WalletBirthday.birthday(with: BlockHeight(663150)).height + let walletBirthday = WalletBirthday.birthday(with: BlockHeight(663150), network: network).height try basicReOrgTest(baseDataset: .beforeReOrg, reorgDataset: .afterLargeReorg, diff --git a/ZcashLightClientKitTests/TestCoordinator.swift b/ZcashLightClientKitTests/TestCoordinator.swift index 6bcc93f2..95c19e9b 100644 --- a/ZcashLightClientKitTests/TestCoordinator.swift +++ b/ZcashLightClientKitTests/TestCoordinator.swift @@ -93,7 +93,7 @@ class TestCoordinator { outputParamsURL: try __outputParamsURL(), spendingKey: spendingKey, unifiedViewingKey: unifiedViewingKey, - walletBirthday: WalletBirthday.birthday(with: birthday), + walletBirthday: WalletBirthday.birthday(with: birthday, network: network), network: network, loggerProxy: SampleLogger(logLevel: .debug)) diff --git a/ZcashLightClientKitTests/TransactionEnhancementTests.swift b/ZcashLightClientKitTests/TransactionEnhancementTests.swift index d5334e87..364439fd 100644 --- a/ZcashLightClientKitTests/TransactionEnhancementTests.swift +++ b/ZcashLightClientKitTests/TransactionEnhancementTests.swift @@ -44,7 +44,7 @@ class TransactionEnhancementTests: XCTestCase { waitExpectation = XCTestExpectation(description: self.description + "waitExpectation") - let birthday = WalletBirthday.birthday(with: walletBirthday) + let birthday = WalletBirthday.birthday(with: walletBirthday, network: network) let config = CompactBlockProcessor.Configuration.standard(for: self.network, walletBirthday: birthday.height) let rustBackend = ZcashRustBackend.self @@ -106,7 +106,7 @@ class TransactionEnhancementTests: XCTestCase { func testBasicEnhacement() throws { let targetLatestHeight = BlockHeight(663250) - let walletBirthday = WalletBirthday.birthday(with: 663151).height + let walletBirthday = WalletBirthday.birthday(with: 663151, network: network).height try basicEnhancementTest(latestHeight: targetLatestHeight, walletBirthday: walletBirthday) } From 6e64b32810b988560c47b333d0739867fc1d6769 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 28 Jul 2021 16:37:05 -0300 Subject: [PATCH 08/17] remove code generation for zcashsdk constants --- Example/ZcashLightClientSample/Podfile | 1 + Example/ZcashLightClientSample/Podfile.lock | 10 +-- .../project.pbxproj | 2 + Scripts/build_librustzcash.sh | 12 +-- Scripts/build_librustzcash_xcode.sh | 23 +----- Scripts/generate_zcashsdk_constants.sh | 42 ---------- Scripts/prepare_zcash_sdk.sh | 19 ----- Scripts/script_commons.sh | 81 +------------------ ZcashLightClientKit.podspec | 12 ++- .../Constants}/WalletBirthday+Constants.swift | 0 .../Constants}/WalletBirthday+mainnet.swift | 0 .../Constants}/WalletBirthday+testnet.swift | 0 .../Constants}/ZcashSDK.swift | 0 13 files changed, 19 insertions(+), 183 deletions(-) delete mode 100644 Scripts/generate_zcashsdk_constants.sh rename {Constants => ZcashLightClientKit/Constants}/WalletBirthday+Constants.swift (100%) rename {Constants => ZcashLightClientKit/Constants}/WalletBirthday+mainnet.swift (100%) rename {Constants => ZcashLightClientKit/Constants}/WalletBirthday+testnet.swift (100%) rename {Constants => ZcashLightClientKit/Constants}/ZcashSDK.swift (100%) diff --git a/Example/ZcashLightClientSample/Podfile b/Example/ZcashLightClientSample/Podfile index ba7baf08..c8be6733 100644 --- a/Example/ZcashLightClientSample/Podfile +++ b/Example/ZcashLightClientSample/Podfile @@ -26,6 +26,7 @@ end target 'ZcashLightClientSample-Mainnet' do inherit! :search_paths use_frameworks! + pod 'MnemonicSwift', '~> 2.0.0' pod "KRProgressHUD" pod 'PaginatedTableView' pod 'NotificationBubbles' diff --git a/Example/ZcashLightClientSample/Podfile.lock b/Example/ZcashLightClientSample/Podfile.lock index 627208dc..2151e31a 100644 --- a/Example/ZcashLightClientSample/Podfile.lock +++ b/Example/ZcashLightClientSample/Podfile.lock @@ -68,13 +68,13 @@ PODS: - SwiftNIOFoundationCompat (< 3, >= 2.19.0) - SwiftNIOTLS (< 3, >= 2.19.0) - SwiftProtobuf (1.16.0) - - ZcashLightClientKit (0.12.0-alpha.10): + - ZcashLightClientKit (0.12.0-alpha.11): - gRPC-Swift (= 1.0.0) - SQLite.swift (~> 0.12.2) - - ZcashLightClientKit/DerivationToolTests (0.12.0-alpha.10): + - ZcashLightClientKit/DerivationToolTests (0.12.0-alpha.11): - gRPC-Swift (= 1.0.0) - SQLite.swift (~> 0.12.2) - - ZcashLightClientKit/Tests (0.12.0-alpha.10): + - ZcashLightClientKit/Tests (0.12.0-alpha.11): - gRPC-Swift (= 1.0.0) - SQLite.swift (~> 0.12.2) @@ -153,8 +153,8 @@ SPEC CHECKSUMS: SwiftNIOTLS: 4f8df225f03393f08e0b47b4d876ae38167f8a27 SwiftNIOTransportServices: 896c9a4ac98698d32aa2feea7657ade219ae80bb SwiftProtobuf: 4e16842b83c6fda06b10fac50d73b3f1fce8ab7b - ZcashLightClientKit: cbd3df0c6736cbcb228b5cdc39baad40346ffba3 + ZcashLightClientKit: 41e62975ad5dac49dd5f9430927e621fa7ec6a39 -PODFILE CHECKSUM: 315a67042788e1eccd948b2b8fe580222fd83cd9 +PODFILE CHECKSUM: fccab5d0eba64105a75095e72799a71df191b5a4 COCOAPODS: 1.10.1 diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj index de06d5a1..4652b39d 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj +++ b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 0D756A94236C761E009B041B /* GetAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D756A93236C761E009B041B /* GetAddressViewController.swift */; }; 0D76121726B1D5F5001CA417 /* Mainnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D76121526B1D5ED001CA417 /* Mainnet.swift */; }; 0D76121926B1D66D001CA417 /* Testnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D76121826B1D66D001CA417 /* Testnet.swift */; }; + 0D76121A26B1E8F6001CA417 /* SampleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D49A18B241698A800CC0649 /* SampleLogger.swift */; }; 0D7A4A83236CCD88001F4DD8 /* SyncBlocksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */; }; 0D7C85E523AD5A9B006878FC /* SampleStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7C85E423AD5A9B006878FC /* SampleStorage.swift */; }; 0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD3DC6238D88B100DD3EC4 /* GetBalanceViewController.swift */; }; @@ -687,6 +688,7 @@ 0D8BB45C23B1DA0700D5E2A1 /* SampleStorage.swift in Sources */, 0D8BB45D23B1DA0700D5E2A1 /* TransactionsDataSource.swift in Sources */, 0D8BB45E23B1DA0700D5E2A1 /* PaginatedTransactionsViewController.swift in Sources */, + 0D76121A26B1E8F6001CA417 /* SampleLogger.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Scripts/build_librustzcash.sh b/Scripts/build_librustzcash.sh index 6ba84b9b..c993360e 100644 --- a/Scripts/build_librustzcash.sh +++ b/Scripts/build_librustzcash.sh @@ -3,16 +3,6 @@ BASEPATH="${PWD}" TARGET_DIR="target" -FEATURE_FLAGS="--features=mainnet" -NETWORK_TYPE="TESTNET" -FLAVOR_FOLDER="Testnet" - - -if [ $1 = "--mainnet" ]; then - FEATURE_FLAGS="--features=mainnet" - NETWORK_TYPE="MAINNET" - FLAVOR_FOLDER="Mainnet" -fi LIB_PATH="ZcashLightClientKit/$FLAVOR_FOLDER/zcashlc" echo "++++ Building librustzcash $NETWORK_TYPE library ++++" @@ -22,7 +12,7 @@ if [ -f $TARGET_DIR ]; then rm -rf $TARGET_DIR fi -cargo build --release $FEATURE_FLAGS && cargo lipo --release +cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --release if [ -f $LIB_PATH ]; then diff --git a/Scripts/build_librustzcash_xcode.sh b/Scripts/build_librustzcash_xcode.sh index 4c928e2c..bedd21fa 100755 --- a/Scripts/build_librustzcash_xcode.sh +++ b/Scripts/build_librustzcash_xcode.sh @@ -7,31 +7,12 @@ if [ ! -f $SCRIPT_COMMONS ]; then fi source $SCRIPT_COMMONS -if [ "$1" = "--testing" ]; then - export ZCASH_NETWORK_ENVIRONMENT=$ZCASH_TESTNET - echo "Testing flag detected, forcing $ZCASH_TESTNET" -fi - -check_environment - if [ "$ACTION" = "clean" ]; then echo "CLEAN DETECTED" clean exit 0 fi -if [ existing_build_mismatch = true ]; then - # clean - echo "Build mismatch. You previously built a different network environment. It appears that your build could be inconsistent if proceeding. Please clean your Pods/ folder and clean your build before running your next build." - exit 1 -fi - -# if is_mainnet; then -# FEATURE_FLAGS="--features=mainnet" -# else -# FEATURE_FLAGS="--features=testnet" -# fi - echo "Building Rust backend" echo "" echo "platform name" @@ -45,7 +26,7 @@ fi echo "fix 'permission denied issue'" chmod -R +w ${PODS_TARGET_SRCROOT} -echo "cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release" +echo "cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --targets $ZCASH_ACTIVE_ARCHITECTURE --release" if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then # Assume we're in Xcode, which means we're probably cross-compiling. # In this case, we need to add an extra library search path for build scripts and proc-macros, @@ -55,7 +36,7 @@ if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then export LIBRARY_PATH="${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}" fi if [ ! -f ${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME} ]; then - cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release + cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --targets $ZCASH_ACTIVE_ARCHITECTURE --release persist_environment fi diff --git a/Scripts/generate_zcashsdk_constants.sh b/Scripts/generate_zcashsdk_constants.sh deleted file mode 100644 index 2887f63d..00000000 --- a/Scripts/generate_zcashsdk_constants.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -SCRIPT_COMMONS="${PODS_TARGET_SRCROOT}/Scripts/script_commons.sh" -if [ -f $SCRIPT_COMMONS ]; then - source $SCRIPT_COMMONS -else - echo "Failed to load $SCRIPT_COMMONS" - exit 1 -fi - -if ! hash sourcery; then - echo "Sourcery not found on your PATH" - exit 1 -fi -export ZCASH_SDK_TEMPLATE="${ZCASH_SRC_PATH}/Stencil" - -echo "export ZCASH_SRC_PATH=${ZCASH_SRC_PATH}" - -check_environment - -if is_mainnet; then - SOURCERY_ARGS="--args ismainnet=true" -else - SOURCERY_ARGS="--args ismainnet=false" -fi - -if [ -d $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]; then - echo "clean up before generating new files: $ZCASH_SDK_GENERATED_SOURCES_FOLDER" - echo "rm -rf ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/*.generated*" - rm -rf "${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/*.generated*" -else - echo "mkdir -p -v $ZCASH_SDK_GENERATED_SOURCES_FOLDER" - mkdir -p -v ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} -fi - -echo "Set +w to ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}" -chmod -R +w ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} - -echo "sourcery --prune --verbose --templates ${ZCASH_SDK_TEMPLATE} --sources ${ZCASH_SRC_PATH} --output ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} $SOURCERY_ARGS " - -sourcery --prune --verbose --templates ${ZCASH_SDK_TEMPLATE} --sources ${ZCASH_SRC_PATH} --output ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} $SOURCERY_ARGS - diff --git a/Scripts/prepare_zcash_sdk.sh b/Scripts/prepare_zcash_sdk.sh index f4cb7bcc..21c6ef3b 100644 --- a/Scripts/prepare_zcash_sdk.sh +++ b/Scripts/prepare_zcash_sdk.sh @@ -26,22 +26,3 @@ echo "************************************************************************** echo " touch ${ZCASH_POD_ROOT}/zcashlc/zcashlc.h" echo "***************************************************************************" touch ${ZCASH_POD_SRCROOT}/zcashlc/zcashlc.h - -echo "make ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} folder" -mkdir -p ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} - -echo "**********************************************" -echo "* create empty ZcashSDK.generated.swift file *" -echo "**********************************************" -echo "" - -echo "touch ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/ZcashSDK.generated.swift" -touch ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/ZcashSDK.generated.swift - -echo "****************************************************************" -echo "* create empty WalletBirthday+saplingtree.generated.swift file *" -echo "****************************************************************" -echo "" - -echo "touch $ZCASH_SDK_GENERATED_SOURCES_FOLDER/WalletBirthday+saplingtree.generated.swift" -touch $ZCASH_SDK_GENERATED_SOURCES_FOLDER/WalletBirthday+saplingtree.generated.swift \ No newline at end of file diff --git a/Scripts/script_commons.sh b/Scripts/script_commons.sh index 9cb2cf45..1f88afd7 100644 --- a/Scripts/script_commons.sh +++ b/Scripts/script_commons.sh @@ -4,14 +4,12 @@ export PATH="$HOME/.cargo/bin:$PATH" export RUST_LIB_PATH="${PODS_TARGET_SRCROOT}/lib" export ZCASH_POD_SCRIPTS="${PODS_TARGET_SRCROOT}/Scripts" export ZCASH_LIB_RUST_BUILD_PATH="${PODS_TARGET_SRCROOT}/target" -export ZCASH_BUILD_TYPE_MAINNET_FLAG=".mainnet_build" -export ZCASH_BUILD_TYPE_TESTNET_FLAG=".testnet_build" + export ZCASH_LIB_RUST_NAME="libzcashlc.a" -export ZCASH_TESTNET="TESTNET" -export ZCASH_MAINNET="MAINNET" + export ZCASH_SRC_PATH="${PODS_TARGET_SRCROOT}/ZcashLightClientKit" export ZCASH_SDK_RUST_LIB_PATH="${ZCASH_SRC_PATH}/zcashlc" -export ZCASH_SDK_GENERATED_SOURCES_FOLDER="${ZCASH_SRC_PATH}/Generated" + function clean { echo "CLEAN DETECTED" @@ -23,76 +21,3 @@ function clean { rm -rf "${ZCASH_LIB_RUST_BUILD_PATH}" fi } - -function check_environment { - - if [[ $ZCASH_NETWORK_ENVIRONMENT != $ZCASH_MAINNET ]] && [[ $ZCASH_NETWORK_ENVIRONMENT != $ZCASH_TESTNET ]]; then - echo "No network environment. Set ZCASH_NETWORK_ENVIRONMENT to $ZCASH_MAINNET or $ZCASH_TESTNET" - exit 1 - fi - - if [[ ! $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]]; then - echo "No 'ZCASH_SDK_GENERATED_SOURCES_FOLDER' variable present. Delete Pods/ and run 'pod install --verbose'" - exit 1 - fi - - echo "**** Building for $ZCASH_NETWORK_ENVIRONMENT environment ****" -} - -function is_mainnet { - if [[ $ZCASH_NETWORK_ENVIRONMENT = $ZCASH_MAINNET ]]; then - true - else - false - fi -} -# Return success (0) if there is a build mismatch, else failure (1) if no mismatch. -function existing_build_mismatch { - #if build exists check that corresponds to the current network environment - if [! -d $ZCASH_LIB_RUST_BUILD_PATH ]; then - return 1 - fi - - # there's a MAINNET Flag and MAINNET ENVIRONMENT - if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_MAINNET" ]] - then - return 1 # no build mismatch - fi - - if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]] - then - warn_mismatch $ZCASH_MAINNET $ZCASH_NETWORK_ENVIRONMENT - return 0 # build mismatch in place - fi - - # There's a TESTNET flag and we are on TESTNET ENVIRONMENT - if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]] - then - return 1 # no build mismatch - fi - # There's a TESTNET flag and we are on a MAINNET Environment - if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_MAINNET" ]] - then - warn_mismatch $ZCASH_TESTNET $ZCASH_NETWORK_ENVIRONMENT - return 0 # build mismatch in place - fi - echo "=== NO BUILD FLAG, CHECKING ENVIRONMENT ===" - check_environment - return 1 # no build mismatch -} - -function warn_mismatch { - echo "*** WARNING: *** build mismatch. Found ${0} but environment is ${1}" -} - -function persist_environment { - check_environment - - if [ $ZCASH_NETWORK_ENVIRONMENT = "$ZCASH_MAINNET" ] - then - touch $ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG - elif [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]] - then - touch $ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG - fi -} diff --git a/ZcashLightClientKit.podspec b/ZcashLightClientKit.podspec index f4f73cf9..0428453e 100644 --- a/ZcashLightClientKit.podspec +++ b/ZcashLightClientKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'ZcashLightClientKit' - s.version = '0.12.0-alpha.10' + s.version = '0.12.0-alpha.11' s.summary = 'Zcash Light Client wallet SDK for iOS' s.description = <<-DESC @@ -30,11 +30,9 @@ Pod::Spec.new do |s| s.script_phase = { :name => 'Build generate constants and build librustzcash', - :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_zcashsdk_constants.sh && sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh', + :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh', :execution_position => :before_compile, - :output_files => [ - '${PODS_TARGET_SRCROOT}/ZcashLightClientKit/Generated/WalletBirthday+saplingtree.generated.swift', - '${PODS_TARGET_SRCROOT}/ZcashLightClientKit/Generated/ZcashSDK.generated.swift'] + } s.test_spec 'Tests' do | test_spec | @@ -42,7 +40,7 @@ Pod::Spec.new do |s| test_spec.ios.resources = 'ZcashLightClientKitTests/**/*.{db,params}' test_spec.script_phase = { :name => 'Build generate constants and build librustzcash', - :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh --testing', + :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh', :execution_position => :before_compile } test_spec.dependency 'gRPC-Swift', '= 1.0.0' @@ -53,7 +51,7 @@ Pod::Spec.new do |s| test_spec.source_files = 'DerivationToolTests/**/*.{swift}' test_spec.script_phase = { :name => 'Build generate constants and build librustzcash', - :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh --testing', + :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh', :execution_position => :before_compile } test_spec.dependency 'gRPC-Swift', '= 1.0.0' diff --git a/Constants/WalletBirthday+Constants.swift b/ZcashLightClientKit/Constants/WalletBirthday+Constants.swift similarity index 100% rename from Constants/WalletBirthday+Constants.swift rename to ZcashLightClientKit/Constants/WalletBirthday+Constants.swift diff --git a/Constants/WalletBirthday+mainnet.swift b/ZcashLightClientKit/Constants/WalletBirthday+mainnet.swift similarity index 100% rename from Constants/WalletBirthday+mainnet.swift rename to ZcashLightClientKit/Constants/WalletBirthday+mainnet.swift diff --git a/Constants/WalletBirthday+testnet.swift b/ZcashLightClientKit/Constants/WalletBirthday+testnet.swift similarity index 100% rename from Constants/WalletBirthday+testnet.swift rename to ZcashLightClientKit/Constants/WalletBirthday+testnet.swift diff --git a/Constants/ZcashSDK.swift b/ZcashLightClientKit/Constants/ZcashSDK.swift similarity index 100% rename from Constants/ZcashSDK.swift rename to ZcashLightClientKit/Constants/ZcashSDK.swift From 740eae13d82e00c3a6e53abf2717f537eeeb6bd9 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 28 Jul 2021 17:02:49 -0300 Subject: [PATCH 09/17] swift lint --- DerivationToolTests/DerivatioToolTestnetTests.swift | 1 + .../Block/DatabaseStorage/DatabaseMigrationManager.swift | 1 - .../Block/Processor/CompactBlockDownloadOperation.swift | 2 +- .../Block/Processor/CompactBlockProcessor.swift | 1 - ZcashLightClientKit/Constants/ZcashSDK.swift | 3 --- ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift | 4 ---- ZcashLightClientKit/Synchronizer.swift | 1 - ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift | 1 - 8 files changed, 2 insertions(+), 12 deletions(-) diff --git a/DerivationToolTests/DerivatioToolTestnetTests.swift b/DerivationToolTests/DerivatioToolTestnetTests.swift index 21b4f8ff..0dc07769 100644 --- a/DerivationToolTests/DerivatioToolTestnetTests.swift +++ b/DerivationToolTests/DerivatioToolTestnetTests.swift @@ -4,6 +4,7 @@ // // Created by Francisco Gindre on 7/26/21. // +// swift-format-ignore-file import XCTest @testable import ZcashLightClientKit diff --git a/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift b/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift index 9a8b36df..e1519c01 100644 --- a/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift +++ b/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift @@ -179,7 +179,6 @@ class MigrationManager { return } - let derivationTool = DerivationTool(networkType: self.network) let uvks = try derivationTool.deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: accounts.count) diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift index d553bb4b..a67c1508 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift @@ -181,7 +181,7 @@ class CompactBlockBatchDownloadOperation: ZcashOperation { let localDownloadedHeight = try self.storage.latestHeight() - if localDownloadedHeight != BlockHeight.empty() && localDownloadedHeight > startHeight { + if localDownloadedHeight != BlockHeight.empty() && localDownloadedHeight > startHeight { LoggerProxy.warn("provided startHeight (\(startHeight)) differs from local latest downloaded height (\(localDownloadedHeight))") startHeight = localDownloadedHeight + 1 } diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index c3136caf..c4c8ee64 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -1334,4 +1334,3 @@ extension CompactBlockProcessor { } } } - diff --git a/ZcashLightClientKit/Constants/ZcashSDK.swift b/ZcashLightClientKit/Constants/ZcashSDK.swift index d0e0e7f9..7a396653 100644 --- a/ZcashLightClientKit/Constants/ZcashSDK.swift +++ b/ZcashLightClientKit/Constants/ZcashSDK.swift @@ -110,7 +110,6 @@ public class ZcashSDK { */ public static var DEFAULT_STALE_TOLERANCE: Int = 10 - /** Default Name for LibRustZcash data.db */ @@ -168,7 +167,6 @@ public protocol NetworkConstants { for librustzcash not figuring out the tx fee from the tx itself. */ static var FEE_CHANGE_HEIGHT: BlockHeight { get } - static func defaultFee(for height: BlockHeight) -> Int64 @@ -208,7 +206,6 @@ public class ZcashSDKMainnetConstants: NetworkConstants { public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_" - public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_077_550 } diff --git a/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift b/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift index 57839821..34549c7a 100644 --- a/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift +++ b/ZcashLightClientKit/Extensions/ZcashSDK+extensions.swift @@ -7,9 +7,6 @@ import Foundation - - - public typealias ConsensusBranchID = Int32 public extension ConsensusBranchID { @@ -23,7 +20,6 @@ public extension ConsensusBranchID { } } - extension NetworkType { init?(_ string: String) { switch string { diff --git a/ZcashLightClientKit/Synchronizer.swift b/ZcashLightClientKit/Synchronizer.swift index bb762d38..fc9214e4 100644 --- a/ZcashLightClientKit/Synchronizer.swift +++ b/ZcashLightClientKit/Synchronizer.swift @@ -394,7 +394,6 @@ extension SyncStatus { } } - extension SyncStatus { init(_ blockProcessorProgress: CompactBlockProgress) { switch blockProcessorProgress { diff --git a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift index 5f4b10d1..751ea94c 100644 --- a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift +++ b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift @@ -848,4 +848,3 @@ fileprivate struct NullProgress: BlockProgressReporting { 0 } } - From a5c67c659315792019066cdf4524ee00681e857e Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 28 Jul 2021 17:03:09 -0300 Subject: [PATCH 10/17] remove ZCASH_NETWORK_ENVIRONMENT --- Example/ZcashLightClientSample/Podfile | 4 +- Example/ZcashLightClientSample/Podfile.lock | 2 +- README.md | 60 +++------------------ 3 files changed, 8 insertions(+), 58 deletions(-) diff --git a/Example/ZcashLightClientSample/Podfile b/Example/ZcashLightClientSample/Podfile index c8be6733..f2f8a4da 100644 --- a/Example/ZcashLightClientSample/Podfile +++ b/Example/ZcashLightClientSample/Podfile @@ -42,9 +42,7 @@ post_install do |installer| if target.name == 'ZcashLightClientKit-Unit-Tests' config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "13.0" end - if target.name == 'ZcashLightClientKit' - config.build_settings['ZCASH_NETWORK_ENVIRONMENT'] = ENV["ZCASH_NETWORK_ENVIRONMENT"] - end + config.build_settings['ENABLE_BITCODE'] = 'NO' end end diff --git a/Example/ZcashLightClientSample/Podfile.lock b/Example/ZcashLightClientSample/Podfile.lock index 2151e31a..8a7d4da9 100644 --- a/Example/ZcashLightClientSample/Podfile.lock +++ b/Example/ZcashLightClientSample/Podfile.lock @@ -155,6 +155,6 @@ SPEC CHECKSUMS: SwiftProtobuf: 4e16842b83c6fda06b10fac50d73b3f1fce8ab7b ZcashLightClientKit: 41e62975ad5dac49dd5f9430927e621fa7ec6a39 -PODFILE CHECKSUM: fccab5d0eba64105a75095e72799a71df191b5a4 +PODFILE CHECKSUM: 0e90dc69ac4c19fd97c0ce4835ece810d79ade23 COCOAPODS: 1.10.1 diff --git a/README.md b/README.md index 853cb9cf..f374fe51 100644 --- a/README.md +++ b/README.md @@ -43,16 +43,13 @@ use_frameworks! pod 'ZcashLightClientKit' ```` -### Set Testnet or Mainnet environment -Before building, make sure that your environment has the variable `ZCASH_NETWORK_ENVIRONMENT` set to `MAINNET` or `TESTNET`. - ### Custom build phases warning When running `pod install` you will see this warning upon success: ```` bash [!] ZcashLightClientKit has added 2 script phases. Please inspect before executing a build. See `https://guides.cocoapods.org/syntax/podspec.html#script_phases` for more information. ```` -Integrating Rust code with Swift code and delivering it in a consistent and (build) reproducible way, is hard. We've taken the lead to get that burden off your shoulders as much as possible by leveraging the `prepare_command` and `script_phases` features from Cocoapods to carefully generate the `TESTNET` and `MAINNET` builds as simple and less error prone as we could think it could be. Which started as some simple vanilla scripts, ended up being some kind of "Build System" on its own. Nothing is written on stone, and we accept collaborations and improvements in this matter too. +Integrating Rust code with Swift code and delivering it in a consistent and (build) reproducible way, is hard. We've taken the lead to get that burden off your shoulders as much as possible by leveraging the `prepare_command` and `script_phases` features from Cocoapods to carefully generate a build for the Rust layer. ## Build system @@ -68,8 +65,7 @@ ZcashLightClientKit needs files to be present at pod installation time, but that - `${ZCASH_POD_SRCROOT}/zcashlc/libzcashlc.a` this is the librustzcash build .a file itself - `lib/libzcashlc.a` (as vendored library that will be added as an asset by xcodeproj) -- `ZcashSDK.generated.swift` which contains sensitive values for the SDK that change depending on the network environment we are building for -- `WalletBirthday+saplingtree.generated.swift` helper functions to import existing wallets + **2. Build Phase** @@ -78,37 +74,17 @@ The build Phase scripts executes within the Xcode Build Step and has all the kno ```` ruby s.script_phase = { :name => 'Build generate constants and build librustzcash', - :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_zcashsdk_constants.sh && sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh', + :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh', :execution_position => :before_compile } ```` This step will generate files needed on the next steps and build the librustzcash with Xcode but *not using cargo's built-in Xcode integration* -**a. Generating ZcashSDK constants** - -To run this you need `Sourcery`. We use `Stencil` templates to create these files based on the `ZCASH_NETWORK_ENVIRONMENT` value of your choice. You can either integrate sourcery with cocoapods or as part of your environment. - -All generated files will be located in the Pods source root within the `Generated` folder. `ZCASH_SDK_GENERATED_SOURCES_FOLDER` represents that path in the build system. - -**b. Building librustzcash and integrating it to the pod structure** +** Building librustzcash and integrating it to the pod structure** Where the magic happens. Here we will make sure that everything is set up properly to start building librustzcash. When on mainnet, the build will append a parameter to include mainnet features. - -**Safeguards points**: -if it appears that you are about to build something smelly, we will let you know. Combining testnet and mainnet values and artifacts and viceversa leads to unstable builds and may cause loss of funds if ran on production. -``` -if [ existing_build_mismatch = true ]; then - # clean - echo "build mismatch. You previously build a Different network environment. It appears that your build could be inconsistent if proceeding. Please clean your Pods/ folder and clean your build before running your next build." - exit 1 -fi -``` -**3. Xcode clean integration** - -When performing a clean, we will clean the rust build folders. - ### Scripts On the Scripts folder you will find the following files: @@ -118,12 +94,11 @@ On the Scripts folder you will find the following files: |-/generate_test_constants.sh |-/build_librustzcash_xcode.sh |-/build_librustzcash.sh - |-/generate_zcashsdk_constants.sh |-/script_commons.sh ```` #### prepare_zcash_sdk.sh -This script is run by the Cocoapods 'preapare_command'. +This script is run by the Cocoapods 'prepare_command'. ```` Ruby s.prepare_command = <<-CMD @@ -194,22 +169,7 @@ We don't like reinventing the wheel, so we gently borrowed swift lint rules from ## Troubleshooting -### No network environment.... -if you see this message when building: -```No network environment. Set ZCASH_NETWORK_ENVIRONMENT to MAINNET or TESTNET``` -make sure your dev environment has this variable set before the build starts. *DO NOT CHANGE IT DURING THE BUILD PROCESS*. - -If the variable was properly set *after* you've seen this message, you will need to either a) set it manually on the pod's target or b) doing a clean pod install and subsequent build. - -#### a) setting the flag manually -1. on your workspace, select the Pods project -2. on the Targets pane, select ZcashLightClientKit -3. go to build settings -4. scroll down to see ZCASH_NETWORK_ENVIRONMENT and complete with TESTNET or MAINNET - -![how to complete network environment manually](docs/images/complete_environment_manually.png) - -#### b) clean pod install +#### clean pod install it's not necessary to delete the whole Pods/ directory and download all of your dependencies again 1. on your project root, locate the `Pods/` directory 2. remove ZcashLightClientKit from it @@ -228,14 +188,6 @@ if you get a build error similar to ```_function_name referenced from...``` 3. run `pod install` 4. build -### ZcashLightClientKitSample missing .params -ZcashLightClientKit has an external dependency on 2 files containing Sapling parameters. Although you can provide those files as you seem fit, the sample app requires them on the main bundle. - -You can download these files from https://z.cash/downloads/sapling-spend.params -and https://z.cash/downloads/sapling-output.params and then move them to the correct folder, which is specified on the error itself. - -![how to fix missing params files](docs/images/output_params_error.png) - ### can't find crate for ... target may not be installed This error could be a side effect of having more then one rust toolchain installed. If you worked with ZcashLightClientKit 0.6.6 or below you might have had to set the compiler to 1.40.0 which can cause this compilation error to happen. From 25f97752bb2c04bdfbb1d6d03ff11296e8985b95 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Wed, 28 Jul 2021 19:25:47 -0300 Subject: [PATCH 11/17] fix tests --- .../CompactBlockDownloadOperation.swift | 6 +- .../BlockBatchValidationTests.swift | 14 ++--- .../BlockDownloaderTests.swift | 2 +- .../BlockScanOperationTests.swift | 4 +- .../BlockStreamingTest.swift | 62 ++++--------------- .../CompactBlockProcessorTests.swift | 23 +++++-- .../CompactBlockReorgTests.swift | 22 ++++++- .../DarksideSanityCheckTests.swift | 5 +- .../DownloadOperationTests.swift | 2 +- .../LightWalletServiceTests.swift | 2 +- .../NetworkUpgradeTests.swift | 2 +- ZcashLightClientKitTests/ReOrgTests.swift | 6 +- .../RewindRescanTests.swift | 2 +- .../TransactionEnhancementTests.swift | 12 ++-- .../utils/FakeService.swift | 6 +- .../utils/Tests+Utils.swift | 4 ++ 16 files changed, 89 insertions(+), 85 deletions(-) diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift index a67c1508..0c63ec17 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift @@ -103,7 +103,11 @@ class CompactBlockStreamDownloadOperation: ZcashOperation { self?.fail(error: e) } case .failure(let e): - self?.fail(error: e) + if case .userCancelled = e { + self?.done = true + } else { + self?.fail(error: e) + } } } handler: {[weak self] block in diff --git a/ZcashLightClientKitTests/BlockBatchValidationTests.swift b/ZcashLightClientKitTests/BlockBatchValidationTests.swift index e2db71e4..4034dabf 100644 --- a/ZcashLightClientKitTests/BlockBatchValidationTests.swift +++ b/ZcashLightClientKitTests/BlockBatchValidationTests.swift @@ -25,7 +25,7 @@ class BlockBatchValidationTests: XCTestCase { func testBranchIdFailure() throws { let network = ZcashNetworkBuilder.network(for: .mainnet) - let service = MockLightWalletService(latestBlockHeight: 1210000) + let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) @@ -65,7 +65,7 @@ class BlockBatchValidationTests: XCTestCase { func testBranchNetworkMismatchFailure() throws { let network = ZcashNetworkBuilder.network(for: .mainnet) - let service = MockLightWalletService(latestBlockHeight: 1210000) + let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) @@ -106,7 +106,7 @@ class BlockBatchValidationTests: XCTestCase { func testBranchNetworkTypeWrongFailure() throws { let network = ZcashNetworkBuilder.network(for: .testnet) - let service = MockLightWalletService(latestBlockHeight: 1210000) + let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) @@ -146,7 +146,7 @@ class BlockBatchValidationTests: XCTestCase { func testSaplingActivationHeightMismatch() throws { let network = ZcashNetworkBuilder.network(for: .mainnet) - let service = MockLightWalletService(latestBlockHeight: 1210000) + let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloader = CompactBlockDownloader(service: service, storage: repository) let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network) @@ -188,7 +188,7 @@ class BlockBatchValidationTests: XCTestCase { let network = ZcashNetworkBuilder.network(for: .mainnet) let expectedLatestHeight = BlockHeight(1210000) - let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight) + let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let expectedStoreLatestHeight = BlockHeight(1220000) let expectedResult = FigureNextBatchOperation.NextState.wait(latestHeight: expectedLatestHeight, latestDownloadHeight: expectedLatestHeight) let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight) @@ -244,7 +244,7 @@ class BlockBatchValidationTests: XCTestCase { func testResultProcessNew() throws { let network = ZcashNetworkBuilder.network(for: .mainnet) let expectedLatestHeight = BlockHeight(1230000) - let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight) + let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let expectedStoreLatestHeight = BlockHeight(1220000) let walletBirthday = BlockHeight(1210000) let expectedResult = FigureNextBatchOperation.NextState.processNewBlocks(range: CompactBlockProcessor.nextBatchBlockRange(latestHeight: expectedLatestHeight, latestDownloadedHeight: expectedStoreLatestHeight, walletBirthday: walletBirthday)) @@ -301,7 +301,7 @@ class BlockBatchValidationTests: XCTestCase { func testResultProcessorFinished() throws { let network = ZcashNetworkBuilder.network(for: .mainnet) let expectedLatestHeight = BlockHeight(1230000) - let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight) + let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)) let expectedStoreLatestHeight = BlockHeight(1230000) let walletBirthday = BlockHeight(1210000) let expectedResult = FigureNextBatchOperation.NextState.finishProcessing(height: expectedStoreLatestHeight) diff --git a/ZcashLightClientKitTests/BlockDownloaderTests.swift b/ZcashLightClientKitTests/BlockDownloaderTests.swift index f4f21bf5..da0ff9e5 100644 --- a/ZcashLightClientKitTests/BlockDownloaderTests.swift +++ b/ZcashLightClientKitTests/BlockDownloaderTests.swift @@ -94,7 +94,7 @@ class BlockDownloaderTests: XCTestCase { } func testFailure() { - let awfulDownloader = CompactBlockDownloader(service: AwfulLightWalletService(latestBlockHeight: self.network.constants.SAPLING_ACTIVATION_HEIGHT + 1000), storage: ZcashConsoleFakeStorage()) + let awfulDownloader = CompactBlockDownloader(service: AwfulLightWalletService(latestBlockHeight: self.network.constants.SAPLING_ACTIVATION_HEIGHT + 1000, service: darksideWalletService), storage: ZcashConsoleFakeStorage()) let expect = XCTestExpectation(description: self.description) expect.expectedFulfillmentCount = 1 diff --git a/ZcashLightClientKitTests/BlockScanOperationTests.swift b/ZcashLightClientKitTests/BlockScanOperationTests.swift index 100de753..fdc74bdb 100644 --- a/ZcashLightClientKitTests/BlockScanOperationTests.swift +++ b/ZcashLightClientKitTests/BlockScanOperationTests.swift @@ -53,7 +53,7 @@ class BlockScanOperationTests: XCTestCase { let scanStartedExpect = XCTestExpectation(description: self.description + "scan started") let scanExpect = XCTestExpectation(description: self.description + "scan") let latestScannedBlockExpect = XCTestExpectation(description: self.description + "latestScannedHeight") - let service = LightWalletGRPCService(endpoint: LightWalletEndpoint(address: "lightwalletd.electriccoin.co", port: 9067)) + let service = LightWalletGRPCService(endpoint: LightWalletEndpoint(address: "lightwalletd.testnet.electriccoin.co", port: 9067)) let blockCount = 100 let range = network.constants.SAPLING_ACTIVATION_HEIGHT ... network.constants.SAPLING_ACTIVATION_HEIGHT + blockCount let downloadOperation = CompactBlockDownloadOperation(downloader: CompactBlockDownloader.sqlDownloader(service: service, at: cacheDbURL)!, range: range) @@ -127,7 +127,7 @@ class BlockScanOperationTests: XCTestCase { try self.rustWelding.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthDay.height), hash: walletBirthDay.hash, time: walletBirthDay.time, saplingTree: walletBirthDay.tree, networkType: network.networkType) - let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 100000, streamingCallTimeout: 1000000000) + let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet) let storage = CompactBlockStorage(url: cacheDbURL, readonly: false) try storage.createTable() diff --git a/ZcashLightClientKitTests/BlockStreamingTest.swift b/ZcashLightClientKitTests/BlockStreamingTest.swift index 7aeffcb8..e4543a9d 100644 --- a/ZcashLightClientKitTests/BlockStreamingTest.swift +++ b/ZcashLightClientKitTests/BlockStreamingTest.swift @@ -23,14 +23,14 @@ class BlockStreamingTest: XCTestCase { try? FileManager.default.removeItem(at: __dataDbURL()) } - func testExample() throws { + func testStreamOperation() throws { let expectation = XCTestExpectation(description: "blockstream expectation") - let service = LightWalletGRPCService(host: Constants.address, + let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host, port: 9067, secure: true, - singleCallTimeout: Int64.max, - streamingCallTimeout: 1000) + singleCallTimeout: 1000, + streamingCallTimeout: 100000) let latestHeight = try service.latestBlockHeight() @@ -55,43 +55,10 @@ class BlockStreamingTest: XCTestCase { } - func testStreamOperation() throws { - let expectation = XCTestExpectation(description: "blockstream expectation") - - let service = LightWalletGRPCService(host: Constants.address, - port: 9067, - secure: true, - singleCallTimeout: 1000, - streamingCallTimeout: 1000) - let storage = try TestDbBuilder.inMemoryCompactBlockStorage() - - let startHeight = try service.latestBlockHeight() - 100_000 - let operation = CompactBlockStreamDownloadOperation(service: service, - storage: storage, - startHeight: startHeight, - progressDelegate: self) - - operation.completionHandler = { (finished, cancelled) in - if cancelled { - XCTFail("operation cancelled") - } - expectation.fulfill() - } - - operation.errorHandler = { error in - XCTFail("failed with error: \(error)") - expectation.fulfill() - } - - queue.addOperation(operation) - - wait(for: [expectation], timeout: 1000) - } - func testStreamOperationCancellation() throws { let expectation = XCTestExpectation(description: "blockstream expectation") - let service = LightWalletGRPCService(host: Constants.address, + let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host, port: 9067, secure: true, singleCallTimeout: 10000, @@ -124,7 +91,7 @@ class BlockStreamingTest: XCTestCase { func testStreamOperationTimeout() throws { let expectation = XCTestExpectation(description: "blockstream expectation") let errorExpectation = XCTestExpectation(description: "blockstream error expectation") - let service = LightWalletGRPCService(host: Constants.address, + let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host, port: 9067, secure: true, singleCallTimeout: 1000, @@ -165,25 +132,18 @@ class BlockStreamingTest: XCTestCase { let elapsed = now.distance(to: date) print("took \(elapsed) seconds") } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } func testBatchOperation() throws { let expectation = XCTestExpectation(description: "blockbatch expectation") - let service = LightWalletGRPCService(host: Constants.address, + let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host, port: 9067, secure: true, singleCallTimeout: 300000, streamingCallTimeout: 10000) let storage = try TestDbBuilder.diskCompactBlockStorage(at: __dataDbURL() ) let targetHeight = try service.latestBlockHeight() - let startHeight = targetHeight - 100_000 + let startHeight = targetHeight - 10_000 let operation = CompactBlockBatchDownloadOperation(service: service, storage: storage, startHeight: startHeight, targetHeight: targetHeight, @@ -203,13 +163,13 @@ class BlockStreamingTest: XCTestCase { queue.addOperation(operation) - wait(for: [expectation], timeout: 300) + wait(for: [expectation], timeout: 120) } func testBatchOperationCancellation() throws { let expectation = XCTestExpectation(description: "blockbatch expectation") - let service = LightWalletGRPCService(host: Constants.address, + let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host, port: 9067, secure: true, singleCallTimeout: 300000, @@ -243,6 +203,6 @@ class BlockStreamingTest: XCTestCase { extension BlockStreamingTest: CompactBlockProgressDelegate { func progressUpdated(_ progress: CompactBlockProgress) { -// print("progressHeight: \(progress.progressHeight) startHeight: \(progress.startHeight), targetHeight: \(progress.targetHeight)") + print("progressHeight: \(String(describing: progress.progressHeight)) startHeight: \(progress.progress), targetHeight: \(String(describing: progress.targetHeight))") } } diff --git a/ZcashLightClientKitTests/CompactBlockProcessorTests.swift b/ZcashLightClientKitTests/CompactBlockProcessorTests.swift index ab930b60..d403ed87 100644 --- a/ZcashLightClientKitTests/CompactBlockProcessorTests.swift +++ b/ZcashLightClientKitTests/CompactBlockProcessorTests.swift @@ -21,10 +21,23 @@ class CompactBlockProcessorTests: XCTestCase { let network = ZcashNetworkBuilder.network(for: .testnet) let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT + 2000 - override func setUp() { + override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. + logger = SampleLogger(logLevel: .debug) + + let service = MockLightWalletService(latestBlockHeight: mockLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)) + let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType) + service.mockLightDInfo = LightdInfo.with({ info in + info.blockHeight = UInt64(mockLatestHeight) + info.branch = "asdf" + info.buildDate = "today" + info.buildUser = "testUser" + info.chainName = "test" + info.consensusBranchID = branchID.toString() + info.estimatedHeight = UInt64(mockLatestHeight) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) + }) - let service = MockLightWalletService(latestBlockHeight: mockLatestHeight) let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) try! storage.createTable() @@ -33,7 +46,7 @@ class CompactBlockProcessorTests: XCTestCase { storage: storage, backend: ZcashRustBackend.self, config: processorConfig) - + try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, networkType: .testnet) downloadStartedExpect = XCTestExpectation(description: self.description + " downloadStartedExpect") stopNotificationExpectation = XCTestExpectation(description: self.description + " stopNotificationExpectation") updatedNotificationExpectation = XCTestExpectation(description: self.description + " updatedNotificationExpectation") @@ -74,7 +87,7 @@ class CompactBlockProcessorTests: XCTestCase { updatedNotificationExpectation.subscribe(to: Notification.Name.blockProcessorUpdated, object: processor) startedValidatingNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedValidating, object: processor) startedScanningNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedScanning, object: processor) - idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorIdle, object: processor) + idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorFinished, object: processor) XCTAssertNoThrow(try processor.start()) } @@ -88,7 +101,7 @@ class CompactBlockProcessorTests: XCTestCase { startedValidatingNotificationExpectation, startedScanningNotificationExpectation, idleNotificationExpectation, - ], timeout: 260,enforceOrder: true) + ], timeout: 30,enforceOrder: true) } func testProgressNotifications() { diff --git a/ZcashLightClientKitTests/CompactBlockReorgTests.swift b/ZcashLightClientKitTests/CompactBlockReorgTests.swift index 12ab6cb9..54f963d4 100644 --- a/ZcashLightClientKitTests/CompactBlockReorgTests.swift +++ b/ZcashLightClientKitTests/CompactBlockReorgTests.swift @@ -23,10 +23,26 @@ class CompactBlockReorgTests: XCTestCase { let network = ZcashNetworkBuilder.network(for: .testnet) let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT + 2000 - override func setUp() { + override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. - let service = MockLightWalletService(latestBlockHeight: mockLatestHeight) + logger = SampleLogger(logLevel: .debug) + + let service = MockLightWalletService(latestBlockHeight: mockLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)) + let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType) + service.mockLightDInfo = LightdInfo.with({ info in + info.blockHeight = UInt64(mockLatestHeight) + info.branch = "asdf" + info.buildDate = "today" + info.buildUser = "testUser" + info.chainName = "test" + info.consensusBranchID = branchID.toString() + info.estimatedHeight = UInt64(mockLatestHeight) + info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT) + }) + + try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, networkType: .testnet) + let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) try! storage.createTable() @@ -99,7 +115,7 @@ class CompactBlockReorgTests: XCTestCase { updatedNotificationExpectation.subscribe(to: Notification.Name.blockProcessorUpdated, object: processor) startedValidatingNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedValidating, object: processor) startedScanningNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedScanning, object: processor) - idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorIdle, object: processor) + idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorFinished, object: processor) reorgNotificationExpectation.subscribe(to: Notification.Name.blockProcessorHandledReOrg, object: processor) XCTAssertNoThrow(try processor.start()) diff --git a/ZcashLightClientKitTests/DarksideSanityCheckTests.swift b/ZcashLightClientKitTests/DarksideSanityCheckTests.swift index eb8eb4e5..d1ee8983 100644 --- a/ZcashLightClientKitTests/DarksideSanityCheckTests.swift +++ b/ZcashLightClientKitTests/DarksideSanityCheckTests.swift @@ -24,6 +24,9 @@ class DarksideSanityCheckTests: XCTestCase { var expectedRewindHeight: BlockHeight = 665188 var network = DarksideWalletDNetwork() var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") + let branchID = "2bb40e60" + let chainName = "main" + override func setUpWithError() throws { coordinator = try TestCoordinator( @@ -32,7 +35,7 @@ class DarksideSanityCheckTests: XCTestCase { channelProvider: ChannelProvider(), network: network ) - try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main") + try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName) try coordinator.resetBlocks(dataset: .default) } diff --git a/ZcashLightClientKitTests/DownloadOperationTests.swift b/ZcashLightClientKitTests/DownloadOperationTests.swift index c618093d..38f1252d 100644 --- a/ZcashLightClientKitTests/DownloadOperationTests.swift +++ b/ZcashLightClientKitTests/DownloadOperationTests.swift @@ -21,7 +21,7 @@ class DownloadOperationTests: XCTestCase { func testSingleOperation() { let expect = XCTestExpectation(description: self.description) - let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) + let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet) let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() let downloader = CompactBlockDownloader(service: service, storage: storage) let blockCount = 100 diff --git a/ZcashLightClientKitTests/LightWalletServiceTests.swift b/ZcashLightClientKitTests/LightWalletServiceTests.swift index d88beb2a..4ccc2c27 100644 --- a/ZcashLightClientKitTests/LightWalletServiceTests.swift +++ b/ZcashLightClientKitTests/LightWalletServiceTests.swift @@ -17,7 +17,7 @@ class LightWalletServiceTests: XCTestCase { override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. channel = ChannelProvider().channel() - service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) + service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet) } override func tearDown() { diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index ba0dfd9d..2153da2e 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -29,7 +29,7 @@ class NetworkUpgradeTests: XCTestCase { // walletBirthday: birthday, // channelProvider: ChannelProvider() // ) - try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main") + try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName) } override func tearDownWithError() throws { diff --git a/ZcashLightClientKitTests/ReOrgTests.swift b/ZcashLightClientKitTests/ReOrgTests.swift index 71e8bd73..c9d1f43e 100644 --- a/ZcashLightClientKitTests/ReOrgTests.swift +++ b/ZcashLightClientKitTests/ReOrgTests.swift @@ -33,6 +33,8 @@ class ReOrgTests: XCTestCase { var expectedReorgHeight: BlockHeight = 665188 var expectedRewindHeight: BlockHeight = 665188 let network = DarksideWalletDNetwork() + let branchID = "2bb40e60" + let chainName = "main" var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") override func setUpWithError() throws { NotificationCenter.default.addObserver(self, selector: #selector(handleReOrgNotification(_:)), name: Notification.Name.blockProcessorHandledReOrg, object: nil) @@ -42,7 +44,7 @@ class ReOrgTests: XCTestCase { channelProvider: ChannelProvider(), network: network ) - try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main") + try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName) try coordinator.resetBlocks(dataset: .default) } @@ -109,7 +111,7 @@ class ReOrgTests: XCTestCase { targetHeight: BlockHeight) throws { do { - try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main") + try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName) try coordinator.resetBlocks(dataset: .predefined(dataset: .beforeReOrg)) try coordinator.applyStaged(blockheight: firstLatestHeight) } catch { diff --git a/ZcashLightClientKitTests/RewindRescanTests.swift b/ZcashLightClientKitTests/RewindRescanTests.swift index 1955d41c..658cb9b6 100644 --- a/ZcashLightClientKitTests/RewindRescanTests.swift +++ b/ZcashLightClientKitTests/RewindRescanTests.swift @@ -23,7 +23,7 @@ class RewindRescanTests: XCTestCase { var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg") let branchID = "2bb40e60" let chainName = "main" - var network = ZcashNetworkBuilder.network(for: .testnet) + var network = ZcashNetworkBuilder.network(for: .mainnet) override func setUpWithError() throws { coordinator = try TestCoordinator( diff --git a/ZcashLightClientKitTests/TransactionEnhancementTests.swift b/ZcashLightClientKitTests/TransactionEnhancementTests.swift index 364439fd..f8c0fd83 100644 --- a/ZcashLightClientKitTests/TransactionEnhancementTests.swift +++ b/ZcashLightClientKitTests/TransactionEnhancementTests.swift @@ -127,12 +127,12 @@ class TransactionEnhancementTests: XCTestCase { connect to dLWD request latest height -> receive firstLatestHeight */ -// do { -// print("first latest height: \(try darksideWalletService.latestBlockHeight())") -// } catch { -// XCTFail("Error: \(error)") -// return -// } + do { + print("first latest height: \(try darksideWalletService.latestBlockHeight())") + } catch { + XCTFail("Error: \(error)") + return + } /** diff --git a/ZcashLightClientKitTests/utils/FakeService.swift b/ZcashLightClientKitTests/utils/FakeService.swift index b4aadc84..634c95ee 100644 --- a/ZcashLightClientKitTests/utils/FakeService.swift +++ b/ZcashLightClientKitTests/utils/FakeService.swift @@ -68,13 +68,15 @@ class MockLightWalletService: LightWalletService { } - private var service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) + private var service: LightWalletService var latestHeight: BlockHeight - init(latestBlockHeight: BlockHeight) { + init(latestBlockHeight: BlockHeight, service: LightWalletService) { self.latestHeight = latestBlockHeight + self.service = service } + func latestBlockHeight(result: @escaping (Result) -> Void) { DispatchQueue.global().asyncAfter(deadline: .now() + 1) { result(.success(self.latestHeight)) diff --git a/ZcashLightClientKitTests/utils/Tests+Utils.swift b/ZcashLightClientKitTests/utils/Tests+Utils.swift index 4e9081bc..818b152e 100644 --- a/ZcashLightClientKitTests/utils/Tests+Utils.swift +++ b/ZcashLightClientKitTests/utils/Tests+Utils.swift @@ -19,6 +19,10 @@ class LightWalletEndpointBuilder { static var publicTestnet: LightWalletEndpoint { LightWalletEndpoint(address: "testnet.lightwalletd.com", port: 9067, secure: true) } + + static var eccTestnet: LightWalletEndpoint { + LightWalletEndpoint(address: "lightwalletd.testnet.electriccoin.co", port: 9067, secure: true) + } } class ChannelProvider { From 11c8b164edf60ea93a4c9bdcc79c4bae0d9e589a Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 29 Jul 2021 11:03:44 -0300 Subject: [PATCH 12/17] testnet checkpoints --- .../Constants/WalletBirthday+testnet.swift | 381 +++++++++++------- 1 file changed, 229 insertions(+), 152 deletions(-) diff --git a/ZcashLightClientKit/Constants/WalletBirthday+testnet.swift b/ZcashLightClientKit/Constants/WalletBirthday+testnet.swift index 15cd6a21..dce48509 100644 --- a/ZcashLightClientKit/Constants/WalletBirthday+testnet.swift +++ b/ZcashLightClientKit/Constants/WalletBirthday+testnet.swift @@ -10,157 +10,234 @@ import Foundation extension WalletBirthday { static func testnetBirthday(with height: BlockHeight) -> WalletBirthday { switch height { - case BlockHeight.min ..< 421720: - return WalletBirthday( - height: 280000, - hash: "000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a", - time: 1535262293, - tree: "000000" - ) - case 421720 ..< 425865: - return WalletBirthday( - height: 421720, - hash: "001ede53476a31a91da3313eddf4e41409fb7f4e003840700557b576024d09b4", - time: 1550762014, - tree: "015495a30aef9e18b9c774df6a9fcd583748c8bba1a6348e70f59bc9f0c2bc673b000f00000000018054b75173b577dc36f2c80dfc41f83d6716557597f74ec54436df32d4466d57000120f1825067a52ca973b07431199d5866a0d46ef231d08aa2f544665936d5b4520168d782e3d028131f59e9296c75de5a101898c5e53108e45baa223c608d6c3d3d01fb0a8d465b57c15d793c742df9470b116ddf06bd30d42123fdb7becef1fd63640001a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69" - ) - case 425865 ..< 518000: - return WalletBirthday( - height: 425865, - hash: "0011c4de26004e564347b8af218ca16cd07b08c4159b1cc9c43afa6cb8807bed", - time: 1551215770, - tree: "01881e4da7e4767ee8a144a32ab8a5719a513bb05854477773bb55e6cd7f15055201f8a99a3a5ae3528ec2fc0bda9652b6728aecb08bf364e06ac511fd6654d782720f019ef0b9bdd075c38519fa4ab8210fe7e94c609f52672796e33e3cab58b1602831000001f803bf338ff1526b2ca527288974cb9be3fe240a2eadb7507e46ba59eaddb9320129fc0148ac088a6aa509f8f64ef79fda92232020369b58a12b32c05b6f428f22015e3dd0950c442940bd015c2176f7c817f22104f54c61159727483188c539dc13000000013589be9e2d9e9e38fd78b1e8eaec5b5f5167bf7fd2b1c95c316fa366a24cac4c01a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69" - ) - case 518000 ..< 523240: - return WalletBirthday( - height: 518000, - hash: "000ba586d734c295f0bc034be229b1c96cb040f9d4929efdb5d2b187eeb238fb", - time: 1560645743, - tree: "01a4f5240a88a6eb4ffbda7961a1430506aad1a50ba011593f02c243d968feb0550010000140f91773b4ab669846e5bcb96f60e68256c49a27872a98e9d5ce50b30a0c434e0000018968663d6a7b444591de83f8a07223113f5de7e8203807adacc7677c3bcd4f420194c7ecac0ef6d702d475680ec32051fdf6368af0c459ab450009c001bcbf7a5300000001f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 523240 ..< 620000: - return WalletBirthday( - height: 523240, - hash: "00000c33da2196f0ed1bda71043f671fc69a0212e01f892653e212ab358f6b79", - time: 1561002603, - tree: "01d3e02bc1c2d66762f370b329a3063067701ad66c44b40285686bc8ff25f5616f00100154bff87bd0bda3b70a6d7754eca261de15fee3cd9bc53073a232e07fc3261e27000001a54dcaccb4c5e578aef89f2a3b4e3c3d8a487e6e904c5da5916118d721948d07000000000118fa9c6fef4963049dc7002a13bb0021d5e950591e48c9e5f2cbd1199429b80401f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 620000 ..< 680000: - return WalletBirthday( - height: 620000, - hash: "005f97953c8e1265d6b45f4435ffa32918e53e8f0025c286a4080c3eab167197", - time: 1569572035, - tree: "0170cf036ea1ea3c6e08432e18b6a372ca0b8b83671cc13ab0cf9e28c182f6c36f00100000013f3fc2c16ac4780f1c472ca65534ab08911f325a9edde5ea7f24364b47c9a95300017621b12e518cbbbdb7511ab423e0bddda412ed61ed3cff5be2140de65d6a0069010576153a5a2098812e7a028c37c3398e186f398c9b07bc199784ab97e5535c3e0000019a6ce2f0f7dbb2de493a315abf62d8ca96ccc701f116b6ddfae33870a2183d3c01c9d3564eff54ebc328eab2e4f1150c3637f4f47516f879a0cfebdf49fe7b1d5201c104705fac60a85596010e41260d07f3a64f38f37a112eaef41cd9d736edc5270145e3d4899fcd7f0f1236ae31eafb3f4b65ad6b11a17eae1729cec09bd3afa01a000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 680000 ..< 720000: - return WalletBirthday( - height: 680000, - hash: "00a4fbf54597d2f474f999576affad63f0ba2daa14c6fcd55c7eeec700107270", - time: 1573569367, - tree: "010a57f939a267f8b1e8b77288c783432e48fa95f7b22ead5e8ff46a788181453801d6457d98d3698a367aef4a2fe5675a575790d5d8081b731f979f0e64043fb7351001afaaf81d6d982b401444dbcf89e63c2583d234c1a60de17940a9b3a15f3494660001ba7acc730584a689413c44781d3b13cd497bfdca3fe27fb78cd9b50e9929906300000000000129e195df514840a20b95200b92d5b8d196b119cd6887508d8de077beffdbfe68016482af04b979e08e4e5760d55832292e55dbdd88143992f123840c8983db7b3f000001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 720000 ..< 740000: - return WalletBirthday( - height: 720000, - hash: "018b71dde8c9b1ee3e79961c6e3536c79226f5d6e79bb35c9ed28dcb8cb78b48", - time: 1575943651, - tree: "012cfde48dff4f20ddc50a7aca3746f7d77920eebc8cf4ef53feac34cb8719c03a012c668d234aaa485862e1d06e46d6d7093c2581e2b9cda90aafd691d6e325410610014f3a875476cb8159d46fec1aba18c201c268cd61b01811b7e5bf83998fb8222500011f19160cc75325c090f3eb3fa0cff2d94e43e2713c89e7b02a34f6ed08fbcd26000001edc05305223f7f2839abc1dc7d900468349577d6d6f5c182ef3a81a848753b5b0000000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - - case 740000 ..< 760000: - return WalletBirthday( - height: 740000, - hash: "00163c394a1e545b4c777fc91474d92becdd0fe9300d38fb3563997d026a54ea", - time: 1577389695, - tree: "0135ee37f83d0b924eed58bcceb249a4977dcb21495561b97bc747a272ebe5d6580010000001fe65cfbb8a76e0d29ac94e5ada80c80b607d1addfc287754f37ddef531eb122500013a1d604d978f716fcb2887cdaa3c582a608b795ed1b3c57998cbede2be479931000108ffb0fbc6b653305b37cd5568b85112b996cd514fe97ec73f7169dae0cef05101baf5541e853483315273c25c1956d233513c3dabd8741972136b2f8f8cd89035000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - - case 760000 ..< 780000: - return WalletBirthday( - height: 760000, - hash: "005ee769f3adbd0b24a63e8e4047200e038c38df277544d40c23ac1a88c1f37b", - time: 1578766903, - tree: "01470a1a4d29374e074f07a646b95dd89892d9b84d235a89ecc9d5a52beadce901001001311898ce56df0ddb10dc573a54ea06d11415e72602daa80c01f888fbd4a9a734018610afa4925cdb8bd4dd75a53ab69a74080322cae53c630ac02ce00b09d3171601bdfbbde5011bd6c0620ed2db3e01d5daa2ff8bb5f3b58687d265dd33a5681d530197e268c82e56dfc62aeb54586a2000766da8078f09a2d15fb558ad05664b4c5301aa204407034ba59fce0eee6518688585e96b0f10befd595b8e68a8ae15328a51017389398c5634242b03ef811f6abf224df9e6fc6d4393139e526dca4cf44dcc2c0000017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - - case 780000 ..< 798181: - return WalletBirthday( - height: 780000, - hash: "0104238cc440b6bf05b86a1b00d794c6d88fc61b8c416124a971fb5ce94b91e6", - time: 1580205978, - tree: "011ed883b7eddb4783eee5b73ceee4c78413e1f6f9db3d88d1007f5fa62292955c001001861feaeab59bc31cd97ffc89467877abf8b9fa157bc875907eb90d6e8c723325000000000001ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - - case 798181 ..< 800000: - return WalletBirthday( - height: 798181, - hash: "02936aa4f8b6b2caad7cca19a866158656e37edfb0f32e2a473dc278fa634b71", - time: 1581521064, - tree: "01901ef0f4221f8a02d5896fda6f78cb5578fb8e9a5361d5689bfb3b6ab92072320010000101c5d791d8748f0ab0ecdb48764de29c470cc74f5d95b5a1f8cf0830bb059b66015af654e998c75460e9c1f5ba185589c53c383167e66951cfe7684321b7a77e5c013faf6b3f21f03982ada477bfddc95b18e63683c497b2f4630ab453623c28974c01aff3253410a6601ab4b5b3626f2121cb77399c634b1774a4c63f415598d16b0c01a6158d0a1a1bec9dadc601b140a9fdfc7bdab7e232739a3cc0e0e46bbe3ef44301ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 800000 ..< 850000: - return WalletBirthday( - height: 800000, - hash: "00599614a7795bbef99a598cfee887782900fa5cd95cd59900b8d6582bdc17a5", - time: 1581643886, - tree: "011ba0f16f59489a9bf9cc46c3ed1108c1dc0ff6e40f3a38def472c3229a96925e01b0eb758757bde323a6417d98365ce8f6299b0fa3de615d6cda68689e6a81573d1001438b40ff7357432d987d6ef4826fba35d38b2db531ea842ccedd4916a6aff9580000017cd705c293895c8b4613a3de3ad3b8d43ae05fff808882db4c5e19917e2f346d00000000000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 850000 ..< 900000: - return WalletBirthday( - height: 850000, - hash: "003b66bc3528dc295193108caab868e0f3b93d13db2ddcad5486225fb2b83d83", - time: 1585012771, - tree: "01e3bd906376b563d184bfbf6616e220f895001b7ef9d26bf38c6cb5c71e57a42b001001d848adf8c38d113140bb30d306b0761da6987e25ffc0d82faa63c2764aab120301de3e6a35d09192cde3430860c70a534d7b63e95a726fab052de2a9befa3cc3320189b958fa030131bb83385a3e3a8b187a166dc1b3a02050f2d2fc20788536c30e0001cb8770ef198e7de60093a339afbc561c16c16749f9f96751c2fc58a22d0ff36f01f86ff70dd512f7075d02c5ee6e28a8824832d08025a4cfaf4c1854f1fba5da10019bcac1b44a27de2c4528fa6f4b3432913511b219cb3b29d137cac0236a3d244800000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 950000 ..< 1013250: - return WalletBirthday( - height: 950000, - hash: "0005050d2ce31b9b925c7ef4ab3d3166d5833bdcfee251294f29072a2bc0f75d", - time: 1591609525, - tree: "01f0637235c4a699d49ba996457a6c4eb7c67edd8270948065683deb19ef218363019f65a9692cefc7b90b42c1538ac1f38f7a7598549089c4561315b482f378523010000000000000018d30d0039277b05ab9e0c3990d53037c45892bf17af2d04fef40ed48c164ad2201ff5d86bbbe360e31378e783b740f8b05db2cf4246b95aa3851d22ed45554750300010cefb25743d5dd6062ef3afba438731cd5b35befc1038ecca3076fd205829e550001c19052386d8bbe3c07a1faf302281d67946cc9547e7e1890ff56b3a3ec69c0310001be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 1013250 ..< 1028400: - return WalletBirthday( - height: 1013250, - hash: "0017b3c49eea14e93f69adbc7a8f24eef3e9645f92e3b8d5e4091e1d5a4824b7", - time: 1595516064, - tree: "01d45e95007f8f97fe3c6a297a9d4bca917772e545fbcbb61b4f42d8a743eae31b0010013d7b7da2e6792dbfc6360f0c13a1ba879aa51a498c6dbab87aa57cef558cc35a00000001f945c15602617327026e3e0f231daf91570b32f7bb766f65e7e82131a911cc3c0000013173e9983fbd7a396e192e520d163be06cdd28abcfeba46c59dc62a400f589080001e7d5b00f0758cd3b7407c6d13e23d1a59e3f510c3dd3a4a8fc367a5305673b3f000001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 1028400 ..< 1130000: - return WalletBirthday( - height: 1028400, - hash: "0006b94b304009f8a6287aa48021aed26582ce74d387c2c452aede86566179a6", - time: 1596480151, - tree: "01ac95378779cf56f0726655d248f95d63e07316ab67651ce357b346f9a7adba300107d7544edbe7d0522fe523df2ff804fc9f33f4844dd29e86a23fc7aa1818e237100001f8779a159482fd3a28c640e6d48ddfb37a44a26a102aae3822f32d2de22a1c70011f97534315f1800961bc78fcd1495e3b8047bb227e2776080fb31be6cae14e73000000000001fe15295e017fc2b8ba4ea1b7e53dd15f19860d10e7952905b7598373e143413e00019289038516ce3d6038cebe852ab5e32f7a1966fc79a1e41c7cb6e67e5a71c33d0001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 1130000 ..< 1370446: - return WalletBirthday( - height: 1130000, - hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", - time: 1603070117, - tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 1370446 ..< 1414969: - return WalletBirthday( - height: 1370446, - hash: "00357a40a8d0473663f5ac32ecd4365bea097e47070b38803cbfae2b7a402233", - time: 1618587354, - tree: "01d0d36f8845f9ffad4f0a8812fbc5c4c69b45733199d7183307cb1a7d00353c0900100000017a8a6f641c487a313bb949623cca3b22b925adfef8216866aa090546bcf520000001bf48febcd2a10e51d420782990e17b746d5ce0f3292007e60a2eeb830bc46d0201ab6e0123bf72f70255ec4cacd33935b19ff834d481d67e06801073d0b8f0ea2a0121f42f607885a0158022413591af8eca7eae38b10c46e3ac81a9bfe70046e51d018229160dbe1f1d9e02d738e9d5060497e786e7434c80c32db7b8c96878e9904601034e6b1c73f09aa81f16a13cdb2188a53d8761483470f0bea01bfb84eb2cea1100018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - case 1414969 ..< BlockHeight.max: - return WalletBirthday( - height: 1414969, - hash: "00212ba35169b77dba4eb4f5ce8c10da31a9df6dd61bb434f2f9e159d78913bd", - time: 1621459669, - tree: "01a9497fdb3add3bc2d0676f3163d94cda7c8cf8112d9dd8d2e7611b187c600a410010000143905c99f7bb45b164c636bb2443d9621db8147dba6a84a279fa8ed8f012083d00016847084e044e84059ea4b88b8af2de3f65c72adcee21522d5ee9d370d70f525b0000014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - default: - return WalletBirthday( - height: 1414969, - hash: "00212ba35169b77dba4eb4f5ce8c10da31a9df6dd61bb434f2f9e159d78913bd", - time: 1621459669, - tree: "01a9497fdb3add3bc2d0676f3163d94cda7c8cf8112d9dd8d2e7611b187c600a410010000143905c99f7bb45b164c636bb2443d9621db8147dba6a84a279fa8ed8f012083d00016847084e044e84059ea4b88b8af2de3f65c72adcee21522d5ee9d370d70f525b0000014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) - } + case BlockHeight.min ..< 421720: + return WalletBirthday( + height: 280000, + hash: "000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a", + time: 1535262293, + tree: "000000" + ) + case 421720 ..< 425865: + return WalletBirthday( + height: 421720, + hash: "001ede53476a31a91da3313eddf4e41409fb7f4e003840700557b576024d09b4", + time: 1550762014, + tree: "015495a30aef9e18b9c774df6a9fcd583748c8bba1a6348e70f59bc9f0c2bc673b000f00000000018054b75173b577dc36f2c80dfc41f83d6716557597f74ec54436df32d4466d57000120f1825067a52ca973b07431199d5866a0d46ef231d08aa2f544665936d5b4520168d782e3d028131f59e9296c75de5a101898c5e53108e45baa223c608d6c3d3d01fb0a8d465b57c15d793c742df9470b116ddf06bd30d42123fdb7becef1fd63640001a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69" + ) + case 425865 ..< 518000: + return WalletBirthday( + height: 425865, + hash: "0011c4de26004e564347b8af218ca16cd07b08c4159b1cc9c43afa6cb8807bed", + time: 1551215770, + tree: "01881e4da7e4767ee8a144a32ab8a5719a513bb05854477773bb55e6cd7f15055201f8a99a3a5ae3528ec2fc0bda9652b6728aecb08bf364e06ac511fd6654d782720f019ef0b9bdd075c38519fa4ab8210fe7e94c609f52672796e33e3cab58b1602831000001f803bf338ff1526b2ca527288974cb9be3fe240a2eadb7507e46ba59eaddb9320129fc0148ac088a6aa509f8f64ef79fda92232020369b58a12b32c05b6f428f22015e3dd0950c442940bd015c2176f7c817f22104f54c61159727483188c539dc13000000013589be9e2d9e9e38fd78b1e8eaec5b5f5167bf7fd2b1c95c316fa366a24cac4c01a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69" + ) + case 518000 ..< 523240: + return WalletBirthday( + height: 518000, + hash: "000ba586d734c295f0bc034be229b1c96cb040f9d4929efdb5d2b187eeb238fb", + time: 1560645743, + tree: "01a4f5240a88a6eb4ffbda7961a1430506aad1a50ba011593f02c243d968feb0550010000140f91773b4ab669846e5bcb96f60e68256c49a27872a98e9d5ce50b30a0c434e0000018968663d6a7b444591de83f8a07223113f5de7e8203807adacc7677c3bcd4f420194c7ecac0ef6d702d475680ec32051fdf6368af0c459ab450009c001bcbf7a5300000001f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 523240 ..< 620000: + return WalletBirthday( + height: 523240, + hash: "00000c33da2196f0ed1bda71043f671fc69a0212e01f892653e212ab358f6b79", + time: 1561002603, + tree: "01d3e02bc1c2d66762f370b329a3063067701ad66c44b40285686bc8ff25f5616f00100154bff87bd0bda3b70a6d7754eca261de15fee3cd9bc53073a232e07fc3261e27000001a54dcaccb4c5e578aef89f2a3b4e3c3d8a487e6e904c5da5916118d721948d07000000000118fa9c6fef4963049dc7002a13bb0021d5e950591e48c9e5f2cbd1199429b80401f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 620000 ..< 680000: + return WalletBirthday( + height: 620000, + hash: "005f97953c8e1265d6b45f4435ffa32918e53e8f0025c286a4080c3eab167197", + time: 1569572035, + tree: "0170cf036ea1ea3c6e08432e18b6a372ca0b8b83671cc13ab0cf9e28c182f6c36f00100000013f3fc2c16ac4780f1c472ca65534ab08911f325a9edde5ea7f24364b47c9a95300017621b12e518cbbbdb7511ab423e0bddda412ed61ed3cff5be2140de65d6a0069010576153a5a2098812e7a028c37c3398e186f398c9b07bc199784ab97e5535c3e0000019a6ce2f0f7dbb2de493a315abf62d8ca96ccc701f116b6ddfae33870a2183d3c01c9d3564eff54ebc328eab2e4f1150c3637f4f47516f879a0cfebdf49fe7b1d5201c104705fac60a85596010e41260d07f3a64f38f37a112eaef41cd9d736edc5270145e3d4899fcd7f0f1236ae31eafb3f4b65ad6b11a17eae1729cec09bd3afa01a000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 680000 ..< 720000: + return WalletBirthday( + height: 680000, + hash: "00a4fbf54597d2f474f999576affad63f0ba2daa14c6fcd55c7eeec700107270", + time: 1573569367, + tree: "010a57f939a267f8b1e8b77288c783432e48fa95f7b22ead5e8ff46a788181453801d6457d98d3698a367aef4a2fe5675a575790d5d8081b731f979f0e64043fb7351001afaaf81d6d982b401444dbcf89e63c2583d234c1a60de17940a9b3a15f3494660001ba7acc730584a689413c44781d3b13cd497bfdca3fe27fb78cd9b50e9929906300000000000129e195df514840a20b95200b92d5b8d196b119cd6887508d8de077beffdbfe68016482af04b979e08e4e5760d55832292e55dbdd88143992f123840c8983db7b3f000001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 720000 ..< 740000: + return WalletBirthday( + height: 720000, + hash: "018b71dde8c9b1ee3e79961c6e3536c79226f5d6e79bb35c9ed28dcb8cb78b48", + time: 1575943651, + tree: "012cfde48dff4f20ddc50a7aca3746f7d77920eebc8cf4ef53feac34cb8719c03a012c668d234aaa485862e1d06e46d6d7093c2581e2b9cda90aafd691d6e325410610014f3a875476cb8159d46fec1aba18c201c268cd61b01811b7e5bf83998fb8222500011f19160cc75325c090f3eb3fa0cff2d94e43e2713c89e7b02a34f6ed08fbcd26000001edc05305223f7f2839abc1dc7d900468349577d6d6f5c182ef3a81a848753b5b0000000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 740000 ..< 760000: + return WalletBirthday( + height: 740000, + hash: "00163c394a1e545b4c777fc91474d92becdd0fe9300d38fb3563997d026a54ea", + time: 1577389695, + tree: "0135ee37f83d0b924eed58bcceb249a4977dcb21495561b97bc747a272ebe5d6580010000001fe65cfbb8a76e0d29ac94e5ada80c80b607d1addfc287754f37ddef531eb122500013a1d604d978f716fcb2887cdaa3c582a608b795ed1b3c57998cbede2be479931000108ffb0fbc6b653305b37cd5568b85112b996cd514fe97ec73f7169dae0cef05101baf5541e853483315273c25c1956d233513c3dabd8741972136b2f8f8cd89035000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 760000 ..< 780000: + return WalletBirthday( + height: 760000, + hash: "005ee769f3adbd0b24a63e8e4047200e038c38df277544d40c23ac1a88c1f37b", + time: 1578766903, + tree: "01470a1a4d29374e074f07a646b95dd89892d9b84d235a89ecc9d5a52beadce901001001311898ce56df0ddb10dc573a54ea06d11415e72602daa80c01f888fbd4a9a734018610afa4925cdb8bd4dd75a53ab69a74080322cae53c630ac02ce00b09d3171601bdfbbde5011bd6c0620ed2db3e01d5daa2ff8bb5f3b58687d265dd33a5681d530197e268c82e56dfc62aeb54586a2000766da8078f09a2d15fb558ad05664b4c5301aa204407034ba59fce0eee6518688585e96b0f10befd595b8e68a8ae15328a51017389398c5634242b03ef811f6abf224df9e6fc6d4393139e526dca4cf44dcc2c0000017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 780000 ..< 798181: + return WalletBirthday( + height: 780000, + hash: "0104238cc440b6bf05b86a1b00d794c6d88fc61b8c416124a971fb5ce94b91e6", + time: 1580205978, + tree: "011ed883b7eddb4783eee5b73ceee4c78413e1f6f9db3d88d1007f5fa62292955c001001861feaeab59bc31cd97ffc89467877abf8b9fa157bc875907eb90d6e8c723325000000000001ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + + case 798181 ..< 800000: + return WalletBirthday( + height: 798181, + hash: "02936aa4f8b6b2caad7cca19a866158656e37edfb0f32e2a473dc278fa634b71", + time: 1581521064, + tree: "01901ef0f4221f8a02d5896fda6f78cb5578fb8e9a5361d5689bfb3b6ab92072320010000101c5d791d8748f0ab0ecdb48764de29c470cc74f5d95b5a1f8cf0830bb059b66015af654e998c75460e9c1f5ba185589c53c383167e66951cfe7684321b7a77e5c013faf6b3f21f03982ada477bfddc95b18e63683c497b2f4630ab453623c28974c01aff3253410a6601ab4b5b3626f2121cb77399c634b1774a4c63f415598d16b0c01a6158d0a1a1bec9dadc601b140a9fdfc7bdab7e232739a3cc0e0e46bbe3ef44301ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 800000 ..< 850000: + return WalletBirthday( + height: 800000, + hash: "00599614a7795bbef99a598cfee887782900fa5cd95cd59900b8d6582bdc17a5", + time: 1581643886, + tree: "011ba0f16f59489a9bf9cc46c3ed1108c1dc0ff6e40f3a38def472c3229a96925e01b0eb758757bde323a6417d98365ce8f6299b0fa3de615d6cda68689e6a81573d1001438b40ff7357432d987d6ef4826fba35d38b2db531ea842ccedd4916a6aff9580000017cd705c293895c8b4613a3de3ad3b8d43ae05fff808882db4c5e19917e2f346d00000000000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 850000 ..< 900000: + return WalletBirthday( + height: 850000, + hash: "003b66bc3528dc295193108caab868e0f3b93d13db2ddcad5486225fb2b83d83", + time: 1585012771, + tree: "01e3bd906376b563d184bfbf6616e220f895001b7ef9d26bf38c6cb5c71e57a42b001001d848adf8c38d113140bb30d306b0761da6987e25ffc0d82faa63c2764aab120301de3e6a35d09192cde3430860c70a534d7b63e95a726fab052de2a9befa3cc3320189b958fa030131bb83385a3e3a8b187a166dc1b3a02050f2d2fc20788536c30e0001cb8770ef198e7de60093a339afbc561c16c16749f9f96751c2fc58a22d0ff36f01f86ff70dd512f7075d02c5ee6e28a8824832d08025a4cfaf4c1854f1fba5da10019bcac1b44a27de2c4528fa6f4b3432913511b219cb3b29d137cac0236a3d244800000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 950000 ..< 1013250: + return WalletBirthday( + height: 950000, + hash: "0005050d2ce31b9b925c7ef4ab3d3166d5833bdcfee251294f29072a2bc0f75d", + time: 1591609525, + tree: "01f0637235c4a699d49ba996457a6c4eb7c67edd8270948065683deb19ef218363019f65a9692cefc7b90b42c1538ac1f38f7a7598549089c4561315b482f378523010000000000000018d30d0039277b05ab9e0c3990d53037c45892bf17af2d04fef40ed48c164ad2201ff5d86bbbe360e31378e783b740f8b05db2cf4246b95aa3851d22ed45554750300010cefb25743d5dd6062ef3afba438731cd5b35befc1038ecca3076fd205829e550001c19052386d8bbe3c07a1faf302281d67946cc9547e7e1890ff56b3a3ec69c0310001be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1013250 ..< 1028400: + return WalletBirthday( + height: 1013250, + hash: "0017b3c49eea14e93f69adbc7a8f24eef3e9645f92e3b8d5e4091e1d5a4824b7", + time: 1595516064, + tree: "01d45e95007f8f97fe3c6a297a9d4bca917772e545fbcbb61b4f42d8a743eae31b0010013d7b7da2e6792dbfc6360f0c13a1ba879aa51a498c6dbab87aa57cef558cc35a00000001f945c15602617327026e3e0f231daf91570b32f7bb766f65e7e82131a911cc3c0000013173e9983fbd7a396e192e520d163be06cdd28abcfeba46c59dc62a400f589080001e7d5b00f0758cd3b7407c6d13e23d1a59e3f510c3dd3a4a8fc367a5305673b3f000001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1028400 ..< 1130000: + return WalletBirthday( + height: 1028400, + hash: "0006b94b304009f8a6287aa48021aed26582ce74d387c2c452aede86566179a6", + time: 1596480151, + tree: "01ac95378779cf56f0726655d248f95d63e07316ab67651ce357b346f9a7adba300107d7544edbe7d0522fe523df2ff804fc9f33f4844dd29e86a23fc7aa1818e237100001f8779a159482fd3a28c640e6d48ddfb37a44a26a102aae3822f32d2de22a1c70011f97534315f1800961bc78fcd1495e3b8047bb227e2776080fb31be6cae14e73000000000001fe15295e017fc2b8ba4ea1b7e53dd15f19860d10e7952905b7598373e143413e00019289038516ce3d6038cebe852ab5e32f7a1966fc79a1e41c7cb6e67e5a71c33d0001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1130000 ..< 1370446: + return WalletBirthday( + height: 1130000, + hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", + time: 1603070117, + tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1370446 ..< 1414969: + return WalletBirthday( + height: 1370446, + hash: "00357a40a8d0473663f5ac32ecd4365bea097e47070b38803cbfae2b7a402233", + time: 1618587354, + tree: "01d0d36f8845f9ffad4f0a8812fbc5c4c69b45733199d7183307cb1a7d00353c0900100000017a8a6f641c487a313bb949623cca3b22b925adfef8216866aa090546bcf520000001bf48febcd2a10e51d420782990e17b746d5ce0f3292007e60a2eeb830bc46d0201ab6e0123bf72f70255ec4cacd33935b19ff834d481d67e06801073d0b8f0ea2a0121f42f607885a0158022413591af8eca7eae38b10c46e3ac81a9bfe70046e51d018229160dbe1f1d9e02d738e9d5060497e786e7434c80c32db7b8c96878e9904601034e6b1c73f09aa81f16a13cdb2188a53d8761483470f0bea01bfb84eb2cea1100018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1414969 ..< 1420000: + return WalletBirthday( + height: 1414969, + hash: "00212ba35169b77dba4eb4f5ce8c10da31a9df6dd61bb434f2f9e159d78913bd", + time: 1621459669, + tree: "01a9497fdb3add3bc2d0676f3163d94cda7c8cf8112d9dd8d2e7611b187c600a410010000143905c99f7bb45b164c636bb2443d9621db8147dba6a84a279fa8ed8f012083d00016847084e044e84059ea4b88b8af2de3f65c72adcee21522d5ee9d370d70f525b0000014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1420000 ..< 1430000: + return WalletBirthday( + height: 1420000, + hash: "0089952e8ca00ee452412c3eef20403f9bc84751fc6ceb630c8a2eb149f051ca", + time: 1621783347, + tree: "0107478e9125e3050506cbeea850266d94108997ec3ef101d9693d136611b4076c00100001dfcde451d111cd50bac54c4ed4e238ca3dd8dcfcb8b50eabccb11a12dbcad71b0001cffd776a8fd6e5df911d000876525aa1d792a4f764e252dac9af69dd8ef3046d0106d4ec443aa1194ea579a1aa179bd5a29eeb4a5a01ccbfcf7af9cadc58225a6900014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1430000 ..< 1440000: + return WalletBirthday( + height: 1430000, + hash: "01d9b2d83a7ec4ecede08df009e389b70535a5d41a1c6d1ce0906381d06006e0", + time: 1622484411, + tree: "010ea3d173a66acda751cb72a86bcc1eed2708b997ca8c7292febbd4c19b41665e001001f908af1ee7296100c06672f69834e5be2dc8b5325945270d562669bba91b825d01c4b42187eb99ab242226f6f2a48a00d4e5b3b4201c931afe9bccc86f3fbdd46501f39c0c0c1f725fa6b3ab8b58e60b280207a41199e2e218405f31ae18f0759f16000154daf736c7f68b0f22072be3e6b59434618b514c0c32d044c187048e2600c60b01f98b75b62bf721db663a442cbfa411242ec07ccb70aee42ea3618ca7b157270a014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1440000 ..< 1450000: + return WalletBirthday( + height: 1440000, + hash: "0026a36cf31a5442caa1ac6d7be2773e1e58a3ccb6ae1116e84e6c90ddc95ec9", + time: 1623136353, + tree: "018d8cc853fd33af2a13ea00f379fe882fc56ecea3e0b1ecb75ac3b9783b443d3b01922d8ec71070cbe88eef0576738169965839e841d2fbc09c85f1d64f3528d4341001ee3dbc8987d7be81ccd8a5b502e9385c447f3f8c9c34085a1d11f7b41ceb625b010c1d1b1687fd081e55598e9bdcc5c565781ec867a12dd056384890f36fef434c00011674571f7aca05cc96139d2e59b08fe7a5b7b779da40a9903755b61e73421e64000001ccb87d20316142450d34c59bc515935f9adfd053a178ae8d799ea1f9bf02664901cc23dbfe7d27d7ad768868d7a96b6b31260ca34e4fbf164f652eb8e651f2fd3801b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1450000 ..< 1460000: + return WalletBirthday( + height: 1450000, + hash: "000008a97bc133de13ca304e0c6a2a1b3f2facdceac2cde5b4141179f2a743cc", + time: 1623815069, + tree: "0175626cf9d8448de98f68fcc585dd7a276c946c11bbc3b192ee08db99c542b86b01acf5a110dc7ab911b534984c46bf56592f0c4cc8cf70dbd6a9cc4a5b47d2c81c1001c91f518ccb74093a217a640c537b69b095de058e0430046c8783f231caa1fa4201f7c982ce76b2c9343fb771e077357322f9a7dabfd7ab93b7adee32806c930d6600000170910ab6355ec614412fae56dad5fdc1747ce1b306a4b8ae03b77513b612b00800000000000000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1460000 ..< 1470000: + return WalletBirthday( + height: 1460000, + hash: "00987b79a3c78d33dcb4d65e81a48b62a40c15d379a3983c4dffdd99a0c21d35", + time: 1624454126, + tree: "01f971b9781e857ab4acd5506174daf7ced473ad5a4a98134816d0c48de197d4400010000001ce49c67660eff9e404a3e4569ffa3ba98cc4514c05fa408beecd5c63420ef30e0192152273e4cbeafd426fa7df421310d2ccefad5e78f8d3e26dc283064b4d0d480188b70932b9ad821d4c9ecd57ed729a724723d22bdee4e5d4f08c9a924e68cf1501b2533ff180b8fb171fc0450fb7d1f91b7528bc19d88fdb2385c207b149d55e53017b499fdb9fe0db4bc418689d8f45f38b127b67d0445c421bfa6892c870610e260000000000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1470000 ..< 1480000: + return WalletBirthday( + height: 1470000, + hash: "0027c8d818126cc8ab96efdcf877c1fb54fb373f41ca8f06e68b0b7b0e304ac7", + time: 1625121412, + tree: "012442af751714abfbb1f6b815b187eecbb60849e29dca1e3acccfbfd73f6bb8150010000109777ddd46c0a0e7eb91f31735f6078c54334f9a6d22d6421898bd44fd83ce140000013337975cc4704be21cbecce1c877936ce395128f6264fcb91ba8c028e7f25230015d7589dc1009350a87831e2fa9c4d9d3ca61754644f1a1d5d09499567fdcb11e0136e55cb009dd4f8bb8a3469b27ec325f06552a66bef2d898b6a72063107d03350001a7b951c79a184af5bda58c8be77db9b1e3813df0de344f26b27e3ad02c325b3b000000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1480000 ..< 1490000: + return WalletBirthday( + height: 1480000, + hash: "0019c7d1a7d9d962de329db0785f35f56c514826702714f8738d14da87f4f20d", + time: 1625795173, + tree: "01a61918852f89d4d68aa82e1d93a7ddc4285ab2cf6a2ce92e79c4b9b498662014016d8109b64819882e5d35ee6730f54dda3a4ddc8232edc22226a367542c977a23100000016891e1f6b99afb29292bd3157f89eb2b8c1f74eed9cef56f4a802939d7392a1a0001f6f393a6ab5b0bc04a6d751bdbcd64a2740ff93aef7e1527dcd5de0511c4fb3001b938c3d7a93793fa04d51cce0369e789316a72f227436e02fc0c45fdd88def3700000001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1490000 ..< 1500000: + return WalletBirthday( + height: 1490000, + hash: "00263c9eab1b6b5e37143a442a8aad242fada58bb5fc8d6a5dc9f217c8c7425c", + time: 1626460494, + tree: "01448b047d9d4611f923ceb0c01a2fc743c7b4a54f7a00e92d666cbd0f39980f3100100000000001d917913fed08004cf1c74eeb918829cb80e576187e2f8e0c0e12a7e9849a9b400130282bcf71d57c40235baa4a3e045d89803c1fe069803da86ccebf25435dd270014aad72f0f5c3cd459d6d89a68657fbd299c84be0228c1a8a50d63ff2f2f74e0a000001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1500000 ..< 1507328: + return WalletBirthday( + height: 1500000, + hash: "00047a34c61409682f44640af9352023ad92f69b827d0f2b288f152ebea50f46", + time: 1627076501, + tree: "01172b95f271c6af8f68388f08c8ef970db8ec8d8d61204ecb7b2bb2c38262b92d0010016284585a6c85dadfef27ff33f1403926b4bb391de92e8be797e4280cc4ca2971000001a1ff388639379c0120782b3929bd8871af797be4b651f694aa961bad65a9c12400000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1500000 ..< 1507328: + return WalletBirthday( + height: 1500000, + hash: "00047a34c61409682f44640af9352023ad92f69b827d0f2b288f152ebea50f46", + time: 1627076501, + tree: "01172b95f271c6af8f68388f08c8ef970db8ec8d8d61204ecb7b2bb2c38262b92d0010016284585a6c85dadfef27ff33f1403926b4bb391de92e8be797e4280cc4ca2971000001a1ff388639379c0120782b3929bd8871af797be4b651f694aa961bad65a9c12400000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + case 1507328 ..< BlockHeight.max: + return WalletBirthday( + height: 1507328, + hash: "0026c9b20540e1bde6aaa8674a4083587a6e2555bcf8bb42680a8870b8da0070", + time: 1627566512, + tree: "01beb58cd0d4ac4e0f61888c7d77c7d73d260453b526bc61a830c158319f01b22301070135db53749d6640bdfc3c3e25d71dd65dcdc2c5828fd992eaee63546194051000000105884e2f6fbe3d0754fca27e20881b74ea687d33a0ea817844330a187d20465a0192f904a39694089c3befc610fd8e1236d5e7cb3b19d2e1d5fc4019af31fbc80201870a7fec351119b307e79c83bb627b343a87668e1d68e60625212e40deb33c3d000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + default: + return WalletBirthday( + height: 1507328, + hash: "0026c9b20540e1bde6aaa8674a4083587a6e2555bcf8bb42680a8870b8da0070", + time: 1627566512, + tree: "01beb58cd0d4ac4e0f61888c7d77c7d73d260453b526bc61a830c158319f01b22301070135db53749d6640bdfc3c3e25d71dd65dcdc2c5828fd992eaee63546194051000000105884e2f6fbe3d0754fca27e20881b74ea687d33a0ea817844330a187d20465a0192f904a39694089c3befc610fd8e1236d5e7cb3b19d2e1d5fc4019af31fbc80201870a7fec351119b307e79c83bb627b343a87668e1d68e60625212e40deb33c3d000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) + } } } From 1a7a9c9467c2f70588b525b681531dc839f58286 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 29 Jul 2021 11:14:59 -0300 Subject: [PATCH 13/17] mainnet checkpoints --- .../Constants/WalletBirthday+mainnet.swift | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/ZcashLightClientKit/Constants/WalletBirthday+mainnet.swift b/ZcashLightClientKit/Constants/WalletBirthday+mainnet.swift index 2d576e48..38980460 100644 --- a/ZcashLightClientKit/Constants/WalletBirthday+mainnet.swift +++ b/ZcashLightClientKit/Constants/WalletBirthday+mainnet.swift @@ -444,19 +444,54 @@ extension WalletBirthday { time: 1621056898, tree: "01c9a0dd6f6dfaaafe6ae4b432c2d1c41d2a73e564c8cb6d2c5ab637c7001a2456001300000000017da32b486a8ea9f13afb93b99d2b1de69aa969e7c2fd7b9ee958bece70c08d6b000001b3a4486b176dfcedc0b3d9287c0333ff464ecbd02bac7c89bcda7932e6a0a36100010d451c18b56877b8a11cb401ab7024c82b9669ede862a53e461087f57220035001a1c5260bc4dfe010510b8135209c6f64229965f71717f1e693abdcf88a58f36700012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" ) - case 1255000 ..< BlockHeight.max: + case 1255000 ..< 1300000: return WalletBirthday( height: 1255000, hash: "0000000000f34f274737e653cc31122e8ba8ca9865c09b65b3c2ecfb2e9687fd", time: 1621434019, tree: "016f51c78a2c55fef567e8deac7cb82b1f62f9ee6f5fdea27fc6fd9d1955e30353013f25aaa8aedcf10cd63b622d8c7dc21eb7b30504f99952bbc8efb437ffc482131301d0fa036d389289e37709f7f01d09e689cf55e989ea9d07440d593f21929f960801f69330a08f076f55f5db32aab6f2d1a2ab23e52a9a4e4fbbd21b8204ff23e64d00012f1469ddab73380dc3302f1cdbefb508141e2689a83b754fd9970037eb04fe6a00000000014ba6ac078f45c360c912ef828c138e4bd7d4150cadb2a498a32ec3fe7e22cc720001638de702094b20c64bc4b046cf7724634096aa192b155d191934120653734414013027101973e524ee59f21261bbf9fc152a61856a00f876a7c2b4dec71d50e969012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" ) + case 1300000 ..< 1310000: + return WalletBirthday( + height: 1300000, + hash: "00000000027222bdbcf9c5f807f851f97312ac6e0dbbc2b93f2be21a69c59d44", + time: 1624830312, + tree: "01f5a97e2679a2bb9103caf37b825f92fcd73fff836234844dfcf1815394522b2c01526587b9b9e8aeb0eb572d81fec1f5127b8278ba0f57e451bd6b796596940a2213000131c7ff90fafff6159b8fb6544a2bcbba6c102903158fce8f9a9d3c6654abb23300013555cb7f4f79badeaca9bf2dca5a8704f0929053d50e95c03002f9a4d5286c3a01ad3557e11c1607ec888dc84f5f8899c3c79fb1f50b613946452ec7dd5e53763c0001c4583f4482b949390dba355fc8fa63019c83acd644ddd633cb50211d236f870600000001088da0d78eefd0c222507927e403b972d0890d0c31e08b02268fbe39ac4a6e170001edf82d4e2b4893ea2028ca8c5149e50a4c358b856d73f2de2b9a22034fa78f22012ffde6dccbef68b60cd7b4e7a8fe7989f5954fa4bacad01b247d16b9bfa5084000000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1310000 ..< 1320000: + return WalletBirthday( + height: 1310000, + hash: "00000000011ced7ee934fe237a80b74f04901db85fa82a4eec008fbb11ecf2e5", + time: 1625583320, + tree: "014be5784c617834157df657bafbc419ca3930f25deddaa9f29fc17483b235524800130001cc95eae2b1c3759963275342e56f1b71cd0bb6a4e2c0405f0108eb96f668851201f559a0e5f1b41af70fd6daccb0a48c3c178dfd8d25c09ff5152abded864a264f000000010bf2a42d0faed94259d4747ef48adaedf5772ebc93211f89be1612c1a9644603019f067dfc649ee5291bdf3caf7a307fb939eceb716c5050b63f620f0e41e1724400000000000001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1320000 ..< 1330000: + return WalletBirthday( + height: 1320000, + hash: "00000000001dd2deed141caa32a167fc9c11dc2d95f76f7cdda9f50326411309", + time: 1626337252, + tree: "018095da27911b257bdeaa799f1c36be3767f8ef268e1f232263e88df0aa7b4f6300130001e4e456c3aa306bf54a77176e2462715076b3586fe36716bfc3ec113a239fdb3c0000014e4fa821d93b8944df3d5500fd71b3fca0f4c2a6add80137f7b3379fdc56a4260000000000011cc990619b9371b0240cf3038e8b3b0aaa6c50e78db250a77f0b4c63f49d811a019b4b90179cf9bf8c7556caacf6acb77ac97620777d2dff5be661e576cac55f22000001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1330000 ..< 1336316: + return WalletBirthday( + height: 1330000, + hash: "0000000001126cdf85b463d086c6bf54d67094f6e17db3b08e38c2b4b16de926", + time: 1627091654, + tree: "016cc0651c73617064bf6de5962c99ec81fdce76d58ac2aab8b881e3b35991486d01593438b57eb9cfa76d5ea965b77a0304ff46163846c7c1ffb2695419a8dbfd4c1301e9766721a57a35e08763a27244291cb7db2ca67a711fd0569fd78aa675a21e1b019a9908d737043f786d7cdddbb22cb4d026c6c3221d34bd82bf4dc55acdd847640000000001de097ad39006362760b514f69a3aa88c66ada02085de26de23b522167df616320000000001a090ee174239a34a5d684425d09006d238c6075a61c5842d0fc26043f09ccd7001a2b7ee187c7b8ce18ebda8600bed7695b12f7d35ac971ed6ee67184a7ceebd490001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) + case 1336316 ..< BlockHeight.max: + return WalletBirthday( + height: 1336316, + hash: "000000000196f12f0d91c95f0acc391454bf81901e95645e5fcd1935bd59ae27", + time: 1627567384, + tree: "0178d99ba141a858548143bfc60443bc965c8abcf4c0be7eca28b7681dfbc64c400013000141a76d7e56cf73013cb8c6549f90601a3d0a0c4057ca4f2b5515986c29d8710b01c21a76fc8075ae365db50bff0a03d674ab8dddd6e167a1c61125168365b40e40013338e3fef636235ace2523ae0d458508e795d04d7c49a77fa32032f45c482714000001fadad4c3da753327273cff5f827ac6a2da9cdf9554fb8e4ae1d73b0beb2b4a5a00012510c0b1bbca57be1267cba3c8e8e28c7457a3580f32fef3ad1ab5c117263e6401ea5e9a0276d6f23b8da7c2006a85277d92badb145c62334243205676b2ec971f012965494015cdab2ce010c1ae4ea88306c286128275de391dcf57d3fa85be7e1b01a090ee174239a34a5d684425d09006d238c6075a61c5842d0fc26043f09ccd7001a2b7ee187c7b8ce18ebda8600bed7695b12f7d35ac971ed6ee67184a7ceebd490001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + ) default: return WalletBirthday( - height: 1255000, - hash: "0000000000f34f274737e653cc31122e8ba8ca9865c09b65b3c2ecfb2e9687fd", - time: 1621434019, - tree: "016f51c78a2c55fef567e8deac7cb82b1f62f9ee6f5fdea27fc6fd9d1955e30353013f25aaa8aedcf10cd63b622d8c7dc21eb7b30504f99952bbc8efb437ffc482131301d0fa036d389289e37709f7f01d09e689cf55e989ea9d07440d593f21929f960801f69330a08f076f55f5db32aab6f2d1a2ab23e52a9a4e4fbbd21b8204ff23e64d00012f1469ddab73380dc3302f1cdbefb508141e2689a83b754fd9970037eb04fe6a00000000014ba6ac078f45c360c912ef828c138e4bd7d4150cadb2a498a32ec3fe7e22cc720001638de702094b20c64bc4b046cf7724634096aa192b155d191934120653734414013027101973e524ee59f21261bbf9fc152a61856a00f876a7c2b4dec71d50e969012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" + height: 1336316, + hash: "000000000196f12f0d91c95f0acc391454bf81901e95645e5fcd1935bd59ae27", + time: 1627567384, + tree: "0178d99ba141a858548143bfc60443bc965c8abcf4c0be7eca28b7681dfbc64c400013000141a76d7e56cf73013cb8c6549f90601a3d0a0c4057ca4f2b5515986c29d8710b01c21a76fc8075ae365db50bff0a03d674ab8dddd6e167a1c61125168365b40e40013338e3fef636235ace2523ae0d458508e795d04d7c49a77fa32032f45c482714000001fadad4c3da753327273cff5f827ac6a2da9cdf9554fb8e4ae1d73b0beb2b4a5a00012510c0b1bbca57be1267cba3c8e8e28c7457a3580f32fef3ad1ab5c117263e6401ea5e9a0276d6f23b8da7c2006a85277d92badb145c62334243205676b2ec971f012965494015cdab2ce010c1ae4ea88306c286128275de391dcf57d3fa85be7e1b01a090ee174239a34a5d684425d09006d238c6075a61c5842d0fc26043f09ccd7001a2b7ee187c7b8ce18ebda8600bed7695b12f7d35ac971ed6ee67184a7ceebd490001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644" ) } } From 4d12e856fc6e4bcf1f3059696f2d7474f7a8b2e2 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 29 Jul 2021 12:02:09 -0300 Subject: [PATCH 14/17] update to xcode 12.2 environment on travis --- .travis.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35c365e1..2d341423 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: swift os: osx -osx_image: xcode12.2 +osx_image: xcode12.5 xcode_workspace: ./Example/ZcashLightClientSample/ZcashLightClientSample.xcworkspace xcode_scheme: ZcashLightClientSample xcode_destination: platform=iOS Simulator,OS=14.2,name=iPhone 8 @@ -9,9 +9,6 @@ addons: packages: - rustup-init - sourcery -env: - global: - - ZCASH_NETWORK_ENVIRONMENT: TESTNET install: - ${TRAVIS_BUILD_DIR}/Scripts/travis/rust_setup.sh - ${TRAVIS_BUILD_DIR}/Scripts/travis/ZcashLightClientSample_setup.sh @@ -19,4 +16,4 @@ install: - curl https://z.cash/downloads/sapling-output.params > ${TRAVIS_BUILD_DIR}/ZcashLightClientKitTests/sapling-spend.params script: - swiftlint - - travis_wait 60 xcodebuild -quiet -UseModernBuildSystem=NO -workspace ./Example/ZcashLightClientSample/ZcashLightClientSample.xcworkspace -scheme ZcashLightClientSample -destination platform\=iOS\ Simulator,OS\=14.2,name\=iPhone\ 8 build + - travis_wait 60 xcodebuild -quiet -UseModernBuildSystem=NO -workspace ./Example/ZcashLightClientSample/ZcashLightClientSample.xcworkspace -scheme ZcashLightClientSample -destination platform\=iOS\ Simulator,OS\=14.5,name\=iPhone\ 8 build From b6873cf8df6fcda81022001fc62f5bfd04de8e8b Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 29 Jul 2021 14:11:21 -0300 Subject: [PATCH 15/17] changelog up to 0.12.0-alpha.11 --- changelog.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/changelog.md b/changelog.md index 0d2be03e..613f9570 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,50 @@ +# 0.12.0-alpha.11 +* [Enhancement] Network Agnostic build + +# 0.12.0-alpha.10 +* Fix: UNIQUE Constraint bug when coming from background. fixed and logged warning to keep investigating +* [New] latestScannedHeight added to SDKSynchronizer + +# 0.12.0-alpha.9 +* CompactBlockProcessor states don't propagate correctly + +# 0.12.0-alpha.8 +* target height reporting enhancements + +# 0.12.0-alpha.7 +* improve status publishing for SDKSynchronizer +* [FIX] missingStartHeight error when scanning from sapling activation + +# 0.12.0-alpha.6 +* Make sapling parameters default url public + +# 0.12.0-alpha.5 +* add output files to build phase to avoid CI failures +* fix lint warnings + +# 0.12.0-alpha.4 +* Tests +* [Fix] Issue #289 main thread lock when validating the server +* [Fix] info single call times out all the time +* make sure operations cancel in a timely manner +* FigureNextBatchOperation.swift tests +* make range function static + +# tag: 0.12.0-alpha.3 +* getInfo service times out too soon +# 0.12.0-alpha.2 +* FIX: processor stalls on reconnection +* Fix warnings +# 0.12.0-alpha.1 +* Replace Status for SyncStatus +* fix tests +* Fix Demo App +* fetch operation does not cancel when the previous operations do +* Fix: operations start when they have been canceled already +* fix progress being > 1 +* Synchronizing by phases, preview +* Add fetch UTXO operation to compact block processor +* CompactBlock batch download and stream download operation tests pass. # 0.11.1 * [Enhancement] Rewind API has a `.quick` option # 0.11.0 From d544c3c96c3ed4a788a6ddd2070df0df0afc1256 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 29 Jul 2021 18:55:22 -0300 Subject: [PATCH 16/17] Issue #292 Shielding funds take too many confirmations --- rust/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 92a6a3ad..58545003 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -11,7 +11,7 @@ use zcash_client_backend::{ data_api::{ chain::{scan_cached_blocks, validate_chain}, error::Error, - wallet::{create_spend_to_address, decrypt_and_store_transaction, shield_funds, ANCHOR_OFFSET}, + wallet::{create_spend_to_address, decrypt_and_store_transaction, shield_funds}, WalletRead, }, encoding::{ @@ -1399,7 +1399,7 @@ pub extern "C" fn zcashlc_shield_funds( &sk, &extsk, &memo_bytes, - ANCHOR_OFFSET) + 0) // fix off-by-one error. 10 confs already added in this function .map_err(|e| format_err!("Error while shielding transaction: {}", e)) }); unwrap_exc_or(res, -1) From 12eab8c6dba83827f92043d74a4bd08b1a34bc2a Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 29 Jul 2021 19:00:45 -0300 Subject: [PATCH 17/17] bump version to alpha12 --- Example/ZcashLightClientSample/Podfile.lock | 8 ++++---- ZcashLightClientKit.podspec | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/ZcashLightClientSample/Podfile.lock b/Example/ZcashLightClientSample/Podfile.lock index 8a7d4da9..a8665a9c 100644 --- a/Example/ZcashLightClientSample/Podfile.lock +++ b/Example/ZcashLightClientSample/Podfile.lock @@ -68,13 +68,13 @@ PODS: - SwiftNIOFoundationCompat (< 3, >= 2.19.0) - SwiftNIOTLS (< 3, >= 2.19.0) - SwiftProtobuf (1.16.0) - - ZcashLightClientKit (0.12.0-alpha.11): + - ZcashLightClientKit (0.12.0-alpha.12): - gRPC-Swift (= 1.0.0) - SQLite.swift (~> 0.12.2) - - ZcashLightClientKit/DerivationToolTests (0.12.0-alpha.11): + - ZcashLightClientKit/DerivationToolTests (0.12.0-alpha.12): - gRPC-Swift (= 1.0.0) - SQLite.swift (~> 0.12.2) - - ZcashLightClientKit/Tests (0.12.0-alpha.11): + - ZcashLightClientKit/Tests (0.12.0-alpha.12): - gRPC-Swift (= 1.0.0) - SQLite.swift (~> 0.12.2) @@ -153,7 +153,7 @@ SPEC CHECKSUMS: SwiftNIOTLS: 4f8df225f03393f08e0b47b4d876ae38167f8a27 SwiftNIOTransportServices: 896c9a4ac98698d32aa2feea7657ade219ae80bb SwiftProtobuf: 4e16842b83c6fda06b10fac50d73b3f1fce8ab7b - ZcashLightClientKit: 41e62975ad5dac49dd5f9430927e621fa7ec6a39 + ZcashLightClientKit: 386288e87e90446638c2314a7b4f3f1ffeee40b5 PODFILE CHECKSUM: 0e90dc69ac4c19fd97c0ce4835ece810d79ade23 diff --git a/ZcashLightClientKit.podspec b/ZcashLightClientKit.podspec index 0428453e..eba7d4f9 100644 --- a/ZcashLightClientKit.podspec +++ b/ZcashLightClientKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'ZcashLightClientKit' - s.version = '0.12.0-alpha.11' + s.version = '0.12.0-alpha.12' s.summary = 'Zcash Light Client wallet SDK for iOS' s.description = <<-DESC