rustfmt
This commit is contained in:
parent
9ae96e7d88
commit
c51c98138a
|
@ -206,8 +206,12 @@ pub fn new_diversified_address(ua_type: u8) -> anyhow::Result<String> {
|
|||
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() { // sapling only
|
||||
return Ok(encode_payment_address(c.chain.network().hrp_sapling_payment_address(), &pa));
|
||||
if ua_type == 2 || orchard_keys.is_none() {
|
||||
// sapling only
|
||||
return Ok(encode_payment_address(
|
||||
c.chain.network().hrp_sapling_payment_address(),
|
||||
&pa,
|
||||
));
|
||||
}
|
||||
|
||||
let orchard_keys = orchard_keys.unwrap();
|
||||
|
@ -371,11 +375,7 @@ pub fn derive_keys(
|
|||
/// * t, s, o: include transparent, sapling, orchard receivers?
|
||||
///
|
||||
/// The address depends on the UA settings and may include transparent, sapling & orchard receivers
|
||||
pub fn get_unified_address(
|
||||
coin: u8,
|
||||
id_account: u32,
|
||||
address_type: u8,
|
||||
) -> anyhow::Result<String> {
|
||||
pub fn get_unified_address(coin: u8, id_account: u32, address_type: u8) -> anyhow::Result<String> {
|
||||
let c = CoinConfig::get(coin);
|
||||
let db = c.db()?;
|
||||
let tpe = UnifiedAddressType {
|
||||
|
|
|
@ -414,7 +414,8 @@ pub async unsafe extern "C" fn get_taddr_balance(coin: u8, id_account: u32) -> C
|
|||
pub async unsafe extern "C" fn transfer_pools(
|
||||
coin: u8,
|
||||
account: u32,
|
||||
from_pool: u8, to_pool: u8,
|
||||
from_pool: u8,
|
||||
to_pool: u8,
|
||||
amount: u64,
|
||||
fee_included: bool,
|
||||
memo: *mut c_char,
|
||||
|
@ -423,9 +424,18 @@ pub async unsafe extern "C" fn transfer_pools(
|
|||
) -> CResult<*mut c_char> {
|
||||
from_c_str!(memo);
|
||||
let res = async move {
|
||||
let tx_plan = crate::api::payment_v2::transfer_pools(coin, account, from_pool, to_pool,
|
||||
amount, fee_included,
|
||||
&memo, split_amount, confirmations).await?;
|
||||
let tx_plan = crate::api::payment_v2::transfer_pools(
|
||||
coin,
|
||||
account,
|
||||
from_pool,
|
||||
to_pool,
|
||||
amount,
|
||||
fee_included,
|
||||
&memo,
|
||||
split_amount,
|
||||
confirmations,
|
||||
)
|
||||
.await?;
|
||||
let tx_plan = serde_json::to_string(&tx_plan)?;
|
||||
Ok::<_, anyhow::Error>(tx_plan)
|
||||
};
|
||||
|
|
|
@ -32,7 +32,9 @@ pub async fn build_tx_plan(
|
|||
let mut recipient_fee = false;
|
||||
for r in recipients {
|
||||
if r.fee_included {
|
||||
if recipient_fee { return Err(TransactionBuilderError::DuplicateRecipientFee) }
|
||||
if recipient_fee {
|
||||
return Err(TransactionBuilderError::DuplicateRecipientFee);
|
||||
}
|
||||
recipient_fee = true;
|
||||
}
|
||||
}
|
||||
|
@ -154,8 +156,17 @@ pub async fn build_max_tx(
|
|||
Err(TransactionBuilderError::TxTooComplex)
|
||||
}
|
||||
|
||||
pub async fn transfer_pools(coin: u8, account: u32, from_pool: u8, to_pool: u8, amount: u64,
|
||||
fee_included: bool, memo: &str, split_amount: u64, confirmations: u32) -> anyhow::Result<TransactionPlan> {
|
||||
pub async fn transfer_pools(
|
||||
coin: u8,
|
||||
account: u32,
|
||||
from_pool: u8,
|
||||
to_pool: u8,
|
||||
amount: u64,
|
||||
fee_included: bool,
|
||||
memo: &str,
|
||||
split_amount: u64,
|
||||
confirmations: u32,
|
||||
) -> anyhow::Result<TransactionPlan> {
|
||||
let address = get_unified_address(coin, account, to_pool)?; // get our own unified address
|
||||
let recipient = RecipientMemo {
|
||||
address,
|
||||
|
@ -165,14 +176,37 @@ pub async fn transfer_pools(coin: u8, account: u32, from_pool: u8, to_pool: u8,
|
|||
max_amount_per_note: split_amount,
|
||||
};
|
||||
let last_height = get_latest_height().await?;
|
||||
let tx_plan = build_tx_plan(coin, account, last_height, slice::from_ref(&recipient),
|
||||
!from_pool, confirmations).await?;
|
||||
let tx_plan = build_tx_plan(
|
||||
coin,
|
||||
account,
|
||||
last_height,
|
||||
slice::from_ref(&recipient),
|
||||
!from_pool,
|
||||
confirmations,
|
||||
)
|
||||
.await?;
|
||||
Ok(tx_plan)
|
||||
}
|
||||
|
||||
/// Make a transaction that shields the transparent balance
|
||||
pub async fn shield_taddr(coin: u8, account: u32, amount: u64, confirmations: u32) -> anyhow::Result<String> {
|
||||
let tx_plan = transfer_pools(coin, account, 1, 6, amount, true, "Shield Transparent Balance", 0, confirmations).await?;
|
||||
pub async fn shield_taddr(
|
||||
coin: u8,
|
||||
account: u32,
|
||||
amount: u64,
|
||||
confirmations: u32,
|
||||
) -> anyhow::Result<String> {
|
||||
let tx_plan = transfer_pools(
|
||||
coin,
|
||||
account,
|
||||
1,
|
||||
6,
|
||||
amount,
|
||||
true,
|
||||
"Shield Transparent Balance",
|
||||
0,
|
||||
confirmations,
|
||||
)
|
||||
.await?;
|
||||
let tx_id = sign_and_broadcast(coin, account, &tx_plan).await?;
|
||||
log::info!("TXID: {}", tx_id);
|
||||
Ok(tx_id)
|
||||
|
|
55
src/db.rs
55
src/db.rs
|
@ -651,8 +651,7 @@ impl DbAdapter {
|
|||
let note = r?;
|
||||
notes.push(note);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let mut statement = self.connection.prepare(
|
||||
"SELECT id_note, diversifier, value, rcm, rho, witness FROM received_notes r, orchard_witnesses w WHERE spent IS NULL AND account = ?2 AND rho IS NOT NULL
|
||||
AND (r.excluded IS NULL OR NOT r.excluded) AND w.height = ?1
|
||||
|
@ -707,36 +706,54 @@ impl DbAdapter {
|
|||
|
||||
pub fn purge_old_witnesses(&mut self, height: u32) -> anyhow::Result<()> {
|
||||
log::debug!("+purge_old_witnesses");
|
||||
let min_height: Option<u32> = self.connection.query_row(
|
||||
"SELECT MAX(height) FROM blocks WHERE height <= ?1",
|
||||
params![height],
|
||||
const BLOCKS_PER_HOUR: u32 = 60*60/75;
|
||||
const BLOCKS_PER_DAY: u32 = 24*BLOCKS_PER_HOUR;
|
||||
const BLOCKS_PER_MONTH: u32 = 30*BLOCKS_PER_DAY;
|
||||
for i in 1..=24 { // 1 checkpoint per hour
|
||||
self.prune_interval(height - i*BLOCKS_PER_HOUR, height - (i-1)*BLOCKS_PER_HOUR)?;
|
||||
}
|
||||
for i in 2..=30 { // 1 checkpoint per day
|
||||
self.prune_interval(height - i*BLOCKS_PER_DAY, height - (i-1)*BLOCKS_PER_DAY)?;
|
||||
}
|
||||
for i in 2..=12 { // 1 checkpoint per 30 days
|
||||
self.prune_interval(height - i*BLOCKS_PER_MONTH, height - (i-1)*BLOCKS_PER_MONTH)?;
|
||||
}
|
||||
|
||||
log::debug!("-purge_old_witnesses");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Only keep the oldest checkpoint in [low, high)
|
||||
fn prune_interval(&mut self, low: u32, high: u32) -> anyhow::Result<()> {
|
||||
log::info!("prune_interval {} {}", low, high);
|
||||
let keep_height: Option<u32> = self.connection.query_row(
|
||||
"SELECT MIN(height) FROM blocks WHERE height >= ?1 AND height < ?2",
|
||||
params![low, high],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
|
||||
// Leave at least one sapling witness
|
||||
if let Some(min_height) = min_height {
|
||||
log::debug!("Purging witnesses older than {}", min_height);
|
||||
if let Some(keep_height) = keep_height {
|
||||
log::info!("keep {}", keep_height);
|
||||
let transaction = self.connection.transaction()?;
|
||||
transaction.execute(
|
||||
"DELETE FROM sapling_witnesses WHERE height < ?1",
|
||||
params![min_height],
|
||||
"DELETE FROM sapling_witnesses WHERE height >= ?1 AND height < ?2 AND height != ?3",
|
||||
params![low, high, keep_height],
|
||||
)?;
|
||||
transaction.execute(
|
||||
"DELETE FROM orchard_witnesses WHERE height < ?1",
|
||||
params![min_height],
|
||||
"DELETE FROM orchard_witnesses WHERE height >= ?1 AND height < ?2 AND height != ?3",
|
||||
params![low, high, keep_height],
|
||||
)?;
|
||||
transaction.execute("DELETE FROM blocks WHERE height < ?1", params![min_height])?;
|
||||
transaction.execute("DELETE FROM blocks WHERE height >= ?1 AND height < ?2 AND height != ?3",
|
||||
params![low, high, keep_height])?;
|
||||
transaction.execute(
|
||||
"DELETE FROM sapling_tree WHERE height < ?1",
|
||||
params![min_height],
|
||||
"DELETE FROM sapling_tree WHERE height >= ?1 AND height < ?2 AND height != ?3",
|
||||
params![low, high, keep_height],
|
||||
)?;
|
||||
transaction.execute(
|
||||
"DELETE FROM orchard_tree WHERE height < ?1",
|
||||
params![min_height],
|
||||
"DELETE FROM orchard_tree WHERE height >= ?1 AND height < ?2 AND height != ?3",
|
||||
params![low, high, keep_height],
|
||||
)?;
|
||||
transaction.commit()?;
|
||||
}
|
||||
log::debug!("-purge_old_witnesses");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
18
src/key2.rs
18
src/key2.rs
|
@ -1,7 +1,11 @@
|
|||
use crate::coinconfig::CoinConfig;
|
||||
use anyhow::anyhow;
|
||||
use bip39::{Language, Mnemonic, Seed};
|
||||
use zcash_client_backend::encoding::{decode_extended_full_viewing_key, decode_extended_spending_key, decode_payment_address, decode_transparent_address, encode_extended_full_viewing_key, encode_extended_spending_key, encode_payment_address};
|
||||
use zcash_client_backend::encoding::{
|
||||
decode_extended_full_viewing_key, decode_extended_spending_key, decode_payment_address,
|
||||
decode_transparent_address, encode_extended_full_viewing_key, encode_extended_spending_key,
|
||||
encode_payment_address,
|
||||
};
|
||||
use zcash_client_backend::keys::UnifiedFullViewingKey;
|
||||
use zcash_primitives::consensus::{Network, Parameters};
|
||||
use zcash_primitives::zip32::{ChildIndex, ExtendedFullViewingKey, ExtendedSpendingKey};
|
||||
|
@ -79,17 +83,15 @@ pub fn is_valid_address(coin: u8, address: &str) -> bool {
|
|||
let network = c.chain.network();
|
||||
if decode_payment_address(network.hrp_sapling_payment_address(), address).is_ok() {
|
||||
true
|
||||
}
|
||||
else if let Ok(Some(_)) = decode_transparent_address(
|
||||
} else if let Ok(Some(_)) = decode_transparent_address(
|
||||
&network.b58_pubkey_address_prefix(),
|
||||
&network.b58_script_address_prefix(),
|
||||
address) {
|
||||
address,
|
||||
) {
|
||||
true
|
||||
}
|
||||
else if zcash_client_backend::address::RecipientAddress::decode(network, address).is_some() {
|
||||
} else if zcash_client_backend::address::RecipientAddress::decode(network, address).is_some() {
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ use thiserror::Error;
|
|||
use warp_api_ffi::api::payment_uri::PaymentURI;
|
||||
use warp_api_ffi::api::recipient::{Recipient, RecipientMemo, RecipientShort};
|
||||
use warp_api_ffi::{
|
||||
build_tx, get_secret_keys, AccountData, AccountRec, CoinConfig, KeyPack,
|
||||
RaptorQDrops, TransactionPlan, TxRec,
|
||||
build_tx, get_secret_keys, AccountData, AccountRec, CoinConfig, KeyPack, RaptorQDrops,
|
||||
TransactionPlan, TxRec,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
|
@ -187,11 +187,8 @@ pub fn get_address() -> Result<String, Error> {
|
|||
#[get("/unified_address?<t>&<s>&<o>")]
|
||||
pub fn get_unified_address(t: u8, s: u8, o: u8) -> Result<String, Error> {
|
||||
let c = CoinConfig::get_active();
|
||||
let address = warp_api_ffi::api::account::get_unified_address(
|
||||
c.coin,
|
||||
c.id_account,
|
||||
t & s << 1 & o << 2,
|
||||
)?;
|
||||
let address =
|
||||
warp_api_ffi::api::account::get_unified_address(c.coin, c.id_account, t & s << 1 & o << 2)?;
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,7 @@ pub fn group_orders(orders: &[Order], fee: u64) -> Result<(Vec<OrderInfo>, Order
|
|||
}
|
||||
}
|
||||
let amount = order.amount(fee)?;
|
||||
order_info.push(OrderInfo {
|
||||
group_type,
|
||||
amount,
|
||||
});
|
||||
order_info.push(OrderInfo { group_type, amount });
|
||||
}
|
||||
|
||||
let mut t0 = 0u64;
|
||||
|
@ -190,7 +187,7 @@ pub fn fill(
|
|||
order_infos: &[OrderInfo],
|
||||
amounts: &OrderGroupAmounts,
|
||||
allocation: &FundAllocation,
|
||||
fee: u64
|
||||
fee: u64,
|
||||
) -> Result<Vec<Fill>> {
|
||||
assert_eq!(orders.len(), order_infos.len());
|
||||
let mut fills = vec![];
|
||||
|
|
|
@ -6,10 +6,7 @@ use zcash_primitives::memo::MemoBytes;
|
|||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "MemoBytes")]
|
||||
pub struct MemoBytesProxy(
|
||||
#[serde(getter = "get_memo_bytes")]
|
||||
pub String,
|
||||
);
|
||||
pub struct MemoBytesProxy(#[serde(getter = "get_memo_bytes")] pub String);
|
||||
|
||||
fn get_memo_bytes(memo: &MemoBytes) -> String {
|
||||
hex::encode(memo.as_slice())
|
||||
|
|
|
@ -201,7 +201,14 @@ impl Destination {
|
|||
}
|
||||
|
||||
impl Order {
|
||||
pub fn new(network: &Network, id: u32, address: &str, amount: u64, take_fee: bool, memo: MemoBytes) -> Self {
|
||||
pub fn new(
|
||||
network: &Network,
|
||||
id: u32,
|
||||
address: &str,
|
||||
amount: u64,
|
||||
take_fee: bool,
|
||||
memo: MemoBytes,
|
||||
) -> Self {
|
||||
let destinations = decode(network, address).unwrap();
|
||||
Order {
|
||||
id,
|
||||
|
@ -214,10 +221,11 @@ impl Order {
|
|||
|
||||
pub fn amount(&self, fee: u64) -> Result<u64, TransactionBuilderError> {
|
||||
if self.take_fee {
|
||||
if self.raw_amount < fee { return Err(TransactionBuilderError::RecipientCannotPayFee) }
|
||||
if self.raw_amount < fee {
|
||||
return Err(TransactionBuilderError::RecipientCannotPayFee);
|
||||
}
|
||||
Ok(self.raw_amount - fee)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Ok(self.raw_amount)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,9 +207,8 @@ async fn sync_async_inner<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
let mut db = db_builder.build()?;
|
||||
let db = db_builder.build()?;
|
||||
db.store_block_timestamp(last_height, &last_hash, last_timestamp)?;
|
||||
db.purge_old_witnesses(last_height - 500)?;
|
||||
height = last_height;
|
||||
let cb = progress_callback.lock().await;
|
||||
cb(progress.clone());
|
||||
|
@ -220,6 +219,8 @@ async fn sync_async_inner<'a>(
|
|||
if get_tx {
|
||||
get_transaction_details(coin).await?;
|
||||
}
|
||||
let mut db = db_builder.build()?;
|
||||
db.purge_old_witnesses(height)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue