From 148abd95d0fcce4b4a5a0569a9bedd55a17b8140 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 8 May 2024 13:49:39 -0500 Subject: [PATCH] Implement fee calculator --- librustzcash-wrapper/src/lib.rs | 145 ++++++++++++++++++-------------- src/C/Zcash.chs | 1 + src/ZcashHaskell/Utils.hs | 4 +- 3 files changed, 86 insertions(+), 64 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index bc234f5..7397401 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1643,6 +1643,7 @@ pub extern "C" fn rust_wrapper_create_transaction( sapoutput_len: usize, net: bool, bl_height: u32, + build: bool, out: *mut u8, out_len: &mut usize){ let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); @@ -1794,71 +1795,89 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } - let spend_params_in: Vec = marshall_from_haskell_var(sapspend, sapspend_len, RW); - let spend_params_reader = Cursor::new(spend_params_in); - let spend_prover = SpendParameters::read(spend_params_reader, false).unwrap(); - let output_params_in: Vec = marshall_from_haskell_var(sapoutput, sapoutput_len, RW); - let output_params_reader = Cursor::new(output_params_in); - let output_prover = OutputParameters::read(output_params_reader, false).unwrap(); - let result = if net { - main_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard()) - } else { - test_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard()) - }; - match result { - Ok(r) => { - let mut out_bytes: Vec = Vec::new(); - let _t = r.transaction().write_v5(&mut out_bytes); - let h = Hhex {bytes: out_bytes}; - marshall_to_haskell_var(&h, out, out_len, RW); - }, - Err(e) => { - match e { - Error::InsufficientFunds(y) => { - let x = Hhex {bytes: vec![0]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::ChangeRequired(y1) => { - let x = Hhex {bytes: vec![1]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::Fee(_y2) => { - let x = Hhex {bytes: vec![2]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::Balance(y3) => { - let x = Hhex {bytes: vec![3]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::TransparentBuild(y4) => { - let x = Hhex {bytes: vec![4]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::SaplingBuild(y5) => { - let x = Hhex {bytes: vec![5]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::OrchardBuild(y7) => { - let x = Hhex {bytes: vec![6]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::OrchardSpend(y8) => { - let x = Hhex {bytes: vec![7]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::OrchardRecipient(y9) => { - let x = Hhex {bytes: vec![8]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::SaplingBuilderNotAvailable => { - let x = Hhex {bytes: vec![9]}; - marshall_to_haskell_var(&x, out, out_len, RW); - }, - Error::OrchardBuilderNotAvailable => { - let x = Hhex {bytes: vec![10]}; - marshall_to_haskell_var(&x, out, out_len, RW); + if build { + let spend_params_in: Vec = marshall_from_haskell_var(sapspend, sapspend_len, RW); + let spend_params_reader = Cursor::new(spend_params_in); + let spend_prover = SpendParameters::read(spend_params_reader, false).unwrap(); + let output_params_in: Vec = marshall_from_haskell_var(sapoutput, sapoutput_len, RW); + let output_params_reader = Cursor::new(output_params_in); + let output_prover = OutputParameters::read(output_params_reader, false).unwrap(); + let result = if net { + main_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard()) + } else { + test_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard()) + }; + match result { + Ok(r) => { + let mut out_bytes: Vec = Vec::new(); + let _t = r.transaction().write_v5(&mut out_bytes); + let h = Hhex {bytes: out_bytes}; + marshall_to_haskell_var(&h, out, out_len, RW); + }, + Err(e) => { + match e { + Error::InsufficientFunds(y) => { + let x = Hhex {bytes: vec![0]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::ChangeRequired(y1) => { + let x = Hhex {bytes: vec![1]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::Fee(_y2) => { + let x = Hhex {bytes: vec![2]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::Balance(y3) => { + let x = Hhex {bytes: vec![3]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::TransparentBuild(y4) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::SaplingBuild(y5) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::OrchardBuild(y7) => { + let x = Hhex {bytes: vec![6]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::OrchardSpend(y8) => { + let x = Hhex {bytes: vec![7]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::OrchardRecipient(y9) => { + let x = Hhex {bytes: vec![8]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::SaplingBuilderNotAvailable => { + let x = Hhex {bytes: vec![9]}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Error::OrchardBuilderNotAvailable => { + let x = Hhex {bytes: vec![10]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } } } } + } else { + let result = if net { + main_builder.get_fee(&FeeRule::standard()) + } else { + test_builder.get_fee(&FeeRule::standard()) + }; + match result { + Ok(r) => { + let x = Hhex {bytes: r.to_i64_le_bytes().to_vec()}; + marshall_to_haskell_var(&x, out, out_len, RW); + }, + Err(e) => { + let x = Hhex {bytes: vec![2]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } } diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 8f27fa2..0f35be4 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -287,6 +287,7 @@ import ZcashHaskell.Types , toBorshVar* `BS.ByteString'& , `Bool' , `Word64' + , `Bool' , getVarBuffer `Buffer HexString'& } -> `()' diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index db001c8..59b38ed 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -133,8 +133,9 @@ createTransaction :: -> SaplingOutputParams -- ^ the Sapling circuit output parameters -> ZcashNet -- ^ the network to be used -> Int -- ^ target block height + -> Bool -- ^ True to build, False to estimate fee -> Either TxError HexString -createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing sParams oParams znet bh = +createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing sParams oParams znet bh build = if BS.length (hexBytes txResult) > 1 then Right txResult else case head (BS.unpack $ hexBytes txResult) of @@ -168,3 +169,4 @@ createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing sParams oPa (sapOParams oParams) (znet == MainNet) (fromIntegral bh) + build