Rebase librustzcash / FB

This commit is contained in:
Hanh 2023-03-11 16:43:10 +10:00
parent fa009f21b7
commit 9a3d08959e
17 changed files with 1550 additions and 130 deletions

View File

@ -120,32 +120,39 @@ sqlcipher = ["rusqlite/bundled-sqlcipher-vendored-openssl"]
[dependencies.zcash_params] [dependencies.zcash_params]
git = "https://github.com/hhanh00/zcash-params.git" git = "https://github.com/hhanh00/zcash-params.git"
rev = "bdb7aa490b32c204307c717f5dcea18358f7be3b" rev = "c43d03dda4a78172fe5283168510cd41ee8f1430"
#path = "../zcash-params"
[dependencies.zcash_client_backend] [dependencies.zcash_client_backend]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa"
#path = "../../librustzcash/zcash_client_backend"
[dependencies.zcash_primitives] [dependencies.zcash_primitives]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa"
#path = "../../librustzcash/zcash_primitives"
features = [ "transparent-inputs" ] features = [ "transparent-inputs" ]
[dependencies.zcash_proofs] [dependencies.zcash_proofs]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa"
#path = "../../librustzcash/zcash_proofs"
[dependencies.zcash_address] [dependencies.zcash_address]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa"
#path = "../../librustzcash/components/zcash_address"
[dependencies.zcash_encoding] [dependencies.zcash_encoding]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa"
#path = "../../librustzcash/components/zcash_encoding"
[dependencies.zcash_note_encryption] [dependencies.zcash_note_encryption]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa"
#path = "../../librustzcash/components/zcash_note_encryption"
[build-dependencies] [build-dependencies]
tonic-build = "0.7.2" tonic-build = "0.7.2"

View File

