From 69b1192e0e39636b243c7a7b780b22d70d24a310 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sat, 15 Apr 2023 20:59:43 -0500 Subject: [PATCH 01/14] Update package config --- package.yaml | 1 + zcash-haskell.cabal | 1 + 2 files changed, 2 insertions(+) diff --git a/package.yaml b/package.yaml index 4abaff2..cdbf9b7 100644 --- a/package.yaml +++ b/package.yaml @@ -9,6 +9,7 @@ copyright: "(c)2023 Vergara Technologies LLC" extra-source-files: - README.md - CHANGELOG.md +- configure # Metadata used when publishing your package synopsis: Utilities to interact with the Zcash blockchain diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index a4f20d2..cda14d2 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -18,6 +18,7 @@ build-type: Simple extra-source-files: README.md CHANGELOG.md + configure source-repository head type: git From 504969834a66c7c161e16aa312ed5afef9f17f98 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Sat, 15 Apr 2023 21:30:54 -0500 Subject: [PATCH 02/14] Add `borsh` version --- package.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.yaml b/package.yaml index cdbf9b7..a87ea24 100644 --- a/package.yaml +++ b/package.yaml @@ -27,7 +27,7 @@ library: source-dirs: src dependencies: - bytestring - - borsh + - borsh >= 0.2 - text - foreign-rust pkg-config-dependencies: From 1261a585e6f775049e772bccae55233a9fa04b05 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 18 Apr 2023 13:58:21 -0500 Subject: [PATCH 03/14] Implement shielded address validator --- app/Main.hs | 6 ------ librustzcash-wrapper/src/lib.rs | 12 ++++++++++-- src/C/Zcash.chs | 6 ++++++ src/Zcash.hs | 11 ++++++++++- zcash-haskell.cabal | 2 +- 5 files changed, 27 insertions(+), 10 deletions(-) delete mode 100644 app/Main.hs diff --git a/app/Main.hs b/app/Main.hs deleted file mode 100644 index 56a7df4..0000000 --- a/app/Main.hs +++ /dev/null @@ -1,6 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} - -module Main where - -main :: IO () -main = putStrLn "Zcash Utilities for Haskell" diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 696573b..71bac6d 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -17,13 +17,13 @@ use haskell_ffi::{ use zcash_address::{ Network, - unified::{Address, Encoding} + unified::{Address, Encoding}, + ZcashAddress }; pub enum RW {} pub const RW: PhantomData = PhantomData; - #[no_mangle] pub extern "C" fn rust_wrapper_f4jumble( input: *const u8, @@ -43,3 +43,11 @@ pub extern "C" fn rust_wrapper_ua_decode( Address::decode(&input).is_ok() //marshall_to_haskell_var(&result, out, out_len, RW); } + +#[no_mangle] +pub extern "C" fn rust_wrapper_shielded_decode( + input: *const u8, + input_len: usize) -> bool { + let input: String = marshall_from_haskell_var(input, input_len, RW); + ZcashAddress::try_from_encoded(&input).is_ok() +} diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 17cdeb5..e6e4acd 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -37,3 +37,9 @@ newtype CodedString = CodedString BS.ByteString } -> `Bool' #} + +{# fun pure unsafe rust_wrapper_shielded_decode as rustWrapperIsShielded + { toBorshVar* `BS.ByteString'& + } + -> `Bool' +#} diff --git a/src/Zcash.hs b/src/Zcash.hs index 9b289f3..ede2cd2 100644 --- a/src/Zcash.hs +++ b/src/Zcash.hs @@ -1,9 +1,15 @@ module Zcash ( f4Jumble , isValidUnifiedAddress + , isValidShieldedAddress ) where -import C.Zcash (CodedString, rustWrapperF4Jumble, rustWrapperIsUA) +import C.Zcash + ( CodedString + , rustWrapperF4Jumble + , rustWrapperIsShielded + , rustWrapperIsUA + ) import qualified Data.ByteString as BS import Foreign.Rust.Marshall.Fixed import Foreign.Rust.Marshall.Variable @@ -13,3 +19,6 @@ f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble isValidUnifiedAddress :: BS.ByteString -> Bool isValidUnifiedAddress = rustWrapperIsUA + +isValidShieldedAddress :: BS.ByteString -> Bool +isValidShieldedAddress = rustWrapperIsShielded diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index cda14d2..62b50de 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -36,7 +36,7 @@ library rustzcash_wrapper-uninstalled build-depends: base >=4.7 && <5 - , borsh + , borsh >=0.2 , bytestring , foreign-rust , text From 6c8a67f2d7f8ddba0f6466fe8ce35682b8763772 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 27 Apr 2023 09:48:11 -0500 Subject: [PATCH 04/14] Add wrappers for UFVKs --- configure | 5 +- librustzcash-wrapper/Cargo.toml | 1 + librustzcash-wrapper/src/lib.rs | 103 +++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 0af689b..21dc7bb 100755 --- a/configure +++ b/configure @@ -1,4 +1,5 @@ #!/bin/bash -export PKG_CONFIG_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug -export LD_LIBRARY_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug +echo "export PKG_CONFIG_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$PKG_CONFIG_PATH" | tee -a ~/.bashrc +echo "export LD_LIBRARY_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$LD_LIBRARY_PATH" | tee -a ~/.bashrc +source ~/.bashrc diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index d26b3d0..44d2cca 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -11,6 +11,7 @@ haskell-ffi.rev = "2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274" f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" +bech32 = "0.9.1" [features] capi = [] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 71bac6d..07b16b9 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -8,22 +8,77 @@ use std::{ use f4jumble; use borsh::{BorshDeserialize, BorshSerialize}; + use haskell_ffi::{ error::Result, - from_haskell::{marshall_from_haskell_var}, + from_haskell::marshall_from_haskell_var, to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed}, FromHaskell, HaskellSize, ToHaskell }; use zcash_address::{ Network, - unified::{Address, Encoding}, + unified::{Address, Encoding, Ufvk, Container, Fvk}, ZcashAddress }; +use bech32::{ + decode, + u5 +}; + pub enum RW {} pub const RW: PhantomData = PhantomData; +#[derive(BorshSerialize, BorshDeserialize)] +pub struct RawData { + hrp: Vec, + bytes: Vec +} + +impl ToHaskell for RawData { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +//impl FromHaskell for RawData { + //fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + //let x = RawData::deserialize(buf)?; + //Ok(x) + //} +//} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hufvk { + net: u8, + orchard: Vec, + sapling: Vec, + transparent: Vec +} + +impl ToHaskell for Hufvk { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl Hufvk { + fn add_key_section(&mut self, fvk: &Fvk) { + if let Fvk::Orchard(v) = fvk { + self.orchard = v.to_vec(); + } + if let Fvk::Sapling(w) = fvk { + self.sapling = w.to_vec(); + } + if let Fvk::P2pkh(x) = fvk { + self.transparent = x.to_vec(); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_f4jumble( input: *const u8, @@ -35,6 +90,17 @@ pub extern "C" fn rust_wrapper_f4jumble( marshall_to_haskell_var(&result, out, out_len, RW); } +#[no_mangle] +pub extern "C" fn rust_wrapper_f4unjumble( + input: *const u8, + input_len: usize, + out: *mut u8, + out_len: &mut usize) { + let input: Vec = marshall_from_haskell_var(input, input_len, RW); + let result = f4jumble::f4jumble_inv(&input).unwrap(); + marshall_to_haskell_var(&result, out, out_len, RW); +} + #[no_mangle] pub extern "C" fn rust_wrapper_ua_decode( input: *const u8, @@ -51,3 +117,36 @@ pub extern "C" fn rust_wrapper_shielded_decode( let input: String = marshall_from_haskell_var(input, input_len, RW); ZcashAddress::try_from_encoded(&input).is_ok() } + +#[no_mangle] +pub extern "C" fn rust_wrapper_bech32decode( + input: *const u8, + input_len: usize, + out: *mut u8, + out_len: &mut usize + ) { + let input: String = marshall_from_haskell_var(input, input_len, RW); + let (hrp, bytes) = bech32::decode_without_checksum(&input).unwrap(); + let rd = RawData {hrp: hrp.into(), bytes: bytes.iter().map(|&x| bech32::u5::to_u8(x)).collect()}; + marshall_to_haskell_var(&rd, out, out_len, RW); +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_ufvk_decode( + input: *const u8, + input_len: usize, + out: *mut u8, + out_len: &mut usize + ) { + let input: String = marshall_from_haskell_var(input, input_len, RW); + let (n, ufvk) = Ufvk::decode(&input).unwrap(); + let x = match n { + Network::Main => 1, + Network::Test => 2, + Network::Regtest => 3 + }; + let mut hk = Hufvk { net: x, orchard: vec![0], sapling: vec![0], transparent: vec![0] }; + let fvks = ufvk.items(); + fvks.iter().for_each(|k| hk.add_key_section(k)); + marshall_to_haskell_var(&hk, out, out_len, RW); +} From ccd4ede950d046690f36853dc5e3cd998f2cd8f7 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 27 Apr 2023 09:50:07 -0500 Subject: [PATCH 05/14] Add functions and tests for Bech32 and F4UnJumble --- package.yaml | 2 + src/C/Zcash.chs | 30 ++++++++--- src/Zcash.hs | 14 +++++- test/Spec.hs | 118 +++++++++++++++++++++++++++++++++++++++++++- zcash-haskell.cabal | 2 + 5 files changed, 156 insertions(+), 10 deletions(-) diff --git a/package.yaml b/package.yaml index a87ea24..e4bb94b 100644 --- a/package.yaml +++ b/package.yaml @@ -30,6 +30,7 @@ library: - borsh >= 0.2 - text - foreign-rust + - generics-sop pkg-config-dependencies: - rustzcash_wrapper-uninstalled @@ -45,3 +46,4 @@ tests: - zcash-haskell - hspec - bytestring + - text diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index e6e4acd..99e5004 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -1,4 +1,6 @@ {-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE UndecidableInstances #-} @@ -18,16 +20,25 @@ import Foreign.Rust.Marshall.Fixed import Foreign.Rust.Marshall.Variable import Foreign.Rust.Serialisation.Raw import Foreign.Rust.Serialisation.Raw.Base16 +import qualified Generics.SOP as SOP +import qualified GHC.Generics as GHC -newtype CodedString = CodedString BS.ByteString - deriving (Eq) - deriving newtype (BorshSize, ToBorsh, FromBorsh) - deriving newtype (IsRaw) - deriving (Prelude.Show, Data.Structured.Show) via AsBase16 CodedString +data RawData = RawData { hrp :: BS.ByteString, bytes :: BS.ByteString} + deriving stock (Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawData {# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble { toBorshVar* `BS.ByteString'& - , getVarBuffer `Buffer (CodedString)'& + , getVarBuffer `Buffer (BS.ByteString)'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_f4unjumble as rustWrapperF4UnJumble + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer (BS.ByteString)'& } -> `()' #} @@ -43,3 +54,10 @@ newtype CodedString = CodedString BS.ByteString } -> `Bool' #} + +{# fun unsafe rust_wrapper_bech32decode as rustWrapperBech32Decode + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer RawData'& + } + -> `()' +#} diff --git a/src/Zcash.hs b/src/Zcash.hs index ede2cd2..fd8953f 100644 --- a/src/Zcash.hs +++ b/src/Zcash.hs @@ -1,12 +1,16 @@ module Zcash ( f4Jumble + , f4UnJumble , isValidUnifiedAddress , isValidShieldedAddress + , decodeBech32 ) where import C.Zcash - ( CodedString + ( RawData + , rustWrapperBech32Decode , rustWrapperF4Jumble + , rustWrapperF4UnJumble , rustWrapperIsShielded , rustWrapperIsUA ) @@ -14,11 +18,17 @@ import qualified Data.ByteString as BS import Foreign.Rust.Marshall.Fixed import Foreign.Rust.Marshall.Variable -f4Jumble :: BS.ByteString -> CodedString +f4Jumble :: BS.ByteString -> BS.ByteString f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble +f4UnJumble :: BS.ByteString -> BS.ByteString +f4UnJumble = withPureBorshVarBuffer . rustWrapperF4UnJumble + isValidUnifiedAddress :: BS.ByteString -> Bool isValidUnifiedAddress = rustWrapperIsUA isValidShieldedAddress :: BS.ByteString -> Bool isValidShieldedAddress = rustWrapperIsShielded + +decodeBech32 :: BS.ByteString -> RawData +decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode diff --git a/test/Spec.hs b/test/Spec.hs index dfbc469..c0aa00e 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1,7 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} -import C.Zcash (CodedString(CodedString), rustWrapperIsUA) +import C.Zcash (RawData(..), rustWrapperIsUA) import qualified Data.ByteString as BS +import qualified Data.Text.Encoding as E import Data.Word import Test.Hspec import Zcash @@ -111,7 +112,120 @@ main = do , 0x8d , 0x22 ] :: [Word8] - CodedString (BS.pack out) `shouldBe` f4Jumble (BS.pack input) + BS.pack out `shouldBe` f4Jumble (BS.pack input) + it "unjumble a string" $ do + let input = + [ 0x5d + , 0x7a + , 0x8f + , 0x73 + , 0x9a + , 0x2d + , 0x9e + , 0x94 + , 0x5b + , 0x0c + , 0xe1 + , 0x52 + , 0xa8 + , 0x04 + , 0x9e + , 0x29 + , 0x4c + , 0x4d + , 0x6e + , 0x66 + , 0xb1 + , 0x64 + , 0x93 + , 0x9d + , 0xaf + , 0xfa + , 0x2e + , 0xf6 + , 0xee + , 0x69 + , 0x21 + , 0x48 + , 0x1c + , 0xdd + , 0x86 + , 0xb3 + , 0xcc + , 0x43 + , 0x18 + , 0xd9 + , 0x61 + , 0x4f + , 0xc8 + , 0x20 + , 0x90 + , 0x5d + , 0x04 + , 0x2b + ] :: [Word8] + let out = + [ 0x03 + , 0x04 + , 0xd0 + , 0x29 + , 0x14 + , 0x1b + , 0x99 + , 0x5d + , 0xa5 + , 0x38 + , 0x7c + , 0x12 + , 0x59 + , 0x70 + , 0x67 + , 0x35 + , 0x04 + , 0xd6 + , 0xc7 + , 0x64 + , 0xd9 + , 0x1e + , 0xa6 + , 0xc0 + , 0x82 + , 0x12 + , 0x37 + , 0x70 + , 0xc7 + , 0x13 + , 0x9c + , 0xcd + , 0x88 + , 0xee + , 0x27 + , 0x36 + , 0x8c + , 0xd0 + , 0xc0 + , 0x92 + , 0x1a + , 0x04 + , 0x44 + , 0xc8 + , 0xe5 + , 0x85 + , 0x8d + , 0x22 + ] :: [Word8] + f4UnJumble (BS.pack out) `shouldBe` BS.pack input + describe "Decode UVK from YWallet" $ do + let uvk = + "uview1u833rp8yykd7h4druwht6xp6k8krle45fx8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" + let res = decodeBech32 uvk + let rawBytes = f4UnJumble $ bytes res + it "decodes Bech32" $ do + print $ hrp res + print $ BS.length $ bytes res + hrp res `shouldBe` "uview" + it "unjumble result" $ do + BS.takeEnd 16 rawBytes `shouldBe` "uview00000000000" describe "Unified address" $ do it "succeeds with correct UA" $ do let ua = diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 62b50de..8815cba 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -39,6 +39,7 @@ library , borsh >=0.2 , bytestring , foreign-rust + , generics-sop , text default-language: Haskell2010 @@ -54,5 +55,6 @@ test-suite zcash-haskell-test base >=4.7 && <5 , bytestring , hspec + , text , zcash-haskell default-language: Haskell2010 From 831403744d48b4f7d798f38087c471052ad64f97 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 27 Apr 2023 09:54:01 -0500 Subject: [PATCH 06/14] Documentation update --- CHANGELOG.md | 3 +++ README.md | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e88dc8c..4c806da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,3 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Function `f4Jumble` - Function `isValidUnifiedAddress` +- Function `f4UnJumble` +- Function `isValidShieldedAddress` +- Function `decodeBech32` diff --git a/README.md b/README.md index ed72755..41e7128 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ -# haskell-wrapper +# zcash-haskell + +A Haskell library to interact with the Zcash blockchain. + +## Installation + + From 7f181ccac39af08798ac00030de5e37e6b44b12a Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 4 May 2023 09:23:05 -0500 Subject: [PATCH 07/14] Add Rust orchard tx decoding function --- Makefile | 11 + librustzcash-wrapper/Cargo.lock | 685 +++++++++++++++++++++++++++++++- librustzcash-wrapper/Cargo.toml | 2 + librustzcash-wrapper/src/lib.rs | 123 +++++- src/C/Zcash.chs | 20 + src/Zcash.hs | 35 ++ test/Spec.hs | 27 +- 7 files changed, 879 insertions(+), 24 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3189202 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +rustlib := librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug + +.PHONY: all + +all: rust-wrapper haskell + +haskell: src/Zcash.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc + stack build + +rust-wrapper: librustzcash-wrapper/src/lib.rs librustzcash-wrapper/Cargo.toml + cd librustzcash-wrapper && cargo +nightly cbuild diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index c5c6ca0..97b5326 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -2,6 +2,27 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.6" @@ -25,12 +46,24 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bincode" version = "1.3.3" @@ -40,6 +73,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2b_simd" version = "1.0.1" @@ -60,6 +105,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "borsh" version = "0.9.3" @@ -165,12 +221,56 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "constant_time_eq" version = "0.2.5" @@ -186,6 +286,65 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "digest" version = "0.9.0" @@ -195,6 +354,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "f4jumble" version = "0.1.0" @@ -204,6 +369,37 @@ dependencies = [ "blake2b_simd", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "fpe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c4b37de5ae15812a764c958297cfc50f5c010438f60c6ce75d11b802abd404" +dependencies = [ + "cbc", + "cipher", + "libm", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" version = "0.14.7" @@ -225,6 +421,58 @@ dependencies = [ "wasi", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "memuse", + "rand_core", + "subtle", +] + +[[package]] +name = "halo2_gadgets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126a150072b0c38c7b573fe3eaf0af944a7fed09e154071bf2436d3f016f7230" +dependencies = [ + "arrayvec", + "bitvec", + "ff", + "group", + "halo2_proofs", + "lazy_static", + "pasta_curves", + "rand", + "subtle", + "uint", +] + +[[package]] +name = "halo2_legacy_pdqsort" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" + +[[package]] +name = "halo2_proofs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b867a8d9bbb85fca76fff60652b5cd19b853a1c4d0665cb89bee68b18d2caf0" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "halo2_legacy_pdqsort", + "maybe-rayon", + "pasta_curves", + "rand_core", + "tracing", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -256,18 +504,148 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "incrementalmerkletree" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5ad43a3f5795945459d577f6589cf62a476e92c79b75e70cd954364e14ce17b" +dependencies = [ + "serde", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "jubjub" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8499f7a74008aafbecb2a2e608a3e13e4dd3e84df198b604451efe93f2de6e61" +dependencies = [ + "bitvec", + "bls12_381", + "ff", + "group", + "rand_core", + "subtle", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + [[package]] name = "libc" version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memuse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" +dependencies = [ + "nonempty", +] + [[package]] name = "nonempty" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -280,6 +658,72 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "orchard" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6f418f2c25573923f81a091f38b4b19bc20f6c92b5070fb8f0711e64a2b998" +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", +] + +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "lazy_static", + "rand", + "static_assertions", + "subtle", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -307,6 +751,82 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "reddsa" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b34d2c0df43159d2ff79d3cf929c9f11415529127344edb8160ad2be499fcd" +dependencies = [ + "blake2b_simd", + "byteorder", + "group", + "hex", + "jubjub", + "pasta_curves", + "rand_core", + "serde", + "thiserror", + "zeroize", +] + [[package]] name = "ref-cast" version = "1.0.16" @@ -331,17 +851,40 @@ dependencies = [ name = "rustzcash-wrapper" version = "0.1.0" dependencies = [ + "bech32 0.9.1", "borsh 0.10.3", "f4jumble", "haskell-ffi", + "orchard", "zcash_address", + "zcash_note_encryption", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] [[package]] name = "sha2" @@ -356,6 +899,24 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.109" @@ -378,6 +939,32 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + [[package]] name = "toml" version = "0.5.11" @@ -387,18 +974,72 @@ dependencies = [ "serde", ] +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "version_check" version = "0.9.4" @@ -411,13 +1052,22 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zcash_address" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "804268e702b664fc09d3e2ce82786d0addf4ae57ba6976469be63e09066bf9f7" dependencies = [ - "bech32", + "bech32 0.8.1", "bs58", "f4jumble", "zcash_encoding", @@ -432,3 +1082,36 @@ dependencies = [ "byteorder", "nonempty", ] + +[[package]] +name = "zcash_note_encryption" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb2149e6cd5fbee36c5b87c601715a8c35554602f7fe84af38b636afa2db318" +dependencies = [ + "chacha20", + "chacha20poly1305", + "cipher", + "rand_core", + "subtle", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index 44d2cca..491d1d4 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -12,6 +12,8 @@ f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" bech32 = "0.9.1" +orchard = "0.4.0" +zcash_note_encryption = "0.3.0" [features] capi = [] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 07b16b9..3662807 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -11,7 +11,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use haskell_ffi::{ error::Result, - from_haskell::marshall_from_haskell_var, + from_haskell::{marshall_from_haskell_var, marshall_from_haskell_fixed}, to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed}, FromHaskell, HaskellSize, ToHaskell }; @@ -22,6 +22,17 @@ use zcash_address::{ ZcashAddress }; +use orchard::{ + Action, + keys::{FullViewingKey, PreparedIncomingViewingKey, Scope}, + note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment}, + note_encryption::OrchardDomain, + primitives::redpallas::{VerificationKey, SpendAuth, Signature}, + value::ValueCommitment +}; + +use zcash_note_encryption; + use bech32::{ decode, u5 @@ -50,6 +61,40 @@ impl ToHaskell for RawData { //} //} +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Haction { + nf: Vec, + rk: Vec, + cmx: Vec, + eph_key: Vec, + enc_txt: Vec, + out_txt: Vec, + cv: Vec, + auth: Vec +} + +impl FromHaskell for Haction { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Haction::deserialize(buf)?; + Ok(x) + } +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hnote { + note: u64, + recipient: Vec, + memo: Vec +} + +impl ToHaskell for Hnote { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + + #[derive(BorshSerialize, BorshDeserialize)] pub struct Hufvk { net: u8, @@ -79,6 +124,10 @@ impl Hufvk { } } +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())) +} + #[no_mangle] pub extern "C" fn rust_wrapper_f4jumble( input: *const u8, @@ -139,14 +188,66 @@ pub extern "C" fn rust_wrapper_ufvk_decode( out_len: &mut usize ) { let input: String = marshall_from_haskell_var(input, input_len, RW); - let (n, ufvk) = Ufvk::decode(&input).unwrap(); - let x = match n { - Network::Main => 1, - Network::Test => 2, - Network::Regtest => 3 - }; - let mut hk = Hufvk { net: x, orchard: vec![0], sapling: vec![0], transparent: vec![0] }; - let fvks = ufvk.items(); - fvks.iter().for_each(|k| hk.add_key_section(k)); - marshall_to_haskell_var(&hk, out, out_len, RW); + let dec_key = Ufvk::decode(&input); + match dec_key { + Ok((n, ufvk)) => { + let x = match n { + Network::Main => 1, + Network::Test => 2, + Network::Regtest => 3 + }; + let mut hk = Hufvk { net: x, orchard: vec![0], sapling: vec![0], transparent: vec![0] }; + let fvks = ufvk.items(); + fvks.iter().for_each(|k| hk.add_key_section(k)); + marshall_to_haskell_var(&hk, out, out_len, RW); + } + Err(_e) => { + let hk0 = Hufvk { net: 0, orchard: vec![0], sapling: vec![0], transparent: vec![0] }; + marshall_to_haskell_var(&hk0, out, out_len, RW); + } + } +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_ua_note_decrypt( + key: *const u8, + key_len: usize, + note: *const u8, + note_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let fvk_input: Vec = marshall_from_haskell_var(key, key_len, RW); + let note_input: Haction = marshall_from_haskell_var(note, note_len, RW); + let action: Action> = Action::from_parts( + Nullifier::from_bytes(&to_array(note_input.nf)).unwrap(), + VerificationKey::try_from(to_array(note_input.rk)).unwrap(), + ExtractedNoteCommitment::from_bytes(&to_array(note_input.cmx)).unwrap(), + TransmittedNoteCiphertext {epk_bytes: to_array(note_input.eph_key), enc_ciphertext: to_array(note_input.enc_txt), out_ciphertext: to_array(note_input.out_txt)}, + ValueCommitment::from_bytes(&to_array(note_input.cv)).unwrap(), + Signature::from(to_array(note_input.auth))); + let fvk_array = to_array(fvk_input); + let domain = OrchardDomain::for_nullifier(*action.nullifier()); + let dec_fvk = FullViewingKey::from_bytes(&fvk_array); + match dec_fvk { + Some(fvk) => { + let ivk = fvk.to_ivk(Scope::External); + let pivk = PreparedIncomingViewingKey::new(&ivk); + let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action); + match result { + Some((n, r, m)) => { + let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec() }; + marshall_to_haskell_var(&hn, out, out_len, RW); + } + None => { + let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] }; + marshall_to_haskell_var(&hn0, out, out_len, RW); + } + } + }, + None => { + let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] }; + marshall_to_haskell_var(&hn0, out, out_len, RW); + } + } } diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 99e5004..e7eed78 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -29,6 +29,19 @@ data RawData = RawData { hrp :: BS.ByteString, bytes :: BS.ByteString} deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawData +data UnifiedFullViewingKey = + UnifiedFullViewingKey + { net :: Word8 + , o_key :: BS.ByteString + , s_key :: BS.ByteString + , t_key :: 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 UnifiedFullViewingKey + + {# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer (BS.ByteString)'& @@ -61,3 +74,10 @@ data RawData = RawData { hrp :: BS.ByteString, bytes :: BS.ByteString} } -> `()' #} + +{# fun unsafe rust_wrapper_ufvk_decode as rustWrapperUfvkDecode + { toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer UnifiedFullViewingKey'& + } + -> `()' +#} diff --git a/src/Zcash.hs b/src/Zcash.hs index fd8953f..66c7d7f 100644 --- a/src/Zcash.hs +++ b/src/Zcash.hs @@ -4,31 +4,66 @@ module Zcash , isValidUnifiedAddress , isValidShieldedAddress , decodeBech32 + , decodeUfvk ) where import C.Zcash ( RawData + , UnifiedFullViewingKey(..) , rustWrapperBech32Decode , rustWrapperF4Jumble , rustWrapperF4UnJumble , rustWrapperIsShielded , rustWrapperIsUA + , rustWrapperUfvkDecode ) import qualified Data.ByteString as BS import Foreign.Rust.Marshall.Fixed import Foreign.Rust.Marshall.Variable +-- | Apply the F4Jumble transformation to the given bytestring f4Jumble :: BS.ByteString -> BS.ByteString f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble +-- | Apply the inverse F4Jumble transformation to the given bytestring f4UnJumble :: BS.ByteString -> BS.ByteString f4UnJumble = withPureBorshVarBuffer . rustWrapperF4UnJumble +-- | Check if given bytestring is a valid encoded unified address isValidUnifiedAddress :: BS.ByteString -> Bool isValidUnifiedAddress = rustWrapperIsUA +-- | Check if given bytesting is a valid encoded shielded address isValidShieldedAddress :: BS.ByteString -> Bool isValidShieldedAddress = rustWrapperIsShielded +-- | Decode the given bytestring using Bech32 decodeBech32 :: BS.ByteString -> RawData decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode + +-- | Attempt to decode the given bytestring into a Unified Full Viewing Key +decodeUfvk :: BS.ByteString -> Maybe UnifiedFullViewingKey +decodeUfvk str = + case net decodedKey of + 0 -> Nothing + _ -> Just decodedKey + where + decodedKey = (withPureBorshVarBuffer . rustWrapperUfvkDecode) str + +deriveOvk :: BS.ByteString -> BS.ByteString +deriveOvk fvk = undefined -- BS.takeEnd (lovk / 8) $ r k (t ak nk) + --where + --lovk :: Int + --lovk = 256 + --ak :: BS.ByteString + --ak = BS.take 32 fvk + --nk :: BS.ByteString + --nk = BS.take 32 $ BS.takeEnd 64 fvk + --rivk :: BS.ByteString + --rivk = BS.takeEnd 32 fvk + --k :: BS.ByteString + --k = i2lebsp rivk + --r :: BS.ByteString -> BS.ByteString -> BS.ByteString + --r ki ti = blake2b512 "Zcash_ExpandSeed" (BS.append (lebs2osp ki) ti) + --t :: BS.ByteString -> BS.ByteString -> BS.ByteString + --t a n = BS.append (BS.cons 0x82 (i2leosp a)) (i2leosp n) diff --git a/test/Spec.hs b/test/Spec.hs index c0aa00e..835d820 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} -import C.Zcash (RawData(..), rustWrapperIsUA) +import C.Zcash (RawData(..), UnifiedFullViewingKey(..), rustWrapperIsUA) import qualified Data.ByteString as BS import qualified Data.Text.Encoding as E import Data.Word @@ -215,17 +215,6 @@ main = do , 0x22 ] :: [Word8] f4UnJumble (BS.pack out) `shouldBe` BS.pack input - describe "Decode UVK from YWallet" $ do - let uvk = - "uview1u833rp8yykd7h4druwht6xp6k8krle45fx8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" - let res = decodeBech32 uvk - let rawBytes = f4UnJumble $ bytes res - it "decodes Bech32" $ do - print $ hrp res - print $ BS.length $ bytes res - hrp res `shouldBe` "uview" - it "unjumble result" $ do - BS.takeEnd 16 rawBytes `shouldBe` "uview00000000000" describe "Unified address" $ do it "succeeds with correct UA" $ do let ua = @@ -235,3 +224,17 @@ main = do let ua = "u1salpdyefbreakingtheaddressh0h9v6qjr478k80amtkqkws5pr408lxt2953dpprvu06mahxt99cv65fgsm7sw8hlchplfg5pl89ur" isValidUnifiedAddress ua `shouldBe` False + describe "Decode UVK from YWallet" $ do + let uvk = + "uview1u833rp8yykd7h4druwht6xp6k8krle45fx8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" + let res = decodeUfvk uvk + it "is mainnet" $ do maybe 0 net res `shouldBe` 1 + it "has Orchard key" $ do BS.length (maybe "" o_key res) `shouldBe` 96 + it "has Sapling key" $ do BS.length (maybe "" s_key res) `shouldBe` 128 + it "does not have Transparent key" $ do + BS.length (maybe "" t_key res) `shouldBe` 1 + describe "Decode bad UVK" $ do + it "should fail" $ do + let fakeUvk = + "uview1u83changinga987bundchofch4ract3r5x8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" + decodeUfvk fakeUvk `shouldBe` Nothing From b35b89fbb4a95036e58310ed63c794f043241347 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 4 May 2023 15:26:49 -0500 Subject: [PATCH 08/14] Implement Orchard Tx decoding and tests --- Makefile | 4 +- librustzcash-wrapper/src/lib.rs | 2 +- src/C/Zcash.chs | 28 +++++-------- src/HaskellZcash/Orchard.hs | 34 ++++++++++++++++ src/HaskellZcash/Sapling.hs | 8 ++++ src/HaskellZcash/Types.hs | 63 ++++++++++++++++++++++++++++++ src/HaskellZcash/Utils.hs | 34 ++++++++++++++++ src/Zcash.hs | 69 --------------------------------- test/Spec.hs | 63 +++++++++++++++++++++++++++++- zcash-haskell.cabal | 5 ++- 10 files changed, 217 insertions(+), 93 deletions(-) create mode 100644 src/HaskellZcash/Orchard.hs create mode 100644 src/HaskellZcash/Sapling.hs create mode 100644 src/HaskellZcash/Types.hs create mode 100644 src/HaskellZcash/Utils.hs delete mode 100644 src/Zcash.hs diff --git a/Makefile b/Makefile index 3189202..2c73f57 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,10 @@ rustlib := librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug .PHONY: all -all: rust-wrapper haskell +all: haskell haskell: src/Zcash.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc stack build -rust-wrapper: librustzcash-wrapper/src/lib.rs librustzcash-wrapper/Cargo.toml +$(rustlib)/rustzcash_wrapper.h: librustzcash-wrapper/src/lib.rs librustzcash-wrapper/Cargo.toml cd librustzcash-wrapper && cargo +nightly cbuild diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 3662807..0aaf6ee 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -209,7 +209,7 @@ pub extern "C" fn rust_wrapper_ufvk_decode( } #[no_mangle] -pub extern "C" fn rust_wrapper_ua_note_decrypt( +pub extern "C" fn rust_wrapper_orchard_note_decrypt( key: *const u8, key_len: usize, note: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index e7eed78..5c1b875 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -13,6 +13,7 @@ import qualified Data.ByteString as BS import Codec.Borsh import Data.Text (Text) import Data.Word +import Data.Int import Data.Structured import Foreign.C.Types import Foreign.Rust.Marshall.External @@ -22,25 +23,8 @@ import Foreign.Rust.Serialisation.Raw import Foreign.Rust.Serialisation.Raw.Base16 import qualified Generics.SOP as SOP import qualified GHC.Generics as GHC +import HaskellZcash.Types -data RawData = RawData { hrp :: BS.ByteString, bytes :: BS.ByteString} - deriving stock (Prelude.Show, GHC.Generic) - deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) - deriving anyclass (Data.Structured.Show) - deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawData - -data UnifiedFullViewingKey = - UnifiedFullViewingKey - { net :: Word8 - , o_key :: BS.ByteString - , s_key :: BS.ByteString - , t_key :: 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 UnifiedFullViewingKey - {# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble { toBorshVar* `BS.ByteString'& @@ -81,3 +65,11 @@ data UnifiedFullViewingKey = } -> `()' #} + +{# fun unsafe rust_wrapper_orchard_note_decrypt as rustWrapperOrchardNoteDecode + { toBorshVar* `BS.ByteString'& + , toBorshVar* `OrchardAction'& + , getVarBuffer `Buffer OrchardDecodedAction'& + } + -> `()' + #} diff --git a/src/HaskellZcash/Orchard.hs b/src/HaskellZcash/Orchard.hs new file mode 100644 index 0000000..46032b7 --- /dev/null +++ b/src/HaskellZcash/Orchard.hs @@ -0,0 +1,34 @@ +module HaskellZcash.Orchard where + +import C.Zcash + ( rustWrapperIsUA + , rustWrapperOrchardNoteDecode + , rustWrapperUfvkDecode + ) +import qualified Data.ByteString as BS +import Foreign.Rust.Marshall.Variable +import HaskellZcash.Types + +-- | Check if given bytestring is a valid encoded unified address +isValidUnifiedAddress :: BS.ByteString -> Bool +isValidUnifiedAddress = rustWrapperIsUA + +-- | Attempt to decode the given bytestring into a Unified Full Viewing Key +decodeUfvk :: BS.ByteString -> Maybe UnifiedFullViewingKey +decodeUfvk str = + case net decodedKey of + 0 -> Nothing + _ -> Just decodedKey + where + decodedKey = (withPureBorshVarBuffer . rustWrapperUfvkDecode) str + +decryptOrchardAction :: + OrchardAction -> UnifiedFullViewingKey -> Maybe OrchardDecodedAction +decryptOrchardAction encAction key = + case a_value decodedAction of + 0 -> Nothing + _ -> Just decodedAction + where + decodedAction = + withPureBorshVarBuffer $ + rustWrapperOrchardNoteDecode (o_key key) encAction diff --git a/src/HaskellZcash/Sapling.hs b/src/HaskellZcash/Sapling.hs new file mode 100644 index 0000000..e77285c --- /dev/null +++ b/src/HaskellZcash/Sapling.hs @@ -0,0 +1,8 @@ +module HaskellZcash.Sapling where + +import C.Zcash (rustWrapperIsShielded) +import qualified Data.ByteString as BS + +-- | Check if given bytesting is a valid encoded shielded address +isValidShieldedAddress :: BS.ByteString -> Bool +isValidShieldedAddress = rustWrapperIsShielded diff --git a/src/HaskellZcash/Types.hs b/src/HaskellZcash/Types.hs new file mode 100644 index 0000000..e3966f6 --- /dev/null +++ b/src/HaskellZcash/Types.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE UndecidableInstances #-} + +module HaskellZcash.Types where + +import qualified Data.ByteString as BS +import Codec.Borsh +import Data.Word +import Data.Int +import Data.Structured +import qualified Generics.SOP as SOP +import qualified GHC.Generics as GHC + +data RawData = RawData { hrp :: BS.ByteString, bytes :: BS.ByteString} + deriving stock (Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawData + +data UnifiedFullViewingKey = + UnifiedFullViewingKey + { net :: Word8 + , o_key :: BS.ByteString + , s_key :: BS.ByteString + , t_key :: 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 UnifiedFullViewingKey + +data OrchardAction = + OrchardAction + { nf :: BS.ByteString + , rk :: BS.ByteString + , cmx :: BS.ByteString + , eph_key :: BS.ByteString + , enc_ciphertext :: BS.ByteString + , out_ciphertext :: BS.ByteString + , cv :: BS.ByteString + , auth :: 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 OrchardAction + +data OrchardDecodedAction = + OrchardDecodedAction + { a_value :: Int64 + , a_recipient :: BS.ByteString + , a_memo :: 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 OrchardDecodedAction + + diff --git a/src/HaskellZcash/Utils.hs b/src/HaskellZcash/Utils.hs new file mode 100644 index 0000000..0bc6766 --- /dev/null +++ b/src/HaskellZcash/Utils.hs @@ -0,0 +1,34 @@ +module HaskellZcash.Utils where + +import C.Zcash + ( rustWrapperBech32Decode + , rustWrapperF4Jumble + , rustWrapperF4UnJumble + ) + +import qualified Data.ByteString as BS +import Foreign.Rust.Marshall.Variable +import HaskellZcash.Types + +-- | Helper function to turn a hex-encoded strings to bytestring +decodeHexText :: String -> BS.ByteString +decodeHexText h = BS.pack $ hexRead h + where + hexRead hexText + | null chunk = [] + | otherwise = + fromIntegral (read ("0x" <> chunk)) : hexRead (drop 2 hexText) + where + chunk = take 2 hexText + +-- | Decode the given bytestring using Bech32 +decodeBech32 :: BS.ByteString -> RawData +decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode + +-- | Apply the F4Jumble transformation to the given bytestring +f4Jumble :: BS.ByteString -> BS.ByteString +f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble + +-- | Apply the inverse F4Jumble transformation to the given bytestring +f4UnJumble :: BS.ByteString -> BS.ByteString +f4UnJumble = withPureBorshVarBuffer . rustWrapperF4UnJumble diff --git a/src/Zcash.hs b/src/Zcash.hs deleted file mode 100644 index 66c7d7f..0000000 --- a/src/Zcash.hs +++ /dev/null @@ -1,69 +0,0 @@ -module Zcash - ( f4Jumble - , f4UnJumble - , isValidUnifiedAddress - , isValidShieldedAddress - , decodeBech32 - , decodeUfvk - ) where - -import C.Zcash - ( RawData - , UnifiedFullViewingKey(..) - , rustWrapperBech32Decode - , rustWrapperF4Jumble - , rustWrapperF4UnJumble - , rustWrapperIsShielded - , rustWrapperIsUA - , rustWrapperUfvkDecode - ) -import qualified Data.ByteString as BS -import Foreign.Rust.Marshall.Fixed -import Foreign.Rust.Marshall.Variable - --- | Apply the F4Jumble transformation to the given bytestring -f4Jumble :: BS.ByteString -> BS.ByteString -f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble - --- | Apply the inverse F4Jumble transformation to the given bytestring -f4UnJumble :: BS.ByteString -> BS.ByteString -f4UnJumble = withPureBorshVarBuffer . rustWrapperF4UnJumble - --- | Check if given bytestring is a valid encoded unified address -isValidUnifiedAddress :: BS.ByteString -> Bool -isValidUnifiedAddress = rustWrapperIsUA - --- | Check if given bytesting is a valid encoded shielded address -isValidShieldedAddress :: BS.ByteString -> Bool -isValidShieldedAddress = rustWrapperIsShielded - --- | Decode the given bytestring using Bech32 -decodeBech32 :: BS.ByteString -> RawData -decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode - --- | Attempt to decode the given bytestring into a Unified Full Viewing Key -decodeUfvk :: BS.ByteString -> Maybe UnifiedFullViewingKey -decodeUfvk str = - case net decodedKey of - 0 -> Nothing - _ -> Just decodedKey - where - decodedKey = (withPureBorshVarBuffer . rustWrapperUfvkDecode) str - -deriveOvk :: BS.ByteString -> BS.ByteString -deriveOvk fvk = undefined -- BS.takeEnd (lovk / 8) $ r k (t ak nk) - --where - --lovk :: Int - --lovk = 256 - --ak :: BS.ByteString - --ak = BS.take 32 fvk - --nk :: BS.ByteString - --nk = BS.take 32 $ BS.takeEnd 64 fvk - --rivk :: BS.ByteString - --rivk = BS.takeEnd 32 fvk - --k :: BS.ByteString - --k = i2lebsp rivk - --r :: BS.ByteString -> BS.ByteString -> BS.ByteString - --r ki ti = blake2b512 "Zcash_ExpandSeed" (BS.append (lebs2osp ki) ti) - --t :: BS.ByteString -> BS.ByteString -> BS.ByteString - --t a n = BS.append (BS.cons 0x82 (i2leosp a)) (i2leosp n) diff --git a/test/Spec.hs b/test/Spec.hs index 835d820..4a01f68 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1,11 +1,18 @@ {-# LANGUAGE OverloadedStrings #-} -import C.Zcash (RawData(..), UnifiedFullViewingKey(..), rustWrapperIsUA) +import C.Zcash (rustWrapperIsUA) import qualified Data.ByteString as BS import qualified Data.Text.Encoding as E import Data.Word +import HaskellZcash.Orchard +import HaskellZcash.Types + ( OrchardAction(..) + , OrchardDecodedAction(..) + , RawData(..) + , UnifiedFullViewingKey(..) + ) +import HaskellZcash.Utils import Test.Hspec -import Zcash main :: IO () main = do @@ -238,3 +245,55 @@ main = do let fakeUvk = "uview1u83changinga987bundchofch4ract3r5x8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" decodeUfvk fakeUvk `shouldBe` Nothing + describe "Decode Orchard tx" $ do + let uvk = + "uview1u833rp8yykd7h4druwht6xp6k8krle45fx8hqsw6vzw63n24atxpcatws82z092kryazuu6d7rayyut8m36wm4wpjy2z8r9hj48fx5pf49gw4sjrq8503qpz3vqj5hg0vg9vsqeasg5qjuyh94uyfm7v76udqcm2m0wfc25hcyqswcn56xxduq3xkgxkr0l73cjy88fdvf90eq5fda9g6x7yv7d0uckpevxg6540wc76xrc4axxvlt03ptaa2a0rektglmdy68656f3uzcdgqqyu0t7wk5cvwghyyvgqc0rp3vgu5ye4nd236ml57rjh083a2755qemf6dk6pw0qrnfm7246s8eg2hhzkzpf9h73chhng7xhmyem2sjh8rs2m9nhfcslsgenm" + let res = decodeUfvk uvk + let a = + OrchardAction + (decodeHexText + "248b16d98dfa33f7ba69a0610a63b606699da76c288840b81d7691ee42764416") + (decodeHexText + "17fcc27cce560733edaf91439a8020c4a029a4e7d5893ce024d5ff4b40bbd0a9") + (decodeHexText + "34796d541864832acca43f083892e98a46c912802d5643672d3f25bea177c61c") + (decodeHexText + "a6d2ca10e3fc7446e372266ef45ee3dc0ba373bd378e6bf3092519a7f272bd8c") + (decodeHexText + "08beafdf59110b5d045e4acc13731ef1a27bfa3a9cabe1d575640c18f18ee6697fbb132d36e982ae3eadf5f37fd35f42c2bb07def14759deab1fbe2f98dc1d5913e4a6ef388b714e2cfd6d89ba2302800e02ab5f45e0e02e3895448518cd8afd2c37bb48a66d8b988a37de9d0838d92876894a311bb9f314ba842e5c18ff7a3d8c7f0ff1a7209e2d661595db8f4a4aa267b9593258914bf63c09286eeda7c9b27ddbb4646208c0d03a8fbdc5d96633335a5a65316f5b25189bdce735bdea7e900de56d3b475ae51b7c35eb7ae79ba104baeb0a5a09d1cd8bb347ab34fb26d62ddbf024f5394710626ec0a665b9c917e65b00256db635145164a0329db7bc5358f435d573b2662adf8a6128801825ec8fb7d8aeef567d35c875ddd784fceb7620355e3f056a648b39b4b2d29a1f5e7b7c4ec5fd2b1874ff1e832b308f8644e83878d90582b9a6fd6c293e19dd3e24dbe1b4c15c96608169843d46551900a8cb787b15f0f1696b736dd4c8ebacf1e3288b14e469bdc004fa8557d6b1395700eaba59334906bb012f876e4cd7acd2157719ebd2e28bd0cd4ab4ac458f8848e1c30e729803dd47102200fe703932a15c3618862ec83b40d3aa0ec2343641bcb9afbf931ab21aa4afdbe7e51deca24283c2ccab0eef6e07aac5a4bf3a775bf7d2ddfc8d8766c3bf8e35df1435cf515d93c3b9549477bd9f53d133f05dd256fbcc0b13a63e3e7f8cce6301ab4f19c114f5af079f8c581537458e861b553218a890ea3e77fb99781c7088cd43c67c155ec611c1148721cab5fd0168e4a5ec390b506ec44145474c") + (decodeHexText + "1e40d33446d9f0f0fad40f8829c1ffe860c11c3439e2c15d37c6c40282f9e933dc01798c800e6c92edb4d20478b92559510eda67f3855f68f5ab22ca31e1885c7fa9d4c9ebfb62ceb5e73267bcad0ba7") + (decodeHexText + "63d0d6e8e92691f700bf8af246dcd4ae1041b13e3969f7a9d819a06e0f9429bc") + (decodeHexText + "fe362be160accf2794841c244e8d80bbeb80b9bc95bb653d297a98d32bddf5a05dd5f874891d55924a83f722f75f576f63796770c31074067694cffb2cce7a2a") + let b = + OrchardAction + (decodeHexText + "8921446787f1bd28fa0e4cc5c945ea7fc71165a25f40cd2a325dae0c4467d12c") + (decodeHexText + "240b08b7861aa78989c68cbedd0038af9b3e3456bdc7ff582d597df571d54da2") + (decodeHexText + "e1bc8ccba69ab9f429bf735417aa005cf439d27500b0d3086dbf1be764b42a36") + (decodeHexText + "c89c58ef8553e7d09ba4090654edd1a8c98763c44d3dfb9dad18286c7ef363ae") + (decodeHexText + "0eee1ca5a3a4959cd4b8bc277e6e633f950680c4acb978c14ad8d944a784f46771c9d666a203ca3ac693943d79dd23f8b76a734a62e81932cbe98e8c851f47a11aaef50249e53151f38f88262a4bae8cf26f5f8b2db1d165aff9b57b64713a677c167608585c038e34ca7bbe468e5f86475ccec0a4a8b9a43b56e342e77a6bd09415787c9f4a1c6f20599f57545f1ac32c3a338d7a5bb2d35456adb880cb65c1455969e10df5d94b8c74b244e7093b1a88cc10697a7c2f4d34b6eae3296e64b820573b4d52e06b4427af5b8f5d6722d3a93fd85da615fceac732976ad2c1be4150b4821c149521f5419ea0746fb132d47f593cfc8a3aab6b2b4480c12fadf21280ccd3142e7188d9e5aef3fcd8c5dc0c066dc975bead023ef7f89a486b615b146110ae68b703a8349a5fc225b26a08b2adaf36fb44c9ad1be59d7ced134eb84e3f0b4aec19b71b2d26e910628a11446b97c5e6bbf97e1befa4e04b5947f83c65161b92f58088d28e57adc2a2873e27008e29772c5803502842045cb355d1ea5a9d27c2683dcb38cb49d26af39625ba99b1342f700387b939e7ff6c129417ca8836fe1e96331e35c8bc0763879e8c17cd4535fbcb27a2785c0a47294e07cb54837bb997df34882ce0bececc6adca365c76fc7533cf0503458937dcfb6058b016dbbd399b9f0cca44cbc881016f4957b5e10daada3393d5b2a4cb15ed983506d4d264f9855ce2ef87a7d4a1fc03293a22c28a53c4455447d546813fa33008e5d2d81848825fae2f437ab9575ba99c230e78f4b23e575e7647beff0e4c4e2b0a1f7320e9460") + (decodeHexText + "d727aeec27bb0f7463c6ed4f5b3f4085cfd3e7218478db0dcebfca875e025320fb64bc4062251823859e963446cadd9924c559e5f981480df5a4f036daf5a8033d4c8241e128902aa1aeaf6adc149730") + (decodeHexText + "98e72813aeb6ea05347798e35379bc881d9cf2b37d38850496ee956fbecd8eab") + (decodeHexText + "cb9926f519041343c957a74f2f67900ed3d250c4dbcd26b9e2addd5247b841a9fde2219d2ef8c9ae8145fecc7792ca6770830c58c95648087f3c8a0a69369402") + let decryptedNote = decryptOrchardAction a =<< res + let decryptedNote2 = decryptOrchardAction b =<< res + describe "First action (sender)" $ do + it "Decryption fails " $ do decryptedNote `shouldBe` Nothing + describe "Second action (recipient)" $ do + it "Decryption succeeds" $ do decryptedNote2 `shouldNotBe` Nothing + it "Tx amount is validated" $ do + (a_value <$> decryptedNote2) `shouldBe` Just 3000 + it "Memo is validated" $ do + let msg = maybe "" a_memo decryptedNote2 + msg `shouldBe` + "Hello World!\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL" diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 8815cba..a5ae1e3 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -27,7 +27,10 @@ source-repository head library exposed-modules: C.Zcash - Zcash + HaskellZcash.Orchard + HaskellZcash.Sapling + HaskellZcash.Types + HaskellZcash.Utils other-modules: Paths_zcash_haskell hs-source-dirs: From 80478c9b6fc41ee20919dfb3fa6a97ad809a90f0 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Jun 2023 09:55:52 -0500 Subject: [PATCH 09/14] Add Sapling VK validation --- Makefile | 2 +- librustzcash-wrapper/Cargo.toml | 2 ++ librustzcash-wrapper/src/lib.rs | 55 ++++++++++++++++++++++++++++++--- src/C/Zcash.chs | 6 ++++ src/HaskellZcash/Sapling.hs | 6 +++- test/Spec.hs | 30 ++++++++++++++++++ 6 files changed, 95 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 2c73f57..77d8055 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ rustlib := librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug all: haskell -haskell: src/Zcash.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc +haskell: src/HaskellZcash/Orchard.hs src/HaskellZcash/Sapling.hs src/HaskellZcash/Types.hs src/HaskellZcash/Utils.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc stack build $(rustlib)/rustzcash_wrapper.h: librustzcash-wrapper/src/lib.rs librustzcash-wrapper/Cargo.toml diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index 491d1d4..5d1340c 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -14,6 +14,8 @@ borsh = "0.10" bech32 = "0.9.1" orchard = "0.4.0" zcash_note_encryption = "0.3.0" +zcash_primitives = "0.12.0" +zcash_client_backend = "0.9.0" [features] capi = [] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 0aaf6ee..93a1245 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -16,12 +16,16 @@ use haskell_ffi::{ FromHaskell, HaskellSize, ToHaskell }; +use zcash_primitives::{sapling::keys::FullViewingKey as SaplingViewingKey, zip32::DiversifiableFullViewingKey}; + use zcash_address::{ Network, unified::{Address, Encoding, Ufvk, Container, Fvk}, ZcashAddress }; +use zcash_client_backend::keys::sapling::ExtendedFullViewingKey; + use orchard::{ Action, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope}, @@ -35,7 +39,10 @@ use zcash_note_encryption; use bech32::{ decode, - u5 + u5, + FromBase32, + ToBase32, + Variant }; pub enum RW {} @@ -124,6 +131,19 @@ impl Hufvk { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hsvk { + vk: Vec, + ovk: Vec +} + +impl ToHaskell for Hsvk { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + 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())) } @@ -175,9 +195,36 @@ pub extern "C" fn rust_wrapper_bech32decode( out_len: &mut usize ) { let input: String = marshall_from_haskell_var(input, input_len, RW); - let (hrp, bytes) = bech32::decode_without_checksum(&input).unwrap(); - let rd = RawData {hrp: hrp.into(), bytes: bytes.iter().map(|&x| bech32::u5::to_u8(x)).collect()}; - marshall_to_haskell_var(&rd, out, out_len, RW); + let (hrp, bytes, variant) = bech32::decode(&input).unwrap(); + let decodedBytes = bech32::decode(&input); + match decodedBytes { + Ok((hrp, bytes, variant)) => { + let rd = RawData {hrp: hrp.into(), bytes: Vec::::from_base32(&bytes).unwrap()}; + marshall_to_haskell_var(&rd, out, out_len, RW); + } + Err(_e) => { + let rd1 = RawData {hrp: "fail".into(), bytes: vec![0]}; + marshall_to_haskell_var(&rd1, out, out_len, RW); + } + } +} + +#[no_mangle] +pub extern "C" fn rust_wrapper_svk_decode( + input: *const u8, + input_len: usize + ) -> bool { + let input: Vec = marshall_from_haskell_var(input, input_len, RW); + let svk = ExtendedFullViewingKey::read(&*input); + match svk { + Ok(k) => { + true + } + Err(e) => { + print!("{}", e); + false + } + } } #[no_mangle] diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 5c1b875..dac9265 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -59,6 +59,12 @@ import HaskellZcash.Types -> `()' #} +{# fun pure unsafe rust_wrapper_svk_decode as rustWrapperSaplingVkDecode + { toBorshVar* `BS.ByteString'& + } + -> `Bool' +#} + {# fun unsafe rust_wrapper_ufvk_decode as rustWrapperUfvkDecode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer UnifiedFullViewingKey'& diff --git a/src/HaskellZcash/Sapling.hs b/src/HaskellZcash/Sapling.hs index e77285c..eede6ac 100644 --- a/src/HaskellZcash/Sapling.hs +++ b/src/HaskellZcash/Sapling.hs @@ -1,8 +1,12 @@ module HaskellZcash.Sapling where -import C.Zcash (rustWrapperIsShielded) +import C.Zcash (rustWrapperIsShielded, rustWrapperSaplingVkDecode) import qualified Data.ByteString as BS -- | Check if given bytesting is a valid encoded shielded address isValidShieldedAddress :: BS.ByteString -> Bool isValidShieldedAddress = rustWrapperIsShielded + +-- | Check if given bytestring is a valid Sapling viewing key +isValidSaplingViewingKey :: BS.ByteString -> Bool +isValidSaplingViewingKey = rustWrapperSaplingVkDecode diff --git a/test/Spec.hs b/test/Spec.hs index 4a01f68..0fefb73 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -5,6 +5,7 @@ import qualified Data.ByteString as BS import qualified Data.Text.Encoding as E import Data.Word import HaskellZcash.Orchard +import HaskellZcash.Sapling (isValidSaplingViewingKey, isValidShieldedAddress) import HaskellZcash.Types ( OrchardAction(..) , OrchardDecodedAction(..) @@ -17,6 +18,12 @@ import Test.Hspec main :: IO () main = do hspec $ do + describe "Bech32" $ do + let s = "bech321qqqsyrhqy2a" + let decodedString = decodeBech32 s + it "hrp matches" $ do hrp decodedString `shouldBe` "bech32" + it "data matches" $ do + bytes decodedString `shouldBe` BS.pack ([0x00, 0x01, 0x02] :: [Word8]) describe "F4Jumble" $ do it "jumble a string" $ do let input = @@ -222,6 +229,29 @@ main = do , 0x22 ] :: [Word8] f4UnJumble (BS.pack out) `shouldBe` BS.pack input + describe "Sapling address" $ do + it "succeeds with valid address" $ do + let sa = + "zs17faa6l5ma55s55exq9rnr32tu0wl8nmqg7xp3e6tz0m5ajn2a6yxlc09t03mqdmvyphavvf3sl8" + isValidShieldedAddress sa `shouldBe` True + it "fails with invalid address" $ do + let sa = + "zs17faa6l5ma55s55exq9rnr32tu0wl8nmqg7xp3e6tz0m5ajn2a6yxlc09t03mqdmvyphavvffake" + isValidShieldedAddress sa `shouldBe` False + describe "Decode Sapling VK" $ do + let vk = + "zxviews1qdjagrrpqqqqpq8es75mlu6rref0qyrstchf8dxzeygtsejwfqu8ckhwl2qj5m8am7lmupxk3vkvdjm8pawjpmesjfapvsqw96pa46c2z0kk7letrxf7mkltwz54fwpxc7kc79mm5kce3rwn5ssl009zwsra2spppwgrx25s9k5hq65f69l4jz2tjmqgy0pl49qmtaj3nudk6wglwe2hpa327hydlchtyq9av6wjd6hu68e04ahwk9a9n2kt0kj3nj99nue65awtu5cwwcpjs" + let sa = + "zs1g2ne5w2r8kvalwzngsk3kfzppx3qcx5560pnfmw9rj5xfd3zfg9dkm7hyxnfyhc423fev5wuue4" + let rawKey = decodeBech32 vk + it "is mainnet" $ do hrp rawKey `shouldBe` "zxviews" + it "is valid Sapling raw key" $ do + isValidSaplingViewingKey (bytes rawKey) `shouldBe` True + describe "Decode invalid Sapling VK" $ do + let vk = + "zxviews1qdjagrrpqqqqpq8es75mlu6rref0qyrstchf8dxzeygtsejwfqu8ckhwl2qj5m8am7lmupxk3vkvdjm8pawjpmesjfapvsqw96pa46c2z0kk7letrxf7mkltwz54fwpxc7kc79mm5kce3rwn5ssl009zwsra2spppwgrx25s9k5hq65f69l4jz2tjmqgy0pl49qmtaj3nudk6wglwe2hpa327hydlchtyq9av6wjd6hu68e04ahwk9a9n2kt0kj3nj99nue65awtu5cwwfake" + let rawKey = decodeBech32 vk + it "is not mainnet" $ do hrp rawKey `shouldBe` "fail" describe "Unified address" $ do it "succeeds with correct UA" $ do let ua = From 19c9d8c4664208353e070138a51f1268788f5158 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Jun 2023 10:53:29 -0500 Subject: [PATCH 10/14] Update source path --- src/{HaskellZcash => ZcashHaskell}/Orchard.hs | 4 ++-- src/{HaskellZcash => ZcashHaskell}/Sapling.hs | 12 ++++++++++-- src/{HaskellZcash => ZcashHaskell}/Types.hs | 2 +- src/{HaskellZcash => ZcashHaskell}/Utils.hs | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) rename src/{HaskellZcash => ZcashHaskell}/Orchard.hs (94%) rename src/{HaskellZcash => ZcashHaskell}/Sapling.hs (50%) rename src/{HaskellZcash => ZcashHaskell}/Types.hs (98%) rename src/{HaskellZcash => ZcashHaskell}/Utils.hs (94%) diff --git a/src/HaskellZcash/Orchard.hs b/src/ZcashHaskell/Orchard.hs similarity index 94% rename from src/HaskellZcash/Orchard.hs rename to src/ZcashHaskell/Orchard.hs index 46032b7..4c759b2 100644 --- a/src/HaskellZcash/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -1,4 +1,4 @@ -module HaskellZcash.Orchard where +module ZcashHaskell.Orchard where import C.Zcash ( rustWrapperIsUA @@ -7,7 +7,7 @@ import C.Zcash ) import qualified Data.ByteString as BS import Foreign.Rust.Marshall.Variable -import HaskellZcash.Types +import ZcashHaskell.Types -- | Check if given bytestring is a valid encoded unified address isValidUnifiedAddress :: BS.ByteString -> Bool diff --git a/src/HaskellZcash/Sapling.hs b/src/ZcashHaskell/Sapling.hs similarity index 50% rename from src/HaskellZcash/Sapling.hs rename to src/ZcashHaskell/Sapling.hs index eede6ac..ed6a81d 100644 --- a/src/HaskellZcash/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -1,6 +1,10 @@ -module HaskellZcash.Sapling where +module ZcashHaskell.Sapling where -import C.Zcash (rustWrapperIsShielded, rustWrapperSaplingVkDecode) +import C.Zcash + ( rustWrapperIsShielded + , rustWrapperSaplingCheck + , rustWrapperSaplingVkDecode + ) import qualified Data.ByteString as BS -- | Check if given bytesting is a valid encoded shielded address @@ -10,3 +14,7 @@ isValidShieldedAddress = rustWrapperIsShielded -- | Check if given bytestring is a valid Sapling viewing key isValidSaplingViewingKey :: BS.ByteString -> Bool isValidSaplingViewingKey = rustWrapperSaplingVkDecode + +-- | Check if the given bytestring for the Sapling viewing key matches the second bytestring for the address +matchSaplingAddress :: BS.ByteString -> BS.ByteString -> Bool +matchSaplingAddress = rustWrapperSaplingCheck diff --git a/src/HaskellZcash/Types.hs b/src/ZcashHaskell/Types.hs similarity index 98% rename from src/HaskellZcash/Types.hs rename to src/ZcashHaskell/Types.hs index e3966f6..adbe573 100644 --- a/src/HaskellZcash/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -5,7 +5,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE UndecidableInstances #-} -module HaskellZcash.Types where +module ZcashHaskell.Types where import qualified Data.ByteString as BS import Codec.Borsh diff --git a/src/HaskellZcash/Utils.hs b/src/ZcashHaskell/Utils.hs similarity index 94% rename from src/HaskellZcash/Utils.hs rename to src/ZcashHaskell/Utils.hs index 0bc6766..8c28cc9 100644 --- a/src/HaskellZcash/Utils.hs +++ b/src/ZcashHaskell/Utils.hs @@ -1,4 +1,4 @@ -module HaskellZcash.Utils where +module ZcashHaskell.Utils where import C.Zcash ( rustWrapperBech32Decode @@ -8,7 +8,7 @@ import C.Zcash import qualified Data.ByteString as BS import Foreign.Rust.Marshall.Variable -import HaskellZcash.Types +import ZcashHaskell.Types -- | Helper function to turn a hex-encoded strings to bytestring decodeHexText :: String -> BS.ByteString From 659361085c6380968babdedf54f681aebfb11c00 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Jun 2023 10:54:02 -0500 Subject: [PATCH 11/14] Add error handling to Bech32 --- librustzcash-wrapper/Cargo.toml | 2 +- librustzcash-wrapper/src/lib.rs | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index 5d1340c..55744d5 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -14,7 +14,7 @@ borsh = "0.10" bech32 = "0.9.1" orchard = "0.4.0" zcash_note_encryption = "0.3.0" -zcash_primitives = "0.12.0" +zcash_primitives = "0.11.0" zcash_client_backend = "0.9.0" [features] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 93a1245..12f68cc 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -16,7 +16,10 @@ use haskell_ffi::{ FromHaskell, HaskellSize, ToHaskell }; -use zcash_primitives::{sapling::keys::FullViewingKey as SaplingViewingKey, zip32::DiversifiableFullViewingKey}; +use zcash_primitives:: sapling::{ + keys::FullViewingKey as SaplingViewingKey, + PaymentAddress +}; use zcash_address::{ Network, @@ -195,7 +198,6 @@ pub extern "C" fn rust_wrapper_bech32decode( out_len: &mut usize ) { let input: String = marshall_from_haskell_var(input, input_len, RW); - let (hrp, bytes, variant) = bech32::decode(&input).unwrap(); let decodedBytes = bech32::decode(&input); match decodedBytes { Ok((hrp, bytes, variant)) => { @@ -227,6 +229,28 @@ pub extern "C" fn rust_wrapper_svk_decode( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_svk_check_address( + key_input: *const u8, + key_input_len: usize, + address_input: *const u8, + address_input_len: usize + ) -> bool { + let key_input: Vec = marshall_from_haskell_var(key_input, key_input_len, RW); + let address_input: Vec = marshall_from_haskell_var(address_input, address_input_len, RW); + let svk = ExtendedFullViewingKey::read(&*key_input); + let sa = PaymentAddress::from_bytes(&to_array(address_input)).unwrap(); + match svk { + Ok(k) => { + let (div_index, def_address) = k.default_address(); + sa == def_address + } + Err(e) => { + false + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_ufvk_decode( input: *const u8, From 0acff0d965123773052bed731e2080aaea123430 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Jun 2023 10:54:20 -0500 Subject: [PATCH 12/14] Add testing to Makefile --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 77d8055..d974301 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,10 @@ rustlib := librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug all: haskell -haskell: src/HaskellZcash/Orchard.hs src/HaskellZcash/Sapling.hs src/HaskellZcash/Types.hs src/HaskellZcash/Utils.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc +test: test/Spec.hs haskell + stack test + +haskell: src/ZcashHaskell/Orchard.hs src/ZcashHaskell/Sapling.hs src/ZcashHaskell/Types.hs src/ZcashHaskell/Utils.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc stack build $(rustlib)/rustzcash_wrapper.h: librustzcash-wrapper/src/lib.rs librustzcash-wrapper/Cargo.toml From 0dd9680158a5c0706717030f332c02e7908a263d Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Jun 2023 10:55:20 -0500 Subject: [PATCH 13/14] Add tests for matching Sapling address and VK --- src/C/Zcash.chs | 9 ++++++++- test/Spec.hs | 22 +++++++++++++++++----- zcash-haskell.cabal | 8 ++++---- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index dac9265..1a85cf9 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -23,7 +23,7 @@ import Foreign.Rust.Serialisation.Raw import Foreign.Rust.Serialisation.Raw.Base16 import qualified Generics.SOP as SOP import qualified GHC.Generics as GHC -import HaskellZcash.Types +import ZcashHaskell.Types {# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble @@ -65,6 +65,13 @@ import HaskellZcash.Types -> `Bool' #} +{# fun pure unsafe rust_wrapper_svk_check_address as rustWrapperSaplingCheck + { toBorshVar* `BS.ByteString'& + , toBorshVar* `BS.ByteString'& + } + -> `Bool' +#} + {# fun unsafe rust_wrapper_ufvk_decode as rustWrapperUfvkDecode { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer UnifiedFullViewingKey'& diff --git a/test/Spec.hs b/test/Spec.hs index 0fefb73..f710256 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -4,16 +4,20 @@ import C.Zcash (rustWrapperIsUA) import qualified Data.ByteString as BS import qualified Data.Text.Encoding as E import Data.Word -import HaskellZcash.Orchard -import HaskellZcash.Sapling (isValidSaplingViewingKey, isValidShieldedAddress) -import HaskellZcash.Types +import Test.Hspec +import ZcashHaskell.Orchard +import ZcashHaskell.Sapling + ( isValidSaplingViewingKey + , isValidShieldedAddress + , matchSaplingAddress + ) +import ZcashHaskell.Types ( OrchardAction(..) , OrchardDecodedAction(..) , RawData(..) , UnifiedFullViewingKey(..) ) -import HaskellZcash.Utils -import Test.Hspec +import ZcashHaskell.Utils main :: IO () main = do @@ -243,10 +247,18 @@ main = do "zxviews1qdjagrrpqqqqpq8es75mlu6rref0qyrstchf8dxzeygtsejwfqu8ckhwl2qj5m8am7lmupxk3vkvdjm8pawjpmesjfapvsqw96pa46c2z0kk7letrxf7mkltwz54fwpxc7kc79mm5kce3rwn5ssl009zwsra2spppwgrx25s9k5hq65f69l4jz2tjmqgy0pl49qmtaj3nudk6wglwe2hpa327hydlchtyq9av6wjd6hu68e04ahwk9a9n2kt0kj3nj99nue65awtu5cwwcpjs" let sa = "zs1g2ne5w2r8kvalwzngsk3kfzppx3qcx5560pnfmw9rj5xfd3zfg9dkm7hyxnfyhc423fev5wuue4" + let sa' = + "zs17faa6l5ma55s55exq9rnr32tu0wl8nmqg7xp3e6tz0m5ajn2a6yxlc09t03mqdmvyphavvf3sl8" let rawKey = decodeBech32 vk + let rawSa = decodeBech32 sa + let rawSa' = decodeBech32 sa' it "is mainnet" $ do hrp rawKey `shouldBe` "zxviews" it "is valid Sapling raw key" $ do isValidSaplingViewingKey (bytes rawKey) `shouldBe` True + it "matches the right Sapling address" $ do + matchSaplingAddress (bytes rawKey) (bytes rawSa) `shouldBe` True + it "doesn't match the wrong Sapling address" $ do + matchSaplingAddress (bytes rawKey) (bytes rawSa') `shouldBe` False describe "Decode invalid Sapling VK" $ do let vk = "zxviews1qdjagrrpqqqqpq8es75mlu6rref0qyrstchf8dxzeygtsejwfqu8ckhwl2qj5m8am7lmupxk3vkvdjm8pawjpmesjfapvsqw96pa46c2z0kk7letrxf7mkltwz54fwpxc7kc79mm5kce3rwn5ssl009zwsra2spppwgrx25s9k5hq65f69l4jz2tjmqgy0pl49qmtaj3nudk6wglwe2hpa327hydlchtyq9av6wjd6hu68e04ahwk9a9n2kt0kj3nj99nue65awtu5cwwfake" diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index a5ae1e3..433f5ae 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -27,10 +27,10 @@ source-repository head library exposed-modules: C.Zcash - HaskellZcash.Orchard - HaskellZcash.Sapling - HaskellZcash.Types - HaskellZcash.Utils + ZcashHaskell.Orchard + ZcashHaskell.Sapling + ZcashHaskell.Types + ZcashHaskell.Utils other-modules: Paths_zcash_haskell hs-source-dirs: From 76d42c46d4209fd1c2a868cb1c5ce473cd2b6fbd Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 14 Jun 2023 19:09:43 -0500 Subject: [PATCH 14/14] Prepare release --- CHANGELOG.md | 17 +- librustzcash-wrapper/Cargo.lock | 876 +++++++++++++++++++++++++++++++- librustzcash-wrapper/src/lib.rs | 70 ++- src/ZcashHaskell/Types.hs | 16 +- test/Spec.hs | 2 +- 5 files changed, 963 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c806da..8a19bc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,23 @@ 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). -## [Unreleased] +## [0.1.0] - 2023-06-14 ### Added +- Function `decodeHexText` +- Function `decodeBech32` - Function `f4Jumble` -- Function `isValidUnifiedAddress` - Function `f4UnJumble` - Function `isValidShieldedAddress` -- Function `decodeBech32` +- Function `isValidSaplingViewingKey` +- Function `matchSaplingAddress` +- Function `isValidUnifiedAddress` +- Function `decodeUfvk` +- Function `decryptOrchardAction` +- Type `RawData` +- Type `ShieldedOutput` +- Type `OrchardAction` +- Type `OrchardDecodedAction` +- Type `UnifiedFullViewingKey` + diff --git a/librustzcash-wrapper/Cargo.lock b/librustzcash-wrapper/Cargo.lock index 97b5326..7f7d85d 100644 --- a/librustzcash-wrapper/Cargo.lock +++ b/librustzcash-wrapper/Cargo.lock @@ -34,6 +34,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + [[package]] name = "arrayref" version = "0.3.7" @@ -52,6 +58,24 @@ 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "base64ct" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" + [[package]] name = "bech32" version = "0.8.1" @@ -73,6 +97,26 @@ dependencies = [ "serde", ] +[[package]] +name = "bip0039" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef0f0152ec5cf17f49a5866afaa3439816207fd4f0a224c0211ffaf5e278426" +dependencies = [ + "hmac", + "pbkdf2", + "rand", + "sha2 0.10.6", + "unicode-normalization", + "zeroize", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitvec" version = "1.0.1" @@ -96,6 +140,17 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blake2s_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -105,6 +160,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bls12_381" version = "0.8.0" @@ -112,6 +176,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" dependencies = [ "ff", + "group", + "pairing", "rand_core", "subtle", ] @@ -123,7 +189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ "borsh-derive 0.9.3", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -133,7 +199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" dependencies = [ "borsh-derive 0.10.3", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -212,15 +278,27 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" dependencies = [ - "sha2", + "sha2 0.9.9", ] +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cbc" version = "0.1.2" @@ -230,6 +308,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + [[package]] name = "cfg-if" version = "1.0.0" @@ -271,6 +355,12 @@ 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" @@ -354,12 +444,60 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "equihash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" +dependencies = [ + "blake2b_simd", + "byteorder", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +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" @@ -369,6 +507,15 @@ dependencies = [ "blake2b_simd", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "ff" version = "0.13.0" @@ -380,6 +527,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fpe" version = "0.6.1" @@ -482,6 +635,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "haskell-ffi" version = "0.1.0" @@ -504,6 +663,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.2.6" @@ -513,12 +678,27 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "incrementalmerkletree" version = "0.3.1" @@ -528,6 +708,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "inout" version = "0.1.3" @@ -537,6 +727,41 @@ 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +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" @@ -562,9 +787,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.141" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "libm" @@ -572,6 +797,18 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + [[package]] name = "maybe-rayon" version = "0.1.1" @@ -582,6 +819,12 @@ dependencies = [ "rayon", ] +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "memoffset" version = "0.8.0" @@ -600,6 +843,28 @@ dependencies = [ "nonempty", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -642,7 +907,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -686,6 +951,26 @@ dependencies = [ "zcash_note_encryption", ] +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group", +] + +[[package]] +name = "password-hash" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "pasta_curves" version = "0.5.1" @@ -701,6 +986,32 @@ dependencies = [ "subtle", ] +[[package]] +name = "pbkdf2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -724,6 +1035,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -733,6 +1054,12 @@ 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.56" @@ -742,6 +1069,60 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + [[package]] name = "quote" version = "1.0.26" @@ -827,6 +1208,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "ref-cast" version = "1.0.16" @@ -847,6 +1237,44 @@ dependencies = [ "syn 2.0.13", ] +[[package]] +name = "regex" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +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", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustzcash-wrapper" version = "0.1.0" @@ -857,15 +1285,47 @@ dependencies = [ "haskell-ffi", "orchard", "zcash_address", + "zcash_client_backend", "zcash_note_encryption", + "zcash_primitives", ] +[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +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" @@ -886,31 +1346,126 @@ dependencies = [ "syn 2.0.13", ] +[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[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" @@ -945,6 +1500,20 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tempfile" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +dependencies = [ + "autocfg", + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + [[package]] name = "thiserror" version = "1.0.40" @@ -965,6 +1534,59 @@ dependencies = [ "syn 2.0.13", ] +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros", + "version_check", + "winapi", +] + +[[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" +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", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml" version = "0.5.11" @@ -974,6 +1596,19 @@ dependencies = [ "serde", ] +[[package]] +name = "tonic-build" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6fdaae4c2c638bb70fe42803a26fbd6fc6ac8c72f5c59f67ecc2a2dcabf4b07" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn 1.0.109", +] + [[package]] name = "tracing" version = "0.1.37" @@ -1030,6 +1665,15 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "universal-hash" version = "0.5.0" @@ -1052,6 +1696,159 @@ 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "wyz" version = "0.5.1" @@ -1073,6 +1870,36 @@ dependencies = [ "zcash_encoding", ] +[[package]] +name = "zcash_client_backend" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55db8d2cb4ca82a71fa66ccd9fa5b211f5ab90c866721311ddd85f8f90d0701" +dependencies = [ + "base64", + "bech32 0.9.1", + "bls12_381", + "bs58", + "crossbeam-channel", + "group", + "memuse", + "nom", + "orchard", + "percent-encoding", + "prost", + "rayon", + "secrecy", + "subtle", + "time", + "tonic-build", + "tracing", + "which", + "zcash_address", + "zcash_encoding", + "zcash_note_encryption", + "zcash_primitives", +] + [[package]] name = "zcash_encoding" version = "0.2.0" @@ -1096,6 +1923,39 @@ dependencies = [ "subtle", ] +[[package]] +name = "zcash_primitives" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914d2195a478d5b63191584dff126f552751115181857b290211ec88e68acc3e" +dependencies = [ + "aes", + "bip0039", + "bitvec", + "blake2b_simd", + "blake2s_simd", + "bls12_381", + "byteorder", + "equihash", + "ff", + "fpe", + "group", + "hex", + "incrementalmerkletree", + "jubjub", + "lazy_static", + "memuse", + "nonempty", + "orchard", + "rand", + "rand_core", + "sha2 0.10.6", + "subtle", + "zcash_address", + "zcash_encoding", + "zcash_note_encryption", +] + [[package]] name = "zeroize" version = "1.6.0" diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 12f68cc..6be1288 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -16,9 +16,24 @@ use haskell_ffi::{ FromHaskell, HaskellSize, ToHaskell }; -use zcash_primitives:: sapling::{ - keys::FullViewingKey as SaplingViewingKey, - PaymentAddress +use zcash_primitives::{ + zip32::Scope as SaplingScope, + transaction::components::sapling::{ + GrothProofBytes, + OutputDescription, + CompactOutputDescription + }, + sapling::{ + value::ValueCommitment as SaplingValueCommitment, + keys::FullViewingKey as SaplingViewingKey, + note_encryption::SaplingDomain, + PaymentAddress, + note::ExtractedNoteCommitment as SaplingExtractedNoteCommitment + }, + consensus::{ + MainNetwork, + BlockHeight + } }; use zcash_address::{ @@ -38,7 +53,7 @@ use orchard::{ value::ValueCommitment }; -use zcash_note_encryption; +use zcash_note_encryption::EphemeralKeyBytes; use bech32::{ decode, @@ -71,6 +86,23 @@ impl ToHaskell for RawData { //} //} +#[derive(BorshSerialize, BorshDeserialize)] +pub struct HshieldedOutput { + cv: Vec, + cmu: Vec, + eph_key: Vec, + enc_txt: Vec, + out_txt: Vec, + proof: Vec +} + +impl FromHaskell for HshieldedOutput { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = HshieldedOutput::deserialize(buf)?; + Ok(x) + } +} + #[derive(BorshSerialize, BorshDeserialize)] pub struct Haction { nf: Vec, @@ -279,6 +311,36 @@ pub extern "C" fn rust_wrapper_ufvk_decode( } } +//#[no_mangle] +//pub extern "C" fn rust_wrapper_sapling_note_decrypt( + //key: *const u8, + //key_len: usize, + //note: *const u8, + //note_len: usize, + //out: *mut u8, + //out_len: &mut usize + //){ + //let evk: Vec = marshall_from_haskell_var(key, key_len, RW); + //let note_input: HshieldedOutput = marshall_from_haskell_var(note,note_len,RW); + //let svk = ExtendedFullViewingKey::read(&*evk); + //match svk { + //Ok(k) => { + //let domain = SaplingDomain::for_height(MainNetwork, BlockHeight::from_u32(2000000)); + //let action: CompactOutputDescription = CompactOutputDescription { + //ephemeral_key: EphemeralKeyBytes(to_array(note_input.eph_key)), + //cmu: SaplingExtractedNoteCommitment::from_bytes(&to_array(note_input.cmu)).unwrap(), + //enc_ciphertext: to_array(note_input.enc_txt) + //}; + //let fvk = k.to_diversifiable_full_viewing_key().to_ivk(SaplingScope::External); + //let result = zcash_note_encryption::try_note_decryption(&domain, &ivk, &action); + //} + //Err(_e) => { + //let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] }; + //marshall_to_haskell_var(&hn0, out, out_len, RW); + //} + //} +//} + #[no_mangle] pub extern "C" fn rust_wrapper_orchard_note_decrypt( key: *const u8, diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index adbe573..b4deba0 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -1,8 +1,6 @@ -{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingVia #-} -{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE UndecidableInstances #-} module ZcashHaskell.Types where @@ -33,6 +31,20 @@ data UnifiedFullViewingKey = deriving anyclass (Data.Structured.Show) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct UnifiedFullViewingKey +data ShieldedOutput = + ShieldedOutput + { s_cv :: BS.ByteString + , s_cmu :: BS.ByteString + , s_ephKey :: BS.ByteString + , s_encCipherText :: BS.ByteString + , s_outCipherText :: BS.ByteString + , s_proof :: 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 ShieldedOutput + data OrchardAction = OrchardAction { nf :: BS.ByteString diff --git a/test/Spec.hs b/test/Spec.hs index f710256..0ad9d47 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -253,7 +253,7 @@ main = do let rawSa = decodeBech32 sa let rawSa' = decodeBech32 sa' it "is mainnet" $ do hrp rawKey `shouldBe` "zxviews" - it "is valid Sapling raw key" $ do + it "is valid Sapling extended full viewing key" $ do isValidSaplingViewingKey (bytes rawKey) `shouldBe` True it "matches the right Sapling address" $ do matchSaplingAddress (bytes rawKey) (bytes rawSa) `shouldBe` True