Fix ycash
This commit is contained in:
parent
d0550c8908
commit
9d7141ae40
|
@ -479,13 +479,13 @@ pub unsafe extern "C" fn transaction_report(coin: u8, plan: *mut c_char) -> CRes
|
|||
pub async unsafe extern "C" fn sign(
|
||||
coin: u8,
|
||||
account: u32,
|
||||
tx: *mut c_char,
|
||||
tx_plan: *mut c_char,
|
||||
_port: i64,
|
||||
) -> CResult<*mut c_char> {
|
||||
from_c_str!(tx);
|
||||
from_c_str!(tx_plan);
|
||||
let res = async {
|
||||
let tx: TransactionPlan = serde_json::from_str(&tx)?;
|
||||
let raw_tx = crate::api::payment_v2::sign_plan(coin, account, &tx)?;
|
||||
let tx_plan: TransactionPlan = serde_json::from_str(&tx_plan)?;
|
||||
let raw_tx = crate::api::payment_v2::sign_plan(coin, account, &tx_plan)?;
|
||||
let tx_str = base64::encode(&raw_tx);
|
||||
Ok::<_, anyhow::Error>(tx_str)
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@ pub async fn build_tx_plan(
|
|||
confirmations: u32,
|
||||
) -> note_selection::Result<TransactionPlan> {
|
||||
let c = CoinConfig::get(coin);
|
||||
let network = c.chain.network();
|
||||
let (fvk, checkpoint_height) = {
|
||||
let db = c.db()?;
|
||||
let AccountData { fvk, .. } = db.get_account_info(account)?;
|
||||
|
@ -48,7 +49,7 @@ pub async fn build_tx_plan(
|
|||
while amount > 0 {
|
||||
let a = min(amount, max_amount_per_note);
|
||||
let memo_bytes: MemoBytes = r.memo.clone().into();
|
||||
let order = Order::new(id_order, &r.address, a, memo_bytes);
|
||||
let order = Order::new(network, id_order, &r.address, a, memo_bytes);
|
||||
orders.push(order);
|
||||
amount -= a;
|
||||
id_order += 1;
|
||||
|
@ -58,6 +59,7 @@ pub async fn build_tx_plan(
|
|||
|
||||
let config = TransactionBuilderConfig::new(&change_address);
|
||||
let tx_plan = crate::note_selection::build_tx_plan::<FeeFlat>(
|
||||
network,
|
||||
&fvk,
|
||||
checkpoint_height,
|
||||
&context.orchard_anchor,
|
||||
|
|
|
@ -11,6 +11,7 @@ pub use utxo::fetch_utxos;
|
|||
|
||||
use crate::api::recipient::Recipient;
|
||||
use thiserror::Error;
|
||||
use zcash_primitives::consensus::Network;
|
||||
use ua::decode;
|
||||
use zcash_primitives::memo::Memo;
|
||||
|
||||
|
@ -37,12 +38,12 @@ mod utxo;
|
|||
pub const MAX_ATTEMPTS: usize = 10;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn recipients_to_orders(recipients: &[Recipient]) -> Result<Vec<Order>> {
|
||||
pub fn recipients_to_orders(network: &Network, recipients: &[Recipient]) -> Result<Vec<Order>> {
|
||||
let orders: Result<Vec<_>> = recipients
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, r)| {
|
||||
let destinations = decode(&r.address)?;
|
||||
let destinations = decode(network, &r.address)?;
|
||||
Ok::<_, TransactionBuilderError>(Order {
|
||||
id: i as u32,
|
||||
destinations,
|
||||
|
|
|
@ -26,8 +26,7 @@ use zcash_primitives::sapling::prover::TxProver;
|
|||
use zcash_primitives::sapling::{Diversifier, Node, PaymentAddress, Rseed};
|
||||
use zcash_primitives::transaction::builder::Builder;
|
||||
use zcash_primitives::transaction::components::{Amount, OutPoint, TxOut};
|
||||
use zcash_primitives::transaction::sighash::SignableInput;
|
||||
use zcash_primitives::transaction::sighash_v5::v5_signature_hash;
|
||||
use zcash_primitives::transaction::sighash::{SignableInput, signature_hash};
|
||||
use zcash_primitives::transaction::txid::TxIdDigester;
|
||||
use zcash_primitives::transaction::{Transaction, TransactionData, TxVersion};
|
||||
use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey};
|
||||
|
@ -41,7 +40,7 @@ pub struct SecretKeys {
|
|||
pub struct TxBuilderContext {
|
||||
pub height: u32,
|
||||
pub sapling_anchor: [u8; 32],
|
||||
pub orchard_anchor: [u8; 32],
|
||||
pub orchard_anchor: Option<[u8; 32]>,
|
||||
}
|
||||
|
||||
impl TxBuilderContext {
|
||||
|
@ -52,9 +51,13 @@ impl TxBuilderContext {
|
|||
let TreeCheckpoint { tree, .. } = db.get_tree_by_name(height, "sapling")?;
|
||||
let hasher = SaplingHasher {};
|
||||
let sapling_anchor = tree.root(32, &SAPLING_ROOTS, &hasher);
|
||||
let TreeCheckpoint { tree, .. } = db.get_tree_by_name(height, "orchard")?;
|
||||
let hasher = OrchardHasher::new();
|
||||
let orchard_anchor = tree.root(32, &ORCHARD_ROOTS, &hasher);
|
||||
|
||||
let orchard_anchor = if c.chain.has_unified() {
|
||||
let TreeCheckpoint { tree, .. } = db.get_tree_by_name(height, "orchard")?;
|
||||
let hasher = OrchardHasher::new();
|
||||
Some(tree.root(32, &ORCHARD_ROOTS, &hasher))
|
||||
}
|
||||
else { None };
|
||||
let context = TxBuilderContext {
|
||||
height,
|
||||
sapling_anchor,
|
||||
|
@ -208,10 +211,13 @@ pub fn build_tx(
|
|||
orchard_bundle = Some(orchard_builder.build(rng.clone()).unwrap());
|
||||
}
|
||||
|
||||
let consensus_branch_id = BranchId::for_height(network, BlockHeight::from_u32(plan.height));
|
||||
let version = TxVersion::suggested_for_branch(consensus_branch_id);
|
||||
|
||||
let unauthed_tx: TransactionData<zcash_primitives::transaction::Unauthorized> =
|
||||
TransactionData::from_parts(
|
||||
TxVersion::Zip225,
|
||||
BranchId::Nu5,
|
||||
version,
|
||||
consensus_branch_id,
|
||||
0,
|
||||
BlockHeight::from_u32(plan.height + EXPIRY_HEIGHT),
|
||||
transparent_bundle,
|
||||
|
@ -221,8 +227,8 @@ pub fn build_tx(
|
|||
);
|
||||
|
||||
let txid_parts = unauthed_tx.digest(TxIdDigester);
|
||||
let sig_hash = v5_signature_hash(&unauthed_tx, &SignableInput::Shielded, &txid_parts);
|
||||
let sig_hash: [u8; 32] = sig_hash.as_bytes().try_into().unwrap();
|
||||
let sig_hash = signature_hash(&unauthed_tx, &SignableInput::Shielded, &txid_parts);
|
||||
let sig_hash: [u8; 32] = sig_hash.as_ref().clone();
|
||||
|
||||
let transparent_bundle = unauthed_tx
|
||||
.transparent_bundle()
|
||||
|
@ -252,8 +258,8 @@ pub fn build_tx(
|
|||
|
||||
let tx_data: TransactionData<zcash_primitives::transaction::Authorized> =
|
||||
TransactionData::from_parts(
|
||||
TxVersion::Zip225,
|
||||
BranchId::Nu5,
|
||||
version,
|
||||
consensus_branch_id,
|
||||
0,
|
||||
BlockHeight::from_u32(plan.height + EXPIRY_HEIGHT),
|
||||
transparent_bundle,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use zcash_primitives::consensus::Network;
|
||||
use super::{types::*, Result};
|
||||
use crate::note_selection::fee::FeeCalculator;
|
||||
use crate::note_selection::ua::decode;
|
||||
|
@ -287,15 +288,17 @@ pub fn outputs_for_change(
|
|||
}
|
||||
|
||||
pub fn build_tx_plan<F: FeeCalculator>(
|
||||
network: &Network,
|
||||
fvk: &str,
|
||||
height: u32,
|
||||
orchard_anchor: &Hash,
|
||||
orchard_anchor: &Option<Hash>,
|
||||
utxos: &[UTXO],
|
||||
orders: &[Order],
|
||||
config: &TransactionBuilderConfig,
|
||||
) -> Result<TransactionPlan> {
|
||||
let mut fee = 0;
|
||||
|
||||
println!("build_tx_plan");
|
||||
for _ in 0..MAX_ATTEMPTS {
|
||||
let balances = sum_utxos(utxos)?;
|
||||
let (groups, amounts) = group_orders(&orders, fee)?;
|
||||
|
@ -311,7 +314,7 @@ pub fn build_tx_plan<F: FeeCalculator>(
|
|||
let mut fills = fill(&orders, &groups, &amounts, &allocation)?;
|
||||
|
||||
let (notes, change) = select_inputs(&utxos, &allocation)?;
|
||||
let change_destinations = decode(&config.change_address)?;
|
||||
let change_destinations = decode(network, &config.change_address)?;
|
||||
let change_outputs = outputs_for_change(&change_destinations, &change)?;
|
||||
fills.extend(change_outputs);
|
||||
|
||||
|
@ -320,7 +323,7 @@ pub fn build_tx_plan<F: FeeCalculator>(
|
|||
let tx_plan = TransactionPlan {
|
||||
fvk: fvk.to_string(),
|
||||
height,
|
||||
orchard_anchor: orchard_anchor.clone(),
|
||||
orchard_anchor: orchard_anchor.unwrap_or(Hash::default()),
|
||||
spends: notes,
|
||||
outputs: fills,
|
||||
net_chg,
|
||||
|
|
|
@ -3,12 +3,12 @@ use super::types::*;
|
|||
use super::TransactionBuilderError::NotEnoughFunds;
|
||||
use crate::note_selection::build_tx_plan;
|
||||
use crate::note_selection::fee::{FeeCalculator, FeeZIP327};
|
||||
use crate::note_selection::optimize::{outputs_for_change, select_inputs};
|
||||
use crate::note_selection::ua::decode;
|
||||
use crate::note_selection::optimize::select_inputs;
|
||||
use crate::Hash;
|
||||
use assert_matches::assert_matches;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
use zcash_primitives::consensus::Network;
|
||||
use zcash_primitives::memo::MemoBytes;
|
||||
|
||||
macro_rules! utxo {
|
||||
|
@ -689,14 +689,6 @@ fn test_select_utxo() {
|
|||
|
||||
const CHANGE_ADDRESS: &str = "u1pncsxa8jt7aq37r8uvhjrgt7sv8a665hdw44rqa28cd9t6qqmktzwktw772nlle6skkkxwmtzxaan3slntqev03g70tzpky3c58hfgvfjkcky255cwqgfuzdjcktfl7pjalt5sl33se75pmga09etn9dplr98eq2g8cgmvgvx6jx2a2xhy39x96c6rumvlyt35whml87r064qdzw30e";
|
||||
|
||||
#[test]
|
||||
fn test_change_fills() {
|
||||
let _ = env_logger::try_init();
|
||||
let destinations = decode(CHANGE_ADDRESS).unwrap();
|
||||
let outputs = outputs_for_change(&destinations, &&PoolAllocation([0, 10000, 10000])).unwrap();
|
||||
log::info!("{:?}", outputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fees() {
|
||||
let _ = env_logger::try_init();
|
||||
|
@ -733,6 +725,7 @@ fn test_tx_plan() {
|
|||
tso!(7, 70),
|
||||
];
|
||||
let tx_plan = build_tx_plan::<FeeZIP327>(
|
||||
&Network::MainNetwork,
|
||||
"",
|
||||
0,
|
||||
&Hash::default(),
|
||||
|
|
|
@ -200,8 +200,8 @@ impl Destination {
|
|||
}
|
||||
|
||||
impl Order {
|
||||
pub fn new(id: u32, address: &str, amount: u64, memo: MemoBytes) -> Self {
|
||||
let destinations = decode(address).unwrap();
|
||||
pub fn new(network: &Network, id: u32, address: &str, amount: u64, memo: MemoBytes) -> Self {
|
||||
let destinations = decode(network, address).unwrap();
|
||||
Order {
|
||||
id,
|
||||
destinations,
|
||||
|
|
|
@ -1,41 +1,53 @@
|
|||
use super::types::*;
|
||||
use zcash_address::unified::{Container, Receiver};
|
||||
use zcash_address::{AddressKind, ZcashAddress};
|
||||
use zcash_client_backend::encoding::{decode_payment_address, decode_transparent_address};
|
||||
use zcash_primitives::consensus::{Network, Parameters};
|
||||
use zcash_primitives::legacy::TransparentAddress;
|
||||
|
||||
pub fn decode(address: &str) -> anyhow::Result<[Option<Destination>; 3]> {
|
||||
pub fn decode(network: &Network, address: &str) -> anyhow::Result<[Option<Destination>; 3]> {
|
||||
let mut destinations: [Option<Destination>; 3] = [None; 3];
|
||||
let address = ZcashAddress::try_from_encoded(address)?;
|
||||
match address.kind {
|
||||
AddressKind::Sprout(_) => {}
|
||||
AddressKind::Sapling(data) => {
|
||||
let destination = Destination::Sapling(data);
|
||||
destinations[Pool::Sapling as usize] = Some(destination);
|
||||
}
|
||||
AddressKind::Unified(unified_address) => {
|
||||
for address in unified_address.items() {
|
||||
match address {
|
||||
Receiver::Orchard(data) => {
|
||||
let destination = Destination::Orchard(data);
|
||||
destinations[Pool::Orchard as usize] = Some(destination);
|
||||
if let Ok(data) = decode_payment_address(network.hrp_sapling_payment_address(), address) {
|
||||
let destination = Destination::Sapling(data.to_bytes());
|
||||
destinations[Pool::Sapling as usize] = Some(destination);
|
||||
}
|
||||
else if let Ok(Some(TransparentAddress::PublicKey(data))) = decode_transparent_address(&network.b58_pubkey_address_prefix(), &network.b58_script_address_prefix(), address) {
|
||||
let destination = Destination::Transparent(data);
|
||||
destinations[Pool::Transparent as usize] = Some(destination);
|
||||
}
|
||||
else if let Ok(address) = ZcashAddress::try_from_encoded(address) { // ZcashAddress only supports Zcash
|
||||
match address.kind {
|
||||
AddressKind::Sprout(_) => {}
|
||||
AddressKind::Sapling(data) => {
|
||||
let destination = Destination::Sapling(data);
|
||||
destinations[Pool::Sapling as usize] = Some(destination);
|
||||
}
|
||||
AddressKind::Unified(unified_address) => {
|
||||
for address in unified_address.items() {
|
||||
match address {
|
||||
Receiver::Orchard(data) => {
|
||||
let destination = Destination::Orchard(data);
|
||||
destinations[Pool::Orchard as usize] = Some(destination);
|
||||
}
|
||||
Receiver::Sapling(data) => {
|
||||
let destination = Destination::Sapling(data);
|
||||
destinations[Pool::Sapling as usize] = Some(destination);
|
||||
}
|
||||
Receiver::P2pkh(data) => {
|
||||
let destination = Destination::Transparent(data);
|
||||
destinations[Pool::Transparent as usize] = Some(destination);
|
||||
}
|
||||
Receiver::P2sh(_) => {}
|
||||
Receiver::Unknown { .. } => {}
|
||||
}
|
||||
Receiver::Sapling(data) => {
|
||||
let destination = Destination::Sapling(data);
|
||||
destinations[Pool::Sapling as usize] = Some(destination);
|
||||
}
|
||||
Receiver::P2pkh(data) => {
|
||||
let destination = Destination::Transparent(data);
|
||||
destinations[Pool::Transparent as usize] = Some(destination);
|
||||
}
|
||||
Receiver::P2sh(_) => {}
|
||||
Receiver::Unknown { .. } => {}
|
||||
}
|
||||
}
|
||||
AddressKind::P2pkh(data) => {
|
||||
let destination = Destination::Transparent(data);
|
||||
destinations[Pool::Transparent as usize] = Some(destination);
|
||||
}
|
||||
AddressKind::P2sh(_) => {}
|
||||
}
|
||||
AddressKind::P2pkh(data) => {
|
||||
let destination = Destination::Transparent(data);
|
||||
destinations[Pool::Transparent as usize] = Some(destination);
|
||||
}
|
||||
AddressKind::P2sh(_) => {}
|
||||
}
|
||||
|
||||
Ok(destinations)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use anyhow::anyhow;
|
||||
use crate::DbAdapter;
|
||||
use chrono::NaiveDateTime;
|
||||
use zcash_params::coin::get_coin_chain;
|
||||
|
@ -52,7 +53,10 @@ pub async fn fetch_historical_prices(
|
|||
let ts = p[0].as_i64().ok_or_else(json_error)? / 1000;
|
||||
let price = p[1].as_f64().ok_or_else(json_error)?;
|
||||
// rounded to daily
|
||||
let date = NaiveDateTime::from_timestamp(ts, 0).date().and_hms(0, 0, 0);
|
||||
let date = NaiveDateTime::from_timestamp_opt(ts, 0)
|
||||
.ok_or(anyhow!("Invalid Date"))?
|
||||
.date().and_hms_opt(0, 0, 0)
|
||||
.ok_or(anyhow!("Invalid Date"))?;
|
||||
let timestamp = date.timestamp();
|
||||
if timestamp != prev_timestamp {
|
||||
let quote = Quote { timestamp, price };
|
||||
|
|
Loading…
Reference in New Issue