@ -162,6 +162,34 @@ typedef struct CResult_bool {
#define Progress_VT_DOWNLOADED 8 #define Progress_VT_DOWNLOADED 8
#define KeyPack_VT_T_ADDR 4
#define KeyPack_VT_T_KEY 6
#define KeyPack_VT_Z_ADDR 8
#define KeyPack_VT_Z_KEY 10
#define Recipient_VT_REPLY_TO 10
#define Recipient_VT_MAX_AMOUNT_PER_NOTE 16
#define UnsignedTxSummary_VT_RECIPIENTS 4
#define TxOutput_VT_POOL 10
#define TxReport_VT_OUTPUTS 4
#define TxReport_VT_TRANSPARENT 6
#define TxReport_VT_NET_SAPLING 12
#define TxReport_VT_NET_ORCHARD 14
#define TxReport_VT_FEE 16
#define TxReport_VT_PRIVACY_LEVEL 18
void dummy_export(void); void dummy_export(void);
void dart_post_cobject(DartPostCObjectFnType ptr); void dart_post_cobject(DartPostCObjectFnType ptr);
@ -247,10 +275,11 @@ struct CResult______u8 scan_transparent_accounts(uint32_t gap_limit);
struct CResult_____c_char prepare_multi_payment(uint8_t coin, struct CResult_____c_char prepare_multi_payment(uint8_t coin,
uint32_t account, uint32_t account,
char *recipients_json, uint8_t *recipients_bytes,
uint64_t recipients_len,
uint32_t anchor_offset); uint32_t anchor_offset);
struct CResult_____c_char transaction_report(uint8_t coin, char *plan); struct CResult______u8 transaction_report(uint8_t coin, char *plan);
struct CResult_____c_char sign(uint8_t coin, uint32_t account, char *tx_plan, int64_t _port); struct CResult_____c_char sign(uint8_t coin, uint32_t account, char *tx_plan, int64_t _port);
@ -310,12 +339,12 @@ struct CResult_____c_char get_best_server(uint8_t *servers, uint64_t len);
void import_from_zwl(uint8_t coin, char *name, char *data); void import_from_zwl(uint8_t coin, char *name, char *data);
struct CResult_____c_char derive_zip32(uint8_t coin, struct CResult______u8 derive_zip32(uint8_t coin,
uint32_t id_account, uint32_t id_account,
uint32_t account, uint32_t account,
uint32_t external, uint32_t external,
bool has_address, bool has_address,
uint32_t address); uint32_t address);
struct CResult_u8 clear_tx_details(uint8_t coin, uint32_t account); struct CResult_u8 clear_tx_details(uint8_t coin, uint32_t account);

View File

@ -4,7 +4,7 @@
use crate::coinconfig::CoinConfig; use crate::coinconfig::CoinConfig;
use crate::db::data_generated::fb::{ use crate::db::data_generated::fb::{
AddressBalance, AddressBalanceArgs, AddressBalanceVec, AddressBalanceVecArgs, BackupT, AddressBalance, AddressBalanceArgs, AddressBalanceVec, AddressBalanceVecArgs, BackupT, KeyPackT,
}; };
use crate::db::AccountData; use crate::db::AccountData;
use crate::key2::decode_key; use crate::key2::decode_key;
@ -12,7 +12,6 @@ use crate::orchard::OrchardKeyBytes;
use crate::taddr::{derive_taddr, derive_tkeys}; use crate::taddr::{derive_taddr, derive_tkeys};
use crate::unified::UnifiedAddressType; use crate::unified::UnifiedAddressType;
use crate::zip32::derive_zip32; use crate::zip32::derive_zip32;
use crate::KeyPack;
use anyhow::anyhow; use anyhow::anyhow;
use bip39::{Language, Mnemonic}; use bip39::{Language, Mnemonic};
use orchard::keys::{FullViewingKey, Scope}; use orchard::keys::{FullViewingKey, Scope};
@ -143,7 +142,7 @@ pub fn get_backup_package(coin: u8, id_account: u32) -> anyhow::Result<BackupT>
decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk) decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk)
.unwrap(); .unwrap();
let sapling_dfvk = sapling_efvk.to_diversifiable_full_viewing_key(); let sapling_dfvk = sapling_efvk.to_diversifiable_full_viewing_key();
let orchard_fvk = orchard::keys::FullViewingKey::from_bytes(&ofvk); let orchard_fvk = FullViewingKey::from_bytes(&ofvk);
let ufvk = UnifiedFullViewingKey::new(Some(sapling_dfvk), orchard_fvk).unwrap(); let ufvk = UnifiedFullViewingKey::new(Some(sapling_dfvk), orchard_fvk).unwrap();
ufvk.encode(network) ufvk.encode(network)
}); });
@ -390,7 +389,7 @@ pub fn derive_keys(
account: u32, account: u32,
external: u32, external: u32,
address: Option<u32>, address: Option<u32>,
) -> anyhow::Result<KeyPack> { ) -> anyhow::Result<KeyPackT> {
let c = CoinConfig::get(coin); let c = CoinConfig::get(coin);
let db = c.db()?; let db = c.db()?;
let AccountData { seed, .. } = db.get_account_info(id_account)?; let AccountData { seed, .. } = db.get_account_info(id_account)?;

View File

@ -1,5 +1,5 @@
use crate::coinconfig::{init_coin, CoinConfig, MEMPOOL, MEMPOOL_RUNNER}; use crate::coinconfig::{init_coin, CoinConfig, MEMPOOL, MEMPOOL_RUNNER};
use crate::db::data_generated::fb::{ProgressT, SendTemplate, Servers}; use crate::db::data_generated::fb::{ProgressT, Recipients, SendTemplate, Servers};
use crate::db::FullEncryptedBackup; use crate::db::FullEncryptedBackup;
use crate::note_selection::TransactionReport; use crate::note_selection::TransactionReport;
use crate::{ChainError, TransactionPlan, Tx}; use crate::{ChainError, TransactionPlan, Tx};
@ -517,13 +517,19 @@ pub async unsafe extern "C" fn scan_transparent_accounts(gap_limit: u32) -> CRes
pub async unsafe extern "C" fn prepare_multi_payment( pub async unsafe extern "C" fn prepare_multi_payment(
coin: u8, coin: u8,
account: u32, account: u32,
recipients_json: *mut c_char, recipients_bytes: *mut u8,
recipients_len: u64,
anchor_offset: u32, anchor_offset: u32,
) -> CResult<*mut c_char> { ) -> CResult<*mut c_char> {
from_c_str!(recipients_json);
let res = async { let res = async {
let last_height = crate::api::sync::get_latest_height().await?; let last_height = crate::api::sync::get_latest_height().await?;
let recipients = crate::api::recipient::parse_recipients(&recipients_json)?; let recipients_bytes: Vec<u8> = Vec::from_raw_parts(
recipients_bytes,
recipients_len as usize,
recipients_len as usize,
);
let recipients = flatbuffers::root::<Recipients>(&recipients_bytes)?;
let recipients = crate::api::recipient::parse_recipients(&recipients)?;
let tx = crate::api::payment_v2::build_tx_plan( let tx = crate::api::payment_v2::build_tx_plan(
coin, coin,
account, account,
@ -540,16 +546,18 @@ pub async unsafe extern "C" fn prepare_multi_payment(
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn transaction_report(coin: u8, plan: *mut c_char) -> CResult<*mut c_char> { pub unsafe extern "C" fn transaction_report(coin: u8, plan: *mut c_char) -> CResult<*const u8> {
from_c_str!(plan); from_c_str!(plan);
let c = CoinConfig::get(coin); let c = CoinConfig::get(coin);
let res = || { let res = || {
let plan: TransactionPlan = serde_json::from_str(&plan)?; let plan: TransactionPlan = serde_json::from_str(&plan)?;
let report = TransactionReport::from_plan(c.chain.network(), plan); let report = TransactionReport::from_plan(c.chain.network(), plan);
let report = serde_json::to_string(&report)?; let mut builder = FlatBufferBuilder::new();
Ok(report) let root = report.pack(&mut builder);
builder.finish(root, None);
Ok(builder.finished_data().to_vec())
}; };
to_cresult_str(res()) to_cresult_bytes(res())
} }
#[tokio::main] #[tokio::main]
@ -841,14 +849,17 @@ pub unsafe extern "C" fn derive_zip32(
external: u32, external: u32,
has_address: bool, has_address: bool,
address: u32, address: u32,
) -> CResult<*mut c_char> { ) -> CResult<*const u8> {
let res = || { let res = || {
let address = if has_address { Some(address) } else { None }; let address = if has_address { Some(address) } else { None };
let kp = crate::api::account::derive_keys(coin, id_account, account, external, address)?; let kp = crate::api::account::derive_keys(coin, id_account, account, external, address)?;
let result = serde_json::to_string(&kp)?; let mut builder = FlatBufferBuilder::new();
Ok(result) let data = kp.pack(&mut builder);
builder.finish(data, None);
let res = builder.finished_data().to_vec();
Ok(res)
}; };
to_cresult_str(res()) to_cresult_bytes(res())
} }
#[no_mangle] #[no_mangle]

View File

@ -1,20 +1,10 @@
use crate::db::data_generated::fb::{Recipient, Recipients};
use crate::db::ZMessage; use crate::db::ZMessage;
use crate::{AccountData, CoinConfig}; use crate::{AccountData, CoinConfig};
use serde::Deserialize; use serde::Deserialize;
use std::str::FromStr; use std::str::FromStr;
use zcash_primitives::memo::Memo; use zcash_primitives::memo::Memo;
#[derive(Deserialize)]
pub struct Recipient {
pub address: String,
pub amount: u64,
pub fee_included: bool,
pub reply_to: bool,
pub subject: String,
pub memo: String,
pub max_amount_per_note: u64,
}
#[derive(Clone, Deserialize)] #[derive(Clone, Deserialize)]
pub struct RecipientShort { pub struct RecipientShort {
pub address: String, pub address: String,
@ -32,17 +22,17 @@ pub struct RecipientMemo {
impl RecipientMemo { impl RecipientMemo {
pub fn from_recipient(from: &str, r: &Recipient) -> anyhow::Result<Self> { pub fn from_recipient(from: &str, r: &Recipient) -> anyhow::Result<Self> {
let memo = if !r.reply_to && r.subject.is_empty() { let memo = if !r.reply_to() && r.subject().as_ref().unwrap().is_empty() {
r.memo.clone() r.memo().unwrap().to_string()
} else { } else {
encode_memo(from, r.reply_to, &r.subject, &r.memo) encode_memo(from, r.reply_to(), r.subject().unwrap(), r.memo().unwrap())
}; };
Ok(RecipientMemo { Ok(RecipientMemo {
address: r.address.clone(), address: r.address().unwrap().to_string(),
amount: r.amount, amount: r.amount(),
fee_included: r.fee_included, fee_included: r.fee_included(),
memo: Memo::from_str(&memo)?, memo: Memo::from_str(&memo)?,
max_amount_per_note: r.max_amount_per_note, max_amount_per_note: r.max_amount_per_note(),
}) })
} }
} }
@ -107,13 +97,13 @@ pub fn decode_memo(
} }
/// Parse a json document that contains a list of recipients /// Parse a json document that contains a list of recipients
pub fn parse_recipients(recipients: &str) -> anyhow::Result<Vec<RecipientMemo>> { pub fn parse_recipients(recipients: &Recipients) -> anyhow::Result<Vec<RecipientMemo>> {
let c = CoinConfig::get_active(); let c = CoinConfig::get_active();
let AccountData { address, .. } = c.db()?.get_account_info(c.id_account)?; let AccountData { address, .. } = c.db()?.get_account_info(c.id_account)?;
let recipients: Vec<Recipient> = serde_json::from_str(recipients)?; let recipients = recipients.values().unwrap();
let recipient_memos: anyhow::Result<Vec<_>> = recipients let recipient_memos: anyhow::Result<Vec<_>> = recipients
.iter() .iter()
.map(|r| RecipientMemo::from_recipient(&address, r)) .map(|r| RecipientMemo::from_recipient(&address, &r))
.collect(); .collect();
recipient_memos recipient_memos
} }

View File

@ -25,6 +25,7 @@ use zcash_note_encryption::batch::try_compact_note_decryption;
use zcash_note_encryption::{Domain, EphemeralKeyBytes, ShieldedOutput, COMPACT_NOTE_SIZE}; use zcash_note_encryption::{Domain, EphemeralKeyBytes, ShieldedOutput, COMPACT_NOTE_SIZE};
use zcash_primitives::consensus::{BlockHeight, Network, NetworkUpgrade, Parameters}; use zcash_primitives::consensus::{BlockHeight, Network, NetworkUpgrade, Parameters};
use zcash_primitives::merkle_tree::{CommitmentTree, IncrementalWitness}; use zcash_primitives::merkle_tree::{CommitmentTree, IncrementalWitness};
use zcash_primitives::sapling::note::ExtractedNoteCommitment;
use zcash_primitives::sapling::note_encryption::{PreparedIncomingViewingKey, SaplingDomain}; use zcash_primitives::sapling::note_encryption::{PreparedIncomingViewingKey, SaplingDomain};
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;
@ -291,13 +292,12 @@ pub struct DecryptedNote {
#[allow(dead_code)] #[allow(dead_code)]
pub fn to_output_description(co: &CompactSaplingOutput) -> CompactOutputDescription { pub fn to_output_description(co: &CompactSaplingOutput) -> CompactOutputDescription {
let cmu: [u8; 32] = co.cmu.clone().try_into().unwrap(); let cmu: [u8; 32] = co.cmu.clone().try_into().unwrap();
let cmu = bls12_381::Scalar::from_repr(cmu).unwrap();
let epk: [u8; 32] = co.epk.clone().try_into().unwrap(); let epk: [u8; 32] = co.epk.clone().try_into().unwrap();
let enc_ciphertext: [u8; 52] = co.ciphertext.clone().try_into().unwrap(); let enc_ciphertext: [u8; 52] = co.ciphertext.clone().try_into().unwrap();
CompactOutputDescription { CompactOutputDescription {
ephemeral_key: EphemeralKeyBytes::from(epk), ephemeral_key: EphemeralKeyBytes::from(epk),
cmu, cmu: ExtractedNoteCommitment::from_bytes(&cmu).unwrap(),
enc_ciphertext, enc_ciphertext,
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -139,7 +139,7 @@ fn collect_decrypted_notes(
usize::from_le_bytes(plaintext[52..60].try_into().unwrap()); usize::from_le_bytes(plaintext[52..60].try_into().unwrap());
let cmu = note.cmu().to_bytes(); let cmu = note.cmu().to_bytes();
if &cmu == co.cmu.as_slice() { if &cmu == co.cmu.as_slice() {
log::info!("Note {} {}", account, u64::from(note.value)); log::info!("Note {} {}", account, u64::from(note.value().inner()));
decrypted_notes.push(DecryptedNote { decrypted_notes.push(DecryptedNote {
account, account,
ivk: fvk.clone(), ivk: fvk.clone(),

View File

@ -123,7 +123,7 @@ fn derive_viewing_key(
network: &Network, network: &Network,
extsk: &ExtendedSpendingKey, extsk: &ExtendedSpendingKey,
) -> anyhow::Result<(String, String)> { ) -> anyhow::Result<(String, String)> {
let fvk = ExtendedFullViewingKey::from(extsk); let fvk = extsk.to_extended_full_viewing_key();
let pa = derive_address(network, &fvk)?; let pa = derive_address(network, &fvk)?;
let fvk = let fvk =
encode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk); encode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk);

View File

@ -125,7 +125,6 @@ pub use crate::fountain::{FountainCodes, RaptorQDrops};
pub use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient; pub use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
pub use crate::lw_rpc::*; pub use crate::lw_rpc::*;
pub use crate::pay::{broadcast_tx, Tx, TxIn, TxOut}; pub use crate::pay::{broadcast_tx, Tx, TxIn, TxOut};
pub use zip32::KeyPack;
// pub use crate::wallet::{decrypt_backup, encrypt_backup, RecipientMemo, Wallet, WalletBalance}; // pub use crate::wallet::{decrypt_backup, encrypt_backup, RecipientMemo, Wallet, WalletBalance};
pub use note_selection::{ pub use note_selection::{

View File

@ -271,7 +271,7 @@ impl MemPoolImpl {
&self.pivk, &self.pivk,
co, co,
) { ) {
balance += note.value as i64; // value is incoming balance += note.value().inner() as i64; // value is incoming
} }
} }
} }

View File

@ -9,7 +9,7 @@ pub use optimize::build_tx_plan;
use std::str::FromStr; use std::str::FromStr;
pub use utxo::fetch_utxos; pub use utxo::fetch_utxos;
use crate::api::recipient::Recipient; use crate::db::data_generated::fb::Recipient;
use thiserror::Error; use thiserror::Error;
use ua::decode; use ua::decode;
use zcash_primitives::consensus::Network; use zcash_primitives::consensus::Network;
@ -47,13 +47,13 @@ pub fn recipients_to_orders(network: &Network, recipients: &[Recipient]) -> Resu
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, r)| { .map(|(i, r)| {
let destinations = decode(network, &r.address)?; let destinations = decode(network, r.address().unwrap())?;
Ok::<_, TransactionBuilderError>(Order { Ok::<_, TransactionBuilderError>(Order {
id: i as u32, id: i as u32,
destinations, destinations,
raw_amount: r.amount, raw_amount: r.amount(),
take_fee: r.fee_included, // Caller must make sure that at most one recipient pays for the fees take_fee: r.fee_included(), // Caller must make sure that at most one recipient pays for the fees
memo: Memo::from_str(&r.memo).unwrap().into(), memo: Memo::from_str(r.memo().unwrap()).unwrap().into(),
}) })
}) })
.collect(); .collect();

View File

@ -29,7 +29,7 @@ use zcash_primitives::transaction::components::{Amount, OutPoint, TxOut};
use zcash_primitives::transaction::sighash::{signature_hash, SignableInput}; use zcash_primitives::transaction::sighash::{signature_hash, SignableInput};
use zcash_primitives::transaction::txid::TxIdDigester; use zcash_primitives::transaction::txid::TxIdDigester;
use zcash_primitives::transaction::{Transaction, TransactionData, TxVersion}; use zcash_primitives::transaction::{Transaction, TransactionData, TxVersion};
use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; use zcash_primitives::zip32::ExtendedSpendingKey;
pub struct SecretKeys { pub struct SecretKeys {
pub transparent: Option<SecretKey>, pub transparent: Option<SecretKey>,
@ -85,7 +85,7 @@ pub fn build_tx(
let sapling_fvk = skeys let sapling_fvk = skeys
.sapling .sapling
.as_ref() .as_ref()
.map(|sk| ExtendedFullViewingKey::from(sk)); .map(|sk| sk.to_extended_full_viewing_key());
let sapling_ovk = sapling_fvk.as_ref().map(|efvk| efvk.fvk.ovk.clone()); let sapling_ovk = sapling_fvk.as_ref().map(|efvk| efvk.fvk.ovk.clone());
let okeys = skeys.orchard.map(|sk| { let okeys = skeys.orchard.map(|sk| {
@ -114,7 +114,9 @@ pub fn build_tx(
.ok_or(anyhow!("No transparent key")) .ok_or(anyhow!("No transparent key"))
.map(|ta| ta.script())?, .map(|ta| ta.script())?,
}; };
builder.add_transparent_input(skeys.transparent.unwrap(), utxo, coin)?; builder
.add_transparent_input(skeys.transparent.unwrap(), utxo, coin)
.map_err(|e| anyhow!(e.to_string()))?;
} }
Source::Sapling { Source::Sapling {
diversifier, diversifier,
@ -131,15 +133,17 @@ pub fn build_tx(
.to_payment_address(diversifier) .to_payment_address(diversifier)
.unwrap(); .unwrap();
let rseed = Rseed::BeforeZip212(Fr::from_bytes(rseed).unwrap()); let rseed = Rseed::BeforeZip212(Fr::from_bytes(rseed).unwrap());
let note = sapling_address.create_note(spend.amount, rseed).unwrap(); let note = sapling_address.create_note(spend.amount, rseed);
let witness = IncrementalWitness::<Node>::read(witness.as_slice())?; let witness = IncrementalWitness::<Node>::read(witness.as_slice())?;
let merkle_path = witness.path().unwrap(); let merkle_path = witness.path().unwrap();
builder.add_sapling_spend( builder
skeys.sapling.clone().ok_or(anyhow!("No Sapling Key"))?, .add_sapling_spend(
diversifier, skeys.sapling.clone().ok_or(anyhow!("No Sapling Key"))?,
note, diversifier,
merkle_path, note,
)?; merkle_path,
)
.map_err(|e| anyhow!(e.to_string()))?;
} }
Source::Orchard { Source::Orchard {
id_note, id_note,
@ -180,16 +184,15 @@ pub fn build_tx(
match &output.destination { match &output.destination {
Destination::Transparent(_addr) => { Destination::Transparent(_addr) => {
let transparent_address = output.destination.transparent(); let transparent_address = output.destination.transparent();
builder.add_transparent_output(&transparent_address, value)?; builder
.add_transparent_output(&transparent_address, value)
.map_err(|e| anyhow!(e.to_string()))?;
} }
Destination::Sapling(addr) => { Destination::Sapling(addr) => {
let sapling_address = PaymentAddress::from_bytes(addr).unwrap(); let sapling_address = PaymentAddress::from_bytes(addr).unwrap();
builder.add_sapling_output( builder
sapling_ovk, .add_sapling_output(sapling_ovk, sapling_address, value, output.memo.clone())
sapling_address, .map_err(|e| anyhow!(e.to_string()))?;
value,
output.memo.clone(),
)?;
} }
Destination::Orchard(addr) => { Destination::Orchard(addr) => {
has_orchard = true; has_orchard = true;

View File

@ -1,4 +1,5 @@
use crate::note_selection::types::{TransactionOutput, TransactionReport}; use crate::db::data_generated::fb::{TxOutputT, TxReportT};
use crate::note_selection::types::TransactionReport;
use crate::TransactionPlan; use crate::TransactionPlan;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use zcash_primitives::consensus::Network; use zcash_primitives::consensus::Network;
@ -19,7 +20,7 @@ impl From<MemoBytesProxy> for MemoBytes {
} }
impl TransactionReport { impl TransactionReport {
pub fn from_plan(network: &Network, p: TransactionPlan) -> Self { pub fn from_plan(network: &Network, p: TransactionPlan) -> TxReportT {
let mut spends = [0; 3]; let mut spends = [0; 3];
let mut outs = [0; 3]; let mut outs = [0; 3];
let mut changes = [0; 3]; let mut changes = [0; 3];
@ -38,9 +39,9 @@ impl TransactionReport {
.outputs .outputs
.iter() .iter()
.filter_map(|o| { .filter_map(|o| {
o.id_order.map(|id| TransactionOutput { o.id_order.map(|id| TxOutputT {
id, id,
address: o.destination.address(network), address: Some(o.destination.address(network)),
amount: o.amount, amount: o.amount,
pool: o.destination.pool() as u8, pool: o.destination.pool() as u8,
}) })
@ -60,8 +61,8 @@ impl TransactionReport {
3 3
}; };
let report = TransactionReport { let report = TxReportT {
outputs, outputs: Some(outputs),
transparent: spends[0] - changes[0], transparent: spends[0] - changes[0],
sapling: spends[1] - changes[1], sapling: spends[1] - changes[1],
orchard: spends[2] - changes[2], orchard: spends[2] - changes[2],

View File

@ -3,7 +3,7 @@ use crate::db::SpendableNote;
use crate::api::recipient::RecipientMemo; use crate::api::recipient::RecipientMemo;
use crate::chain::get_latest_height; use crate::chain::get_latest_height;
use crate::coinconfig::CoinConfig; use crate::coinconfig::CoinConfig;
use crate::{GetAddressUtxosReply, Hash, RawTransaction}; use crate::{GetAddressUtxosReply, RawTransaction};
use anyhow::anyhow; use anyhow::anyhow;
use jubjub::Fr; use jubjub::Fr;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
@ -14,8 +14,7 @@ use std::sync::mpsc;
use tonic::Request; use tonic::Request;
use zcash_client_backend::address::RecipientAddress; use zcash_client_backend::address::RecipientAddress;
use zcash_client_backend::encoding::{ use zcash_client_backend::encoding::{
decode_extended_full_viewing_key, decode_payment_address, encode_extended_full_viewing_key, decode_extended_full_viewing_key, encode_extended_full_viewing_key, encode_payment_address,
encode_payment_address,
}; };
use zcash_params::coin::{get_coin_chain, CoinChain, CoinType}; use zcash_params::coin::{get_coin_chain, CoinChain, CoinType};
use zcash_primitives::consensus::{BlockHeight, Parameters}; use zcash_primitives::consensus::{BlockHeight, Parameters};
@ -28,6 +27,7 @@ use zcash_primitives::sapling::{Diversifier, Node, PaymentAddress, Rseed};
use zcash_primitives::transaction::builder::{Builder, Progress}; use zcash_primitives::transaction::builder::{Builder, Progress};
use zcash_primitives::transaction::components::amount::{DEFAULT_FEE, MAX_MONEY}; use zcash_primitives::transaction::components::amount::{DEFAULT_FEE, MAX_MONEY};
use zcash_primitives::transaction::components::{Amount, OutPoint, TxOut as ZTxOut}; use zcash_primitives::transaction::components::{Amount, OutPoint, TxOut as ZTxOut};
use zcash_primitives::transaction::fees::fixed::FeeRule;
use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey};
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -219,7 +219,7 @@ impl TxBuilder {
for n in notes.iter() { for n in notes.iter() {
if amount.is_positive() { if amount.is_positive() {
let a = amount.min( let a = amount.min(
Amount::from_u64(n.note.value) Amount::from_u64(n.note.value().inner())
.map_err(|_| anyhow::anyhow!("Invalid amount"))?, .map_err(|_| anyhow::anyhow!("Invalid amount"))?,
); );
amount -= a; amount -= a;
@ -230,7 +230,7 @@ impl TxBuilder {
self.add_z_input( self.add_z_input(
&n.diversifier, &n.diversifier,
fvk, fvk,
Amount::from_u64(n.note.value).unwrap(), Amount::from_u64(n.note.value().inner()).unwrap(),
&rseed.to_bytes(), &rseed.to_bytes(),
&witness_bytes, &witness_bytes,
)?; )?;
@ -322,27 +322,22 @@ impl Tx {
let chain = get_coin_chain(self.coin_type); let chain = get_coin_chain(self.coin_type);
let last_height = BlockHeight::from_u32(self.height as u32); let last_height = BlockHeight::from_u32(self.height as u32);
let mut builder = Builder::new(*chain.network(), last_height); let mut builder = Builder::new(*chain.network(), last_height);
let efvk = ExtendedFullViewingKey::from(zsk); let efvk = zsk.to_extended_full_viewing_key();
let ovk: Hash = hex::decode(&self.ovk)?.try_into().unwrap();
builder.send_change_to(
OutgoingViewingKey(ovk),
decode_payment_address(chain.network().hrp_sapling_payment_address(), &self.change)
.unwrap(),
);
if let Some(tsk) = tsk { if let Some(tsk) = tsk {
for txin in self.t_inputs.iter() { for txin in self.t_inputs.iter() {
let mut txid = [0u8; 32]; let mut txid = [0u8; 32];
hex::decode_to_slice(&txin.op, &mut txid)?; hex::decode_to_slice(&txin.op, &mut txid)?;
builder.add_transparent_input( builder
tsk, .add_transparent_input(
OutPoint::new(txid, txin.n), tsk,
ZTxOut { OutPoint::new(txid, txin.n),
value: Amount::from_u64(txin.amount).unwrap(), ZTxOut {
script_pubkey: Script(hex::decode(&txin.script).unwrap()), value: Amount::from_u64(txin.amount).unwrap(),
}, script_pubkey: Script(hex::decode(&txin.script).unwrap()),
)?; },
)
.map_err(|e| anyhow!(e.to_string()))?;
} }
} else if !self.t_inputs.is_empty() { } else if !self.t_inputs.is_empty() {
anyhow::bail!("Missing secret key of transparent account"); anyhow::bail!("Missing secret key of transparent account");
@ -364,14 +359,14 @@ impl Tx {
let mut rseed_bytes = [0u8; 32]; let mut rseed_bytes = [0u8; 32];
hex::decode_to_slice(&txin.rseed, &mut rseed_bytes)?; hex::decode_to_slice(&txin.rseed, &mut rseed_bytes)?;
let rseed = Fr::from_bytes(&rseed_bytes).unwrap(); let rseed = Fr::from_bytes(&rseed_bytes).unwrap();
let note = pa let note = pa.create_note(txin.amount, Rseed::BeforeZip212(rseed));
.create_note(txin.amount, Rseed::BeforeZip212(rseed))
.unwrap();
let w = hex::decode(&txin.witness)?; let w = hex::decode(&txin.witness)?;
let witness = IncrementalWitness::<Node>::read(&*w)?; let witness = IncrementalWitness::<Node>::read(&*w)?;
let merkle_path = witness.path().unwrap(); let merkle_path = witness.path().unwrap();
builder.add_sapling_spend(zsk.clone(), diversifier, note, merkle_path)?; builder
.add_sapling_spend(zsk.clone(), diversifier, note, merkle_path)
.map_err(|e| anyhow!(e.to_string()))?;
} }
for txout in self.outputs.iter() { for txout in self.outputs.iter() {
@ -379,7 +374,9 @@ impl Tx {
let amount = Amount::from_u64(txout.amount).unwrap(); let amount = Amount::from_u64(txout.amount).unwrap();
match recipient { match recipient {
RecipientAddress::Transparent(ta) => { RecipientAddress::Transparent(ta) => {
builder.add_transparent_output(&ta, amount)?; builder
.add_transparent_output(&ta, amount)
.map_err(|e| anyhow!(e.to_string()))?;
} }
RecipientAddress::Shielded(pa) => { RecipientAddress::Shielded(pa) => {
let mut ovk = [0u8; 32]; let mut ovk = [0u8; 32];
@ -389,7 +386,9 @@ impl Tx {
let m = hex::decode(&txout.memo)?; let m = hex::decode(&txout.memo)?;
memo[..m.len()].copy_from_slice(&m); memo[..m.len()].copy_from_slice(&m);
let memo = MemoBytes::from_bytes(&memo)?; let memo = MemoBytes::from_bytes(&memo)?;
builder.add_sapling_output(Some(ovk), pa, amount, memo)?; builder
.add_sapling_output(Some(ovk), pa, amount, memo)
.map_err(|e| anyhow!(e.to_string()))?;
} }
RecipientAddress::Unified(_ua) => { RecipientAddress::Unified(_ua) => {
todo!() // TODO todo!() // TODO
@ -406,7 +405,7 @@ impl Tx {
progress_callback(progress); progress_callback(progress);
} }
}); });
let (tx, _) = builder.build(prover)?; let (tx, _) = builder.build(prover, &FeeRule::standard())?;
let mut raw_tx = vec![]; let mut raw_tx = vec![];
tx.write(&mut raw_tx)?; tx.write(&mut raw_tx)?;

View File

@ -67,7 +67,7 @@ impl<P: Parameters> DecryptedNote<SaplingDomain<P>, SaplingViewKey> for Decrypte
height: self.output_position.height, height: self.output_position.height,
output_index: self.output_position.output_index as u32, output_index: self.output_position.output_index as u32,
diversifier: self.pa.diversifier().0.to_vec(), diversifier: self.pa.diversifier().0.to_vec(),
value: self.note.value, value: self.note.value().inner(),
rcm: self.note.rcm().to_repr().to_vec(), rcm: self.note.rcm().to_repr().to_vec(),
nf: self.note.nf(&viewing_key.nk, position).to_vec(), nf: self.note.nf(&viewing_key.nk, position).to_vec(),
rho: None, rho: None,

View File

@ -1,10 +1,10 @@
use crate::db::data_generated::fb::KeyPackT;
use crate::key2::split_key; use crate::key2::split_key;
use anyhow::anyhow; use anyhow::anyhow;
use base58check::ToBase58Check; use base58check::ToBase58Check;
use bip39::{Language, Mnemonic, Seed}; use bip39::{Language, Mnemonic, Seed};
use ripemd::{Digest, Ripemd160}; use ripemd::{Digest, Ripemd160};
use secp256k1::{All, PublicKey, Secp256k1, SecretKey}; use secp256k1::{All, PublicKey, Secp256k1, SecretKey};
use serde::Serialize;
use sha2::Sha256; use sha2::Sha256;
use tiny_hderive::bip32::ExtendedPrivKey; use tiny_hderive::bip32::ExtendedPrivKey;
use zcash_client_backend::encoding::{ use zcash_client_backend::encoding::{
@ -14,21 +14,13 @@ use zcash_primitives::consensus::{Network, Parameters};
use zcash_primitives::legacy::TransparentAddress; use zcash_primitives::legacy::TransparentAddress;
use zcash_primitives::zip32::{ChildIndex, ExtendedSpendingKey}; use zcash_primitives::zip32::{ChildIndex, ExtendedSpendingKey};
#[derive(Serialize)]
pub struct KeyPack {
pub t_addr: String,
pub t_key: String,
pub z_addr: String,
pub z_key: String,
}
pub fn derive_zip32( pub fn derive_zip32(
network: &Network, network: &Network,
phrase: &str, phrase: &str,
account_index: u32, account_index: u32,
external: u32, external: u32,
address_index: Option<u32>, address_index: Option<u32>,
) -> anyhow::Result<KeyPack> { ) -> anyhow::Result<KeyPackT> {
let (phrase, password) = split_key(phrase); let (phrase, password) = split_key(phrase);
let mnemonic = Mnemonic::from_phrase(&phrase, Language::English)?; let mnemonic = Mnemonic::from_phrase(&phrase, Language::English)?;
let seed = Seed::new(&mnemonic, &password); let seed = Seed::new(&mnemonic, &password);
@ -71,10 +63,10 @@ pub fn derive_zip32(
sk.push(0x01); sk.push(0x01);
let t_key = sk.to_base58check(0x80); let t_key = sk.to_base58check(0x80);
Ok(KeyPack { Ok(KeyPackT {
z_key, z_key: Some(z_key),
z_addr, z_addr: Some(z_addr),
t_key, t_key: Some(t_key),
t_addr, t_addr: Some(t_addr),
}) })
} }