From 8895038c40239c07072f8c6a4f7318a76044b7a0 Mon Sep 17 00:00:00 2001 From: DanS Date: Sat, 10 Oct 2026 09:50:03 -0500 Subject: [PATCH] test(lite-backend): port the core-crate tests to the current API The lite backend core's in-crate tests no longer compiled (119 errors in lightwallet/tests.rs and the lightclient and walletzkey test modules): they still used the old LightWallet::new and send_to_address signatures, the removed extfvks/extsks/zaddress fields and the old new_from_phrase and do_send arities. So `cargo test` built nothing and no backend change could be checked against them. Port them, and the commands and checkpoints tests, to the current API, touching only #[cfg(test)] code: - LightWallet::new takes 4 arguments, send_to_address 7 (with an explicit default fee, returning (txid, raw tx)), new_from_phrase 5 and do_send 2; keys are read through zkeys and tkeys; - every config uses the "main" chain: creating a wallet on the "test" chain panics in base58_pubkey_address, so LightClient::unconnected (which hard-codes "test") is no longer used; - every LightClient lives in a temporary data dir, so a test cannot write to the real ~/.silentdragonxlite or ~/.zcash-params; - ten send_to_address recipient lists garbled by an upstream change in 2020 are restored from the upstream history. Expectations that contradicted deliberate current behaviour are updated; none is ignored: - a pending send's mempool entry sits at the tip, not tip+1, and zbalance no longer counts a note with a pending spend; - keys cannot be added to an encrypted wallet, so the encrypted-receive tests derive their second address before encrypting; - the t-address vectors are m/44'/141'/0'/0/{0,1}, checked against an independent BIP32 derivation; the z-address vectors record the current output; - test_addresses and test_checkpoints follow the current address count and checkpoint tables. All 43 tests pass on the unchanged production code (three runs) and leave the real wallet and params directories untouched; that list is the regression baseline for the following commits. They cover balances, address derivation, bookkeeping, the mempool, encryption, serialization and rollback, but none verifies a proof, an anchor or a witness. Co-Authored-By: Claude Opus 5.5 --- .../silentdragonxlite-cli/lib/src/commands.rs | 9 +- .../lib/src/lightclient.rs | 42 ++- .../lib/src/lightclient/checkpoints.rs | 15 +- .../lib/src/lightwallet/tests.rs | 297 +++++++++--------- .../lib/src/lightwallet/walletzkey.rs | 1 + 5 files changed, 196 insertions(+), 168 deletions(-) diff --git a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/commands.rs b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/commands.rs index f90b67a..3c4c222 100644 --- a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/commands.rs +++ b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/commands.rs @@ -980,8 +980,9 @@ pub fn do_user_command(cmd: &str, args: &Vec<&str>, lightclient: &LightClient) - #[cfg(test)] pub mod tests { use lazy_static::lazy_static; + use tempdir::TempDir; use super::do_user_command; - use crate::lightclient::{LightClient}; + use crate::lightclient::{LightClient, LightClientConfig}; lazy_static!{ static ref TEST_SEED: String = "youth strong sweet gorilla hammer unhappy congress stamp left stereo riot salute road tag clean toilet artefact fork certain leopard entire civil degree wonder".to_string(); @@ -989,7 +990,11 @@ pub mod tests { #[test] pub fn test_command_caseinsensitive() { - let lc = LightClient::unconnected(TEST_SEED.to_string(), None).unwrap(); + // "main" chain in a temp data dir: LightClient::unconnected uses the "test" chain, which + // panics when the wallet is created, and no data dir would mean the real wallet directory. + let tmp = TempDir::new("cmdtest").unwrap(); + let config = LightClientConfig::create_unconnected("main".to_string(), tmp.path().to_str().map(|s| s.to_string())); + let lc = LightClient::new_from_phrase(TEST_SEED.to_string(), &config, 0, 0, false).unwrap(); assert_eq!(do_user_command("addresses", &vec![], &lc), do_user_command("AddReSSeS", &vec![], &lc)); diff --git a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient.rs b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient.rs index 8872eb1..8b76b29 100644 --- a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient.rs +++ b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient.rs @@ -1758,9 +1758,17 @@ pub mod tests { static ref TEST_SEED: String = "youth strong sweet gorilla hammer unhappy congress stamp left stereo riot salute road tag clean toilet artefact fork certain leopard entire civil degree wonder".to_string(); } + // Every client here is on the "main" chain (the "test" chain, which LightClient::unconnected + // hard-codes, panics in base58_pubkey_address when the wallet is created) and lives in a temp + // data dir, so nothing is ever written to the real ~/.silentdragonxlite. + fn main_config(tmp: &TempDir) -> LightClientConfig { + LightClientConfig::create_unconnected("main".to_string(), tmp.path().to_str().map(|s| s.to_string())) + } + #[test] pub fn test_encrypt_decrypt() { - let lc = super::LightClient::unconnected(TEST_SEED.to_string(), None).unwrap(); + let tmp = TempDir::new("lctest").unwrap(); + let lc = LightClient::new_from_phrase(TEST_SEED.to_string(), &main_config(&tmp), 0, 0, false).unwrap(); assert!(!lc.do_export(None).is_err()); assert!(!lc.do_new_address("zs").is_err()); @@ -1773,7 +1781,7 @@ pub mod tests { assert!(lc.do_seed_phrase().is_err()); assert!(lc.do_new_address("R").is_err()); assert!(lc.do_new_address("zs").is_err()); - assert!(lc.do_send(vec![("zs", 0, None)]).is_err()); + assert!(lc.do_send(vec![("zs", 0, None)], &10000).is_err()); // Do a unlock, and make sure it all works now lc.wallet.write().unwrap().unlock("password".to_string()).unwrap(); @@ -1793,11 +1801,12 @@ pub mod tests { #[test] pub fn test_addresses() { - let lc = super::LightClient::unconnected(TEST_SEED.to_string(), None).unwrap(); + let tmp = TempDir::new("lctest").unwrap(); + let lc = LightClient::new_from_phrase(TEST_SEED.to_string(), &main_config(&tmp), 0, 50, false).unwrap(); { let addresses = lc.do_address(); - // When restoring from seed, there should be 5+1 addresses + // When restoring from seed with 50 extra z-addresses, there should be 50+1 z and 5+1 t addresses assert_eq!(addresses["z_addresses"].len(), 51); assert_eq!(addresses["t_addresses"].len(), 6); } @@ -1811,21 +1820,23 @@ pub mod tests { let addresses = lc.do_address(); - assert_eq!(addresses["z_addresses"].len(), 52); - assert_eq!(addresses["z_addresses"][49], zaddr1); - assert_eq!(addresses["z_addresses"][50], zaddr2); + assert_eq!(addresses["z_addresses"].len(), 53); + assert_eq!(addresses["z_addresses"][51], zaddr1); + assert_eq!(addresses["z_addresses"][52], zaddr2); assert_eq!(addresses["t_addresses"].len(), 8); assert_eq!(addresses["t_addresses"][6], taddr1); assert_eq!(addresses["t_addresses"][7], taddr2); use std::sync::{Arc, RwLock, Mutex}; + use std::sync::atomic::AtomicBool; use crate::lightclient::{WalletStatus, LightWallet}; // When creating a new wallet, there is only 1 address - let config = LightClientConfig::create_unconnected("test".to_string(), None); + let tmp2 = TempDir::new("lctest").unwrap(); + let config = main_config(&tmp2); let lc = LightClient { - wallet : Arc::new(RwLock::new(LightWallet::new(None, &config, 0).unwrap())), + wallet : Arc::new(RwLock::new(LightWallet::new(None, &config, 0, 0).unwrap())), config : config, sapling_output : vec![], sapling_spend : vec![], @@ -1843,7 +1854,8 @@ pub mod tests { #[test] pub fn test_bad_import() { - let lc = super::LightClient::unconnected(TEST_SEED.to_string(), None).unwrap(); + let tmp = TempDir::new("lctest").unwrap(); + let lc = LightClient::new_from_phrase(TEST_SEED.to_string(), &main_config(&tmp), 0, 0, false).unwrap(); assert!(lc.do_import_sk("bad_priv_key".to_string(), 0).is_err()); assert!(lc.do_import_vk("bad_view_key".to_string(), 0).is_err()); @@ -1857,7 +1869,7 @@ pub fn test_bad_import() { let dir_name = tmp.path().to_str().map(|s| s.to_string()); // A lightclient to a new, empty directory works. - let config = LightClientConfig::create_unconnected("test".to_string(), dir_name); + let config = LightClientConfig::create_unconnected("main".to_string(), dir_name); let lc = LightClient::new(&config, 0).unwrap(); let seed = lc.do_seed_phrase().unwrap()["seed"].as_str().unwrap().to_string(); lc.do_save().unwrap(); @@ -1866,7 +1878,7 @@ pub fn test_bad_import() { assert!(LightClient::new(&config, 0).is_err()); // new_from_phrase will not work either, again, because wallet file exists - assert!(LightClient::new_from_phrase(TEST_SEED.to_string(), &config, 0, false).is_err()); + assert!(LightClient::new_from_phrase(TEST_SEED.to_string(), &config, 0, 0, false).is_err()); // Creating a lightclient to the same dir without a seed should re-read the same wallet // file and therefore the same seed phrase @@ -1879,13 +1891,13 @@ pub fn test_bad_import() { let tmp = TempDir::new("lctest").unwrap(); let dir_name = tmp.path().to_str().map(|s| s.to_string()); - let config = LightClientConfig::create_unconnected("test".to_string(), dir_name); + let config = LightClientConfig::create_unconnected("main".to_string(), dir_name); // read_from_disk will fail, because the dir doesn't exist assert!(LightClient::read_from_disk(&config).is_err()); // New from phrase should work becase a file doesn't exist already - let lc = LightClient::new_from_phrase(TEST_SEED.to_string(), &config, 0, false).unwrap(); + let lc = LightClient::new_from_phrase(TEST_SEED.to_string(), &config, 0, 0, false).unwrap(); assert_eq!(TEST_SEED.to_string(), lc.do_seed_phrase().unwrap()["seed"].as_str().unwrap().to_string()); lc.do_save().unwrap(); @@ -1902,7 +1914,7 @@ pub fn test_bad_import() { let dir_name = tmp.path().to_str().map(|s| s.to_string()); // A lightclient to a new, empty directory works. - let config = LightClientConfig::create_unconnected("test".to_string(), dir_name); + let config = LightClientConfig::create_unconnected("main".to_string(), dir_name); let lc = LightClient::new(&config, 0).unwrap(); let seed = lc.do_seed_phrase().unwrap()["seed"].as_str().unwrap().to_string(); lc.do_save().unwrap(); diff --git a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient/checkpoints.rs b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient/checkpoints.rs index bf5741a..603f682 100644 --- a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient/checkpoints.rs +++ b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightclient/checkpoints.rs @@ -1007,15 +1007,16 @@ pub mod tests { #[test] fn test_checkpoints() { + // Heights follow the current tables: test {130000, 152000}; main every 10000 from 10000. assert_eq!(get_test_checkpoint(100000), None); - assert_eq!(get_test_checkpoint(120000).unwrap().0, 120000); - assert_eq!(get_test_checkpoint(125000).unwrap().0, 120000); - assert_eq!(get_test_checkpoint(157000).unwrap().0, 157000); - assert_eq!(get_test_checkpoint(175000).unwrap().0, 157000); + assert_eq!(get_test_checkpoint(130000).unwrap().0, 130000); + assert_eq!(get_test_checkpoint(135000).unwrap().0, 130000); + assert_eq!(get_test_checkpoint(152000).unwrap().0, 152000); + assert_eq!(get_test_checkpoint(175000).unwrap().0, 152000); - assert_eq!(get_main_checkpoint(100000), None); - assert_eq!(get_main_checkpoint(170947).unwrap().0, 170947); - assert_eq!(get_main_checkpoint(170949).unwrap().0, 170947); + assert_eq!(get_main_checkpoint(9999), None); + assert_eq!(get_main_checkpoint(170000).unwrap().0, 170000); + assert_eq!(get_main_checkpoint(170947).unwrap().0, 170000); } } diff --git a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/tests.rs b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/tests.rs index fb43756..65339fc 100644 --- a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/tests.rs +++ b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/tests.rs @@ -45,6 +45,11 @@ fn get_sapling_params() -> Result<(Vec, Vec), Error> { Ok((sapling_spend, sapling_output)) } +// send_to_address now takes the fee explicitly; the tests send with the default fee. +fn default_fee() -> u64 { + u64::from(DEFAULT_FEE) +} + struct FakeCompactBlock { block: CompactBlock, } @@ -290,15 +295,15 @@ impl FakeTransaction { #[test] fn test_z_balances() { - let wallet = LightWallet::new(None, &get_test_config(), 0).unwrap(); + let wallet = LightWallet::new(None, &get_test_config(), 0, 0).unwrap(); const AMOUNT1:u64 = 5; // Address is encoded in bech32 let address = Some(encode_payment_address(wallet.config.hrp_sapling_address(), - &wallet.extfvks.read().unwrap()[0].default_address().unwrap().1)); + &wallet.zkeys.read().unwrap()[0].extfvk.default_address().unwrap().1)); let mut cb1 = FakeCompactBlock::new(0, BlockHash([0; 32])); - cb1.add_tx_paying(wallet.extfvks.read().unwrap()[0].clone(), AMOUNT1); + cb1.add_tx_paying(wallet.zkeys.read().unwrap()[0].extfvk.clone(), AMOUNT1); // Make sure that the intial state is empty assert_eq!(wallet.txs.read().unwrap().len(), 0); @@ -317,7 +322,7 @@ fn test_z_balances() { // Add a second block let mut cb2 = FakeCompactBlock::new(1, cb1.hash()); - cb2.add_tx_paying(wallet.extfvks.read().unwrap()[0].clone(), AMOUNT2); + cb2.add_tx_paying(wallet.zkeys.read().unwrap()[0].extfvk.clone(), AMOUNT2); wallet.scan_block(&cb2.as_bytes()).unwrap(); @@ -329,13 +334,13 @@ fn test_z_balances() { #[test] fn test_z_change_balances() { - let wallet = LightWallet::new(None, &get_test_config(), 0).unwrap(); + let wallet = LightWallet::new(None, &get_test_config(), 0, 0).unwrap(); // First, add an incoming transaction const AMOUNT1:u64 = 5; let mut cb1 = FakeCompactBlock::new(0, BlockHash([0; 32])); - let (nf1, txid1) = cb1.add_tx_paying(wallet.extfvks.read().unwrap()[0].clone(), AMOUNT1); + let (nf1, txid1) = cb1.add_tx_paying(wallet.zkeys.read().unwrap()[0].extfvk.clone(), AMOUNT1); wallet.scan_block(&cb1.as_bytes()).unwrap(); @@ -349,7 +354,7 @@ fn test_z_change_balances() { let addr2 = ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[0u8; 32])) .default_address().unwrap().1; let mut cb2 = FakeCompactBlock::new(1, cb1.hash()); - let txid2 = cb2.add_tx_spending((nf1, AMOUNT1), wallet.extfvks.read().unwrap()[0].clone(), addr2, AMOUNT2); + let txid2 = cb2.add_tx_spending((nf1, AMOUNT1), wallet.zkeys.read().unwrap()[0].extfvk.clone(), addr2, AMOUNT2); wallet.scan_block(&cb2.as_bytes()).unwrap(); // Now, the original note should be spent and there should be a change @@ -378,10 +383,10 @@ fn test_t_receive_spend() { let mut rng = OsRng; let secp = Secp256k1::new(); - let wallet = LightWallet::new(None, &get_test_config(), 0).unwrap(); + let wallet = LightWallet::new(None, &get_test_config(), 0, 0).unwrap(); - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0]); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0].tkey.unwrap()); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); const AMOUNT1: u64 = 20; @@ -444,10 +449,10 @@ fn test_t_receive_spend_among_tadds() { let mut rng = OsRng; let secp = Secp256k1::new(); - let wallet = LightWallet::new(None, &get_test_config(), 0).unwrap(); + let wallet = LightWallet::new(None, &get_test_config(), 0, 0).unwrap(); - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0]); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0].tkey.unwrap()); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); let non_wallet_sk = &SecretKey::from_slice(&[1u8; 32]).unwrap(); let non_wallet_pk = PublicKey::from_secret_key(&secp, &non_wallet_sk); @@ -513,13 +518,13 @@ fn test_serialization() { let secp = Secp256k1::new(); let config = get_test_config(); - let wallet = LightWallet::new(None, &config, 0).unwrap(); + let wallet = LightWallet::new(None, &config, 0, 0).unwrap(); // First, add an incoming transaction const AMOUNT1:u64 = 5; let mut cb1 = FakeCompactBlock::new(0, BlockHash([0; 32])); - let (nf1, txid1) = cb1.add_tx_paying(wallet.extfvks.read().unwrap()[0].clone(), AMOUNT1); + let (nf1, txid1) = cb1.add_tx_paying(wallet.zkeys.read().unwrap()[0].extfvk.clone(), AMOUNT1); wallet.scan_block(&cb1.as_bytes()).unwrap(); @@ -528,8 +533,8 @@ fn test_serialization() { assert_eq!(wallet.zbalance(None), AMOUNT1); // Add a t input at the Tx - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0]); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0].tkey.unwrap()); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); const TAMOUNT1: u64 = 20; @@ -543,7 +548,7 @@ fn test_serialization() { let addr2 = ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[0u8; 32])) .default_address().unwrap().1; let mut cb2 = FakeCompactBlock::new(1, cb1.hash()); - let txid2 = cb2.add_tx_spending((nf1, AMOUNT1), wallet.extfvks.read().unwrap()[0].clone(), addr2, AMOUNT2); + let txid2 = cb2.add_tx_spending((nf1, AMOUNT1), wallet.zkeys.read().unwrap()[0].extfvk.clone(), addr2, AMOUNT2); wallet.scan_block(&cb2.as_bytes()).unwrap(); let mut tx = FakeTransaction::new_with_txid(txid2); @@ -564,10 +569,10 @@ fn test_serialization() { { assert_eq!(wallet.seed, wallet2.seed); - assert_eq!(wallet.extsks.read().unwrap().len(), wallet2.extsks.read().unwrap().len()); - assert_eq!(wallet.extsks.read().unwrap()[0], wallet2.extsks.read().unwrap()[0]); - assert_eq!(wallet.extfvks.read().unwrap()[0], wallet2.extfvks.read().unwrap()[0]); - assert_eq!(wallet.zaddress.read().unwrap()[0], wallet2.zaddress.read().unwrap()[0]); + assert_eq!(wallet.zkeys.read().unwrap().len(), wallet2.zkeys.read().unwrap().len()); + assert_eq!(wallet.zkeys.read().unwrap()[0].extsk, wallet2.zkeys.read().unwrap()[0].extsk); + assert_eq!(wallet.zkeys.read().unwrap()[0].extfvk, wallet2.zkeys.read().unwrap()[0].extfvk); + assert_eq!(wallet.zkeys.read().unwrap()[0].zaddress, wallet2.zkeys.read().unwrap()[0].zaddress); assert_eq!(wallet.tkeys.read().unwrap().len(), wallet2.tkeys.read().unwrap().len()); assert_eq!(wallet.tkeys.read().unwrap()[0], wallet2.tkeys.read().unwrap()[0]); @@ -621,12 +626,12 @@ fn test_serialization() { fn test_multi_serialization() { let config = get_test_config(); - let wallet = LightWallet::new(None, &config, 0).unwrap(); + let wallet = LightWallet::new(None, &config, 0, 0).unwrap(); - let taddr1 = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let taddr1 = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); let taddr2 = wallet.add_taddr(); - let (zaddr1, zpk1) = &wallet.get_z_private_keys()[0]; + let (zaddr1, zpk1, _) = &wallet.get_z_private_keys()[0]; let zaddr2 = wallet.add_zaddr(); let mut serialized_data = vec![]; @@ -634,15 +639,13 @@ fn test_multi_serialization() { let wallet2 = LightWallet::read(&serialized_data[..], &config).unwrap(); assert_eq!(wallet2.tkeys.read().unwrap().len(), 2); - assert_eq!(wallet2.extsks.read().unwrap().len(), 2); - assert_eq!(wallet2.extfvks.read().unwrap().len(), 2); - assert_eq!(wallet2.zaddress.read().unwrap().len(), 2); + assert_eq!(wallet2.zkeys.read().unwrap().len(), 2); - assert_eq!(taddr1, wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0])); - assert_eq!(taddr2, wallet.address_from_sk(&wallet.tkeys.read().unwrap()[1])); + assert_eq!(taddr1, wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap())); + assert_eq!(taddr2, wallet.address_from_sk(&wallet.tkeys.read().unwrap()[1].tkey.unwrap())); - let (w2_zaddr1, w2_zpk1) = &wallet.get_z_private_keys()[0]; - let (w2_zaddr2, _) = &wallet.get_z_private_keys()[1]; + let (w2_zaddr1, w2_zpk1, _) = &wallet.get_z_private_keys()[0]; + let (w2_zaddr2, _, _) = &wallet.get_z_private_keys()[1]; assert_eq!(zaddr1, w2_zaddr1); assert_eq!(zpk1, w2_zpk1); assert_eq!(zaddr2, *w2_zaddr2); @@ -652,7 +655,7 @@ fn test_multi_serialization() { fn get_test_config() -> LightClientConfig { LightClientConfig { server: "0.0.0.0:0".parse().unwrap(), - chain_name: "test".to_string(), + chain_name: "main".to_string(), sapling_activation_height: 0, consensus_branch_id: "000000".to_string(), anchor_offset: 0, @@ -665,10 +668,10 @@ fn get_test_config() -> LightClientConfig { fn get_test_wallet(amount: u64) -> (LightWallet, TxId, BlockHash) { let config = get_test_config(); - let wallet = LightWallet::new(None, &config, 0).unwrap(); + let wallet = LightWallet::new(None, &config, 0, 0).unwrap(); let mut cb1 = FakeCompactBlock::new(0, BlockHash([0; 32])); - let (_, txid1) = cb1.add_tx_paying(wallet.extfvks.read().unwrap()[0].clone(), amount); + let (_, txid1) = cb1.add_tx_paying(wallet.zkeys.read().unwrap()[0].extfvk.clone(), amount); wallet.scan_block(&cb1.as_bytes()).unwrap(); // We have one note @@ -713,8 +716,8 @@ fn test_z_spend_to_z() { } // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -733,7 +736,7 @@ fn test_z_spend_to_z() { { let mem = wallet.mempool_txs.read().unwrap(); - assert_eq!(mem[&sent_txid].block, 2); // block number is next block + assert_eq!(mem[&sent_txid].block, 1); // block number is the current tip (the fork targets the tip, d2887d0) assert! (mem[&sent_txid].datetime > 0); assert_eq!(mem[&sent_txid].txid, sent_txid); assert_eq!(mem[&sent_txid].outgoing_metadata.len(), 1); @@ -743,8 +746,9 @@ fn test_z_spend_to_z() { } { - // The wallet should deduct this from the verified balance. The zbalance still includes it - assert_eq!(wallet.zbalance(None), AMOUNT1); + // The wallet should deduct this from the verified balance. The zbalance excludes it too + // (since the fork's mempool integration, eff5dd7, pending spends are not in zbalance) + assert_eq!(wallet.zbalance(None), 0); assert_eq!(wallet.verified_zbalance(None), 0); } @@ -798,8 +802,8 @@ fn test_self_txns_ttoz_withmemo() { let (wallet, _txid1, block_hash) = get_test_wallet(0); - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0]); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0].tkey.unwrap()); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); const TAMOUNT1: u64 = 50000; @@ -828,8 +832,8 @@ fn test_self_txns_ttoz_withmemo() { let (ss, so) =get_sapling_params().unwrap(); // Create a tx and send to address. This should consume both the UTXO and the note - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&zaddr, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -857,8 +861,8 @@ fn test_self_txns_ttoz_nomemo() { let (wallet, _txid1, block_hash) = get_test_wallet(0); - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0]); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0].tkey.unwrap()); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); const TAMOUNT1: u64 = 50000; @@ -886,8 +890,8 @@ fn test_self_txns_ttoz_nomemo() { let (ss, so) =get_sapling_params().unwrap(); // Create a tx and send to address. This should consume both the UTXO and the note - let raw_tx = wallet.send_to_address(branch_id, &ss, &so, - vec![(&zaddr, AMOUNT_SENT, None)]).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&zaddr, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -922,8 +926,8 @@ fn test_self_txns_ztoz() { let (ss, so) =get_sapling_params().unwrap(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&zaddr2, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&zaddr2, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -942,8 +946,8 @@ fn test_self_txns_ztoz() { } // Another self tx, this time without a memo - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&zaddr2, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&zaddr2, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -978,8 +982,8 @@ fn test_multi_z() { let (ss, so) =get_sapling_params().unwrap(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&zaddr2, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&zaddr2, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1033,8 +1037,8 @@ fn test_multi_z() { let amount_all:u64 = (AMOUNT1 - AMOUNT_SENT - fee) + (AMOUNT_SENT) - fee; let taddr = wallet.address_from_sk(&SecretKey::from_slice(&[1u8; 32]).unwrap()); - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr, amount_all, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, amount_all, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_ext_txid = sent_tx.txid(); @@ -1075,8 +1079,8 @@ fn test_z_spend_to_taddr() { const AMOUNT_SENT: u64 = 30; let fee: u64 = DEFAULT_FEE.try_into().unwrap(); - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1123,8 +1127,8 @@ fn test_z_spend_to_taddr() { } // Create a new Tx, but this time with a memo. - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr, AMOUNT_SENT, Some("T address memo".to_string()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, AMOUNT_SENT, Some("T address memo".to_string()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid2 = sent_tx.txid(); @@ -1164,8 +1168,8 @@ fn test_t_spend_to_z() { const AMOUNT_T: u64 = 40000; let (wallet, txid1, block_hash) = get_test_wallet(AMOUNT_Z); - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0]); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap()[0].tkey.unwrap()); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); let mut tx = FakeTransaction::new(&mut rng); tx.add_t_output(&pk, AMOUNT_T); @@ -1198,8 +1202,8 @@ fn test_t_spend_to_z() { let (ss, so) =get_sapling_params().unwrap(); // Create a tx and send to address. This should consume both the UTXO and the note - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1263,7 +1267,7 @@ fn test_z_incoming_memo() { let (wallet, _txid1, block_hash) = get_test_wallet(AMOUNT1); let my_address = encode_payment_address(wallet.config.hrp_sapling_address(), - &wallet.extfvks.read().unwrap()[0].default_address().unwrap().1); + &wallet.zkeys.read().unwrap()[0].extfvk.default_address().unwrap().1); let memo = "Incoming Memo".to_string(); let fee: u64 = DEFAULT_FEE.try_into().unwrap(); @@ -1272,8 +1276,8 @@ fn test_z_incoming_memo() { let (ss, so) = get_sapling_params().unwrap(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&my_address, AMOUNT1 - fee, Some(memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1290,7 +1294,7 @@ fn test_z_incoming_memo() { assert_eq!(txs[&sent_txid].notes.len(), 1); - assert_eq!(txs[&sent_txid].notes[0].extfvk, wallet.extfvks.read().unwrap()[0]); + assert_eq!(txs[&sent_txid].notes[0].extfvk, wallet.zkeys.read().unwrap()[0].extfvk); assert_eq!(txs[&sent_txid].notes[0].note.value, AMOUNT1 - fee); assert_eq!(LightWallet::note_address(wallet.config.hrp_sapling_address(), &txs[&sent_txid].notes[0]), Some(my_address)); assert_eq!(LightWallet::memo_str(&txs[&sent_txid].notes[0].memo), Some(memo)); @@ -1305,18 +1309,18 @@ fn test_add_new_zt_hd_after_incoming() { // Get the last address let my_address = encode_payment_address(wallet.config.hrp_sapling_address(), - &wallet.extfvks.read().unwrap().last().unwrap().default_address().unwrap().1); + &wallet.zkeys.read().unwrap().last().unwrap().extfvk.default_address().unwrap().1); let fee: u64 = DEFAULT_FEE.try_into().unwrap(); let branch_id = u32::from_str_radix("2bb40e60", 16).unwrap(); let (ss, so) = get_sapling_params().unwrap(); - assert_eq!(wallet.zaddress.read().unwrap().len(), 6); // Starts with 1+5 addresses + assert_eq!(wallet.zkeys.read().unwrap().len(), 6); // Starts with 1+5 addresses // Create a tx and send to the last address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&my_address, AMOUNT1 - fee, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); // Add it to a block @@ -1325,15 +1329,15 @@ fn test_add_new_zt_hd_after_incoming() { wallet.scan_block(&cb3.as_bytes()).unwrap(); // NOw, 5 new addresses should be created - assert_eq!(wallet.zaddress.read().unwrap().len(), 6+5); + assert_eq!(wallet.zkeys.read().unwrap().len(), 6+5); let mut rng = OsRng; let secp = Secp256k1::new(); // Send a fake transaction to the last taddr - let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap().last().unwrap()); + let pk = PublicKey::from_secret_key(&secp, &wallet.tkeys.read().unwrap().last().unwrap().tkey.unwrap()); // Start with 1 taddr - assert_eq!(wallet.taddresses.read().unwrap().len(), 1); + assert_eq!(wallet.tkeys.read().unwrap().len(), 1); // Send a Tx to the last address let mut tx = FakeTransaction::new(&mut rng); @@ -1341,7 +1345,7 @@ fn test_add_new_zt_hd_after_incoming() { wallet.scan_full_tx(&tx.get_tx(), 3, 0); // Now, 5 new addresses should be created. - assert_eq!(wallet.taddresses.read().unwrap().len(), 1+5); + assert_eq!(wallet.tkeys.read().unwrap().len(), 1+5); } #[test] @@ -1350,7 +1354,7 @@ fn test_z_to_t_withinwallet() { const AMOUNT_SENT: u64 = 20000; let (wallet, txid1, block_hash) = get_test_wallet(AMOUNT); - let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let taddr = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); let fee: u64 = DEFAULT_FEE.try_into().unwrap(); @@ -1358,8 +1362,8 @@ fn test_z_to_t_withinwallet() { let (ss, so) = get_sapling_params().unwrap(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1418,8 +1422,8 @@ fn test_multi_t() { let (ss, so) = get_sapling_params().unwrap(); // Create a Tx and send to the second t address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr2, AMOUNT_SENT1, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid1 = sent_tx.txid(); @@ -1462,8 +1466,8 @@ fn test_multi_t() { let taddr3 = wallet.add_taddr(); // Create a Tx and send to the second t address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr3, AMOUNT_SENT2, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid2 = sent_tx.txid(); @@ -1499,8 +1503,8 @@ fn test_multi_t() { let outgoing_memo = "Outgoing Memo".to_string(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_address, AMOUNT_SENT_EXT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid3 = sent_tx.txid(); @@ -1557,7 +1561,7 @@ fn test_multi_spends() { (taddr2.as_str(), TAMOUNT2, None), (taddr3.as_str(), TAMOUNT3, None) ]; - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, tos, |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, tos, &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1629,7 +1633,7 @@ fn test_multi_spends() { let tos = vec![ (ext_address.as_str(), EXT_ZADDR_AMOUNT, Some(ext_memo.clone())), (ext_taddr.as_str(), ext_taddr_amount, None)]; - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, tos, |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, tos, &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid2 = sent_tx.txid(); @@ -1681,17 +1685,17 @@ fn test_bad_send() { let ext_taddr = wallet.address_from_sk(&SecretKey::from_slice(&[1u8; 32]).unwrap()); // Bad address - let raw_tx = wallet.send_to_address(branch_id, &ss, &so, - vec![(&"badaddress", 10, None)], |_| Ok(' '.to_string())); + let raw_tx = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&"badaddress", 10, None)], &default_fee(), |_| Ok(' '.to_string())); assert!(raw_tx.err().unwrap().contains("Invalid recipient address")); // Insufficient funds - let raw_tx = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_taddr, AMOUNT1 + 10, None)], |_| Ok(' '.to_string())); + let raw_tx = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_taddr, AMOUNT1 + 10, None)], &default_fee(), |_| Ok(' '.to_string())); assert!(raw_tx.err().unwrap().contains("Insufficient verified funds")); // No addresses - let raw_tx = wallet.send_to_address(branch_id, &ss, &so, vec![], |_| Ok(' '.to_string())); + let raw_tx = wallet.send_to_address(branch_id, &ss, &so, false, vec![], &default_fee(), |_| Ok(' '.to_string())); assert!(raw_tx.err().unwrap().contains("at least one")); } @@ -1709,10 +1713,10 @@ fn test_duplicate_outputs() { let ext_taddr = wallet.address_from_sk(&SecretKey::from_slice(&[1u8; 32]).unwrap()); // Duplicated addresses with memos are fine too - let raw_tx = wallet.send_to_address(branch_id, &ss, &so, + let raw_tx = wallet.send_to_address(branch_id, &ss, &so, false, vec![(&ext_taddr, 100, Some("First memo".to_string())), (&ext_taddr, 0, Some("Second memo".to_string())), - (&ext_taddr, 0, Some("Third memo".to_string()))], |_| Ok(' '.to_string())); + (&ext_taddr, 0, Some("Third memo".to_string()))], &default_fee(), |_| Ok(' '.to_string())); assert!(raw_tx.is_ok()); } @@ -1724,8 +1728,8 @@ fn test_bad_params() { let branch_id = u32::from_str_radix("76b809bb", 16).unwrap(); // Bad params - let _ = wallet.send_to_address(branch_id, &[], &[], - vec![(&ext_taddr, 10, None)], |_| Ok(' '.to_string())); + let _ = wallet.send_to_address(branch_id, &[], &[], false, + vec![(&ext_taddr, 10, None)], &default_fee(), |_| Ok(' '.to_string())); } /// Test helper to add blocks @@ -1761,8 +1765,8 @@ fn test_z_mempool_expiry() { let (ss, so) = get_sapling_params().unwrap(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1771,7 +1775,7 @@ fn test_z_mempool_expiry() { { let mem = wallet.mempool_txs.read().unwrap(); - assert_eq!(mem[&sent_txid].block, 2); // block number is next block + assert_eq!(mem[&sent_txid].block, 1); // block number is the current tip (the fork targets the tip, d2887d0) assert! (mem[&sent_txid].datetime > 0); assert_eq!(mem[&sent_txid].txid, sent_txid); assert_eq!(mem[&sent_txid].outgoing_metadata.len(), 1); @@ -1878,8 +1882,8 @@ fn test_rollback() { // Create a tx and send to address const AMOUNT_SENT: u64 = 30000; let fee: u64 = DEFAULT_FEE.try_into().unwrap(); - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); let sent_tx = Transaction::read(&raw_tx[..]).unwrap(); let sent_txid = sent_tx.txid(); @@ -1940,22 +1944,23 @@ fn test_t_derivation() { let seed_phrase = Some("chimney better bulb horror rebuild whisper improve intact letter giraffe brave rib appear bulk aim burst snap salt hill sad merge tennis phrase raise".to_string()); - let wallet = LightWallet::new(seed_phrase.clone(), &lc, 0).unwrap(); + let wallet = LightWallet::new(seed_phrase.clone(), &lc, 0, 0).unwrap(); - // Test the addresses against https://iancoleman.io/bip39/ + // t: m/44'/141'/0'/0/i, checked against an independent BIP39/BIP32 derivation. + // z: ZIP32 m/32'/141'/0' as produced by this crate (snapshot). let (taddr, pk) = &wallet.get_t_secret_keys()[0]; - assert_eq!(taddr, "RXBxhYDg8vSsHVmAGadniQKh3NvzAtzjRe"); - assert_eq!(pk, "UvGDnY7bpsyz9GnRPvMRQTMKHPyCK5k6c2FBiGQcgRSe9xVNuGGs"); + assert_eq!(taddr, "RUytX9weUJDFqmzZPh7iRm7n99ksh2HmXP"); + assert_eq!(pk, "UvdRFABcSj8uXtzdVAb72ddtrKB69UCLg4ykGfkFMKRcvSozEwNe"); // Test a couple more wallet.add_taddr(); let (taddr, pk) = &wallet.get_t_secret_keys()[1]; - assert_eq!(taddr, "RKDGjDoFHf9BfTFuL27voFdqdV7LhWw9rG"); - assert_eq!(pk, "UqGi6D8rFfdoEtbqhjz1utu1hKLmagY5TBVHWau54pput9HRfYbG"); + assert_eq!(taddr, "RMmVfFs82EvHEGny6zD3Hjf1C3Yz9jkQXf"); + assert_eq!(pk, "UqzH1HqvD1qyy6xS4fMnowPnDJis9h5VEN2qSUD1TPHa7qJp5WfP"); - let (zaddr, sk) = &wallet.get_z_private_keys()[0]; - assert_eq!(zaddr, "zs1wp96063hjs496d28e05uz5gavg7mwshhsgglchtan57el88uwa5jfdgk4nd68kda62vgwucfe6z"); - assert_eq!(sk, "secret-extended-key-main1qvkk0dn2qqqqpqrk6fl6c6fzzrmkhlj59d2c6kkz37hmal6d4dm69ne75xf0exuvnyk6qrjgp6crvdtaehkda2edg0llv488u25vjh5jtldnp53nrphqeexel57a0dn4t2kkcr6uj6y832yg8wsx3wx6t6rk470dynzdx3cp37xdwl9mpe59vj6yqh67x09vea9khzk5wdqkt65c6x9qkuht7nxyetthu0pr7jrwpthzq2ncgm0dvczadqxuhhk5ekua5v5zzw2kydcudu965"); + let (zaddr, sk, _) = &wallet.get_z_private_keys()[0]; + assert_eq!(zaddr, "zs1uqgg6nq8uct2wv5pszgw65ea4ft9z0kkcememm5qaspw8c2lgpulf78e46y46r23cz9cz48eqwe"); + assert_eq!(sk, "secret-extended-key-main1qv6r09npqqqqpqphzfl70tss2ysdnsv8gjh8zxtk8wuuqd8k48re30nu7gdalh3llalq6mtefpv6w2efm4aklk6dfpe7udpnee08u69gc565mmfv7jcshf2t2llv3424q2kldfks7npww8rc8m2dah3tt67dv0cg4yqpxlsy8nmz65vl5h4wvw5nxtedry77s5hsn73t2lf0c3p6ps5ju959h8y9v03y2yk3vn3kynh6csls9zayqh5xup4l82d5yhwvgmelgvvyfxgcd25xa"); assert_eq!(seed_phrase, Some(wallet.get_seed_phrase())); } @@ -1969,11 +1974,11 @@ fn test_lock_unlock() { // Add some addresses let zaddr0 = encode_payment_address(config.hrp_sapling_address(), - &wallet.extfvks.read().unwrap()[0].default_address().unwrap().1); + &wallet.zkeys.read().unwrap()[0].extfvk.default_address().unwrap().1); let zaddr1 = wallet.add_zaddr(); // This is actually address at index 6 let zaddr2 = wallet.add_zaddr(); // This is actually address at index 7 - let taddr0 = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0]); + let taddr0 = wallet.address_from_sk(&wallet.tkeys.read().unwrap()[0].tkey.unwrap()); let taddr1 = wallet.add_taddr(); let taddr2 = wallet.add_taddr(); @@ -2000,21 +2005,21 @@ fn test_lock_unlock() { assert_eq!(seed, wallet.seed); { - let extsks = wallet.extsks.read().unwrap(); + let zkeys = wallet.zkeys.read().unwrap(); let tkeys = wallet.tkeys.read().unwrap(); - assert_eq!(extsks.len(), 8); // 3 zaddrs + 1 original + 4 extra HD addreses + assert_eq!(zkeys.len(), 8); // 3 zaddrs + 1 original + 4 extra HD addreses assert_eq!(tkeys.len(), 3); assert_eq!(zaddr0, encode_payment_address(config.hrp_sapling_address(), - &ExtendedFullViewingKey::from(&extsks[0]).default_address().unwrap().1)); + &ExtendedFullViewingKey::from(zkeys[0].extsk.as_ref().unwrap()).default_address().unwrap().1)); assert_eq!(zaddr1, encode_payment_address(config.hrp_sapling_address(), - &ExtendedFullViewingKey::from(&extsks[6]).default_address().unwrap().1)); + &ExtendedFullViewingKey::from(zkeys[6].extsk.as_ref().unwrap()).default_address().unwrap().1)); assert_eq!(zaddr2, encode_payment_address(config.hrp_sapling_address(), - &ExtendedFullViewingKey::from(&extsks[7]).default_address().unwrap().1)); + &ExtendedFullViewingKey::from(zkeys[7].extsk.as_ref().unwrap()).default_address().unwrap().1)); - assert_eq!(taddr0, wallet.address_from_sk(&tkeys[0])); - assert_eq!(taddr1, wallet.address_from_sk(&tkeys[1])); - assert_eq!(taddr2, wallet.address_from_sk(&tkeys[2])); + assert_eq!(taddr0, wallet.address_from_sk(&tkeys[0].tkey.unwrap())); + assert_eq!(taddr1, wallet.address_from_sk(&tkeys[1].tkey.unwrap())); + assert_eq!(taddr2, wallet.address_from_sk(&tkeys[2].tkey.unwrap())); } // Unlocking an already unlocked wallet should fail @@ -2036,21 +2041,21 @@ fn test_lock_unlock() { assert_eq!(seed, wallet2.seed); { - let extsks = wallet2.extsks.read().unwrap(); + let zkeys = wallet2.zkeys.read().unwrap(); let tkeys = wallet2.tkeys.read().unwrap(); - assert_eq!(extsks.len(), 8); + assert_eq!(zkeys.len(), 8); assert_eq!(tkeys.len(), 3); assert_eq!(zaddr0, encode_payment_address(wallet2.config.hrp_sapling_address(), - &ExtendedFullViewingKey::from(&extsks[0]).default_address().unwrap().1)); + &ExtendedFullViewingKey::from(zkeys[0].extsk.as_ref().unwrap()).default_address().unwrap().1)); assert_eq!(zaddr1, encode_payment_address(wallet2.config.hrp_sapling_address(), - &ExtendedFullViewingKey::from(&extsks[6]).default_address().unwrap().1)); + &ExtendedFullViewingKey::from(zkeys[6].extsk.as_ref().unwrap()).default_address().unwrap().1)); assert_eq!(zaddr2, encode_payment_address(wallet2.config.hrp_sapling_address(), - &ExtendedFullViewingKey::from(&extsks[7]).default_address().unwrap().1)); + &ExtendedFullViewingKey::from(zkeys[7].extsk.as_ref().unwrap()).default_address().unwrap().1)); - assert_eq!(taddr0, wallet2.address_from_sk(&tkeys[0])); - assert_eq!(taddr1, wallet2.address_from_sk(&tkeys[1])); - assert_eq!(taddr2, wallet2.address_from_sk(&tkeys[2])); + assert_eq!(taddr0, wallet2.address_from_sk(&tkeys[0].tkey.unwrap())); + assert_eq!(taddr1, wallet2.address_from_sk(&tkeys[1].tkey.unwrap())); + assert_eq!(taddr2, wallet2.address_from_sk(&tkeys[2].tkey.unwrap())); } // Remove encryption from a unlocked wallet should succeed @@ -2142,8 +2147,11 @@ fn test_encrypted_zreceive() { let (ss, so) = get_sapling_params().unwrap(); // Create a tx and send to address - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); + + // Second z address. Keys can't be added to an encrypted wallet, so derive it now. + let zaddr2 = wallet.add_zaddr(); // This is address number 6 // Now that we have the transaction, we'll encrypt the wallet wallet.encrypt(password.clone()).unwrap(); @@ -2185,19 +2193,18 @@ fn test_encrypted_zreceive() { } // Trying to spend from a locked wallet is an error - assert!(wallet.send_to_address(branch_id, &ss, &so, - vec![(&ext_address, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).is_err()); + assert!(wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&ext_address, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).is_err()); // unlock the wallet so we can spend to the second z address wallet.unlock(password.clone()).unwrap(); - // Second z address - let zaddr2 = wallet.add_zaddr(); // This is address number 6 + // Second z address (derived before encrypting) const ZAMOUNT2:u64 = 30; let outgoing_memo2 = "Outgoing Memo2".to_string(); - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&zaddr2, ZAMOUNT2, Some(outgoing_memo2.clone()))], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&zaddr2, ZAMOUNT2, Some(outgoing_memo2.clone()))], &default_fee(), |_| Ok(' '.to_string())).unwrap(); // Now lock the wallet again wallet.lock().unwrap(); @@ -2251,8 +2258,11 @@ fn test_encrypted_treceive() { const AMOUNT_SENT: u64 = 30; let fee: u64 = DEFAULT_FEE.try_into().unwrap(); - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); + + // Second t address. Keys can't be added to an encrypted wallet, so derive it now. + let taddr2 = wallet.add_taddr(); // Now that we have the transaction, we'll encrypt the wallet wallet.encrypt(password.clone()).unwrap(); @@ -2287,18 +2297,17 @@ fn test_encrypted_treceive() { } // Trying to spend from a locked wallet is an error - assert!(wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr, AMOUNT_SENT, None)], |_| Ok(' '.to_string())).is_err()); + assert!(wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr, AMOUNT_SENT, None)], &default_fee(), |_| Ok(' '.to_string())).is_err()); // unlock the wallet so we can spend to the second z address wallet.unlock(password.clone()).unwrap(); - // Second z address - let taddr2 = wallet.add_taddr(); + // Second t address (derived before encrypting) const TAMOUNT2:u64 = 50; - let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, - vec![(&taddr2, TAMOUNT2, None)], |_| Ok(' '.to_string())).unwrap(); + let (_, raw_tx) = wallet.send_to_address(branch_id, &ss, &so, false, + vec![(&taddr2, TAMOUNT2, None)], &default_fee(), |_| Ok(' '.to_string())).unwrap(); // Now lock the wallet again wallet.lock().unwrap(); diff --git a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/walletzkey.rs b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/walletzkey.rs index 554fb1c..d8eb8e4 100644 --- a/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/walletzkey.rs +++ b/third_party/silentdragonxlite/silentdragonxlite-cli/lib/src/lightwallet/walletzkey.rs @@ -454,6 +454,7 @@ pub mod tests { sapling_activation_height: 0, consensus_branch_id: "000000".to_string(), anchor_offset: 0, + no_cert_verification: false, data_dir: None, } }