From d9c48b9e81a7b12d3857f8db9f3e2aabcd430b93 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Fri, 13 Sep 2024 19:07:37 -0400 Subject: [PATCH] scan using the postboard ufvk --- src/wallet.rs | 40 +++++++++++++++++++++++++- tests/tests.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/wallet.rs b/src/wallet.rs index c8624ae..9a9714f 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -32,7 +32,7 @@ use zcash_client_backend::wallet::OvkPolicy; use zcash_client_backend::zip321::{Payment, TransactionRequest}; use zcash_client_backend::ShieldedProtocol; use zcash_client_memory::MemoryWalletDb; -use zcash_keys::keys::UnifiedSpendingKey; +use zcash_keys::keys::{UnifiedFullViewingKey, UnifiedSpendingKey}; use zcash_primitives::consensus::{self, BlockHeight, Network}; use zcash_primitives::transaction::components::amount::NonNegativeAmount; use zcash_primitives::transaction::fees::zip317::FeeRule; @@ -159,6 +159,44 @@ where Ok("0".to_string()) } + pub async fn import_ufvk( + &mut self, + ufvk: UnifiedFullViewingKey, + birthday_height: Option, + ) -> Result { + let birthday = match birthday_height { + Some(height) => height, + None => { + let chain_tip: u32 = self + .client + .get_latest_block(service::ChainSpec::default()) + .await? + .into_inner() + .height + .try_into() + .expect("block heights must fit into u32"); + chain_tip - 100 + } + }; + // Construct an `AccountBirthday` for the account's birthday. + let birthday = { + // Fetch the tree state corresponding to the last block prior to the wallet's + // birthday height. NOTE: THIS APPROACH LEAKS THE BIRTHDAY TO THE SERVER! + let request = service::BlockId { + height: (birthday - 1).into(), + ..Default::default() + }; + let treestate = self.client.get_tree_state(request).await?.into_inner(); + AccountBirthday::from_treestate(treestate, None).map_err(|_| Error::BirthdayError)? + }; + + let _account = self + .db + .import_account_ufvk(&ufvk, &birthday, AccountPurpose::Spending)?; + + Ok("0".to_string()) + } + pub fn suggest_scan_ranges(&self) -> Result, Error> { Ok(self.db.suggest_scan_ranges().map(|ranges| { ranges diff --git a/tests/tests.rs b/tests/tests.rs index 075c0e1..327abe9 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -114,3 +114,80 @@ async fn test_get_and_scan_range_native() { let summary = w.get_wallet_summary().unwrap(); tracing::info!("Wallet summary: {:?}", summary); } + +// let s = zcash_keys::encoding::decode_extended_full_viewing_key( +// constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, +// &self.ufvk.trim(), +// ) +// .unwrap() +// .to_diversifiable_full_viewing_key(); +// let ufvk = UnifiedFullViewingKey::new(None, Some(s), None).unwrap(); + +#[cfg(feature = "native")] +#[tokio::test] +async fn test_post_board() { + let key_str = "zxviews1q0duytgcqqqqpqre26wkl45gvwwwd706xw608hucmvfalr759ejwf7qshjf5r9aa7323zulvz6plhttp5mltqcgs9t039cx2d09mgq05ts63n8u35hyv6h9nc9ctqqtue2u7cer2mqegunuulq2luhq3ywjcz35yyljewa4mgkgjzyfwh6fr6jd0dzd44ghk0nxdv2hnv4j5nxfwv24rwdmgllhe0p8568sgqt9ckt02v2kxf5ahtql6s0ltjpkckw8gtymxtxuu9gcr0swvz"; + + use zcash_keys::keys::UnifiedFullViewingKey; + use zcash_primitives::{consensus, constants}; + let db_cache = tempfile::tempdir().unwrap(); + let _db_data = tempfile::NamedTempFile::new_in(db_cache.path()).unwrap(); + + initialize(); + let url = "https://zec.rocks:443"; + let c = tonic::transport::Channel::from_shared(url).unwrap(); + + let tls = tonic::transport::ClientTlsConfig::new() + .domain_name("zec.rocks") + .with_webpki_roots(); + let channel = c.tls_config(tls).unwrap(); + + #[cfg(feature = "sqlite-db")] + let wallet_db = { + use zcash_client_sqlite::{ + chain::init::init_blockmeta_db, wallet::init::init_wallet_db, FsBlockDb, WalletDb, + }; + + let mut db_cache = FsBlockDb::for_path(&db_cache).unwrap(); + let mut wallet_db = WalletDb::for_path(&_db_data, consensus::Network::MainNetwork).unwrap(); + init_blockmeta_db(&mut db_cache).unwrap(); + init_wallet_db(&mut wallet_db, None).unwrap(); + wallet_db + }; + + #[cfg(not(feature = "sqlite-db"))] + let wallet_db = zcash_client_memory::MemoryWalletDb::new( + consensus::Network::MainNetwork, + webz_core::PRUNING_DEPTH, + ); + + let mut w = Wallet::new( + wallet_db, + channel.connect().await.unwrap(), + Network::MainNetwork, + NonZeroU32::try_from(1).unwrap(), + ) + .unwrap(); + + let s = zcash_keys::encoding::decode_extended_full_viewing_key( + constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + &key_str.trim(), + ) + .unwrap(); + + let ufvk = UnifiedFullViewingKey::from_sapling_extended_full_viewing_key(s).unwrap(); + let id = w.import_ufvk(ufvk, Some(2477329)).await.unwrap(); + tracing::info!("Created account with id: {}", id); + + tracing::info!("Syncing wallet"); + w.sync(|scanned_to, tip| { + println!("Scanned: {}/{}", scanned_to, tip); + }) + .await + .unwrap(); + + tracing::info!("Syncing complete :)"); + + let summary = w.get_wallet_summary().unwrap(); + tracing::info!("Wallet summary: {:?}", summary); +}