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 <noreply@anthropic.com>
This commit is contained in:
2026-10-10 09:50:03 -05:00
co-authored by Claude Opus 5.5
parent 3f13d79ccb
commit 8895038c40
5 changed files with 196 additions and 168 deletions
@@ -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));
@@ -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();
@@ -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);
}
}
@@ -45,6 +45,11 @@ fn get_sapling_params() -> Result<(Vec<u8>, Vec<u8>), 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();
@@ -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,
}
}