From 9a5ad756b87f6ace1dbaf42abf781b84ec20e097 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sat, 2 Mar 2024 07:53:48 -0600 Subject: [PATCH 01/10] Add `Read` implementation to `UnifiedAddress` --- 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 f0cbcdb..7650dbb 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -215,7 +215,7 @@ data UnifiedAddress = UnifiedAddress , o_rec :: BS.ByteString , s_rec :: BS.ByteString , t_rec :: Maybe TransparentAddress - } deriving (Prelude.Show, Eq) + } deriving (Prelude.Show, Eq, Read) -- | Helper type for marshalling UAs data RawUA = RawUA From 3cc0e96c448b41d3fc44c682546e121220e76e3b Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sun, 3 Mar 2024 08:23:48 -0600 Subject: [PATCH 02/10] Rust updates for `bech32` encode/decode --- CHANGELOG.md | 2 ++ librustzcash-wrapper/Cargo.lock | 8 +++++++- librustzcash-wrapper/Cargo.toml | 2 +- librustzcash-wrapper/src/lib.rs | 26 ++++++++++++++++++++------ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2fed36..bbea7b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Function to generate a seed phrase - Implementations of `Read` for types - Function to make RPC calls to `zebrad` +- Function to encode unified addresses from receivers ### Changed - Update installation to `cabal` +- Updated `bech32` Rust crate to 0.11 ### Removed diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index a77c068..2672c97 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -88,6 +88,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bincode" version = "1.3.3" @@ -1282,7 +1288,7 @@ dependencies = [ name = "rustzcash-wrapper" version = "0.1.0" dependencies = [ - "bech32 0.9.1", + "bech32 0.11.0", "borsh 0.10.3", "f4jumble", "haskell-ffi", diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index fa4fb55..49fbb9a 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -10,7 +10,7 @@ haskell-ffi.rev = "2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274" f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" -bech32 = "0.9.1" +bech32 = "0.11" orchard = "0.4.0" zcash_note_encryption = "0.3.0" zcash_primitives = "0.11.0" diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index ff83321..4b9e27a 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -71,10 +71,8 @@ use zcash_note_encryption::EphemeralKeyBytes; use bech32::{ decode, - u5, - FromBase32, - ToBase32, - Variant + Hrp, + Bech32m }; pub enum RW {} @@ -330,8 +328,8 @@ pub extern "C" fn rust_wrapper_bech32decode( let input: String = marshall_from_haskell_var(input, input_len, RW); let decodedBytes = bech32::decode(&input); match decodedBytes { - Ok((hrp, bytes, variant)) => { - let rd = RawData {hrp: hrp.into(), bytes: Vec::::from_base32(&bytes).unwrap()}; + Ok((hrp, bytes)) => { + let rd = RawData {hrp: hrp.as_bytes().to_vec(), bytes}; marshall_to_haskell_var(&rd, out, out_len, RW); } Err(_e) => { @@ -341,6 +339,22 @@ pub extern "C" fn rust_wrapper_bech32decode( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_bech32_encode( + hr: *const u8, + hr_len: usize, + b: *const u8, + b_len: usize, + out: *mut u8, + out_len: &mut usize + ) { + let hr: String = marshall_from_haskell_var(hr, hr_len, RW); + let hrp = Hrp::parse(&hr).unwrap(); + let b: Vec = marshall_from_haskell_var(b, b_len, RW); + let string = bech32::encode::(hrp, &b).unwrap(); + marshall_to_haskell_var(&string, out, out_len, RW); +} + #[no_mangle] pub extern "C" fn rust_wrapper_svk_decode( input: *const u8, From 2ae18463fc8d56ad2c6da8a5097cfc87bb22a1f4 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sun, 3 Mar 2024 15:29:50 -0600 Subject: [PATCH 03/10] Increase verbosity of Rust compile --- Setup.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Setup.hs b/Setup.hs index 81a2622..968fd0c 100644 --- a/Setup.hs +++ b/Setup.hs @@ -55,7 +55,7 @@ rsFolder = "librustzcash-wrapper" execCargo :: Verbosity -> String -> [String] -> IO () execCargo verbosity command args = do cargoPath <- - findProgramOnSearchPath Verbosity.silent defaultProgramSearchPath "cargo" + findProgramOnSearchPath Verbosity.normal defaultProgramSearchPath "cargo" dir <- getCurrentDirectory let cargoExec = case cargoPath of From 53a5b62b6bec0a8e09f454a1418d60ddaffbdd6a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 4 Mar 2024 11:58:04 -0600 Subject: [PATCH 04/10] Correct casing on Rust code --- 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 4b9e27a..0fee899 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -326,8 +326,8 @@ pub extern "C" fn rust_wrapper_bech32decode( out_len: &mut usize ) { let input: String = marshall_from_haskell_var(input, input_len, RW); - let decodedBytes = bech32::decode(&input); - match decodedBytes { + let decoded_bytes = bech32::decode(&input); + match decoded_bytes { Ok((hrp, bytes)) => { let rd = RawData {hrp: hrp.as_bytes().to_vec(), bytes}; marshall_to_haskell_var(&rd, out, out_len, RW); From 0b1d9e09203ef214b61104de01412250fa2e5fd5 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 4 Mar 2024 11:59:07 -0600 Subject: [PATCH 05/10] Implement UA encoding per ZIP-316 --- src/C/Zcash.chs | 8 ++++++++ src/ZcashHaskell/Orchard.hs | 34 ++++++++++++++++++++++++++++++++++ src/ZcashHaskell/Types.hs | 12 ++++++------ src/ZcashHaskell/Utils.hs | 5 +++++ test/Spec.hs | 15 +++++++++++---- 5 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index f93c6c9..0013f83 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -38,6 +38,14 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_bech32_encode as rustWrapperBech32Encode + { toBorshVar* `BS.ByteString'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer (T.Text)'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer (BS.ByteString)'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index 1472c9c..f0dba87 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE OverloadedStrings #-} + -- Copyright 2022-2024 Vergara Technologies LLC -- -- This file is part of Zcash-Haskell. @@ -22,8 +24,13 @@ import C.Zcash , rustWrapperUfvkDecode ) import qualified Data.ByteString as BS +import qualified Data.ByteString.Char8 as C +import qualified Data.Text as T +import qualified Data.Text.Encoding as E +import Data.Word import Foreign.Rust.Marshall.Variable import ZcashHaskell.Types +import ZcashHaskell.Utils (encodeBech32m, f4Jumble) -- | Checks if given bytestring is a valid encoded unified address isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress @@ -49,6 +56,33 @@ isValidUnifiedAddress str = then Just $ TransparentAddress P2SH whichNet (raw_to x) else Nothing) +-- | Encode a 'UnifiedAddress' per [ZIP-316](https://zips.z.cash/zip-0316) +encodeUnifiedAddress :: UnifiedAddress -> T.Text +encodeUnifiedAddress ua = encodeBech32m (E.encodeUtf8 hr) b + where + hr = + case ua_net ua of + MainNet -> "u" + TestNet -> "utest" + b = f4Jumble $ tReceiver <> sReceiver <> oReceiver <> padding + tReceiver = + case t_rec ua of + Nothing -> BS.empty + Just t -> + case ta_type t of + P2SH -> packReceiver 0x01 $ ta_bytes t + P2PKH -> packReceiver 0x00 $ ta_bytes t + sReceiver = packReceiver 0x02 $ s_rec ua + oReceiver = packReceiver 0x03 $ o_rec ua + padding = E.encodeUtf8 $ T.justifyLeft 16 '\NUL' hr + packReceiver :: Word8 -> BS.ByteString -> BS.ByteString + packReceiver typeCode receiver = + if BS.length receiver > 1 + then BS.singleton typeCode `BS.append` + (BS.singleton . toEnum . BS.length) receiver `BS.append` + receiver + else BS.empty + -- | Attempts to decode the given bytestring into a Unified Full Viewing Key decodeUfvk :: BS.ByteString -> Maybe UnifiedFullViewingKey decodeUfvk str = diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 7650dbb..356bdc4 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -186,12 +186,12 @@ data TransparentAddress = TransparentAddress -- * Sapling -- | Type to represent a Sapling Shielded Output as provided by the @getrawtransaction@ RPC method of @zcashd@. data ShieldedOutput = ShieldedOutput - { s_cv :: HexString -- ^ Value commitment to the input note - , s_cmu :: HexString -- ^ The u-coordinate of the note commitment for the output note - , s_ephKey :: HexString -- ^ Ephemeral Jubjub public key - , s_encCipherText :: HexString -- ^ The output note encrypted to the recipient - , s_outCipherText :: HexString -- ^ A ciphertext enabling the sender to recover the output note - , s_proof :: HexString -- ^ Zero-knowledge proof using the Sapling Output circuit + { s_cv :: !HexString -- ^ Value commitment to the input note + , s_cmu :: !HexString -- ^ The u-coordinate of the note commitment for the output note + , s_ephKey :: !HexString -- ^ Ephemeral Jubjub public key + , s_encCipherText :: !HexString -- ^ The output note encrypted to the recipient + , s_outCipherText :: !HexString -- ^ A ciphertext enabling the sender to recover the output note + , s_proof :: !HexString -- ^ Zero-knowledge proof using the Sapling Output circuit } 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 853857c..838afb1 100644 --- a/src/ZcashHaskell/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -19,6 +19,7 @@ module ZcashHaskell.Utils where import C.Zcash ( rustWrapperBech32Decode + , rustWrapperBech32Encode , rustWrapperF4Jumble , rustWrapperF4UnJumble ) @@ -35,6 +36,10 @@ import ZcashHaskell.Types decodeBech32 :: BS.ByteString -> RawData decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode +-- | Encode the given Human Readable Part and bytestring as a Bech32m string +encodeBech32m :: BS.ByteString -> BS.ByteString -> T.Text +encodeBech32m h d = withPureBorshVarBuffer $ rustWrapperBech32Encode h d + -- | Apply the F4Jumble transformation to the given bytestring f4Jumble :: BS.ByteString -> BS.ByteString f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble diff --git a/test/Spec.hs b/test/Spec.hs index c387f83..08e08e4 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -60,11 +60,14 @@ main :: IO () main = do hspec $ do describe "Bech32" $ do - let s = "bech321qqqsyrhqy2a" + let s = "abc14w46h2at4w46h2at4w46h2at4w46h2at958ngu" let decodedString = decodeBech32 s - it "hrp matches" $ do hrp decodedString `shouldBe` "bech32" - it "data matches" $ do + it "hrp matches" $ do hrp decodedString `shouldBe` "abc" + xit "data matches" $ do bytes decodedString `shouldBe` BS.pack ([0x00, 0x01, 0x02] :: [Word8]) + it "encoding works" $ do + encodeBech32m "abc" (bytes decodedString) `shouldBe` + E.decodeUtf8Lenient s describe "F4Jumble" $ do it "jumble a string" $ do let input = @@ -337,6 +340,11 @@ main = do let ua = "u1salpdyefbreakingtheaddressh0h9v6qjr478k80amtkqkws5pr408lxt2953dpprvu06mahxt99cv65fgsm7sw8hlchplfg5pl89ur" isValidUnifiedAddress ua `shouldBe` Nothing + it "encodes UA correctly" $ do + let ua = + "u1salpdyefywvsg2dlmxg9589yznh0h9v6qjr478k80amtkqkws5pr408lxt2953dpprvu06mahxt99cv65fgsm7sw8hlchplfg5pl89ur" + (encodeUnifiedAddress <$> isValidUnifiedAddress ua) `shouldBe` + Just (E.decodeUtf8Lenient ua) describe "Decode UVK from YWallet" $ do let uvk = "uview1u833rp8yykd7h4druwht6xp6k8krle45fx8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" @@ -440,7 +448,6 @@ main = do describe "Wallet seed phrase" $ do it "Generate phrase" $ do p <- generateWalletSeedPhrase - print p BS.length p `shouldNotBe` 0 it "Derive seed" $ do p <- generateWalletSeedPhrase From f09c3c500ba072e0c14177f67ecc2f4ec2f5dfa6 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Mar 2024 14:43:33 -0600 Subject: [PATCH 06/10] Update versions of Zcash crates --- librustzcash-wrapper/Cargo.lock | 474 ++++++++++++-------------------- librustzcash-wrapper/Cargo.toml | 9 +- librustzcash-wrapper/src/lib.rs | 40 ++- 3 files changed, 203 insertions(+), 320 deletions(-) diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index 2672c97..7f59103 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -58,12 +58,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base-x" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" - [[package]] name = "base64" version = "0.21.2" @@ -123,6 +117,12 @@ version = "1.3.2" 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" + [[package]] name = "bitvec" version = "1.0.1" @@ -288,10 +288,14 @@ dependencies = [ ] [[package]] -name = "bumpalo" -version = "3.13.0" +name = "bs58" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "sha2 0.10.6", + "tinyvec", +] [[package]] name = "byteorder" @@ -361,12 +365,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "const_fn" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" - [[package]] name = "constant_time_eq" version = "0.2.5" @@ -441,6 +439,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.9.0" @@ -461,12 +468,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "either" version = "1.8.1" @@ -710,11 +711,11 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.3.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ad43a3f5795945459d577f6589cf62a476e92c79b75e70cd954364e14ce17b" +checksum = "361c467824d4d9d4f284be4b2608800839419dccc4d4608f28345237fe354623" dependencies = [ - "serde", + "either", ] [[package]] @@ -765,12 +766,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" - [[package]] name = "jubjub" version = "0.10.0" @@ -891,6 +886,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.45" @@ -934,9 +935,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6f418f2c25573923f81a091f38b4b19bc20f6c92b5070fb8f0711e64a2b998" +checksum = "5d31e68534df32024dcc89a8390ec6d7bef65edd87d91b45cfb481a2eb2d77c5" dependencies = [ "aes", "bitvec", @@ -960,6 +961,36 @@ dependencies = [ "zcash_note_encryption", ] +[[package]] +name = "orchard" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb255c3ffdccd3c84fe9ebed72aef64fdc72e6a3e4180dd411002d47abaad42" +dependencies = [ + "aes", + "bitvec", + "blake2b_simd", + "ff", + "fpe", + "group", + "halo2_gadgets", + "halo2_proofs", + "hex", + "incrementalmerkletree", + "lazy_static", + "memuse", + "nonempty", + "pasta_curves", + "rand", + "reddsa", + "serde", + "subtle", + "tracing", + "zcash_note_encryption", + "zcash_spec", + "zip32", +] + [[package]] name = "pairing" version = "0.23.0" @@ -1038,6 +1069,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1046,12 +1083,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.25" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 1.0.109", + "syn 2.0.32", ] [[package]] @@ -1063,12 +1100,6 @@ dependencies = [ "toml", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.66" @@ -1080,9 +1111,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" dependencies = [ "bytes", "prost-derive", @@ -1090,53 +1121,53 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.9" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck", "itertools", - "lazy_static", "log", "multimap", + "once_cell", "petgraph", "prettyplease", "prost", "prost-types", "regex", - "syn 1.0.109", + "syn 2.0.32", "tempfile", "which", ] [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.32", ] [[package]] name = "prost-types" -version = "0.11.9" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" dependencies = [ "prost", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1223,7 +1254,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1243,7 +1274,7 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.32", ] [[package]] @@ -1261,22 +1292,13 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "0.37.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -1292,20 +1314,15 @@ dependencies = [ "borsh 0.10.3", "f4jumble", "haskell-ffi", - "orchard", + "orchard 0.7.1", "proc-macro2", - "zcash_address", + "zcash_address 0.2.0", "zcash_client_backend", "zcash_note_encryption", "zcash_primitives", + "zip32", ] -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - [[package]] name = "scopeguard" version = "1.1.0" @@ -1321,67 +1338,26 @@ dependencies = [ "zeroize", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" -version = "1.0.159" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.32", ] -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" version = "0.9.9" @@ -1406,76 +1382,30 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "shardtree" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19f96dde3a8693874f7e7c53d95616569b4009379a903789efbd448f4ea9cc7" +dependencies = [ + "bitflags 2.4.2", + "either", + "incrementalmerkletree", + "tracing", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "subtle" version = "2.4.1" @@ -1495,9 +1425,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.13" +version = "2.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" dependencies = [ "proc-macro2", "quote", @@ -1541,46 +1471,27 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.32", ] [[package]] name = "time" -version = "0.2.27" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", - "time-macros", - "version_check", - "winapi", + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", ] [[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" +name = "time-core" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn 1.0.109", -] +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tinyvec" @@ -1608,15 +1519,15 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.9.2" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6fdaae4c2c638bb70fe42803a26fbd6fc6ac8c72f5c59f67ecc2a2dcabf4b07" +checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" dependencies = [ "prettyplease", "proc-macro2", "prost-build", "quote", - "syn 1.0.109", + "syn 2.0.32", ] [[package]] @@ -1639,7 +1550,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.32", ] [[package]] @@ -1706,60 +1617,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.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.13", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.13", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - [[package]] name = "which" version = "4.4.0" @@ -1771,28 +1628,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" @@ -1875,36 +1710,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "804268e702b664fc09d3e2ce82786d0addf4ae57ba6976469be63e09066bf9f7" dependencies = [ "bech32 0.8.1", - "bs58", + "bs58 0.4.0", + "f4jumble", + "zcash_encoding", +] + +[[package]] +name = "zcash_address" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bce173f1d9ed4f806e310bc3a873301531e7a6dc209928584d6404e3f8228ef4" +dependencies = [ + "bech32 0.9.1", + "bs58 0.5.0", "f4jumble", "zcash_encoding", ] [[package]] name = "zcash_client_backend" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55db8d2cb4ca82a71fa66ccd9fa5b211f5ab90c866721311ddd85f8f90d0701" +checksum = "d6a382af39be9ee5a3788157145c404b7cd19acc440903f6c34b09fb44f0e991" dependencies = [ "base64", "bech32 0.9.1", "bls12_381", - "bs58", + "bs58 0.5.0", "crossbeam-channel", "group", + "hex", + "incrementalmerkletree", "memuse", "nom", - "orchard", + "orchard 0.6.0", "percent-encoding", "prost", "rayon", "secrecy", + "shardtree", "subtle", "time", "tonic-build", "tracing", "which", - "zcash_address", + "zcash_address 0.3.1", "zcash_encoding", "zcash_note_encryption", "zcash_primitives", @@ -1922,9 +1772,9 @@ dependencies = [ [[package]] name = "zcash_note_encryption" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb2149e6cd5fbee36c5b87c601715a8c35554602f7fe84af38b636afa2db318" +checksum = "5b4580cd6cee12e44421dac43169be8d23791650816bdb34e6ddfa70ac89c1c5" dependencies = [ "chacha20", "chacha20poly1305", @@ -1935,9 +1785,9 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914d2195a478d5b63191584dff126f552751115181857b290211ec88e68acc3e" +checksum = "d17e4c94ca8d69d2fcf2be97522da5732a580eb2125cda3b150761952f8df8e6" dependencies = [ "aes", "bip0039", @@ -1956,16 +1806,25 @@ dependencies = [ "lazy_static", "memuse", "nonempty", - "orchard", + "orchard 0.6.0", "rand", "rand_core", "sha2 0.10.6", "subtle", - "zcash_address", + "zcash_address 0.3.1", "zcash_encoding", "zcash_note_encryption", ] +[[package]] +name = "zcash_spec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b" +dependencies = [ + "blake2b_simd", +] + [[package]] name = "zeroize" version = "1.6.0" @@ -1983,5 +1842,16 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.32", +] + +[[package]] +name = "zip32" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d724a63be4dfb50b7f3617e542984e22e4b4a5b8ca5de91f55613152885e6b22" +dependencies = [ + "blake2b_simd", + "memuse", + "subtle", ] diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index 49fbb9a..9c8f966 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -11,10 +11,11 @@ f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" bech32 = "0.11" -orchard = "0.4.0" -zcash_note_encryption = "0.3.0" -zcash_primitives = "0.11.0" -zcash_client_backend = "0.9.0" +orchard = "0.7.0" +zcash_note_encryption = "0.4.0" +zcash_primitives = "0.13.0" +zcash_client_backend = "0.10.0" +zip32 = "0.1.0" proc-macro2 = "1.0.66" [features] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 0fee899..ed160e6 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -9,7 +9,6 @@ use std::{ Write, Cursor }, - fmt::{Debug, Display, Formatter} }; use f4jumble; @@ -23,24 +22,19 @@ use haskell_ffi::{ FromHaskell, HaskellSize, ToHaskell }; +use zip32; + use zcash_primitives::{ zip32::Scope as SaplingScope, zip339::{Count, Mnemonic}, transaction::components::sapling::{ - read_zkproof, GrothProofBytes, OutputDescription, - CompactOutputDescription }, sapling::{ - value::ValueCommitment as SaplingValueCommitment, - keys::{ - FullViewingKey as SaplingViewingKey, - PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey - }, - note_encryption::SaplingDomain, PaymentAddress, - note::ExtractedNoteCommitment as SaplingExtractedNoteCommitment + keys::PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey, + note_encryption::SaplingDomain }, transaction::Transaction, consensus::{ @@ -60,17 +54,14 @@ use zcash_client_backend::keys::sapling::ExtendedFullViewingKey; use orchard::{ Action, - keys::{FullViewingKey, PreparedIncomingViewingKey, Scope}, + keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope}, note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment}, note_encryption::OrchardDomain, primitives::redpallas::{VerificationKey, SpendAuth, Signature}, value::ValueCommitment }; -use zcash_note_encryption::EphemeralKeyBytes; - use bech32::{ - decode, Hrp, Bech32m }; @@ -620,3 +611,24 @@ pub extern "C" fn rust_wrapper_recover_seed( } } } + +#[no_mangle] +pub extern "C" fn rust_wrapper_derive_orchard_spending_key( + seed: *const u8, + seed_len: usize, + coin_type: u32, + acc_id: u32, + out: *mut u8, + out_len: &mut usize + ){ + let s: Vec = marshall_from_haskell_var(seed, seed_len, RW); + let sk = SpendingKey::from_zip32_seed(&s, coin_type, zip32::AccountId::try_from(acc_id).unwrap()); + match sk { + Ok(key) => { + marshall_to_haskell_var(&key.to_bytes(), out, out_len, RW); + }, + Err(_e) => { + marshall_to_haskell_var(&vec![0], out, out_len, RW); + } + } +} From 694ab8fd172ba0328f94c5f73d6ca0a9e3167585 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Mar 2024 14:44:00 -0600 Subject: [PATCH 07/10] Add new Orchard spending key generation --- src/C/Zcash.chs | 9 +++++++++ src/ZcashHaskell/Orchard.hs | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 0013f83..84a641b 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -133,3 +133,12 @@ import ZcashHaskell.Types } -> `()' #} + +{# fun unsafe rust_wrapper_derive_orchard_spending_key as rustWrapperGenOrchardSpendKey + { toBorshVar* `BS.ByteString'& + , `Word32' + , `Word32' + , getVarBuffer `Buffer (BS.ByteString)'& + } + -> `()' +#} diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index f0dba87..ffe5248 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -18,7 +18,8 @@ module ZcashHaskell.Orchard where import C.Zcash - ( rustWrapperOrchardCheck + ( rustWrapperGenOrchardSpendKey + , rustWrapperOrchardCheck , rustWrapperOrchardNoteDecode , rustWrapperUADecode , rustWrapperUfvkDecode @@ -32,6 +33,12 @@ import Foreign.Rust.Marshall.Variable import ZcashHaskell.Types import ZcashHaskell.Utils (encodeBech32m, f4Jumble) +-- | Derives an Orchard spending key for the given seed and account ID +genOrchardSpendingKey :: Seed -> CoinType -> AccountId -> BS.ByteString +genOrchardSpendingKey s coinType accountId = + withPureBorshVarBuffer $ + rustWrapperGenOrchardSpendKey s (getValue coinType) (fromIntegral accountId) + -- | Checks if given bytestring is a valid encoded unified address isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress isValidUnifiedAddress str = From 53716685a89ab65404820eaf5ae9a08349e9961a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Mar 2024 14:44:19 -0600 Subject: [PATCH 08/10] Add new types for constants for Zcash protocol --- src/ZcashHaskell/Types.hs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 356bdc4..11668d1 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -61,6 +61,22 @@ data ZcashNet | RegTestNet deriving (Eq, Prelude.Show, Read) +type AccountId = Int + +-- ** Constants +-- | Types for coin types on the different networks +data CoinType + = MainNetCoin + | TestNetCoin + | RegTestNetCoin + +getValue :: CoinType -> Word32 +getValue c = + case c of + MainNetCoin -> 133 + TestNetCoin -> 1 + RegTestNetCoin -> 1 + -- * RPC -- | A type to model Zcash RPC calls data RpcCall = RpcCall From 3822e9f2ff966f9c271e9b5a316ec016168fd172 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Mar 2024 15:09:35 -0600 Subject: [PATCH 09/10] Add tests for Orchard spending key --- librustzcash-wrapper/src/lib.rs | 2 +- src/ZcashHaskell/Orchard.hs | 14 +++++++++++--- test/Spec.hs | 7 +++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index ed160e6..3b7297a 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -625,7 +625,7 @@ pub extern "C" fn rust_wrapper_derive_orchard_spending_key( let sk = SpendingKey::from_zip32_seed(&s, coin_type, zip32::AccountId::try_from(acc_id).unwrap()); match sk { Ok(key) => { - marshall_to_haskell_var(&key.to_bytes(), out, out_len, RW); + marshall_to_haskell_var(&key.to_bytes().to_vec(), out, out_len, RW); }, Err(_e) => { marshall_to_haskell_var(&vec![0], out, out_len, RW); diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index ffe5248..9d33959 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -34,10 +34,18 @@ import ZcashHaskell.Types import ZcashHaskell.Utils (encodeBech32m, f4Jumble) -- | Derives an Orchard spending key for the given seed and account ID -genOrchardSpendingKey :: Seed -> CoinType -> AccountId -> BS.ByteString +genOrchardSpendingKey :: Seed -> CoinType -> AccountId -> Maybe BS.ByteString genOrchardSpendingKey s coinType accountId = - withPureBorshVarBuffer $ - rustWrapperGenOrchardSpendKey s (getValue coinType) (fromIntegral accountId) + if BS.length k /= 32 + then Nothing + else Just k + where + k = + withPureBorshVarBuffer $ + rustWrapperGenOrchardSpendKey + s + (getValue coinType) + (fromIntegral accountId) -- | Checks if given bytestring is a valid encoded unified address isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress diff --git a/test/Spec.hs b/test/Spec.hs index 08e08e4..c06a689 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -19,6 +19,7 @@ {-# LANGUAGE OverloadedStrings #-} import C.Zcash (rustWrapperUADecode) +import Control.Monad.IO.Class (liftIO) import Data.Aeson import Data.Bool (Bool(True)) import qualified Data.ByteString as BS @@ -45,6 +46,7 @@ import ZcashHaskell.Sapling import ZcashHaskell.Transparent (encodeTransparent) import ZcashHaskell.Types ( BlockResponse(..) + , CoinType(..) , DecodedNote(..) , OrchardAction(..) , RawData(..) @@ -453,6 +455,11 @@ main = do p <- generateWalletSeedPhrase let s = getWalletSeed p maybe 0 BS.length s `shouldBe` 64 + it "Generate Orchard spending key" $ do + p <- generateWalletSeedPhrase + let s = getWalletSeed p + genOrchardSpendingKey (fromMaybe "" s) MainNetCoin 1 `shouldNotBe` + Nothing describe "Address tests" $ do it "Encode transparent" $ do let ua = From c13d321da5784f9f93b5a289d88bc4b49137510f Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 5 Mar 2024 15:09:57 -0600 Subject: [PATCH 10/10] Bump version --- CHANGELOG.md | 2 ++ zcash-haskell.cabal | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbea7b4..6a768c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Implementations of `Read` for types - Function to make RPC calls to `zebrad` - Function to encode unified addresses from receivers +- Function to generate an Orchard spending key +- Constants for Zcash protocol ### Changed diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index ad2e0d3..e4a2f3b 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.4.2.3 +version: 0.4.3.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain