diversifier address by time

This commit is contained in:
Hanh 2023-02-26 09:53:50 +10:00
parent cda240c8e9
commit 39266e766e
6 changed files with 118 additions and 44 deletions

View File

@ -190,7 +190,7 @@ int8_t is_valid_key(uint8_t coin, char *key);
bool valid_address(uint8_t coin, char *address);
struct CResult_____c_char new_diversified_address(uint8_t ua_type);
struct CResult_____c_char get_diversified_address(uint8_t ua_type, uint32_t time);
struct CResult_u32 get_latest_height(void);

View File

@ -24,6 +24,7 @@ use zcash_address::{ToAddress, ZcashAddress};
use zcash_client_backend::encoding::{decode_extended_full_viewing_key, encode_payment_address};
use zcash_client_backend::keys::UnifiedFullViewingKey;
use zcash_primitives::consensus::Parameters;
use zcash_primitives::zip32::DiversifierIndex;
/// Create a new account
/// # Arguments
@ -188,7 +189,7 @@ pub fn import_transparent_secret_key(coin: u8, id_account: u32, sk: &str) -> any
}
/// Generate a new diversified address
pub fn new_diversified_address(ua_type: u8) -> anyhow::Result<String> {
pub fn get_diversified_address(ua_type: u8, time: u32) -> anyhow::Result<String> {
let ua_type = ua_type & 6; // don't include transparent component
if ua_type == 0 {
anyhow::bail!("Must include a shielded receiver");
@ -201,12 +202,12 @@ pub fn new_diversified_address(ua_type: u8) -> anyhow::Result<String> {
&fvk,
)
.map_err(|_| anyhow!("Bech32 Decode Error"))?;
let mut diversifier_index = db.get_diversifier(c.id_account)?;
diversifier_index.increment().unwrap();
let (new_diversifier_index, pa) = fvk
let mut di = [0u8; 11];
di[4..8].copy_from_slice(&time.to_le_bytes());
let diversifier_index = DiversifierIndex(di);
let (_, pa) = fvk
.find_address(diversifier_index)
.ok_or_else(|| anyhow::anyhow!("Cannot generate new address"))?;
db.store_diversifier(c.id_account, &new_diversifier_index)?;
let orchard_keys = db.get_orchard(c.id_account)?;
if ua_type == 2 || orchard_keys.is_none() {

View File

@ -348,8 +348,8 @@ pub unsafe extern "C" fn valid_address(coin: u8, address: *mut c_char) -> bool {
}
#[no_mangle]
pub unsafe extern "C" fn new_diversified_address(ua_type: u8) -> CResult<*mut c_char> {
let res = || crate::api::account::new_diversified_address(ua_type);
pub unsafe extern "C" fn get_diversified_address(ua_type: u8, time: u32) -> CResult<*mut c_char> {
let res = || crate::api::account::get_diversified_address(ua_type, time);
to_cresult_str(res())
}

View File

@ -5,7 +5,7 @@ use crate::orchard::{derive_orchard_keys, OrchardKeyBytes, OrchardViewKey};
use crate::prices::Quote;
use crate::sapling::SaplingViewKey;
use crate::sync::tree::{CTree, TreeCheckpoint};
use crate::taddr::derive_tkeys;
use crate::taddr::{derive_tkeys, TransparentTxInfo};
use crate::transaction::{GetTransactionDetailRequest, TransactionDetails};
use crate::unified::UnifiedAddressType;
use crate::{sync, BlockId, CoinConfig, CompactTxStreamerClient, Hash};
@ -486,6 +486,14 @@ impl DbAdapter {
Ok(())
}
pub fn store_transparent_tx(
_account: u32,
_tx: &TransparentTxInfo,
_db_tx: &Transaction,
) -> anyhow::Result<()> {
todo!()
}
pub fn add_value(id_tx: u32, value: i64, db_tx: &Transaction) -> anyhow::Result<()> {
db_tx.execute(
"UPDATE transactions SET value = value + ?2 WHERE id_tx = ?1",
@ -825,38 +833,6 @@ impl DbAdapter {
Ok(contacts)
}
pub fn get_diversifier(&self, account: u32) -> anyhow::Result<DiversifierIndex> {
let diversifier_index = self
.connection
.query_row(
"SELECT diversifier_index FROM diversifiers WHERE account = ?1",
params![account],
|row| {
let d: Vec<u8> = row.get(0)?;
let mut div = [0u8; 11];
div.copy_from_slice(&d);
Ok(div)
},
)
.optional()?
.unwrap_or([0u8; 11]);
Ok(DiversifierIndex(diversifier_index))
}
pub fn store_diversifier(
&self,
account: u32,
diversifier_index: &DiversifierIndex,
) -> anyhow::Result<()> {
let diversifier_bytes = diversifier_index.0.to_vec();
self.connection.execute(
"INSERT INTO diversifiers(account, diversifier_index) VALUES (?1, ?2) ON CONFLICT \
(account) DO UPDATE SET diversifier_index = excluded.diversifier_index",
params![account, diversifier_bytes],
)?;
Ok(())
}
pub fn get_account_info(&self, account: u32) -> anyhow::Result<AccountData> {
assert_ne!(account, 0);
log::info!("get_account_info {} {}", self.db_path, account);

View File

@ -356,7 +356,7 @@ pub async fn build_from_plan(tx_plan: Json<TransactionPlan>) -> Result<String, E
#[get("/new_diversified_address")]
pub fn new_diversified_address() -> Result<String, Error> {
let address = warp_api_ffi::api::account::new_diversified_address()?;
let address = warp_api_ffi::api::account::get_diversified_address()?;
Ok(address)
}

View File

@ -6,8 +6,8 @@ use crate::db::AccountData;
use crate::note_selection::{SecretKeys, Source, UTXO};
use crate::unified::orchard_as_unified;
use crate::{
broadcast_tx, build_tx, AddressList, CompactTxStreamerClient, GetAddressUtxosArg,
GetAddressUtxosReply, TransparentAddressBlockFilter,
broadcast_tx, build_tx, AddressList, BlockId, CompactTxStreamerClient, GetAddressUtxosArg,
GetAddressUtxosReply, Hash, TransparentAddressBlockFilter, TxFilter,
};
use anyhow::anyhow;
use base58check::FromBase58Check;
@ -18,13 +18,17 @@ use rand::rngs::OsRng;
use ripemd::{Digest, Ripemd160};
use secp256k1::{All, PublicKey, Secp256k1, SecretKey};
use sha2::Sha256;
use std::collections::HashMap;
use tiny_hderive::bip32::ExtendedPrivKey;
use tonic::transport::Channel;
use tonic::Request;
use zcash_client_backend::encoding::encode_transparent_address;
use zcash_params::coin::get_branch;
use zcash_primitives::consensus::{Network, Parameters};
use zcash_primitives::legacy::TransparentAddress;
use zcash_primitives::memo::Memo;
use zcash_primitives::transaction::components::OutPoint;
use zcash_primitives::transaction::Transaction;
pub async fn get_taddr_balance(
client: &mut CompactTxStreamerClient<Channel>,
@ -40,6 +44,99 @@ pub async fn get_taddr_balance(
Ok(rep.value_zat as u64)
}
pub struct TransparentTxInfo {
pub txid: Hash,
pub height: u32,
pub timestamp: u32,
pub inputs: Vec<OutPoint>,
pub in_value: u64,
pub out_value: u64,
}
/* With the current LWD API, this function performs poorly because
the server does not return tx timestamp, height and value
*/
#[allow(unused)]
pub async fn get_ttx_history(
network: &Network,
client: &mut CompactTxStreamerClient<Channel>,
address: &str,
) -> anyhow::Result<Vec<TransparentTxInfo>> {
let mut rep = client
.get_taddress_txids(Request::new(TransparentAddressBlockFilter {
address: address.to_string(),
range: None,
}))
.await?
.into_inner();
let mut heights: HashMap<u32, u32> = HashMap::new();
let mut txs = vec![];
while let Some(raw_tx) = rep.message().await? {
let height = raw_tx.height as u32;
heights.insert(height, 0);
let consensus_branch_id = get_branch(network, height);
let tx = Transaction::read(&*raw_tx.data, consensus_branch_id)?;
let txid = tx.txid();
let tx_data = tx.into_data();
let mut inputs = vec![];
if let Some(transparent_bundle) = tx_data.transparent_bundle() {
for vin in transparent_bundle.vin.iter() {
inputs.push(vin.prevout.clone());
}
let out_value = transparent_bundle
.vout
.iter()
.map(|vout| i64::from(vout.value))
.sum::<i64>() as u64;
txs.push(TransparentTxInfo {
txid: txid.as_ref().clone(),
height,
timestamp: 0,
inputs,
in_value: 0,
out_value,
});
}
}
for (h, timestamp) in heights.iter_mut() {
let block = client
.get_block(Request::new(BlockId {
height: *h as u64,
hash: vec![],
}))
.await?
.into_inner();
*timestamp = block.time;
}
for tx in txs.iter_mut() {
let mut in_value = 0;
for input in tx.inputs.iter() {
let raw_tx = client
.get_transaction(Request::new(TxFilter {
block: None,
index: 0,
hash: input.hash().to_vec(),
}))
.await?
.into_inner();
let consensus_branch_id = get_branch(network, raw_tx.height as u32);
let tx = Transaction::read(&*raw_tx.data, consensus_branch_id)?;
let tx_data = tx.into_data();
let transparent_bundle = tx_data
.transparent_bundle()
.ok_or(anyhow!("No transparent bundle"))?;
let value = i64::from(transparent_bundle.vout[input.n() as usize].value);
in_value += value;
}
tx.timestamp = heights[&tx.height];
tx.in_value = in_value as u64;
tx.inputs.clear();
}
Ok(txs)
}
pub async fn get_taddr_tx_count(
client: &mut CompactTxStreamerClient<Channel>,
address: &str,