From 9a3d08959eff6056bb9226ae8d10e14d410212ee Mon Sep 17 00:00:00 2001 From: Hanh Date: Sat, 11 Mar 2023 16:43:10 +1000 Subject: [PATCH] Rebase librustzcash / FB --- Cargo.toml | 21 +- binding.h | 45 +- src/api/account.rs | 7 +- src/api/dart_ffi.rs | 35 +- src/api/recipient.rs | 32 +- src/chain.rs | 4 +- src/db/data_generated.rs | 1390 +++++++++++++++++++++++++++++++++ src/gpu.rs | 2 +- src/key2.rs | 2 +- src/lib.rs | 1 - src/mempool.rs | 2 +- src/note_selection.rs | 10 +- src/note_selection/builder.rs | 37 +- src/note_selection/ser.rs | 13 +- src/pay.rs | 55 +- src/sapling/note.rs | 2 +- src/zip32.rs | 22 +- 17 files changed, 1550 insertions(+), 130 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b20e73e..1cd9fe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,32 +120,39 @@ sqlcipher = ["rusqlite/bundled-sqlcipher-vendored-openssl"] [dependencies.zcash_params] git = "https://github.com/hhanh00/zcash-params.git" -rev = "bdb7aa490b32c204307c717f5dcea18358f7be3b" +rev = "c43d03dda4a78172fe5283168510cd41ee8f1430" +#path = "../zcash-params" [dependencies.zcash_client_backend] git = "https://github.com/hhanh00/librustzcash.git" -rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" +rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" +#path = "../../librustzcash/zcash_client_backend" [dependencies.zcash_primitives] git = "https://github.com/hhanh00/librustzcash.git" -rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" +rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" +#path = "../../librustzcash/zcash_primitives" features = [ "transparent-inputs" ] [dependencies.zcash_proofs] git = "https://github.com/hhanh00/librustzcash.git" -rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" +rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" +#path = "../../librustzcash/zcash_proofs" [dependencies.zcash_address] git = "https://github.com/hhanh00/librustzcash.git" -rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" +rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" +#path = "../../librustzcash/components/zcash_address" [dependencies.zcash_encoding] git = "https://github.com/hhanh00/librustzcash.git" -rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" +rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" +#path = "../../librustzcash/components/zcash_encoding" [dependencies.zcash_note_encryption] git = "https://github.com/hhanh00/librustzcash.git" -rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" +rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" +#path = "../../librustzcash/components/zcash_note_encryption" [build-dependencies] tonic-build = "0.7.2" diff --git a/binding.h b/binding.h index 3795e25..dec446f 100644 --- a/binding.h +++ b/binding.h @@ -162,6 +162,34 @@ typedef struct CResult_bool { #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 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, uint32_t account, - char *recipients_json, + uint8_t *recipients_bytes, + uint64_t recipients_len, 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); @@ -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); -struct CResult_____c_char derive_zip32(uint8_t coin, - uint32_t id_account, - uint32_t account, - uint32_t external, - bool has_address, - uint32_t address); +struct CResult______u8 derive_zip32(uint8_t coin, + uint32_t id_account, + uint32_t account, + uint32_t external, + bool has_address, + uint32_t address); struct CResult_u8 clear_tx_details(uint8_t coin, uint32_t account); diff --git a/src/api/account.rs b/src/api/account.rs index 6946c3e..cae419f 100644 --- a/src/api/account.rs +++ b/src/api/account.rs @@ -4,7 +4,7 @@ use crate::coinconfig::CoinConfig; use crate::db::data_generated::fb::{ - AddressBalance, AddressBalanceArgs, AddressBalanceVec, AddressBalanceVecArgs, BackupT, + AddressBalance, AddressBalanceArgs, AddressBalanceVec, AddressBalanceVecArgs, BackupT, KeyPackT, }; use crate::db::AccountData; use crate::key2::decode_key; @@ -12,7 +12,6 @@ use crate::orchard::OrchardKeyBytes; use crate::taddr::{derive_taddr, derive_tkeys}; use crate::unified::UnifiedAddressType; use crate::zip32::derive_zip32; -use crate::KeyPack; use anyhow::anyhow; use bip39::{Language, Mnemonic}; use orchard::keys::{FullViewingKey, Scope}; @@ -143,7 +142,7 @@ pub fn get_backup_package(coin: u8, id_account: u32) -> anyhow::Result decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk) .unwrap(); 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(); ufvk.encode(network) }); @@ -390,7 +389,7 @@ pub fn derive_keys( account: u32, external: u32, address: Option, -) -> anyhow::Result { +) -> anyhow::Result { let c = CoinConfig::get(coin); let db = c.db()?; let AccountData { seed, .. } = db.get_account_info(id_account)?; diff --git a/src/api/dart_ffi.rs b/src/api/dart_ffi.rs index a98277d..d1437fc 100644 --- a/src/api/dart_ffi.rs +++ b/src/api/dart_ffi.rs @@ -1,5 +1,5 @@ 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::note_selection::TransactionReport; 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( coin: u8, account: u32, - recipients_json: *mut c_char, + recipients_bytes: *mut u8, + recipients_len: u64, anchor_offset: u32, ) -> CResult<*mut c_char> { - from_c_str!(recipients_json); let res = async { let last_height = crate::api::sync::get_latest_height().await?; - let recipients = crate::api::recipient::parse_recipients(&recipients_json)?; + let recipients_bytes: Vec = Vec::from_raw_parts( + recipients_bytes, + recipients_len as usize, + recipients_len as usize, + ); + let recipients = flatbuffers::root::(&recipients_bytes)?; + let recipients = crate::api::recipient::parse_recipients(&recipients)?; let tx = crate::api::payment_v2::build_tx_plan( coin, account, @@ -540,16 +546,18 @@ pub async unsafe extern "C" fn prepare_multi_payment( } #[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); let c = CoinConfig::get(coin); let res = || { let plan: TransactionPlan = serde_json::from_str(&plan)?; let report = TransactionReport::from_plan(c.chain.network(), plan); - let report = serde_json::to_string(&report)?; - Ok(report) + let mut builder = FlatBufferBuilder::new(); + 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] @@ -841,14 +849,17 @@ pub unsafe extern "C" fn derive_zip32( external: u32, has_address: bool, address: u32, -) -> CResult<*mut c_char> { +) -> CResult<*const u8> { let res = || { let address = if has_address { Some(address) } else { None }; let kp = crate::api::account::derive_keys(coin, id_account, account, external, address)?; - let result = serde_json::to_string(&kp)?; - Ok(result) + let mut builder = FlatBufferBuilder::new(); + 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] diff --git a/src/api/recipient.rs b/src/api/recipient.rs index 1925ad6..8cb899d 100644 --- a/src/api/recipient.rs +++ b/src/api/recipient.rs @@ -1,20 +1,10 @@ +use crate::db::data_generated::fb::{Recipient, Recipients}; use crate::db::ZMessage; use crate::{AccountData, CoinConfig}; use serde::Deserialize; use std::str::FromStr; 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)] pub struct RecipientShort { pub address: String, @@ -32,17 +22,17 @@ pub struct RecipientMemo { impl RecipientMemo { pub fn from_recipient(from: &str, r: &Recipient) -> anyhow::Result { - let memo = if !r.reply_to && r.subject.is_empty() { - r.memo.clone() + let memo = if !r.reply_to() && r.subject().as_ref().unwrap().is_empty() { + r.memo().unwrap().to_string() } 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 { - address: r.address.clone(), - amount: r.amount, - fee_included: r.fee_included, + address: r.address().unwrap().to_string(), + amount: r.amount(), + fee_included: r.fee_included(), 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 -pub fn parse_recipients(recipients: &str) -> anyhow::Result> { +pub fn parse_recipients(recipients: &Recipients) -> anyhow::Result> { let c = CoinConfig::get_active(); let AccountData { address, .. } = c.db()?.get_account_info(c.id_account)?; - let recipients: Vec = serde_json::from_str(recipients)?; + let recipients = recipients.values().unwrap(); let recipient_memos: anyhow::Result> = recipients .iter() - .map(|r| RecipientMemo::from_recipient(&address, r)) + .map(|r| RecipientMemo::from_recipient(&address, &r)) .collect(); recipient_memos } diff --git a/src/chain.rs b/src/chain.rs index a594f3f..f0270a6 100644 --- a/src/chain.rs +++ b/src/chain.rs @@ -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_primitives::consensus::{BlockHeight, Network, NetworkUpgrade, Parameters}; 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::{Node, Note, PaymentAddress}; use zcash_primitives::transaction::components::sapling::CompactOutputDescription; @@ -291,13 +292,12 @@ pub struct DecryptedNote { #[allow(dead_code)] pub fn to_output_description(co: &CompactSaplingOutput) -> CompactOutputDescription { 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 enc_ciphertext: [u8; 52] = co.ciphertext.clone().try_into().unwrap(); CompactOutputDescription { ephemeral_key: EphemeralKeyBytes::from(epk), - cmu, + cmu: ExtractedNoteCommitment::from_bytes(&cmu).unwrap(), enc_ciphertext, } } diff --git a/src/db/data_generated.rs b/src/db/data_generated.rs index 58b763c..c312713 100644 --- a/src/db/data_generated.rs +++ b/src/db/data_generated.rs @@ -5288,5 +5288,1395 @@ impl ProgressT { }) } } +pub enum KeyPackOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct KeyPack<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for KeyPack<'a> { + type Inner = KeyPack<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> KeyPack<'a> { + pub const VT_T_ADDR: flatbuffers::VOffsetT = 4; + pub const VT_T_KEY: flatbuffers::VOffsetT = 6; + pub const VT_Z_ADDR: flatbuffers::VOffsetT = 8; + pub const VT_Z_KEY: flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + KeyPack { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args KeyPackArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = KeyPackBuilder::new(_fbb); + if let Some(x) = args.z_key { builder.add_z_key(x); } + if let Some(x) = args.z_addr { builder.add_z_addr(x); } + if let Some(x) = args.t_key { builder.add_t_key(x); } + if let Some(x) = args.t_addr { builder.add_t_addr(x); } + builder.finish() + } + + pub fn unpack(&self) -> KeyPackT { + let t_addr = self.t_addr().map(|x| { + x.to_string() + }); + let t_key = self.t_key().map(|x| { + x.to_string() + }); + let z_addr = self.z_addr().map(|x| { + x.to_string() + }); + let z_key = self.z_key().map(|x| { + x.to_string() + }); + KeyPackT { + t_addr, + t_key, + z_addr, + z_key, + } + } + + #[inline] + pub fn t_addr(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(KeyPack::VT_T_ADDR, None)} + } + #[inline] + pub fn t_key(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(KeyPack::VT_T_KEY, None)} + } + #[inline] + pub fn z_addr(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(KeyPack::VT_Z_ADDR, None)} + } + #[inline] + pub fn z_key(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(KeyPack::VT_Z_KEY, None)} + } +} + +impl flatbuffers::Verifiable for KeyPack<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>("t_addr", Self::VT_T_ADDR, false)? + .visit_field::>("t_key", Self::VT_T_KEY, false)? + .visit_field::>("z_addr", Self::VT_Z_ADDR, false)? + .visit_field::>("z_key", Self::VT_Z_KEY, false)? + .finish(); + Ok(()) + } +} +pub struct KeyPackArgs<'a> { + pub t_addr: Option>, + pub t_key: Option>, + pub z_addr: Option>, + pub z_key: Option>, +} +impl<'a> Default for KeyPackArgs<'a> { + #[inline] + fn default() -> Self { + KeyPackArgs { + t_addr: None, + t_key: None, + z_addr: None, + z_key: None, + } + } +} + +pub struct KeyPackBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> KeyPackBuilder<'a, 'b> { + #[inline] + pub fn add_t_addr(&mut self, t_addr: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(KeyPack::VT_T_ADDR, t_addr); + } + #[inline] + pub fn add_t_key(&mut self, t_key: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(KeyPack::VT_T_KEY, t_key); + } + #[inline] + pub fn add_z_addr(&mut self, z_addr: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(KeyPack::VT_Z_ADDR, z_addr); + } + #[inline] + pub fn add_z_key(&mut self, z_key: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(KeyPack::VT_Z_KEY, z_key); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> KeyPackBuilder<'a, 'b> { + let start = _fbb.start_table(); + KeyPackBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for KeyPack<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("KeyPack"); + ds.field("t_addr", &self.t_addr()); + ds.field("t_key", &self.t_key()); + ds.field("z_addr", &self.z_addr()); + ds.field("z_key", &self.z_key()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct KeyPackT { + pub t_addr: Option, + pub t_key: Option, + pub z_addr: Option, + pub z_key: Option, +} +impl Default for KeyPackT { + fn default() -> Self { + Self { + t_addr: None, + t_key: None, + z_addr: None, + z_key: None, + } + } +} +impl KeyPackT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let t_addr = self.t_addr.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let t_key = self.t_key.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let z_addr = self.z_addr.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let z_key = self.z_key.as_ref().map(|x|{ + _fbb.create_string(x) + }); + KeyPack::create(_fbb, &KeyPackArgs{ + t_addr, + t_key, + z_addr, + z_key, + }) + } +} +pub enum RecipientOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Recipient<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Recipient<'a> { + type Inner = Recipient<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> Recipient<'a> { + pub const VT_ADDRESS: flatbuffers::VOffsetT = 4; + pub const VT_AMOUNT: flatbuffers::VOffsetT = 6; + pub const VT_FEE_INCLUDED: flatbuffers::VOffsetT = 8; + pub const VT_REPLY_TO: flatbuffers::VOffsetT = 10; + pub const VT_SUBJECT: flatbuffers::VOffsetT = 12; + pub const VT_MEMO: flatbuffers::VOffsetT = 14; + pub const VT_MAX_AMOUNT_PER_NOTE: flatbuffers::VOffsetT = 16; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Recipient { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args RecipientArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = RecipientBuilder::new(_fbb); + builder.add_max_amount_per_note(args.max_amount_per_note); + builder.add_amount(args.amount); + if let Some(x) = args.memo { builder.add_memo(x); } + if let Some(x) = args.subject { builder.add_subject(x); } + if let Some(x) = args.address { builder.add_address(x); } + builder.add_reply_to(args.reply_to); + builder.add_fee_included(args.fee_included); + builder.finish() + } + + pub fn unpack(&self) -> RecipientT { + let address = self.address().map(|x| { + x.to_string() + }); + let amount = self.amount(); + let fee_included = self.fee_included(); + let reply_to = self.reply_to(); + let subject = self.subject().map(|x| { + x.to_string() + }); + let memo = self.memo().map(|x| { + x.to_string() + }); + let max_amount_per_note = self.max_amount_per_note(); + RecipientT { + address, + amount, + fee_included, + reply_to, + subject, + memo, + max_amount_per_note, + } + } + + #[inline] + pub fn address(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Recipient::VT_ADDRESS, None)} + } + #[inline] + pub fn amount(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Recipient::VT_AMOUNT, Some(0)).unwrap()} + } + #[inline] + pub fn fee_included(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Recipient::VT_FEE_INCLUDED, Some(false)).unwrap()} + } + #[inline] + pub fn reply_to(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Recipient::VT_REPLY_TO, Some(false)).unwrap()} + } + #[inline] + pub fn subject(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Recipient::VT_SUBJECT, None)} + } + #[inline] + pub fn memo(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Recipient::VT_MEMO, None)} + } + #[inline] + pub fn max_amount_per_note(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Recipient::VT_MAX_AMOUNT_PER_NOTE, Some(0)).unwrap()} + } +} + +impl flatbuffers::Verifiable for Recipient<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>("address", Self::VT_ADDRESS, false)? + .visit_field::("amount", Self::VT_AMOUNT, false)? + .visit_field::("fee_included", Self::VT_FEE_INCLUDED, false)? + .visit_field::("reply_to", Self::VT_REPLY_TO, false)? + .visit_field::>("subject", Self::VT_SUBJECT, false)? + .visit_field::>("memo", Self::VT_MEMO, false)? + .visit_field::("max_amount_per_note", Self::VT_MAX_AMOUNT_PER_NOTE, false)? + .finish(); + Ok(()) + } +} +pub struct RecipientArgs<'a> { + pub address: Option>, + pub amount: u64, + pub fee_included: bool, + pub reply_to: bool, + pub subject: Option>, + pub memo: Option>, + pub max_amount_per_note: u64, +} +impl<'a> Default for RecipientArgs<'a> { + #[inline] + fn default() -> Self { + RecipientArgs { + address: None, + amount: 0, + fee_included: false, + reply_to: false, + subject: None, + memo: None, + max_amount_per_note: 0, + } + } +} + +pub struct RecipientBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> RecipientBuilder<'a, 'b> { + #[inline] + pub fn add_address(&mut self, address: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(Recipient::VT_ADDRESS, address); + } + #[inline] + pub fn add_amount(&mut self, amount: u64) { + self.fbb_.push_slot::(Recipient::VT_AMOUNT, amount, 0); + } + #[inline] + pub fn add_fee_included(&mut self, fee_included: bool) { + self.fbb_.push_slot::(Recipient::VT_FEE_INCLUDED, fee_included, false); + } + #[inline] + pub fn add_reply_to(&mut self, reply_to: bool) { + self.fbb_.push_slot::(Recipient::VT_REPLY_TO, reply_to, false); + } + #[inline] + pub fn add_subject(&mut self, subject: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(Recipient::VT_SUBJECT, subject); + } + #[inline] + pub fn add_memo(&mut self, memo: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(Recipient::VT_MEMO, memo); + } + #[inline] + pub fn add_max_amount_per_note(&mut self, max_amount_per_note: u64) { + self.fbb_.push_slot::(Recipient::VT_MAX_AMOUNT_PER_NOTE, max_amount_per_note, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> RecipientBuilder<'a, 'b> { + let start = _fbb.start_table(); + RecipientBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Recipient<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Recipient"); + ds.field("address", &self.address()); + ds.field("amount", &self.amount()); + ds.field("fee_included", &self.fee_included()); + ds.field("reply_to", &self.reply_to()); + ds.field("subject", &self.subject()); + ds.field("memo", &self.memo()); + ds.field("max_amount_per_note", &self.max_amount_per_note()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct RecipientT { + pub address: Option, + pub amount: u64, + pub fee_included: bool, + pub reply_to: bool, + pub subject: Option, + pub memo: Option, + pub max_amount_per_note: u64, +} +impl Default for RecipientT { + fn default() -> Self { + Self { + address: None, + amount: 0, + fee_included: false, + reply_to: false, + subject: None, + memo: None, + max_amount_per_note: 0, + } + } +} +impl RecipientT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let address = self.address.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let amount = self.amount; + let fee_included = self.fee_included; + let reply_to = self.reply_to; + let subject = self.subject.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let memo = self.memo.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let max_amount_per_note = self.max_amount_per_note; + Recipient::create(_fbb, &RecipientArgs{ + address, + amount, + fee_included, + reply_to, + subject, + memo, + max_amount_per_note, + }) + } +} +pub enum RecipientsOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Recipients<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Recipients<'a> { + type Inner = Recipients<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> Recipients<'a> { + pub const VT_VALUES: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Recipients { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args RecipientsArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = RecipientsBuilder::new(_fbb); + if let Some(x) = args.values { builder.add_values(x); } + builder.finish() + } + + pub fn unpack(&self) -> RecipientsT { + let values = self.values().map(|x| { + x.iter().map(|t| t.unpack()).collect() + }); + RecipientsT { + values, + } + } + + #[inline] + pub fn values(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Recipients::VT_VALUES, None)} + } +} + +impl flatbuffers::Verifiable for Recipients<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>>>("values", Self::VT_VALUES, false)? + .finish(); + Ok(()) + } +} +pub struct RecipientsArgs<'a> { + pub values: Option>>>>, +} +impl<'a> Default for RecipientsArgs<'a> { + #[inline] + fn default() -> Self { + RecipientsArgs { + values: None, + } + } +} + +pub struct RecipientsBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> RecipientsBuilder<'a, 'b> { + #[inline] + pub fn add_values(&mut self, values: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(Recipients::VT_VALUES, values); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> RecipientsBuilder<'a, 'b> { + let start = _fbb.start_table(); + RecipientsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Recipients<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Recipients"); + ds.field("values", &self.values()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct RecipientsT { + pub values: Option>, +} +impl Default for RecipientsT { + fn default() -> Self { + Self { + values: None, + } + } +} +impl RecipientsT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let values = self.values.as_ref().map(|x|{ + let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w) + }); + Recipients::create(_fbb, &RecipientsArgs{ + values, + }) + } +} +pub enum RecipientSummaryOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct RecipientSummary<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for RecipientSummary<'a> { + type Inner = RecipientSummary<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> RecipientSummary<'a> { + pub const VT_AMOUNT: flatbuffers::VOffsetT = 4; + pub const VT_ADDRESS: flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + RecipientSummary { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args RecipientSummaryArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = RecipientSummaryBuilder::new(_fbb); + builder.add_amount(args.amount); + if let Some(x) = args.address { builder.add_address(x); } + builder.finish() + } + + pub fn unpack(&self) -> RecipientSummaryT { + let amount = self.amount(); + let address = self.address().map(|x| { + x.to_string() + }); + RecipientSummaryT { + amount, + address, + } + } + + #[inline] + pub fn amount(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RecipientSummary::VT_AMOUNT, Some(0)).unwrap()} + } + #[inline] + pub fn address(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(RecipientSummary::VT_ADDRESS, None)} + } +} + +impl flatbuffers::Verifiable for RecipientSummary<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("amount", Self::VT_AMOUNT, false)? + .visit_field::>("address", Self::VT_ADDRESS, false)? + .finish(); + Ok(()) + } +} +pub struct RecipientSummaryArgs<'a> { + pub amount: u64, + pub address: Option>, +} +impl<'a> Default for RecipientSummaryArgs<'a> { + #[inline] + fn default() -> Self { + RecipientSummaryArgs { + amount: 0, + address: None, + } + } +} + +pub struct RecipientSummaryBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> RecipientSummaryBuilder<'a, 'b> { + #[inline] + pub fn add_amount(&mut self, amount: u64) { + self.fbb_.push_slot::(RecipientSummary::VT_AMOUNT, amount, 0); + } + #[inline] + pub fn add_address(&mut self, address: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(RecipientSummary::VT_ADDRESS, address); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> RecipientSummaryBuilder<'a, 'b> { + let start = _fbb.start_table(); + RecipientSummaryBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for RecipientSummary<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("RecipientSummary"); + ds.field("amount", &self.amount()); + ds.field("address", &self.address()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct RecipientSummaryT { + pub amount: u64, + pub address: Option, +} +impl Default for RecipientSummaryT { + fn default() -> Self { + Self { + amount: 0, + address: None, + } + } +} +impl RecipientSummaryT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let amount = self.amount; + let address = self.address.as_ref().map(|x|{ + _fbb.create_string(x) + }); + RecipientSummary::create(_fbb, &RecipientSummaryArgs{ + amount, + address, + }) + } +} +pub enum UnsignedTxSummaryOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct UnsignedTxSummary<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for UnsignedTxSummary<'a> { + type Inner = UnsignedTxSummary<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> UnsignedTxSummary<'a> { + pub const VT_RECIPIENTS: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + UnsignedTxSummary { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args UnsignedTxSummaryArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = UnsignedTxSummaryBuilder::new(_fbb); + if let Some(x) = args.recipients { builder.add_recipients(x); } + builder.finish() + } + + pub fn unpack(&self) -> UnsignedTxSummaryT { + let recipients = self.recipients().map(|x| { + x.iter().map(|t| t.unpack()).collect() + }); + UnsignedTxSummaryT { + recipients, + } + } + + #[inline] + pub fn recipients(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(UnsignedTxSummary::VT_RECIPIENTS, None)} + } +} + +impl flatbuffers::Verifiable for UnsignedTxSummary<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>>>("recipients", Self::VT_RECIPIENTS, false)? + .finish(); + Ok(()) + } +} +pub struct UnsignedTxSummaryArgs<'a> { + pub recipients: Option>>>>, +} +impl<'a> Default for UnsignedTxSummaryArgs<'a> { + #[inline] + fn default() -> Self { + UnsignedTxSummaryArgs { + recipients: None, + } + } +} + +pub struct UnsignedTxSummaryBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> UnsignedTxSummaryBuilder<'a, 'b> { + #[inline] + pub fn add_recipients(&mut self, recipients: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(UnsignedTxSummary::VT_RECIPIENTS, recipients); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> UnsignedTxSummaryBuilder<'a, 'b> { + let start = _fbb.start_table(); + UnsignedTxSummaryBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for UnsignedTxSummary<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("UnsignedTxSummary"); + ds.field("recipients", &self.recipients()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct UnsignedTxSummaryT { + pub recipients: Option>, +} +impl Default for UnsignedTxSummaryT { + fn default() -> Self { + Self { + recipients: None, + } + } +} +impl UnsignedTxSummaryT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let recipients = self.recipients.as_ref().map(|x|{ + let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w) + }); + UnsignedTxSummary::create(_fbb, &UnsignedTxSummaryArgs{ + recipients, + }) + } +} +pub enum TxOutputOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct TxOutput<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for TxOutput<'a> { + type Inner = TxOutput<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> TxOutput<'a> { + pub const VT_ID: flatbuffers::VOffsetT = 4; + pub const VT_ADDRESS: flatbuffers::VOffsetT = 6; + pub const VT_AMOUNT: flatbuffers::VOffsetT = 8; + pub const VT_POOL: flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + TxOutput { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args TxOutputArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = TxOutputBuilder::new(_fbb); + builder.add_amount(args.amount); + if let Some(x) = args.address { builder.add_address(x); } + builder.add_id(args.id); + builder.add_pool(args.pool); + builder.finish() + } + + pub fn unpack(&self) -> TxOutputT { + let id = self.id(); + let address = self.address().map(|x| { + x.to_string() + }); + let amount = self.amount(); + let pool = self.pool(); + TxOutputT { + id, + address, + amount, + pool, + } + } + + #[inline] + pub fn id(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxOutput::VT_ID, Some(0)).unwrap()} + } + #[inline] + pub fn address(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TxOutput::VT_ADDRESS, None)} + } + #[inline] + pub fn amount(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxOutput::VT_AMOUNT, Some(0)).unwrap()} + } + #[inline] + pub fn pool(&self) -> u8 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxOutput::VT_POOL, Some(0)).unwrap()} + } +} + +impl flatbuffers::Verifiable for TxOutput<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("id", Self::VT_ID, false)? + .visit_field::>("address", Self::VT_ADDRESS, false)? + .visit_field::("amount", Self::VT_AMOUNT, false)? + .visit_field::("pool", Self::VT_POOL, false)? + .finish(); + Ok(()) + } +} +pub struct TxOutputArgs<'a> { + pub id: u32, + pub address: Option>, + pub amount: u64, + pub pool: u8, +} +impl<'a> Default for TxOutputArgs<'a> { + #[inline] + fn default() -> Self { + TxOutputArgs { + id: 0, + address: None, + amount: 0, + pool: 0, + } + } +} + +pub struct TxOutputBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> TxOutputBuilder<'a, 'b> { + #[inline] + pub fn add_id(&mut self, id: u32) { + self.fbb_.push_slot::(TxOutput::VT_ID, id, 0); + } + #[inline] + pub fn add_address(&mut self, address: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(TxOutput::VT_ADDRESS, address); + } + #[inline] + pub fn add_amount(&mut self, amount: u64) { + self.fbb_.push_slot::(TxOutput::VT_AMOUNT, amount, 0); + } + #[inline] + pub fn add_pool(&mut self, pool: u8) { + self.fbb_.push_slot::(TxOutput::VT_POOL, pool, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> TxOutputBuilder<'a, 'b> { + let start = _fbb.start_table(); + TxOutputBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for TxOutput<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("TxOutput"); + ds.field("id", &self.id()); + ds.field("address", &self.address()); + ds.field("amount", &self.amount()); + ds.field("pool", &self.pool()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct TxOutputT { + pub id: u32, + pub address: Option, + pub amount: u64, + pub pool: u8, +} +impl Default for TxOutputT { + fn default() -> Self { + Self { + id: 0, + address: None, + amount: 0, + pool: 0, + } + } +} +impl TxOutputT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let id = self.id; + let address = self.address.as_ref().map(|x|{ + _fbb.create_string(x) + }); + let amount = self.amount; + let pool = self.pool; + TxOutput::create(_fbb, &TxOutputArgs{ + id, + address, + amount, + pool, + }) + } +} +pub enum TxReportOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct TxReport<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for TxReport<'a> { + type Inner = TxReport<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> TxReport<'a> { + pub const VT_OUTPUTS: flatbuffers::VOffsetT = 4; + pub const VT_TRANSPARENT: flatbuffers::VOffsetT = 6; + pub const VT_SAPLING: flatbuffers::VOffsetT = 8; + pub const VT_ORCHARD: flatbuffers::VOffsetT = 10; + pub const VT_NET_SAPLING: flatbuffers::VOffsetT = 12; + pub const VT_NET_ORCHARD: flatbuffers::VOffsetT = 14; + pub const VT_FEE: flatbuffers::VOffsetT = 16; + pub const VT_PRIVACY_LEVEL: flatbuffers::VOffsetT = 18; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + TxReport { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args TxReportArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = TxReportBuilder::new(_fbb); + builder.add_fee(args.fee); + builder.add_net_orchard(args.net_orchard); + builder.add_net_sapling(args.net_sapling); + builder.add_orchard(args.orchard); + builder.add_sapling(args.sapling); + builder.add_transparent(args.transparent); + if let Some(x) = args.outputs { builder.add_outputs(x); } + builder.add_privacy_level(args.privacy_level); + builder.finish() + } + + pub fn unpack(&self) -> TxReportT { + let outputs = self.outputs().map(|x| { + x.iter().map(|t| t.unpack()).collect() + }); + let transparent = self.transparent(); + let sapling = self.sapling(); + let orchard = self.orchard(); + let net_sapling = self.net_sapling(); + let net_orchard = self.net_orchard(); + let fee = self.fee(); + let privacy_level = self.privacy_level(); + TxReportT { + outputs, + transparent, + sapling, + orchard, + net_sapling, + net_orchard, + fee, + privacy_level, + } + } + + #[inline] + pub fn outputs(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(TxReport::VT_OUTPUTS, None)} + } + #[inline] + pub fn transparent(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_TRANSPARENT, Some(0)).unwrap()} + } + #[inline] + pub fn sapling(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_SAPLING, Some(0)).unwrap()} + } + #[inline] + pub fn orchard(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_ORCHARD, Some(0)).unwrap()} + } + #[inline] + pub fn net_sapling(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_NET_SAPLING, Some(0)).unwrap()} + } + #[inline] + pub fn net_orchard(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_NET_ORCHARD, Some(0)).unwrap()} + } + #[inline] + pub fn fee(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_FEE, Some(0)).unwrap()} + } + #[inline] + pub fn privacy_level(&self) -> u8 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TxReport::VT_PRIVACY_LEVEL, Some(0)).unwrap()} + } +} + +impl flatbuffers::Verifiable for TxReport<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>>>("outputs", Self::VT_OUTPUTS, false)? + .visit_field::("transparent", Self::VT_TRANSPARENT, false)? + .visit_field::("sapling", Self::VT_SAPLING, false)? + .visit_field::("orchard", Self::VT_ORCHARD, false)? + .visit_field::("net_sapling", Self::VT_NET_SAPLING, false)? + .visit_field::("net_orchard", Self::VT_NET_ORCHARD, false)? + .visit_field::("fee", Self::VT_FEE, false)? + .visit_field::("privacy_level", Self::VT_PRIVACY_LEVEL, false)? + .finish(); + Ok(()) + } +} +pub struct TxReportArgs<'a> { + pub outputs: Option>>>>, + pub transparent: u64, + pub sapling: u64, + pub orchard: u64, + pub net_sapling: i64, + pub net_orchard: i64, + pub fee: u64, + pub privacy_level: u8, +} +impl<'a> Default for TxReportArgs<'a> { + #[inline] + fn default() -> Self { + TxReportArgs { + outputs: None, + transparent: 0, + sapling: 0, + orchard: 0, + net_sapling: 0, + net_orchard: 0, + fee: 0, + privacy_level: 0, + } + } +} + +pub struct TxReportBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> TxReportBuilder<'a, 'b> { + #[inline] + pub fn add_outputs(&mut self, outputs: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(TxReport::VT_OUTPUTS, outputs); + } + #[inline] + pub fn add_transparent(&mut self, transparent: u64) { + self.fbb_.push_slot::(TxReport::VT_TRANSPARENT, transparent, 0); + } + #[inline] + pub fn add_sapling(&mut self, sapling: u64) { + self.fbb_.push_slot::(TxReport::VT_SAPLING, sapling, 0); + } + #[inline] + pub fn add_orchard(&mut self, orchard: u64) { + self.fbb_.push_slot::(TxReport::VT_ORCHARD, orchard, 0); + } + #[inline] + pub fn add_net_sapling(&mut self, net_sapling: i64) { + self.fbb_.push_slot::(TxReport::VT_NET_SAPLING, net_sapling, 0); + } + #[inline] + pub fn add_net_orchard(&mut self, net_orchard: i64) { + self.fbb_.push_slot::(TxReport::VT_NET_ORCHARD, net_orchard, 0); + } + #[inline] + pub fn add_fee(&mut self, fee: u64) { + self.fbb_.push_slot::(TxReport::VT_FEE, fee, 0); + } + #[inline] + pub fn add_privacy_level(&mut self, privacy_level: u8) { + self.fbb_.push_slot::(TxReport::VT_PRIVACY_LEVEL, privacy_level, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> TxReportBuilder<'a, 'b> { + let start = _fbb.start_table(); + TxReportBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for TxReport<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("TxReport"); + ds.field("outputs", &self.outputs()); + ds.field("transparent", &self.transparent()); + ds.field("sapling", &self.sapling()); + ds.field("orchard", &self.orchard()); + ds.field("net_sapling", &self.net_sapling()); + ds.field("net_orchard", &self.net_orchard()); + ds.field("fee", &self.fee()); + ds.field("privacy_level", &self.privacy_level()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct TxReportT { + pub outputs: Option>, + pub transparent: u64, + pub sapling: u64, + pub orchard: u64, + pub net_sapling: i64, + pub net_orchard: i64, + pub fee: u64, + pub privacy_level: u8, +} +impl Default for TxReportT { + fn default() -> Self { + Self { + outputs: None, + transparent: 0, + sapling: 0, + orchard: 0, + net_sapling: 0, + net_orchard: 0, + fee: 0, + privacy_level: 0, + } + } +} +impl TxReportT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let outputs = self.outputs.as_ref().map(|x|{ + let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w) + }); + let transparent = self.transparent; + let sapling = self.sapling; + let orchard = self.orchard; + let net_sapling = self.net_sapling; + let net_orchard = self.net_orchard; + let fee = self.fee; + let privacy_level = self.privacy_level; + TxReport::create(_fbb, &TxReportArgs{ + outputs, + transparent, + sapling, + orchard, + net_sapling, + net_orchard, + fee, + privacy_level, + }) + } +} } // pub mod fb diff --git a/src/gpu.rs b/src/gpu.rs index 476bc90..dd5185b 100644 --- a/src/gpu.rs +++ b/src/gpu.rs @@ -139,7 +139,7 @@ fn collect_decrypted_notes( usize::from_le_bytes(plaintext[52..60].try_into().unwrap()); let cmu = note.cmu().to_bytes(); 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 { account, ivk: fvk.clone(), diff --git a/src/key2.rs b/src/key2.rs index b10dbf3..b483d69 100644 --- a/src/key2.rs +++ b/src/key2.rs @@ -123,7 +123,7 @@ fn derive_viewing_key( network: &Network, extsk: &ExtendedSpendingKey, ) -> anyhow::Result<(String, String)> { - let fvk = ExtendedFullViewingKey::from(extsk); + let fvk = extsk.to_extended_full_viewing_key(); let pa = derive_address(network, &fvk)?; let fvk = encode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk); diff --git a/src/lib.rs b/src/lib.rs index 9205c0e..aa65c71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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::*; 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 note_selection::{ diff --git a/src/mempool.rs b/src/mempool.rs index c89943e..e3c05cd 100644 --- a/src/mempool.rs +++ b/src/mempool.rs @@ -271,7 +271,7 @@ impl MemPoolImpl { &self.pivk, co, ) { - balance += note.value as i64; // value is incoming + balance += note.value().inner() as i64; // value is incoming } } } diff --git a/src/note_selection.rs b/src/note_selection.rs index 9720808..e7f6c75 100644 --- a/src/note_selection.rs +++ b/src/note_selection.rs @@ -9,7 +9,7 @@ pub use optimize::build_tx_plan; use std::str::FromStr; pub use utxo::fetch_utxos; -use crate::api::recipient::Recipient; +use crate::db::data_generated::fb::Recipient; use thiserror::Error; use ua::decode; use zcash_primitives::consensus::Network; @@ -47,13 +47,13 @@ pub fn recipients_to_orders(network: &Network, recipients: &[Recipient]) -> Resu .iter() .enumerate() .map(|(i, r)| { - let destinations = decode(network, &r.address)?; + let destinations = decode(network, r.address().unwrap())?; Ok::<_, TransactionBuilderError>(Order { id: i as u32, destinations, - raw_amount: r.amount, - 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(), + raw_amount: r.amount(), + 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()).unwrap().into(), }) }) .collect(); diff --git a/src/note_selection/builder.rs b/src/note_selection/builder.rs index 0e2806a..cb6eb79 100644 --- a/src/note_selection/builder.rs +++ b/src/note_selection/builder.rs @@ -29,7 +29,7 @@ use zcash_primitives::transaction::components::{Amount, OutPoint, TxOut}; use zcash_primitives::transaction::sighash::{signature_hash, SignableInput}; use zcash_primitives::transaction::txid::TxIdDigester; use zcash_primitives::transaction::{Transaction, TransactionData, TxVersion}; -use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; +use zcash_primitives::zip32::ExtendedSpendingKey; pub struct SecretKeys { pub transparent: Option, @@ -85,7 +85,7 @@ pub fn build_tx( let sapling_fvk = skeys .sapling .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 okeys = skeys.orchard.map(|sk| { @@ -114,7 +114,9 @@ pub fn build_tx( .ok_or(anyhow!("No transparent key")) .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 { diversifier, @@ -131,15 +133,17 @@ pub fn build_tx( .to_payment_address(diversifier) .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::::read(witness.as_slice())?; let merkle_path = witness.path().unwrap(); - builder.add_sapling_spend( - skeys.sapling.clone().ok_or(anyhow!("No Sapling Key"))?, - diversifier, - note, - merkle_path, - )?; + builder + .add_sapling_spend( + skeys.sapling.clone().ok_or(anyhow!("No Sapling Key"))?, + diversifier, + note, + merkle_path, + ) + .map_err(|e| anyhow!(e.to_string()))?; } Source::Orchard { id_note, @@ -180,16 +184,15 @@ pub fn build_tx( match &output.destination { Destination::Transparent(_addr) => { 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) => { let sapling_address = PaymentAddress::from_bytes(addr).unwrap(); - builder.add_sapling_output( - sapling_ovk, - sapling_address, - value, - output.memo.clone(), - )?; + builder + .add_sapling_output(sapling_ovk, sapling_address, value, output.memo.clone()) + .map_err(|e| anyhow!(e.to_string()))?; } Destination::Orchard(addr) => { has_orchard = true; diff --git a/src/note_selection/ser.rs b/src/note_selection/ser.rs index f161f4d..1bd6866 100644 --- a/src/note_selection/ser.rs +++ b/src/note_selection/ser.rs @@ -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 serde::{Deserialize, Serialize}; use zcash_primitives::consensus::Network; @@ -19,7 +20,7 @@ impl From for MemoBytes { } 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 outs = [0; 3]; let mut changes = [0; 3]; @@ -38,9 +39,9 @@ impl TransactionReport { .outputs .iter() .filter_map(|o| { - o.id_order.map(|id| TransactionOutput { + o.id_order.map(|id| TxOutputT { id, - address: o.destination.address(network), + address: Some(o.destination.address(network)), amount: o.amount, pool: o.destination.pool() as u8, }) @@ -60,8 +61,8 @@ impl TransactionReport { 3 }; - let report = TransactionReport { - outputs, + let report = TxReportT { + outputs: Some(outputs), transparent: spends[0] - changes[0], sapling: spends[1] - changes[1], orchard: spends[2] - changes[2], diff --git a/src/pay.rs b/src/pay.rs index 2d1e1bc..16afa02 100644 --- a/src/pay.rs +++ b/src/pay.rs @@ -3,7 +3,7 @@ use crate::db::SpendableNote; use crate::api::recipient::RecipientMemo; use crate::chain::get_latest_height; use crate::coinconfig::CoinConfig; -use crate::{GetAddressUtxosReply, Hash, RawTransaction}; +use crate::{GetAddressUtxosReply, RawTransaction}; use anyhow::anyhow; use jubjub::Fr; use rand::prelude::SliceRandom; @@ -14,8 +14,7 @@ use std::sync::mpsc; use tonic::Request; use zcash_client_backend::address::RecipientAddress; use zcash_client_backend::encoding::{ - decode_extended_full_viewing_key, decode_payment_address, encode_extended_full_viewing_key, - encode_payment_address, + decode_extended_full_viewing_key, encode_extended_full_viewing_key, encode_payment_address, }; use zcash_params::coin::{get_coin_chain, CoinChain, CoinType}; 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::components::amount::{DEFAULT_FEE, MAX_MONEY}; use zcash_primitives::transaction::components::{Amount, OutPoint, TxOut as ZTxOut}; +use zcash_primitives::transaction::fees::fixed::FeeRule; use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; #[derive(Serialize, Deserialize, Debug)] @@ -219,7 +219,7 @@ impl TxBuilder { for n in notes.iter() { if amount.is_positive() { let a = amount.min( - Amount::from_u64(n.note.value) + Amount::from_u64(n.note.value().inner()) .map_err(|_| anyhow::anyhow!("Invalid amount"))?, ); amount -= a; @@ -230,7 +230,7 @@ impl TxBuilder { self.add_z_input( &n.diversifier, fvk, - Amount::from_u64(n.note.value).unwrap(), + Amount::from_u64(n.note.value().inner()).unwrap(), &rseed.to_bytes(), &witness_bytes, )?; @@ -322,27 +322,22 @@ impl Tx { let chain = get_coin_chain(self.coin_type); let last_height = BlockHeight::from_u32(self.height as u32); let mut builder = Builder::new(*chain.network(), last_height); - let efvk = ExtendedFullViewingKey::from(zsk); - - 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(), - ); + let efvk = zsk.to_extended_full_viewing_key(); if let Some(tsk) = tsk { for txin in self.t_inputs.iter() { let mut txid = [0u8; 32]; hex::decode_to_slice(&txin.op, &mut txid)?; - builder.add_transparent_input( - tsk, - OutPoint::new(txid, txin.n), - ZTxOut { - value: Amount::from_u64(txin.amount).unwrap(), - script_pubkey: Script(hex::decode(&txin.script).unwrap()), - }, - )?; + builder + .add_transparent_input( + tsk, + OutPoint::new(txid, txin.n), + ZTxOut { + 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() { anyhow::bail!("Missing secret key of transparent account"); @@ -364,14 +359,14 @@ impl Tx { let mut rseed_bytes = [0u8; 32]; hex::decode_to_slice(&txin.rseed, &mut rseed_bytes)?; let rseed = Fr::from_bytes(&rseed_bytes).unwrap(); - let note = pa - .create_note(txin.amount, Rseed::BeforeZip212(rseed)) - .unwrap(); + let note = pa.create_note(txin.amount, Rseed::BeforeZip212(rseed)); let w = hex::decode(&txin.witness)?; let witness = IncrementalWitness::::read(&*w)?; 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() { @@ -379,7 +374,9 @@ impl Tx { let amount = Amount::from_u64(txout.amount).unwrap(); match recipient { 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) => { let mut ovk = [0u8; 32]; @@ -389,7 +386,9 @@ impl Tx { let m = hex::decode(&txout.memo)?; memo[..m.len()].copy_from_slice(&m); 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) => { todo!() // TODO @@ -406,7 +405,7 @@ impl Tx { progress_callback(progress); } }); - let (tx, _) = builder.build(prover)?; + let (tx, _) = builder.build(prover, &FeeRule::standard())?; let mut raw_tx = vec![]; tx.write(&mut raw_tx)?; diff --git a/src/sapling/note.rs b/src/sapling/note.rs index f504409..fc1f7ff 100644 --- a/src/sapling/note.rs +++ b/src/sapling/note.rs @@ -67,7 +67,7 @@ impl DecryptedNote, SaplingViewKey> for Decrypte height: self.output_position.height, output_index: self.output_position.output_index as u32, diversifier: self.pa.diversifier().0.to_vec(), - value: self.note.value, + value: self.note.value().inner(), rcm: self.note.rcm().to_repr().to_vec(), nf: self.note.nf(&viewing_key.nk, position).to_vec(), rho: None, diff --git a/src/zip32.rs b/src/zip32.rs index f160aae..dcb58b6 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -1,10 +1,10 @@ +use crate::db::data_generated::fb::KeyPackT; use crate::key2::split_key; use anyhow::anyhow; use base58check::ToBase58Check; use bip39::{Language, Mnemonic, Seed}; use ripemd::{Digest, Ripemd160}; use secp256k1::{All, PublicKey, Secp256k1, SecretKey}; -use serde::Serialize; use sha2::Sha256; use tiny_hderive::bip32::ExtendedPrivKey; use zcash_client_backend::encoding::{ @@ -14,21 +14,13 @@ use zcash_primitives::consensus::{Network, Parameters}; use zcash_primitives::legacy::TransparentAddress; 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( network: &Network, phrase: &str, account_index: u32, external: u32, address_index: Option, -) -> anyhow::Result { +) -> anyhow::Result { let (phrase, password) = split_key(phrase); let mnemonic = Mnemonic::from_phrase(&phrase, Language::English)?; let seed = Seed::new(&mnemonic, &password); @@ -71,10 +63,10 @@ pub fn derive_zip32( sk.push(0x01); let t_key = sk.to_base58check(0x80); - Ok(KeyPack { - z_key, - z_addr, - t_key, - t_addr, + Ok(KeyPackT { + z_key: Some(z_key), + z_addr: Some(z_addr), + t_key: Some(t_key), + t_addr: Some(t_addr), }) }