From 7c79ee6163d18d03a6bfc7d703bf650558d4b976 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 25 Jul 2024 11:09:17 -0500 Subject: [PATCH 01/72] Add JSON instances for ZcashNet --- CHANGELOG.md | 4 ++++ src/ZcashHaskell/Types.hs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24814be..2f3492f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.2.2] + +- Added JSON instances for `ZcashNet` + ## [0.6.2.1] ### Changed diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index af60f0f..f806413 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -90,7 +90,7 @@ data ZcashNet = MainNet | TestNet | RegTestNet - deriving (Eq, Prelude.Show, Read) + deriving (Eq, Prelude.Show, Read, GHC.Generic, ToJSON, FromJSON) type AccountId = Int -- 2.34.1 From 9ca702a68e5ac2e9893bf4f6826686cb3ae99a56 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 13 Aug 2024 07:56:25 -0500 Subject: [PATCH 02/72] Add `ValidAddress` --- CHANGELOG.md | 1 + src/ZcashHaskell/Types.hs | 8 ++++++++ zcash-haskell.cabal | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f3492f..64af8aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.6.2.2] - Added JSON instances for `ZcashNet` +- Added `ValidAddress` ## [0.6.2.1] diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index f806413..d6bfd2e 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -583,6 +583,14 @@ data RawUA = RawUA deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawUA +-- | A type to handle user-entered addresses +data ValidAddress + = Unified !UnifiedAddress + | Sapling !SaplingAddress + | Transparent !TransparentAddress + | Exchange !ExchangeAddress + deriving stock (Eq, Prelude.Show) + -- | Type to represent a Unified Full Viewing Key data UnifiedFullViewingKey = UnifiedFullViewingKey { net :: !Word8 -- ^ Number representing the network the key belongs to. @1@ for @mainnet@, @2@ for @testnet@ and @3@ for @regtestnet@. diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 27924ee..436bf5a 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.6.2.1 +version: 0.6.2.2 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From b7c91e10fe9210a01de914a3fc55e7698d32c085 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Aug 2024 12:32:30 -0500 Subject: [PATCH 03/72] Add functions to compare and validate addresses --- src/ZcashHaskell/Orchard.hs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index d7c3e38..145c503 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -37,6 +37,11 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as E import Data.Word import Foreign.Rust.Marshall.Variable +import ZcashHaskell.Sapling (decodeSaplingAddress) +import ZcashHaskell.Transparent + ( decodeExchangeAddress + , decodeTransparentAddress + ) import ZcashHaskell.Types import ZcashHaskell.Utils (encodeBech32, encodeBech32m, f4Jumble) @@ -221,8 +226,33 @@ getOrchardNotePosition :: OrchardWitness -> Integer getOrchardNotePosition = fromIntegral . rustWrapperReadOrchardPosition . hexBytes . orchWit +-- | Update the witness of an Orchard note updateOrchardWitness :: OrchardWitness -> [HexString] -> OrchardWitness updateOrchardWitness wit cmus = OrchardWitness $ withPureBorshVarBuffer $ rustWrapperUpdateOrchardWitness (toBytes $ orchWit wit) (map toBytes cmus) + +-- | Parse a potential Zcash address +parseAddress :: BS.ByteString -> Maybe ValidAddress +parseAddress t = + case isValidUnifiedAddress t of + Nothing -> + case decodeSaplingAddress t of + Nothing -> + case decodeTransparentAddress t of + Nothing -> + case decodeExchangeAddress t of + Nothing -> Nothing + Just x -> Just $ Exchange x + Just t -> Just $ Transparent t + Just s -> Just $ Sapling s + Just u -> Just $ Unified u + +compareAddress :: ValidAddress -> UnifiedAddress -> Bool +compareAddress a u = + case a of + Unified i -> i == u + Sapling s -> s_rec u == Just (sa_receiver s) && ua_net u == net_type s + Transparent t -> t_rec u == Just (ta_receiver t) && ua_net u == ta_network t + Exchange x -> False -- 2.34.1 From 774e135aabc0f5cddae76d93d7a80f8786e46f4e Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Aug 2024 12:32:48 -0500 Subject: [PATCH 04/72] Fix data type --- src/ZcashHaskell/Transparent.hs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/ZcashHaskell/Transparent.hs b/src/ZcashHaskell/Transparent.hs index 878a7d8..287fe99 100644 --- a/src/ZcashHaskell/Transparent.hs +++ b/src/ZcashHaskell/Transparent.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE OverloadedStrings #-} + -- Copyright 2022-2024 Vergara Technologies LLC -- -- This file is part of Zcash-Haskell. @@ -172,27 +174,27 @@ decodeTransparentAddress taddress = do -- | Encode an Exchange Addresss into HRF from TransparentReceiver encodeExchangeAddress :: ZcashNet -> TransparentReceiver -> Maybe T.Text encodeExchangeAddress net tr = do - case (tr_type tr) of + case tr_type tr of P2PKH -> do case net of MainNet -> do - let vhash = encodeBech32m (BC.pack "tex") (toBytes (tr_bytes tr)) + let vhash = encodeBech32m "tex" (toBytes (tr_bytes tr)) Just vhash TestNet -> do - let vhash = encodeBech32m (BC.pack "textest") (toBytes (tr_bytes tr)) + let vhash = encodeBech32m "textest" (toBytes (tr_bytes tr)) Just vhash - _ -> Nothing + _any -> Nothing -- | Decode an Exchange Address into a ExchangeAddress -decodeExchangeAddress :: T.Text -> Maybe ExchangeAddress +decodeExchangeAddress :: BS.ByteString -> Maybe ExchangeAddress decodeExchangeAddress ex = do - if (T.length ex) > 1 + if BS.length ex > 1 then do - let rawd = decodeBech32 (E.encodeUtf8 ex) - let tMain = BS.unpack (BC.pack "tex") - let tTest = BS.unpack (BC.pack "textest") - let tFail = BS.unpack (BC.pack "fail") - let hr = BS.unpack (hrp rawd) + let rawd = decodeBech32 ex + let tMain = "tex" + let tTest = "textest" + let tFail = "fail" + let hr = hrp rawd if hr /= tFail then do let transparentReceiver = bytes rawd -- 2.34.1 From c8f411fcdd0e987dc0c4b544d1ad4dcfb12dd97e Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 20 Aug 2024 15:50:07 -0500 Subject: [PATCH 05/72] add JSON instances for `Transaction` --- CHANGELOG.md | 1 + src/ZcashHaskell/Types.hs | 71 +++++++++++++++++++++++++++++++++++++++ zcash-haskell.cabal | 1 + 3 files changed, 73 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64af8aa..5d7630c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.6.2.2] - Added JSON instances for `ZcashNet` +- Added JSON instances for `Transaction` - Added `ValidAddress` ## [0.6.2.1] diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index d6bfd2e..9884b7f 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -38,6 +38,7 @@ import Data.Maybe (fromJust, fromMaybe) import Data.Structured import qualified Data.Text as T import qualified Data.Text.Encoding as E +import qualified Data.Vector as V import Data.Word import qualified GHC.Generics as GHC import qualified Generics.SOP as SOP @@ -133,6 +134,18 @@ data Transaction = Transaction , tx_orchardBundle :: !(Maybe OrchardBundle) } deriving (Prelude.Show, Eq, Read) +instance ToJSON Transaction where + toJSON (Transaction t h c e tb sb ob) = + object + [ "txid" .= t + , "height" .= h + , "confirmations" .= c + , "expiry" .= e + , "transparent" .= tb + , "sapling" .= sb + , "orchard" .= ob + ] + -- | The transparent portion of a Zcash transaction data TransparentBundle = TransparentBundle { tb_vin :: ![H.TxIn] @@ -140,6 +153,10 @@ data TransparentBundle = TransparentBundle , tb_coinbase :: !Bool } deriving (Eq, Prelude.Show, Read) +instance ToJSON TransparentBundle where + toJSON (TransparentBundle vin vout c) = + object ["vin" .= vin, "vout" .= vout, "coinbase" .= c] + -- | Read a raw transparent bundle into the Haskell type fromRawTBundle :: RawTBundle -> Maybe TransparentBundle fromRawTBundle rtb = @@ -324,6 +341,10 @@ data SaplingBundle = SaplingBundle , sbSig :: !HexString } deriving stock (Eq, Prelude.Show, GHC.Generic, Read) +instance ToJSON SaplingBundle where + toJSON (SaplingBundle s o v sig) = + object ["spends" .= s, "outputs" .= o, "value" .= v, "sig" .= sig] + fromRawSBundle :: RawSBundle -> Maybe SaplingBundle fromRawSBundle b = if zsb_empty b @@ -355,6 +376,17 @@ data OrchardBundle = OrchardBundle , obSig :: !HexString } deriving stock (Eq, Prelude.Show, GHC.Generic, Read) +instance ToJSON OrchardBundle where + toJSON (OrchardBundle a f v an p s) = + object + [ "actions" .= a + , "flags" .= f + , "value" .= v + , "anchor" .= an + , "proof" .= p + , "sig" .= s + ] + fromRawOBundle :: RawOBundle -> Maybe OrchardBundle fromRawOBundle b = if zob_empty b @@ -377,6 +409,10 @@ data OrchardFlags = OrchardFlags deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardFlags +instance ToJSON OrchardFlags where + toJSON (OrchardFlags s o) = + Data.Aeson.Array $ V.fromList [Data.Aeson.Bool s, Data.Aeson.Bool o] + -- | Type for the response from the `zebrad` RPC method `getinfo` data ZebraGetInfo = ZebraGetInfo { zgi_build :: !T.Text @@ -501,6 +537,17 @@ data ShieldedSpend = ShieldedSpend deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedSpend +instance ToJSON ShieldedSpend where + toJSON (ShieldedSpend cv a n rk p au) = + object + [ "cv" .= cv + , "anchor" .= a + , "nullifier" .= n + , "rk" .= rk + , "proof" .= p + , "spendAuthSig" .= au + ] + instance FromJSON ShieldedSpend where parseJSON = withObject "ShieldedSpend" $ \obj -> do @@ -525,6 +572,17 @@ data ShieldedOutput = ShieldedOutput deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedOutput +instance ToJSON ShieldedOutput where + toJSON (ShieldedOutput c cm e enc o p) = + object + [ "cv" .= c + , "cmu" .= cm + , "ephemeralKey" .= e + , "encCiphertext" .= enc + , "outCiphertext" .= o + , "proof" .= p + ] + instance FromJSON ShieldedOutput where parseJSON = withObject "ShieldedOutput" $ \obj -> do @@ -617,6 +675,19 @@ data OrchardAction = OrchardAction deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardAction +instance ToJSON OrchardAction where + toJSON (OrchardAction n r c e en o cv a) = + object + [ "nullifier" .= n + , "rk" .= r + , "cmx" .= c + , "ephemeralKey" .= e + , "encCiphertext" .= en + , "outCiphertext" .= o + , "cv" .= cv + , "spendAuthSig" .= a + ] + instance FromJSON OrchardAction where parseJSON = withObject "OrchardAction" $ \obj -> do diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 436bf5a..33c6140 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -59,6 +59,7 @@ library , text , haskoin-core , secp256k1-haskell >= 1.1 + , vector , utf8-string build-tool-depends: c2hs:c2hs -- 2.34.1 From 85a4741dcb32999a265f879327c1b56c31e307c8 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 30 Aug 2024 11:02:52 -0500 Subject: [PATCH 06/72] fix: decode unified addresses with no transparent receivers ensures that a unified address that does not contain a transparent receiver is properly represented in the type --- CHANGELOG.md | 6 ++++++ src/ZcashHaskell/Orchard.hs | 4 ++-- test/Spec.hs | 2 +- zcash-haskell.cabal | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d7630c..6a1a508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.2.3] + +### Fixed + +- Decoding of unified addresses with no transparent receivers + ## [0.6.2.2] - Added JSON instances for `ZcashNet` diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 145c503..6bfe0c4 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -103,9 +103,9 @@ isValidUnifiedAddress str = (if BS.length (raw_s x) == 43 then Just $ SaplingReceiver (raw_s x) else Nothing) - (if not (BS.null (raw_t x)) + (if BS.length (raw_t x) > 1 then Just $ TransparentReceiver P2PKH (fromRawBytes $ raw_t x) - else if not (BS.null (raw_to x)) + else if BS.length (raw_to x) > 1 then Just $ TransparentReceiver P2SH (fromRawBytes $ raw_to x) else Nothing) diff --git a/test/Spec.hs b/test/Spec.hs index 7b0aac0..67ca3ce 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1143,7 +1143,7 @@ main = do case exch of Nothing -> assertFailure "Failed to encode Exchange address" Just addr -> do - let eadr = decodeExchangeAddress addr + let eadr = decodeExchangeAddress (E.encodeUtf8 addr) eadr `shouldNotBe` Nothing describe "Witness updates" $ do it "Sapling" $ do diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 33c6140..b521e58 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.6.2.2 +version: 0.6.2.3 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 5a8cd44fbca5bbac613fe5e4a75e64635a45e2f2 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 16 Sep 2024 13:36:49 -0500 Subject: [PATCH 07/72] feat: implement `wagyu-zcash-parameters` crate --- librustzcash-wrapper/Cargo.lock | 51 +++++++++++++++++++++++++++++++++ librustzcash-wrapper/Cargo.toml | 1 + librustzcash-wrapper/src/lib.rs | 11 ++++--- src/C/Zcash.chs | 2 -- src/ZcashHaskell/Utils.hs | 6 +--- test/Spec.hs | 5 +++- zcash-haskell.cabal | 1 + 7 files changed, 63 insertions(+), 14 deletions(-) diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index 53583a4..e74b7c7 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -1395,6 +1395,7 @@ dependencies = [ "rand_core", "sapling-crypto", "secp256k1", + "wagyu-zcash-parameters", "zcash_address 0.2.0", "zcash_client_backend", "zcash_note_encryption", @@ -1746,6 +1747,56 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wagyu-zcash-parameters" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c904628658374e651288f000934c33ef738b2d8b3e65d4100b70b395dbe2bb" +dependencies = [ + "wagyu-zcash-parameters-1", + "wagyu-zcash-parameters-2", + "wagyu-zcash-parameters-3", + "wagyu-zcash-parameters-4", + "wagyu-zcash-parameters-5", + "wagyu-zcash-parameters-6", +] + +[[package]] +name = "wagyu-zcash-parameters-1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bf2e21bb027d3f8428c60d6a720b54a08bf6ce4e6f834ef8e0d38bb5695da8" + +[[package]] +name = "wagyu-zcash-parameters-2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a616ab2e51e74cc48995d476e94de810fb16fc73815f390bf2941b046cc9ba2c" + +[[package]] +name = "wagyu-zcash-parameters-3" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14da1e2e958ff93c0830ee68e91884069253bf3462a67831b02b367be75d6147" + +[[package]] +name = "wagyu-zcash-parameters-4" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f058aeef03a2070e8666ffb5d1057d8bb10313b204a254a6e6103eb958e9a6d6" + +[[package]] +name = "wagyu-zcash-parameters-5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ffe916b30e608c032ae1b734f02574a3e12ec19ab5cc5562208d679efe4969d" + +[[package]] +name = "wagyu-zcash-parameters-6" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7b6d5a78adc3e8f198e9cd730f219a695431467f7ec29dcfc63ade885feebe1" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index b8b2b37..abb27b5 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -23,6 +23,7 @@ incrementalmerkletree = "0.5.0" secp256k1 = "0.26.0" jubjub = "0.10.0" rand_core = { version = "0.6.4", features = ["getrandom"]} +wagyu-zcash-parameters = "0.2.0" [features] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 7397401..be36e38 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -167,6 +167,8 @@ use bech32::{ Bech32m }; +use wagyu_zcash_parameters::load_sapling_parameters; + pub enum RW {} pub const RW: PhantomData = PhantomData; @@ -1637,10 +1639,6 @@ pub extern "C" fn rust_wrapper_create_transaction( o_input_len: usize, out_list: *const u8, out_list_len: usize, - sapspend: *const u8, - sapspend_len: usize, - sapoutput: *const u8, - sapoutput_len: usize, net: bool, bl_height: u32, build: bool, @@ -1796,10 +1794,11 @@ pub extern "C" fn rust_wrapper_create_transaction( } } if build { - let spend_params_in: Vec = marshall_from_haskell_var(sapspend, sapspend_len, RW); + let (spend_params_in, output_params_in) = load_sapling_parameters(); + //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_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 { diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 0f35be4..bc75ee4 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -283,8 +283,6 @@ import ZcashHaskell.Types , toBorshVar* `[SaplingTxSpend]'& , toBorshVar* `[OrchardTxSpend]'& , toBorshVar* `[OutgoingNote]'& - , toBorshVar* `BS.ByteString'& - , toBorshVar* `BS.ByteString'& , `Bool' , `Word64' , `Bool' diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index 0f67ed7..e7e1aae 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -129,13 +129,11 @@ createTransaction :: -> [SaplingTxSpend] -- ^ the list of Sapling notes to spend -> [OrchardTxSpend] -- ^ the list of Orchard notes to spend -> [OutgoingNote] -- ^ the list of outgoing notes, including change notes - -> SaplingSpendParams -- ^ the Sapling circuit spending parameters - -> 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 build = +createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = processResult $! txResult where processResult :: HexString -> Either TxError HexString @@ -168,8 +166,6 @@ createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing sParams oPa sSpend oSpend outgoing - (sapSParams sParams) - (sapOParams oParams) (znet == MainNet) (fromIntegral bh) build diff --git a/test/Spec.hs b/test/Spec.hs index 67ca3ce..ac4581e 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -40,6 +40,7 @@ import GHC.Float.RealFracMethods (properFractionDoubleInteger) import Haskoin.Crypto.Hash (ripemd160) import Haskoin.Crypto.Keys.Extended import Haskoin.Transaction.Common +import Network.HTTP.Simple (Response(..)) import Test.HUnit import Test.Hspec import Test.Hspec.QuickCheck @@ -82,6 +83,8 @@ import ZcashHaskell.Types , RawTxOut(..) , RawTxResponse(..) , RawZebraTx(..) + , RpcError(..) + , RpcResponse(..) , SaplingAddress(..) , SaplingBundle(..) , SaplingCommitmentTree(..) @@ -1179,7 +1182,7 @@ main = do updateOrchardWitness wit cmxs `shouldBe` OrchardWitness (hexString - "016225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631001f0000011d6f5da3f619bfaab957fc643c17eb144db0101c90f422da2fcbe0e80d74412e000000000001746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000040e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e0504bfbc12edc35e05042c16bbfb8fed591f01f18fe128eeb57f2c456c9eb222d6d261c549e95d9007bce4c6ae0b86bc865711cdd9f0fa92e2d5b5e149b51f3be127df3b1d2372adf6c811b2e456c1d64d0e9eb167a995f9c6b66a03c9cbda250101c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e0002010cfb50d8c877eb39e9c07082a032dd99d34be7c19fa7f30e9fecf5f14736240f019df5b9366d0f21caa678d1567390b5bfd3cfa0438271bcfe301b5558a2863301") + "016225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631001f0000011d6f5da3f619bfaab957fc643c17eb144db0101c90f422da2fcbe0e80d74412e000000000001746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000040e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e0504bfbc12edc35e05042c16bbfb8fed591f01f18fe128eeb57f2c456c9eb222d6d261c549e95d9007bce4c6ae0b86bc865711cdd9f0fa92e2d5b5e149b51f3be127df3b1d2372adf6c811b2e456c1d64d0e9eb167a995f9c6b66a03c9cbda250101c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e01ac20b8170b008888c19fc6e16f5e30a5ef1653e5219d0cd0c9353c3aa8f7982302010cfb50d8c877eb39e9c07082a032dd99d34be7c19fa7f30e9fecf5f14736240f019df5b9366d0f21caa678d1567390b5bfd3cfa0438271bcfe301b5558a2863301") -- | Properties prop_PhraseLength :: Property diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index b521e58..cd61471 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -86,5 +86,6 @@ test-suite zcash-haskell-test , binary , cryptonite , secp256k1-haskell + , http-conduit pkgconfig-depends: rustzcash_wrapper default-language: Haskell2010 -- 2.34.1 From 1f1ca4e2061891920b84e31996524519ce3ff582 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 17 Sep 2024 13:06:28 -0500 Subject: [PATCH 08/72] docs: update version --- CHANGELOG.md | 4 ++++ zcash-haskell.cabal | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a1a508..91b0b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.0.0] + +- Implement `wagyu-zcash-parameters` in Rust bindings + ## [0.6.2.3] ### Fixed diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index cd61471..2794c6c 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.6.2.3 +version: 0.7.0.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 343495f6e7439042c5d50c28b0be6a9e67966014 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 18 Sep 2024 07:27:53 -0500 Subject: [PATCH 09/72] feat: add privacy policy error to `TxError` --- CHANGELOG.md | 5 +++++ src/ZcashHaskell/Types.hs | 1 + zcash-haskell.cabal | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b0b51..9497285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.0.1] + +### Added +- New error type `PrivacyPolicyError` + ## [0.7.0.0] - Implement `wagyu-zcash-parameters` in Rust bindings diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 9884b7f..abfb334 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -791,6 +791,7 @@ data TxError | OrchardRecipient | SaplingBuilderNotAvailable | OrchardBuilderNotAvailable + | PrivacyPolicyError !T.Text | ZHError deriving (Eq, Prelude.Show, Read) diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 2794c6c..9cf7abd 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.0.0 +version: 0.7.0.1 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From f24ea80cde27161f56fb972ffd92d276aaa8a735 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 23 Sep 2024 10:17:35 -0500 Subject: [PATCH 10/72] feat: add block hash to `BlockResponse` --- src/ZcashHaskell/Types.hs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index abfb334..1647b42 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -256,7 +256,8 @@ instance FromJSON RpcError where -- ** `zcashd` -- | Type to represent response from the `zcashd` RPC `getblock` method data BlockResponse = BlockResponse - { bl_confirmations :: !Integer -- ^ Block confirmations + { bl_hash :: !HexString + , bl_confirmations :: !Integer -- ^ Block confirmations , bl_height :: !Integer -- ^ Block height , bl_time :: !Integer -- ^ Block time , bl_txs :: ![HexString] -- ^ List of transaction IDs in the block @@ -269,7 +270,8 @@ instance FromJSON BlockResponse where h <- obj .: "height" t <- obj .:? "time" txs <- obj .: "tx" - pure $ BlockResponse c h (fromMaybe 0 t) txs + hash <- obj .: "hash" + pure $ BlockResponse hash c h (fromMaybe 0 t) txs -- | Type to represent response from the `zcashd` RPC `getrawtransaction` data RawTxResponse = RawTxResponse -- 2.34.1 From 5de1844e9d19e3b44b649904ba2881cf9843b2e4 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 25 Sep 2024 14:43:11 -0500 Subject: [PATCH 11/72] feat: improve witness updates --- CHANGELOG.md | 6 ++++++ src/ZcashHaskell/Orchard.hs | 10 +++++++--- src/ZcashHaskell/Sapling.hs | 10 +++++++--- zcash-haskell.cabal | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9497285..a27c7a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.0.2] + +## Changed + +- Modified witness update functions to skip the process if no commitments are present + ## [0.7.0.1] ### Added diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 6bfe0c4..d975c2a 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -229,9 +229,13 @@ getOrchardNotePosition = -- | Update the witness of an Orchard note updateOrchardWitness :: OrchardWitness -> [HexString] -> OrchardWitness updateOrchardWitness wit cmus = - OrchardWitness $ - withPureBorshVarBuffer $ - rustWrapperUpdateOrchardWitness (toBytes $ orchWit wit) (map toBytes cmus) + if not (null cmus) + then OrchardWitness $ + withPureBorshVarBuffer $ + rustWrapperUpdateOrchardWitness + (toBytes $ orchWit wit) + (map toBytes cmus) + else wit -- | Parse a potential Zcash address parseAddress :: BS.ByteString -> Maybe ValidAddress diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index ad7cd01..f145c91 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -218,9 +218,13 @@ getSaplingNotePosition = updateSaplingWitness :: SaplingWitness -> [HexString] -> SaplingWitness updateSaplingWitness wit cmus = - SaplingWitness $ - withPureBorshVarBuffer $ - rustWrapperUpdateSaplingWitness (toBytes $ sapWit wit) (map toBytes cmus) + if not (null cmus) + then SaplingWitness $ + withPureBorshVarBuffer $ + rustWrapperUpdateSaplingWitness + (toBytes $ sapWit wit) + (map toBytes cmus) + else wit -- | Encode a SaplingReceiver into HRF text encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 9cf7abd..a3288b5 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.0.1 +version: 0.7.0.2 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 48afd8159585b29587dbcb5e4d5cf3a3a1b2b820 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 30 Sep 2024 12:05:00 -0500 Subject: [PATCH 12/72] feat!: migrate Orchard commitment trees to Frontier --- CHANGELOG.md | 12 +- librustzcash-wrapper/Cargo.lock | 286 ++++++++++++-------------------- librustzcash-wrapper/Cargo.toml | 13 +- librustzcash-wrapper/src/lib.rs | 122 +++++++++----- src/C/Zcash.chs | 11 +- src/ZcashHaskell/Orchard.hs | 31 ++-- src/ZcashHaskell/Types.hs | 9 + test/Spec.hs | 41 ++++- zcash-haskell.cabal | 2 +- 9 files changed, 283 insertions(+), 244 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a27c7a7..9a68512 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.1.0] + +### Added + +- Type `OrchardFrontier` + +### Changed + +- Modified Orchard commitment trees functions to use Frontier + ## [0.7.0.2] -## Changed +### Changed - Modified witness update functions to skip the process if no commitments are present diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index e74b7c7..604eeee 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -66,9 +66,9 @@ checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64ct" -version = "1.0.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bech32" @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "bip0039" -version = "0.10.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef0f0152ec5cf17f49a5866afaa3439816207fd4f0a224c0211ffaf5e278426" +checksum = "568b6890865156d9043af490d4c4081c385dd68ea10acd6ca15733d511e6b51c" dependencies = [ "hmac", "pbkdf2", @@ -132,6 +132,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bip32" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa13fae8b6255872fd86f7faf4b41168661d7d78609f7bfe6771b85c6739a15b" +dependencies = [ + "bs58 0.5.0", + "hmac", + "rand_core", + "ripemd", + "secp256k1", + "sha2 0.10.6", + "subtle", + "zeroize", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -318,12 +334,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "bumpalo" -version = "3.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" - [[package]] name = "byteorder" version = "1.4.3" @@ -709,19 +719,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "hdwallet" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a03ba7d4c9ea41552cd4351965ff96883e629693ae85005c501bb4b9e1c48a7" -dependencies = [ - "lazy_static", - "rand_core", - "ring", - "secp256k1", - "thiserror", -] - [[package]] name = "heck" version = "0.4.1" @@ -760,9 +757,9 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1872810fb725b06b8c153dde9e86f3ec26747b9b60096da7a869883b549cbe" +checksum = "75346da3bd8e3d8891d02508245ed2df34447ca6637e343829f8d08986e9cde2" dependencies = [ "either", ] @@ -815,15 +812,6 @@ dependencies = [ "either", ] -[[package]] -name = "js-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "jubjub" version = "0.10.0" @@ -999,9 +987,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb255c3ffdccd3c84fe9ebed72aef64fdc72e6a3e4180dd411002d47abaad42" +checksum = "4dc7bde644aeb980be296cd908c6650894dc8541deb56f9f5294c52ed7ca568f" dependencies = [ "aes", "bitvec", @@ -1022,6 +1010,7 @@ dependencies = [ "serde", "subtle", "tracing", + "visibility", "zcash_note_encryption", "zcash_spec", "zip32", @@ -1038,9 +1027,9 @@ dependencies = [ [[package]] name = "password-hash" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", "rand_core", @@ -1064,9 +1053,9 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.10.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", "password-hash", @@ -1147,9 +1136,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", "prost-derive", @@ -1157,9 +1146,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", "heck", @@ -1174,14 +1163,13 @@ dependencies = [ "regex", "syn 2.0.32", "tempfile", - "which", ] [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", "itertools", @@ -1192,9 +1180,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ "prost", ] @@ -1341,21 +1329,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - [[package]] name = "ripemd" version = "0.1.3" @@ -1384,6 +1357,7 @@ name = "rustzcash-wrapper" version = "0.1.0" dependencies = [ "bech32 0.11.0", + "bip0039", "borsh 0.10.3", "f4jumble", "haskell-ffi", @@ -1405,9 +1379,9 @@ dependencies = [ [[package]] name = "sapling-crypto" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f4270033afcb0c74c5c7d59c73cfd1040367f67f224fe7ed9a919ae618f1b7" +checksum = "15e379398fffad84e49f9a45a05635fc004f66086e65942dbf4eb95332c26d2a" dependencies = [ "aes", "bellman", @@ -1443,9 +1417,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "secp256k1" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ "secp256k1-sys", ] @@ -1514,9 +1488,9 @@ dependencies = [ [[package]] name = "shardtree" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf20c7a2747d9083092e3a3eeb9a7ed75577ae364896bebbc5e0bdcd4e97735" +checksum = "78222845cd8bbe5eb95687407648ff17693a35de5e8abaa39a4681fb21e033f9" dependencies = [ "bitflags 2.4.2", "either", @@ -1649,13 +1623,14 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.10.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2", "prost-build", + "prost-types", "quote", "syn 2.0.32", ] @@ -1718,9 +1693,9 @@ checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -1735,18 +1710,23 @@ dependencies = [ "subtle", ] -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "visibility" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "wagyu-zcash-parameters" version = "0.2.0" @@ -1803,70 +1783,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.32", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.32", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "web-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "which" version = "4.4.0" @@ -1878,28 +1794,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.48.0" @@ -1989,21 +1883,22 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bce173f1d9ed4f806e310bc3a873301531e7a6dc209928584d6404e3f8228ef4" +checksum = "a6d26f21381dc220836dd8d2a9a10dbe85928a26232b011bc6a42b611789b743" dependencies = [ "bech32 0.9.1", "bs58 0.5.0", "f4jumble", "zcash_encoding", + "zcash_protocol", ] [[package]] name = "zcash_client_backend" -version = "0.11.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "001ec65dc2828ee648dc6d29f0944d7a877fe68ad06e001a203c11770ab1b3d4" +checksum = "80e3a0f3e5d7f299d8b7ef3237697630989c31ab1b162824c99c1cd8bc83715e" dependencies = [ "base64", "bech32 0.9.1", @@ -2029,19 +1924,21 @@ dependencies = [ "tonic-build", "tracing", "which", - "zcash_address 0.3.1", + "zcash_address 0.4.0", "zcash_encoding", "zcash_keys", "zcash_note_encryption", "zcash_primitives", + "zcash_protocol", "zip32", + "zip321", ] [[package]] name = "zcash_encoding" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03391b81727875efa6ac0661a20883022b6fba92365dc121c48fa9b00c5aac0" +checksum = "052d8230202f0a018cd9b5d1b56b94cd25e18eccc2d8665073bcea8261ab87fc" dependencies = [ "byteorder", "nonempty", @@ -2049,11 +1946,12 @@ dependencies = [ [[package]] name = "zcash_keys" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f22d3407fdd6992b49f037f23862ab376be6013be6f2d0bc85948a635edc1f5" +checksum = "712faf4070107ab0b2828d0eda6aeaf4c3cb02564109832d95b97ad3467c95a5" dependencies = [ "bech32 0.9.1", + "blake2b_simd", "bls12_381", "bs58 0.5.0", "document-features", @@ -2062,11 +1960,13 @@ dependencies = [ "nonempty", "rand_core", "sapling-crypto", + "secrecy", "subtle", "tracing", - "zcash_address 0.3.1", + "zcash_address 0.4.0", "zcash_encoding", "zcash_primitives", + "zcash_protocol", "zip32", ] @@ -2085,20 +1985,20 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9070e084570bb78aed4f8d71fd6254492e62c87a5d01e084183980e98117092d" +checksum = "5f044bc9cf2887ec408196fbafb44749e5581f57cc18d8da7aabaeb60cc40c64" dependencies = [ "aes", - "bip0039", + "bip32", "blake2b_simd", + "bs58 0.5.0", "byteorder", "document-features", "equihash", "ff", "fpe", "group", - "hdwallet", "hex", "incrementalmerkletree", "jubjub", @@ -2114,13 +2014,24 @@ dependencies = [ "sha2 0.10.6", "subtle", "tracing", - "zcash_address 0.3.1", + "zcash_address 0.4.0", "zcash_encoding", "zcash_note_encryption", + "zcash_protocol", "zcash_spec", "zip32", ] +[[package]] +name = "zcash_protocol" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f35eac659fdbba614333d119217c5963c0d7cea43aee33176c4f2f95e5460d8d" +dependencies = [ + "document-features", + "memuse", +] + [[package]] name = "zcash_spec" version = "0.1.0" @@ -2160,3 +2071,16 @@ dependencies = [ "memuse", "subtle", ] + +[[package]] +name = "zip321" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc85f862f7be64fb0d46f9eb5b82ad54e58cde314fa979d5bae591bc0143693" +dependencies = [ + "base64", + "nom", + "percent-encoding", + "zcash_address 0.4.0", + "zcash_protocol", +] diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index abb27b5..208022f 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -11,19 +11,20 @@ f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" bech32 = "0.11" -orchard = "0.7.1" +orchard = "0.9.0" zcash_note_encryption = "0.4.0" -zcash_primitives = { version = "0.14.0", features = ["transparent-inputs"]} -zcash_client_backend = "0.11.1" -sapling-crypto = "0.1.3" +zcash_primitives = { version = "0.16.0", features = ["transparent-inputs"]} +zcash_client_backend = "0.13.0" +sapling-crypto = "0.2" zip32 = "0.1.0" proc-macro2 = "1.0.66" nonempty = "0.7.0" -incrementalmerkletree = "0.5.0" -secp256k1 = "0.26.0" +incrementalmerkletree = "0.6.0" +secp256k1 = "0.27.0" jubjub = "0.10.0" rand_core = { version = "0.6.4", features = ["getrandom"]} wagyu-zcash-parameters = "0.2.0" +bip0039 = "0.12.0" [features] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index be36e38..63c4d2b 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -30,7 +30,12 @@ use secp256k1::SecretKey; use jubjub::Fr; use incrementalmerkletree::{ - frontier::CommitmentTree, + Position, + frontier::{ + CommitmentTree, + Frontier, + NonEmptyFrontier + }, witness::IncrementalWitness }; @@ -79,18 +84,20 @@ use sapling_crypto::{ } }; +use bip0039::{Count, Mnemonic, English}; + use zcash_primitives::{ merkle_tree::{ read_commitment_tree, write_commitment_tree, read_incremental_witness, - write_incremental_witness + write_incremental_witness, + read_frontier_v1 }, legacy::{ Script, TransparentAddress }, - zip339::{Count, Mnemonic}, transaction::{ Transaction, fees::zip317::FeeRule, @@ -147,7 +154,7 @@ use orchard::{ }, Action, keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope}, - note::{RandomSeed, Note, Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment}, + note::{Rho, RandomSeed, Note, Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment}, note_encryption::OrchardDomain, primitives::redpallas::{VerificationKey, SpendAuth, Signature}, tree::{ @@ -686,6 +693,27 @@ impl ToHaskell for Hsvk { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hfrontier { + position: u64, + leaf: Hhex, + ommers: Vec> +} + +impl ToHaskell for Hfrontier { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl FromHaskell for Hfrontier { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Hfrontier::deserialize(buf)?; + Ok(x) + } +} + fn to_array(v: Vec) -> [T; N] { v.try_into().unwrap_or_else(|v: Vec| panic!("Expected a Vec of length {} but it was {}", N, v.len())) } @@ -1026,7 +1054,7 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt( ValueCommitment::from_bytes(&to_array(note_input.cv.bytes)).unwrap(), Signature::from(to_array(note_input.auth.bytes))); let fvk_array = to_array(fvk_input); - let domain = OrchardDomain::for_nullifier(*action.nullifier()); + let domain = OrchardDomain::for_action(&action); let dec_fvk = FullViewingKey::from_bytes(&fvk_array); match dec_fvk { Some(fvk) => { @@ -1073,7 +1101,7 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt_sk( ValueCommitment::from_bytes(&to_array(note_input.cv.bytes)).unwrap(), Signature::from(to_array(note_input.auth.bytes))); let sk_array = to_array(sk_input); - let domain = OrchardDomain::for_nullifier(*action.nullifier()); + let domain = OrchardDomain::for_action(&action); let dec_sk = SpendingKey::from_bytes(sk_array).unwrap(); let fvk = FullViewingKey::from(&dec_sk); let ivk = if external { @@ -1186,7 +1214,7 @@ pub extern "C" fn rust_wrapper_gen_seed_phrase( out: *mut u8, out_len: &mut usize ){ - let mnemonic = Mnemonic::generate(Count::Words24); + let mnemonic: Mnemonic = Mnemonic::generate(Count::Words24); let seed = mnemonic.phrase().as_bytes().to_vec(); marshall_to_haskell_var(&seed, out, out_len, RW); } @@ -1199,7 +1227,7 @@ pub extern "C" fn rust_wrapper_recover_seed( out_len: &mut usize ){ let phrase: String = marshall_from_haskell_var(input, input_len, RW); - let mnemonic = Mnemonic::from_phrase(phrase); + let mnemonic = >::from_phrase(phrase); match mnemonic { Ok(m) => { let s = m.to_seed("").to_vec(); @@ -1456,6 +1484,34 @@ pub extern "C" fn rust_wrapper_update_sapling_witness( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_frontier( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); + //let comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); + let frontier: Frontier = comm_tree.to_frontier(); + match frontier.value() { + Some(f1) => { + let (pos, leaf, omm) = f1.clone().into_parts(); + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + marshall_to_haskell_var(&f, out, out_len, RW); + }, + None => { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + marshall_to_haskell_var(&f0, out, out_len, RW); + } + } +} + + + + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( tree: *const u8, @@ -1465,37 +1521,23 @@ pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( out: *mut u8, out_len: &mut usize ){ - let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); - let tree_reader = Cursor::new(tree_in); - let ct = read_commitment_tree::>, 32>(tree_reader); - match ct { - Ok(mut comm_tree) => { - let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); - let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); - if orchard_note_comm.is_some().into() { - let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); - comm_tree.append(n); - let mut out_bytes: Vec = Vec::new(); - let result = write_commitment_tree(&comm_tree, &mut out_bytes ); - match result { - Ok(()) => { - let h = Hhex { bytes: out_bytes}; - marshall_to_haskell_var(&h, out, out_len, RW); - }, - Err(_e) => { - let h0 = Hhex { bytes: vec![0]}; - marshall_to_haskell_var(&h0, out, out_len, RW); - } - } - } else { - let h0 = Hhex { bytes: vec![0]}; - marshall_to_haskell_var(&h0, out, out_len, RW); - } - }, - Err(_e) => { - let h0 = Hhex { bytes: vec![0]}; - marshall_to_haskell_var(&h0, out, out_len, RW); - } + let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); + //let tree_reader = Cursor::new(tree_in); + //let mut comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); + //let mut comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); + let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); + let mut comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap(); + let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); + let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); + if orchard_note_comm.is_some().into() { + let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); + comm_tree.append(n); + let (pos, leaf, omm) = comm_tree.into_parts(); + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + marshall_to_haskell_var(&f, out, out_len, RW); + } else { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1726,7 +1768,7 @@ pub extern "C" fn rust_wrapper_create_transaction( if o_in.sk.len() > 1 { let sp_key = SpendingKey::from_bytes(o_in.sk[0..32].try_into().unwrap()).unwrap(); let pay_addr = OrchardAddress::from_raw_address_bytes(&to_array(o_in.note.recipient)).unwrap(); - let rho = Nullifier::from_bytes(&to_array(o_in.note.rho)).unwrap(); + let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); let val = NoteValue::from_raw(o_in.note.note); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index bc75ee4..884d0e6 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -240,9 +240,16 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree - { toBorshVar* `BS.ByteString'& + { toBorshVar* `OrchardFrontier'& , toBorshVar* `BS.ByteString'& - , getVarBuffer `Buffer HexString'& + , getVarBuffer `Buffer OrchardFrontier'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_read_orchard_frontier as rustWrapperReadOrchardFrontier + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer OrchardFrontier'& } -> `()' #} diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index d975c2a..a4ef75a 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -24,6 +24,7 @@ import C.Zcash , rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecodeSK , rustWrapperReadOrchardCommitmentTree + , rustWrapperReadOrchardFrontier , rustWrapperReadOrchardPosition , rustWrapperReadOrchardWitness , rustWrapperUADecode @@ -194,21 +195,29 @@ decryptOrchardActionSK sk scope oa = withPureBorshVarBuffer $ rustWrapperOrchardNoteDecodeSK (getBytes sk) oa (scope == External) --- | Update a Orchard commitment tree -updateOrchardCommitmentTree :: - OrchardCommitmentTree -- ^ the base tree - -> HexString -- ^ the new note commitment - -> Maybe OrchardCommitmentTree -updateOrchardCommitmentTree tree cmx = - if BS.length (hexBytes updatedTree) > 1 - then Just $ OrchardCommitmentTree updatedTree +getOrchardFrontier :: OrchardCommitmentTree -> Maybe OrchardFrontier +getOrchardFrontier tree = + if of_pos updatedTree > 1 + then Just updatedTree else Nothing where updatedTree = withPureBorshVarBuffer $ - rustWrapperReadOrchardCommitmentTree - (hexBytes $ orchTree tree) - (hexBytes cmx) + rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree + +-- | Update a Orchard commitment tree +updateOrchardCommitmentTree :: + OrchardFrontier -- ^ the base tree + -> HexString -- ^ the new note commitment + -> Maybe OrchardFrontier +updateOrchardCommitmentTree tree cmx = + if of_pos updatedTree > 1 + then Just updatedTree + else Nothing + where + updatedTree = + withPureBorshVarBuffer $ + rustWrapperReadOrchardCommitmentTree tree (hexBytes cmx) -- | Get the Orchard incremental witness from a commitment tree getOrchardWitness :: OrchardCommitmentTree -> Maybe OrchardWitness diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 1647b42..0fc44c3 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -708,6 +708,15 @@ newtype OrchardCommitmentTree = OrchardCommitmentTree { orchTree :: HexString } deriving (Eq, Prelude.Show, Read) +data OrchardFrontier = OrchardFrontier + { of_pos :: !Int64 + , of_leaf :: !HexString + , of_ommers :: ![BS.ByteString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardFrontier + -- | Type for a Sapling incremental witness newtype OrchardWitness = OrchardWitness { orchWit :: HexString diff --git a/test/Spec.hs b/test/Spec.hs index ac4581e..ac744cb 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -922,7 +922,7 @@ main = do getSaplingNotePosition <$> (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1) p `shouldBe` Just 129405 - describe "Orchard commitment trees" $ do + {- describe "Orchard commitment trees" $ do let tree = OrchardCommitmentTree $ hexString @@ -942,7 +942,7 @@ main = do let p = getOrchardNotePosition <$> (getOrchardWitness =<< updateOrchardCommitmentTree tree cmx) - p `shouldBe` Just 39432 + p `shouldBe` Just 39432 -} describe "Extract Sapling Address - UA Valid" $ do let sr = getSaplingFromUA @@ -1148,6 +1148,43 @@ main = do Just addr -> do let eadr = decodeExchangeAddress (E.encodeUtf8 addr) eadr `shouldNotBe` Nothing + describe "Tree updates" $ do + it "Orchard" $ do + let tree = + OrchardCommitmentTree $ + hexString + "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" + let cmx1 = + hexString + "1712ead46028d4349e234abf59e94e0640fe7a0829e2e2e17e1a931631810400" + let cmx2 = + hexString + "39f5ad39817fb432fa07c5feb3a957189fbe7662a4b5555ca95093b6d853cf07" + let cmx3 = + hexString + "84f7fbc4b9f87215c653078d7fdd90756c3ba370c745065167da9eb73a65a83f" + let cmx4 = + hexString + "e55ad64e1ea2b261893fdea6ad0509b66e5f62d3142f351298c7135c4498d429" + let finalTree = + getOrchardFrontier $ + OrchardCommitmentTree $ + hexString + "0184f7fbc4b9f87215c653078d7fdd90756c3ba370c745065167da9eb73a65a83f01e55ad64e1ea2b261893fdea6ad0509b66e5f62d3142f351298c7135c4498d4291f0000014b1a76d3820087b26cd087ca84e17f3067a25ebed82ad23a93fa485affb5530b01ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" + case getOrchardFrontier tree of + Nothing -> assertFailure "Failed to get frontier" + Just t1 -> + case updateOrchardCommitmentTree t1 cmx1 of + Nothing -> assertFailure "Failed to update frontier with cmx" + Just t2 -> + case updateOrchardCommitmentTree t2 cmx2 of + Nothing -> assertFailure "Failed to update frontier with cmx" + Just t3 -> + case updateOrchardCommitmentTree t3 cmx3 of + Nothing -> + assertFailure "Failed to update frontier with cmx" + Just t4 -> + updateOrchardCommitmentTree t4 cmx4 `shouldBe` finalTree describe "Witness updates" $ do it "Sapling" $ do let wit = diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index a3288b5..bcec9de 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.0.2 +version: 0.7.1.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 38e4131daaebd45bfe005e753b0b5716a4481d89 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 30 Sep 2024 13:18:47 -0500 Subject: [PATCH 13/72] feat!: update Orchard witness calculation Now uses Frontier --- librustzcash-wrapper/src/lib.rs | 7 ++++--- src/C/Zcash.chs | 2 +- src/ZcashHaskell/Orchard.hs | 6 ++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 63c4d2b..6034424 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1548,9 +1548,10 @@ pub extern "C" fn rust_wrapper_read_orchard_witness( out: *mut u8, out_len: &mut usize ){ - let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); - let tree_reader = Cursor::new(tree_in); - let ct: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); + let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); + let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); + let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap(); + let ct: CommitmentTree = CommitmentTree::from_frontier(&frontier); let inc_wit = IncrementalWitness::from_tree(ct); let mut out_bytes: Vec = Vec::new(); let result = write_incremental_witness(&inc_wit, &mut out_bytes); diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 884d0e6..beb11e2 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -255,7 +255,7 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_read_orchard_witness as rustWrapperReadOrchardWitness - { toBorshVar* `BS.ByteString'& + { toBorshVar* `OrchardFrontier'& , getVarBuffer `Buffer HexString'& } -> `()' diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index a4ef75a..1bb7167 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -220,15 +220,13 @@ updateOrchardCommitmentTree tree cmx = rustWrapperReadOrchardCommitmentTree tree (hexBytes cmx) -- | Get the Orchard incremental witness from a commitment tree -getOrchardWitness :: OrchardCommitmentTree -> Maybe OrchardWitness +getOrchardWitness :: OrchardFrontier -> Maybe OrchardWitness getOrchardWitness tree = if BS.length (hexBytes wit) > 1 then Just $ OrchardWitness wit else Nothing where - wit = - withPureBorshVarBuffer $ - rustWrapperReadOrchardWitness (hexBytes $ orchTree tree) + wit = withPureBorshVarBuffer $ rustWrapperReadOrchardWitness tree -- | Get the Sapling note position from a witness getOrchardNotePosition :: OrchardWitness -> Integer -- 2.34.1 From 3969490283420af0bb193590a1e5d4b6828cc2f9 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 30 Sep 2024 14:50:54 -0500 Subject: [PATCH 14/72] feat: Use the notes to determine anchors --- librustzcash-wrapper/src/lib.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 6034424..10e8df0 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1702,14 +1702,24 @@ pub extern "C" fn rust_wrapper_create_transaction( let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); let orch_wit_reader = Cursor::new(orch_wit_in); let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); - let orch_anchor = match orch_iw { - Ok(o_iw) => { - Some(OrchardAnchor::from(o_iw.root())) - }, - Err(_e) => { + let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); + //let orch_anchor = match orch_iw { + //Ok(o_iw) => { + //Some(OrchardAnchor::from(o_iw.root())) + //}, + //Err(_e) => { + //None + //} + //}; + let orch_anchor = + if orch_input.is_empty() { None - } - }; + } else { + let oi = &orch_input[0]; + let wit_reader = Cursor::new(&oi.iw); + let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); + Some(OrchardAnchor::from(iw.root())) + }; let build_config = BuildConfig::Standard {sapling_anchor: sap_anchor, orchard_anchor: orch_anchor}; let mut main_builder = Builder::new(MainNetwork, BlockHeight::from(bl_height), build_config); let mut test_builder = Builder::new(TestNetwork, BlockHeight::from(bl_height), build_config); @@ -1764,7 +1774,6 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } - let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); for o_in in orch_input { if o_in.sk.len() > 1 { let sp_key = SpendingKey::from_bytes(o_in.sk[0..32].try_into().unwrap()).unwrap(); -- 2.34.1 From 5a08c802854eebd1b5b4d8e7e1e2dad574b06100 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 11 Oct 2024 08:17:02 -0500 Subject: [PATCH 15/72] feat: add `toJSON` for `BlockResponse` --- CHANGELOG.md | 21 +++++++++++++++++++++ cabal.project.freeze | 23 ++++++++++++----------- src/ZcashHaskell/Types.hs | 10 ++++++++++ zcash-haskell.cabal | 2 +- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a68512..1feacf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.1.1] + +### Added + +- `ToJSON` instance for `BlockResponse` + +### Changed + +- Updated libraries: + - conduit + - data-fix + - happy + - happy-lib + - http-conduit + - iproute + - mono-traversable + - network + - secp256k1-haskell + - strict + - typed-process + ## [0.7.1.0] ### Added diff --git a/cabal.project.freeze b/cabal.project.freeze index b5bd80f..206c446 100644 --- a/cabal.project.freeze +++ b/cabal.project.freeze @@ -54,7 +54,7 @@ constraints: any.Cabal ==3.10.3.0, any.colour ==2.3.6, any.comonad ==5.0.8, comonad +containers +distributive +indexed-traversable, - any.conduit ==1.3.5, + any.conduit ==1.3.6, any.conduit-extra ==1.3.6, any.containers ==0.6.7, any.contravariant ==1.5.5, @@ -74,7 +74,7 @@ constraints: any.Cabal ==3.10.3.0, any.data-default-instances-containers ==0.0.1, any.data-default-instances-dlist ==0.0.1, any.data-default-instances-old-locale ==0.0.1, - any.data-fix ==0.3.3, + any.data-fix ==0.3.4, any.deepseq ==1.4.8.1, any.directory ==1.3.8.4, any.distributive ==0.6.2.1, @@ -93,7 +93,8 @@ constraints: any.Cabal ==3.10.3.0, any.ghc-boot-th ==9.6.5, any.ghc-prim ==0.10.0, any.half ==0.3.1, - any.happy ==1.20.1.1, + any.happy ==2.0.2, + any.happy-lib ==2.0.2, any.hashable ==1.4.7.0, hashable -arch-native +integer-gmp -random-initial-seed, any.haskell-lexer ==1.1.1, @@ -109,7 +110,7 @@ constraints: any.Cabal ==3.10.3.0, any.http-client ==0.7.17, http-client +network-uri, any.http-client-tls ==0.3.6.3, - any.http-conduit ==2.3.8.3, + any.http-conduit ==2.3.9, http-conduit +aeson, any.http-types ==0.12.4, any.indexed-traversable ==0.1.4, @@ -118,16 +119,16 @@ constraints: any.Cabal ==3.10.3.0, any.integer-gmp ==1.1, any.integer-logarithms ==1.0.3.1, integer-logarithms -check-bounds +integer-gmp, - any.iproute ==1.7.12, + any.iproute ==1.7.14, any.language-c ==0.9.3, language-c -allwarnings +iecfpextension +usebytestrings, any.memory ==0.18.0, memory +support_bytestring +support_deepseq, any.mime-types ==0.1.2.0, - any.mono-traversable ==1.0.17.0, + any.mono-traversable ==1.0.20.0, any.mtl ==2.3.1, any.murmur3 ==1.0.5, - any.network ==3.2.1.0, + any.network ==3.2.4.0, network -devel, any.network-uri ==2.6.4.2, any.old-locale ==1.0.0.7, @@ -150,7 +151,7 @@ constraints: any.Cabal ==3.10.3.0, any.safe ==0.3.21, any.scientific ==0.3.8.0, scientific -integer-simple, - any.secp256k1-haskell ==1.2.0, + any.secp256k1-haskell ==1.4.0, any.semialign ==1.3.1, semialign +semigroupoids, any.semigroupoids ==6.0.1, @@ -165,7 +166,7 @@ constraints: any.Cabal ==3.10.3.0, any.stm ==2.5.1.0, any.streaming-commons ==0.2.2.6, streaming-commons -use-bytestring-builder, - any.strict ==0.5, + any.strict ==0.5.1, any.string-conversions ==0.4.0.1, any.tagged ==0.8.8, tagged +deepseq +transformers, @@ -185,7 +186,7 @@ constraints: any.Cabal ==3.10.3.0, any.transformers ==0.6.1.0, any.transformers-compat ==0.7.2, transformers-compat -five +five-three -four +generic-deriving +mtl -three -two, - any.typed-process ==0.2.11.1, + any.typed-process ==0.2.12.0, any.unix ==2.8.4.0, any.unix-time ==0.4.15, any.unliftio-core ==0.2.1.0, @@ -204,4 +205,4 @@ constraints: any.Cabal ==3.10.3.0, any.witherable ==0.5, any.zlib ==0.7.1.0, zlib -bundled-c-zlib +non-blocking-ffi +pkg-config -index-state: hackage.haskell.org 2024-07-01T20:28:56Z +index-state: hackage.haskell.org 2024-10-11T12:55:31Z diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 0fc44c3..ebf3dbf 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -273,6 +273,16 @@ instance FromJSON BlockResponse where hash <- obj .: "hash" pure $ BlockResponse hash c h (fromMaybe 0 t) txs +instance ToJSON BlockResponse where + toJSON (BlockResponse h c ht t txs) = + object + [ "hash" .= h + , "confirmations" .= c + , "height" .= ht + , "time" .= t + , "tx" .= txs + ] + -- | Type to represent response from the `zcashd` RPC `getrawtransaction` data RawTxResponse = RawTxResponse { rt_id :: !HexString diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index bcec9de..babe1f3 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.1.0 +version: 0.7.1.1 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 3203c7e8ffefcb788caf5801425af344a85922bc Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 18 Oct 2024 08:47:52 -0500 Subject: [PATCH 16/72] feat: implement Frontier for Sapling witnesses --- librustzcash-wrapper/src/lib.rs | 109 ++++++++++++++++++++++++++------ src/C/Zcash.chs | 11 +++- src/ZcashHaskell/Sapling.hs | 31 +++++---- src/ZcashHaskell/Types.hs | 9 +++ 4 files changed, 128 insertions(+), 32 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 10e8df0..a0e98b6 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1369,6 +1369,31 @@ pub extern "C" fn rust_wrapper_bech32_encode( marshall_to_haskell_var(&string, out, out_len, RW); } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_sapling_frontier( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); + //let comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); + let frontier: Frontier = comm_tree.to_frontier(); + match frontier.value() { + Some(f1) => { + let (pos, leaf, omm) = f1.clone().into_parts(); + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + marshall_to_haskell_var(&f, out, out_len, RW); + }, + None => { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + marshall_to_haskell_var(&f0, out, out_len, RW); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_sapling_commitment_tree( tree: *const u8, @@ -1687,21 +1712,31 @@ pub extern "C" fn rust_wrapper_create_transaction( build: bool, out: *mut u8, out_len: &mut usize){ - let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); - let sap_wit_reader = Cursor::new(sap_wit_in); - let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); - let sap_anchor = match sap_iw { - Ok(s_iw) => { - Some(SaplingAnchor::from(s_iw.root())) - }, - Err(_e) => { + //let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); + //let sap_wit_reader = Cursor::new(sap_wit_in); + //let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); + let sap_input: Vec = marshall_from_haskell_var(s_input, s_input_len, RW); + let sap_anchor = + if sap_input.is_empty() { None - } - }; + } else { + let si = &sap_input[0]; + let swit_reader = Cursor::new(&si.iw); + let iw: IncrementalWitness = read_incremental_witness(swit_reader).unwrap(); + Some(SaplingAnchor::from(iw.root())) + }; + //let sap_anchor = match sap_iw { + //Ok(s_iw) => { + //Some(SaplingAnchor::from(s_iw.root())) + //}, + //Err(_e) => { + //None + //} + //}; //println!("{:?}", sap_anchor); - let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); - let orch_wit_reader = Cursor::new(orch_wit_in); - let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); + //let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); + //let orch_wit_reader = Cursor::new(orch_wit_in); + //let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); //let orch_anchor = match orch_iw { //Ok(o_iw) => { @@ -1746,7 +1781,6 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } - let sap_input: Vec = marshall_from_haskell_var(s_input, s_input_len, RW); for s_in in sap_input { if s_in.sk.len() > 1 { let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk); @@ -1763,13 +1797,32 @@ pub extern "C" fn rust_wrapper_create_transaction( let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); let merkle_path = iw.path().unwrap(); if net { - let _mb = main_builder.add_sapling_spend::(&sk, note, merkle_path).unwrap(); + let mb = main_builder.add_sapling_spend::(&sk, note, merkle_path); + match mb { + Ok(()) => { + continue; + }, + Err(_e) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_sapling_spend::(&sk, note, merkle_path).unwrap(); + let tb = test_builder.add_sapling_spend::(&sk, note, merkle_path); + match tb { + Ok(()) => { + continue; + }, + Err(_e) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, Err(_e) => { - continue; + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); } } } @@ -1786,9 +1839,27 @@ pub extern "C" fn rust_wrapper_create_transaction( let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); let merkle_path = OrchardMerklePath::from(iw.path().unwrap()); if net { - let _mb = main_builder.add_orchard_spend::(&sp_key, note, merkle_path).unwrap(); + let mb = main_builder.add_orchard_spend::(&sp_key, note, merkle_path); + match mb { + Ok(()) => { + continue; + }, + Err(_e) => { + let x = Hhex {bytes: vec![7]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_orchard_spend::(&sp_key, note, merkle_path).unwrap(); + let tb = test_builder.add_orchard_spend::(&sp_key, note, merkle_path); + match tb { + Ok(()) => { + continue; + }, + Err(_e) => { + let x = Hhex {bytes: vec![7]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } } } diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index beb11e2..ab4bd54 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -204,9 +204,9 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_read_sapling_commitment_tree as rustWrapperReadSaplingCommitmentTree - { toBorshVar* `BS.ByteString'& + { toBorshVar* `SaplingFrontier'& , toBorshVar* `BS.ByteString'& - , getVarBuffer `Buffer HexString'& + , getVarBuffer `Buffer SaplingFrontier'& } -> `()' #} @@ -232,6 +232,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_sapling_frontier as rustWrapperReadSaplingFrontier + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer SaplingFrontier'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_decode_sapling_address as rustWrapperDecodeSaplingAddress { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer (BS.ByteString)'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index f145c91..4b7c286 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -21,6 +21,7 @@ import C.Zcash ( rustWrapperDecodeSaplingAddress , rustWrapperIsShielded , rustWrapperReadSaplingCommitmentTree + , rustWrapperReadSaplingFrontier , rustWrapperReadSaplingPosition , rustWrapperReadSaplingWitness , rustWrapperSaplingCheck @@ -184,21 +185,29 @@ genSaplingInternalAddress sk = res = withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk) --- | Update a Sapling commitment tree -updateSaplingCommitmentTree :: - SaplingCommitmentTree -- ^ the base tree - -> HexString -- ^ the new note commitment - -> Maybe SaplingCommitmentTree -updateSaplingCommitmentTree tree cmu = - if BS.length (hexBytes updatedTree) > 1 - then Just $ SaplingCommitmentTree updatedTree +getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier +getSaplingFrontier tree = + if sf_pos updatedTree > 1 + then Just updatedTree else Nothing where updatedTree = withPureBorshVarBuffer $ - rustWrapperReadSaplingCommitmentTree - (hexBytes $ sapTree tree) - (hexBytes cmu) + rustWrapperReadSaplingFrontier $ toBytes $ sapTree tree + +-- | Update a Sapling commitment tree +updateSaplingCommitmentTree :: + SaplingFrontier -- ^ the base tree + -> HexString -- ^ the new note commitment + -> Maybe SaplingFrontier +updateSaplingCommitmentTree tree cmu = + if sf_pos updatedTree > 1 + then Just updatedTree + else Nothing + where + updatedTree = + withPureBorshVarBuffer $ + rustWrapperReadSaplingCommitmentTree tree (hexBytes cmu) -- | Get the Sapling incremental witness from a commitment tree getSaplingWitness :: SaplingCommitmentTree -> Maybe SaplingWitness diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index ebf3dbf..8105d30 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -611,6 +611,15 @@ newtype SaplingCommitmentTree = SaplingCommitmentTree { sapTree :: HexString } deriving (Eq, Prelude.Show, Read) +data SaplingFrontier = SaplingFrontier + { sf_pos :: !Int64 + , sf_leaf :: !HexString + , sf_ommers :: ![BS.ByteString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct SaplingFrontier + -- | Type for a Sapling incremental witness newtype SaplingWitness = SaplingWitness { sapWit :: HexString -- 2.34.1 From 96cfe3a52a0fc2c6910ea193daa51dc839857f0a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 18 Oct 2024 09:43:02 -0500 Subject: [PATCH 17/72] feat: use `SaplingFrontier` for witnesses --- librustzcash-wrapper/src/lib.rs | 7 ++++--- src/C/Zcash.chs | 2 +- src/ZcashHaskell/Sapling.hs | 6 ++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a0e98b6..3209737 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1445,9 +1445,10 @@ pub extern "C" fn rust_wrapper_read_sapling_witness( out: *mut u8, out_len: &mut usize ){ - let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); - let tree_reader = Cursor::new(tree_in); - let ct: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); + let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); + let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap(); + let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap(); + let ct: CommitmentTree = CommitmentTree::from_frontier(&frontier); let inc_wit = IncrementalWitness::from_tree(ct); let mut out_bytes: Vec = Vec::new(); let result = write_incremental_witness(&inc_wit, &mut out_bytes); diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index ab4bd54..71c73e5 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -212,7 +212,7 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_read_sapling_witness as rustWrapperReadSaplingWitness - { toBorshVar* `BS.ByteString'& + { toBorshVar* `SaplingFrontier'& , getVarBuffer `Buffer HexString'& } -> `()' diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index 4b7c286..e15bf4f 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -210,15 +210,13 @@ updateSaplingCommitmentTree tree cmu = rustWrapperReadSaplingCommitmentTree tree (hexBytes cmu) -- | Get the Sapling incremental witness from a commitment tree -getSaplingWitness :: SaplingCommitmentTree -> Maybe SaplingWitness +getSaplingWitness :: SaplingFrontier -> Maybe SaplingWitness getSaplingWitness tree = if BS.length (hexBytes wit) > 1 then Just $ SaplingWitness wit else Nothing where - wit = - withPureBorshVarBuffer $ - rustWrapperReadSaplingWitness (hexBytes $ sapTree tree) + wit = withPureBorshVarBuffer $ rustWrapperReadSaplingWitness tree -- | Get the Sapling note position from a witness getSaplingNotePosition :: SaplingWitness -> Integer -- 2.34.1 From 5a9ed11c258170855fb17c9c2bdd8944b550f4b0 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 18 Oct 2024 12:25:30 -0500 Subject: [PATCH 18/72] fix(rust): SaplingFrontier marshalling --- librustzcash-wrapper/src/lib.rs | 46 ++++++++++----------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 3209737..92e9319 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1403,39 +1403,21 @@ pub extern "C" fn rust_wrapper_read_sapling_commitment_tree( out: *mut u8, out_len: &mut usize ){ - let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); - let tree_reader = Cursor::new(tree_in); - let mut ct = read_commitment_tree::>, SAPLING_DEPTH>(tree_reader); - match ct { - Ok(mut comm_tree) => { - let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); - let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in)); - if sap_note_comm.is_some().into() { - let n = Node::from_cmu(&sap_note_comm.unwrap()); - comm_tree.append(n); - let mut out_bytes: Vec = Vec::new(); - let result = write_commitment_tree(&comm_tree, &mut out_bytes ); - match result { - Ok(()) => { - let h = Hhex { bytes: out_bytes}; - marshall_to_haskell_var(&h, out, out_len, RW); - }, - Err(_e) => { - let h0 = Hhex { bytes: vec![0]}; - marshall_to_haskell_var(&h0, out, out_len, RW); - } - } - } else { - let h0 = Hhex { bytes: vec![0]}; - marshall_to_haskell_var(&h0, out, out_len, RW); - } - }, - Err(_e) => { - let h0 = Hhex { bytes: vec![0]}; - marshall_to_haskell_var(&h0, out, out_len, RW); - } + let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); + let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap(); + let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap(); + let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); + let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in)); + if sap_note_comm.is_some().into() { + let n = Node::from_cmu(&sap_note_comm.unwrap()); + comm_tree.append(n); + let (pos, leaf, omm) = comm_tree.into_parts(); + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + marshall_to_haskell_var(&f, out, out_len, RW); + } else { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + marshall_to_haskell_var(&f0, out, out_len, RW); } - } #[no_mangle] -- 2.34.1 From 4608577c417c1fbfde54bcd502673e413e1f95a5 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 18 Oct 2024 14:39:05 -0500 Subject: [PATCH 19/72] docs: version bump --- CHANGELOG.md | 6 ++++++ zcash-haskell.cabal | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1feacf7..3bdb344 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.2.0] + +### Changed + +- Modified Sapling commitment trees to use Frontier + ## [0.7.1.1] ### Added diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index babe1f3..edad0f8 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.1.1 +version: 0.7.2.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 004e2c85cd2dbb5f59ba3ee6b06937596bc49c7a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sun, 27 Oct 2024 06:42:04 -0500 Subject: [PATCH 20/72] feat: creation of Orchard commitment nodes --- CHANGELOG.md | 11 ++ librustzcash-wrapper/src/lib.rs | 138 ++++++++++++++++++++---- src/C/Zcash.chs | 30 ++++++ src/ZcashHaskell/Orchard.hs | 36 ++++++- src/ZcashHaskell/Types.hs | 4 +- test/Spec.hs | 181 +++++++++++++++++--------------- zcash-haskell.cabal | 2 +- 7 files changed, 292 insertions(+), 110 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bdb344..9eed57f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.3.0] + +### Added + +- Function to create an Orchard hash from a note commitment +- Function to hash Orchard commitments + +### Changed + +- Modified frontiers to use `HexString` for ommers + ## [0.7.2.0] ### Changed diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 92e9319..e7b5d04 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -30,6 +30,8 @@ use secp256k1::SecretKey; use jubjub::Fr; use incrementalmerkletree::{ + Hashable, + Level, Position, frontier::{ CommitmentTree, @@ -92,7 +94,8 @@ use zcash_primitives::{ write_commitment_tree, read_incremental_witness, write_incremental_witness, - read_frontier_v1 + read_frontier_v1, + read_nonempty_frontier_v1 }, legacy::{ Script, @@ -697,7 +700,7 @@ impl ToHaskell for Hsvk { pub struct Hfrontier { position: u64, leaf: Hhex, - ommers: Vec> + ommers: Vec } impl ToHaskell for Hfrontier { @@ -1384,11 +1387,11 @@ pub extern "C" fn rust_wrapper_read_sapling_frontier( match frontier.value() { Some(f1) => { let (pos, leaf, omm) = f1.clone().into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; marshall_to_haskell_var(&f, out, out_len, RW); }, None => { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1405,17 +1408,17 @@ pub extern "C" fn rust_wrapper_read_sapling_commitment_tree( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap(); - let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap(); + let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in)); if sap_note_comm.is_some().into() { let n = Node::from_cmu(&sap_note_comm.unwrap()); comm_tree.append(n); let (pos, leaf, omm) = comm_tree.into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; marshall_to_haskell_var(&f, out, out_len, RW); } else { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1429,7 +1432,7 @@ pub extern "C" fn rust_wrapper_read_sapling_witness( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap(); - let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap(); + let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let ct: CommitmentTree = CommitmentTree::from_frontier(&frontier); let inc_wit = IncrementalWitness::from_tree(ct); let mut out_bytes: Vec = Vec::new(); @@ -1501,23 +1504,114 @@ pub extern "C" fn rust_wrapper_read_orchard_frontier( ){ let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); let tree_reader = Cursor::new(tree_in); - let comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); - //let comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); - let frontier: Frontier = comm_tree.to_frontier(); - match frontier.value() { - Some(f1) => { - let (pos, leaf, omm) = f1.clone().into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; - marshall_to_haskell_var(&f, out, out_len, RW); + let comm_tree = read_commitment_tree(tree_reader); + //let comm_tree = read_frontier_v1(tree_reader); + //let frontier: Frontier = comm_tree.to_frontier(); + match comm_tree { + Ok::, _>(f1) => { + let frontier = f1.to_frontier(); + match frontier.value() { + Some(f2) => { + let (pos, leaf, omm) = f2.clone().into_parts(); + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; + marshall_to_haskell_var(&f, out, out_len, RW); + }, + None => { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; + marshall_to_haskell_var(&f0, out, out_len, RW); + } + } }, - None => { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + Err(_e) => { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_tree_anchor( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); + let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); + let comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); + let root = comm_tree.root(None); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_witness_anchor( + wit: *const u8, + wit_len: usize, + out: *mut u8, + out_len: &mut usize + ) { + let wit_in: Vec = marshall_from_haskell_var(wit, wit_len, RW); + let wit_reader = Cursor::new(wit_in); + let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); + let root = iw.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_node( + cmx: *const u8, + cmx_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let node_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); + let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); + if orchard_note_comm.is_some().into() { + let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec()}; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_combine_orchard_nodes( + level: u8, + left: *const u8, + left_len: usize, + right: *const u8, + right_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let left_in: Vec = marshall_from_haskell_var(left, left_len, RW); + let right_in: Vec = marshall_from_haskell_var(right, right_len, RW); + let left_node = MerkleHashOrchard::from_bytes(&to_array(left_in)); + if left_node.is_some().into() { + if right_in.len() > 1 { + let right_node = MerkleHashOrchard::from_bytes(&to_array(right_in)); + if right_node.is_some().into() { + let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &right_node.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } else { + let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &MerkleHashOrchard::empty_leaf()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} #[no_mangle] @@ -1534,17 +1628,17 @@ pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( //let mut comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); //let mut comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let mut comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap(); + let mut comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); if orchard_note_comm.is_some().into() { let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); comm_tree.append(n); let (pos, leaf, omm) = comm_tree.into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; marshall_to_haskell_var(&f, out, out_len, RW); } else { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1558,7 +1652,7 @@ pub extern "C" fn rust_wrapper_read_orchard_witness( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap(); + let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let ct: CommitmentTree = CommitmentTree::from_frontier(&frontier); let inc_wit = IncrementalWitness::from_tree(ct); let mut out_bytes: Vec = Vec::new(); diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 71c73e5..da2f86b 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -246,6 +246,36 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_combine_orchard_nodes as rustWrapperCombineOrchardNodes + { `Int8' + , toBorshVar* `BS.ByteString'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_read_orchard_tree_anchor as rustWrapperReadOrchardTreeAnchor + { toBorshVar* `OrchardFrontier'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_read_orchard_witness_anchor as rustWrapperReadOrchardWitnessAnchor + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree { toBorshVar* `OrchardFrontier'& , toBorshVar* `BS.ByteString'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 1bb7167..79043ea 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -18,15 +18,19 @@ module ZcashHaskell.Orchard where import C.Zcash - ( rustWrapperGenOrchardReceiver + ( rustWrapperCombineOrchardNodes + , rustWrapperGenOrchardReceiver , rustWrapperGenOrchardSpendKey , rustWrapperOrchardCheck , rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecodeSK , rustWrapperReadOrchardCommitmentTree , rustWrapperReadOrchardFrontier + , rustWrapperReadOrchardNode , rustWrapperReadOrchardPosition + , rustWrapperReadOrchardTreeAnchor , rustWrapperReadOrchardWitness + , rustWrapperReadOrchardWitnessAnchor , rustWrapperUADecode , rustWrapperUfvkDecode , rustWrapperUpdateOrchardWitness @@ -205,6 +209,15 @@ getOrchardFrontier tree = withPureBorshVarBuffer $ rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree +getOrchardTreeAnchor :: OrchardFrontier -> HexString +getOrchardTreeAnchor tree = + withPureBorshVarBuffer $ rustWrapperReadOrchardTreeAnchor tree + +getOrchardWitnessAnchor :: OrchardWitness -> HexString +getOrchardWitnessAnchor wit = + withPureBorshVarBuffer $ + rustWrapperReadOrchardWitnessAnchor $ toBytes $ orchWit wit + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree @@ -244,6 +257,27 @@ updateOrchardWitness wit cmus = (map toBytes cmus) else wit +getOrchardNodeValue :: BS.ByteString -> Maybe HexString +getOrchardNodeValue cmx = + if BS.length (hexBytes n) > 1 + then Just n + else Nothing + where + n = withPureBorshVarBuffer $ rustWrapperReadOrchardNode cmx + +combineOrchardNodes :: Integer -> HexString -> HexString -> Maybe HexString +combineOrchardNodes level n1 n2 = + if BS.length (hexBytes r) > 1 + then Just r + else Nothing + where + r = + withPureBorshVarBuffer $ + rustWrapperCombineOrchardNodes + (fromIntegral level) + (toBytes n1) + (toBytes n2) + -- | Parse a potential Zcash address parseAddress :: BS.ByteString -> Maybe ValidAddress parseAddress t = diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 8105d30..324216f 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -614,7 +614,7 @@ newtype SaplingCommitmentTree = SaplingCommitmentTree data SaplingFrontier = SaplingFrontier { sf_pos :: !Int64 , sf_leaf :: !HexString - , sf_ommers :: ![BS.ByteString] + , sf_ommers :: ![HexString] } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (Data.Structured.Show) @@ -730,7 +730,7 @@ newtype OrchardCommitmentTree = OrchardCommitmentTree data OrchardFrontier = OrchardFrontier { of_pos :: !Int64 , of_leaf :: !HexString - , of_ommers :: ![BS.ByteString] + , of_ommers :: ![HexString] } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (Data.Structured.Show) diff --git a/test/Spec.hs b/test/Spec.hs index ac744cb..0547e16 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -55,6 +55,7 @@ import ZcashHaskell.Sapling , genSaplingInternalAddress , genSaplingPaymentAddress , genSaplingSpendingKey + , getSaplingFrontier , getSaplingNotePosition , getSaplingWitness , getShieldedOutputs @@ -73,6 +74,7 @@ import ZcashHaskell.Types , OrchardAction(..) , OrchardBundle(..) , OrchardCommitmentTree(..) + , OrchardFrontier(..) , OrchardSpendingKey(..) , OrchardWitness(..) , Phrase(..) @@ -88,6 +90,7 @@ import ZcashHaskell.Types , SaplingAddress(..) , SaplingBundle(..) , SaplingCommitmentTree(..) + , SaplingFrontier(..) , SaplingReceiver(..) , SaplingSpendingKey(..) , SaplingWitness(..) @@ -895,33 +898,35 @@ main = do Just t' -> do let tb = zt_tBundle t' show tb `shouldNotBe` "" - describe "Sapling commitment trees" $ do - let tree = - SaplingCommitmentTree $ - hexString - "01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - let cmu1 = - hexString - "45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f" - let cmu2 = - hexString - "426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d" - let tree2 = - hexString - "01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - it "Commitment tree is updated correctly" $ do - let t1 = updateSaplingCommitmentTree tree cmu1 - t1 `shouldNotBe` Nothing - it "Incremental witness is generated" $ do - let t1 = updateSaplingCommitmentTree tree cmu1 - case t1 of - Nothing -> assertFailure "Failed to append node to tree" - Just t -> getSaplingWitness t `shouldNotBe` Nothing - it "Position of note is obtained" $ do - let p = - getSaplingNotePosition <$> - (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1) - p `shouldBe` Just 129405 + {- + -describe "Sapling commitment trees" $ do + - let tree = + - SaplingCommitmentTree $ + - hexString + - "01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + - let cmu1 = + - hexString + - "45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f" + - let cmu2 = + - hexString + - "426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d" + - let tree2 = + - hexString + - "01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + - it "Commitment tree is updated correctly" $ do + - let t1 = updateSaplingCommitmentTree tree cmu1 + - t1 `shouldNotBe` Nothing + - it "Incremental witness is generated" $ do + - let t1 = updateSaplingCommitmentTree tree cmu1 + - case t1 of + - Nothing -> assertFailure "Failed to append node to tree" + - Just t -> getSaplingWitness t `shouldNotBe` Nothing + - it "Position of note is obtained" $ do + - let p = + - getSaplingNotePosition <$> + - (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1) + - p `shouldBe` Just 129405 + -} {- describe "Orchard commitment trees" $ do let tree = OrchardCommitmentTree $ @@ -1061,18 +1066,22 @@ main = do (hexString "97e5f003d16720844ba1bd157688a7697133f4bb4a33a7c91974937a1351d7af56d16d4a10bd196ddda700fcd8be517f8f9e39a17ba0eea235d98450a626be3a998ac31f35e8e082106a31fe94da11d02b73748db4aa519df6bbf25c1d62a2cf0b192c6a486bca2632fee9e4124ce2dba6f3366a14850f6a3b784d863119f52458ed774f8d63105b4f6a3d2e09cc74e3a02ec8386213087b4c849172ded6724a45c9c12744ec4a0f86a29b803b17187df5dd5f90e71d1f3f4578d4e1496e8892") it "Sap output 1" $ do - let pos = - getSaplingNotePosition <$> - (getSaplingWitness =<< - updateSaplingCommitmentTree - tree - (fromText - "fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858")) - case pos of - Nothing -> assertFailure "couldn't get note position" - Just p -> do - let dn = decodeSaplingOutputEsk sk so1 TestNet External p - dn `shouldBe` Nothing + case getSaplingFrontier tree of + Nothing -> assertFailure "failed to read comm tree" + Just tree' -> do + let pos = + sf_pos <$> + updateSaplingCommitmentTree + tree' + (fromText + "fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858") + case pos of + Nothing -> assertFailure "couldn't get note position" + Just p -> do + let dn = + decodeSaplingOutputEsk sk so1 TestNet External $ + fromIntegral p + dn `shouldBe` Nothing it "Sap output 2" $ do case readZebraTransaction txHex2 of Nothing -> assertFailure "Failed to read Tx" @@ -1082,24 +1091,27 @@ main = do Nothing -> assertFailure "Failed to get sapling bundle" Just sB -> do let sOuts = sbOutputs sB - let pos = - getSaplingNotePosition <$> - (getSaplingWitness =<< - updateSaplingCommitmentTree - tree - (fromText - "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")) - case pos of - Nothing -> assertFailure "couldn't get note position" - Just p -> do - let dn = - decodeSaplingOutputEsk - sk - (head . tail $ sOuts) - TestNet - External - p - dn `shouldBe` Nothing + case getSaplingFrontier tree of + Nothing -> assertFailure "Failed to read tree" + Just tree' -> do + let pos = + getSaplingNotePosition <$> + (getSaplingWitness =<< + updateSaplingCommitmentTree + tree' + (fromText + "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")) + case pos of + Nothing -> assertFailure "couldn't get note position" + Just p -> do + let dn = + decodeSaplingOutputEsk + sk + (head . tail $ sOuts) + TestNet + External + p + dn `shouldBe` Nothing it "Decode Sapling Output from Zingo" $ do case readZebraTransaction txHex of Nothing -> assertFailure "Failed to read Tx" @@ -1112,24 +1124,26 @@ main = do Nothing -> assertFailure "Failed to get sapling bundle" Just sB -> do let sOuts = sbOutputs sB - let pos = - getSaplingNotePosition <$> - (getSaplingWitness =<< - updateSaplingCommitmentTree - tree - (fromText - "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")) - case pos of - Nothing -> assertFailure "couldn't get note position" - Just p -> do - let dn = - decodeSaplingOutputEsk - sK' - (head . tail $ sOuts) - MainNet - External - p - dn `shouldNotBe` Nothing + case getSaplingFrontier tree of + Nothing -> assertFailure "failed to read comm tree" + Just tree' -> do + let pos = + sf_pos <$> + updateSaplingCommitmentTree + tree' + (fromText + "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843") + case pos of + Nothing -> assertFailure "couldn't get note position" + Just p -> do + let dn = + decodeSaplingOutputEsk + sK' + (head . tail $ sOuts) + MainNet + External + (fromIntegral p) + dn `shouldNotBe` Nothing describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e" it "Try to generate valid ExchangeAddress from Transparent Address" $ do @@ -1176,15 +1190,14 @@ main = do Just t1 -> case updateOrchardCommitmentTree t1 cmx1 of Nothing -> assertFailure "Failed to update frontier with cmx" - Just t2 -> - case updateOrchardCommitmentTree t2 cmx2 of - Nothing -> assertFailure "Failed to update frontier with cmx" - Just t3 -> - case updateOrchardCommitmentTree t3 cmx3 of - Nothing -> - assertFailure "Failed to update frontier with cmx" - Just t4 -> - updateOrchardCommitmentTree t4 cmx4 `shouldBe` finalTree + Just t2 -> do + case getOrchardWitness t2 of + Nothing -> assertFailure "Failed to get witness" + Just wit -> do + let uWit = updateOrchardWitness wit [cmx2, cmx3, cmx4] + Just (getOrchardWitnessAnchor uWit) `shouldBe` + getOrchardTreeAnchor <$> + finalTree describe "Witness updates" $ do it "Sapling" $ do let wit = diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index edad0f8..36ce2ae 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.2.0 +version: 0.7.3.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 2e9e6d8831cda2507d5fd893aea2b040ac11a813 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 28 Oct 2024 11:59:07 -0500 Subject: [PATCH 21/72] feat: allow combining empty Orchard leaves --- librustzcash-wrapper/src/lib.rs | 40 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index e7b5d04..df054c6 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1590,26 +1590,32 @@ pub extern "C" fn rust_wrapper_combine_orchard_nodes( ){ let left_in: Vec = marshall_from_haskell_var(left, left_len, RW); let right_in: Vec = marshall_from_haskell_var(right, right_len, RW); - let left_node = MerkleHashOrchard::from_bytes(&to_array(left_in)); - if left_node.is_some().into() { - if right_in.len() > 1 { - let right_node = MerkleHashOrchard::from_bytes(&to_array(right_in)); - if right_node.is_some().into() { - let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &right_node.unwrap()); - let h = Hhex { bytes: n.to_bytes().to_vec() }; - marshall_to_haskell_var(&h, out, out_len, RW); - } else { - let h0 = Hhex { bytes: vec![0] }; - marshall_to_haskell_var(&h0, out, out_len, RW); - } - } else { - let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &MerkleHashOrchard::empty_leaf()); + if left_in.len() > 1 { + let n = MerkleHashOrchard::combine(Level::new(level), &MerkleHashOrchard::empty_leaf(), &MerkleHashOrchard::empty_leaf()); let h = Hhex { bytes: n.to_bytes().to_vec() }; marshall_to_haskell_var(&h, out, out_len, RW); - } } else { - let h0 = Hhex { bytes: vec![0] }; - marshall_to_haskell_var(&h0, out, out_len, RW); + let left_node = MerkleHashOrchard::from_bytes(&to_array(left_in)); + if left_node.is_some().into() { + if right_in.len() > 1 { + let right_node = MerkleHashOrchard::from_bytes(&to_array(right_in)); + if right_node.is_some().into() { + let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &right_node.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } else { + let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &MerkleHashOrchard::empty_leaf()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } } } -- 2.34.1 From b6d490d05300a9db9cdf9929baa9b984bee9f3f6 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 28 Oct 2024 12:25:34 -0500 Subject: [PATCH 22/72] fix(rust): orchard hash length check --- librustzcash-wrapper/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index df054c6..1673061 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1590,7 +1590,7 @@ pub extern "C" fn rust_wrapper_combine_orchard_nodes( ){ let left_in: Vec = marshall_from_haskell_var(left, left_len, RW); let right_in: Vec = marshall_from_haskell_var(right, right_len, RW); - if left_in.len() > 1 { + if left_in.len() == 1 { let n = MerkleHashOrchard::combine(Level::new(level), &MerkleHashOrchard::empty_leaf(), &MerkleHashOrchard::empty_leaf()); let h = Hhex { bytes: n.to_bytes().to_vec() }; marshall_to_haskell_var(&h, out, out_len, RW); -- 2.34.1 From 1492f3b6ad44f8aba2daf3e153dc792c6bab3fbf Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 09:46:24 -0500 Subject: [PATCH 23/72] docs: add debugging to create_transaction --- librustzcash-wrapper/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 1673061..73b52cd 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1844,6 +1844,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let trans_input: Vec = marshall_from_haskell_var(t_input, t_input_len, RW); for t_in in trans_input { if t_in.sk.len() > 1 { + println!("t inp: {:?}", t_in); let k = SecretKey::from_slice(&t_in.sk).unwrap(); if net { match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) { @@ -1866,6 +1867,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } for s_in in sap_input { if s_in.sk.len() > 1 { + println!("s inp: {:?}", s_in); let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk); match sp_key { Ok(sk) => { @@ -1912,6 +1914,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } for o_in in orch_input { if o_in.sk.len() > 1 { + println!("o inp: {:?}", o_in); let sp_key = SpendingKey::from_bytes(o_in.sk[0..32].try_into().unwrap()).unwrap(); let pay_addr = OrchardAddress::from_raw_address_bytes(&to_array(o_in.note.recipient)).unwrap(); let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); @@ -1952,6 +1955,7 @@ pub extern "C" fn rust_wrapper_create_transaction( 1 => { let recipient = TransparentAddress::PublicKeyHash(to_array(output.to)); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); + println!("t out: {:?} {:?}", val, output.chg); if net { let _mb = main_builder.add_transparent_output(&recipient, val); } else { @@ -1961,6 +1965,7 @@ pub extern "C" fn rust_wrapper_create_transaction( 2 => { let recipient = TransparentAddress::ScriptHash(to_array(output.to)); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); + println!("t out: {:?} {:?}", val, output.chg); if net { let _mb = main_builder.add_transparent_output(&recipient, val); } else { @@ -1972,6 +1977,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let recipient = PaymentAddress::from_bytes(&to_array(output.to)).unwrap(); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); + println!("s out: {:?} {:?}", val, output.chg); if net { let _mb = main_builder.add_sapling_output::(ovk, recipient, val, memo); } else { @@ -1987,6 +1993,7 @@ pub extern "C" fn rust_wrapper_create_transaction( }; let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap(); let val = output.amt; + println!("o out: {:?} {:?}", val, output.chg); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); if net { let _mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); -- 2.34.1 From 42da2d3a0fb876e070892fa9fc16a91a7106991f Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 10:12:41 -0500 Subject: [PATCH 24/72] docs: add debug for fee --- librustzcash-wrapper/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 73b52cd..6abf905 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2007,6 +2007,12 @@ pub extern "C" fn rust_wrapper_create_transaction( } } if build { + let fee_result = if net { + main_builder.get_fee(&FeeRule::standard()) + } else { + test_builder.get_fee(&FeeRule::standard()) + }; + println!("fee: {:?}", fee_result); let (spend_params_in, output_params_in) = load_sapling_parameters(); //let spend_params_in: Vec = marshall_from_haskell_var(sapspend, sapspend_len, RW); let spend_params_reader = Cursor::new(spend_params_in); -- 2.34.1 From 0ad6b9ebab1ab43e2d275883ab3742ce1e40f9a4 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 10:31:25 -0500 Subject: [PATCH 25/72] docs: add error debug output --- librustzcash-wrapper/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 6abf905..d15036e 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2039,6 +2039,7 @@ pub extern "C" fn rust_wrapper_create_transaction( marshall_to_haskell_var(&x, out, out_len, RW); }, Error::ChangeRequired(y1) => { + println!("change req: {:?}", y1); let x = Hhex {bytes: vec![1]}; marshall_to_haskell_var(&x, out, out_len, RW); }, -- 2.34.1 From 1e350c289c5b9332df35599a43671103d7e6f65b Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 11:06:25 -0500 Subject: [PATCH 26/72] docs: add debug for sapling outputs --- librustzcash-wrapper/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index d15036e..a67eba0 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1914,12 +1914,12 @@ pub extern "C" fn rust_wrapper_create_transaction( } for o_in in orch_input { if o_in.sk.len() > 1 { - println!("o inp: {:?}", o_in); let sp_key = SpendingKey::from_bytes(o_in.sk[0..32].try_into().unwrap()).unwrap(); let pay_addr = OrchardAddress::from_raw_address_bytes(&to_array(o_in.note.recipient)).unwrap(); let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); let val = NoteValue::from_raw(o_in.note.note); + println!("o inp: {:?}", val); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); let wit_reader = Cursor::new(o_in.iw); let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); -- 2.34.1 From a21642baeeeef51c2cbe31d64ea282ea61e26c77 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 11:19:03 -0500 Subject: [PATCH 27/72] docs: add more Rust debug output --- librustzcash-wrapper/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a67eba0..c243aa2 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1981,7 +1981,8 @@ pub extern "C" fn rust_wrapper_create_transaction( if net { let _mb = main_builder.add_sapling_output::(ovk, recipient, val, memo); } else { - let _tb = test_builder.add_sapling_output::(ovk, recipient, val, memo); + let tb = test_builder.add_sapling_output::(ovk, recipient, val, memo); + println!("add sap: {:?}", tb); } }, 4 => { -- 2.34.1 From 5139f9dd7bacae07aa013f7610e3ed37cb5999ab Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 12:15:04 -0500 Subject: [PATCH 28/72] fix(rust): correct tx builder startup --- librustzcash-wrapper/src/lib.rs | 46 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index c243aa2..ade568c 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1795,43 +1795,41 @@ pub extern "C" fn rust_wrapper_create_transaction( build: bool, out: *mut u8, out_len: &mut usize){ - //let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); - //let sap_wit_reader = Cursor::new(sap_wit_in); - //let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); let sap_input: Vec = marshall_from_haskell_var(s_input, s_input_len, RW); let sap_anchor = if sap_input.is_empty() { - None + let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); + let sap_wit_reader = Cursor::new(sap_wit_in); + let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); + match sap_iw { + Ok(s_iw) => { + Some(SaplingAnchor::from(s_iw.root())) + }, + Err(_e) => { + None + } + } } else { let si = &sap_input[0]; let swit_reader = Cursor::new(&si.iw); let iw: IncrementalWitness = read_incremental_witness(swit_reader).unwrap(); Some(SaplingAnchor::from(iw.root())) }; - //let sap_anchor = match sap_iw { - //Ok(s_iw) => { - //Some(SaplingAnchor::from(s_iw.root())) - //}, - //Err(_e) => { - //None - //} - //}; //println!("{:?}", sap_anchor); - //let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); - //let orch_wit_reader = Cursor::new(orch_wit_in); - //let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); - //let orch_anchor = match orch_iw { - //Ok(o_iw) => { - //Some(OrchardAnchor::from(o_iw.root())) - //}, - //Err(_e) => { - //None - //} - //}; let orch_anchor = if orch_input.is_empty() { - None + let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); + let orch_wit_reader = Cursor::new(orch_wit_in); + let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); + match orch_iw { + Ok(o_iw) => { + Some(OrchardAnchor::from(o_iw.root())) + }, + Err(_e) => { + None + } + } } else { let oi = &orch_input[0]; let wit_reader = Cursor::new(&oi.iw); -- 2.34.1 From 1694898117d3d0b211f9d3de224ca206bc30b166 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 14:14:39 -0500 Subject: [PATCH 29/72] fix: correct transaction creation --- src/ZcashHaskell/Utils.hs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index e7e1aae..e060e18 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -137,22 +137,22 @@ createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh bui processResult $! txResult where processResult :: HexString -> Either TxError HexString - processResult input = - if BS.length (hexBytes input) > 1 - then Right input - else case head (BS.unpack $ hexBytes input) of - 0 -> Left InsufficientFunds - 1 -> Left ChangeRequired - 2 -> Left Fee - 3 -> Left Balance - 4 -> Left TransparentBuild - 5 -> Left SaplingBuild - 6 -> Left OrchardBuild - 7 -> Left OrchardSpend - 8 -> Left OrchardRecipient - 9 -> Left SaplingBuilderNotAvailable - 10 -> Left OrchardBuilderNotAvailable - _ -> Left ZHError + processResult input + | BS.length (hexBytes input) > 1 = Right input + | otherwise = + case head (BS.unpack $ hexBytes input) of + 0 -> Left InsufficientFunds + 1 -> Left ChangeRequired + 2 -> Left Fee + 3 -> Left Balance + 4 -> Left TransparentBuild + 5 -> Left SaplingBuild + 6 -> Left OrchardBuild + 7 -> Left OrchardSpend + 8 -> Left OrchardRecipient + 9 -> Left SaplingBuilderNotAvailable + 10 -> Left OrchardBuilderNotAvailable + _ -> Left ZHError txResult = withPureBorshVarBuffer $ rustWrapperCreateTx -- 2.34.1 From 24210b1e0be8ba7319a6ec2fbbe645ae03f9143b Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 29 Oct 2024 14:55:43 -0500 Subject: [PATCH 30/72] fix: optimize create transaction --- src/ZcashHaskell/Utils.hs | 52 ++++++++++++--------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index e060e18..bc3566b 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -132,40 +132,20 @@ createTransaction :: -> ZcashNet -- ^ the network to be used -> Int -- ^ target block height -> Bool -- ^ True to build, False to estimate fee - -> Either TxError HexString + -> HexString createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = - processResult $! txResult - where - processResult :: HexString -> Either TxError HexString - processResult input - | BS.length (hexBytes input) > 1 = Right input - | otherwise = - case head (BS.unpack $ hexBytes input) of - 0 -> Left InsufficientFunds - 1 -> Left ChangeRequired - 2 -> Left Fee - 3 -> Left Balance - 4 -> Left TransparentBuild - 5 -> Left SaplingBuild - 6 -> Left OrchardBuild - 7 -> Left OrchardSpend - 8 -> Left OrchardRecipient - 9 -> Left SaplingBuilderNotAvailable - 10 -> Left OrchardBuilderNotAvailable - _ -> Left ZHError - txResult = - withPureBorshVarBuffer $ - rustWrapperCreateTx - (case sapAnchor of - Nothing -> "0" - Just sA -> toBytes $ sapTree sA) - (case orchAnchor of - Nothing -> "0" - Just oA -> toBytes $ orchTree oA) - tSpend - sSpend - oSpend - outgoing - (znet == MainNet) - (fromIntegral bh) - build + withPureBorshVarBuffer $ + rustWrapperCreateTx + (case sapAnchor of + Nothing -> "0" + Just sA -> toBytes $ sapTree sA) + (case orchAnchor of + Nothing -> "0" + Just oA -> toBytes $ orchTree oA) + tSpend + sSpend + oSpend + outgoing + (znet == MainNet) + (fromIntegral bh) + build -- 2.34.1 From fa2b34e26f32b93b2adf81c1465bc6b9eba416b8 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 09:09:11 -0500 Subject: [PATCH 31/72] debuggin FFI --- librustzcash-wrapper/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index ade568c..a09f3e6 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -728,6 +728,7 @@ pub extern "C" fn rust_wrapper_f4jumble( out: *mut u8, out_len: &mut usize) { let input: Vec = marshall_from_haskell_var(input, input_len, RW); + println!("testy mc testface"); let result = f4jumble::f4jumble(&input).unwrap(); marshall_to_haskell_var(&result, out, out_len, RW); } -- 2.34.1 From f4ecfe9d11c67b8517ccabc7b6bb18b55c99dab4 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 10:23:23 -0500 Subject: [PATCH 32/72] fix: optimize FFI for large results --- src/ZcashHaskell/Utils.hs | 50 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index bc3566b..62fb89c 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -132,20 +132,36 @@ createTransaction :: -> ZcashNet -- ^ the network to be used -> Int -- ^ target block height -> Bool -- ^ True to build, False to estimate fee - -> HexString -createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = - withPureBorshVarBuffer $ - rustWrapperCreateTx - (case sapAnchor of - Nothing -> "0" - Just sA -> toBytes $ sapTree sA) - (case orchAnchor of - Nothing -> "0" - Just oA -> toBytes $ orchTree oA) - tSpend - sSpend - oSpend - outgoing - (znet == MainNet) - (fromIntegral bh) - build + -> IO (Either TxError HexString) +createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do + txResult <- + withBorshBufferOfInitSize 5120 $ + rustWrapperCreateTx + (case sapAnchor of + Nothing -> "0" + Just sA -> toBytes $ sapTree sA) + (case orchAnchor of + Nothing -> "0" + Just oA -> toBytes $ orchTree oA) + tSpend + sSpend + oSpend + outgoing + (znet == MainNet) + (fromIntegral bh) + build + if BS.length (hexBytes txResult) > 1 + then pure $ Right txResult + else case head (BS.unpack $ hexBytes txResult) of + 0 -> pure $ Left InsufficientFunds + 1 -> pure $ Left ChangeRequired + 2 -> pure $ Left Fee + 3 -> pure $ Left Balance + 4 -> pure $ Left TransparentBuild + 5 -> pure $ Left SaplingBuild + 6 -> pure $ Left OrchardBuild + 7 -> pure $ Left OrchardSpend + 8 -> pure $ Left OrchardRecipient + 9 -> pure $ Left SaplingBuilderNotAvailable + 10 -> pure $ Left OrchardBuilderNotAvailable + _ -> pure $ Left ZHError -- 2.34.1 From a8d4a96b8ac09cd112c260ac76234dc4801c5d18 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 10:59:20 -0500 Subject: [PATCH 33/72] fix: increase buffer size for createTransaction --- src/ZcashHaskell/Utils.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index 62fb89c..4b783ac 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -135,7 +135,7 @@ createTransaction :: -> IO (Either TxError HexString) createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do txResult <- - withBorshBufferOfInitSize 5120 $ + withBorshBufferOfInitSize 10240 $ rustWrapperCreateTx (case sapAnchor of Nothing -> "0" -- 2.34.1 From b3ec3aecbd0d5555538ed8e431b430df40bb4855 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 11:15:34 -0500 Subject: [PATCH 34/72] fix: adjust FFI buffer --- src/ZcashHaskell/Utils.hs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index 4b783ac..6956e3f 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -135,21 +135,22 @@ createTransaction :: -> IO (Either TxError HexString) createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do txResult <- - withBorshBufferOfInitSize 10240 $ - rustWrapperCreateTx - (case sapAnchor of - Nothing -> "0" - Just sA -> toBytes $ sapTree sA) - (case orchAnchor of - Nothing -> "0" - Just oA -> toBytes $ orchTree oA) - tSpend - sSpend - oSpend - outgoing - (znet == MainNet) - (fromIntegral bh) - build + do print "calling FFI" + withBorshBufferOfInitSize 51200 $ + rustWrapperCreateTx + (case sapAnchor of + Nothing -> "0" + Just sA -> toBytes $ sapTree sA) + (case orchAnchor of + Nothing -> "0" + Just oA -> toBytes $ orchTree oA) + tSpend + sSpend + oSpend + outgoing + (znet == MainNet) + (fromIntegral bh) + build if BS.length (hexBytes txResult) > 1 then pure $ Right txResult else case head (BS.unpack $ hexBytes txResult) of -- 2.34.1 From c793e0c4ff9547be5b1a7663c6d21277df8876e7 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 11:42:36 -0500 Subject: [PATCH 35/72] fix(rust): remove debug messages --- librustzcash-wrapper/src/lib.rs | 110 ++++++++++++++++++++++++-------- src/ZcashHaskell/Utils.hs | 31 +++++---- 2 files changed, 97 insertions(+), 44 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a09f3e6..a469cb8 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -20,9 +20,9 @@ use borsh::{BorshDeserialize, BorshSerialize}; use haskell_ffi::{ error::Result, - from_haskell::{marshall_from_haskell_var, marshall_from_haskell_fixed}, - to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed}, - FromHaskell, HaskellSize, ToHaskell + from_haskell::marshall_from_haskell_var, + to_haskell::marshall_to_haskell_var, + FromHaskell, ToHaskell }; use secp256k1::SecretKey; @@ -42,8 +42,7 @@ use incrementalmerkletree::{ }; use zip32::{ - Scope as SaplingScope, - ChildIndex + Scope as SaplingScope }; @@ -728,7 +727,6 @@ pub extern "C" fn rust_wrapper_f4jumble( out: *mut u8, out_len: &mut usize) { let input: Vec = marshall_from_haskell_var(input, input_len, RW); - println!("testy mc testface"); let result = f4jumble::f4jumble(&input).unwrap(); marshall_to_haskell_var(&result, out, out_len, RW); } @@ -1843,7 +1841,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let trans_input: Vec = marshall_from_haskell_var(t_input, t_input_len, RW); for t_in in trans_input { if t_in.sk.len() > 1 { - println!("t inp: {:?}", t_in); + //println!("t inp: {:?}", t_in); let k = SecretKey::from_slice(&t_in.sk).unwrap(); if net { match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) { @@ -1866,7 +1864,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } for s_in in sap_input { if s_in.sk.len() > 1 { - println!("s inp: {:?}", s_in); + //println!("s inp: {:?}", s_in); let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk); match sp_key { Ok(sk) => { @@ -1918,7 +1916,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); let val = NoteValue::from_raw(o_in.note.note); - println!("o inp: {:?}", val); + //println!("o inp: {:?}", val); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); let wit_reader = Cursor::new(o_in.iw); let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); @@ -1954,21 +1952,49 @@ pub extern "C" fn rust_wrapper_create_transaction( 1 => { let recipient = TransparentAddress::PublicKeyHash(to_array(output.to)); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); - println!("t out: {:?} {:?}", val, output.chg); + //println!("t out: {:?} {:?}", val, output.chg); if net { - let _mb = main_builder.add_transparent_output(&recipient, val); + let mb = main_builder.add_transparent_output(&recipient, val); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_transparent_output(&recipient, val); + let tb = test_builder.add_transparent_output(&recipient, val); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, 2 => { let recipient = TransparentAddress::ScriptHash(to_array(output.to)); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); - println!("t out: {:?} {:?}", val, output.chg); + //println!("t out: {:?} {:?}", val, output.chg); if net { - let _mb = main_builder.add_transparent_output(&recipient, val); + let mb = main_builder.add_transparent_output(&recipient, val); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_transparent_output(&recipient, val); + let tb = test_builder.add_transparent_output(&recipient, val); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, 3 => { @@ -1976,12 +2002,26 @@ pub extern "C" fn rust_wrapper_create_transaction( let recipient = PaymentAddress::from_bytes(&to_array(output.to)).unwrap(); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); - println!("s out: {:?} {:?}", val, output.chg); + //println!("s out: {:?} {:?}", val, output.chg); if net { - let _mb = main_builder.add_sapling_output::(ovk, recipient, val, memo); + let mb = main_builder.add_sapling_output::(ovk, recipient, val, memo); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { let tb = test_builder.add_sapling_output::(ovk, recipient, val, memo); - println!("add sap: {:?}", tb); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } + //println!("add sap: {:?}", tb); } }, 4 => { @@ -1993,12 +2033,26 @@ pub extern "C" fn rust_wrapper_create_transaction( }; let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap(); let val = output.amt; - println!("o out: {:?} {:?}", val, output.chg); + //println!("o out: {:?} {:?}", val, output.chg); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); if net { - let _mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); + let mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![6]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_orchard_output::(ovk, recipient, val, memo); + let tb = test_builder.add_orchard_output::(ovk, recipient, val, memo); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![6]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, _ => { @@ -2007,12 +2061,12 @@ pub extern "C" fn rust_wrapper_create_transaction( } } if build { - let fee_result = if net { - main_builder.get_fee(&FeeRule::standard()) - } else { - test_builder.get_fee(&FeeRule::standard()) - }; - println!("fee: {:?}", fee_result); + //let fee_result = if net { + //main_builder.get_fee(&FeeRule::standard()) + //} else { + //test_builder.get_fee(&FeeRule::standard()) + //}; + //println!("fee: {:?}", fee_result); let (spend_params_in, output_params_in) = load_sapling_parameters(); //let spend_params_in: Vec = marshall_from_haskell_var(sapspend, sapspend_len, RW); let spend_params_reader = Cursor::new(spend_params_in); @@ -2039,7 +2093,7 @@ pub extern "C" fn rust_wrapper_create_transaction( marshall_to_haskell_var(&x, out, out_len, RW); }, Error::ChangeRequired(y1) => { - println!("change req: {:?}", y1); + //println!("change req: {:?}", y1); let x = Hhex {bytes: vec![1]}; marshall_to_haskell_var(&x, out, out_len, RW); }, diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index 6956e3f..ee0a0d9 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -135,22 +135,21 @@ createTransaction :: -> IO (Either TxError HexString) createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do txResult <- - do print "calling FFI" - withBorshBufferOfInitSize 51200 $ - rustWrapperCreateTx - (case sapAnchor of - Nothing -> "0" - Just sA -> toBytes $ sapTree sA) - (case orchAnchor of - Nothing -> "0" - Just oA -> toBytes $ orchTree oA) - tSpend - sSpend - oSpend - outgoing - (znet == MainNet) - (fromIntegral bh) - build + withBorshBufferOfInitSize 51200 $ + rustWrapperCreateTx + (case sapAnchor of + Nothing -> "0" + Just sA -> toBytes $ sapTree sA) + (case orchAnchor of + Nothing -> "0" + Just oA -> toBytes $ orchTree oA) + tSpend + sSpend + oSpend + outgoing + (znet == MainNet) + (fromIntegral bh) + build if BS.length (hexBytes txResult) > 1 then pure $ Right txResult else case head (BS.unpack $ hexBytes txResult) of -- 2.34.1 From 33085a46bff80d63a2fb81a0fa2db705765c9ee0 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 11:44:56 -0500 Subject: [PATCH 36/72] docs: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eed57f..3f3a7e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Modified frontiers to use `HexString` for ommers +- Optimized `createTransaction` ## [0.7.2.0] -- 2.34.1 From 6d4b6840d30fe1631902acd0388bef0040fee9e8 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 16:47:11 +0000 Subject: [PATCH 37/72] Optimize transaction creation (#98) Reviewed-on: https://git.vergara.tech///Vergara_Tech/zcash-haskell/pulls/98 Co-authored-by: Rene Vergara Co-committed-by: Rene Vergara --- CHANGELOG.md | 12 ++ librustzcash-wrapper/src/lib.rs | 286 +++++++++++++++++++++++++------- src/C/Zcash.chs | 30 ++++ src/ZcashHaskell/Orchard.hs | 36 +++- src/ZcashHaskell/Types.hs | 4 +- src/ZcashHaskell/Utils.hs | 70 ++++---- test/Spec.hs | 181 ++++++++++---------- zcash-haskell.cabal | 2 +- 8 files changed, 437 insertions(+), 184 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bdb344..3f3a7e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.3.0] + +### Added + +- Function to create an Orchard hash from a note commitment +- Function to hash Orchard commitments + +### Changed + +- Modified frontiers to use `HexString` for ommers +- Optimized `createTransaction` + ## [0.7.2.0] ### Changed diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 92e9319..a469cb8 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -20,9 +20,9 @@ use borsh::{BorshDeserialize, BorshSerialize}; use haskell_ffi::{ error::Result, - from_haskell::{marshall_from_haskell_var, marshall_from_haskell_fixed}, - to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed}, - FromHaskell, HaskellSize, ToHaskell + from_haskell::marshall_from_haskell_var, + to_haskell::marshall_to_haskell_var, + FromHaskell, ToHaskell }; use secp256k1::SecretKey; @@ -30,6 +30,8 @@ use secp256k1::SecretKey; use jubjub::Fr; use incrementalmerkletree::{ + Hashable, + Level, Position, frontier::{ CommitmentTree, @@ -40,8 +42,7 @@ use incrementalmerkletree::{ }; use zip32::{ - Scope as SaplingScope, - ChildIndex + Scope as SaplingScope }; @@ -92,7 +93,8 @@ use zcash_primitives::{ write_commitment_tree, read_incremental_witness, write_incremental_witness, - read_frontier_v1 + read_frontier_v1, + read_nonempty_frontier_v1 }, legacy::{ Script, @@ -697,7 +699,7 @@ impl ToHaskell for Hsvk { pub struct Hfrontier { position: u64, leaf: Hhex, - ommers: Vec> + ommers: Vec } impl ToHaskell for Hfrontier { @@ -1384,11 +1386,11 @@ pub extern "C" fn rust_wrapper_read_sapling_frontier( match frontier.value() { Some(f1) => { let (pos, leaf, omm) = f1.clone().into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; marshall_to_haskell_var(&f, out, out_len, RW); }, None => { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1405,17 +1407,17 @@ pub extern "C" fn rust_wrapper_read_sapling_commitment_tree( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap(); - let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap(); + let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in)); if sap_note_comm.is_some().into() { let n = Node::from_cmu(&sap_note_comm.unwrap()); comm_tree.append(n); let (pos, leaf, omm) = comm_tree.into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; marshall_to_haskell_var(&f, out, out_len, RW); } else { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1429,7 +1431,7 @@ pub extern "C" fn rust_wrapper_read_sapling_witness( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap(); - let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap(); + let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let ct: CommitmentTree = CommitmentTree::from_frontier(&frontier); let inc_wit = IncrementalWitness::from_tree(ct); let mut out_bytes: Vec = Vec::new(); @@ -1501,23 +1503,120 @@ pub extern "C" fn rust_wrapper_read_orchard_frontier( ){ let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); let tree_reader = Cursor::new(tree_in); - let comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); - //let comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); - let frontier: Frontier = comm_tree.to_frontier(); - match frontier.value() { - Some(f1) => { - let (pos, leaf, omm) = f1.clone().into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; - marshall_to_haskell_var(&f, out, out_len, RW); + let comm_tree = read_commitment_tree(tree_reader); + //let comm_tree = read_frontier_v1(tree_reader); + //let frontier: Frontier = comm_tree.to_frontier(); + match comm_tree { + Ok::, _>(f1) => { + let frontier = f1.to_frontier(); + match frontier.value() { + Some(f2) => { + let (pos, leaf, omm) = f2.clone().into_parts(); + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; + marshall_to_haskell_var(&f, out, out_len, RW); + }, + None => { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; + marshall_to_haskell_var(&f0, out, out_len, RW); + } + } }, - None => { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + Err(_e) => { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_tree_anchor( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); + let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); + let comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); + let root = comm_tree.root(None); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_witness_anchor( + wit: *const u8, + wit_len: usize, + out: *mut u8, + out_len: &mut usize + ) { + let wit_in: Vec = marshall_from_haskell_var(wit, wit_len, RW); + let wit_reader = Cursor::new(wit_in); + let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); + let root = iw.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_node( + cmx: *const u8, + cmx_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let node_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); + let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); + if orchard_note_comm.is_some().into() { + let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec()}; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_combine_orchard_nodes( + level: u8, + left: *const u8, + left_len: usize, + right: *const u8, + right_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let left_in: Vec = marshall_from_haskell_var(left, left_len, RW); + let right_in: Vec = marshall_from_haskell_var(right, right_len, RW); + if left_in.len() == 1 { + let n = MerkleHashOrchard::combine(Level::new(level), &MerkleHashOrchard::empty_leaf(), &MerkleHashOrchard::empty_leaf()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let left_node = MerkleHashOrchard::from_bytes(&to_array(left_in)); + if left_node.is_some().into() { + if right_in.len() > 1 { + let right_node = MerkleHashOrchard::from_bytes(&to_array(right_in)); + if right_node.is_some().into() { + let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &right_node.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } else { + let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &MerkleHashOrchard::empty_leaf()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } +} #[no_mangle] @@ -1534,17 +1633,17 @@ pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( //let mut comm_tree: CommitmentTree = read_commitment_tree(tree_reader).unwrap(); //let mut comm_tree: Frontier = read_frontier_v1(tree_reader).unwrap(); let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let mut comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap(); + let mut comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); if orchard_note_comm.is_some().into() { let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); comm_tree.append(n); let (pos, leaf, omm) = comm_tree.into_parts(); - let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()}; + let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; marshall_to_haskell_var(&f, out, out_len, RW); } else { - let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]}; + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; marshall_to_haskell_var(&f0, out, out_len, RW); } } @@ -1558,7 +1657,7 @@ pub extern "C" fn rust_wrapper_read_orchard_witness( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap(); + let frontier: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); let ct: CommitmentTree = CommitmentTree::from_frontier(&frontier); let inc_wit = IncrementalWitness::from_tree(ct); let mut out_bytes: Vec = Vec::new(); @@ -1695,43 +1794,41 @@ pub extern "C" fn rust_wrapper_create_transaction( build: bool, out: *mut u8, out_len: &mut usize){ - //let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); - //let sap_wit_reader = Cursor::new(sap_wit_in); - //let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); let sap_input: Vec = marshall_from_haskell_var(s_input, s_input_len, RW); let sap_anchor = if sap_input.is_empty() { - None + let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); + let sap_wit_reader = Cursor::new(sap_wit_in); + let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); + match sap_iw { + Ok(s_iw) => { + Some(SaplingAnchor::from(s_iw.root())) + }, + Err(_e) => { + None + } + } } else { let si = &sap_input[0]; let swit_reader = Cursor::new(&si.iw); let iw: IncrementalWitness = read_incremental_witness(swit_reader).unwrap(); Some(SaplingAnchor::from(iw.root())) }; - //let sap_anchor = match sap_iw { - //Ok(s_iw) => { - //Some(SaplingAnchor::from(s_iw.root())) - //}, - //Err(_e) => { - //None - //} - //}; //println!("{:?}", sap_anchor); - //let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); - //let orch_wit_reader = Cursor::new(orch_wit_in); - //let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); - //let orch_anchor = match orch_iw { - //Ok(o_iw) => { - //Some(OrchardAnchor::from(o_iw.root())) - //}, - //Err(_e) => { - //None - //} - //}; let orch_anchor = if orch_input.is_empty() { - None + let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); + let orch_wit_reader = Cursor::new(orch_wit_in); + let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); + match orch_iw { + Ok(o_iw) => { + Some(OrchardAnchor::from(o_iw.root())) + }, + Err(_e) => { + None + } + } } else { let oi = &orch_input[0]; let wit_reader = Cursor::new(&oi.iw); @@ -1744,6 +1841,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let trans_input: Vec = marshall_from_haskell_var(t_input, t_input_len, RW); for t_in in trans_input { if t_in.sk.len() > 1 { + //println!("t inp: {:?}", t_in); let k = SecretKey::from_slice(&t_in.sk).unwrap(); if net { match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) { @@ -1766,6 +1864,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } for s_in in sap_input { if s_in.sk.len() > 1 { + //println!("s inp: {:?}", s_in); let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk); match sp_key { Ok(sk) => { @@ -1817,6 +1916,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); let val = NoteValue::from_raw(o_in.note.note); + //println!("o inp: {:?}", val); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); let wit_reader = Cursor::new(o_in.iw); let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); @@ -1852,19 +1952,49 @@ pub extern "C" fn rust_wrapper_create_transaction( 1 => { let recipient = TransparentAddress::PublicKeyHash(to_array(output.to)); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); + //println!("t out: {:?} {:?}", val, output.chg); if net { - let _mb = main_builder.add_transparent_output(&recipient, val); + let mb = main_builder.add_transparent_output(&recipient, val); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_transparent_output(&recipient, val); + let tb = test_builder.add_transparent_output(&recipient, val); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, 2 => { let recipient = TransparentAddress::ScriptHash(to_array(output.to)); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); + //println!("t out: {:?} {:?}", val, output.chg); if net { - let _mb = main_builder.add_transparent_output(&recipient, val); + let mb = main_builder.add_transparent_output(&recipient, val); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_transparent_output(&recipient, val); + let tb = test_builder.add_transparent_output(&recipient, val); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![4]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, 3 => { @@ -1872,10 +2002,26 @@ pub extern "C" fn rust_wrapper_create_transaction( let recipient = PaymentAddress::from_bytes(&to_array(output.to)).unwrap(); let val = NonNegativeAmount::from_u64(output.amt).unwrap(); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); + //println!("s out: {:?} {:?}", val, output.chg); if net { - let _mb = main_builder.add_sapling_output::(ovk, recipient, val, memo); + let mb = main_builder.add_sapling_output::(ovk, recipient, val, memo); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_sapling_output::(ovk, recipient, val, memo); + let tb = test_builder.add_sapling_output::(ovk, recipient, val, memo); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![5]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } + //println!("add sap: {:?}", tb); } }, 4 => { @@ -1887,11 +2033,26 @@ pub extern "C" fn rust_wrapper_create_transaction( }; let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap(); let val = output.amt; + //println!("o out: {:?} {:?}", val, output.chg); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); if net { - let _mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); + let mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); + match mb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![6]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } else { - let _tb = test_builder.add_orchard_output::(ovk, recipient, val, memo); + let tb = test_builder.add_orchard_output::(ovk, recipient, val, memo); + match tb { + Ok(()) => { continue; }, + Err(_e) => { + let x = Hhex {bytes: vec![6]}; + marshall_to_haskell_var(&x, out, out_len, RW); + } + } } }, _ => { @@ -1900,6 +2061,12 @@ pub extern "C" fn rust_wrapper_create_transaction( } } if build { + //let fee_result = if net { + //main_builder.get_fee(&FeeRule::standard()) + //} else { + //test_builder.get_fee(&FeeRule::standard()) + //}; + //println!("fee: {:?}", fee_result); let (spend_params_in, output_params_in) = load_sapling_parameters(); //let spend_params_in: Vec = marshall_from_haskell_var(sapspend, sapspend_len, RW); let spend_params_reader = Cursor::new(spend_params_in); @@ -1926,6 +2093,7 @@ pub extern "C" fn rust_wrapper_create_transaction( marshall_to_haskell_var(&x, out, out_len, RW); }, Error::ChangeRequired(y1) => { + //println!("change req: {:?}", y1); let x = Hhex {bytes: vec![1]}; marshall_to_haskell_var(&x, out, out_len, RW); }, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 71c73e5..da2f86b 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -246,6 +246,36 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_combine_orchard_nodes as rustWrapperCombineOrchardNodes + { `Int8' + , toBorshVar* `BS.ByteString'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_read_orchard_tree_anchor as rustWrapperReadOrchardTreeAnchor + { toBorshVar* `OrchardFrontier'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_read_orchard_witness_anchor as rustWrapperReadOrchardWitnessAnchor + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree { toBorshVar* `OrchardFrontier'& , toBorshVar* `BS.ByteString'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 1bb7167..79043ea 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -18,15 +18,19 @@ module ZcashHaskell.Orchard where import C.Zcash - ( rustWrapperGenOrchardReceiver + ( rustWrapperCombineOrchardNodes + , rustWrapperGenOrchardReceiver , rustWrapperGenOrchardSpendKey , rustWrapperOrchardCheck , rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecodeSK , rustWrapperReadOrchardCommitmentTree , rustWrapperReadOrchardFrontier + , rustWrapperReadOrchardNode , rustWrapperReadOrchardPosition + , rustWrapperReadOrchardTreeAnchor , rustWrapperReadOrchardWitness + , rustWrapperReadOrchardWitnessAnchor , rustWrapperUADecode , rustWrapperUfvkDecode , rustWrapperUpdateOrchardWitness @@ -205,6 +209,15 @@ getOrchardFrontier tree = withPureBorshVarBuffer $ rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree +getOrchardTreeAnchor :: OrchardFrontier -> HexString +getOrchardTreeAnchor tree = + withPureBorshVarBuffer $ rustWrapperReadOrchardTreeAnchor tree + +getOrchardWitnessAnchor :: OrchardWitness -> HexString +getOrchardWitnessAnchor wit = + withPureBorshVarBuffer $ + rustWrapperReadOrchardWitnessAnchor $ toBytes $ orchWit wit + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree @@ -244,6 +257,27 @@ updateOrchardWitness wit cmus = (map toBytes cmus) else wit +getOrchardNodeValue :: BS.ByteString -> Maybe HexString +getOrchardNodeValue cmx = + if BS.length (hexBytes n) > 1 + then Just n + else Nothing + where + n = withPureBorshVarBuffer $ rustWrapperReadOrchardNode cmx + +combineOrchardNodes :: Integer -> HexString -> HexString -> Maybe HexString +combineOrchardNodes level n1 n2 = + if BS.length (hexBytes r) > 1 + then Just r + else Nothing + where + r = + withPureBorshVarBuffer $ + rustWrapperCombineOrchardNodes + (fromIntegral level) + (toBytes n1) + (toBytes n2) + -- | Parse a potential Zcash address parseAddress :: BS.ByteString -> Maybe ValidAddress parseAddress t = diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 8105d30..324216f 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -614,7 +614,7 @@ newtype SaplingCommitmentTree = SaplingCommitmentTree data SaplingFrontier = SaplingFrontier { sf_pos :: !Int64 , sf_leaf :: !HexString - , sf_ommers :: ![BS.ByteString] + , sf_ommers :: ![HexString] } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (Data.Structured.Show) @@ -730,7 +730,7 @@ newtype OrchardCommitmentTree = OrchardCommitmentTree data OrchardFrontier = OrchardFrontier { of_pos :: !Int64 , of_leaf :: !HexString - , of_ommers :: ![BS.ByteString] + , of_ommers :: ![HexString] } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (Data.Structured.Show) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index e7e1aae..ee0a0d9 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -132,40 +132,36 @@ createTransaction :: -> 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 znet bh build = - processResult $! txResult - where - processResult :: HexString -> Either TxError HexString - processResult input = - if BS.length (hexBytes input) > 1 - then Right input - else case head (BS.unpack $ hexBytes input) of - 0 -> Left InsufficientFunds - 1 -> Left ChangeRequired - 2 -> Left Fee - 3 -> Left Balance - 4 -> Left TransparentBuild - 5 -> Left SaplingBuild - 6 -> Left OrchardBuild - 7 -> Left OrchardSpend - 8 -> Left OrchardRecipient - 9 -> Left SaplingBuilderNotAvailable - 10 -> Left OrchardBuilderNotAvailable - _ -> Left ZHError - txResult = - withPureBorshVarBuffer $ - rustWrapperCreateTx - (case sapAnchor of - Nothing -> "0" - Just sA -> toBytes $ sapTree sA) - (case orchAnchor of - Nothing -> "0" - Just oA -> toBytes $ orchTree oA) - tSpend - sSpend - oSpend - outgoing - (znet == MainNet) - (fromIntegral bh) - build + -> IO (Either TxError HexString) +createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do + txResult <- + withBorshBufferOfInitSize 51200 $ + rustWrapperCreateTx + (case sapAnchor of + Nothing -> "0" + Just sA -> toBytes $ sapTree sA) + (case orchAnchor of + Nothing -> "0" + Just oA -> toBytes $ orchTree oA) + tSpend + sSpend + oSpend + outgoing + (znet == MainNet) + (fromIntegral bh) + build + if BS.length (hexBytes txResult) > 1 + then pure $ Right txResult + else case head (BS.unpack $ hexBytes txResult) of + 0 -> pure $ Left InsufficientFunds + 1 -> pure $ Left ChangeRequired + 2 -> pure $ Left Fee + 3 -> pure $ Left Balance + 4 -> pure $ Left TransparentBuild + 5 -> pure $ Left SaplingBuild + 6 -> pure $ Left OrchardBuild + 7 -> pure $ Left OrchardSpend + 8 -> pure $ Left OrchardRecipient + 9 -> pure $ Left SaplingBuilderNotAvailable + 10 -> pure $ Left OrchardBuilderNotAvailable + _ -> pure $ Left ZHError diff --git a/test/Spec.hs b/test/Spec.hs index ac744cb..0547e16 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -55,6 +55,7 @@ import ZcashHaskell.Sapling , genSaplingInternalAddress , genSaplingPaymentAddress , genSaplingSpendingKey + , getSaplingFrontier , getSaplingNotePosition , getSaplingWitness , getShieldedOutputs @@ -73,6 +74,7 @@ import ZcashHaskell.Types , OrchardAction(..) , OrchardBundle(..) , OrchardCommitmentTree(..) + , OrchardFrontier(..) , OrchardSpendingKey(..) , OrchardWitness(..) , Phrase(..) @@ -88,6 +90,7 @@ import ZcashHaskell.Types , SaplingAddress(..) , SaplingBundle(..) , SaplingCommitmentTree(..) + , SaplingFrontier(..) , SaplingReceiver(..) , SaplingSpendingKey(..) , SaplingWitness(..) @@ -895,33 +898,35 @@ main = do Just t' -> do let tb = zt_tBundle t' show tb `shouldNotBe` "" - describe "Sapling commitment trees" $ do - let tree = - SaplingCommitmentTree $ - hexString - "01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - let cmu1 = - hexString - "45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f" - let cmu2 = - hexString - "426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d" - let tree2 = - hexString - "01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - it "Commitment tree is updated correctly" $ do - let t1 = updateSaplingCommitmentTree tree cmu1 - t1 `shouldNotBe` Nothing - it "Incremental witness is generated" $ do - let t1 = updateSaplingCommitmentTree tree cmu1 - case t1 of - Nothing -> assertFailure "Failed to append node to tree" - Just t -> getSaplingWitness t `shouldNotBe` Nothing - it "Position of note is obtained" $ do - let p = - getSaplingNotePosition <$> - (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1) - p `shouldBe` Just 129405 + {- + -describe "Sapling commitment trees" $ do + - let tree = + - SaplingCommitmentTree $ + - hexString + - "01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + - let cmu1 = + - hexString + - "45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f" + - let cmu2 = + - hexString + - "426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d" + - let tree2 = + - hexString + - "01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + - it "Commitment tree is updated correctly" $ do + - let t1 = updateSaplingCommitmentTree tree cmu1 + - t1 `shouldNotBe` Nothing + - it "Incremental witness is generated" $ do + - let t1 = updateSaplingCommitmentTree tree cmu1 + - case t1 of + - Nothing -> assertFailure "Failed to append node to tree" + - Just t -> getSaplingWitness t `shouldNotBe` Nothing + - it "Position of note is obtained" $ do + - let p = + - getSaplingNotePosition <$> + - (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1) + - p `shouldBe` Just 129405 + -} {- describe "Orchard commitment trees" $ do let tree = OrchardCommitmentTree $ @@ -1061,18 +1066,22 @@ main = do (hexString "97e5f003d16720844ba1bd157688a7697133f4bb4a33a7c91974937a1351d7af56d16d4a10bd196ddda700fcd8be517f8f9e39a17ba0eea235d98450a626be3a998ac31f35e8e082106a31fe94da11d02b73748db4aa519df6bbf25c1d62a2cf0b192c6a486bca2632fee9e4124ce2dba6f3366a14850f6a3b784d863119f52458ed774f8d63105b4f6a3d2e09cc74e3a02ec8386213087b4c849172ded6724a45c9c12744ec4a0f86a29b803b17187df5dd5f90e71d1f3f4578d4e1496e8892") it "Sap output 1" $ do - let pos = - getSaplingNotePosition <$> - (getSaplingWitness =<< - updateSaplingCommitmentTree - tree - (fromText - "fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858")) - case pos of - Nothing -> assertFailure "couldn't get note position" - Just p -> do - let dn = decodeSaplingOutputEsk sk so1 TestNet External p - dn `shouldBe` Nothing + case getSaplingFrontier tree of + Nothing -> assertFailure "failed to read comm tree" + Just tree' -> do + let pos = + sf_pos <$> + updateSaplingCommitmentTree + tree' + (fromText + "fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858") + case pos of + Nothing -> assertFailure "couldn't get note position" + Just p -> do + let dn = + decodeSaplingOutputEsk sk so1 TestNet External $ + fromIntegral p + dn `shouldBe` Nothing it "Sap output 2" $ do case readZebraTransaction txHex2 of Nothing -> assertFailure "Failed to read Tx" @@ -1082,24 +1091,27 @@ main = do Nothing -> assertFailure "Failed to get sapling bundle" Just sB -> do let sOuts = sbOutputs sB - let pos = - getSaplingNotePosition <$> - (getSaplingWitness =<< - updateSaplingCommitmentTree - tree - (fromText - "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")) - case pos of - Nothing -> assertFailure "couldn't get note position" - Just p -> do - let dn = - decodeSaplingOutputEsk - sk - (head . tail $ sOuts) - TestNet - External - p - dn `shouldBe` Nothing + case getSaplingFrontier tree of + Nothing -> assertFailure "Failed to read tree" + Just tree' -> do + let pos = + getSaplingNotePosition <$> + (getSaplingWitness =<< + updateSaplingCommitmentTree + tree' + (fromText + "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")) + case pos of + Nothing -> assertFailure "couldn't get note position" + Just p -> do + let dn = + decodeSaplingOutputEsk + sk + (head . tail $ sOuts) + TestNet + External + p + dn `shouldBe` Nothing it "Decode Sapling Output from Zingo" $ do case readZebraTransaction txHex of Nothing -> assertFailure "Failed to read Tx" @@ -1112,24 +1124,26 @@ main = do Nothing -> assertFailure "Failed to get sapling bundle" Just sB -> do let sOuts = sbOutputs sB - let pos = - getSaplingNotePosition <$> - (getSaplingWitness =<< - updateSaplingCommitmentTree - tree - (fromText - "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")) - case pos of - Nothing -> assertFailure "couldn't get note position" - Just p -> do - let dn = - decodeSaplingOutputEsk - sK' - (head . tail $ sOuts) - MainNet - External - p - dn `shouldNotBe` Nothing + case getSaplingFrontier tree of + Nothing -> assertFailure "failed to read comm tree" + Just tree' -> do + let pos = + sf_pos <$> + updateSaplingCommitmentTree + tree' + (fromText + "d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843") + case pos of + Nothing -> assertFailure "couldn't get note position" + Just p -> do + let dn = + decodeSaplingOutputEsk + sK' + (head . tail $ sOuts) + MainNet + External + (fromIntegral p) + dn `shouldNotBe` Nothing describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e" it "Try to generate valid ExchangeAddress from Transparent Address" $ do @@ -1176,15 +1190,14 @@ main = do Just t1 -> case updateOrchardCommitmentTree t1 cmx1 of Nothing -> assertFailure "Failed to update frontier with cmx" - Just t2 -> - case updateOrchardCommitmentTree t2 cmx2 of - Nothing -> assertFailure "Failed to update frontier with cmx" - Just t3 -> - case updateOrchardCommitmentTree t3 cmx3 of - Nothing -> - assertFailure "Failed to update frontier with cmx" - Just t4 -> - updateOrchardCommitmentTree t4 cmx4 `shouldBe` finalTree + Just t2 -> do + case getOrchardWitness t2 of + Nothing -> assertFailure "Failed to get witness" + Just wit -> do + let uWit = updateOrchardWitness wit [cmx2, cmx3, cmx4] + Just (getOrchardWitnessAnchor uWit) `shouldBe` + getOrchardTreeAnchor <$> + finalTree describe "Witness updates" $ do it "Sapling" $ do let wit = diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index edad0f8..36ce2ae 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.2.0 +version: 0.7.3.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From f6b8a772770f492221dc99281016d7090f981e63 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 13:23:46 -0500 Subject: [PATCH 38/72] feat: add function to test empty trees --- librustzcash-wrapper/src/lib.rs | 14 +++++++++++++- src/C/Zcash.chs | 7 +++++++ src/ZcashHaskell/Orchard.hs | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a469cb8..d011e65 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -36,7 +36,8 @@ use incrementalmerkletree::{ frontier::{ CommitmentTree, Frontier, - NonEmptyFrontier + NonEmptyFrontier, + PathFiller }, witness::IncrementalWitness }; @@ -1618,6 +1619,17 @@ pub extern "C" fn rust_wrapper_combine_orchard_nodes( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_get_orchard_root( + level: u8, + out: *mut u8, + out_len: &mut usize + ){ + let tree: CommitmentTree = CommitmentTree::empty(); + let root = tree.root_at_depth(level, PathFiller::empty()); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index da2f86b..abb7435 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -276,6 +276,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_get_orchard_root as rustWrapperGetOrchardRootTest + { `Int8' + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree { toBorshVar* `OrchardFrontier'& , toBorshVar* `BS.ByteString'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 79043ea..170e177 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -218,6 +218,10 @@ getOrchardWitnessAnchor wit = withPureBorshVarBuffer $ rustWrapperReadOrchardWitnessAnchor $ toBytes $ orchWit wit +getOrchardRootTest :: Int -> HexString +getOrchardRootTest level = + withPureBorshVarBuffer $ rustWrapperGetOrchardRootTest $ fromIntegral level + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree -- 2.34.1 From 52c3faa7d4d676945464a47ce352548d850c28e8 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 14:21:48 -0500 Subject: [PATCH 39/72] feat: function to test orchard trees --- src/ZcashHaskell/Orchard.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 170e177..4cb8b9e 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -21,6 +21,7 @@ import C.Zcash ( rustWrapperCombineOrchardNodes , rustWrapperGenOrchardReceiver , rustWrapperGenOrchardSpendKey + , rustWrapperGetOrchardRootTest , rustWrapperOrchardCheck , rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecodeSK -- 2.34.1 From 96ee5f417944b1f1719b5613d2d7cdb9a6f8160b Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 15:24:06 -0500 Subject: [PATCH 40/72] feat: new function to test tree with one node --- librustzcash-wrapper/src/lib.rs | 22 ++++++++++++++++++++++ src/C/Zcash.chs | 8 ++++++++ src/ZcashHaskell/Orchard.hs | 5 +++++ 3 files changed, 35 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index d011e65..3b060fd 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1631,6 +1631,28 @@ pub extern "C" fn rust_wrapper_get_orchard_root( marshall_to_haskell_var(&h, out, out_len, RW); } +#[no_mangle] +pub extern "C" fn rust_wrapper_orchard_add_node( + node: *const u8, + node_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let mut tree: CommitmentTree = CommitmentTree::empty(); + let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); + let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); + if orchard_note_comm.is_some().into() { + let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); + tree.append(n); + let root = tree.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index abb7435..915058f 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -311,6 +311,14 @@ import ZcashHaskell.Types -> `Word64' #} +{# fun unsafe rust_wrapper_orchard_add_node as rustWrapperOrchardAddNodeTest + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' + +#} + {# fun unsafe rust_wrapper_update_sapling_witness as rustWrapperUpdateSaplingWitness { toBorshVar* `BS.ByteString'& , toBorshVar* `[BS.ByteString]'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 4cb8b9e..7e30158 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -22,6 +22,7 @@ import C.Zcash , rustWrapperGenOrchardReceiver , rustWrapperGenOrchardSpendKey , rustWrapperGetOrchardRootTest + , rustWrapperOrchardAddNodeTest , rustWrapperOrchardCheck , rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecodeSK @@ -223,6 +224,10 @@ getOrchardRootTest :: Int -> HexString getOrchardRootTest level = withPureBorshVarBuffer $ rustWrapperGetOrchardRootTest $ fromIntegral level +addOrchardNodeGetRoot :: BS.ByteString -> HexString +addOrchardNodeGetRoot n = + withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest n + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree -- 2.34.1 From 1938e162f46ce7c879ccb3aa5e3eb6bbf7e63969 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 30 Oct 2024 16:24:02 -0500 Subject: [PATCH 41/72] feat: update root testing functions --- librustzcash-wrapper/src/lib.rs | 18 +++++++++++++----- src/C/Zcash.chs | 3 ++- src/ZcashHaskell/Orchard.hs | 6 +++--- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 3b060fd..1b22434 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1626,13 +1626,14 @@ pub extern "C" fn rust_wrapper_get_orchard_root( out_len: &mut usize ){ let tree: CommitmentTree = CommitmentTree::empty(); - let root = tree.root_at_depth(level, PathFiller::empty()); + let root = tree.root(); let h = Hhex { bytes: root.to_bytes().to_vec() }; marshall_to_haskell_var(&h, out, out_len, RW); } #[no_mangle] pub extern "C" fn rust_wrapper_orchard_add_node( + level: u8, node: *const u8, node_len: usize, out: *mut u8, @@ -1643,10 +1644,17 @@ pub extern "C" fn rust_wrapper_orchard_add_node( let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); if orchard_note_comm.is_some().into() { let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); - tree.append(n); - let root = tree.root(); - let h = Hhex { bytes: root.to_bytes().to_vec() }; - marshall_to_haskell_var(&h, out, out_len, RW); + match tree.append(n) { + Ok(()) => { + let root = tree.root_at_depth(level, PathFiller::empty()); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + }, + Err(_) => { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } } else { let h0 = Hhex { bytes: vec![0] }; marshall_to_haskell_var(&h0, out, out_len, RW); diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 915058f..fda259a 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -312,7 +312,8 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_orchard_add_node as rustWrapperOrchardAddNodeTest - { toBorshVar* `BS.ByteString'& + { `Int8' + , toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& } -> `()' diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 7e30158..3fdb25a 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -224,9 +224,9 @@ getOrchardRootTest :: Int -> HexString getOrchardRootTest level = withPureBorshVarBuffer $ rustWrapperGetOrchardRootTest $ fromIntegral level -addOrchardNodeGetRoot :: BS.ByteString -> HexString -addOrchardNodeGetRoot n = - withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest n +addOrchardNodeGetRoot :: Int -> BS.ByteString -> HexString +addOrchardNodeGetRoot l n = + withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest (fromIntegral l) n -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: -- 2.34.1 From 92cc2aabe4e7bb675b97af7f23fb9bdf0b984aab Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 31 Oct 2024 09:28:34 -0500 Subject: [PATCH 42/72] modify tree root validation --- librustzcash-wrapper/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 1b22434..d90351e 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1538,8 +1538,8 @@ pub extern "C" fn rust_wrapper_read_orchard_tree_anchor( ){ let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); - let root = comm_tree.root(None); + let comm_tree: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); + let root = comm_tree.root(); let h = Hhex { bytes: root.to_bytes().to_vec() }; marshall_to_haskell_var(&h, out, out_len, RW); } -- 2.34.1 From c94bce3c25840a65282ec51dba1a00924db761cc Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 31 Oct 2024 10:11:35 -0500 Subject: [PATCH 43/72] add validation of frontier and tree --- librustzcash-wrapper/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index d90351e..93b96ee 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1514,7 +1514,13 @@ pub extern "C" fn rust_wrapper_read_orchard_frontier( Some(f2) => { let (pos, leaf, omm) = f2.clone().into_parts(); let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; - marshall_to_haskell_var(&f, out, out_len, RW); + let comm_tree2: Frontier = Frontier::from_parts(Position::from(f.position), MerkleHashOrchard::from_bytes(&to_array(f.leaf.bytes.clone())).unwrap(), f.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); + if f1.root() == comm_tree2.root() { + marshall_to_haskell_var(&f, out, out_len, RW); + } else { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; + marshall_to_haskell_var(&f0, out, out_len, RW); + } }, None => { let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; -- 2.34.1 From 8f03811fcad2e18aa814ac11e457b887ce4e7e53 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 31 Oct 2024 13:36:28 -0500 Subject: [PATCH 44/72] feat: add orchard comm tree parts functionality --- librustzcash-wrapper/src/lib.rs | 67 +++++++++++++++++++++++++++++++++ src/C/Zcash.chs | 7 ++++ src/ZcashHaskell/Orchard.hs | 20 ++++++++++ src/ZcashHaskell/Types.hs | 15 ++++++++ 4 files changed, 109 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 93b96ee..926aa42 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -717,6 +717,27 @@ impl FromHaskell for Hfrontier { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Htree { + left: Hhex, + right: Hhex, + parents: Vec +} + +impl ToHaskell for Htree { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl FromHaskell for Htree { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Htree::deserialize(buf)?; + Ok(x) + } +} + fn to_array(v: Vec) -> [T; N] { v.try_into().unwrap_or_else(|v: Vec| panic!("Expected a Vec of length {} but it was {}", N, v.len())) } @@ -1550,6 +1571,52 @@ pub extern "C" fn rust_wrapper_read_orchard_tree_anchor( marshall_to_haskell_var(&h, out, out_len, RW); } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_commitment_tree_parts( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree = read_commitment_tree(tree_reader); + match comm_tree { + Ok::, _>(c1) => { + let left = match c1.left() { + Some(x) => { + Hhex { bytes: x.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }; + let right = match c1.right() { + Some(x) => { + Hhex { bytes: x.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }; + let parents = c1.parents().iter().map(|x| match x { + Some(y) => { + Hhex { bytes: y.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }).collect(); + let ht = Htree { left, right, parents}; + marshall_to_haskell_var(&ht, out, out_len, RW); + }, + Err(_e) => { + let ht0 = Htree { left: Hhex { bytes: vec![0] } , right: Hhex { bytes: vec![0] }, parents: vec![Hhex { bytes: vec![0] }]}; + marshall_to_haskell_var(&ht0, out, out_len, RW); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_witness_anchor( wit: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index fda259a..6e721de 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -291,6 +291,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_commitment_tree_parts as rustWrapperReadOrchardTreeParts + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer OrchardRawTree'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_frontier as rustWrapperReadOrchardFrontier { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer OrchardFrontier'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 3fdb25a..6a21eb8 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -31,6 +31,7 @@ import C.Zcash , rustWrapperReadOrchardNode , rustWrapperReadOrchardPosition , rustWrapperReadOrchardTreeAnchor + , rustWrapperReadOrchardTreeParts , rustWrapperReadOrchardWitness , rustWrapperReadOrchardWitnessAnchor , rustWrapperUADecode @@ -228,6 +229,25 @@ addOrchardNodeGetRoot :: Int -> BS.ByteString -> HexString addOrchardNodeGetRoot l n = withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest (fromIntegral l) n +getOrchardTreeParts :: OrchardCommitmentTree -> Maybe OrchardTree +getOrchardTreeParts h = + if isBlank (ort_left tree) && isBlank (ort_right tree) + then Nothing + else Just $ + OrchardTree + (parseHex $ ort_left tree) + (parseHex $ ort_right tree) + (map parseHex (ort_parents tree)) + where + isBlank h = (BS.length $ hexBytes $ h) == 1 + parseHex h = + if (BS.length $ hexBytes $ h) > 1 + then Just h + else Nothing + tree = + withPureBorshVarBuffer $ + rustWrapperReadOrchardTreeParts $ toBytes $ orchTree h + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 324216f..afa6a81 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -727,6 +727,21 @@ newtype OrchardCommitmentTree = OrchardCommitmentTree { orchTree :: HexString } deriving (Eq, Prelude.Show, Read) +data OrchardRawTree = OrchardRawTree + { ort_left :: !HexString + , ort_right :: !HexString + , ort_parents :: ![HexString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardRawTree + +data OrchardTree = OrchardTree + { ot_left :: !(Maybe HexString) + , ot_right :: !(Maybe HexString) + , ot_parents :: ![Maybe HexString] + } deriving (Eq, Prelude.Show, Read) + data OrchardFrontier = OrchardFrontier { of_pos :: !Int64 , of_leaf :: !HexString -- 2.34.1 From 1cdd1d75fad541d300aa5842213410e2d6b35821 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 1 Nov 2024 08:07:29 -0500 Subject: [PATCH 45/72] add validation of orchard anchor --- librustzcash-wrapper/src/lib.rs | 20 ++++++++++++++------ src/C/Zcash.chs | 2 +- src/ZcashHaskell/Orchard.hs | 5 +++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 926aa42..a234c82 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1563,12 +1563,20 @@ pub extern "C" fn rust_wrapper_read_orchard_tree_anchor( out: *mut u8, out_len: &mut usize ){ - let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); - let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let comm_tree: Frontier = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); - let root = comm_tree.root(); - let h = Hhex { bytes: root.to_bytes().to_vec() }; - marshall_to_haskell_var(&h, out, out_len, RW); + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree = read_commitment_tree(tree_reader); + match comm_tree { + Ok::, _>(c1) => { + let root = c1.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + }, + Err(_) => { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } } #[no_mangle] diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 6e721de..9c485d2 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -263,7 +263,7 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_read_orchard_tree_anchor as rustWrapperReadOrchardTreeAnchor - { toBorshVar* `OrchardFrontier'& + { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& } -> `()' diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 6a21eb8..e99e9e3 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -212,9 +212,10 @@ getOrchardFrontier tree = withPureBorshVarBuffer $ rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree -getOrchardTreeAnchor :: OrchardFrontier -> HexString +getOrchardTreeAnchor :: OrchardCommitmentTree -> HexString getOrchardTreeAnchor tree = - withPureBorshVarBuffer $ rustWrapperReadOrchardTreeAnchor tree + withPureBorshVarBuffer $ + rustWrapperReadOrchardTreeAnchor $ toBytes $ orchTree tree getOrchardWitnessAnchor :: OrchardWitness -> HexString getOrchardWitnessAnchor wit = -- 2.34.1 From 70927645e774d53dd04650d68d996670033a8ef1 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 1 Nov 2024 15:44:32 -0500 Subject: [PATCH 46/72] feat: add `MerklePath` --- src/ZcashHaskell/Types.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index afa6a81..f87444d 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -722,6 +722,14 @@ instance FromJSON OrchardAction where a <- obj .: "spendAuthSig" pure $ OrchardAction n r c ephKey encText outText cval a +data MerklePath = MerklePath + { mp_position :: !Int64 + , mp_path :: ![HexString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct MerklePath + -- | Type for a Orchard note commitment tree newtype OrchardCommitmentTree = OrchardCommitmentTree { orchTree :: HexString -- 2.34.1 From b748cba3103c23ff90937c905f7a94c30bb31628 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 4 Nov 2024 14:55:44 -0600 Subject: [PATCH 47/72] feat: add Merkle path tests for orchard --- librustzcash-wrapper/src/lib.rs | 43 +++++++++++++++++++++++++++++++++ src/C/Zcash.chs | 8 ++++++ src/ZcashHaskell/Orchard.hs | 5 ++++ 3 files changed, 56 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a234c82..9054ed0 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -738,6 +738,26 @@ impl FromHaskell for Htree { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hpath { + position: u32, + path: Vec +} + +impl ToHaskell for Hpath { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl FromHaskell for Hpath { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Hpath::deserialize(buf)?; + Ok(x) + } +} + fn to_array(v: Vec) -> [T; N] { v.try_into().unwrap_or_else(|v: Vec| panic!("Expected a Vec of length {} but it was {}", N, v.len())) } @@ -1659,6 +1679,29 @@ pub extern "C" fn rust_wrapper_read_orchard_node( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_path_anchor( + path: *const u8, + path_len: usize, + cmx: *const u8, + cmx_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let path_in: Hpath = marshall_from_haskell_var(path, path_len, RW); + let cmx_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); + let mk_path = orchard::tree::MerklePath::from_parts(path_in.position, to_array(path_in.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); + let nc = ExtractedNoteCommitment::from_bytes(&to_array(cmx_in)); + if nc.is_some().into() { + let anchor = mk_path.root(nc.unwrap()); + let h = Hhex { bytes: anchor.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_combine_orchard_nodes( level: u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 9c485d2..a896a10 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -276,6 +276,14 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_path_anchor as rustWrapperReadOrchardPathAnchor + { toBorshVar* `MerklePath'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_get_orchard_root as rustWrapperGetOrchardRootTest { `Int8' , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index e99e9e3..7991138 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -29,6 +29,7 @@ import C.Zcash , rustWrapperReadOrchardCommitmentTree , rustWrapperReadOrchardFrontier , rustWrapperReadOrchardNode + , rustWrapperReadOrchardPathAnchor , rustWrapperReadOrchardPosition , rustWrapperReadOrchardTreeAnchor , rustWrapperReadOrchardTreeParts @@ -249,6 +250,10 @@ getOrchardTreeParts h = withPureBorshVarBuffer $ rustWrapperReadOrchardTreeParts $ toBytes $ orchTree h +getOrchardPathAnchor :: HexString -> MerklePath -> HexString +getOrchardPathAnchor hex p = + withPureBorshVarBuffer $ rustWrapperReadOrchardPathAnchor p (hexBytes hex) + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree -- 2.34.1 From 1ec6d2df5b09d259ebfbccade4255f13f66233a4 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 4 Nov 2024 15:41:27 -0600 Subject: [PATCH 48/72] feat(rust): add marshalling for Hhex --- librustzcash-wrapper/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 9054ed0..7657829 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -272,6 +272,12 @@ impl ToHaskell for Hhex { } } +impl FromHaskell for Hhex { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Hhex::deserialize(buf)?; + Ok(x) + } +} #[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct Haction { -- 2.34.1 From 9008010db7dc36a88602ff936ddfa38ea684b40d Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 4 Nov 2024 18:38:55 -0600 Subject: [PATCH 49/72] feat: update position size --- src/ZcashHaskell/Types.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index f87444d..8b8a90b 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -723,7 +723,7 @@ instance FromJSON OrchardAction where pure $ OrchardAction n r c ephKey encText outText cval a data MerklePath = MerklePath - { mp_position :: !Int64 + { mp_position :: !Int32 , mp_path :: ![HexString] } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) -- 2.34.1 From 5ce149c54f8e7e53e455536f30dd27a35d05c036 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Nov 2024 18:28:45 +0000 Subject: [PATCH 50/72] Functions to create and manage Orchard commitment trees (#99) This PR contains the functions to create, update and validate Orchard commitment trees. Reviewed-on: https://git.vergara.tech///Vergara_Tech/zcash-haskell/pulls/99 Co-authored-by: Rene Vergara Co-committed-by: Rene Vergara --- librustzcash-wrapper/src/lib.rs | 188 ++++++++++++++++++++++++++++++-- src/C/Zcash.chs | 33 +++++- src/ZcashHaskell/Orchard.hs | 40 ++++++- src/ZcashHaskell/Types.hs | 23 ++++ 4 files changed, 273 insertions(+), 11 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a469cb8..7657829 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -36,7 +36,8 @@ use incrementalmerkletree::{ frontier::{ CommitmentTree, Frontier, - NonEmptyFrontier + NonEmptyFrontier, + PathFiller }, witness::IncrementalWitness }; @@ -271,6 +272,12 @@ impl ToHaskell for Hhex { } } +impl FromHaskell for Hhex { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Hhex::deserialize(buf)?; + Ok(x) + } +} #[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct Haction { @@ -716,6 +723,47 @@ impl FromHaskell for Hfrontier { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Htree { + left: Hhex, + right: Hhex, + parents: Vec +} + +impl ToHaskell for Htree { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl FromHaskell for Htree { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Htree::deserialize(buf)?; + Ok(x) + } +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hpath { + position: u32, + path: Vec +} + +impl ToHaskell for Hpath { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl FromHaskell for Hpath { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Hpath::deserialize(buf)?; + Ok(x) + } +} + fn to_array(v: Vec) -> [T; N] { v.try_into().unwrap_or_else(|v: Vec| panic!("Expected a Vec of length {} but it was {}", N, v.len())) } @@ -1513,7 +1561,13 @@ pub extern "C" fn rust_wrapper_read_orchard_frontier( Some(f2) => { let (pos, leaf, omm) = f2.clone().into_parts(); let f = Hfrontier { position: ::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()}; - marshall_to_haskell_var(&f, out, out_len, RW); + let comm_tree2: Frontier = Frontier::from_parts(Position::from(f.position), MerkleHashOrchard::from_bytes(&to_array(f.leaf.bytes.clone())).unwrap(), f.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); + if f1.root() == comm_tree2.root() { + marshall_to_haskell_var(&f, out, out_len, RW); + } else { + let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; + marshall_to_haskell_var(&f0, out, out_len, RW); + } }, None => { let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]}; @@ -1535,12 +1589,66 @@ pub extern "C" fn rust_wrapper_read_orchard_tree_anchor( out: *mut u8, out_len: &mut usize ){ - let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW); - let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap(); - let comm_tree: NonEmptyFrontier = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap(); - let root = comm_tree.root(None); - let h = Hhex { bytes: root.to_bytes().to_vec() }; - marshall_to_haskell_var(&h, out, out_len, RW); + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree = read_commitment_tree(tree_reader); + match comm_tree { + Ok::, _>(c1) => { + let root = c1.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + }, + Err(_) => { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_commitment_tree_parts( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree = read_commitment_tree(tree_reader); + match comm_tree { + Ok::, _>(c1) => { + let left = match c1.left() { + Some(x) => { + Hhex { bytes: x.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }; + let right = match c1.right() { + Some(x) => { + Hhex { bytes: x.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }; + let parents = c1.parents().iter().map(|x| match x { + Some(y) => { + Hhex { bytes: y.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }).collect(); + let ht = Htree { left, right, parents}; + marshall_to_haskell_var(&ht, out, out_len, RW); + }, + Err(_e) => { + let ht0 = Htree { left: Hhex { bytes: vec![0] } , right: Hhex { bytes: vec![0] }, parents: vec![Hhex { bytes: vec![0] }]}; + marshall_to_haskell_var(&ht0, out, out_len, RW); + } + } } #[no_mangle] @@ -1577,6 +1685,29 @@ pub extern "C" fn rust_wrapper_read_orchard_node( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_path_anchor( + path: *const u8, + path_len: usize, + cmx: *const u8, + cmx_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let path_in: Hpath = marshall_from_haskell_var(path, path_len, RW); + let cmx_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); + let mk_path = orchard::tree::MerklePath::from_parts(path_in.position, to_array(path_in.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); + let nc = ExtractedNoteCommitment::from_bytes(&to_array(cmx_in)); + if nc.is_some().into() { + let anchor = mk_path.root(nc.unwrap()); + let h = Hhex { bytes: anchor.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_combine_orchard_nodes( level: u8, @@ -1618,6 +1749,47 @@ pub extern "C" fn rust_wrapper_combine_orchard_nodes( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_get_orchard_root( + level: u8, + out: *mut u8, + out_len: &mut usize + ){ + let tree: CommitmentTree = CommitmentTree::empty(); + let root = tree.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_orchard_add_node( + level: u8, + node: *const u8, + node_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let mut tree: CommitmentTree = CommitmentTree::empty(); + let node_in: Vec = marshall_from_haskell_var(node, node_len, RW); + let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in)); + if orchard_note_comm.is_some().into() { + let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap()); + match tree.append(n) { + Ok(()) => { + let root = tree.root_at_depth(level, PathFiller::empty()); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + }, + Err(_) => { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index da2f86b..a896a10 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -263,7 +263,7 @@ import ZcashHaskell.Types #} {# fun unsafe rust_wrapper_read_orchard_tree_anchor as rustWrapperReadOrchardTreeAnchor - { toBorshVar* `OrchardFrontier'& + { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& } -> `()' @@ -276,6 +276,21 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_path_anchor as rustWrapperReadOrchardPathAnchor + { toBorshVar* `MerklePath'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_get_orchard_root as rustWrapperGetOrchardRootTest + { `Int8' + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree { toBorshVar* `OrchardFrontier'& , toBorshVar* `BS.ByteString'& @@ -284,6 +299,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_commitment_tree_parts as rustWrapperReadOrchardTreeParts + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer OrchardRawTree'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_frontier as rustWrapperReadOrchardFrontier { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer OrchardFrontier'& @@ -304,6 +326,15 @@ import ZcashHaskell.Types -> `Word64' #} +{# fun unsafe rust_wrapper_orchard_add_node as rustWrapperOrchardAddNodeTest + { `Int8' + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' + +#} + {# fun unsafe rust_wrapper_update_sapling_witness as rustWrapperUpdateSaplingWitness { toBorshVar* `BS.ByteString'& , toBorshVar* `[BS.ByteString]'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 79043ea..7991138 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -21,14 +21,18 @@ import C.Zcash ( rustWrapperCombineOrchardNodes , rustWrapperGenOrchardReceiver , rustWrapperGenOrchardSpendKey + , rustWrapperGetOrchardRootTest + , rustWrapperOrchardAddNodeTest , rustWrapperOrchardCheck , rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecodeSK , rustWrapperReadOrchardCommitmentTree , rustWrapperReadOrchardFrontier , rustWrapperReadOrchardNode + , rustWrapperReadOrchardPathAnchor , rustWrapperReadOrchardPosition , rustWrapperReadOrchardTreeAnchor + , rustWrapperReadOrchardTreeParts , rustWrapperReadOrchardWitness , rustWrapperReadOrchardWitnessAnchor , rustWrapperUADecode @@ -209,15 +213,47 @@ getOrchardFrontier tree = withPureBorshVarBuffer $ rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree -getOrchardTreeAnchor :: OrchardFrontier -> HexString +getOrchardTreeAnchor :: OrchardCommitmentTree -> HexString getOrchardTreeAnchor tree = - withPureBorshVarBuffer $ rustWrapperReadOrchardTreeAnchor tree + withPureBorshVarBuffer $ + rustWrapperReadOrchardTreeAnchor $ toBytes $ orchTree tree getOrchardWitnessAnchor :: OrchardWitness -> HexString getOrchardWitnessAnchor wit = withPureBorshVarBuffer $ rustWrapperReadOrchardWitnessAnchor $ toBytes $ orchWit wit +getOrchardRootTest :: Int -> HexString +getOrchardRootTest level = + withPureBorshVarBuffer $ rustWrapperGetOrchardRootTest $ fromIntegral level + +addOrchardNodeGetRoot :: Int -> BS.ByteString -> HexString +addOrchardNodeGetRoot l n = + withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest (fromIntegral l) n + +getOrchardTreeParts :: OrchardCommitmentTree -> Maybe OrchardTree +getOrchardTreeParts h = + if isBlank (ort_left tree) && isBlank (ort_right tree) + then Nothing + else Just $ + OrchardTree + (parseHex $ ort_left tree) + (parseHex $ ort_right tree) + (map parseHex (ort_parents tree)) + where + isBlank h = (BS.length $ hexBytes $ h) == 1 + parseHex h = + if (BS.length $ hexBytes $ h) > 1 + then Just h + else Nothing + tree = + withPureBorshVarBuffer $ + rustWrapperReadOrchardTreeParts $ toBytes $ orchTree h + +getOrchardPathAnchor :: HexString -> MerklePath -> HexString +getOrchardPathAnchor hex p = + withPureBorshVarBuffer $ rustWrapperReadOrchardPathAnchor p (hexBytes hex) + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 324216f..8b8a90b 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -722,11 +722,34 @@ instance FromJSON OrchardAction where a <- obj .: "spendAuthSig" pure $ OrchardAction n r c ephKey encText outText cval a +data MerklePath = MerklePath + { mp_position :: !Int32 + , mp_path :: ![HexString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct MerklePath + -- | Type for a Orchard note commitment tree newtype OrchardCommitmentTree = OrchardCommitmentTree { orchTree :: HexString } deriving (Eq, Prelude.Show, Read) +data OrchardRawTree = OrchardRawTree + { ort_left :: !HexString + , ort_right :: !HexString + , ort_parents :: ![HexString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardRawTree + +data OrchardTree = OrchardTree + { ot_left :: !(Maybe HexString) + , ot_right :: !(Maybe HexString) + , ot_parents :: ![Maybe HexString] + } deriving (Eq, Prelude.Show, Read) + data OrchardFrontier = OrchardFrontier { of_pos :: !Int64 , of_leaf :: !HexString -- 2.34.1 From 62cda9cc15621dead6fbfd7a4944840408d69da4 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Nov 2024 12:42:03 -0600 Subject: [PATCH 51/72] docs: version bump --- CHANGELOG.md | 6 ++++++ zcash-haskell.cabal | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f3a7e4..3cbfed3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.4.0] + +### Added + +- `MerklePath` + ## [0.7.3.0] ### Added diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 36ce2ae..3216af8 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.3.0 +version: 0.7.4.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From ef8dba474e263f330f7ab173bcea4e40c3e30803 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Nov 2024 14:35:19 -0600 Subject: [PATCH 52/72] feat: add sapling node creation --- librustzcash-wrapper/src/lib.rs | 19 +++++++++++++++++++ src/C/Zcash.chs | 7 +++++++ src/ZcashHaskell/Sapling.hs | 9 +++++++++ 3 files changed, 35 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 7657829..feeb16c 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1542,6 +1542,25 @@ pub extern "C" fn rust_wrapper_update_sapling_witness( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_sapling_node( + cmu: *const u8, + cmu_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let node_in: Vec = marshall_from_haskell_var(cmu, cmu_len, RW); + let sapling_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in)); + if sapling_note_comm.is_some().into() { + let n = Node::from_cmu(&sapling_note_comm.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec()}; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_frontier( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index a896a10..48e3189 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -246,6 +246,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_sapling_node as rustWrapperReadSaplingNode + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index e15bf4f..8cbe12c 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -22,6 +22,7 @@ import C.Zcash , rustWrapperIsShielded , rustWrapperReadSaplingCommitmentTree , rustWrapperReadSaplingFrontier + , rustWrapperReadSaplingNode , rustWrapperReadSaplingPosition , rustWrapperReadSaplingWitness , rustWrapperSaplingCheck @@ -185,6 +186,14 @@ genSaplingInternalAddress sk = res = withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk) +getSaplingNodeValue :: BS.ByteString -> Maybe HexString +getSaplingNodeValue cmu = + if BS.length (hexBytes n) > 1 + then Just n + else Nothing + where + n = withPureBorshVarBuffer $ rustWrapperReadSaplingNode cmu + getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier getSaplingFrontier tree = if sf_pos updatedTree > 1 -- 2.34.1 From 93622f445615ae89490be63fa09324fb8bd370f6 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Nov 2024 15:35:56 -0600 Subject: [PATCH 53/72] feat: add Sapling node combinator --- CHANGELOG.md | 6 +++++ librustzcash-wrapper/src/lib.rs | 41 +++++++++++++++++++++++++++++++++ src/C/Zcash.chs | 9 ++++++++ src/ZcashHaskell/Sapling.hs | 14 ++++++++++- zcash-haskell.cabal | 2 +- 5 files changed, 70 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cbfed3..c817ca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.5.0] + +### Added + +- Sapling commitment node functions + ## [0.7.4.0] ### Added diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index feeb16c..8170650 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1561,6 +1561,47 @@ pub extern "C" fn rust_wrapper_read_sapling_node( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_combine_sapling_nodes( + level: u8, + left: *const u8, + left_len: usize, + right: *const u8, + right_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let left_in: Vec = marshall_from_haskell_var(left, left_len, RW); + let right_in: Vec = marshall_from_haskell_var(right, right_len, RW); + if left_in.len() == 1 { + let n = Node::combine(Level::new(level), &Node::empty_leaf(), &Node::empty_leaf()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let left_node = Node::from_bytes(to_array(left_in)); + if left_node.is_some().into() { + if right_in.len() > 1 { + let right_node = Node::from_bytes(to_array(right_in)); + if right_node.is_some().into() { + let n = Node::combine(Level::new(level), &left_node.unwrap(), &right_node.unwrap()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } else { + let n = Node::combine(Level::new(level), &left_node.unwrap(), &Node::empty_leaf()); + let h = Hhex { bytes: n.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_frontier( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 48e3189..06b486a 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -253,6 +253,15 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_combine_sapling_nodes as rustWrapperCombineSaplingNodes + { `Int8' + , toBorshVar* `BS.ByteString'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index 8cbe12c..c7fe8e2 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -18,7 +18,8 @@ module ZcashHaskell.Sapling where import C.Zcash - ( rustWrapperDecodeSaplingAddress + ( rustWrapperCombineSaplingNodes + , rustWrapperDecodeSaplingAddress , rustWrapperIsShielded , rustWrapperReadSaplingCommitmentTree , rustWrapperReadSaplingFrontier @@ -39,6 +40,7 @@ import Data.Aeson import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as C import Data.HexString (HexString(..), fromText, hexString, toBytes, toText) +import Data.Int (Int8) import qualified Data.Text as T import Data.Word import Foreign.Rust.Marshall.Variable @@ -194,6 +196,16 @@ getSaplingNodeValue cmu = where n = withPureBorshVarBuffer $ rustWrapperReadSaplingNode cmu +combineSaplingNodes :: Int8 -> HexString -> HexString -> Maybe HexString +combineSaplingNodes level n1 n2 = + if BS.length (hexBytes r) > 1 + then Just r + else Nothing + where + r = + withPureBorshVarBuffer $ + rustWrapperCombineSaplingNodes level (toBytes n1) (toBytes n2) + getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier getSaplingFrontier tree = if sf_pos updatedTree > 1 diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 3216af8..c1d1d82 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.4.0 +version: 0.7.5.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From 00782b80c07993d877174b352d1d0c7b07651179 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 6 Nov 2024 07:29:48 -0600 Subject: [PATCH 54/72] feat: add sapling tree root test --- librustzcash-wrapper/src/lib.rs | 12 ++++++++++++ src/C/Zcash.chs | 7 +++++++ src/ZcashHaskell/Sapling.hs | 5 +++++ 3 files changed, 24 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 8170650..7a03a49 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1602,6 +1602,18 @@ pub extern "C" fn rust_wrapper_combine_sapling_nodes( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_get_sapling_root( + level: u8, + out: *mut u8, + out_len: &mut usize + ){ + let tree: CommitmentTree = CommitmentTree::empty(); + let root = tree.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_frontier( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 06b486a..8e8947b 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -262,6 +262,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_get_sapling_root as rustWrapperGetSaplingRootTest + { `Int8' + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index c7fe8e2..362a8e9 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -20,6 +20,7 @@ module ZcashHaskell.Sapling where import C.Zcash ( rustWrapperCombineSaplingNodes , rustWrapperDecodeSaplingAddress + , rustWrapperGetSaplingRootTest , rustWrapperIsShielded , rustWrapperReadSaplingCommitmentTree , rustWrapperReadSaplingFrontier @@ -206,6 +207,10 @@ combineSaplingNodes level n1 n2 = withPureBorshVarBuffer $ rustWrapperCombineSaplingNodes level (toBytes n1) (toBytes n2) +getSaplingRootTest :: Int8 -> HexString +getSaplingRootTest level = + withPureBorshVarBuffer $ rustWrapperGetSaplingRootTest level + getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier getSaplingFrontier tree = if sf_pos updatedTree > 1 -- 2.34.1 From a13eab17d7b5765d820f96f81ec177893e79b263 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 6 Nov 2024 13:17:58 -0600 Subject: [PATCH 55/72] feat: add sapling commitment trees --- librustzcash-wrapper/src/lib.rs | 46 +++++++++++++++++++++++++++++++++ src/C/Zcash.chs | 7 +++++ src/ZcashHaskell/Sapling.hs | 20 ++++++++++++++ src/ZcashHaskell/Types.hs | 15 +++++++++++ 4 files changed, 88 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 7a03a49..903c256 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1614,6 +1614,52 @@ pub extern "C" fn rust_wrapper_get_sapling_root( marshall_to_haskell_var(&h, out, out_len, RW); } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_sapling_commitment_tree_parts( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree = read_commitment_tree(tree_reader); + match comm_tree { + Ok::, _>(c1) => { + let left = match c1.left() { + Some(x) => { + Hhex { bytes: x.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }; + let right = match c1.right() { + Some(x) => { + Hhex { bytes: x.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }; + let parents = c1.parents().iter().map(|x| match x { + Some(y) => { + Hhex { bytes: y.to_bytes().to_vec() } + }, + None => { + Hhex { bytes: vec![0] } + } + }).collect(); + let ht = Htree { left, right, parents}; + marshall_to_haskell_var(&ht, out, out_len, RW); + }, + Err(_e) => { + let ht0 = Htree { left: Hhex { bytes: vec![0] } , right: Hhex { bytes: vec![0] }, parents: vec![Hhex { bytes: vec![0] }]}; + marshall_to_haskell_var(&ht0, out, out_len, RW); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_frontier( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 8e8947b..0bcdf6d 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -269,6 +269,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_sapling_commitment_tree_parts as rustWrapperReadSaplingTreeParts + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer SaplingRawTree'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index 362a8e9..f0b743c 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -26,6 +26,7 @@ import C.Zcash , rustWrapperReadSaplingFrontier , rustWrapperReadSaplingNode , rustWrapperReadSaplingPosition + , rustWrapperReadSaplingTreeParts , rustWrapperReadSaplingWitness , rustWrapperSaplingCheck , rustWrapperSaplingChgPaymentAddress @@ -211,6 +212,25 @@ getSaplingRootTest :: Int8 -> HexString getSaplingRootTest level = withPureBorshVarBuffer $ rustWrapperGetSaplingRootTest level +getSaplingTreeParts :: SaplingCommitmentTree -> Maybe SaplingTree +getSaplingTreeParts h = + if isBlank (srt_left tree) && isBlank (srt_right tree) + then Nothing + else Just $ + SaplingTree + (parseHex $ srt_left tree) + (parseHex $ srt_right tree) + (map parseHex (srt_parents tree)) + where + isBlank h = (BS.length $ hexBytes $ h) == 1 + parseHex h = + if (BS.length $ hexBytes $ h) > 1 + then Just h + else Nothing + tree = + withPureBorshVarBuffer $ + rustWrapperReadSaplingTreeParts $ toBytes $ sapTree h + getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier getSaplingFrontier tree = if sf_pos updatedTree > 1 diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 8b8a90b..0226ea1 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -611,6 +611,21 @@ newtype SaplingCommitmentTree = SaplingCommitmentTree { sapTree :: HexString } deriving (Eq, Prelude.Show, Read) +data SaplingRawTree = SaplingRawTree + { srt_left :: !HexString + , srt_right :: !HexString + , srt_parents :: ![HexString] + } deriving stock (Eq, Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct SaplingRawTree + +data SaplingTree = SaplingTree + { ot_left :: !(Maybe HexString) + , ot_right :: !(Maybe HexString) + , ot_parents :: ![Maybe HexString] + } deriving (Eq, Prelude.Show, Read) + data SaplingFrontier = SaplingFrontier { sf_pos :: !Int64 , sf_leaf :: !HexString -- 2.34.1 From 4c3a188c32330c1a12a5e01d3083bd523292bb5f Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 6 Nov 2024 14:02:24 -0600 Subject: [PATCH 56/72] fix: sapling tree field names --- src/ZcashHaskell/Types.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 0226ea1..ada4a58 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -621,9 +621,9 @@ data SaplingRawTree = SaplingRawTree deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct SaplingRawTree data SaplingTree = SaplingTree - { ot_left :: !(Maybe HexString) - , ot_right :: !(Maybe HexString) - , ot_parents :: ![Maybe HexString] + { st_left :: !(Maybe HexString) + , st_right :: !(Maybe HexString) + , st_parents :: ![Maybe HexString] } deriving (Eq, Prelude.Show, Read) data SaplingFrontier = SaplingFrontier -- 2.34.1 From 1dcc549bd5f59290897ce21b40a60c3d7cd4644c Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 6 Nov 2024 15:48:50 -0600 Subject: [PATCH 57/72] feat: add sapling tree anchor function --- librustzcash-wrapper/src/lib.rs | 23 +++++++++++++++++++++++ src/C/Zcash.chs | 7 +++++++ src/ZcashHaskell/Sapling.hs | 6 ++++++ 3 files changed, 36 insertions(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 903c256..2c1b644 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1660,6 +1660,29 @@ pub extern "C" fn rust_wrapper_read_sapling_commitment_tree_parts( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_sapling_tree_anchor( + tree: *const u8, + tree_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let tree_in: Vec = marshall_from_haskell_var(tree, tree_len, RW); + let tree_reader = Cursor::new(tree_in); + let comm_tree = read_commitment_tree(tree_reader); + match comm_tree { + Ok::, _>(c1) => { + let root = c1.root(); + let h = Hhex { bytes: root.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + }, + Err(_) => { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_frontier( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 0bcdf6d..6d915bb 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -276,6 +276,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_sapling_tree_anchor as rustWrapperReadSaplingTreeAnchor + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index f0b743c..87b21f7 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -26,6 +26,7 @@ import C.Zcash , rustWrapperReadSaplingFrontier , rustWrapperReadSaplingNode , rustWrapperReadSaplingPosition + , rustWrapperReadSaplingTreeAnchor , rustWrapperReadSaplingTreeParts , rustWrapperReadSaplingWitness , rustWrapperSaplingCheck @@ -231,6 +232,11 @@ getSaplingTreeParts h = withPureBorshVarBuffer $ rustWrapperReadSaplingTreeParts $ toBytes $ sapTree h +getSaplingTreeAnchor :: SaplingCommitmentTree -> HexString +getSaplingTreeAnchor tree = + withPureBorshVarBuffer $ + rustWrapperReadSaplingTreeAnchor $ toBytes $ sapTree tree + getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier getSaplingFrontier tree = if sf_pos updatedTree > 1 -- 2.34.1 From 8244ffa1cec822a6e0db108ec72ed5f268297eee Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 7 Nov 2024 12:13:52 -0600 Subject: [PATCH 58/72] feat: add sapling merkle path test --- CHANGELOG.md | 1 + librustzcash-wrapper/src/lib.rs | 31 +++++++++++++++++++++++++++++++ src/C/Zcash.chs | 8 ++++++++ src/ZcashHaskell/Sapling.hs | 5 +++++ 4 files changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c817ca1..5c1328f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Sapling commitment node functions +- Sapling Merkle path test ## [0.7.4.0] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 2c1b644..165b144 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1683,6 +1683,37 @@ pub extern "C" fn rust_wrapper_read_sapling_tree_anchor( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_sapling_path_anchor( + path: *const u8, + path_len: usize, + cmx: *const u8, + cmx_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let path_in: Hpath = marshall_from_haskell_var(path, path_len, RW); + let cmx_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); + let mk_path = sapling_crypto::MerklePath::from_parts(path_in.path.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap()).collect(), Position::from(u64::from(path_in.position))); + match mk_path { + Ok(mp1) => { + let nc = SaplingNoteCommitment::from_bytes(&to_array(cmx_in)); + if nc.is_some().into() { + let anchor = mp1.root(Node::from_cmu(&nc.unwrap())); + let h = Hhex { bytes: anchor.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + }, + Err(_e) =>{ + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_read_orchard_frontier( tree: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 6d915bb..fde4550 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -283,6 +283,14 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_sapling_path_anchor as rustWrapperReadSaplingPathAnchor + { toBorshVar* `MerklePath'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index 87b21f7..1347778 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -25,6 +25,7 @@ import C.Zcash , rustWrapperReadSaplingCommitmentTree , rustWrapperReadSaplingFrontier , rustWrapperReadSaplingNode + , rustWrapperReadSaplingPathAnchor , rustWrapperReadSaplingPosition , rustWrapperReadSaplingTreeAnchor , rustWrapperReadSaplingTreeParts @@ -237,6 +238,10 @@ getSaplingTreeAnchor tree = withPureBorshVarBuffer $ rustWrapperReadSaplingTreeAnchor $ toBytes $ sapTree tree +getSaplingPathAnchor :: HexString -> MerklePath -> HexString +getSaplingPathAnchor hex p = + withPureBorshVarBuffer $ rustWrapperReadSaplingPathAnchor p (hexBytes hex) + getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier getSaplingFrontier tree = if sf_pos updatedTree > 1 -- 2.34.1 From 20851a4e48f768a492796fb828f16ae9745931dc Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 7 Nov 2024 12:54:22 -0600 Subject: [PATCH 59/72] fix(rust): account for empty leaf in sapling path --- librustzcash-wrapper/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 165b144..6c4095f 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1694,7 +1694,12 @@ pub extern "C" fn rust_wrapper_read_sapling_path_anchor( ){ let path_in: Hpath = marshall_from_haskell_var(path, path_len, RW); let cmx_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); - let mk_path = sapling_crypto::MerklePath::from_parts(path_in.path.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap()).collect(), Position::from(u64::from(path_in.position))); + let mk_path = sapling_crypto::MerklePath::from_parts(path_in.path.iter().map(|x| + if x.bytes.len() > 1 { + Node::from_bytes(to_array(x.bytes.clone())).unwrap() + } else { + Node::empty_leaf() + }).collect(), Position::from(u64::from(path_in.position))); match mk_path { Ok(mp1) => { let nc = SaplingNoteCommitment::from_bytes(&to_array(cmx_in)); -- 2.34.1 From 1ce7dc24feb8fc7063a49e3fd9f8e5e0512cba2f Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 11 Nov 2024 11:21:24 -0600 Subject: [PATCH 60/72] feat: Implement transaction creation with new trees --- librustzcash-wrapper/src/lib.rs | 70 ++++++++++++--------------------- src/ZcashHaskell/Types.hs | 4 +- src/ZcashHaskell/Utils.hs | 12 ++---- 3 files changed, 31 insertions(+), 55 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 6c4095f..1e99fbe 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -570,11 +570,11 @@ impl Hspend { } } -#[derive(Debug, BorshSerialize, BorshDeserialize)] +#[derive(BorshSerialize, BorshDeserialize)] pub struct HsaplingInput { sk: Vec, note: Hnote, - iw: Vec + iw: Hpath } impl FromHaskell for HsaplingInput { @@ -585,11 +585,11 @@ impl FromHaskell for HsaplingInput { } -#[derive(Debug, BorshSerialize, BorshDeserialize)] +#[derive(BorshSerialize, BorshDeserialize)] pub struct HorchardInput { sk: Vec, note: Hnote, - iw: Vec + iw: Hpath } impl FromHaskell for HorchardInput { @@ -2144,47 +2144,25 @@ pub extern "C" fn rust_wrapper_create_transaction( out: *mut u8, out_len: &mut usize){ let sap_input: Vec = marshall_from_haskell_var(s_input, s_input_len, RW); - let sap_anchor = - if sap_input.is_empty() { - let sap_wit_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); - let sap_wit_reader = Cursor::new(sap_wit_in); - let sap_iw = read_commitment_tree::>, SAPLING_DEPTH>(sap_wit_reader); - match sap_iw { - Ok(s_iw) => { - Some(SaplingAnchor::from(s_iw.root())) - }, - Err(_e) => { - None - } - } + let sap_anchor_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); + let sap_anchor = SaplingAnchor::from_bytes(to_array(sap_anchor_in)); + let sapling_anchor = + if sap_anchor.is_some().into() { + Some(sap_anchor.unwrap()) } else { - let si = &sap_input[0]; - let swit_reader = Cursor::new(&si.iw); - let iw: IncrementalWitness = read_incremental_witness(swit_reader).unwrap(); - Some(SaplingAnchor::from(iw.root())) + None }; //println!("{:?}", sap_anchor); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); - let orch_anchor = - if orch_input.is_empty() { - let orch_wit_in: Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); - let orch_wit_reader = Cursor::new(orch_wit_in); - let orch_iw = read_commitment_tree::>, 32>(orch_wit_reader); - match orch_iw { - Ok(o_iw) => { - Some(OrchardAnchor::from(o_iw.root())) - }, - Err(_e) => { - None - } - } + let orch_anchor_in : Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); + let orch_anchor = OrchardAnchor::from_bytes(to_array(orch_anchor_in)); + let orchard_anchor = + if orch_anchor.is_some().into() { + Some(orch_anchor.unwrap()) } else { - let oi = &orch_input[0]; - let wit_reader = Cursor::new(&oi.iw); - let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); - Some(OrchardAnchor::from(iw.root())) + None }; - let build_config = BuildConfig::Standard {sapling_anchor: sap_anchor, orchard_anchor: orch_anchor}; + let build_config = BuildConfig::Standard {sapling_anchor, orchard_anchor}; let mut main_builder = Builder::new(MainNetwork, BlockHeight::from(bl_height), build_config); let mut test_builder = Builder::new(TestNetwork, BlockHeight::from(bl_height), build_config); let trans_input: Vec = marshall_from_haskell_var(t_input, t_input_len, RW); @@ -2224,9 +2202,13 @@ pub extern "C" fn rust_wrapper_create_transaction( Rseed::AfterZip212(to_array(s_in.note.rseed.bytes)) }; let note = SaplingNote::from_parts(pay_addr, SaplingNoteValue::from_raw(s_in.note.note), rseed); - let wit_reader = Cursor::new(s_in.iw); - let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); - let merkle_path = iw.path().unwrap(); + let mk_path = sapling_crypto::MerklePath::from_parts(s_in.iw.path.iter().map(|x| + if x.bytes.len() > 1 { + Node::from_bytes(to_array(x.bytes.clone())).unwrap() + } else { + Node::empty_leaf() + }).collect(), Position::from(u64::from(s_in.iw.position))); + let merkle_path = mk_path.unwrap(); if net { let mb = main_builder.add_sapling_spend::(&sk, note, merkle_path); match mb { @@ -2267,9 +2249,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let val = NoteValue::from_raw(o_in.note.note); //println!("o inp: {:?}", val); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); - let wit_reader = Cursor::new(o_in.iw); - let iw: IncrementalWitness = read_incremental_witness(wit_reader).unwrap(); - let merkle_path = OrchardMerklePath::from(iw.path().unwrap()); + let merkle_path = orchard::tree::MerklePath::from_parts(o_in.iw.position, to_array(o_in.iw.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); if net { let mb = main_builder.add_orchard_spend::(&sp_key, note, merkle_path); match mb { diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index ada4a58..1c55a73 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -812,7 +812,7 @@ data TransparentTxSpend = TransparentTxSpend data SaplingTxSpend = SaplingTxSpend { ss_sk :: !BS.ByteString , ss_note :: !DecodedNote - , ss_iw :: !BS.ByteString + , ss_iw :: !MerklePath } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (Data.Structured.Show) @@ -821,7 +821,7 @@ data SaplingTxSpend = SaplingTxSpend data OrchardTxSpend = OrchardTxSpend { ss_sk :: !BS.ByteString , ss_note :: !DecodedNote - , ss_iw :: !BS.ByteString + , ss_iw :: !MerklePath } deriving stock (Eq, Prelude.Show, GHC.Generic) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (Data.Structured.Show) diff --git a/src/ZcashHaskell/Utils.hs b/src/ZcashHaskell/Utils.hs index ee0a0d9..03db2b5 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -123,8 +123,8 @@ readZebraTransaction hex = rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex createTransaction :: - Maybe SaplingCommitmentTree -- ^ to obtain the Sapling anchor - -> Maybe OrchardCommitmentTree -- ^ to obtain the Orchard anchor + HexString -- ^ to obtain the Sapling anchor + -> HexString -- ^ to obtain the Orchard anchor -> [TransparentTxSpend] -- ^ the list of transparent notes to spend -> [SaplingTxSpend] -- ^ the list of Sapling notes to spend -> [OrchardTxSpend] -- ^ the list of Orchard notes to spend @@ -137,12 +137,8 @@ createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh bui txResult <- withBorshBufferOfInitSize 51200 $ rustWrapperCreateTx - (case sapAnchor of - Nothing -> "0" - Just sA -> toBytes $ sapTree sA) - (case orchAnchor of - Nothing -> "0" - Just oA -> toBytes $ orchTree oA) + (hexBytes sapAnchor) + (hexBytes orchAnchor) tSpend sSpend oSpend -- 2.34.1 From 58951db64a0927d0004b2c33b573ae04c1cd0ef8 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 14:32:23 -0600 Subject: [PATCH 61/72] docs: add debugging --- librustzcash-wrapper/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 1e99fbe..64908d7 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2418,6 +2418,7 @@ pub extern "C" fn rust_wrapper_create_transaction( Err(e) => { match e { Error::InsufficientFunds(y) => { + println!("ins funds: {:?}", y); let x = Hhex {bytes: vec![0]}; marshall_to_haskell_var(&x, out, out_len, RW); }, -- 2.34.1 From 42f3e3a7fd03b279a1c968e632df8adef846deea Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 14:53:59 -0600 Subject: [PATCH 62/72] docs: add debugging --- librustzcash-wrapper/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 64908d7..9b446f6 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2247,7 +2247,7 @@ pub extern "C" fn rust_wrapper_create_transaction( let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); let val = NoteValue::from_raw(o_in.note.note); - //println!("o inp: {:?}", val); + println!("o inp: {:?}", val); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); let merkle_path = orchard::tree::MerklePath::from_parts(o_in.iw.position, to_array(o_in.iw.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); if net { -- 2.34.1 From 107e1fa6e5f479a795d279546ec1c90ed49b7d3a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 14:56:41 -0600 Subject: [PATCH 63/72] add debugging --- librustzcash-wrapper/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 9b446f6..04eb794 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2152,7 +2152,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } else { None }; - //println!("{:?}", sap_anchor); + println!("{:?}", sapling_anchor); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); let orch_anchor_in : Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); let orch_anchor = OrchardAnchor::from_bytes(to_array(orch_anchor_in)); @@ -2162,6 +2162,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } else { None }; + println!("{:?}", orchard_anchor); let build_config = BuildConfig::Standard {sapling_anchor, orchard_anchor}; let mut main_builder = Builder::new(MainNetwork, BlockHeight::from(bl_height), build_config); let mut test_builder = Builder::new(TestNetwork, BlockHeight::from(bl_height), build_config); -- 2.34.1 From 442d2adfad2154dca02a50e368a3e6b13560d67b Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 15:10:47 -0600 Subject: [PATCH 64/72] update anchors for builder --- librustzcash-wrapper/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 04eb794..0433ee7 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2145,20 +2145,20 @@ pub extern "C" fn rust_wrapper_create_transaction( out_len: &mut usize){ let sap_input: Vec = marshall_from_haskell_var(s_input, s_input_len, RW); let sap_anchor_in: Vec = marshall_from_haskell_var(sap_wit, sap_wit_len, RW); - let sap_anchor = SaplingAnchor::from_bytes(to_array(sap_anchor_in)); + let sap_anchor = Node::from_bytes(to_array(sap_anchor_in)); let sapling_anchor = if sap_anchor.is_some().into() { - Some(sap_anchor.unwrap()) + Some(SaplingAnchor::from(sap_anchor.unwrap())) } else { None }; println!("{:?}", sapling_anchor); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); let orch_anchor_in : Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); - let orch_anchor = OrchardAnchor::from_bytes(to_array(orch_anchor_in)); + let orch_anchor = MerkleHashOrchard::from_bytes(&to_array(orch_anchor_in)); let orchard_anchor = if orch_anchor.is_some().into() { - Some(orch_anchor.unwrap()) + Some(OrchardAnchor::from(orch_anchor.unwrap())) } else { None }; -- 2.34.1 From a5898d04f8a43bb99e210b13e6909bf79eb570af Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 15:40:58 -0600 Subject: [PATCH 65/72] add debugging --- librustzcash-wrapper/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 0433ee7..24912ba 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2363,7 +2363,7 @@ pub extern "C" fn rust_wrapper_create_transaction( }; let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap(); let val = output.amt; - //println!("o out: {:?} {:?}", val, output.chg); + println!("o out: {:?} {:?}", val, output.chg); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); if net { let mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); -- 2.34.1 From 0171b5ec5af08852f87ec46cd4bb618f5330f570 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 16:01:53 -0600 Subject: [PATCH 66/72] add debugging --- librustzcash-wrapper/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 24912ba..1549e16 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2255,9 +2255,11 @@ pub extern "C" fn rust_wrapper_create_transaction( let mb = main_builder.add_orchard_spend::(&sp_key, note, merkle_path); match mb { Ok(()) => { + println!("added orchard inp: {:?}", val); continue; }, - Err(_e) => { + Err(e) => { + println!("failed orchard inp: {:?}", e); let x = Hhex {bytes: vec![7]}; marshall_to_haskell_var(&x, out, out_len, RW); } -- 2.34.1 From 5ce29d096d0f747e824280b6a472033689481657 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 12 Nov 2024 16:22:56 -0600 Subject: [PATCH 67/72] add debugging --- librustzcash-wrapper/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 1549e16..e13fffb 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -2268,9 +2268,11 @@ pub extern "C" fn rust_wrapper_create_transaction( let tb = test_builder.add_orchard_spend::(&sp_key, note, merkle_path); match tb { Ok(()) => { + println!("added orchard inp: {:?}", val); continue; }, - Err(_e) => { + Err(e) => { + println!("failed orchard inp: {:?}", e); let x = Hhex {bytes: vec![7]}; marshall_to_haskell_var(&x, out, out_len, RW); } -- 2.34.1 From 952ceeda4bc779fd46c876c5bb6df9844abb0e9a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 13 Nov 2024 12:57:08 -0600 Subject: [PATCH 68/72] upgrade rust deps --- librustzcash-wrapper/Cargo.lock | 61 +++++++++++++++++---------------- librustzcash-wrapper/Cargo.toml | 12 +++---- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index 604eeee..0c20ffb 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -60,9 +60,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.2" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -757,9 +757,9 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75346da3bd8e3d8891d02508245ed2df34447ca6637e343829f8d08986e9cde2" +checksum = "d45063fbc4b0a37837f6bfe0445f269d13d730ad0aa3b5a7f74aa7bf27a0f4df" dependencies = [ "either", ] @@ -987,9 +987,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc7bde644aeb980be296cd908c6650894dc8541deb56f9f5294c52ed7ca568f" +checksum = "4f18e997fa121de5c73e95cdc7e8512ae43b7de38904aeea5e5713cc48f3c0ba" dependencies = [ "aes", "bitvec", @@ -1379,9 +1379,9 @@ dependencies = [ [[package]] name = "sapling-crypto" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e379398fffad84e49f9a45a05635fc004f66086e65942dbf4eb95332c26d2a" +checksum = "cfff8cfce16aeb38da50b8e2ed33c9018f30552beff2210c266662a021b17f38" dependencies = [ "aes", "bellman", @@ -1488,9 +1488,9 @@ dependencies = [ [[package]] name = "shardtree" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78222845cd8bbe5eb95687407648ff17693a35de5e8abaa39a4681fb21e033f9" +checksum = "b5f2390975ebfe8838f9e861f7a588123d49a7a7a0a08568ea831d8ad53fc9b4" dependencies = [ "bitflags 2.4.2", "either", @@ -1883,9 +1883,9 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d26f21381dc220836dd8d2a9a10dbe85928a26232b011bc6a42b611789b743" +checksum = "4ff95eac82f71286a79c750e674550d64fb2b7aadaef7b89286b2917f645457d" dependencies = [ "bech32 0.9.1", "bs58 0.5.0", @@ -1896,9 +1896,9 @@ dependencies = [ [[package]] name = "zcash_client_backend" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e3a0f3e5d7f299d8b7ef3237697630989c31ab1b162824c99c1cd8bc83715e" +checksum = "cbeeede366fdb642710d3c59fc2090489affd075f66db53ed11bb7138d2d0258" dependencies = [ "base64", "bech32 0.9.1", @@ -1924,7 +1924,7 @@ dependencies = [ "tonic-build", "tracing", "which", - "zcash_address 0.4.0", + "zcash_address 0.6.0", "zcash_encoding", "zcash_keys", "zcash_note_encryption", @@ -1946,9 +1946,9 @@ dependencies = [ [[package]] name = "zcash_keys" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712faf4070107ab0b2828d0eda6aeaf4c3cb02564109832d95b97ad3467c95a5" +checksum = "e8162c94957f1e379b8e2fb30f97b95cfa93ac9c6bc02895946ca6392d1abb81" dependencies = [ "bech32 0.9.1", "blake2b_simd", @@ -1963,7 +1963,7 @@ dependencies = [ "secrecy", "subtle", "tracing", - "zcash_address 0.4.0", + "zcash_address 0.6.0", "zcash_encoding", "zcash_primitives", "zcash_protocol", @@ -1985,9 +1985,9 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.16.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f044bc9cf2887ec408196fbafb44749e5581f57cc18d8da7aabaeb60cc40c64" +checksum = "6ab47d526d7fd6f88b3a2854ad81b54757a80c2aeadd1d8b06f690556af9743c" dependencies = [ "aes", "bip32", @@ -2014,7 +2014,7 @@ dependencies = [ "sha2 0.10.6", "subtle", "tracing", - "zcash_address 0.4.0", + "zcash_address 0.6.0", "zcash_encoding", "zcash_note_encryption", "zcash_protocol", @@ -2024,9 +2024,9 @@ dependencies = [ [[package]] name = "zcash_protocol" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f35eac659fdbba614333d119217c5963c0d7cea43aee33176c4f2f95e5460d8d" +checksum = "6bc22b9155b2c7eb20105cd06de170d188c1bc86489b92aa3fda7b8da8d96acf" dependencies = [ "document-features", "memuse", @@ -2034,9 +2034,9 @@ dependencies = [ [[package]] name = "zcash_spec" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b" +checksum = "9cede95491c2191d3e278cab76e097a44b17fde8d6ca0d4e3a22cf4807b2d857" dependencies = [ "blake2b_simd", ] @@ -2063,24 +2063,25 @@ dependencies = [ [[package]] name = "zip32" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e" +checksum = "92022ac1e47c7b78f9cee29efac8a1a546e189506f3bb5ad46d525be7c519bf6" dependencies = [ "blake2b_simd", "memuse", "subtle", + "zcash_spec", ] [[package]] name = "zip321" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc85f862f7be64fb0d46f9eb5b82ad54e58cde314fa979d5bae591bc0143693" +checksum = "1f3e613defb0940acef1f54774b51c7f48f2fa705613dd800870dc69f35cd2ea" dependencies = [ "base64", "nom", "percent-encoding", - "zcash_address 0.4.0", + "zcash_address 0.6.0", "zcash_protocol", ] diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index 208022f..350ecb2 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -11,15 +11,15 @@ f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" bech32 = "0.11" -orchard = "0.9.0" +orchard = "0.10.0" zcash_note_encryption = "0.4.0" -zcash_primitives = { version = "0.16.0", features = ["transparent-inputs"]} -zcash_client_backend = "0.13.0" -sapling-crypto = "0.2" -zip32 = "0.1.0" +zcash_primitives = { version = "0.19.0", features = ["transparent-inputs"]} +zcash_client_backend = "0.14.0" +sapling-crypto = "0.3" +zip32 = "0.1.2" proc-macro2 = "1.0.66" nonempty = "0.7.0" -incrementalmerkletree = "0.6.0" +incrementalmerkletree = "0.7.0" secp256k1 = "0.27.0" jubjub = "0.10.0" rand_core = { version = "0.6.4", features = ["getrandom"]} -- 2.34.1 From c205bc6cf53b1c511b421e399b84b9038eec8114 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 13 Nov 2024 13:10:10 -0600 Subject: [PATCH 69/72] remove debugging --- librustzcash-wrapper/src/lib.rs | 34 ++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index e13fffb..563ac5f 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -1873,7 +1873,13 @@ pub extern "C" fn rust_wrapper_read_orchard_path_anchor( ){ let path_in: Hpath = marshall_from_haskell_var(path, path_len, RW); let cmx_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); - let mk_path = orchard::tree::MerklePath::from_parts(path_in.position, to_array(path_in.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); + let mk_path = orchard::tree::MerklePath::from_parts(path_in.position, to_array(path_in.path.iter().map(|x| + if x.bytes.len() > 1 { + MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() + } else { + MerkleHashOrchard::empty_leaf() + } + ).collect())); let nc = ExtractedNoteCommitment::from_bytes(&to_array(cmx_in)); if nc.is_some().into() { let anchor = mk_path.root(nc.unwrap()); @@ -2152,7 +2158,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } else { None }; - println!("{:?}", sapling_anchor); + //println!("{:?}", sapling_anchor); let orch_input: Vec = marshall_from_haskell_var(o_input, o_input_len, RW); let orch_anchor_in : Vec = marshall_from_haskell_var(orch_wit, orch_wit_len, RW); let orch_anchor = MerkleHashOrchard::from_bytes(&to_array(orch_anchor_in)); @@ -2162,7 +2168,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } else { None }; - println!("{:?}", orchard_anchor); + //println!("{:?}", orchard_anchor); let build_config = BuildConfig::Standard {sapling_anchor, orchard_anchor}; let mut main_builder = Builder::new(MainNetwork, BlockHeight::from(bl_height), build_config); let mut test_builder = Builder::new(TestNetwork, BlockHeight::from(bl_height), build_config); @@ -2248,18 +2254,24 @@ pub extern "C" fn rust_wrapper_create_transaction( let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); let val = NoteValue::from_raw(o_in.note.note); - println!("o inp: {:?}", val); + //println!("o inp: {:?}", val); let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap(); - let merkle_path = orchard::tree::MerklePath::from_parts(o_in.iw.position, to_array(o_in.iw.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); + let merkle_path = orchard::tree::MerklePath::from_parts(o_in.iw.position, to_array(o_in.iw.path.iter().map(|x| + if x.bytes.len() > 1 { + MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() + } else { + MerkleHashOrchard::empty_leaf() + } + ).collect())); if net { let mb = main_builder.add_orchard_spend::(&sp_key, note, merkle_path); match mb { Ok(()) => { - println!("added orchard inp: {:?}", val); + //println!("added orchard inp: {:?}", val); continue; }, Err(e) => { - println!("failed orchard inp: {:?}", e); + //println!("failed orchard inp: {:?}", e); let x = Hhex {bytes: vec![7]}; marshall_to_haskell_var(&x, out, out_len, RW); } @@ -2268,11 +2280,11 @@ pub extern "C" fn rust_wrapper_create_transaction( let tb = test_builder.add_orchard_spend::(&sp_key, note, merkle_path); match tb { Ok(()) => { - println!("added orchard inp: {:?}", val); + //println!("added orchard inp: {:?}", val); continue; }, Err(e) => { - println!("failed orchard inp: {:?}", e); + //println!("failed orchard inp: {:?}", e); let x = Hhex {bytes: vec![7]}; marshall_to_haskell_var(&x, out, out_len, RW); } @@ -2367,7 +2379,7 @@ pub extern "C" fn rust_wrapper_create_transaction( }; let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap(); let val = output.amt; - println!("o out: {:?} {:?}", val, output.chg); + //println!("o out: {:?} {:?}", val, output.chg); let memo = MemoBytes::from_bytes(&output.memo).unwrap(); if net { let mb = main_builder.add_orchard_output::(ovk, recipient, val, memo); @@ -2423,7 +2435,7 @@ pub extern "C" fn rust_wrapper_create_transaction( Err(e) => { match e { Error::InsufficientFunds(y) => { - println!("ins funds: {:?}", y); + //println!("ins funds: {:?}", y); let x = Hhex {bytes: vec![0]}; marshall_to_haskell_var(&x, out, out_len, RW); }, -- 2.34.1 From db92676ca4dd281b55ea4dd5ce4fc08d2348e0f2 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 15 Nov 2024 12:46:35 -0600 Subject: [PATCH 70/72] docs: update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c1328f..ed642a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Sapling commitment node functions - Sapling Merkle path test +### Changed + +- Upgraded Rust dependencies to latest versions: + - `zcash_primitives` 0.19.0 + - `zcash_client_backend` 0.14.0 + - `orchard` 0.10.0 + - `sapling-crypto` 0.3.0 + - `incrementalmerkletree` 0.7.0 + - `zip32` 0.1.2 + ## [0.7.4.0] ### Added -- 2.34.1 From 0bab23375f9458664a5fb3016a733776d3471205 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sat, 14 Dec 2024 06:22:19 -0600 Subject: [PATCH 71/72] feat: support for new Zebra `getblock` format --- CHANGELOG.md | 6 ++++++ src/ZcashHaskell/Types.hs | 4 ++-- zcash-haskell.cabal | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed642a7..973ccec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.6.0] + +### Changed + +- Removed workaround for missing `time` field in Zebra's `getblock` response. + ## [0.7.5.0] ### Added diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 1c55a73..a02ed15 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -268,10 +268,10 @@ instance FromJSON BlockResponse where withObject "BlockResponse" $ \obj -> do c <- obj .: "confirmations" h <- obj .: "height" - t <- obj .:? "time" + t <- obj .: "time" txs <- obj .: "tx" hash <- obj .: "hash" - pure $ BlockResponse hash c h (fromMaybe 0 t) txs + pure $ BlockResponse hash c h t txs instance ToJSON BlockResponse where toJSON (BlockResponse h c ht t txs) = diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index c1d1d82..4cddd8a 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.5.0 +version: 0.7.6.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1 From d350c2e7844a526ff9b21bb14e1723fce9b0b46b Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 18 Dec 2024 09:10:55 -0600 Subject: [PATCH 72/72] chore: update Rust crates --- CHANGELOG.md | 6 + librustzcash-wrapper/Cargo.lock | 853 ++++++++++++----------- librustzcash-wrapper/Cargo.toml | 9 +- librustzcash-wrapper/rust-toolchain.toml | 2 +- librustzcash-wrapper/src/lib.rs | 25 +- test/Spec.hs | 71 -- zcash-haskell.cabal | 2 +- 7 files changed, 476 insertions(+), 492 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 973ccec..4c70e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.7.0] + +### Changed + +- Updated Rust crates + ## [0.7.6.0] ### Changed diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index 0c20ffb..57a7a8f 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -35,28 +35,37 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.71" +name = "aho-corasick" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" @@ -70,12 +79,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bech32" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" - [[package]] name = "bech32" version = "0.9.1" @@ -127,7 +130,7 @@ dependencies = [ "hmac", "pbkdf2", "rand", - "sha2 0.10.6", + "sha2 0.10.8", "unicode-normalization", "zeroize", ] @@ -138,27 +141,21 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa13fae8b6255872fd86f7faf4b41168661d7d78609f7bfe6771b85c6739a15b" dependencies = [ - "bs58 0.5.0", + "bs58 0.5.1", "hmac", "rand_core", "ripemd", "secp256k1", - "sha2 0.10.6", + "sha2 0.10.8", "subtle", "zeroize", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -174,9 +171,9 @@ dependencies = [ [[package]] name = "blake2b_simd" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", @@ -185,9 +182,9 @@ dependencies = [ [[package]] name = "blake2s_simd" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" +checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" dependencies = [ "arrayref", "arrayvec", @@ -231,41 +228,18 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ - "borsh-derive 0.9.3", + "borsh-derive", "hashbrown 0.11.2", ] -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.12.3", -] - [[package]] name = "borsh-derive" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" dependencies = [ - "borsh-derive-internal 0.9.3", - "borsh-schema-derive-internal 0.9.3", - "proc-macro-crate", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal 0.10.3", - "borsh-schema-derive-internal 0.10.3", + "borsh-derive-internal", + "borsh-schema-derive-internal", "proc-macro-crate", "proc-macro2", "syn 1.0.109", @@ -282,17 +256,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "borsh-schema-derive-internal" version = "0.9.3" @@ -304,17 +267,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bs58" version = "0.4.0" @@ -326,25 +278,25 @@ dependencies = [ [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "sha2 0.10.6", + "sha2 0.10.8", "tinyvec", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cbc" @@ -357,9 +309,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -404,61 +359,61 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.2.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr", +] [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -507,18 +462,18 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" dependencies = [ "litrs", ] [[package]] name = "either" -version = "1.8.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equihash" @@ -531,43 +486,35 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.1" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ - "errno-dragonfly", "libc", "windows-sys", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "f4jumble" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" +checksum = "0d42773cb15447644d170be20231a3268600e0c4cea8987d013b93ac973d3cf7" dependencies = [ "blake2b_simd", ] [[package]] name = "fastrand" -version = "1.9.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ff" @@ -618,15 +565,27 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "getset" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "group" version = "0.13.0" @@ -641,18 +600,20 @@ dependencies = [ [[package]] name = "halo2_gadgets" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126a150072b0c38c7b573fe3eaf0af944a7fed09e154071bf2436d3f016f7230" +checksum = "73a5e510d58a07d8ed238a5a8a436fe6c2c79e1bb2611f62688bc65007b4e6e7" dependencies = [ "arrayvec", "bitvec", "ff", "group", + "halo2_poseidon", "halo2_proofs", "lazy_static", "pasta_curves", "rand", + "sinsemilla", "subtle", "uint", ] @@ -663,6 +624,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" +[[package]] +name = "halo2_poseidon" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa3da60b81f02f9b33ebc6252d766f843291fb4d2247a07ae73d20b791fc56f" +dependencies = [ + "bitvec", + "ff", + "group", + "pasta_curves", +] + [[package]] name = "halo2_proofs" version = "0.3.0" @@ -690,12 +663,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "haskell-ffi" @@ -703,7 +673,7 @@ version = "0.1.0" source = "git+https://github.com/BeFunctional/haskell-rust-ffi.git?rev=2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274#2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274" dependencies = [ "bincode", - "borsh 0.9.3", + "borsh", "haskell-ffi-derive", "ref-cast", "serde", @@ -721,24 +691,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -756,22 +717,31 @@ dependencies = [ ] [[package]] -name = "incrementalmerkletree" -version = "0.7.0" +name = "home" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45063fbc4b0a37837f6bfe0445f269d13d730ad0aa3b5a7f74aa7bf27a0f4df" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "incrementalmerkletree" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216c71634ac6f6ed13c2102d64354c0a04dcbdc30e31692c5972d3974d8b6d97" dependencies = [ "either", ] [[package]] name = "indexmap" -version = "1.9.3" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "equivalent", + "hashbrown 0.15.2", ] [[package]] @@ -783,31 +753,11 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys", -] - [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -828,30 +778,30 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libm" -version = "0.2.6" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litrs" @@ -861,9 +811,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "log" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "maybe-rayon" @@ -877,27 +827,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memuse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" -dependencies = [ - "nonempty", -] +checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" [[package]] name = "minimal-lexical" @@ -907,9 +845,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "nom" @@ -929,11 +867,10 @@ checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -946,58 +883,60 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orchard" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f18e997fa121de5c73e95cdc7e8512ae43b7de38904aeea5e5713cc48f3c0ba" +checksum = "02f7152474406422f572de163e0bc63b2126cdbfe17bc849efbbde36fcfe647e" dependencies = [ "aes", "bitvec", "blake2b_simd", + "core2", "ff", "fpe", + "getset", "group", "halo2_gadgets", + "halo2_poseidon", "halo2_proofs", "hex", "incrementalmerkletree", @@ -1008,6 +947,7 @@ dependencies = [ "rand", "reddsa", "serde", + "sinsemilla", "subtle", "tracing", "visibility", @@ -1063,15 +1003,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap", @@ -1079,9 +1019,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "poly1305" @@ -1102,18 +1042,21 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] @@ -1126,19 +1069,41 @@ dependencies = [ ] [[package]] -name = "proc-macro2" -version = "1.0.66" +name = "proc-macro-error-attr2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" dependencies = [ "bytes", "prost-derive", @@ -1146,11 +1111,10 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +checksum = "d0f3e5beed80eb580c68e2c600937ac2c4eedabdfd5ef1e5b7ea4f3fba84497b" dependencies = [ - "bytes", "heck", "itertools", "log", @@ -1161,37 +1125,37 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.32", + "syn 2.0.90", "tempfile", ] [[package]] name = "prost-derive" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] name = "prost-types" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" dependencies = [ "prost", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1234,9 +1198,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1244,21 +1208,19 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "reddsa" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b34d2c0df43159d2ff79d3cf929c9f11415529127344edb8160ad2be499fcd" +checksum = "78a5191930e84973293aa5f532b513404460cd2216c1cfb76d08748c15b40b02" dependencies = [ "blake2b_simd", "byteorder", @@ -1285,49 +1247,54 @@ dependencies = [ "zeroize", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "ref-cast" -version = "1.0.16" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.16" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ripemd" @@ -1340,13 +1307,12 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.20" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ - "bitflags 1.3.2", + "bitflags", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys", @@ -1356,9 +1322,10 @@ dependencies = [ name = "rustzcash-wrapper" version = "0.1.0" dependencies = [ + "ahash", "bech32 0.11.0", "bip0039", - "borsh 0.10.3", + "borsh", "f4jumble", "haskell-ffi", "incrementalmerkletree", @@ -1370,7 +1337,7 @@ dependencies = [ "sapling-crypto", "secp256k1", "wagyu-zcash-parameters", - "zcash_address 0.2.0", + "zcash_address 0.2.1", "zcash_client_backend", "zcash_note_encryption", "zcash_primitives", @@ -1379,9 +1346,9 @@ dependencies = [ [[package]] name = "sapling-crypto" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfff8cfce16aeb38da50b8e2ed33c9018f30552beff2210c266662a021b17f38" +checksum = "85c2acdbbab83d554fc2dceea5f7d6d3da71e57adb18a6c80b8901bd0eee54b0" dependencies = [ "aes", "bellman", @@ -1393,6 +1360,7 @@ dependencies = [ "document-features", "ff", "fpe", + "getset", "group", "hex", "incrementalmerkletree", @@ -1409,12 +1377,6 @@ dependencies = [ "zip32", ] -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "secp256k1" version = "0.27.0" @@ -1444,22 +1406,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] @@ -1477,9 +1439,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1492,17 +1454,34 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5f2390975ebfe8838f9e861f7a588123d49a7a7a0a08568ea831d8ad53fc9b4" dependencies = [ - "bitflags 2.4.2", + "bitflags", "either", "incrementalmerkletree", "tracing", ] [[package]] -name = "spin" -version = "0.5.2" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sinsemilla" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d268ae0ea06faafe1662e9967cd4f9022014f5eeb798e0c302c876df8b7af9c" +dependencies = [ + "group", + "pasta_curves", + "subtle", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "static_assertions" @@ -1512,9 +1491,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -1529,9 +1508,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.32" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1546,43 +1525,42 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ - "autocfg", "cfg-if", "fastrand", - "redox_syscall", + "once_cell", "rustix", "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] name = "time" -version = "0.3.34" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "num-conv", @@ -1599,9 +1577,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1632,16 +1610,15 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1649,29 +1626,29 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" @@ -1687,9 +1664,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -1702,9 +1679,9 @@ dependencies = [ [[package]] name = "universal-hash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", "subtle", @@ -1712,9 +1689,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "visibility" @@ -1724,7 +1701,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] @@ -1785,33 +1762,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "which" -version = "4.4.0" +version = "6.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" dependencies = [ "either", - "libc", - "once_cell", + "home", + "rustix", + "winsafe", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -1820,45 +1799,57 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "wyz" @@ -1871,11 +1862,11 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804268e702b664fc09d3e2ce82786d0addf4ae57ba6976469be63e09066bf9f7" +checksum = "52be35a205369d480378646bff9c9fedafd8efe8af1e0e54bb858f405883f2b2" dependencies = [ - "bech32 0.8.1", + "bech32 0.9.1", "bs58 0.4.0", "f4jumble", "zcash_encoding", @@ -1883,12 +1874,13 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff95eac82f71286a79c750e674550d64fb2b7aadaef7b89286b2917f645457d" +checksum = "9b955fe87f2d9052e3729bdbeb0e94975355f4fe39f7d26aea9457bec6a0bb55" dependencies = [ - "bech32 0.9.1", - "bs58 0.5.0", + "bech32 0.11.0", + "bs58 0.5.1", + "core2", "f4jumble", "zcash_encoding", "zcash_protocol", @@ -1896,14 +1888,14 @@ dependencies = [ [[package]] name = "zcash_client_backend" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbeeede366fdb642710d3c59fc2090489affd075f66db53ed11bb7138d2d0258" +checksum = "c2a187ad05cdfe13707c07e6aedca8026b34921d081decfd0b43aac1efd438a7" dependencies = [ "base64", - "bech32 0.9.1", + "bech32 0.11.0", "bls12_381", - "bs58 0.5.0", + "bs58 0.5.1", "crossbeam-channel", "document-features", "group", @@ -1924,7 +1916,7 @@ dependencies = [ "tonic-build", "tracing", "which", - "zcash_address 0.6.0", + "zcash_address 0.6.2", "zcash_encoding", "zcash_keys", "zcash_note_encryption", @@ -1936,24 +1928,25 @@ dependencies = [ [[package]] name = "zcash_encoding" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052d8230202f0a018cd9b5d1b56b94cd25e18eccc2d8665073bcea8261ab87fc" +checksum = "3654116ae23ab67dd1f849b01f8821a8a156f884807ff665eac109bf28306c4d" dependencies = [ - "byteorder", + "core2", "nonempty", ] [[package]] name = "zcash_keys" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8162c94957f1e379b8e2fb30f97b95cfa93ac9c6bc02895946ca6392d1abb81" +checksum = "6ad3cf576c6e6094cd03f446fcb83ad241ec315a088593cd50940f135cb03ce1" dependencies = [ - "bech32 0.9.1", + "bech32 0.11.0", "blake2b_simd", "bls12_381", - "bs58 0.5.0", + "bs58 0.5.1", + "core2", "document-features", "group", "memuse", @@ -1963,18 +1956,18 @@ dependencies = [ "secrecy", "subtle", "tracing", - "zcash_address 0.6.0", + "zcash_address 0.6.2", "zcash_encoding", - "zcash_primitives", "zcash_protocol", + "zcash_transparent", "zip32", ] [[package]] name = "zcash_note_encryption" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4580cd6cee12e44421dac43169be8d23791650816bdb34e6ddfa70ac89c1c5" +checksum = "77efec759c3798b6e4d829fcc762070d9b229b0f13338c40bf993b7b609c2272" dependencies = [ "chacha20", "chacha20poly1305", @@ -1985,19 +1978,20 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab47d526d7fd6f88b3a2854ad81b54757a80c2aeadd1d8b06f690556af9743c" +checksum = "9b45f3ca3a9df34fcdbf036c2c814417bb417bde742812abc09d744bb3d7ed72" dependencies = [ "aes", "bip32", "blake2b_simd", - "bs58 0.5.0", + "bs58 0.5.1", "byteorder", "document-features", "equihash", "ff", "fpe", + "getset", "group", "hex", "incrementalmerkletree", @@ -2011,24 +2005,27 @@ dependencies = [ "ripemd", "sapling-crypto", "secp256k1", - "sha2 0.10.6", + "sha2 0.10.8", "subtle", "tracing", - "zcash_address 0.6.0", + "zcash_address 0.6.2", "zcash_encoding", "zcash_note_encryption", "zcash_protocol", "zcash_spec", + "zcash_transparent", "zip32", ] [[package]] name = "zcash_protocol" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bc22b9155b2c7eb20105cd06de170d188c1bc86489b92aa3fda7b8da8d96acf" +checksum = "82cb36b15b5a1be70b30c32ce40372dead6561df8a467e297f96b892873a63a2" dependencies = [ + "core2", "document-features", + "hex", "memuse", ] @@ -2042,10 +2039,54 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "1.6.0" +name = "zcash_transparent" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "ed0512e8e02af804e852fbbc4bd5db35a9037bc253d2ce396506293a6e7dd745" +dependencies = [ + "bip32", + "blake2b_simd", + "bs58 0.5.1", + "core2", + "getset", + "hex", + "ripemd", + "secp256k1", + "sha2 0.10.8", + "subtle", + "zcash_address 0.6.2", + "zcash_encoding", + "zcash_protocol", + "zcash_spec", + "zip32", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -2058,14 +2099,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.90", ] [[package]] name = "zip32" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92022ac1e47c7b78f9cee29efac8a1a546e189506f3bb5ad46d525be7c519bf6" +checksum = "2e9943793abf9060b68e1889012dafbd5523ab5b125c0fcc24802d69182f2ac9" dependencies = [ "blake2b_simd", "memuse", @@ -2082,6 +2123,6 @@ dependencies = [ "base64", "nom", "percent-encoding", - "zcash_address 0.6.0", + "zcash_address 0.6.2", "zcash_protocol", ] diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index 350ecb2..900fd1a 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -9,13 +9,13 @@ haskell-ffi.git = "https://github.com/BeFunctional/haskell-rust-ffi.git" haskell-ffi.rev = "2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274" f4jumble = "0.1" zcash_address = "0.2.0" -borsh = "0.10" +borsh = "0.9" bech32 = "0.11" orchard = "0.10.0" zcash_note_encryption = "0.4.0" -zcash_primitives = { version = "0.19.0", features = ["transparent-inputs"]} -zcash_client_backend = "0.14.0" -sapling-crypto = "0.3" +zcash_primitives = { version = "0.21.0", features = ["transparent-inputs"]} +zcash_client_backend = "0.16.0" +sapling-crypto = "0.4" zip32 = "0.1.2" proc-macro2 = "1.0.66" nonempty = "0.7.0" @@ -25,6 +25,7 @@ jubjub = "0.10.0" rand_core = { version = "0.6.4", features = ["getrandom"]} wagyu-zcash-parameters = "0.2.0" bip0039 = "0.12.0" +ahash = "0.7.8" [features] diff --git a/librustzcash-wrapper/rust-toolchain.toml b/librustzcash-wrapper/rust-toolchain.toml index af255e0..7c4fd88 100644 --- a/librustzcash-wrapper/rust-toolchain.toml +++ b/librustzcash-wrapper/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-02-04" +channel = "nightly" components = [ "rustfmt", "rustc-dev"] profile = "minimal" diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 563ac5f..cb1fbbe 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -116,6 +116,7 @@ use zcash_primitives::{ }, transparent::{ Bundle as TransparentBundle, + builder::TransparentSigningSet, TxIn, TxOut, OutPoint, @@ -156,7 +157,7 @@ use orchard::{ Flags }, Action, - keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope}, + keys::{SpendAuthorizingKey, SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope}, note::{Rho, RandomSeed, Note, Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment}, note_encryption::OrchardDomain, primitives::redpallas::{VerificationKey, SpendAuth, Signature}, @@ -2173,12 +2174,13 @@ pub extern "C" fn rust_wrapper_create_transaction( let mut main_builder = Builder::new(MainNetwork, BlockHeight::from(bl_height), build_config); let mut test_builder = Builder::new(TestNetwork, BlockHeight::from(bl_height), build_config); let trans_input: Vec = marshall_from_haskell_var(t_input, t_input_len, RW); + let mut tss = TransparentSigningSet::new(); for t_in in trans_input { if t_in.sk.len() > 1 { //println!("t inp: {:?}", t_in); let k = SecretKey::from_slice(&t_in.sk).unwrap(); if net { - match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) { + match main_builder.add_transparent_input(tss.add_key(k), t_in.utxo.unpack(), t_in.coin.unpack()) { Ok(()) => { //println!("added t-input in main"); continue; @@ -2186,7 +2188,7 @@ pub extern "C" fn rust_wrapper_create_transaction( Err(_e) => { println!("Error reading transparent input"); } } } else { - match test_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) { + match test_builder.add_transparent_input(tss.add_key(k), t_in.utxo.unpack(), t_in.coin.unpack()) { Ok(()) => { //println!("added t-input in test"); continue; @@ -2196,12 +2198,14 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } + let mut sap_key_array = vec![]; for s_in in sap_input { if s_in.sk.len() > 1 { //println!("s inp: {:?}", s_in); let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk); match sp_key { Ok(sk) => { + sap_key_array.push(sk.clone()); let pay_addr = PaymentAddress::from_bytes(&to_array(s_in.note.recipient)).unwrap(); let rseed = if s_in.note.rseed.kind == 1 { Rseed::BeforeZip212(Fr::from_bytes(&to_array(s_in.note.rseed.bytes)).unwrap()) @@ -2216,8 +2220,9 @@ pub extern "C" fn rust_wrapper_create_transaction( Node::empty_leaf() }).collect(), Position::from(u64::from(s_in.iw.position))); let merkle_path = mk_path.unwrap(); + let fvk = sk.to_diversifiable_full_viewing_key().fvk().clone(); if net { - let mb = main_builder.add_sapling_spend::(&sk, note, merkle_path); + let mb = main_builder.add_sapling_spend::(fvk, note, merkle_path); match mb { Ok(()) => { continue; @@ -2228,7 +2233,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } else { - let tb = test_builder.add_sapling_spend::(&sk, note, merkle_path); + let tb = test_builder.add_sapling_spend::(fvk, note, merkle_path); match tb { Ok(()) => { continue; @@ -2247,9 +2252,11 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } + let mut orch_keys = vec![]; for o_in in orch_input { if o_in.sk.len() > 1 { let sp_key = SpendingKey::from_bytes(o_in.sk[0..32].try_into().unwrap()).unwrap(); + orch_keys.push(SpendAuthorizingKey::from(&sp_key)); let pay_addr = OrchardAddress::from_raw_address_bytes(&to_array(o_in.note.recipient)).unwrap(); let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap(); let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap(); @@ -2264,7 +2271,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } ).collect())); if net { - let mb = main_builder.add_orchard_spend::(&sp_key, note, merkle_path); + let mb = main_builder.add_orchard_spend::(FullViewingKey::from(&sp_key), note, merkle_path); match mb { Ok(()) => { //println!("added orchard inp: {:?}", val); @@ -2277,7 +2284,7 @@ pub extern "C" fn rust_wrapper_create_transaction( } } } else { - let tb = test_builder.add_orchard_spend::(&sp_key, note, merkle_path); + let tb = test_builder.add_orchard_spend::(FullViewingKey::from(&sp_key), note, merkle_path); match tb { Ok(()) => { //println!("added orchard inp: {:?}", val); @@ -2421,9 +2428,9 @@ pub extern "C" fn rust_wrapper_create_transaction( 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()) + main_builder.build(&tss, &sap_key_array, &orch_keys, OsRng, &spend_prover, &output_prover, &FeeRule::standard()) } else { - test_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard()) + test_builder.build(&tss, &sap_key_array, &orch_keys,OsRng, &spend_prover, &output_prover, &FeeRule::standard()) }; match result { Ok(r) => { diff --git a/test/Spec.hs b/test/Spec.hs index 0547e16..9388a8e 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1162,77 +1162,6 @@ main = do Just addr -> do let eadr = decodeExchangeAddress (E.encodeUtf8 addr) eadr `shouldNotBe` Nothing - describe "Tree updates" $ do - it "Orchard" $ do - let tree = - OrchardCommitmentTree $ - hexString - "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" - let cmx1 = - hexString - "1712ead46028d4349e234abf59e94e0640fe7a0829e2e2e17e1a931631810400" - let cmx2 = - hexString - "39f5ad39817fb432fa07c5feb3a957189fbe7662a4b5555ca95093b6d853cf07" - let cmx3 = - hexString - "84f7fbc4b9f87215c653078d7fdd90756c3ba370c745065167da9eb73a65a83f" - let cmx4 = - hexString - "e55ad64e1ea2b261893fdea6ad0509b66e5f62d3142f351298c7135c4498d429" - let finalTree = - getOrchardFrontier $ - OrchardCommitmentTree $ - hexString - "0184f7fbc4b9f87215c653078d7fdd90756c3ba370c745065167da9eb73a65a83f01e55ad64e1ea2b261893fdea6ad0509b66e5f62d3142f351298c7135c4498d4291f0000014b1a76d3820087b26cd087ca84e17f3067a25ebed82ad23a93fa485affb5530b01ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" - case getOrchardFrontier tree of - Nothing -> assertFailure "Failed to get frontier" - Just t1 -> - case updateOrchardCommitmentTree t1 cmx1 of - Nothing -> assertFailure "Failed to update frontier with cmx" - Just t2 -> do - case getOrchardWitness t2 of - Nothing -> assertFailure "Failed to get witness" - Just wit -> do - let uWit = updateOrchardWitness wit [cmx2, cmx3, cmx4] - Just (getOrchardWitnessAnchor uWit) `shouldBe` - getOrchardTreeAnchor <$> - finalTree - describe "Witness updates" $ do - it "Sapling" $ do - let wit = - SaplingWitness $ - hexString - "01bd8a3f3cfc964332a2ada8c09a0da9dfc24174befb938abb086b9be5ca049e49013607f5e51826c8e5f660571ddfae14cd6fb1dc026bcd6855459b4e9339b20521100000019f0d7efb00169bb2202152d3266059d208ab17d14642c3339f9075e997160657000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39038cd7f6e2238d16ef49420963348dd4e4c7d23d5e5dac69507fba8937f63eb626f6856115bea2fa8db3a65a0ab294db41c51435d3b7ea27c7b2835aca28e82a2c1d9634efe07449a47c251518ac6f92c49f3a1ef119948f6a824d1e7ff7d0443e0101e57ec972a9b9383dc9cb228980d2d7752bb2abebc4a604ca48c5457039d2e05b000301392bed8592185dde5ab7fc81aed75e98fcf041f1a3fda55ad0b0b139ba9380130001808304b4d7c4fc407f5ce28247a7119013aeaaf1481902419c42bc8b21575c15" - let cmus = - [ hexString - "958ccdc752f2f593f6c1c8e2d7201348cd896e54c6d3c92200bdbe8b859eac44" - , hexString - "e49992fdd071d90bf56242d1aa625bbe267a34e0debd4307818a686d05b45447" - , hexString - "0c4b26766d89bf6cdb4fd3b0317b4e9a2fb3850f6a24869f32fe7cb0fd512e18" - ] - updateSaplingWitness wit cmus `shouldBe` - SaplingWitness - (hexString - "01bd8a3f3cfc964332a2ada8c09a0da9dfc24174befb938abb086b9be5ca049e49013607f5e51826c8e5f660571ddfae14cd6fb1dc026bcd6855459b4e9339b20521100000019f0d7efb00169bb2202152d3266059d208ab17d14642c3339f9075e997160657000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39038cd7f6e2238d16ef49420963348dd4e4c7d23d5e5dac69507fba8937f63eb626f6856115bea2fa8db3a65a0ab294db41c51435d3b7ea27c7b2835aca28e82a2c1d9634efe07449a47c251518ac6f92c49f3a1ef119948f6a824d1e7ff7d0443e0101e49992fdd071d90bf56242d1aa625bbe267a34e0debd4307818a686d05b45447010c4b26766d89bf6cdb4fd3b0317b4e9a2fb3850f6a24869f32fe7cb0fd512e1803000121c06ee1f1584f79d50785797a694c742be2ded600367ab7d54f3ed49e3adf7201808304b4d7c4fc407f5ce28247a7119013aeaaf1481902419c42bc8b21575c15") - it "Orchard" $ do - let wit = - OrchardWitness $ - hexString - "016225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631001f0000011d6f5da3f619bfaab957fc643c17eb144db0101c90f422da2fcbe0e80d74412e000000000001746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000040e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e0504bfbc12edc35e05042c16bbfb8fed591f01f18fe128eeb57f2c456c9eb222d6d261c549e95d9007bce4c6ae0b86bc865711cdd9f0fa92e2d5b5e149b51f3be127df3b1d2372adf6c811b2e456c1d64d0e9eb167a995f9c6b66a03c9cbda250101c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e000200019df5b9366d0f21caa678d1567390b5bfd3cfa0438271bcfe301b5558a2863301" - let cmxs = - [ hexString - "712ba86615ff4447e8d7c7b59f3873f03c03a173438b8e4c8d416756ed4fae10" - , hexString - "c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e" - , hexString - "ac20b8170b008888c19fc6e16f5e30a5ef1653e5219d0cd0c9353c3aa8f79823" - ] - updateOrchardWitness wit cmxs `shouldBe` - OrchardWitness - (hexString - "016225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631001f0000011d6f5da3f619bfaab957fc643c17eb144db0101c90f422da2fcbe0e80d74412e000000000001746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000040e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e0504bfbc12edc35e05042c16bbfb8fed591f01f18fe128eeb57f2c456c9eb222d6d261c549e95d9007bce4c6ae0b86bc865711cdd9f0fa92e2d5b5e149b51f3be127df3b1d2372adf6c811b2e456c1d64d0e9eb167a995f9c6b66a03c9cbda250101c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e01ac20b8170b008888c19fc6e16f5e30a5ef1653e5219d0cd0c9353c3aa8f7982302010cfb50d8c877eb39e9c07082a032dd99d34be7c19fa7f30e9fecf5f14736240f019df5b9366d0f21caa678d1567390b5bfd3cfa0438271bcfe301b5558a2863301") -- | Properties prop_PhraseLength :: Property diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 4cddd8a..4a2e933 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.7.6.0 +version: 0.7.7.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain -- 2.34.1