diff --git a/src/api/account.rs b/src/api/account.rs index f2453f7..04e66a5 100644 --- a/src/api/account.rs +++ b/src/api/account.rs @@ -1,6 +1,7 @@ // Account creation use crate::coinconfig::CoinConfig; +use crate::db::AccountData; use crate::key2::decode_key; use crate::taddr::{derive_taddr, derive_tkeys}; use crate::transaction::retrieve_tx_info; @@ -36,7 +37,7 @@ pub fn new_account( pub fn new_sub_account(name: &str, index: Option, count: u32) -> anyhow::Result<()> { let c = CoinConfig::get_active(); let db = c.db()?; - let (seed, _) = db.get_seed(c.id_account)?; + let AccountData { seed, .. } = db.get_account_info(c.id_account)?; let seed = seed.ok_or_else(|| anyhow!("Account has no seed"))?; let index = index.unwrap_or_else(|| db.next_account_id(&seed).unwrap()); drop(db); @@ -61,7 +62,7 @@ fn new_account_with_key(coin: u8, name: &str, key: &str, index: u32) -> anyhow:: pub fn import_transparent_key(coin: u8, id_account: u32, path: &str) -> anyhow::Result<()> { let c = CoinConfig::get(coin); let db = c.db()?; - let (seed, _) = db.get_seed(c.id_account)?; + let AccountData { seed, .. } = db.get_account_info(c.id_account)?; let seed = seed.ok_or_else(|| anyhow!("Account has no seed"))?; let (sk, addr) = derive_tkeys(c.chain.network(), &seed, path)?; db.store_transparent_key(id_account, &sk, &addr)?; @@ -79,10 +80,10 @@ pub fn import_transparent_secret_key(coin: u8, id_account: u32, sk: &str) -> any pub fn new_diversified_address() -> anyhow::Result { let c = CoinConfig::get_active(); let db = c.db()?; - let ivk = db.get_ivk(c.id_account)?; + let AccountData { fvk, .. } = db.get_account_info(c.id_account)?; let fvk = decode_extended_full_viewing_key( c.chain.network().hrp_sapling_extended_full_viewing_key(), - &ivk, + &fvk, )? .unwrap(); let mut diversifier_index = db.get_diversifier(c.id_account)?; @@ -122,20 +123,20 @@ pub async fn scan_transparent_accounts(gap_limit: usize) -> anyhow::Result<()> { pub fn get_backup(account: u32) -> anyhow::Result { let c = CoinConfig::get_active(); - let (seed, sk, ivk) = c.db()?.get_backup(account)?; + let AccountData { seed, sk, fvk, .. } = c.db()?.get_account_info(account)?; if let Some(seed) = seed { return Ok(seed); } if let Some(sk) = sk { return Ok(sk); } - Ok(ivk) + Ok(fvk) } pub fn get_sk(account: u32) -> anyhow::Result { let c = CoinConfig::get_active(); - let sk = c.db()?.get_sk(account)?; - Ok(sk) + let AccountData { sk, .. } = c.db()?.get_account_info(account)?; + Ok(sk.unwrap_or(String::new())) } pub fn reset_db(coin: u8) -> anyhow::Result<()> { @@ -184,7 +185,7 @@ pub fn derive_keys( ) -> anyhow::Result { let c = CoinConfig::get(coin); let db = c.db()?; - let (seed, _) = db.get_seed(id_account)?; + let AccountData { seed, .. } = db.get_account_info(id_account)?; let seed = seed.unwrap(); derive_zip32(c.chain.network(), &seed, account, external, address) } diff --git a/src/api/contact.rs b/src/api/contact.rs index 1f1f34c..43bc29a 100644 --- a/src/api/contact.rs +++ b/src/api/contact.rs @@ -2,6 +2,7 @@ use crate::api::payment::{build_sign_send_multi_payment, RecipientMemo}; use crate::api::sync::get_latest_height; use crate::coinconfig::CoinConfig; use crate::contact::{serialize_contacts, Contact}; +use crate::db::AccountData; use zcash_primitives::memo::Memo; pub fn store_contact(id: u32, name: &str, address: &str, dirty: bool) -> anyhow::Result<()> { @@ -26,7 +27,7 @@ pub async fn commit_unsaved_contacts(anchor_offset: u32) -> anyhow::Result anyhow::Result { let c = CoinConfig::get_active(); let last_height = get_latest_height().await?; - let address = c.db()?.get_address(c.id_account)?; + let AccountData { address, .. } = c.db()?.get_account_info(c.id_account)?; let recipients: Vec<_> = memos .iter() .map(|m| RecipientMemo { diff --git a/src/api/dart_ffi.rs b/src/api/dart_ffi.rs index ec30725..35cfb02 100644 --- a/src/api/dart_ffi.rs +++ b/src/api/dart_ffi.rs @@ -534,7 +534,7 @@ pub unsafe extern "C" fn parse_payment_uri(uri: *mut c_char) -> *mut c_char { #[no_mangle] pub unsafe extern "C" fn generate_random_enc_key() -> *mut c_char { - to_c_str(log_string(crate::key2::generate_random_enc_key())) + to_c_str(log_string(crate::key::generate_random_enc_key())) } #[no_mangle] diff --git a/src/api/mempool.rs b/src/api/mempool.rs index f053eab..8ef8918 100644 --- a/src/api/mempool.rs +++ b/src/api/mempool.rs @@ -2,11 +2,12 @@ use zcash_client_backend::encoding::decode_extended_full_viewing_key; use zcash_primitives::consensus::Parameters; use crate::coinconfig::CoinConfig; +use crate::db::AccountData; use crate::get_latest_height; pub async fn scan() -> anyhow::Result { let c = CoinConfig::get_active(); - let ivk = c.db()?.get_ivk(c.id_account)?; + let AccountData { fvk, .. } = c.db()?.get_account_info(c.id_account)?; let mut client = c.connect_lwd().await?; let height = get_latest_height(&mut client).await?; let mut mempool = c.mempool.lock().unwrap(); @@ -17,7 +18,7 @@ pub async fn scan() -> anyhow::Result { } let fvk = decode_extended_full_viewing_key( c.chain.network().hrp_sapling_extended_full_viewing_key(), - &ivk, + &fvk, )? .unwrap(); mempool diff --git a/src/api/payment.rs b/src/api/payment.rs index 7e7a004..7882017 100644 --- a/src/api/payment.rs +++ b/src/api/payment.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use std::str::FromStr; use secp256k1::SecretKey; @@ -12,7 +13,7 @@ use zcash_client_backend::encoding::{ use zcash_primitives::consensus::Parameters; use zcash_primitives::transaction::builder::Progress; -use crate::db::ZMessage; +use crate::db::{AccountData, ZMessage}; use crate::taddr::get_utxos; use serde::Deserialize; use zcash_primitives::memo::Memo; @@ -29,7 +30,7 @@ async fn prepare_multi_payment( let c = CoinConfig::get_active(); let mut tx_builder = TxBuilder::new(c.coin_type, last_height); - let fvk = c.db()?.get_ivk(c.id_account)?; + let AccountData { fvk, .. } = c.db()?.get_account_info(c.id_account)?; let fvk = decode_extended_full_viewing_key( c.chain.network().hrp_sapling_extended_full_viewing_key(), &fvk, @@ -62,7 +63,8 @@ fn sign(tx: &Tx, progress_callback: PaymentProgressCallback) -> anyhow::Result anyhow::Result { pub fn parse_recipients(recipients: &str) -> anyhow::Result> { let c = CoinConfig::get_active(); - let address = c.db()?.get_address(c.id_account)?; + let AccountData { address, .. } = c.db()?.get_account_info(c.id_account)?; let recipients: Vec = serde_json::from_str(recipients)?; let recipient_memos: Vec<_> = recipients .iter() diff --git a/src/api/sync.rs b/src/api/sync.rs index fb5e4b4..adf6988 100644 --- a/src/api/sync.rs +++ b/src/api/sync.rs @@ -2,11 +2,13 @@ use crate::coinconfig::CoinConfig; use crate::scan::AMProgressCallback; -use crate::{BlockId, CTree, CompactTxStreamerClient, DbAdapter}; +use crate::{BlockId, CTree, CompactTxStreamerClient, DbAdapter, AccountData}; use std::sync::Arc; use tokio::sync::Mutex; use tonic::transport::Channel; use tonic::Request; +use zcash_primitives::sapling::Note; +use crate::db::PlainNote; const DEFAULT_CHUNK_SIZE: u32 = 100_000; @@ -90,7 +92,6 @@ pub async fn skip_to_last_height(coin: u8) -> anyhow::Result<()> { pub async fn rewind_to_height(height: u32) -> anyhow::Result { let c = CoinConfig::get_active(); - let mut client = c.connect_lwd().await?; let height = c.db()?.trim_to_height(height, false)?; Ok(height) } @@ -129,3 +130,10 @@ pub async fn get_block_by_time(time: u32) -> anyhow::Result { let date_time = crate::chain::get_block_by_time(c.chain.network(), &mut client, time).await?; Ok(date_time) } + +pub fn trial_decrypt(height: u32, cmu: &[u8], epk: &[u8], ciphertext: &[u8]) -> anyhow::Result> { + let c = CoinConfig::get_active(); + let AccountData { fvk, .. } = c.db().unwrap().get_account_info(c.id_account)?; + let note = crate::scan::trial_decrypt_one(c.chain.network(), height, &fvk, cmu, epk, ciphertext)?; + Ok(note) +} diff --git a/src/db.rs b/src/db.rs index 11c2b32..0bdc6ee 100644 --- a/src/db.rs +++ b/src/db.rs @@ -214,7 +214,7 @@ impl DbAdapter { .query_row( "SELECT 1 from blocks WHERE height = ?1", params![height], - |row| Ok(()), + |_| Ok(()), ) .map_err(wrap_query_no_rows("trim_to_height: height not found"))?; height @@ -644,97 +644,6 @@ impl DbAdapter { Ok(contacts) } - pub fn get_backup( - &self, - account: u32, - ) -> anyhow::Result<(Option, Option, String)> { - log::debug!("+get_backup"); - let (seed, sk, ivk) = self - .connection - .query_row( - "SELECT seed, sk, ivk FROM accounts WHERE id_account = ?1", - params![account], - |row| { - let seed: Option = row.get(0)?; - let sk: Option = row.get(1)?; - let ivk: String = row.get(2)?; - Ok((seed, sk, ivk)) - }, - ) - .map_err(wrap_query_no_rows("get_backup"))?; - log::debug!("-get_backup"); - Ok((seed, sk, ivk)) - } - - pub fn get_seed(&self, account: u32) -> anyhow::Result<(Option, u32)> { - log::info!("+get_seed"); - let (seed, index) = self - .connection - .query_row( - "SELECT seed, aindex FROM accounts WHERE id_account = ?1", - params![account], - |row| { - let sk: Option = row.get(0)?; - let index: u32 = row.get(1)?; - Ok((sk, index)) - }, - ) - .map_err(wrap_query_no_rows("get_seed"))?; - log::info!("-get_seed"); - Ok((seed, index)) - } - - pub fn get_sk(&self, account: u32) -> anyhow::Result { - log::info!("+get_sk"); - let sk = self - .connection - .query_row( - "SELECT sk FROM accounts WHERE id_account = ?1", - params![account], - |row| { - let sk: String = row.get(0)?; - Ok(sk) - }, - ) - .map_err(wrap_query_no_rows("get_sk"))?; - log::info!("-get_sk"); - Ok(sk) - } - - pub fn get_ivk(&self, account: u32) -> anyhow::Result { - log::debug!("+get_ivk"); - let ivk = self - .connection - .query_row( - "SELECT ivk FROM accounts WHERE id_account = ?1", - params![account], - |row| { - let ivk: String = row.get(0)?; - Ok(ivk) - }, - ) - .map_err(wrap_query_no_rows("get_ivk"))?; - log::debug!("-get_ivk"); - Ok(ivk) - } - - pub fn get_address(&self, account: u32) -> anyhow::Result { - log::debug!("+get_address"); - let address = self - .connection - .query_row( - "SELECT address FROM accounts WHERE id_account = ?1", - params![account], - |row| { - let address: String = row.get(0)?; - Ok(address) - }, - ) - .map_err(wrap_query_no_rows("get_address"))?; - log::debug!("-get_address"); - Ok(address) - } - pub fn get_diversifier(&self, account: u32) -> anyhow::Result { let diversifier_index = self .connection @@ -753,6 +662,33 @@ impl DbAdapter { Ok(DiversifierIndex(diversifier_index)) } + pub fn get_account_info(&self, account: u32) -> anyhow::Result { + let account_data = self + .connection + .query_row( + "SELECT name, seed, sk, ivk, address, aindex FROM accounts WHERE id_account = ?1", + params![account], + |row| { + let name: String = row.get(0)?; + let seed: Option = row.get(1)?; + let sk: Option = row.get(2)?; + let fvk: String = row.get(3)?; + let address: String = row.get(4)?; + let aindex: u32 = row.get(5)?; + Ok(AccountData { + name, + seed, + sk, + fvk, + address, + aindex, + }) + }, + ) + .map_err(wrap_query_no_rows("get_account_info"))?; + Ok(account_data) + } + pub fn store_diversifier( &self, account: u32, @@ -798,9 +734,9 @@ impl DbAdapter { } pub fn create_taddr(&self, account: u32) -> anyhow::Result<()> { - let (seed, index) = self.get_seed(account)?; + let AccountData { seed, aindex, .. } = self.get_account_info(account)?; if let Some(seed) = seed { - let bip44_path = format!("m/44'/{}'/0'/0/{}", self.network().coin_type(), index); + let bip44_path = format!("m/44'/{}'/0'/0/{}", self.network().coin_type(), aindex); let (sk, address) = derive_tkeys(self.network(), &seed, &bip44_path)?; self.connection.execute( "INSERT INTO taddrs(account, sk, address) VALUES (?1, ?2, ?3) \ @@ -1181,7 +1117,7 @@ pub struct AccountRec { } #[serde_as] -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize, Debug)] pub struct PlainNote { pub height: u32, pub value: u64, @@ -1273,3 +1209,12 @@ mod tests { println!("{}", balance); } } + +pub struct AccountData { + pub name: String, + pub seed: Option, + pub sk: Option, + pub fvk: String, + pub address: String, + pub aindex: u32, +} diff --git a/src/gpu.rs b/src/gpu.rs index fe9a987..f457920 100644 --- a/src/gpu.rs +++ b/src/gpu.rs @@ -1,3 +1,4 @@ +use std::convert::TryInto; use crate::chain::{DecryptedBlock, DecryptedNote, Nf}; use crate::db::AccountViewKey; use crate::CompactBlock; @@ -119,16 +120,16 @@ fn collect_decrypted_notes( for db in decrypted_blocks { let b = &db.compact_block; let mut decrypted_notes = vec![]; - let mut position_in_block = 0; let domain = SaplingDomain::for_height(*network, BlockHeight::from_u32(b.height as u32)); for (tx_index, tx) in b.vtx.iter().enumerate() { for (output_index, co) in tx.outputs.iter().enumerate() { - let plaintext = &output_buffer[i * buffer_stride + 64..i * buffer_stride + 116]; + let plaintext = &output_buffer[i * buffer_stride + 32..i * buffer_stride + 84]; // version and amount must be in range - 21 million ZEC is less than 0x0008 0000 0000 0000 if plaintext[0] <= 2 && plaintext[18] < 0x08 && plaintext[19] == 0 { if let Some((note, pa)) = domain.parse_note_plaintext_without_memo_ivk(&ivk, plaintext) { + let position_in_block = usize::from_le_bytes(plaintext[52..60].try_into().unwrap()); let cmu = note.cmu().to_bytes(); if &cmu == co.cmu.as_slice() { log::info!("Note {} {}", account, u64::from(note.value)); @@ -148,7 +149,6 @@ fn collect_decrypted_notes( } } i += 1; - position_in_block += 1; } } db.notes.extend(decrypted_notes); diff --git a/src/gpu/cuda.rs b/src/gpu/cuda.rs index f459bbb..ac71a99 100644 --- a/src/gpu/cuda.rs +++ b/src/gpu/cuda.rs @@ -16,7 +16,7 @@ use zcash_primitives::consensus::Network; use zcash_primitives::sapling::SaplingIvk; const THREADS_PER_BLOCK: usize = 256usize; -const BUFFER_SIZE: usize = 128usize; +const BUFFER_SIZE: usize = 96usize; lazy_static! { pub static ref CUDA_CONTEXT: Mutex> = Mutex::new(CudaContext::new().ok()); @@ -159,15 +159,20 @@ impl CudaProcessor { let decrypted_blocks = collect_nf(blocks)?; let mut data_buffer = vec![0u8; n * BUFFER_SIZE]; - let mut i = 0; for db in decrypted_blocks.iter() { + let mut i = 0; + let mut position_in_block = 0; let b = &db.compact_block; for tx in b.vtx.iter() { for co in tx.outputs.iter() { + if co.epk.is_empty() { break } // skip decryption data_buffer[i * BUFFER_SIZE..i * BUFFER_SIZE + 32].copy_from_slice(&co.epk); - data_buffer[i * BUFFER_SIZE + 64..i * BUFFER_SIZE + 116] + data_buffer[i * BUFFER_SIZE + 32..i * BUFFER_SIZE + 84] .copy_from_slice(&co.ciphertext); + data_buffer[i * BUFFER_SIZE + 84..i * BUFFER_SIZE + 92] + .copy_from_slice(&usize::to_le_bytes(position_in_block)); i += 1; + position_in_block += 1; } } } diff --git a/src/key2.rs b/src/key2.rs index 6da54ad..f11fa73 100644 --- a/src/key2.rs +++ b/src/key2.rs @@ -1,8 +1,5 @@ use crate::coinconfig::CoinConfig; -use bech32::{ToBase32, Variant}; use bip39::{Language, Mnemonic, Seed}; -use rand::rngs::OsRng; -use rand::RngCore; use zcash_client_backend::address::RecipientAddress; use zcash_client_backend::encoding::{ decode_extended_full_viewing_key, decode_extended_spending_key, @@ -98,10 +95,3 @@ fn derive_address(network: &Network, fvk: &ExtendedFullViewingKey) -> anyhow::Re let address = encode_payment_address(network.hrp_sapling_payment_address(), &payment_address); Ok(address) } - -pub fn generate_random_enc_key() -> anyhow::Result { - let mut key = [0u8; 32]; - OsRng.fill_bytes(&mut key); - let key = bech32::encode("zwk", key.to_base32(), Variant::Bech32)?; - Ok(key) -} diff --git a/src/lib.rs b/src/lib.rs index 8435257..53782f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +71,7 @@ pub use crate::coinconfig::{ init_coin, set_active, set_active_account, set_coin_lwd_url, CoinConfig, }; pub use crate::commitment::{CTree, Witness}; -pub use crate::db::{AccountInfo, AccountRec, DbAdapter, TxRec}; +pub use crate::db::{AccountInfo, AccountRec, AccountData, DbAdapter, TxRec}; pub use crate::fountain::{put_drop, FountainCodes, RaptorQDrops}; pub use crate::hash::{pedersen_hash, Hash, GENERATORS_EXP}; pub use crate::key::{generate_random_enc_key, KeyHelpers}; diff --git a/src/main/rpc.rs b/src/main/rpc.rs index 0f2447f..68ff2b4 100644 --- a/src/main/rpc.rs +++ b/src/main/rpc.rs @@ -15,10 +15,7 @@ use std::sync::Mutex; use thiserror::Error; use warp_api_ffi::api::payment::{Recipient, RecipientMemo}; use warp_api_ffi::api::payment_uri::PaymentURI; -use warp_api_ffi::{ - derive_zip32, get_best_server, AccountInfo, AccountRec, CoinConfig, KeyPack, RaptorQDrops, Tx, - TxRec, -}; +use warp_api_ffi::{derive_zip32, get_best_server, AccountInfo, AccountRec, CoinConfig, KeyPack, RaptorQDrops, Tx, TxRec, AccountData}; lazy_static! { static ref SYNC_CANCELED: Mutex = Mutex::new(false); @@ -26,6 +23,8 @@ lazy_static! { #[derive(Error, Debug)] pub enum Error { + #[error(transparent)] + Hex(#[from] hex::FromHexError), #[error(transparent)] Reqwest(#[from] reqwest::Error), #[error(transparent)] @@ -69,6 +68,9 @@ async fn main() -> anyhow::Result<()> { let yec: HashMap = figment.extract_inner("yec")?; init(1, yec)?; + warp_api_ffi::set_active_account(0, 1); + warp_api_ffi::set_active(0); + let _ = rocket .mount( "/", @@ -95,6 +97,7 @@ async fn main() -> anyhow::Result<()> { merge_data, derive_keys, instant_sync, + trial_decrypt, ], ) .attach(AdHoc::config::()) @@ -169,7 +172,7 @@ pub async fn get_latest_height() -> Result, Error> { pub fn get_address() -> Result { let c = CoinConfig::get_active(); let db = c.db()?; - let address = db.get_address(c.id_account)?; + let AccountData { address, .. } = db.get_account_info(c.id_account)?; Ok(address) } @@ -180,7 +183,7 @@ pub fn get_backup(config: &State) -> Result, Error> { } else { let c = CoinConfig::get_active(); let db = c.db()?; - let (seed, sk, fvk) = db.get_backup(c.id_account)?; + let AccountData { seed, sk, fvk, .. } = db.get_account_info(c.id_account)?; Ok(Json(Backup { seed, sk, fvk })) } } @@ -207,7 +210,8 @@ pub async fn create_offline_tx(payment: Json) -> Result, Error let latest = warp_api_ffi::api::sync::get_latest_height().await?; let from = { let db = c.db()?; - db.get_address(c.id_account)? + let AccountData { address, .. } = db.get_account_info(c.id_account)?; + address }; let recipients: Vec<_> = payment .recipients @@ -244,7 +248,8 @@ pub async fn pay(payment: Json, config: &State) -> Result = payment .recipients @@ -323,12 +328,22 @@ pub fn derive_keys( Ok(Json(result)) } +#[post("/trial_decrypt?&&&")] +pub async fn trial_decrypt(height: u32, cmu: String, epk: String, ciphertext: String) -> Result { + let epk = hex::decode(&epk)?; + let cmu = hex::decode(&cmu)?; + let ciphertext = hex::decode(&ciphertext)?; + let note = warp_api_ffi::api::sync::trial_decrypt(height, &cmu, &epk, &ciphertext)?; + log::info!("{:?}", note); + Ok(note.is_some().to_string()) +} + #[post("/instant_sync")] pub async fn instant_sync() -> Result<(), Error> { let c = CoinConfig::get_active(); let fvk = { let db = c.db()?; - let (_, _, fvk) = db.get_backup(c.id_account)?; + let AccountData { fvk, .. } = db.get_account_info(c.id_account)?; fvk }; let client = reqwest::Client::new(); diff --git a/src/scan.rs b/src/scan.rs index 33cc33c..eef01f3 100644 --- a/src/scan.rs +++ b/src/scan.rs @@ -1,12 +1,10 @@ use crate::builder::BlockProcessor; use crate::chain::{DecryptedBlock, Nf, NfRef, TRIAL_DECRYPTIONS}; -use crate::db::{DbAdapter, ReceivedNote}; +use crate::db::{AccountViewKey, DbAdapter, PlainNote, ReceivedNote}; use std::cmp::Ordering; use crate::transaction::retrieve_tx_info; -use crate::{ - connect_lightwalletd, download_chain, get_latest_height, CompactBlock, DecryptNode, Witness, -}; +use crate::{connect_lightwalletd, download_chain, get_latest_height, CompactBlock, DecryptNode, Witness, CompactTx, CompactSaplingOutput}; use ff::PrimeField; use lazy_static::lazy_static; @@ -14,12 +12,15 @@ use std::collections::HashMap; use std::panic; use std::sync::Arc; use std::time::Instant; +use anyhow::anyhow; use tokio::runtime::{Builder, Runtime}; use tokio::sync::mpsc; use tokio::sync::Mutex; +use zcash_client_backend::encoding::decode_extended_full_viewing_key; +use zcash_primitives::consensus::{Network, Parameters}; use zcash_params::coin::{get_coin_chain, CoinType}; -use zcash_primitives::sapling::Node; +use zcash_primitives::sapling::{Node, Note}; pub struct Blocks(pub Vec); @@ -66,7 +67,7 @@ pub async fn sync_async( let mut client = connect_lightwalletd(&ld_url).await?; let (start_height, prev_hash, vks) = { - let mut db = DbAdapter::new(coin_type, &db_path)?; + let db = DbAdapter::new(coin_type, &db_path)?; let height = db.get_db_height()?; let hash = db.get_db_hash(height)?; let vks = db.get_fvks()?; @@ -357,3 +358,45 @@ pub async fn latest_height(ld_url: &str) -> anyhow::Result { let height = get_latest_height(&mut client).await?; Ok(height) } + +#[allow(dead_code)] +// test function +pub fn trial_decrypt_one(network: &Network, height: u32, fvk: &str, cmu: &[u8], epk: &[u8], ciphertext: &[u8]) -> anyhow::Result> { + let mut vks = HashMap::new(); + let fvk = decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk)?.ok_or(anyhow!("Invalid FVK"))?; + let ivk = fvk.fvk.vk.ivk(); + vks.insert(0, AccountViewKey { + fvk, + ivk, + viewonly: false + }); + let dn = DecryptNode::new(vks); + let block = vec![CompactBlock { + proto_version: 0, // don't care about most of these fields + height: height as u64, + hash: vec![], + prev_hash: vec![], + time: 0, + header: vec![], + vtx: vec![ + CompactTx { + index: 0, + hash: vec![], + fee: 0, + spends: vec![], + actions: vec![], + outputs: vec![ + CompactSaplingOutput { + cmu: cmu.to_vec(), + epk: epk.to_vec(), + ciphertext: ciphertext.to_vec(), + } + ], + } + ] + }]; + let decrypted_block = dn.decrypt_blocks(network, block); + let decrypted_block = decrypted_block.first().unwrap(); + let note = decrypted_block.notes.first().map(|dn| dn.note.clone()); + Ok(note) +} \ No newline at end of file diff --git a/src/taddr.rs b/src/taddr.rs index e2f8b26..4dc1245 100644 --- a/src/taddr.rs +++ b/src/taddr.rs @@ -1,4 +1,5 @@ use crate::coinconfig::CoinConfig; +use crate::db::AccountData; use crate::{AddressList, CompactTxStreamerClient, GetAddressUtxosArg, GetAddressUtxosReply}; use anyhow::anyhow; use base58check::FromBase58Check; @@ -52,17 +53,20 @@ pub async fn scan_transparent_accounts( let c = CoinConfig::get_active(); let mut addresses = vec![]; let db = c.db()?; - let (seed, mut index) = db.get_seed(c.id_account)?; + let account_data = db.get_account_info(c.id_account)?; + let AccountData { + seed, mut aindex, .. + } = account_data; if let Some(seed) = seed { let mut gap = 0; while gap < gap_limit { - let bip44_path = format!("m/44'/{}'/0'/0/{}", network.coin_type(), index); - log::info!("{} {}", index, bip44_path); + let bip44_path = format!("m/44'/{}'/0'/0/{}", network.coin_type(), aindex); + log::info!("{} {}", aindex, bip44_path); let (_, address) = derive_tkeys(network, &seed, &bip44_path)?; let balance = get_taddr_balance(client, &address).await?; if balance > 0 { addresses.push(TBalance { - index, + index: aindex, address, balance, }); @@ -70,7 +74,7 @@ pub async fn scan_transparent_accounts( } else { gap += 1; } - index += 1; + aindex += 1; } } db.store_t_scan(&addresses)?;