GetTransactionInfo performance optimizations
This commit is contained in:
parent
632792ffba
commit
7590bf179b
|
@ -1,4 +1,5 @@
|
||||||
use crate::commitment::{CTree, Witness};
|
use crate::commitment::{CTree, Witness};
|
||||||
|
use crate::db::AccountViewKey;
|
||||||
use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
|
use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
|
||||||
use crate::lw_rpc::*;
|
use crate::lw_rpc::*;
|
||||||
use crate::{advance_tree, NETWORK};
|
use crate::{advance_tree, NETWORK};
|
||||||
|
@ -17,7 +18,6 @@ use zcash_primitives::sapling::note_encryption::try_sapling_compact_note_decrypt
|
||||||
use zcash_primitives::sapling::{Node, Note, PaymentAddress};
|
use zcash_primitives::sapling::{Node, Note, PaymentAddress};
|
||||||
use zcash_primitives::transaction::components::sapling::CompactOutputDescription;
|
use zcash_primitives::transaction::components::sapling::CompactOutputDescription;
|
||||||
use zcash_primitives::zip32::ExtendedFullViewingKey;
|
use zcash_primitives::zip32::ExtendedFullViewingKey;
|
||||||
use crate::db::AccountViewKey;
|
|
||||||
|
|
||||||
const MAX_CHUNK: u32 = 50000;
|
const MAX_CHUNK: u32 = 50000;
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ pub fn to_output_description(co: &CompactOutput) -> CompactOutputDescription {
|
||||||
|
|
||||||
fn decrypt_notes<'a>(
|
fn decrypt_notes<'a>(
|
||||||
block: &'a CompactBlock,
|
block: &'a CompactBlock,
|
||||||
vks: &HashMap<u32, AccountViewKey>
|
vks: &HashMap<u32, AccountViewKey>,
|
||||||
) -> DecryptedBlock<'a> {
|
) -> DecryptedBlock<'a> {
|
||||||
let height = BlockHeight::from_u32(block.height as u32);
|
let height = BlockHeight::from_u32(block.height as u32);
|
||||||
let mut count_outputs = 0u32;
|
let mut count_outputs = 0u32;
|
||||||
|
@ -366,6 +366,7 @@ mod tests {
|
||||||
calculate_tree_state_v1, calculate_tree_state_v2, download_chain, get_latest_height,
|
calculate_tree_state_v1, calculate_tree_state_v2, download_chain, get_latest_height,
|
||||||
get_tree_state, DecryptNode,
|
get_tree_state, DecryptNode,
|
||||||
};
|
};
|
||||||
|
use crate::db::AccountViewKey;
|
||||||
use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
|
use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
|
||||||
use crate::LWD_URL;
|
use crate::LWD_URL;
|
||||||
use crate::NETWORK;
|
use crate::NETWORK;
|
||||||
|
@ -374,7 +375,6 @@ mod tests {
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use zcash_client_backend::encoding::decode_extended_full_viewing_key;
|
use zcash_client_backend::encoding::decode_extended_full_viewing_key;
|
||||||
use zcash_primitives::consensus::{NetworkUpgrade, Parameters};
|
use zcash_primitives::consensus::{NetworkUpgrade, Parameters};
|
||||||
use crate::db::AccountViewKey;
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_latest_height() -> anyhow::Result<()> {
|
async fn test_get_latest_height() -> anyhow::Result<()> {
|
||||||
|
|
74
src/db.rs
74
src/db.rs
|
@ -1,15 +1,15 @@
|
||||||
use crate::chain::{Nf, NfRef};
|
use crate::chain::{Nf, NfRef};
|
||||||
use crate::db::migration::{get_schema_version, update_schema_version};
|
use crate::db::migration::{get_schema_version, update_schema_version};
|
||||||
use crate::taddr::{derive_tkeys, BIP44_PATH};
|
use crate::taddr::{derive_tkeys, BIP44_PATH};
|
||||||
use crate::transaction::{TransactionInfo, Contact};
|
use crate::transaction::{Contact, TransactionInfo};
|
||||||
use crate::{CTree, Witness, NETWORK};
|
use crate::{CTree, Witness, NETWORK};
|
||||||
use rusqlite::{params, Connection, OptionalExtension, NO_PARAMS};
|
use rusqlite::{params, Connection, OptionalExtension, NO_PARAMS};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use zcash_client_backend::encoding::decode_extended_full_viewing_key;
|
||||||
use zcash_primitives::consensus::{NetworkUpgrade, Parameters};
|
use zcash_primitives::consensus::{NetworkUpgrade, Parameters};
|
||||||
use zcash_primitives::merkle_tree::IncrementalWitness;
|
use zcash_primitives::merkle_tree::IncrementalWitness;
|
||||||
use zcash_primitives::sapling::{Diversifier, Node, Note, Rseed, SaplingIvk};
|
use zcash_primitives::sapling::{Diversifier, Node, Note, Rseed, SaplingIvk};
|
||||||
use zcash_primitives::zip32::{DiversifierIndex, ExtendedFullViewingKey};
|
use zcash_primitives::zip32::{DiversifierIndex, ExtendedFullViewingKey};
|
||||||
use zcash_client_backend::encoding::decode_extended_full_viewing_key;
|
|
||||||
|
|
||||||
mod migration;
|
mod migration;
|
||||||
|
|
||||||
|
@ -57,14 +57,10 @@ impl AccountViewKey {
|
||||||
impl DbAdapter {
|
impl DbAdapter {
|
||||||
pub fn new(db_path: &str) -> anyhow::Result<DbAdapter> {
|
pub fn new(db_path: &str) -> anyhow::Result<DbAdapter> {
|
||||||
let connection = Connection::open(db_path)?;
|
let connection = Connection::open(db_path)?;
|
||||||
|
connection.execute("PRAGMA synchronous = off", NO_PARAMS)?;
|
||||||
Ok(DbAdapter { connection })
|
Ok(DbAdapter { connection })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn synchronous(&self, flag: bool) -> anyhow::Result<()> {
|
|
||||||
self.connection.execute(&format!("PRAGMA synchronous = {}", if flag { "on" } else { "off" }), NO_PARAMS)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn begin_transaction(&self) -> anyhow::Result<()> {
|
pub fn begin_transaction(&self) -> anyhow::Result<()> {
|
||||||
self.connection.execute("BEGIN TRANSACTION", NO_PARAMS)?;
|
self.connection.execute("BEGIN TRANSACTION", NO_PARAMS)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -175,7 +171,8 @@ impl DbAdapter {
|
||||||
account INTEGER NOT NULL,
|
account INTEGER NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
address TEXT NOT NULL,
|
address TEXT NOT NULL,
|
||||||
PRIMARY KEY (account, address))", NO_PARAMS
|
PRIMARY KEY (account, address))",
|
||||||
|
NO_PARAMS,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,9 +210,21 @@ impl DbAdapter {
|
||||||
let account: u32 = row.get(0)?;
|
let account: u32 = row.get(0)?;
|
||||||
let ivk: String = row.get(1)?;
|
let ivk: String = row.get(1)?;
|
||||||
let sk: Option<String> = row.get(2)?;
|
let sk: Option<String> = row.get(2)?;
|
||||||
let fvk = decode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &ivk).unwrap().unwrap();
|
let fvk = decode_extended_full_viewing_key(
|
||||||
|
NETWORK.hrp_sapling_extended_full_viewing_key(),
|
||||||
|
&ivk,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
let ivk = fvk.fvk.vk.ivk();
|
let ivk = fvk.fvk.vk.ivk();
|
||||||
Ok((account, AccountViewKey { fvk, ivk, viewonly: sk.is_none() }))
|
Ok((
|
||||||
|
account,
|
||||||
|
AccountViewKey {
|
||||||
|
fvk,
|
||||||
|
ivk,
|
||||||
|
viewonly: sk.is_none(),
|
||||||
|
},
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
let mut fvks: HashMap<u32, AccountViewKey> = HashMap::new();
|
let mut fvks: HashMap<u32, AccountViewKey> = HashMap::new();
|
||||||
for r in rows {
|
for r in rows {
|
||||||
|
@ -245,18 +254,19 @@ impl DbAdapter {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_txhash(&self, id_tx: u32) -> anyhow::Result<(u32, u32, Vec<u8>)> {
|
pub fn get_txhash(&self, id_tx: u32) -> anyhow::Result<(u32, u32, Vec<u8>, String)> {
|
||||||
let (account, height, tx_hash) = self.connection.query_row(
|
let (account, height, tx_hash, ivk) = self.connection.query_row(
|
||||||
"SELECT account, height, txid FROM transactions WHERE id_tx = ?1",
|
"SELECT account, height, txid, ivk FROM transactions t, accounts a WHERE id_tx = ?1 AND t.account = a.id_account",
|
||||||
params![id_tx],
|
params![id_tx],
|
||||||
|row| {
|
|row| {
|
||||||
let account: u32 = row.get(0)?;
|
let account: u32 = row.get(0)?;
|
||||||
let height: u32 = row.get(1)?;
|
let height: u32 = row.get(1)?;
|
||||||
let tx_hash: Vec<u8> = row.get(2)?;
|
let tx_hash: Vec<u8> = row.get(2)?;
|
||||||
Ok((account, height, tx_hash))
|
let ivk: String = row.get(3)?;
|
||||||
|
Ok((account, height, tx_hash, ivk))
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
Ok((account, height, tx_hash))
|
Ok((account, height, tx_hash, ivk))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store_block(
|
pub fn store_block(
|
||||||
|
@ -574,13 +584,17 @@ impl DbAdapter {
|
||||||
pub fn store_contact(&self, account: u32, contact: &Contact) -> anyhow::Result<()> {
|
pub fn store_contact(&self, account: u32, contact: &Contact) -> anyhow::Result<()> {
|
||||||
log::info!("{:?}", contact);
|
log::info!("{:?}", contact);
|
||||||
if contact.name.is_empty() {
|
if contact.name.is_empty() {
|
||||||
self.connection.execute("DELETE FROM contacts WHERE account = ?1 AND address = ?2",
|
self.connection.execute(
|
||||||
params![account, contact.address])?;
|
"DELETE FROM contacts WHERE account = ?1 AND address = ?2",
|
||||||
}
|
params![account, contact.address],
|
||||||
else {
|
)?;
|
||||||
self.connection.execute("INSERT INTO contacts(account, name, address)
|
} else {
|
||||||
|
self.connection.execute(
|
||||||
|
"INSERT INTO contacts(account, name, address)
|
||||||
VALUES (?1, ?2, ?3) ON CONFLICT (account, address) DO UPDATE SET
|
VALUES (?1, ?2, ?3) ON CONFLICT (account, address) DO UPDATE SET
|
||||||
name = excluded.name", params![account, &contact.name, &contact.address])?;
|
name = excluded.name",
|
||||||
|
params![account, &contact.name, &contact.address],
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -606,16 +620,14 @@ impl DbAdapter {
|
||||||
|
|
||||||
pub fn get_seed(&self, account: u32) -> anyhow::Result<Option<String>> {
|
pub fn get_seed(&self, account: u32) -> anyhow::Result<Option<String>> {
|
||||||
log::info!("+get_seed");
|
log::info!("+get_seed");
|
||||||
let seed = self
|
let seed = self.connection.query_row(
|
||||||
.connection
|
"SELECT seed FROM accounts WHERE id_account = ?1",
|
||||||
.query_row(
|
params![account],
|
||||||
"SELECT seed FROM accounts WHERE id_account = ?1",
|
|row| {
|
||||||
params![account],
|
let sk: Option<String> = row.get(0)?;
|
||||||
|row| {
|
Ok(sk)
|
||||||
let sk: Option<String> = row.get(0)?;
|
},
|
||||||
Ok(sk)
|
)?;
|
||||||
},
|
|
||||||
)?;
|
|
||||||
log::info!("-get_seed");
|
log::info!("-get_seed");
|
||||||
Ok(seed)
|
Ok(seed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustyline::Editor;
|
|
||||||
use rustyline::error::ReadlineError;
|
|
||||||
use clap::{AppSettings, Clap};
|
use clap::{AppSettings, Clap};
|
||||||
|
use rustyline::error::ReadlineError;
|
||||||
|
use rustyline::Editor;
|
||||||
|
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
#[clap(setting = AppSettings::NoBinaryName)]
|
#[clap(setting = AppSettings::NoBinaryName)]
|
||||||
|
@ -32,7 +32,7 @@ fn main() {
|
||||||
match Commands::try_parse_from(line.split_whitespace()) {
|
match Commands::try_parse_from(line.split_whitespace()) {
|
||||||
Ok(cmd) => {
|
Ok(cmd) => {
|
||||||
run_cmd(&cmd.cmd);
|
run_cmd(&cmd.cmd);
|
||||||
},
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,7 @@ use bip39::{Language, Mnemonic};
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use rand::{thread_rng, RngCore};
|
use rand::{thread_rng, RngCore};
|
||||||
use rusqlite::NO_PARAMS;
|
use rusqlite::NO_PARAMS;
|
||||||
use sync::{
|
use sync::{pedersen_hash, print_witness2, ChainError, DbAdapter, Wallet, Witness, LWD_URL};
|
||||||
pedersen_hash, print_witness2, ChainError, DbAdapter, Wallet, Witness, LWD_URL,
|
|
||||||
};
|
|
||||||
use zcash_client_backend::data_api::wallet::ANCHOR_OFFSET;
|
use zcash_client_backend::data_api::wallet::ANCHOR_OFFSET;
|
||||||
use zcash_primitives::merkle_tree::Hashable;
|
use zcash_primitives::merkle_tree::Hashable;
|
||||||
use zcash_primitives::sapling::Node;
|
use zcash_primitives::sapling::Node;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::builder::BlockProcessor;
|
use crate::builder::BlockProcessor;
|
||||||
use crate::chain::{Nf, NfRef};
|
use crate::chain::{Nf, NfRef};
|
||||||
use crate::db::{DbAdapter, ReceivedNote, AccountViewKey};
|
use crate::db::{AccountViewKey, DbAdapter, ReceivedNote};
|
||||||
use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
|
use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
|
||||||
use crate::transaction::retrieve_tx_info;
|
use crate::transaction::retrieve_tx_info;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -130,7 +130,6 @@ pub async fn sync_async(
|
||||||
|
|
||||||
let processor = tokio::spawn(async move {
|
let processor = tokio::spawn(async move {
|
||||||
let db = DbAdapter::new(&db_path)?;
|
let db = DbAdapter::new(&db_path)?;
|
||||||
db.synchronous(false)?;
|
|
||||||
let mut nfs = db.get_nullifiers()?;
|
let mut nfs = db.get_nullifiers()?;
|
||||||
|
|
||||||
let (mut tree, mut witnesses) = db.get_tree()?;
|
let (mut tree, mut witnesses) = db.get_tree()?;
|
||||||
|
@ -268,7 +267,9 @@ pub async fn sync_async(
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
if get_tx && !new_tx_ids.is_empty() {
|
if get_tx && !new_tx_ids.is_empty() {
|
||||||
retrieve_tx_info(&mut client, &db_path2, &new_tx_ids).await.unwrap();
|
retrieve_tx_info(&mut client, &db_path2, &new_tx_ids)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
log::info!("Transaction Details : {}", start.elapsed().as_millis());
|
log::info!("Transaction Details : {}", start.elapsed().as_millis());
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use zcash_primitives::sapling::note_encryption::{
|
||||||
try_sapling_note_decryption, try_sapling_output_recovery,
|
try_sapling_note_decryption, try_sapling_output_recovery,
|
||||||
};
|
};
|
||||||
use zcash_primitives::transaction::Transaction;
|
use zcash_primitives::transaction::Transaction;
|
||||||
|
use zcash_primitives::zip32::ExtendedFullViewingKey;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TransactionInfo {
|
pub struct TransactionInfo {
|
||||||
|
@ -31,13 +32,10 @@ pub async fn decode_transaction(
|
||||||
client: &mut CompactTxStreamerClient<Channel>,
|
client: &mut CompactTxStreamerClient<Channel>,
|
||||||
nfs: &HashMap<(u32, Vec<u8>), u64>,
|
nfs: &HashMap<(u32, Vec<u8>), u64>,
|
||||||
account: u32,
|
account: u32,
|
||||||
fvk: &str,
|
fvk: &ExtendedFullViewingKey,
|
||||||
tx_hash: &[u8],
|
tx_hash: &[u8],
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> anyhow::Result<TransactionInfo> {
|
) -> anyhow::Result<TransactionInfo> {
|
||||||
let fvk =
|
|
||||||
decode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &fvk)?
|
|
||||||
.unwrap();
|
|
||||||
let ivk = fvk.fvk.vk.ivk();
|
let ivk = fvk.fvk.vk.ivk();
|
||||||
let ovk = fvk.fvk.ovk;
|
let ovk = fvk.fvk.ovk;
|
||||||
|
|
||||||
|
@ -82,7 +80,7 @@ pub async fn decode_transaction(
|
||||||
tx_memo = memo;
|
tx_memo = memo;
|
||||||
}
|
}
|
||||||
} else if let Some((_note, pa, memo)) =
|
} else if let Some((_note, pa, memo)) =
|
||||||
try_sapling_output_recovery(&NETWORK, height, &ovk, &output)
|
try_sapling_output_recovery(&NETWORK, height, &ovk, &output)
|
||||||
{
|
{
|
||||||
address = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &pa);
|
address = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &pa);
|
||||||
tx_memo = memo;
|
tx_memo = memo;
|
||||||
|
@ -107,21 +105,33 @@ pub async fn decode_transaction(
|
||||||
Ok(tx_info)
|
Ok(tx_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn retrieve_tx_info(client: &mut CompactTxStreamerClient<Channel>, db_path: &str, tx_ids: &[u32]) -> anyhow::Result<()> {
|
pub async fn retrieve_tx_info(
|
||||||
|
client: &mut CompactTxStreamerClient<Channel>,
|
||||||
|
db_path: &str,
|
||||||
|
tx_ids: &[u32],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let db = DbAdapter::new(db_path)?;
|
let db = DbAdapter::new(db_path)?;
|
||||||
let mut tx_ids_set: HashSet<u32> = HashSet::new();
|
db.begin_transaction()?;
|
||||||
let nfs = db.get_nullifiers_raw()?;
|
let nfs = db.get_nullifiers_raw()?;
|
||||||
let mut nf_map: HashMap<(u32, Vec<u8>), u64> = HashMap::new();
|
let mut nf_map: HashMap<(u32, Vec<u8>), u64> = HashMap::new();
|
||||||
for nf in nfs.iter() {
|
for nf in nfs.iter() {
|
||||||
nf_map.insert((nf.0, nf.2.clone()), nf.1);
|
nf_map.insert((nf.0, nf.2.clone()), nf.1);
|
||||||
}
|
}
|
||||||
for &id_tx in tx_ids.iter() { // need to keep tx order
|
let mut tx_ids_set: HashSet<u32> = HashSet::new();
|
||||||
if tx_ids_set.contains(&id_tx) { continue }
|
let mut fvk_cache: HashMap<u32, ExtendedFullViewingKey> = HashMap::new();
|
||||||
|
for &id_tx in tx_ids.iter() {
|
||||||
|
// need to keep tx order
|
||||||
|
if tx_ids_set.contains(&id_tx) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
tx_ids_set.insert(id_tx);
|
tx_ids_set.insert(id_tx);
|
||||||
let (account, height, tx_hash) = db.get_txhash(id_tx)?;
|
let (account, height, tx_hash, ivk) = db.get_txhash(id_tx)?;
|
||||||
let fvk = db.get_ivk(account)?;
|
let fvk = fvk_cache.entry(account).or_insert_with(|| {
|
||||||
let tx_info =
|
decode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &ivk)
|
||||||
decode_transaction(client, &nf_map, account, &fvk, &tx_hash, height).await?;
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
let tx_info = decode_transaction(client, &nf_map, account, fvk, &tx_hash, height).await?;
|
||||||
if !tx_info.address.is_empty() && !tx_info.memo.is_empty() {
|
if !tx_info.address.is_empty() && !tx_info.memo.is_empty() {
|
||||||
if let Some(contact) = decode_contact(&tx_info.address, &tx_info.memo)? {
|
if let Some(contact) = decode_contact(&tx_info.address, &tx_info.memo)? {
|
||||||
db.store_contact(account, &contact)?;
|
db.store_contact(account, &contact)?;
|
||||||
|
@ -129,6 +139,7 @@ pub async fn retrieve_tx_info(client: &mut CompactTxStreamerClient<Channel>, db_
|
||||||
}
|
}
|
||||||
db.store_tx_metadata(id_tx, &tx_info)?;
|
db.store_tx_metadata(id_tx, &tx_info)?;
|
||||||
}
|
}
|
||||||
|
db.commit()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -140,15 +151,19 @@ fn decode_contact(address: &str, memo: &str) -> anyhow::Result<Option<Contact>>
|
||||||
name: name.trim().to_string(),
|
name: name.trim().to_string(),
|
||||||
address: address.to_string(),
|
address: address.to_string(),
|
||||||
})
|
})
|
||||||
} else { None };
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::transaction::decode_transaction;
|
use crate::transaction::decode_transaction;
|
||||||
use crate::{connect_lightwalletd, DbAdapter, LWD_URL};
|
use crate::{connect_lightwalletd, DbAdapter, LWD_URL, NETWORK};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use zcash_client_backend::encoding::decode_extended_full_viewing_key;
|
||||||
|
use zcash_primitives::consensus::Parameters;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_decode_transaction() {
|
async fn test_decode_transaction() {
|
||||||
|
@ -166,6 +181,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let fvk = db.get_ivk(account).unwrap();
|
let fvk = db.get_ivk(account).unwrap();
|
||||||
|
let fvk =
|
||||||
|
decode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &fvk)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
let tx_info = decode_transaction(&mut client, &nf_map, account, &fvk, &tx_hash, 1313212)
|
let tx_info = decode_transaction(&mut client, &nf_map, account, &fvk, &tx_hash, 1313212)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Reference in New Issue