Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
0d042d639d | |||
a28edcb599 | |||
cfa862ec94 | |||
7d3ae36d2b | |||
4289a9ded6 | |||
d45bd7dcf3 |
16 changed files with 3482 additions and 1024 deletions
151
CHANGELOG.md
151
CHANGELOG.md
|
@ -5,6 +5,157 @@ 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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.8.1.0]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Producing nullifiers from decoding with viewing keys
|
||||||
|
|
||||||
|
## [0.8.0.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `UnifiedIncomingViewingKey` type
|
||||||
|
- `ValidVk` type
|
||||||
|
- Address derivation from full viewing keys
|
||||||
|
- Address derivation from incoming viewing keys
|
||||||
|
- Orchard note decoding with full viewing key
|
||||||
|
- Orchard note decoding with incoming viewing key
|
||||||
|
- Sapling note decoding with full viewing key
|
||||||
|
- Sapling note decoding with incoming viewing key
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Transparent viewing key component generation
|
||||||
|
|
||||||
|
## [0.7.8.1]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Referenced libraries updated to use the new Vergara Tech git server
|
||||||
|
|
||||||
|
## [0.7.8.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- New `UnifiedIncomingViewingKey` type
|
||||||
|
- Functions to derive Orchard full viewing key
|
||||||
|
- Functions to derive Sapling full viewing key
|
||||||
|
- Functions to derive transparent "full viewing key"
|
||||||
|
- Functions to encode Unified Full Viewing Keys
|
||||||
|
- Functions to encode Unified Incoming Viewing Keys
|
||||||
|
|
||||||
|
## [0.7.7.0]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Updated Rust crates
|
||||||
|
|
||||||
|
## [0.7.6.0]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Removed workaround for missing `time` field in Zebra's `getblock` response.
|
||||||
|
|
||||||
|
## [0.7.5.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Sapling commitment node functions
|
||||||
|
- Sapling Merkle path test
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Upgraded Rust dependencies to latest versions:
|
||||||
|
- `zcash_primitives` 0.19.0
|
||||||
|
- `zcash_client_backend` 0.14.0
|
||||||
|
- `orchard` 0.10.0
|
||||||
|
- `sapling-crypto` 0.3.0
|
||||||
|
- `incrementalmerkletree` 0.7.0
|
||||||
|
- `zip32` 0.1.2
|
||||||
|
|
||||||
|
## [0.7.4.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `MerklePath`
|
||||||
|
|
||||||
|
## [0.7.3.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Function to create an Orchard hash from a note commitment
|
||||||
|
- Function to hash Orchard commitments
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Modified frontiers to use `HexString` for ommers
|
||||||
|
- Optimized `createTransaction`
|
||||||
|
|
||||||
|
## [0.7.2.0]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Modified Sapling commitment trees to use Frontier
|
||||||
|
|
||||||
|
## [0.7.1.1]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `ToJSON` instance for `BlockResponse`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Updated libraries:
|
||||||
|
- conduit
|
||||||
|
- data-fix
|
||||||
|
- happy
|
||||||
|
- happy-lib
|
||||||
|
- http-conduit
|
||||||
|
- iproute
|
||||||
|
- mono-traversable
|
||||||
|
- network
|
||||||
|
- secp256k1-haskell
|
||||||
|
- strict
|
||||||
|
- typed-process
|
||||||
|
|
||||||
|
## [0.7.1.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Type `OrchardFrontier`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Modified Orchard commitment trees functions to use Frontier
|
||||||
|
|
||||||
|
## [0.7.0.2]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Modified witness update functions to skip the process if no commitments are present
|
||||||
|
|
||||||
|
## [0.7.0.1]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- New error type `PrivacyPolicyError`
|
||||||
|
|
||||||
|
## [0.7.0.0]
|
||||||
|
|
||||||
|
- Implement `wagyu-zcash-parameters` in Rust bindings
|
||||||
|
|
||||||
|
## [0.6.2.3]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Decoding of unified addresses with no transparent receivers
|
||||||
|
|
||||||
|
## [0.6.2.2]
|
||||||
|
|
||||||
|
- Added JSON instances for `ZcashNet`
|
||||||
|
- Added JSON instances for `Transaction`
|
||||||
|
- Added `ValidAddress`
|
||||||
|
|
||||||
## [0.6.2.1]
|
## [0.6.2.1]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -4,10 +4,10 @@ with-compiler: ghc-9.6.5
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://git.vergara.tech/Vergara_Tech/haskell-foreign-rust.git
|
location: https://code.vergara.tech/Vergara_Tech/haskell-foreign-rust.git
|
||||||
tag: 335e804454cd30da2c526457be37e477f71e4665
|
tag: 335e804454cd30da2c526457be37e477f71e4665
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git
|
location: https://code.vergara.tech/Vergara_Tech/haskell-hexstring.git
|
||||||
tag: 39d8da7b11a80269454c2f134a5c834e0f3cb9a7
|
tag: 39d8da7b11a80269454c2f134a5c834e0f3cb9a7
|
||||||
|
|
|
@ -3,13 +3,13 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
any.Cabal-syntax ==3.10.3.0,
|
any.Cabal-syntax ==3.10.3.0,
|
||||||
any.HUnit ==1.6.2.0,
|
any.HUnit ==1.6.2.0,
|
||||||
any.OneTuple ==0.4.2,
|
any.OneTuple ==0.4.2,
|
||||||
any.QuickCheck ==2.14.3,
|
any.QuickCheck ==2.15.0.1,
|
||||||
QuickCheck -old-random +templatehaskell,
|
QuickCheck -old-random +templatehaskell,
|
||||||
any.StateVar ==1.2.2,
|
any.StateVar ==1.2.2,
|
||||||
any.aeson ==2.2.3.0,
|
any.aeson ==2.2.3.0,
|
||||||
aeson +ordered-keymap,
|
aeson +ordered-keymap,
|
||||||
any.alex ==3.5.1.0,
|
any.alex ==3.5.2.0,
|
||||||
any.ansi-terminal ==1.1.1,
|
any.ansi-terminal ==1.1.2,
|
||||||
ansi-terminal -example,
|
ansi-terminal -example,
|
||||||
any.ansi-terminal-types ==1.1,
|
any.ansi-terminal-types ==1.1,
|
||||||
any.appar ==0.1.8,
|
any.appar ==0.1.8,
|
||||||
|
@ -25,7 +25,7 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
attoparsec -developer,
|
attoparsec -developer,
|
||||||
any.attoparsec-aeson ==2.2.2.0,
|
any.attoparsec-aeson ==2.2.2.0,
|
||||||
any.base ==4.18.2.1,
|
any.base ==4.18.2.1,
|
||||||
any.base-orphans ==0.9.2,
|
any.base-orphans ==0.9.3,
|
||||||
any.base16 ==1.0,
|
any.base16 ==1.0,
|
||||||
any.base16-bytestring ==1.0.2.0,
|
any.base16-bytestring ==1.0.2.0,
|
||||||
any.base58-bytestring ==0.1.0,
|
any.base58-bytestring ==0.1.0,
|
||||||
|
@ -40,7 +40,7 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
any.blaze-builder ==0.4.2.3,
|
any.blaze-builder ==0.4.2.3,
|
||||||
any.borsh ==0.3.0,
|
any.borsh ==0.3.0,
|
||||||
any.byteorder ==1.0.4,
|
any.byteorder ==1.0.4,
|
||||||
any.bytes ==0.17.3,
|
any.bytes ==0.17.4,
|
||||||
any.bytestring ==0.11.5.3,
|
any.bytestring ==0.11.5.3,
|
||||||
any.c2hs ==0.28.8,
|
any.c2hs ==0.28.8,
|
||||||
c2hs +base3 -regression,
|
c2hs +base3 -regression,
|
||||||
|
@ -52,38 +52,35 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
cereal -bytestring-builder,
|
cereal -bytestring-builder,
|
||||||
any.character-ps ==0.1,
|
any.character-ps ==0.1,
|
||||||
any.colour ==2.3.6,
|
any.colour ==2.3.6,
|
||||||
any.comonad ==5.0.8,
|
any.comonad ==5.0.9,
|
||||||
comonad +containers +distributive +indexed-traversable,
|
comonad +containers +distributive +indexed-traversable,
|
||||||
any.conduit ==1.3.5,
|
any.conduit ==1.3.6,
|
||||||
any.conduit-extra ==1.3.6,
|
any.conduit-extra ==1.3.7,
|
||||||
any.containers ==0.6.7,
|
any.containers ==0.6.7,
|
||||||
any.contravariant ==1.5.5,
|
any.contravariant ==1.5.5,
|
||||||
contravariant +semigroups +statevar +tagged,
|
contravariant +semigroups +statevar +tagged,
|
||||||
any.cookie ==0.5.0,
|
any.cookie ==0.5.0,
|
||||||
any.crypton ==1.0.0,
|
any.crypton ==1.0.1,
|
||||||
crypton -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq +support_pclmuldq +support_rdrand -support_sse +use_target_attributes,
|
crypton -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq +support_pclmuldq +support_rdrand -support_sse +use_target_attributes,
|
||||||
any.crypton-connection ==0.4.1,
|
any.crypton-connection ==0.4.3,
|
||||||
any.crypton-x509 ==1.7.7,
|
any.crypton-x509 ==1.7.7,
|
||||||
any.crypton-x509-store ==1.6.9,
|
any.crypton-x509-store ==1.6.9,
|
||||||
any.crypton-x509-system ==1.6.7,
|
any.crypton-x509-system ==1.6.7,
|
||||||
any.crypton-x509-validation ==1.6.12,
|
any.crypton-x509-validation ==1.6.13,
|
||||||
any.cryptonite ==0.30,
|
any.cryptonite ==0.30,
|
||||||
cryptonite -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq -support_pclmuldq +support_rdrand -support_sse +use_target_attributes,
|
cryptonite -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq -support_pclmuldq +support_rdrand -support_sse +use_target_attributes,
|
||||||
any.data-default ==0.7.1.1,
|
any.data-default ==0.8.0.0,
|
||||||
any.data-default-class ==0.1.2.0,
|
any.data-default-class ==0.2.0.0,
|
||||||
any.data-default-instances-containers ==0.0.1,
|
any.data-fix ==0.3.4,
|
||||||
any.data-default-instances-dlist ==0.0.1,
|
|
||||||
any.data-default-instances-old-locale ==0.0.1,
|
|
||||||
any.data-fix ==0.3.3,
|
|
||||||
any.deepseq ==1.4.8.1,
|
any.deepseq ==1.4.8.1,
|
||||||
any.directory ==1.3.8.4,
|
any.directory ==1.3.8.4,
|
||||||
any.distributive ==0.6.2.1,
|
any.distributive ==0.6.2.1,
|
||||||
distributive +semigroups +tagged,
|
distributive +semigroups +tagged,
|
||||||
any.dlist ==1.0,
|
any.dlist ==1.0,
|
||||||
dlist -werror,
|
dlist -werror,
|
||||||
any.entropy ==0.4.1.10,
|
any.entropy ==0.4.1.11,
|
||||||
entropy -donotgetentropy,
|
entropy -donotgetentropy,
|
||||||
any.envy ==2.1.3.0,
|
any.envy ==2.1.4.0,
|
||||||
any.exceptions ==0.10.7,
|
any.exceptions ==0.10.7,
|
||||||
any.filepath ==1.4.300.1,
|
any.filepath ==1.4.300.1,
|
||||||
any.foreign-rust ==0.1.0,
|
any.foreign-rust ==0.1.0,
|
||||||
|
@ -92,55 +89,61 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
any.ghc-bignum ==1.3,
|
any.ghc-bignum ==1.3,
|
||||||
any.ghc-boot-th ==9.6.5,
|
any.ghc-boot-th ==9.6.5,
|
||||||
any.ghc-prim ==0.10.0,
|
any.ghc-prim ==0.10.0,
|
||||||
any.half ==0.3.1,
|
any.half ==0.3.2,
|
||||||
any.happy ==1.20.1.1,
|
any.happy ==2.1.4,
|
||||||
any.hashable ==1.4.7.0,
|
any.happy-lib ==2.1.4,
|
||||||
hashable -arch-native +integer-gmp -random-initial-seed,
|
any.hashable ==1.5.0.0,
|
||||||
any.haskell-lexer ==1.1.1,
|
hashable -arch-native -random-initial-seed,
|
||||||
|
any.haskell-lexer ==1.1.2,
|
||||||
any.haskoin-core ==1.1.0,
|
any.haskoin-core ==1.1.0,
|
||||||
any.hexstring ==0.12.1.0,
|
any.hexstring ==0.12.1.0,
|
||||||
any.hourglass ==0.2.12,
|
any.hourglass ==0.2.12,
|
||||||
any.hsc2hs ==0.68.10,
|
any.hsc2hs ==0.68.10,
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
any.hspec ==2.11.9,
|
any.hspec ==2.11.10,
|
||||||
any.hspec-core ==2.11.9,
|
any.hspec-core ==2.11.10,
|
||||||
any.hspec-discover ==2.11.9,
|
any.hspec-discover ==2.11.10,
|
||||||
any.hspec-expectations ==0.8.4,
|
any.hspec-expectations ==0.8.4,
|
||||||
any.http-client ==0.7.17,
|
any.http-client ==0.7.18,
|
||||||
http-client +network-uri,
|
http-client +network-uri,
|
||||||
any.http-client-tls ==0.3.6.3,
|
any.http-client-tls ==0.3.6.4,
|
||||||
any.http-conduit ==2.3.8.3,
|
any.http-conduit ==2.3.9.1,
|
||||||
http-conduit +aeson,
|
http-conduit +aeson,
|
||||||
any.http-types ==0.12.4,
|
any.http-types ==0.12.4,
|
||||||
any.indexed-traversable ==0.1.4,
|
any.indexed-traversable ==0.1.4,
|
||||||
any.indexed-traversable-instances ==0.1.2,
|
any.indexed-traversable-instances ==0.1.2,
|
||||||
any.integer-conversion ==0.1.1,
|
any.integer-conversion ==0.1.1,
|
||||||
any.integer-gmp ==1.1,
|
any.integer-gmp ==1.1,
|
||||||
any.integer-logarithms ==1.0.3.1,
|
any.integer-logarithms ==1.0.4,
|
||||||
integer-logarithms -check-bounds +integer-gmp,
|
integer-logarithms -check-bounds +integer-gmp,
|
||||||
any.iproute ==1.7.12,
|
any.iproute ==1.7.15,
|
||||||
any.language-c ==0.9.3,
|
any.language-c ==0.10.0,
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
language-c +iecfpextension +usebytestrings,
|
||||||
any.memory ==0.18.0,
|
any.memory ==0.18.0,
|
||||||
memory +support_bytestring +support_deepseq,
|
memory +support_bytestring +support_deepseq,
|
||||||
any.mime-types ==0.1.2.0,
|
any.mime-types ==0.1.2.0,
|
||||||
any.mono-traversable ==1.0.17.0,
|
any.mono-traversable ==1.0.21.0,
|
||||||
any.mtl ==2.3.1,
|
any.mtl ==2.3.1,
|
||||||
any.murmur3 ==1.0.5,
|
any.murmur3 ==1.0.5,
|
||||||
any.network ==3.2.1.0,
|
any.network ==3.2.7.0,
|
||||||
network -devel,
|
network -devel,
|
||||||
any.network-uri ==2.6.4.2,
|
any.network-uri ==2.6.4.2,
|
||||||
any.old-locale ==1.0.0.7,
|
any.old-locale ==1.0.0.7,
|
||||||
any.old-time ==1.1.0.4,
|
any.old-time ==1.1.0.4,
|
||||||
any.os-string ==2.0.6,
|
any.optparse-applicative ==0.18.1.0,
|
||||||
|
optparse-applicative +process,
|
||||||
|
any.os-string ==2.0.7,
|
||||||
any.parsec ==3.1.16.1,
|
any.parsec ==3.1.16.1,
|
||||||
any.pem ==0.2.4,
|
any.pem ==0.2.4,
|
||||||
any.pretty ==1.1.3.6,
|
any.pretty ==1.1.3.6,
|
||||||
|
any.prettyprinter ==1.7.1,
|
||||||
|
prettyprinter -buildreadme +text,
|
||||||
|
any.prettyprinter-ansi-terminal ==1.1.3,
|
||||||
any.primitive ==0.9.0.0,
|
any.primitive ==0.9.0.0,
|
||||||
any.process ==1.6.19.0,
|
any.process ==1.6.19.0,
|
||||||
any.quickcheck-io ==0.2.0,
|
any.quickcheck-io ==0.2.0,
|
||||||
any.quickcheck-transformer ==0.3.1.2,
|
any.quickcheck-transformer ==0.3.1.2,
|
||||||
any.random ==1.2.1.2,
|
any.random ==1.2.1.3,
|
||||||
any.regex-base ==0.94.0.2,
|
any.regex-base ==0.94.0.2,
|
||||||
any.regex-compat ==0.95.2.1,
|
any.regex-compat ==0.95.2.1,
|
||||||
any.regex-posix ==0.96.0.1,
|
any.regex-posix ==0.96.0.1,
|
||||||
|
@ -150,7 +153,7 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
any.safe ==0.3.21,
|
any.safe ==0.3.21,
|
||||||
any.scientific ==0.3.8.0,
|
any.scientific ==0.3.8.0,
|
||||||
scientific -integer-simple,
|
scientific -integer-simple,
|
||||||
any.secp256k1-haskell ==1.2.0,
|
any.secp256k1-haskell ==1.4.2,
|
||||||
any.semialign ==1.3.1,
|
any.semialign ==1.3.1,
|
||||||
semialign +semigroupoids,
|
semialign +semigroupoids,
|
||||||
any.semigroupoids ==6.0.1,
|
any.semigroupoids ==6.0.1,
|
||||||
|
@ -160,42 +163,44 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
any.socks ==0.6.1,
|
any.socks ==0.6.1,
|
||||||
any.sop-core ==0.5.0.2,
|
any.sop-core ==0.5.0.2,
|
||||||
any.split ==0.2.5,
|
any.split ==0.2.5,
|
||||||
any.splitmix ==0.1.0.5,
|
any.splitmix ==0.1.1,
|
||||||
splitmix -optimised-mixer,
|
splitmix -optimised-mixer,
|
||||||
any.stm ==2.5.1.0,
|
any.stm ==2.5.1.0,
|
||||||
any.streaming-commons ==0.2.2.6,
|
any.streaming-commons ==0.2.3.0,
|
||||||
streaming-commons -use-bytestring-builder,
|
streaming-commons -use-bytestring-builder,
|
||||||
any.strict ==0.5,
|
any.strict ==0.5.1,
|
||||||
any.string-conversions ==0.4.0.1,
|
any.string-conversions ==0.4.0.1,
|
||||||
any.tagged ==0.8.8,
|
any.tagged ==0.8.9,
|
||||||
tagged +deepseq +transformers,
|
tagged +deepseq +transformers,
|
||||||
|
any.tasty ==1.5.3,
|
||||||
|
tasty +unix,
|
||||||
any.template-haskell ==2.20.0.0,
|
any.template-haskell ==2.20.0.0,
|
||||||
any.text ==2.0.2,
|
any.text ==2.0.2,
|
||||||
any.text-iso8601 ==0.1.1,
|
any.text-iso8601 ==0.1.1,
|
||||||
any.text-short ==0.1.6,
|
any.text-short ==0.1.6,
|
||||||
text-short -asserts,
|
text-short -asserts,
|
||||||
any.tf-random ==0.5,
|
any.tf-random ==0.5,
|
||||||
any.th-abstraction ==0.7.0.0,
|
any.th-abstraction ==0.7.1.0,
|
||||||
any.th-compat ==0.1.5,
|
any.th-compat ==0.1.6,
|
||||||
any.these ==1.2.1,
|
any.these ==1.2.1,
|
||||||
any.time ==1.12.2,
|
any.time ==1.12.2,
|
||||||
any.time-compat ==1.9.7,
|
any.time-compat ==1.9.8,
|
||||||
any.tls ==2.1.0,
|
any.tls ==2.1.7,
|
||||||
tls -devel,
|
tls -devel,
|
||||||
any.transformers ==0.6.1.0,
|
any.transformers ==0.6.1.0,
|
||||||
any.transformers-compat ==0.7.2,
|
any.transformers-compat ==0.7.2,
|
||||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
||||||
any.typed-process ==0.2.11.1,
|
any.typed-process ==0.2.12.0,
|
||||||
any.unix ==2.8.4.0,
|
any.unix ==2.8.4.0,
|
||||||
any.unix-time ==0.4.15,
|
any.unix-time ==0.4.16,
|
||||||
any.unliftio-core ==0.2.1.0,
|
any.unliftio-core ==0.2.1.0,
|
||||||
any.unordered-containers ==0.2.20,
|
any.unordered-containers ==0.2.20,
|
||||||
unordered-containers -debug,
|
unordered-containers -debug,
|
||||||
any.utf8-string ==1.0.2,
|
any.utf8-string ==1.0.2,
|
||||||
any.uuid-types ==1.0.6,
|
any.uuid-types ==1.0.6,
|
||||||
any.vector ==0.13.1.0,
|
any.vector ==0.13.2.0,
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||||
any.vector-algorithms ==0.9.0.2,
|
any.vector-algorithms ==0.9.0.3,
|
||||||
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
|
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
|
||||||
any.vector-stream ==0.1.0.1,
|
any.vector-stream ==0.1.0.1,
|
||||||
any.void ==0.7.3,
|
any.void ==0.7.3,
|
||||||
|
@ -204,4 +209,4 @@ constraints: any.Cabal ==3.10.3.0,
|
||||||
any.witherable ==0.5,
|
any.witherable ==0.5,
|
||||||
any.zlib ==0.7.1.0,
|
any.zlib ==0.7.1.0,
|
||||||
zlib -bundled-c-zlib +non-blocking-ffi +pkg-config
|
zlib -bundled-c-zlib +non-blocking-ffi +pkg-config
|
||||||
index-state: hackage.haskell.org 2024-07-01T20:28:56Z
|
index-state: hackage.haskell.org 2025-01-31T18:30:19Z
|
||||||
|
|
1123
librustzcash-wrapper/Cargo.lock
generated
1123
librustzcash-wrapper/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -9,20 +9,23 @@ haskell-ffi.git = "https://github.com/BeFunctional/haskell-rust-ffi.git"
|
||||||
haskell-ffi.rev = "2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274"
|
haskell-ffi.rev = "2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274"
|
||||||
f4jumble = "0.1"
|
f4jumble = "0.1"
|
||||||
zcash_address = "0.2.0"
|
zcash_address = "0.2.0"
|
||||||
borsh = "0.10"
|
borsh = "0.9"
|
||||||
bech32 = "0.11"
|
bech32 = "0.11"
|
||||||
orchard = "0.7.1"
|
orchard = "0.10.0"
|
||||||
zcash_note_encryption = "0.4.0"
|
zcash_note_encryption = "0.4.0"
|
||||||
zcash_primitives = { version = "0.14.0", features = ["transparent-inputs"]}
|
zcash_primitives = { version = "0.21.0", features = ["transparent-inputs"]}
|
||||||
zcash_client_backend = "0.11.1"
|
zcash_client_backend = "0.16.0"
|
||||||
sapling-crypto = "0.1.3"
|
sapling-crypto = "0.4"
|
||||||
zip32 = "0.1.0"
|
zip32 = "0.1.2"
|
||||||
proc-macro2 = "1.0.66"
|
proc-macro2 = "1.0.66"
|
||||||
nonempty = "0.7.0"
|
nonempty = "0.7.0"
|
||||||
incrementalmerkletree = "0.5.0"
|
incrementalmerkletree = "0.7.0"
|
||||||
secp256k1 = "0.26.0"
|
secp256k1 = "0.27.0"
|
||||||
jubjub = "0.10.0"
|
jubjub = "0.10.0"
|
||||||
rand_core = { version = "0.6.4", features = ["getrandom"]}
|
rand_core = { version = "0.6.4", features = ["getrandom"]}
|
||||||
|
wagyu-zcash-parameters = "0.2.0"
|
||||||
|
bip0039 = "0.12.0"
|
||||||
|
ahash = "0.7.8"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2024-02-04"
|
channel = "nightly"
|
||||||
components = [ "rustfmt", "rustc-dev"]
|
components = [ "rustfmt", "rustc-dev"]
|
||||||
profile = "minimal"
|
profile = "minimal"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
242
src/C/Zcash.chs
242
src/C/Zcash.chs
|
@ -120,6 +120,13 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_uivk_decode as rustWrapperUivkDecode
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer UnifiedIncomingViewingKey'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_orchard_note_decrypt as rustWrapperOrchardNoteDecode
|
{# fun unsafe rust_wrapper_orchard_note_decrypt as rustWrapperOrchardNoteDecode
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, toBorshVar* `OrchardAction'&
|
, toBorshVar* `OrchardAction'&
|
||||||
|
@ -128,6 +135,23 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_orchard_note_decrypt_fvk as rustWrapperOrchardNoteDecodeFvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `OrchardAction'&
|
||||||
|
, `Bool'
|
||||||
|
, getVarBuffer `Buffer DecodedNote'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_orchard_note_decrypt_ivk as rustWrapperOrchardNoteDecodeIvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `OrchardAction'&
|
||||||
|
, getVarBuffer `Buffer DecodedNote'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_orchard_note_decrypt_sk as rustWrapperOrchardNoteDecodeSK
|
{# fun unsafe rust_wrapper_orchard_note_decrypt_sk as rustWrapperOrchardNoteDecodeSK
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, toBorshVar* `OrchardAction'&
|
, toBorshVar* `OrchardAction'&
|
||||||
|
@ -203,16 +227,33 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_sapling_commitment_tree as rustWrapperReadSaplingCommitmentTree
|
{# fun unsafe rust_wrapper_derive_orchard_receiver_fvk as rustWrapperGenOrchardReceiverFvk
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, `Word32'
|
||||||
|
, `Bool'
|
||||||
|
, getVarBuffer `Buffer (BS.ByteString)'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_derive_orchard_receiver_ivk as rustWrapperGenOrchardReceiverIvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, `Word32'
|
||||||
|
, getVarBuffer `Buffer (BS.ByteString)'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_sapling_commitment_tree as rustWrapperReadSaplingCommitmentTree
|
||||||
|
{ toBorshVar* `SaplingFrontier'&
|
||||||
, toBorshVar* `BS.ByteString'&
|
, toBorshVar* `BS.ByteString'&
|
||||||
, getVarBuffer `Buffer HexString'&
|
, getVarBuffer `Buffer SaplingFrontier'&
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_sapling_witness as rustWrapperReadSaplingWitness
|
{# fun unsafe rust_wrapper_read_sapling_witness as rustWrapperReadSaplingWitness
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `SaplingFrontier'&
|
||||||
, getVarBuffer `Buffer HexString'&
|
, getVarBuffer `Buffer HexString'&
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
|
@ -232,6 +273,13 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_sapling_frontier as rustWrapperReadSaplingFrontier
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer SaplingFrontier'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_decode_sapling_address as rustWrapperDecodeSaplingAddress
|
{# fun unsafe rust_wrapper_decode_sapling_address as rustWrapperDecodeSaplingAddress
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, getVarBuffer `Buffer (BS.ByteString)'&
|
, getVarBuffer `Buffer (BS.ByteString)'&
|
||||||
|
@ -239,16 +287,120 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree
|
{# fun unsafe rust_wrapper_read_sapling_node as rustWrapperReadSaplingNode
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_combine_sapling_nodes as rustWrapperCombineSaplingNodes
|
||||||
|
{ `Int8'
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
, toBorshVar* `BS.ByteString'&
|
, toBorshVar* `BS.ByteString'&
|
||||||
, getVarBuffer `Buffer HexString'&
|
, getVarBuffer `Buffer HexString'&
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_orchard_witness as rustWrapperReadOrchardWitness
|
{# fun unsafe rust_wrapper_get_sapling_root as rustWrapperGetSaplingRootTest
|
||||||
|
{ `Int8'
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_sapling_commitment_tree_parts as rustWrapperReadSaplingTreeParts
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer SaplingRawTree'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_sapling_tree_anchor as rustWrapperReadSaplingTreeAnchor
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_sapling_path_anchor as rustWrapperReadSaplingPathAnchor
|
||||||
|
{ toBorshVar* `MerklePath'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_combine_orchard_nodes as rustWrapperCombineOrchardNodes
|
||||||
|
{ `Int8'
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_tree_anchor as rustWrapperReadOrchardTreeAnchor
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_witness_anchor as rustWrapperReadOrchardWitnessAnchor
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_path_anchor as rustWrapperReadOrchardPathAnchor
|
||||||
|
{ toBorshVar* `MerklePath'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_get_orchard_root as rustWrapperGetOrchardRootTest
|
||||||
|
{ `Int8'
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree
|
||||||
|
{ toBorshVar* `OrchardFrontier'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer OrchardFrontier'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_commitment_tree_parts as rustWrapperReadOrchardTreeParts
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer OrchardRawTree'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_frontier as rustWrapperReadOrchardFrontier
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer OrchardFrontier'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_witness as rustWrapperReadOrchardWitness
|
||||||
|
{ toBorshVar* `OrchardFrontier'&
|
||||||
, getVarBuffer `Buffer HexString'&
|
, getVarBuffer `Buffer HexString'&
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
|
@ -260,6 +412,15 @@ import ZcashHaskell.Types
|
||||||
-> `Word64'
|
-> `Word64'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_orchard_add_node as rustWrapperOrchardAddNodeTest
|
||||||
|
{ `Int8'
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_update_sapling_witness as rustWrapperUpdateSaplingWitness
|
{# fun unsafe rust_wrapper_update_sapling_witness as rustWrapperUpdateSaplingWitness
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, toBorshVar* `[BS.ByteString]'&
|
, toBorshVar* `[BS.ByteString]'&
|
||||||
|
@ -283,8 +444,6 @@ import ZcashHaskell.Types
|
||||||
, toBorshVar* `[SaplingTxSpend]'&
|
, toBorshVar* `[SaplingTxSpend]'&
|
||||||
, toBorshVar* `[OrchardTxSpend]'&
|
, toBorshVar* `[OrchardTxSpend]'&
|
||||||
, toBorshVar* `[OutgoingNote]'&
|
, toBorshVar* `[OutgoingNote]'&
|
||||||
, toBorshVar* `BS.ByteString'&
|
|
||||||
, toBorshVar* `BS.ByteString'&
|
|
||||||
, `Bool'
|
, `Bool'
|
||||||
, `Word64'
|
, `Word64'
|
||||||
, `Bool'
|
, `Bool'
|
||||||
|
@ -292,3 +451,72 @@ import ZcashHaskell.Types
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_create_orchard_fvk as rustWrapperCreateOrchardFvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_create_orchard_ivk as rustWrapperCreateOrchardIvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_create_sapling_fvk as rustWrapperCreateSaplingFvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_create_sapling_ivk as rustWrapperCreateSaplingIvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_receiver_fvk as rustWrapperSaplingReceiverFvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, `Word32'
|
||||||
|
, getVarBuffer `Buffer BS.ByteString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_receiver_ivk as rustWrapperSaplingReceiverIvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, `Word32'
|
||||||
|
, getVarBuffer `Buffer BS.ByteString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_change_receiver_fvk as rustWrapperSaplingChgReceiverFvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer BS.ByteString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_note_decrypt_fvk as rustWrapperSaplingDecodeFvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `ShieldedOutput'&
|
||||||
|
, `Bool'
|
||||||
|
, `Int64'
|
||||||
|
, getVarBuffer `Buffer DecodedNote'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_note_decrypt_ivk as rustWrapperSaplingDecodeIvk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `ShieldedOutput'&
|
||||||
|
, getVarBuffer `Buffer DecodedNote'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
-- Copyright 2022-2024 Vergara Technologies LLC
|
-- Copyright 2022-2024 Vergara Technologies LLC
|
||||||
-- This file is part of Zcash-Haskell.
|
-- This file is part of Zcash-Haskell.
|
||||||
--
|
--
|
||||||
|
@ -15,13 +17,47 @@
|
||||||
module ZcashHaskell.Keys where
|
module ZcashHaskell.Keys where
|
||||||
|
|
||||||
import C.Zcash (rustWrapperGenSeedPhrase, rustWrapperGetSeed)
|
import C.Zcash (rustWrapperGenSeedPhrase, rustWrapperGetSeed)
|
||||||
|
import Crypto.Secp256k1 (PubKey(..), createContext, exportPubKey)
|
||||||
|
import qualified Data.Binary as Bi
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
|
import qualified Data.ByteString.Lazy as BSL
|
||||||
|
import Data.HexString (HexString(..), hexBytes)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.Encoding as E
|
||||||
|
import Data.Word (Word8(..))
|
||||||
import Foreign.Rust.Marshall.Variable
|
import Foreign.Rust.Marshall.Variable
|
||||||
( withBorshVarBuffer
|
( withBorshVarBuffer
|
||||||
, withPureBorshVarBuffer
|
, withPureBorshVarBuffer
|
||||||
)
|
)
|
||||||
import ZcashHaskell.Types (Phrase, Seed(..), ToBytes(..))
|
import Haskoin.Address.Base58 (decodeBase58)
|
||||||
|
import Haskoin.Crypto.Keys.Extended
|
||||||
|
( DerivPath(..)
|
||||||
|
, DerivPathI(..)
|
||||||
|
, XPubKey(..)
|
||||||
|
, derivePath
|
||||||
|
, deriveXPubKey
|
||||||
|
, xPubExport
|
||||||
|
)
|
||||||
|
import Haskoin.Network.Constants (btc)
|
||||||
|
import ZcashHaskell.Orchard (deriveOrchardFvk, deriveOrchardIvk)
|
||||||
|
import ZcashHaskell.Sapling (deriveSaplingFvk, deriveSaplingIvk)
|
||||||
|
import ZcashHaskell.Types
|
||||||
|
( OrchardSpendingKey(..)
|
||||||
|
, Phrase
|
||||||
|
, SaplingSpendingKey(..)
|
||||||
|
, Seed(..)
|
||||||
|
, ToBytes(..)
|
||||||
|
, TransparentSpendingKey(..)
|
||||||
|
, UnifiedFullViewingKey(..)
|
||||||
|
, UnifiedIncomingViewingKey(..)
|
||||||
|
, ValidVk(..)
|
||||||
|
, ZcashNet(..)
|
||||||
|
, uniFullViewingKeyHrp
|
||||||
|
, uniIncomingViewingKeyHrp
|
||||||
|
, uniTestFullViewingKeyHrp
|
||||||
|
, uniTestIncomingViewingKeyHrp
|
||||||
|
)
|
||||||
|
import ZcashHaskell.Utils (encodeBech32m, f4Jumble)
|
||||||
|
|
||||||
-- | Generate a random seed that can be used to generate private keys for shielded addresses and transparent addresses.
|
-- | Generate a random seed that can be used to generate private keys for shielded addresses and transparent addresses.
|
||||||
generateWalletSeedPhrase :: IO Phrase
|
generateWalletSeedPhrase :: IO Phrase
|
||||||
|
@ -36,3 +72,138 @@ getWalletSeed p =
|
||||||
where
|
where
|
||||||
result :: Seed
|
result :: Seed
|
||||||
result = (withPureBorshVarBuffer . rustWrapperGetSeed) p
|
result = (withPureBorshVarBuffer . rustWrapperGetSeed) p
|
||||||
|
|
||||||
|
-- | Derive a transparent root node for unified viewing keys
|
||||||
|
deriveFullTransparentNode :: TransparentSpendingKey -> IO BS.ByteString
|
||||||
|
deriveFullTransparentNode sk = do
|
||||||
|
ioCtx <- createContext
|
||||||
|
let (XPubKey d p i c k) = deriveXPubKey ioCtx sk
|
||||||
|
let tPubKeyBytes = BSL.toStrict (Bi.encode c) <> exportPubKey ioCtx True k
|
||||||
|
if BS.length tPubKeyBytes == 65
|
||||||
|
then return tPubKeyBytes
|
||||||
|
else fail "Unable to get transparent key bytes"
|
||||||
|
|
||||||
|
-- | Derive a transparent incoming root node for unified incoming viewing keys
|
||||||
|
deriveIncomingTransparentNode :: TransparentSpendingKey -> IO BS.ByteString
|
||||||
|
deriveIncomingTransparentNode sk = do
|
||||||
|
ioCtx <- createContext
|
||||||
|
let path = Deriv :/ 0 :: DerivPath
|
||||||
|
let childPrvKey = derivePath ioCtx path sk
|
||||||
|
let (XPubKey d p i c k) = deriveXPubKey ioCtx childPrvKey
|
||||||
|
let tPubKeyBytes = BSL.toStrict (Bi.encode c) <> exportPubKey ioCtx True k
|
||||||
|
if BS.length tPubKeyBytes == 65
|
||||||
|
then return tPubKeyBytes
|
||||||
|
else fail "Unable to get transparent key bytes"
|
||||||
|
|
||||||
|
-- | Derive a Unified Full Viewing Key
|
||||||
|
deriveUfvk ::
|
||||||
|
ZcashNet
|
||||||
|
-> Maybe OrchardSpendingKey
|
||||||
|
-> Maybe SaplingSpendingKey
|
||||||
|
-> Maybe TransparentSpendingKey
|
||||||
|
-> IO ValidVk
|
||||||
|
deriveUfvk net okey skey tkey = do
|
||||||
|
tSec <- maybe (return BS.empty) deriveFullTransparentNode tkey
|
||||||
|
let oSec = deriveOrchardFvk =<< okey
|
||||||
|
let sSec = deriveSaplingFvk =<< skey
|
||||||
|
case oSec of
|
||||||
|
Nothing -> fail "Unable to derive Orchard viewing key"
|
||||||
|
Just oSec' -> do
|
||||||
|
return $
|
||||||
|
FullVk $
|
||||||
|
UnifiedFullViewingKey
|
||||||
|
(case net of
|
||||||
|
MainNet -> 1
|
||||||
|
TestNet -> 2)
|
||||||
|
(hexBytes oSec')
|
||||||
|
(maybe BS.empty hexBytes sSec)
|
||||||
|
tSec
|
||||||
|
|
||||||
|
-- | Derive a Unified Incoming Viewing Key
|
||||||
|
deriveUivk ::
|
||||||
|
ZcashNet
|
||||||
|
-> Maybe OrchardSpendingKey
|
||||||
|
-> Maybe SaplingSpendingKey
|
||||||
|
-> Maybe TransparentSpendingKey
|
||||||
|
-> IO ValidVk
|
||||||
|
deriveUivk net okey skey tkey = do
|
||||||
|
tSec <- maybe (return BS.empty) deriveIncomingTransparentNode tkey
|
||||||
|
let oSec = deriveOrchardIvk =<< okey
|
||||||
|
let sSec = deriveSaplingIvk =<< skey
|
||||||
|
case oSec of
|
||||||
|
Nothing -> fail "Unable to derive Orchard viewing key"
|
||||||
|
Just oSec' -> do
|
||||||
|
return $
|
||||||
|
IncomingVk $
|
||||||
|
UnifiedIncomingViewingKey
|
||||||
|
(case net of
|
||||||
|
MainNet -> 1
|
||||||
|
TestNet -> 2)
|
||||||
|
(hexBytes oSec')
|
||||||
|
(maybe BS.empty hexBytes sSec)
|
||||||
|
tSec
|
||||||
|
|
||||||
|
-- | Encode a Unified Viewing Key per [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
|
encodeVK ::
|
||||||
|
ValidVk -- ^ The viewing key
|
||||||
|
-> T.Text
|
||||||
|
encodeVK vk = encodeBech32m (E.encodeUtf8 hr) b
|
||||||
|
where
|
||||||
|
tReceiver =
|
||||||
|
if tvk /= BS.empty
|
||||||
|
then packReceiver 0x00 $ Just tvk
|
||||||
|
else packReceiver 0x00 Nothing
|
||||||
|
b = f4Jumble $ tReceiver <> sReceiver <> oReceiver <> padding
|
||||||
|
tvk =
|
||||||
|
case vk of
|
||||||
|
FullVk f -> t_key f
|
||||||
|
IncomingVk i -> i_t_key i
|
||||||
|
svk =
|
||||||
|
case vk of
|
||||||
|
FullVk f -> s_key f
|
||||||
|
IncomingVk i -> i_s_key i
|
||||||
|
ovk =
|
||||||
|
case vk of
|
||||||
|
FullVk f -> o_key f
|
||||||
|
IncomingVk i -> i_o_key i
|
||||||
|
znet =
|
||||||
|
case vk of
|
||||||
|
FullVk f ->
|
||||||
|
if net f == 1
|
||||||
|
then MainNet
|
||||||
|
else TestNet
|
||||||
|
IncomingVk i ->
|
||||||
|
if i_net i == 1
|
||||||
|
then MainNet
|
||||||
|
else TestNet
|
||||||
|
hr =
|
||||||
|
case vk of
|
||||||
|
FullVk _ ->
|
||||||
|
case znet of
|
||||||
|
MainNet -> uniFullViewingKeyHrp
|
||||||
|
TestNet -> uniTestFullViewingKeyHrp
|
||||||
|
IncomingVk _ ->
|
||||||
|
case znet of
|
||||||
|
MainNet -> uniIncomingViewingKeyHrp
|
||||||
|
TestNet -> uniTestIncomingViewingKeyHrp
|
||||||
|
sReceiver =
|
||||||
|
packReceiver 0x02 $
|
||||||
|
if svk /= BS.empty
|
||||||
|
then Just svk
|
||||||
|
else Nothing
|
||||||
|
oReceiver =
|
||||||
|
packReceiver 0x03 $
|
||||||
|
if ovk /= BS.empty
|
||||||
|
then Just ovk
|
||||||
|
else Nothing
|
||||||
|
padding = E.encodeUtf8 $ T.justifyLeft 16 '\NUL' hr
|
||||||
|
packReceiver :: Word8 -> Maybe BS.ByteString -> BS.ByteString
|
||||||
|
packReceiver typeCode receiver' =
|
||||||
|
case receiver' of
|
||||||
|
Just receiver ->
|
||||||
|
if BS.length receiver > 1
|
||||||
|
then BS.singleton typeCode `BS.append`
|
||||||
|
(BS.singleton . toEnum . BS.length) receiver `BS.append`
|
||||||
|
receiver
|
||||||
|
else BS.empty
|
||||||
|
Nothing -> BS.empty
|
||||||
|
|
|
@ -18,16 +18,32 @@
|
||||||
module ZcashHaskell.Orchard where
|
module ZcashHaskell.Orchard where
|
||||||
|
|
||||||
import C.Zcash
|
import C.Zcash
|
||||||
( rustWrapperGenOrchardReceiver
|
( rustWrapperCombineOrchardNodes
|
||||||
|
, rustWrapperCreateOrchardFvk
|
||||||
|
, rustWrapperCreateOrchardIvk
|
||||||
|
, rustWrapperGenOrchardReceiver
|
||||||
|
, rustWrapperGenOrchardReceiverFvk
|
||||||
|
, rustWrapperGenOrchardReceiverIvk
|
||||||
, rustWrapperGenOrchardSpendKey
|
, rustWrapperGenOrchardSpendKey
|
||||||
|
, rustWrapperGetOrchardRootTest
|
||||||
|
, rustWrapperOrchardAddNodeTest
|
||||||
, rustWrapperOrchardCheck
|
, rustWrapperOrchardCheck
|
||||||
, rustWrapperOrchardNoteDecode
|
, rustWrapperOrchardNoteDecode
|
||||||
|
, rustWrapperOrchardNoteDecodeFvk
|
||||||
|
, rustWrapperOrchardNoteDecodeIvk
|
||||||
, rustWrapperOrchardNoteDecodeSK
|
, rustWrapperOrchardNoteDecodeSK
|
||||||
, rustWrapperReadOrchardCommitmentTree
|
, rustWrapperReadOrchardCommitmentTree
|
||||||
|
, rustWrapperReadOrchardFrontier
|
||||||
|
, rustWrapperReadOrchardNode
|
||||||
|
, rustWrapperReadOrchardPathAnchor
|
||||||
, rustWrapperReadOrchardPosition
|
, rustWrapperReadOrchardPosition
|
||||||
|
, rustWrapperReadOrchardTreeAnchor
|
||||||
|
, rustWrapperReadOrchardTreeParts
|
||||||
, rustWrapperReadOrchardWitness
|
, rustWrapperReadOrchardWitness
|
||||||
|
, rustWrapperReadOrchardWitnessAnchor
|
||||||
, rustWrapperUADecode
|
, rustWrapperUADecode
|
||||||
, rustWrapperUfvkDecode
|
, rustWrapperUfvkDecode
|
||||||
|
, rustWrapperUivkDecode
|
||||||
, rustWrapperUpdateOrchardWitness
|
, rustWrapperUpdateOrchardWitness
|
||||||
)
|
)
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
|
@ -37,6 +53,11 @@ import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Foreign.Rust.Marshall.Variable
|
import Foreign.Rust.Marshall.Variable
|
||||||
|
import ZcashHaskell.Sapling (decodeSaplingAddress)
|
||||||
|
import ZcashHaskell.Transparent
|
||||||
|
( decodeExchangeAddress
|
||||||
|
, decodeTransparentAddress
|
||||||
|
)
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
import ZcashHaskell.Utils (encodeBech32, encodeBech32m, f4Jumble)
|
import ZcashHaskell.Utils (encodeBech32, encodeBech32m, f4Jumble)
|
||||||
|
|
||||||
|
@ -76,6 +97,35 @@ genOrchardReceiver i scope osk =
|
||||||
(fromIntegral i)
|
(fromIntegral i)
|
||||||
(scope == External)
|
(scope == External)
|
||||||
|
|
||||||
|
-- | Derives an Orchard receiver for the given full viewing key and index
|
||||||
|
genOrchardReceiverFvk ::
|
||||||
|
Int -- ^ The index of the address to be created
|
||||||
|
-> Scope -- ^ `External` for wallet addresses, `Internal` for change addresses
|
||||||
|
-> BS.ByteString -- ^ The full viewing key
|
||||||
|
-> Maybe OrchardReceiver
|
||||||
|
genOrchardReceiverFvk i scope osk =
|
||||||
|
if BS.length k /= 43
|
||||||
|
then Nothing
|
||||||
|
else Just $ OrchardReceiver k
|
||||||
|
where
|
||||||
|
k =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperGenOrchardReceiverFvk osk (fromIntegral i) (scope == External)
|
||||||
|
|
||||||
|
-- | Derives an Orchard receiver for the given incoming viewing key and index
|
||||||
|
genOrchardReceiverIvk ::
|
||||||
|
Int -- ^ The index of the address to be created
|
||||||
|
-> BS.ByteString -- ^ The full viewing key
|
||||||
|
-> Maybe OrchardReceiver
|
||||||
|
genOrchardReceiverIvk i osk =
|
||||||
|
if BS.length k /= 43
|
||||||
|
then Nothing
|
||||||
|
else Just $ OrchardReceiver k
|
||||||
|
where
|
||||||
|
k =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperGenOrchardReceiverIvk osk (fromIntegral i)
|
||||||
|
|
||||||
-- | Checks if given bytestring is a valid encoded unified address
|
-- | Checks if given bytestring is a valid encoded unified address
|
||||||
isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress
|
isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress
|
||||||
isValidUnifiedAddress str =
|
isValidUnifiedAddress str =
|
||||||
|
@ -98,9 +148,9 @@ isValidUnifiedAddress str =
|
||||||
(if BS.length (raw_s x) == 43
|
(if BS.length (raw_s x) == 43
|
||||||
then Just $ SaplingReceiver (raw_s x)
|
then Just $ SaplingReceiver (raw_s x)
|
||||||
else Nothing)
|
else Nothing)
|
||||||
(if not (BS.null (raw_t x))
|
(if BS.length (raw_t x) > 1
|
||||||
then Just $ TransparentReceiver P2PKH (fromRawBytes $ raw_t x)
|
then Just $ TransparentReceiver P2PKH (fromRawBytes $ raw_t x)
|
||||||
else if not (BS.null (raw_to x))
|
else if BS.length (raw_to x) > 1
|
||||||
then Just $ TransparentReceiver P2SH (fromRawBytes $ raw_to x)
|
then Just $ TransparentReceiver P2SH (fromRawBytes $ raw_to x)
|
||||||
else Nothing)
|
else Nothing)
|
||||||
|
|
||||||
|
@ -143,6 +193,15 @@ decodeUfvk str =
|
||||||
where
|
where
|
||||||
decodedKey = (withPureBorshVarBuffer . rustWrapperUfvkDecode) str
|
decodedKey = (withPureBorshVarBuffer . rustWrapperUfvkDecode) str
|
||||||
|
|
||||||
|
-- | Attempts to decode the given bytestring into a Unified Full Viewing Key
|
||||||
|
decodeUivk :: BS.ByteString -> Maybe UnifiedIncomingViewingKey
|
||||||
|
decodeUivk str =
|
||||||
|
case i_net decodedKey of
|
||||||
|
0 -> Nothing
|
||||||
|
_ -> Just decodedKey
|
||||||
|
where
|
||||||
|
decodedKey = (withPureBorshVarBuffer . rustWrapperUivkDecode) str
|
||||||
|
|
||||||
-- | Check if the given UVK matches the UA given
|
-- | Check if the given UVK matches the UA given
|
||||||
matchOrchardAddress :: BS.ByteString -> BS.ByteString -> Bool
|
matchOrchardAddress :: BS.ByteString -> BS.ByteString -> Bool
|
||||||
matchOrchardAddress = rustWrapperOrchardCheck
|
matchOrchardAddress = rustWrapperOrchardCheck
|
||||||
|
@ -159,6 +218,30 @@ decryptOrchardAction key encAction =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperOrchardNoteDecode (o_key key) encAction
|
rustWrapperOrchardNoteDecode (o_key key) encAction
|
||||||
|
|
||||||
|
-- | Attempts to decode the given @OrchardAction@ using the given @UnifiedFullViewingKey@.
|
||||||
|
decryptOrchardActionFvk ::
|
||||||
|
UnifiedFullViewingKey -> Scope -> OrchardAction -> Maybe DecodedNote
|
||||||
|
decryptOrchardActionFvk key scope encAction =
|
||||||
|
case a_value decodedAction of
|
||||||
|
0 -> Nothing
|
||||||
|
_ -> Just decodedAction
|
||||||
|
where
|
||||||
|
decodedAction =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperOrchardNoteDecodeFvk (o_key key) encAction (scope == External)
|
||||||
|
|
||||||
|
-- | Attempts to decode the given @OrchardAction@ using the given @UnifiedFullViewingKey@.
|
||||||
|
decryptOrchardActionIvk ::
|
||||||
|
UnifiedIncomingViewingKey -> OrchardAction -> Maybe DecodedNote
|
||||||
|
decryptOrchardActionIvk key encAction =
|
||||||
|
case a_value decodedAction of
|
||||||
|
0 -> Nothing
|
||||||
|
_ -> Just decodedAction
|
||||||
|
where
|
||||||
|
decodedAction =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperOrchardNoteDecodeIvk (i_o_key key) encAction
|
||||||
|
|
||||||
getSaplingFromUA :: BS.ByteString -> Maybe T.Text
|
getSaplingFromUA :: BS.ByteString -> Maybe T.Text
|
||||||
getSaplingFromUA uadd = do
|
getSaplingFromUA uadd = do
|
||||||
let a = isValidUnifiedAddress uadd
|
let a = isValidUnifiedAddress uadd
|
||||||
|
@ -189,40 +272,159 @@ decryptOrchardActionSK sk scope oa =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperOrchardNoteDecodeSK (getBytes sk) oa (scope == External)
|
rustWrapperOrchardNoteDecodeSK (getBytes sk) oa (scope == External)
|
||||||
|
|
||||||
-- | Update a Orchard commitment tree
|
getOrchardFrontier :: OrchardCommitmentTree -> Maybe OrchardFrontier
|
||||||
updateOrchardCommitmentTree ::
|
getOrchardFrontier tree =
|
||||||
OrchardCommitmentTree -- ^ the base tree
|
if of_pos updatedTree > 1
|
||||||
-> HexString -- ^ the new note commitment
|
then Just updatedTree
|
||||||
-> Maybe OrchardCommitmentTree
|
|
||||||
updateOrchardCommitmentTree tree cmx =
|
|
||||||
if BS.length (hexBytes updatedTree) > 1
|
|
||||||
then Just $ OrchardCommitmentTree updatedTree
|
|
||||||
else Nothing
|
else Nothing
|
||||||
where
|
where
|
||||||
updatedTree =
|
updatedTree =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperReadOrchardCommitmentTree
|
rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree
|
||||||
(hexBytes $ orchTree tree)
|
|
||||||
(hexBytes cmx)
|
getOrchardTreeAnchor :: OrchardCommitmentTree -> HexString
|
||||||
|
getOrchardTreeAnchor tree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadOrchardTreeAnchor $ toBytes $ orchTree tree
|
||||||
|
|
||||||
|
getOrchardWitnessAnchor :: OrchardWitness -> HexString
|
||||||
|
getOrchardWitnessAnchor wit =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadOrchardWitnessAnchor $ toBytes $ orchWit wit
|
||||||
|
|
||||||
|
getOrchardRootTest :: Int -> HexString
|
||||||
|
getOrchardRootTest level =
|
||||||
|
withPureBorshVarBuffer $ rustWrapperGetOrchardRootTest $ fromIntegral level
|
||||||
|
|
||||||
|
addOrchardNodeGetRoot :: Int -> BS.ByteString -> HexString
|
||||||
|
addOrchardNodeGetRoot l n =
|
||||||
|
withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest (fromIntegral l) n
|
||||||
|
|
||||||
|
getOrchardTreeParts :: OrchardCommitmentTree -> Maybe OrchardTree
|
||||||
|
getOrchardTreeParts h =
|
||||||
|
if isBlank (ort_left tree) && isBlank (ort_right tree)
|
||||||
|
then Nothing
|
||||||
|
else Just $
|
||||||
|
OrchardTree
|
||||||
|
(parseHex $ ort_left tree)
|
||||||
|
(parseHex $ ort_right tree)
|
||||||
|
(map parseHex (ort_parents tree))
|
||||||
|
where
|
||||||
|
isBlank h = (BS.length $ hexBytes $ h) == 1
|
||||||
|
parseHex h =
|
||||||
|
if (BS.length $ hexBytes $ h) > 1
|
||||||
|
then Just h
|
||||||
|
else Nothing
|
||||||
|
tree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadOrchardTreeParts $ toBytes $ orchTree h
|
||||||
|
|
||||||
|
getOrchardPathAnchor :: HexString -> MerklePath -> HexString
|
||||||
|
getOrchardPathAnchor hex p =
|
||||||
|
withPureBorshVarBuffer $ rustWrapperReadOrchardPathAnchor p (hexBytes hex)
|
||||||
|
|
||||||
|
-- | Update a Orchard commitment tree
|
||||||
|
updateOrchardCommitmentTree ::
|
||||||
|
OrchardFrontier -- ^ the base tree
|
||||||
|
-> HexString -- ^ the new note commitment
|
||||||
|
-> Maybe OrchardFrontier
|
||||||
|
updateOrchardCommitmentTree tree cmx =
|
||||||
|
if of_pos updatedTree > 1
|
||||||
|
then Just updatedTree
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
updatedTree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadOrchardCommitmentTree tree (hexBytes cmx)
|
||||||
|
|
||||||
-- | Get the Orchard incremental witness from a commitment tree
|
-- | Get the Orchard incremental witness from a commitment tree
|
||||||
getOrchardWitness :: OrchardCommitmentTree -> Maybe OrchardWitness
|
getOrchardWitness :: OrchardFrontier -> Maybe OrchardWitness
|
||||||
getOrchardWitness tree =
|
getOrchardWitness tree =
|
||||||
if BS.length (hexBytes wit) > 1
|
if BS.length (hexBytes wit) > 1
|
||||||
then Just $ OrchardWitness wit
|
then Just $ OrchardWitness wit
|
||||||
else Nothing
|
else Nothing
|
||||||
where
|
where
|
||||||
wit =
|
wit = withPureBorshVarBuffer $ rustWrapperReadOrchardWitness tree
|
||||||
withPureBorshVarBuffer $
|
|
||||||
rustWrapperReadOrchardWitness (hexBytes $ orchTree tree)
|
|
||||||
|
|
||||||
-- | Get the Sapling note position from a witness
|
-- | Get the Sapling note position from a witness
|
||||||
getOrchardNotePosition :: OrchardWitness -> Integer
|
getOrchardNotePosition :: OrchardWitness -> Integer
|
||||||
getOrchardNotePosition =
|
getOrchardNotePosition =
|
||||||
fromIntegral . rustWrapperReadOrchardPosition . hexBytes . orchWit
|
fromIntegral . rustWrapperReadOrchardPosition . hexBytes . orchWit
|
||||||
|
|
||||||
|
-- | Update the witness of an Orchard note
|
||||||
updateOrchardWitness :: OrchardWitness -> [HexString] -> OrchardWitness
|
updateOrchardWitness :: OrchardWitness -> [HexString] -> OrchardWitness
|
||||||
updateOrchardWitness wit cmus =
|
updateOrchardWitness wit cmus =
|
||||||
OrchardWitness $
|
if not (null cmus)
|
||||||
|
then OrchardWitness $
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperUpdateOrchardWitness (toBytes $ orchWit wit) (map toBytes cmus)
|
rustWrapperUpdateOrchardWitness
|
||||||
|
(toBytes $ orchWit wit)
|
||||||
|
(map toBytes cmus)
|
||||||
|
else wit
|
||||||
|
|
||||||
|
getOrchardNodeValue :: BS.ByteString -> Maybe HexString
|
||||||
|
getOrchardNodeValue cmx =
|
||||||
|
if BS.length (hexBytes n) > 1
|
||||||
|
then Just n
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
n = withPureBorshVarBuffer $ rustWrapperReadOrchardNode cmx
|
||||||
|
|
||||||
|
combineOrchardNodes :: Integer -> HexString -> HexString -> Maybe HexString
|
||||||
|
combineOrchardNodes level n1 n2 =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperCombineOrchardNodes
|
||||||
|
(fromIntegral level)
|
||||||
|
(toBytes n1)
|
||||||
|
(toBytes n2)
|
||||||
|
|
||||||
|
-- | Parse a potential Zcash address
|
||||||
|
parseAddress :: BS.ByteString -> Maybe ValidAddress
|
||||||
|
parseAddress t =
|
||||||
|
case isValidUnifiedAddress t of
|
||||||
|
Nothing ->
|
||||||
|
case decodeSaplingAddress t of
|
||||||
|
Nothing ->
|
||||||
|
case decodeTransparentAddress t of
|
||||||
|
Nothing ->
|
||||||
|
case decodeExchangeAddress t of
|
||||||
|
Nothing -> Nothing
|
||||||
|
Just x -> Just $ Exchange x
|
||||||
|
Just t -> Just $ Transparent t
|
||||||
|
Just s -> Just $ Sapling s
|
||||||
|
Just u -> Just $ Unified u
|
||||||
|
|
||||||
|
compareAddress :: ValidAddress -> UnifiedAddress -> Bool
|
||||||
|
compareAddress a u =
|
||||||
|
case a of
|
||||||
|
Unified i -> i == u
|
||||||
|
Sapling s -> s_rec u == Just (sa_receiver s) && ua_net u == net_type s
|
||||||
|
Transparent t -> t_rec u == Just (ta_receiver t) && ua_net u == ta_network t
|
||||||
|
Exchange x -> False
|
||||||
|
|
||||||
|
-- | Derive an Orchard Full Viewing Key
|
||||||
|
deriveOrchardFvk ::
|
||||||
|
OrchardSpendingKey -- ^ The Orchard spending key
|
||||||
|
-> Maybe HexString
|
||||||
|
deriveOrchardFvk sk =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r = withPureBorshVarBuffer $ rustWrapperCreateOrchardFvk $ getBytes sk
|
||||||
|
|
||||||
|
-- | Derive an Orchard Incoming Viewing Key
|
||||||
|
deriveOrchardIvk ::
|
||||||
|
OrchardSpendingKey -- ^ The Orchard spending key
|
||||||
|
-> Maybe HexString
|
||||||
|
deriveOrchardIvk sk =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r = withPureBorshVarBuffer $ rustWrapperCreateOrchardIvk $ getBytes sk
|
||||||
|
|
|
@ -18,16 +18,30 @@
|
||||||
module ZcashHaskell.Sapling where
|
module ZcashHaskell.Sapling where
|
||||||
|
|
||||||
import C.Zcash
|
import C.Zcash
|
||||||
( rustWrapperDecodeSaplingAddress
|
( rustWrapperCombineSaplingNodes
|
||||||
|
, rustWrapperCreateSaplingFvk
|
||||||
|
, rustWrapperCreateSaplingIvk
|
||||||
|
, rustWrapperDecodeSaplingAddress
|
||||||
|
, rustWrapperGetSaplingRootTest
|
||||||
, rustWrapperIsShielded
|
, rustWrapperIsShielded
|
||||||
, rustWrapperReadSaplingCommitmentTree
|
, rustWrapperReadSaplingCommitmentTree
|
||||||
|
, rustWrapperReadSaplingFrontier
|
||||||
|
, rustWrapperReadSaplingNode
|
||||||
|
, rustWrapperReadSaplingPathAnchor
|
||||||
, rustWrapperReadSaplingPosition
|
, rustWrapperReadSaplingPosition
|
||||||
|
, rustWrapperReadSaplingTreeAnchor
|
||||||
|
, rustWrapperReadSaplingTreeParts
|
||||||
, rustWrapperReadSaplingWitness
|
, rustWrapperReadSaplingWitness
|
||||||
, rustWrapperSaplingCheck
|
, rustWrapperSaplingCheck
|
||||||
, rustWrapperSaplingChgPaymentAddress
|
, rustWrapperSaplingChgPaymentAddress
|
||||||
|
, rustWrapperSaplingChgReceiverFvk
|
||||||
, rustWrapperSaplingDecodeEsk
|
, rustWrapperSaplingDecodeEsk
|
||||||
|
, rustWrapperSaplingDecodeFvk
|
||||||
|
, rustWrapperSaplingDecodeIvk
|
||||||
, rustWrapperSaplingNoteDecode
|
, rustWrapperSaplingNoteDecode
|
||||||
, rustWrapperSaplingPaymentAddress
|
, rustWrapperSaplingPaymentAddress
|
||||||
|
, rustWrapperSaplingReceiverFvk
|
||||||
|
, rustWrapperSaplingReceiverIvk
|
||||||
, rustWrapperSaplingSpendingkey
|
, rustWrapperSaplingSpendingkey
|
||||||
, rustWrapperSaplingVkDecode
|
, rustWrapperSaplingVkDecode
|
||||||
, rustWrapperTxParse
|
, rustWrapperTxParse
|
||||||
|
@ -37,6 +51,7 @@ import Data.Aeson
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Char8 as C
|
import qualified Data.ByteString.Char8 as C
|
||||||
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
|
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
|
||||||
|
import Data.Int (Int64, Int8)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Foreign.Rust.Marshall.Variable
|
import Foreign.Rust.Marshall.Variable
|
||||||
|
@ -85,6 +100,27 @@ decodeSaplingOutput key out =
|
||||||
decodedAction =
|
decodedAction =
|
||||||
withPureBorshVarBuffer $ rustWrapperSaplingNoteDecode key out
|
withPureBorshVarBuffer $ rustWrapperSaplingNoteDecode key out
|
||||||
|
|
||||||
|
-- | Attempt to decode the given @ShieldedOutput@ using the given Sapling full viewing key
|
||||||
|
decodeSaplingOutputFvk ::
|
||||||
|
BS.ByteString -> ShieldedOutput -> Scope -> Int64 -> Maybe DecodedNote
|
||||||
|
decodeSaplingOutputFvk fvk so scope pos =
|
||||||
|
case a_value decodedAction of
|
||||||
|
0 -> Nothing
|
||||||
|
_ -> Just decodedAction
|
||||||
|
where
|
||||||
|
decodedAction =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperSaplingDecodeFvk fvk so (scope == External) pos
|
||||||
|
|
||||||
|
-- | Attempt to decode the given @ShieldedOutput@ using the given Sapling incoming viewing key
|
||||||
|
decodeSaplingOutputIvk :: BS.ByteString -> ShieldedOutput -> Maybe DecodedNote
|
||||||
|
decodeSaplingOutputIvk fvk so =
|
||||||
|
case a_value decodedAction of
|
||||||
|
0 -> Nothing
|
||||||
|
_ -> Just decodedAction
|
||||||
|
where
|
||||||
|
decodedAction = withPureBorshVarBuffer $ rustWrapperSaplingDecodeIvk fvk so
|
||||||
|
|
||||||
instance FromJSON RawTxResponse where
|
instance FromJSON RawTxResponse where
|
||||||
parseJSON =
|
parseJSON =
|
||||||
withObject "RawTxResponse" $ \obj -> do
|
withObject "RawTxResponse" $ \obj -> do
|
||||||
|
@ -174,6 +210,28 @@ genSaplingPaymentAddress i extspk =
|
||||||
(getBytes extspk)
|
(getBytes extspk)
|
||||||
(fromIntegral (i * 111)))
|
(fromIntegral (i * 111)))
|
||||||
|
|
||||||
|
-- | Attempts to generate a Sapling receiver using an full viewing key and a diversifier index
|
||||||
|
genSaplingReceiverFvk :: Int -> BS.ByteString -> Maybe SaplingReceiver
|
||||||
|
genSaplingReceiverFvk i fvk =
|
||||||
|
if BS.length res == 43
|
||||||
|
then Just $ SaplingReceiver res
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
res =
|
||||||
|
withPureBorshVarBuffer
|
||||||
|
(rustWrapperSaplingReceiverFvk fvk (fromIntegral (i * 111)))
|
||||||
|
|
||||||
|
-- | Attempts to generate a Sapling receiver using an incoming viewing key and a diversifier index
|
||||||
|
genSaplingReceiverIvk :: Int -> BS.ByteString -> Maybe SaplingReceiver
|
||||||
|
genSaplingReceiverIvk i ivk =
|
||||||
|
if BS.length res == 43
|
||||||
|
then Just $ SaplingReceiver res
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
res =
|
||||||
|
withPureBorshVarBuffer
|
||||||
|
(rustWrapperSaplingReceiverIvk ivk (fromIntegral (i * 111)))
|
||||||
|
|
||||||
-- | Generate an internal Sapling address
|
-- | Generate an internal Sapling address
|
||||||
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingReceiver
|
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingReceiver
|
||||||
genSaplingInternalAddress sk =
|
genSaplingInternalAddress sk =
|
||||||
|
@ -184,32 +242,97 @@ genSaplingInternalAddress sk =
|
||||||
res =
|
res =
|
||||||
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
||||||
|
|
||||||
-- | Update a Sapling commitment tree
|
-- | Generate a change Sapling receiver from Full Viewing Key
|
||||||
updateSaplingCommitmentTree ::
|
genSaplingInternalAddressFvk :: BS.ByteString -> Maybe SaplingReceiver
|
||||||
SaplingCommitmentTree -- ^ the base tree
|
genSaplingInternalAddressFvk fvk =
|
||||||
-> HexString -- ^ the new note commitment
|
if BS.length res == 43
|
||||||
-> Maybe SaplingCommitmentTree
|
then Just $ SaplingReceiver res
|
||||||
updateSaplingCommitmentTree tree cmu =
|
else Nothing
|
||||||
if BS.length (hexBytes updatedTree) > 1
|
where
|
||||||
then Just $ SaplingCommitmentTree updatedTree
|
res = withPureBorshVarBuffer (rustWrapperSaplingChgReceiverFvk fvk)
|
||||||
|
|
||||||
|
getSaplingNodeValue :: BS.ByteString -> Maybe HexString
|
||||||
|
getSaplingNodeValue cmu =
|
||||||
|
if BS.length (hexBytes n) > 1
|
||||||
|
then Just n
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
n = withPureBorshVarBuffer $ rustWrapperReadSaplingNode cmu
|
||||||
|
|
||||||
|
combineSaplingNodes :: Int8 -> HexString -> HexString -> Maybe HexString
|
||||||
|
combineSaplingNodes level n1 n2 =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperCombineSaplingNodes level (toBytes n1) (toBytes n2)
|
||||||
|
|
||||||
|
getSaplingRootTest :: Int8 -> HexString
|
||||||
|
getSaplingRootTest level =
|
||||||
|
withPureBorshVarBuffer $ rustWrapperGetSaplingRootTest level
|
||||||
|
|
||||||
|
getSaplingTreeParts :: SaplingCommitmentTree -> Maybe SaplingTree
|
||||||
|
getSaplingTreeParts h =
|
||||||
|
if isBlank (srt_left tree) && isBlank (srt_right tree)
|
||||||
|
then Nothing
|
||||||
|
else Just $
|
||||||
|
SaplingTree
|
||||||
|
(parseHex $ srt_left tree)
|
||||||
|
(parseHex $ srt_right tree)
|
||||||
|
(map parseHex (srt_parents tree))
|
||||||
|
where
|
||||||
|
isBlank h = (BS.length $ hexBytes $ h) == 1
|
||||||
|
parseHex h =
|
||||||
|
if (BS.length $ hexBytes $ h) > 1
|
||||||
|
then Just h
|
||||||
|
else Nothing
|
||||||
|
tree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadSaplingTreeParts $ toBytes $ sapTree h
|
||||||
|
|
||||||
|
getSaplingTreeAnchor :: SaplingCommitmentTree -> HexString
|
||||||
|
getSaplingTreeAnchor tree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadSaplingTreeAnchor $ toBytes $ sapTree tree
|
||||||
|
|
||||||
|
getSaplingPathAnchor :: HexString -> MerklePath -> HexString
|
||||||
|
getSaplingPathAnchor hex p =
|
||||||
|
withPureBorshVarBuffer $ rustWrapperReadSaplingPathAnchor p (hexBytes hex)
|
||||||
|
|
||||||
|
getSaplingFrontier :: SaplingCommitmentTree -> Maybe SaplingFrontier
|
||||||
|
getSaplingFrontier tree =
|
||||||
|
if sf_pos updatedTree > 1
|
||||||
|
then Just updatedTree
|
||||||
else Nothing
|
else Nothing
|
||||||
where
|
where
|
||||||
updatedTree =
|
updatedTree =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperReadSaplingCommitmentTree
|
rustWrapperReadSaplingFrontier $ toBytes $ sapTree tree
|
||||||
(hexBytes $ sapTree tree)
|
|
||||||
(hexBytes cmu)
|
-- | Update a Sapling commitment tree
|
||||||
|
updateSaplingCommitmentTree ::
|
||||||
|
SaplingFrontier -- ^ the base tree
|
||||||
|
-> HexString -- ^ the new note commitment
|
||||||
|
-> Maybe SaplingFrontier
|
||||||
|
updateSaplingCommitmentTree tree cmu =
|
||||||
|
if sf_pos updatedTree > 1
|
||||||
|
then Just updatedTree
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
updatedTree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadSaplingCommitmentTree tree (hexBytes cmu)
|
||||||
|
|
||||||
-- | Get the Sapling incremental witness from a commitment tree
|
-- | Get the Sapling incremental witness from a commitment tree
|
||||||
getSaplingWitness :: SaplingCommitmentTree -> Maybe SaplingWitness
|
getSaplingWitness :: SaplingFrontier -> Maybe SaplingWitness
|
||||||
getSaplingWitness tree =
|
getSaplingWitness tree =
|
||||||
if BS.length (hexBytes wit) > 1
|
if BS.length (hexBytes wit) > 1
|
||||||
then Just $ SaplingWitness wit
|
then Just $ SaplingWitness wit
|
||||||
else Nothing
|
else Nothing
|
||||||
where
|
where
|
||||||
wit =
|
wit = withPureBorshVarBuffer $ rustWrapperReadSaplingWitness tree
|
||||||
withPureBorshVarBuffer $
|
|
||||||
rustWrapperReadSaplingWitness (hexBytes $ sapTree tree)
|
|
||||||
|
|
||||||
-- | Get the Sapling note position from a witness
|
-- | Get the Sapling note position from a witness
|
||||||
getSaplingNotePosition :: SaplingWitness -> Integer
|
getSaplingNotePosition :: SaplingWitness -> Integer
|
||||||
|
@ -218,9 +341,13 @@ getSaplingNotePosition =
|
||||||
|
|
||||||
updateSaplingWitness :: SaplingWitness -> [HexString] -> SaplingWitness
|
updateSaplingWitness :: SaplingWitness -> [HexString] -> SaplingWitness
|
||||||
updateSaplingWitness wit cmus =
|
updateSaplingWitness wit cmus =
|
||||||
SaplingWitness $
|
if not (null cmus)
|
||||||
|
then SaplingWitness $
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperUpdateSaplingWitness (toBytes $ sapWit wit) (map toBytes cmus)
|
rustWrapperUpdateSaplingWitness
|
||||||
|
(toBytes $ sapWit wit)
|
||||||
|
(map toBytes cmus)
|
||||||
|
else wit
|
||||||
|
|
||||||
-- | Encode a SaplingReceiver into HRF text
|
-- | Encode a SaplingReceiver into HRF text
|
||||||
encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text
|
encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text
|
||||||
|
@ -250,3 +377,25 @@ decodeSaplingAddress sapling_address = do
|
||||||
where
|
where
|
||||||
sa =
|
sa =
|
||||||
withPureBorshVarBuffer $ rustWrapperDecodeSaplingAddress sapling_address
|
withPureBorshVarBuffer $ rustWrapperDecodeSaplingAddress sapling_address
|
||||||
|
|
||||||
|
-- | Derive a Sapling Full Viewing Key
|
||||||
|
deriveSaplingFvk ::
|
||||||
|
SaplingSpendingKey -- ^ The Sapling spending key
|
||||||
|
-> Maybe HexString
|
||||||
|
deriveSaplingFvk sk =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r = withPureBorshVarBuffer $ rustWrapperCreateSaplingFvk $ getBytes sk
|
||||||
|
|
||||||
|
-- | Derive a Sapling Incoming Viewing Key
|
||||||
|
deriveSaplingIvk ::
|
||||||
|
SaplingSpendingKey -- ^ The Sapling spending key
|
||||||
|
-> Maybe HexString
|
||||||
|
deriveSaplingIvk sk =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r = withPureBorshVarBuffer $ rustWrapperCreateSaplingIvk $ getBytes sk
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
-- Copyright 2022-2024 Vergara Technologies LLC
|
-- Copyright 2022-2024 Vergara Technologies LLC
|
||||||
--
|
--
|
||||||
-- This file is part of Zcash-Haskell.
|
-- This file is part of Zcash-Haskell.
|
||||||
|
@ -18,33 +20,36 @@ module ZcashHaskell.Transparent where
|
||||||
import Control.Exception (throwIO)
|
import Control.Exception (throwIO)
|
||||||
import Crypto.Hash
|
import Crypto.Hash
|
||||||
import Crypto.Secp256k1
|
import Crypto.Secp256k1
|
||||||
|
import qualified Data.Binary as Bi
|
||||||
import qualified Data.ByteArray as BA
|
import qualified Data.ByteArray as BA
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
|
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
|
||||||
import qualified Data.ByteString.Char8 as BC
|
import qualified Data.ByteString.Lazy as BSL
|
||||||
|
import qualified Data.ByteString.Short as Short
|
||||||
import Data.Char (chr)
|
import Data.Char (chr)
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Haskoin.Address (Address(..))
|
import Haskoin.Address (Address(..))
|
||||||
import qualified Haskoin.Crypto.Hash as H
|
import qualified Haskoin.Crypto.Hash as H (Hash256(..))
|
||||||
import Haskoin.Crypto.Keys.Extended
|
import Haskoin.Crypto.Keys.Extended
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
|
( AccountId
|
||||||
-- ( AccountId
|
, CoinType(..)
|
||||||
-- , CoinType(..)
|
, ExchangeAddress(..)
|
||||||
-- , Scope(..)
|
, RawData(..)
|
||||||
-- , Seed(..)
|
, Scope(..)
|
||||||
-- , ToBytes(..)
|
, Seed(..)
|
||||||
-- , TransparentAddress(..)
|
, ToBytes(..)
|
||||||
-- , TransparentReceiver(..)
|
, TransparentAddress(..)
|
||||||
-- , TransparentSpendingKey(..)
|
, TransparentReceiver(..)
|
||||||
-- , TransparentType(..)
|
, TransparentSpendingKey(..)
|
||||||
-- , ZcashNet(..)
|
, TransparentType(..)
|
||||||
-- , getTransparentPrefix
|
, ZcashNet(..)
|
||||||
-- , getValue
|
, getTransparentPrefix
|
||||||
-- )
|
, getValue
|
||||||
|
)
|
||||||
import ZcashHaskell.Utils (decodeBech32, encodeBech32m)
|
import ZcashHaskell.Utils (decodeBech32, encodeBech32m)
|
||||||
|
|
||||||
-- | Required for `TransparentReceiver` encoding and decoding
|
-- | Required for `TransparentReceiver` encoding and decoding
|
||||||
|
@ -101,7 +106,76 @@ genTransparentReceiver i scope xprvk = do
|
||||||
ScriptAddress j -> return $ TransparentReceiver P2SH $ fromBinary j
|
ScriptAddress j -> return $ TransparentReceiver P2SH $ fromBinary j
|
||||||
_anyOtherKind -> throwIO $ userError "Unsupported transparent address type"
|
_anyOtherKind -> throwIO $ userError "Unsupported transparent address type"
|
||||||
|
|
||||||
-- | Generate a transparent receiver
|
-- | Generate a transparent receiver from a Full Transparent Node
|
||||||
|
genTransparentReceiverFvk ::
|
||||||
|
Int -- ^ The index of the address to be created
|
||||||
|
-> Scope -- ^ `External` for wallet addresses or `Internal` for change addresses
|
||||||
|
-> BS.ByteString -- ^ The transparent public key
|
||||||
|
-> IO (Maybe TransparentReceiver)
|
||||||
|
genTransparentReceiverFvk i scope pubkey = do
|
||||||
|
ioCtx <- createContext
|
||||||
|
let s =
|
||||||
|
case scope of
|
||||||
|
External -> 0
|
||||||
|
Internal -> 1
|
||||||
|
let path = Deriv :/ s :/ fromIntegral i :: SoftPath
|
||||||
|
let fp' = textToFingerprint "f09f8fbe"
|
||||||
|
case fp' of
|
||||||
|
Left e -> fail "couldn't get fingerprint"
|
||||||
|
Right fp -> do
|
||||||
|
let x = importPubKey ioCtx $ BS.takeEnd 33 pubkey
|
||||||
|
case x of
|
||||||
|
Nothing -> fail "couldn't get pubkey"
|
||||||
|
Just pk -> do
|
||||||
|
let prepKey =
|
||||||
|
XPubKey
|
||||||
|
3
|
||||||
|
fp
|
||||||
|
0
|
||||||
|
(Bi.decode $ BSL.fromStrict $ BS.take 32 pubkey)
|
||||||
|
pk
|
||||||
|
let childPubKey = derivePubPath ioCtx path prepKey
|
||||||
|
let x = xPubAddr ioCtx childPubKey
|
||||||
|
case x of
|
||||||
|
PubKeyAddress k ->
|
||||||
|
return $ Just $ TransparentReceiver P2PKH $ fromBinary k
|
||||||
|
ScriptAddress j ->
|
||||||
|
return $ Just $ TransparentReceiver P2SH $ fromBinary j
|
||||||
|
_anyOtherKind -> return Nothing
|
||||||
|
|
||||||
|
-- | Generate a transparent receiver from a Incoming Transparent Node
|
||||||
|
genTransparentReceiverIvk ::
|
||||||
|
Int -- ^ The index of the address to be created
|
||||||
|
-> BS.ByteString -- ^ The transparent public key
|
||||||
|
-> IO (Maybe TransparentReceiver)
|
||||||
|
genTransparentReceiverIvk i pubkey = do
|
||||||
|
ioCtx <- createContext
|
||||||
|
let path = Deriv :/ fromIntegral i :: SoftPath
|
||||||
|
let fp' = textToFingerprint "f09f8fbe"
|
||||||
|
case fp' of
|
||||||
|
Left e -> fail "couldn't get fingerprint"
|
||||||
|
Right fp -> do
|
||||||
|
let x = importPubKey ioCtx $ BS.takeEnd 33 pubkey
|
||||||
|
case x of
|
||||||
|
Nothing -> fail "couldn't get pubkey"
|
||||||
|
Just pk -> do
|
||||||
|
let prepKey =
|
||||||
|
XPubKey
|
||||||
|
3
|
||||||
|
fp
|
||||||
|
0
|
||||||
|
(Bi.decode $ BSL.fromStrict $ BS.take 32 pubkey)
|
||||||
|
pk
|
||||||
|
let childPubKey = derivePubPath ioCtx path prepKey
|
||||||
|
let x = xPubAddr ioCtx childPubKey
|
||||||
|
case x of
|
||||||
|
PubKeyAddress k ->
|
||||||
|
return $ Just $ TransparentReceiver P2PKH $ fromBinary k
|
||||||
|
ScriptAddress j ->
|
||||||
|
return $ Just $ TransparentReceiver P2SH $ fromBinary j
|
||||||
|
_anyOtherKind -> return Nothing
|
||||||
|
|
||||||
|
-- | Generate a transparent spending key
|
||||||
genTransparentSecretKey ::
|
genTransparentSecretKey ::
|
||||||
Int -- ^ The index of the address to be created
|
Int -- ^ The index of the address to be created
|
||||||
-> Scope -- ^ `External` for wallet addresses or `Internal` for change addresses
|
-> Scope -- ^ `External` for wallet addresses or `Internal` for change addresses
|
||||||
|
@ -172,27 +246,27 @@ decodeTransparentAddress taddress = do
|
||||||
-- | Encode an Exchange Addresss into HRF from TransparentReceiver
|
-- | Encode an Exchange Addresss into HRF from TransparentReceiver
|
||||||
encodeExchangeAddress :: ZcashNet -> TransparentReceiver -> Maybe T.Text
|
encodeExchangeAddress :: ZcashNet -> TransparentReceiver -> Maybe T.Text
|
||||||
encodeExchangeAddress net tr = do
|
encodeExchangeAddress net tr = do
|
||||||
case (tr_type tr) of
|
case tr_type tr of
|
||||||
P2PKH -> do
|
P2PKH -> do
|
||||||
case net of
|
case net of
|
||||||
MainNet -> do
|
MainNet -> do
|
||||||
let vhash = encodeBech32m (BC.pack "tex") (toBytes (tr_bytes tr))
|
let vhash = encodeBech32m "tex" (toBytes (tr_bytes tr))
|
||||||
Just vhash
|
Just vhash
|
||||||
TestNet -> do
|
TestNet -> do
|
||||||
let vhash = encodeBech32m (BC.pack "textest") (toBytes (tr_bytes tr))
|
let vhash = encodeBech32m "textest" (toBytes (tr_bytes tr))
|
||||||
Just vhash
|
Just vhash
|
||||||
_ -> Nothing
|
_any -> Nothing
|
||||||
|
|
||||||
-- | Decode an Exchange Address into a ExchangeAddress
|
-- | Decode an Exchange Address into a ExchangeAddress
|
||||||
decodeExchangeAddress :: T.Text -> Maybe ExchangeAddress
|
decodeExchangeAddress :: BS.ByteString -> Maybe ExchangeAddress
|
||||||
decodeExchangeAddress ex = do
|
decodeExchangeAddress ex = do
|
||||||
if (T.length ex) > 1
|
if BS.length ex > 1
|
||||||
then do
|
then do
|
||||||
let rawd = decodeBech32 (E.encodeUtf8 ex)
|
let rawd = decodeBech32 ex
|
||||||
let tMain = BS.unpack (BC.pack "tex")
|
let tMain = "tex"
|
||||||
let tTest = BS.unpack (BC.pack "textest")
|
let tTest = "textest"
|
||||||
let tFail = BS.unpack (BC.pack "fail")
|
let tFail = "fail"
|
||||||
let hr = BS.unpack (hrp rawd)
|
let hr = hrp rawd
|
||||||
if hr /= tFail
|
if hr /= tFail
|
||||||
then do
|
then do
|
||||||
let transparentReceiver = bytes rawd
|
let transparentReceiver = bytes rawd
|
||||||
|
|
|
@ -38,6 +38,7 @@ import Data.Maybe (fromJust, fromMaybe)
|
||||||
import Data.Structured
|
import Data.Structured
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
|
import qualified Data.Vector as V
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import qualified GHC.Generics as GHC
|
import qualified GHC.Generics as GHC
|
||||||
import qualified Generics.SOP as SOP
|
import qualified Generics.SOP as SOP
|
||||||
|
@ -90,7 +91,7 @@ data ZcashNet
|
||||||
= MainNet
|
= MainNet
|
||||||
| TestNet
|
| TestNet
|
||||||
| RegTestNet
|
| RegTestNet
|
||||||
deriving (Eq, Prelude.Show, Read)
|
deriving (Eq, Prelude.Show, Read, GHC.Generic, ToJSON, FromJSON)
|
||||||
|
|
||||||
type AccountId = Int
|
type AccountId = Int
|
||||||
|
|
||||||
|
@ -133,6 +134,18 @@ data Transaction = Transaction
|
||||||
, tx_orchardBundle :: !(Maybe OrchardBundle)
|
, tx_orchardBundle :: !(Maybe OrchardBundle)
|
||||||
} deriving (Prelude.Show, Eq, Read)
|
} deriving (Prelude.Show, Eq, Read)
|
||||||
|
|
||||||
|
instance ToJSON Transaction where
|
||||||
|
toJSON (Transaction t h c e tb sb ob) =
|
||||||
|
object
|
||||||
|
[ "txid" .= t
|
||||||
|
, "height" .= h
|
||||||
|
, "confirmations" .= c
|
||||||
|
, "expiry" .= e
|
||||||
|
, "transparent" .= tb
|
||||||
|
, "sapling" .= sb
|
||||||
|
, "orchard" .= ob
|
||||||
|
]
|
||||||
|
|
||||||
-- | The transparent portion of a Zcash transaction
|
-- | The transparent portion of a Zcash transaction
|
||||||
data TransparentBundle = TransparentBundle
|
data TransparentBundle = TransparentBundle
|
||||||
{ tb_vin :: ![H.TxIn]
|
{ tb_vin :: ![H.TxIn]
|
||||||
|
@ -140,6 +153,10 @@ data TransparentBundle = TransparentBundle
|
||||||
, tb_coinbase :: !Bool
|
, tb_coinbase :: !Bool
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
instance ToJSON TransparentBundle where
|
||||||
|
toJSON (TransparentBundle vin vout c) =
|
||||||
|
object ["vin" .= vin, "vout" .= vout, "coinbase" .= c]
|
||||||
|
|
||||||
-- | Read a raw transparent bundle into the Haskell type
|
-- | Read a raw transparent bundle into the Haskell type
|
||||||
fromRawTBundle :: RawTBundle -> Maybe TransparentBundle
|
fromRawTBundle :: RawTBundle -> Maybe TransparentBundle
|
||||||
fromRawTBundle rtb =
|
fromRawTBundle rtb =
|
||||||
|
@ -239,7 +256,8 @@ instance FromJSON RpcError where
|
||||||
-- ** `zcashd`
|
-- ** `zcashd`
|
||||||
-- | Type to represent response from the `zcashd` RPC `getblock` method
|
-- | Type to represent response from the `zcashd` RPC `getblock` method
|
||||||
data BlockResponse = BlockResponse
|
data BlockResponse = BlockResponse
|
||||||
{ bl_confirmations :: !Integer -- ^ Block confirmations
|
{ bl_hash :: !HexString
|
||||||
|
, bl_confirmations :: !Integer -- ^ Block confirmations
|
||||||
, bl_height :: !Integer -- ^ Block height
|
, bl_height :: !Integer -- ^ Block height
|
||||||
, bl_time :: !Integer -- ^ Block time
|
, bl_time :: !Integer -- ^ Block time
|
||||||
, bl_txs :: ![HexString] -- ^ List of transaction IDs in the block
|
, bl_txs :: ![HexString] -- ^ List of transaction IDs in the block
|
||||||
|
@ -250,9 +268,20 @@ instance FromJSON BlockResponse where
|
||||||
withObject "BlockResponse" $ \obj -> do
|
withObject "BlockResponse" $ \obj -> do
|
||||||
c <- obj .: "confirmations"
|
c <- obj .: "confirmations"
|
||||||
h <- obj .: "height"
|
h <- obj .: "height"
|
||||||
t <- obj .:? "time"
|
t <- obj .: "time"
|
||||||
txs <- obj .: "tx"
|
txs <- obj .: "tx"
|
||||||
pure $ BlockResponse c h (fromMaybe 0 t) txs
|
hash <- obj .: "hash"
|
||||||
|
pure $ BlockResponse hash c h t txs
|
||||||
|
|
||||||
|
instance ToJSON BlockResponse where
|
||||||
|
toJSON (BlockResponse h c ht t txs) =
|
||||||
|
object
|
||||||
|
[ "hash" .= h
|
||||||
|
, "confirmations" .= c
|
||||||
|
, "height" .= ht
|
||||||
|
, "time" .= t
|
||||||
|
, "tx" .= txs
|
||||||
|
]
|
||||||
|
|
||||||
-- | Type to represent response from the `zcashd` RPC `getrawtransaction`
|
-- | Type to represent response from the `zcashd` RPC `getrawtransaction`
|
||||||
data RawTxResponse = RawTxResponse
|
data RawTxResponse = RawTxResponse
|
||||||
|
@ -324,6 +353,10 @@ data SaplingBundle = SaplingBundle
|
||||||
, sbSig :: !HexString
|
, sbSig :: !HexString
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
|
||||||
|
|
||||||
|
instance ToJSON SaplingBundle where
|
||||||
|
toJSON (SaplingBundle s o v sig) =
|
||||||
|
object ["spends" .= s, "outputs" .= o, "value" .= v, "sig" .= sig]
|
||||||
|
|
||||||
fromRawSBundle :: RawSBundle -> Maybe SaplingBundle
|
fromRawSBundle :: RawSBundle -> Maybe SaplingBundle
|
||||||
fromRawSBundle b =
|
fromRawSBundle b =
|
||||||
if zsb_empty b
|
if zsb_empty b
|
||||||
|
@ -355,6 +388,17 @@ data OrchardBundle = OrchardBundle
|
||||||
, obSig :: !HexString
|
, obSig :: !HexString
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
|
||||||
|
|
||||||
|
instance ToJSON OrchardBundle where
|
||||||
|
toJSON (OrchardBundle a f v an p s) =
|
||||||
|
object
|
||||||
|
[ "actions" .= a
|
||||||
|
, "flags" .= f
|
||||||
|
, "value" .= v
|
||||||
|
, "anchor" .= an
|
||||||
|
, "proof" .= p
|
||||||
|
, "sig" .= s
|
||||||
|
]
|
||||||
|
|
||||||
fromRawOBundle :: RawOBundle -> Maybe OrchardBundle
|
fromRawOBundle :: RawOBundle -> Maybe OrchardBundle
|
||||||
fromRawOBundle b =
|
fromRawOBundle b =
|
||||||
if zob_empty b
|
if zob_empty b
|
||||||
|
@ -377,6 +421,10 @@ data OrchardFlags = OrchardFlags
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardFlags
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardFlags
|
||||||
|
|
||||||
|
instance ToJSON OrchardFlags where
|
||||||
|
toJSON (OrchardFlags s o) =
|
||||||
|
Data.Aeson.Array $ V.fromList [Data.Aeson.Bool s, Data.Aeson.Bool o]
|
||||||
|
|
||||||
-- | Type for the response from the `zebrad` RPC method `getinfo`
|
-- | Type for the response from the `zebrad` RPC method `getinfo`
|
||||||
data ZebraGetInfo = ZebraGetInfo
|
data ZebraGetInfo = ZebraGetInfo
|
||||||
{ zgi_build :: !T.Text
|
{ zgi_build :: !T.Text
|
||||||
|
@ -501,6 +549,17 @@ data ShieldedSpend = ShieldedSpend
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedSpend
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedSpend
|
||||||
|
|
||||||
|
instance ToJSON ShieldedSpend where
|
||||||
|
toJSON (ShieldedSpend cv a n rk p au) =
|
||||||
|
object
|
||||||
|
[ "cv" .= cv
|
||||||
|
, "anchor" .= a
|
||||||
|
, "nullifier" .= n
|
||||||
|
, "rk" .= rk
|
||||||
|
, "proof" .= p
|
||||||
|
, "spendAuthSig" .= au
|
||||||
|
]
|
||||||
|
|
||||||
instance FromJSON ShieldedSpend where
|
instance FromJSON ShieldedSpend where
|
||||||
parseJSON =
|
parseJSON =
|
||||||
withObject "ShieldedSpend" $ \obj -> do
|
withObject "ShieldedSpend" $ \obj -> do
|
||||||
|
@ -525,6 +584,17 @@ data ShieldedOutput = ShieldedOutput
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedOutput
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedOutput
|
||||||
|
|
||||||
|
instance ToJSON ShieldedOutput where
|
||||||
|
toJSON (ShieldedOutput c cm e enc o p) =
|
||||||
|
object
|
||||||
|
[ "cv" .= c
|
||||||
|
, "cmu" .= cm
|
||||||
|
, "ephemeralKey" .= e
|
||||||
|
, "encCiphertext" .= enc
|
||||||
|
, "outCiphertext" .= o
|
||||||
|
, "proof" .= p
|
||||||
|
]
|
||||||
|
|
||||||
instance FromJSON ShieldedOutput where
|
instance FromJSON ShieldedOutput where
|
||||||
parseJSON =
|
parseJSON =
|
||||||
withObject "ShieldedOutput" $ \obj -> do
|
withObject "ShieldedOutput" $ \obj -> do
|
||||||
|
@ -541,6 +611,30 @@ newtype SaplingCommitmentTree = SaplingCommitmentTree
|
||||||
{ sapTree :: HexString
|
{ sapTree :: HexString
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
data SaplingRawTree = SaplingRawTree
|
||||||
|
{ srt_left :: !HexString
|
||||||
|
, srt_right :: !HexString
|
||||||
|
, srt_parents :: ![HexString]
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct SaplingRawTree
|
||||||
|
|
||||||
|
data SaplingTree = SaplingTree
|
||||||
|
{ st_left :: !(Maybe HexString)
|
||||||
|
, st_right :: !(Maybe HexString)
|
||||||
|
, st_parents :: ![Maybe HexString]
|
||||||
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
data SaplingFrontier = SaplingFrontier
|
||||||
|
{ sf_pos :: !Int64
|
||||||
|
, sf_leaf :: !HexString
|
||||||
|
, sf_ommers :: ![HexString]
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct SaplingFrontier
|
||||||
|
|
||||||
-- | Type for a Sapling incremental witness
|
-- | Type for a Sapling incremental witness
|
||||||
newtype SaplingWitness = SaplingWitness
|
newtype SaplingWitness = SaplingWitness
|
||||||
{ sapWit :: HexString
|
{ sapWit :: HexString
|
||||||
|
@ -583,17 +677,43 @@ data RawUA = RawUA
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawUA
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawUA
|
||||||
|
|
||||||
|
-- | A type to handle user-entered addresses
|
||||||
|
data ValidAddress
|
||||||
|
= Unified !UnifiedAddress
|
||||||
|
| Sapling !SaplingAddress
|
||||||
|
| Transparent !TransparentAddress
|
||||||
|
| Exchange !ExchangeAddress
|
||||||
|
deriving stock (Eq, Prelude.Show)
|
||||||
|
|
||||||
|
-- | A type to handle user-entered viewing keys
|
||||||
|
data ValidVk
|
||||||
|
= FullVk !UnifiedFullViewingKey
|
||||||
|
| IncomingVk !UnifiedIncomingViewingKey
|
||||||
|
deriving stock (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
-- | Type to represent a Unified Full Viewing Key
|
-- | Type to represent a Unified Full Viewing Key
|
||||||
data UnifiedFullViewingKey = UnifiedFullViewingKey
|
data UnifiedFullViewingKey = UnifiedFullViewingKey
|
||||||
{ net :: !Word8 -- ^ Number representing the network the key belongs to. @1@ for @mainnet@, @2@ for @testnet@ and @3@ for @regtestnet@.
|
{ net :: !Word8 -- ^ Number representing the network the key belongs to. @1@ for @mainnet@, @2@ for @testnet@ and @3@ for @regtestnet@.
|
||||||
, o_key :: !BS.ByteString -- ^ Raw bytes of the Orchard Full Viewing Key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
, o_key :: !BS.ByteString -- ^ Raw bytes of the Orchard Full Viewing Key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
, s_key :: !BS.ByteString -- ^ Raw bytes of the Sapling Full Viewing Key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
, s_key :: !BS.ByteString -- ^ Raw bytes of the Sapling Full Viewing Key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
, t_key :: !BS.ByteString -- ^ Raw bytes of the P2PKH chain code and public key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
, t_key :: !BS.ByteString -- ^ Raw bytes of the P2PKH chain code and public key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
|
||||||
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct UnifiedFullViewingKey
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct UnifiedFullViewingKey
|
||||||
|
|
||||||
|
-- | Type to represent a Unified Incoming Viewing Key
|
||||||
|
data UnifiedIncomingViewingKey = UnifiedIncomingViewingKey
|
||||||
|
{ i_net :: !Word8 -- ^ Number representing the network the key belongs to. @1@ for @mainnet@, @2@ for @testnet@ and @3@ for @regtestnet@.
|
||||||
|
, i_o_key :: !BS.ByteString -- ^ Raw bytes of the Orchard Incoming Viewing Key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
|
, i_s_key :: !BS.ByteString -- ^ Raw bytes of the Sapling Incoming Viewing Key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
|
, i_t_key :: !BS.ByteString -- ^ Raw bytes of the P2PKH chain code and public key as specified in [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct
|
||||||
|
UnifiedIncomingViewingKey
|
||||||
|
|
||||||
-- | Type to represent an Orchard Action as provided by the @getrawtransaction@ RPC method of @zcashd@, and defined in the [Zcash Protocol](https://zips.z.cash/protocol/protocol.pdf)
|
-- | Type to represent an Orchard Action as provided by the @getrawtransaction@ RPC method of @zcashd@, and defined in the [Zcash Protocol](https://zips.z.cash/protocol/protocol.pdf)
|
||||||
data OrchardAction = OrchardAction
|
data OrchardAction = OrchardAction
|
||||||
{ nf :: !HexString -- ^ The nullifier of the input note
|
{ nf :: !HexString -- ^ The nullifier of the input note
|
||||||
|
@ -609,6 +729,19 @@ data OrchardAction = OrchardAction
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardAction
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardAction
|
||||||
|
|
||||||
|
instance ToJSON OrchardAction where
|
||||||
|
toJSON (OrchardAction n r c e en o cv a) =
|
||||||
|
object
|
||||||
|
[ "nullifier" .= n
|
||||||
|
, "rk" .= r
|
||||||
|
, "cmx" .= c
|
||||||
|
, "ephemeralKey" .= e
|
||||||
|
, "encCiphertext" .= en
|
||||||
|
, "outCiphertext" .= o
|
||||||
|
, "cv" .= cv
|
||||||
|
, "spendAuthSig" .= a
|
||||||
|
]
|
||||||
|
|
||||||
instance FromJSON OrchardAction where
|
instance FromJSON OrchardAction where
|
||||||
parseJSON =
|
parseJSON =
|
||||||
withObject "OrchardAction" $ \obj -> do
|
withObject "OrchardAction" $ \obj -> do
|
||||||
|
@ -622,11 +755,43 @@ instance FromJSON OrchardAction where
|
||||||
a <- obj .: "spendAuthSig"
|
a <- obj .: "spendAuthSig"
|
||||||
pure $ OrchardAction n r c ephKey encText outText cval a
|
pure $ OrchardAction n r c ephKey encText outText cval a
|
||||||
|
|
||||||
|
data MerklePath = MerklePath
|
||||||
|
{ mp_position :: !Int32
|
||||||
|
, mp_path :: ![HexString]
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct MerklePath
|
||||||
|
|
||||||
-- | Type for a Orchard note commitment tree
|
-- | Type for a Orchard note commitment tree
|
||||||
newtype OrchardCommitmentTree = OrchardCommitmentTree
|
newtype OrchardCommitmentTree = OrchardCommitmentTree
|
||||||
{ orchTree :: HexString
|
{ orchTree :: HexString
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
data OrchardRawTree = OrchardRawTree
|
||||||
|
{ ort_left :: !HexString
|
||||||
|
, ort_right :: !HexString
|
||||||
|
, ort_parents :: ![HexString]
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardRawTree
|
||||||
|
|
||||||
|
data OrchardTree = OrchardTree
|
||||||
|
{ ot_left :: !(Maybe HexString)
|
||||||
|
, ot_right :: !(Maybe HexString)
|
||||||
|
, ot_parents :: ![Maybe HexString]
|
||||||
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
data OrchardFrontier = OrchardFrontier
|
||||||
|
{ of_pos :: !Int64
|
||||||
|
, of_leaf :: !HexString
|
||||||
|
, of_ommers :: ![HexString]
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardFrontier
|
||||||
|
|
||||||
-- | Type for a Sapling incremental witness
|
-- | Type for a Sapling incremental witness
|
||||||
newtype OrchardWitness = OrchardWitness
|
newtype OrchardWitness = OrchardWitness
|
||||||
{ orchWit :: HexString
|
{ orchWit :: HexString
|
||||||
|
@ -665,7 +830,7 @@ data TransparentTxSpend = TransparentTxSpend
|
||||||
data SaplingTxSpend = SaplingTxSpend
|
data SaplingTxSpend = SaplingTxSpend
|
||||||
{ ss_sk :: !BS.ByteString
|
{ ss_sk :: !BS.ByteString
|
||||||
, ss_note :: !DecodedNote
|
, ss_note :: !DecodedNote
|
||||||
, ss_iw :: !BS.ByteString
|
, ss_iw :: !MerklePath
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
@ -674,7 +839,7 @@ data SaplingTxSpend = SaplingTxSpend
|
||||||
data OrchardTxSpend = OrchardTxSpend
|
data OrchardTxSpend = OrchardTxSpend
|
||||||
{ ss_sk :: !BS.ByteString
|
{ ss_sk :: !BS.ByteString
|
||||||
, ss_note :: !DecodedNote
|
, ss_note :: !DecodedNote
|
||||||
, ss_iw :: !BS.ByteString
|
, ss_iw :: !MerklePath
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
@ -712,6 +877,7 @@ data TxError
|
||||||
| OrchardRecipient
|
| OrchardRecipient
|
||||||
| SaplingBuilderNotAvailable
|
| SaplingBuilderNotAvailable
|
||||||
| OrchardBuilderNotAvailable
|
| OrchardBuilderNotAvailable
|
||||||
|
| PrivacyPolicyError !T.Text
|
||||||
| ZHError
|
| ZHError
|
||||||
deriving (Eq, Prelude.Show, Read)
|
deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
|
|
@ -123,53 +123,41 @@ readZebraTransaction hex =
|
||||||
rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex
|
rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex
|
||||||
|
|
||||||
createTransaction ::
|
createTransaction ::
|
||||||
Maybe SaplingCommitmentTree -- ^ to obtain the Sapling anchor
|
HexString -- ^ to obtain the Sapling anchor
|
||||||
-> Maybe OrchardCommitmentTree -- ^ to obtain the Orchard anchor
|
-> HexString -- ^ to obtain the Orchard anchor
|
||||||
-> [TransparentTxSpend] -- ^ the list of transparent notes to spend
|
-> [TransparentTxSpend] -- ^ the list of transparent notes to spend
|
||||||
-> [SaplingTxSpend] -- ^ the list of Sapling notes to spend
|
-> [SaplingTxSpend] -- ^ the list of Sapling notes to spend
|
||||||
-> [OrchardTxSpend] -- ^ the list of Orchard notes to spend
|
-> [OrchardTxSpend] -- ^ the list of Orchard notes to spend
|
||||||
-> [OutgoingNote] -- ^ the list of outgoing notes, including change notes
|
-> [OutgoingNote] -- ^ the list of outgoing notes, including change notes
|
||||||
-> SaplingSpendParams -- ^ the Sapling circuit spending parameters
|
|
||||||
-> SaplingOutputParams -- ^ the Sapling circuit output parameters
|
|
||||||
-> ZcashNet -- ^ the network to be used
|
-> ZcashNet -- ^ the network to be used
|
||||||
-> Int -- ^ target block height
|
-> Int -- ^ target block height
|
||||||
-> Bool -- ^ True to build, False to estimate fee
|
-> Bool -- ^ True to build, False to estimate fee
|
||||||
-> Either TxError HexString
|
-> IO (Either TxError HexString)
|
||||||
createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing sParams oParams znet bh build =
|
createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do
|
||||||
processResult $! txResult
|
txResult <-
|
||||||
where
|
withBorshBufferOfInitSize 102400 $
|
||||||
processResult :: HexString -> Either TxError HexString
|
|
||||||
processResult input =
|
|
||||||
if BS.length (hexBytes input) > 1
|
|
||||||
then Right input
|
|
||||||
else case head (BS.unpack $ hexBytes input) of
|
|
||||||
0 -> Left InsufficientFunds
|
|
||||||
1 -> Left ChangeRequired
|
|
||||||
2 -> Left Fee
|
|
||||||
3 -> Left Balance
|
|
||||||
4 -> Left TransparentBuild
|
|
||||||
5 -> Left SaplingBuild
|
|
||||||
6 -> Left OrchardBuild
|
|
||||||
7 -> Left OrchardSpend
|
|
||||||
8 -> Left OrchardRecipient
|
|
||||||
9 -> Left SaplingBuilderNotAvailable
|
|
||||||
10 -> Left OrchardBuilderNotAvailable
|
|
||||||
_ -> Left ZHError
|
|
||||||
txResult =
|
|
||||||
withPureBorshVarBuffer $
|
|
||||||
rustWrapperCreateTx
|
rustWrapperCreateTx
|
||||||
(case sapAnchor of
|
(hexBytes sapAnchor)
|
||||||
Nothing -> "0"
|
(hexBytes orchAnchor)
|
||||||
Just sA -> toBytes $ sapTree sA)
|
|
||||||
(case orchAnchor of
|
|
||||||
Nothing -> "0"
|
|
||||||
Just oA -> toBytes $ orchTree oA)
|
|
||||||
tSpend
|
tSpend
|
||||||
sSpend
|
sSpend
|
||||||
oSpend
|
oSpend
|
||||||
outgoing
|
outgoing
|
||||||
(sapSParams sParams)
|
|
||||||
(sapOParams oParams)
|
|
||||||
(znet == MainNet)
|
(znet == MainNet)
|
||||||
(fromIntegral bh)
|
(fromIntegral bh)
|
||||||
build
|
build
|
||||||
|
if BS.length (hexBytes txResult) > 1
|
||||||
|
then pure $ Right txResult
|
||||||
|
else case head (BS.unpack $ hexBytes txResult) of
|
||||||
|
0 -> pure $ Left InsufficientFunds
|
||||||
|
1 -> pure $ Left ChangeRequired
|
||||||
|
2 -> pure $ Left Fee
|
||||||
|
3 -> pure $ Left Balance
|
||||||
|
4 -> pure $ Left TransparentBuild
|
||||||
|
5 -> pure $ Left SaplingBuild
|
||||||
|
6 -> pure $ Left OrchardBuild
|
||||||
|
7 -> pure $ Left OrchardSpend
|
||||||
|
8 -> pure $ Left OrchardRecipient
|
||||||
|
9 -> pure $ Left SaplingBuilderNotAvailable
|
||||||
|
10 -> pure $ Left OrchardBuilderNotAvailable
|
||||||
|
_ -> pure $ Left ZHError
|
||||||
|
|
360
test/Spec.hs
360
test/Spec.hs
|
@ -22,10 +22,13 @@
|
||||||
import C.Zcash (rustWrapperUADecode)
|
import C.Zcash (rustWrapperUADecode)
|
||||||
import Control.Exception (throwIO)
|
import Control.Exception (throwIO)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
import Crypto.Secp256k1
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
|
import qualified Data.Binary as Bi
|
||||||
import Data.Bool (Bool(True))
|
import Data.Bool (Bool(True))
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Char8 as C
|
import qualified Data.ByteString.Char8 as C
|
||||||
|
import qualified Data.ByteString.Lazy as BSL
|
||||||
import Data.Either (isRight)
|
import Data.Either (isRight)
|
||||||
import Data.Foldable (sequenceA_)
|
import Data.Foldable (sequenceA_)
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
|
@ -40,20 +43,34 @@ import GHC.Float.RealFracMethods (properFractionDoubleInteger)
|
||||||
import Haskoin.Crypto.Hash (ripemd160)
|
import Haskoin.Crypto.Hash (ripemd160)
|
||||||
import Haskoin.Crypto.Keys.Extended
|
import Haskoin.Crypto.Keys.Extended
|
||||||
import Haskoin.Transaction.Common
|
import Haskoin.Transaction.Common
|
||||||
|
import Network.HTTP.Simple (Response(..))
|
||||||
import Test.HUnit
|
import Test.HUnit
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
import Test.Hspec.QuickCheck
|
import Test.Hspec.QuickCheck
|
||||||
import Test.QuickCheck
|
import Test.QuickCheck
|
||||||
import ZcashHaskell.Keys (generateWalletSeedPhrase, getWalletSeed)
|
import ZcashHaskell.Keys
|
||||||
|
( deriveFullTransparentNode
|
||||||
|
, deriveUfvk
|
||||||
|
, deriveUivk
|
||||||
|
, generateWalletSeedPhrase
|
||||||
|
, getWalletSeed
|
||||||
|
)
|
||||||
import ZcashHaskell.Orchard
|
import ZcashHaskell.Orchard
|
||||||
import ZcashHaskell.Sapling
|
import ZcashHaskell.Sapling
|
||||||
( decodeSaplingAddress
|
( decodeSaplingAddress
|
||||||
, decodeSaplingOutput
|
, decodeSaplingOutput
|
||||||
, decodeSaplingOutputEsk
|
, decodeSaplingOutputEsk
|
||||||
|
, decodeSaplingOutputFvk
|
||||||
|
, decodeSaplingOutputIvk
|
||||||
|
, deriveSaplingFvk
|
||||||
, encodeSaplingAddress
|
, encodeSaplingAddress
|
||||||
, genSaplingInternalAddress
|
, genSaplingInternalAddress
|
||||||
|
, genSaplingInternalAddressFvk
|
||||||
, genSaplingPaymentAddress
|
, genSaplingPaymentAddress
|
||||||
|
, genSaplingReceiverFvk
|
||||||
|
, genSaplingReceiverIvk
|
||||||
, genSaplingSpendingKey
|
, genSaplingSpendingKey
|
||||||
|
, getSaplingFrontier
|
||||||
, getSaplingNotePosition
|
, getSaplingNotePosition
|
||||||
, getSaplingWitness
|
, getSaplingWitness
|
||||||
, getShieldedOutputs
|
, getShieldedOutputs
|
||||||
|
@ -72,6 +89,7 @@ import ZcashHaskell.Types
|
||||||
, OrchardAction(..)
|
, OrchardAction(..)
|
||||||
, OrchardBundle(..)
|
, OrchardBundle(..)
|
||||||
, OrchardCommitmentTree(..)
|
, OrchardCommitmentTree(..)
|
||||||
|
, OrchardFrontier(..)
|
||||||
, OrchardSpendingKey(..)
|
, OrchardSpendingKey(..)
|
||||||
, OrchardWitness(..)
|
, OrchardWitness(..)
|
||||||
, Phrase(..)
|
, Phrase(..)
|
||||||
|
@ -82,9 +100,12 @@ import ZcashHaskell.Types
|
||||||
, RawTxOut(..)
|
, RawTxOut(..)
|
||||||
, RawTxResponse(..)
|
, RawTxResponse(..)
|
||||||
, RawZebraTx(..)
|
, RawZebraTx(..)
|
||||||
|
, RpcError(..)
|
||||||
|
, RpcResponse(..)
|
||||||
, SaplingAddress(..)
|
, SaplingAddress(..)
|
||||||
, SaplingBundle(..)
|
, SaplingBundle(..)
|
||||||
, SaplingCommitmentTree(..)
|
, SaplingCommitmentTree(..)
|
||||||
|
, SaplingFrontier(..)
|
||||||
, SaplingReceiver(..)
|
, SaplingReceiver(..)
|
||||||
, SaplingSpendingKey(..)
|
, SaplingSpendingKey(..)
|
||||||
, SaplingWitness(..)
|
, SaplingWitness(..)
|
||||||
|
@ -98,6 +119,9 @@ import ZcashHaskell.Types
|
||||||
, TransparentType(..)
|
, TransparentType(..)
|
||||||
, UnifiedAddress(..)
|
, UnifiedAddress(..)
|
||||||
, UnifiedFullViewingKey(..)
|
, UnifiedFullViewingKey(..)
|
||||||
|
, UnifiedIncomingViewingKey(..)
|
||||||
|
, ValidAddress(..)
|
||||||
|
, ValidVk(..)
|
||||||
, ZcashNet(..)
|
, ZcashNet(..)
|
||||||
, ZebraTxResponse(..)
|
, ZebraTxResponse(..)
|
||||||
, decodeHexText
|
, decodeHexText
|
||||||
|
@ -892,34 +916,36 @@ main = do
|
||||||
Just t' -> do
|
Just t' -> do
|
||||||
let tb = zt_tBundle t'
|
let tb = zt_tBundle t'
|
||||||
show tb `shouldNotBe` ""
|
show tb `shouldNotBe` ""
|
||||||
describe "Sapling commitment trees" $ do
|
{-
|
||||||
let tree =
|
-describe "Sapling commitment trees" $ do
|
||||||
SaplingCommitmentTree $
|
- let tree =
|
||||||
hexString
|
- SaplingCommitmentTree $
|
||||||
"01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
- hexString
|
||||||
let cmu1 =
|
- "01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
||||||
hexString
|
- let cmu1 =
|
||||||
"45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f"
|
- hexString
|
||||||
let cmu2 =
|
- "45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f"
|
||||||
hexString
|
- let cmu2 =
|
||||||
"426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d"
|
- hexString
|
||||||
let tree2 =
|
- "426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d"
|
||||||
hexString
|
- let tree2 =
|
||||||
"01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
- hexString
|
||||||
it "Commitment tree is updated correctly" $ do
|
- "01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
||||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
- it "Commitment tree is updated correctly" $ do
|
||||||
t1 `shouldNotBe` Nothing
|
- let t1 = updateSaplingCommitmentTree tree cmu1
|
||||||
it "Incremental witness is generated" $ do
|
- t1 `shouldNotBe` Nothing
|
||||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
- it "Incremental witness is generated" $ do
|
||||||
case t1 of
|
- let t1 = updateSaplingCommitmentTree tree cmu1
|
||||||
Nothing -> assertFailure "Failed to append node to tree"
|
- case t1 of
|
||||||
Just t -> getSaplingWitness t `shouldNotBe` Nothing
|
- Nothing -> assertFailure "Failed to append node to tree"
|
||||||
it "Position of note is obtained" $ do
|
- Just t -> getSaplingWitness t `shouldNotBe` Nothing
|
||||||
let p =
|
- it "Position of note is obtained" $ do
|
||||||
getSaplingNotePosition <$>
|
- let p =
|
||||||
(getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1)
|
- getSaplingNotePosition <$>
|
||||||
p `shouldBe` Just 129405
|
- (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1)
|
||||||
describe "Orchard commitment trees" $ do
|
- p `shouldBe` Just 129405
|
||||||
|
-}
|
||||||
|
{- describe "Orchard commitment trees" $ do
|
||||||
let tree =
|
let tree =
|
||||||
OrchardCommitmentTree $
|
OrchardCommitmentTree $
|
||||||
hexString
|
hexString
|
||||||
|
@ -939,7 +965,7 @@ main = do
|
||||||
let p =
|
let p =
|
||||||
getOrchardNotePosition <$>
|
getOrchardNotePosition <$>
|
||||||
(getOrchardWitness =<< updateOrchardCommitmentTree tree cmx)
|
(getOrchardWitness =<< updateOrchardCommitmentTree tree cmx)
|
||||||
p `shouldBe` Just 39432
|
p `shouldBe` Just 39432 -}
|
||||||
describe "Extract Sapling Address - UA Valid" $ do
|
describe "Extract Sapling Address - UA Valid" $ do
|
||||||
let sr =
|
let sr =
|
||||||
getSaplingFromUA
|
getSaplingFromUA
|
||||||
|
@ -1058,17 +1084,21 @@ main = do
|
||||||
(hexString
|
(hexString
|
||||||
"97e5f003d16720844ba1bd157688a7697133f4bb4a33a7c91974937a1351d7af56d16d4a10bd196ddda700fcd8be517f8f9e39a17ba0eea235d98450a626be3a998ac31f35e8e082106a31fe94da11d02b73748db4aa519df6bbf25c1d62a2cf0b192c6a486bca2632fee9e4124ce2dba6f3366a14850f6a3b784d863119f52458ed774f8d63105b4f6a3d2e09cc74e3a02ec8386213087b4c849172ded6724a45c9c12744ec4a0f86a29b803b17187df5dd5f90e71d1f3f4578d4e1496e8892")
|
"97e5f003d16720844ba1bd157688a7697133f4bb4a33a7c91974937a1351d7af56d16d4a10bd196ddda700fcd8be517f8f9e39a17ba0eea235d98450a626be3a998ac31f35e8e082106a31fe94da11d02b73748db4aa519df6bbf25c1d62a2cf0b192c6a486bca2632fee9e4124ce2dba6f3366a14850f6a3b784d863119f52458ed774f8d63105b4f6a3d2e09cc74e3a02ec8386213087b4c849172ded6724a45c9c12744ec4a0f86a29b803b17187df5dd5f90e71d1f3f4578d4e1496e8892")
|
||||||
it "Sap output 1" $ do
|
it "Sap output 1" $ do
|
||||||
|
case getSaplingFrontier tree of
|
||||||
|
Nothing -> assertFailure "failed to read comm tree"
|
||||||
|
Just tree' -> do
|
||||||
let pos =
|
let pos =
|
||||||
getSaplingNotePosition <$>
|
sf_pos <$>
|
||||||
(getSaplingWitness =<<
|
|
||||||
updateSaplingCommitmentTree
|
updateSaplingCommitmentTree
|
||||||
tree
|
tree'
|
||||||
(fromText
|
(fromText
|
||||||
"fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858"))
|
"fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858")
|
||||||
case pos of
|
case pos of
|
||||||
Nothing -> assertFailure "couldn't get note position"
|
Nothing -> assertFailure "couldn't get note position"
|
||||||
Just p -> do
|
Just p -> do
|
||||||
let dn = decodeSaplingOutputEsk sk so1 TestNet External p
|
let dn =
|
||||||
|
decodeSaplingOutputEsk sk so1 TestNet External $
|
||||||
|
fromIntegral p
|
||||||
dn `shouldBe` Nothing
|
dn `shouldBe` Nothing
|
||||||
it "Sap output 2" $ do
|
it "Sap output 2" $ do
|
||||||
case readZebraTransaction txHex2 of
|
case readZebraTransaction txHex2 of
|
||||||
|
@ -1079,11 +1109,14 @@ main = do
|
||||||
Nothing -> assertFailure "Failed to get sapling bundle"
|
Nothing -> assertFailure "Failed to get sapling bundle"
|
||||||
Just sB -> do
|
Just sB -> do
|
||||||
let sOuts = sbOutputs sB
|
let sOuts = sbOutputs sB
|
||||||
|
case getSaplingFrontier tree of
|
||||||
|
Nothing -> assertFailure "Failed to read tree"
|
||||||
|
Just tree' -> do
|
||||||
let pos =
|
let pos =
|
||||||
getSaplingNotePosition <$>
|
getSaplingNotePosition <$>
|
||||||
(getSaplingWitness =<<
|
(getSaplingWitness =<<
|
||||||
updateSaplingCommitmentTree
|
updateSaplingCommitmentTree
|
||||||
tree
|
tree'
|
||||||
(fromText
|
(fromText
|
||||||
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843"))
|
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843"))
|
||||||
case pos of
|
case pos of
|
||||||
|
@ -1109,13 +1142,15 @@ main = do
|
||||||
Nothing -> assertFailure "Failed to get sapling bundle"
|
Nothing -> assertFailure "Failed to get sapling bundle"
|
||||||
Just sB -> do
|
Just sB -> do
|
||||||
let sOuts = sbOutputs sB
|
let sOuts = sbOutputs sB
|
||||||
|
case getSaplingFrontier tree of
|
||||||
|
Nothing -> assertFailure "failed to read comm tree"
|
||||||
|
Just tree' -> do
|
||||||
let pos =
|
let pos =
|
||||||
getSaplingNotePosition <$>
|
sf_pos <$>
|
||||||
(getSaplingWitness =<<
|
|
||||||
updateSaplingCommitmentTree
|
updateSaplingCommitmentTree
|
||||||
tree
|
tree'
|
||||||
(fromText
|
(fromText
|
||||||
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843"))
|
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")
|
||||||
case pos of
|
case pos of
|
||||||
Nothing -> assertFailure "couldn't get note position"
|
Nothing -> assertFailure "couldn't get note position"
|
||||||
Just p -> do
|
Just p -> do
|
||||||
|
@ -1125,7 +1160,7 @@ main = do
|
||||||
(head . tail $ sOuts)
|
(head . tail $ sOuts)
|
||||||
MainNet
|
MainNet
|
||||||
External
|
External
|
||||||
p
|
(fromIntegral p)
|
||||||
dn `shouldNotBe` Nothing
|
dn `shouldNotBe` Nothing
|
||||||
describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do
|
describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do
|
||||||
let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e"
|
let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e"
|
||||||
|
@ -1143,43 +1178,218 @@ main = do
|
||||||
case exch of
|
case exch of
|
||||||
Nothing -> assertFailure "Failed to encode Exchange address"
|
Nothing -> assertFailure "Failed to encode Exchange address"
|
||||||
Just addr -> do
|
Just addr -> do
|
||||||
let eadr = decodeExchangeAddress addr
|
let eadr = decodeExchangeAddress (E.encodeUtf8 addr)
|
||||||
eadr `shouldNotBe` Nothing
|
eadr `shouldNotBe` Nothing
|
||||||
describe "Witness updates" $ do
|
describe "Generate Viewing Keys" $ do
|
||||||
it "Sapling" $ do
|
let p =
|
||||||
let wit =
|
Phrase
|
||||||
SaplingWitness $
|
"cloth swing left trap random tornado have great onion element until make shy dad success art tuition canvas thunder apple decade elegant struggle invest"
|
||||||
hexString
|
let seed = getWalletSeed p
|
||||||
"01bd8a3f3cfc964332a2ada8c09a0da9dfc24174befb938abb086b9be5ca049e49013607f5e51826c8e5f660571ddfae14cd6fb1dc026bcd6855459b4e9339b20521100000019f0d7efb00169bb2202152d3266059d208ab17d14642c3339f9075e997160657000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39038cd7f6e2238d16ef49420963348dd4e4c7d23d5e5dac69507fba8937f63eb626f6856115bea2fa8db3a65a0ab294db41c51435d3b7ea27c7b2835aca28e82a2c1d9634efe07449a47c251518ac6f92c49f3a1ef119948f6a824d1e7ff7d0443e0101e57ec972a9b9383dc9cb228980d2d7752bb2abebc4a604ca48c5457039d2e05b000301392bed8592185dde5ab7fc81aed75e98fcf041f1a3fda55ad0b0b139ba9380130001808304b4d7c4fc407f5ce28247a7119013aeaaf1481902419c42bc8b21575c15"
|
let oK = genOrchardSpendingKey (fromJust seed) MainNetCoin 0
|
||||||
let cmus =
|
let sK = genSaplingSpendingKey (fromJust seed) MainNetCoin 0
|
||||||
[ hexString
|
it "Generate FVK" $ do
|
||||||
"958ccdc752f2f593f6c1c8e2d7201348cd896e54c6d3c92200bdbe8b859eac44"
|
tK <- genTransparentPrvKey (fromJust seed) MainNetCoin 0
|
||||||
, hexString
|
FullVk fvk <- deriveUfvk MainNet oK sK (Just tK)
|
||||||
"e49992fdd071d90bf56242d1aa625bbe267a34e0debd4307818a686d05b45447"
|
net fvk `shouldBe` 1
|
||||||
, hexString
|
it "Generate IVK" $ do
|
||||||
"0c4b26766d89bf6cdb4fd3b0317b4e9a2fb3850f6a24869f32fe7cb0fd512e18"
|
tK <- genTransparentPrvKey (fromJust seed) MainNetCoin 0
|
||||||
]
|
IncomingVk ivk <- deriveUivk MainNet oK sK (Just tK)
|
||||||
updateSaplingWitness wit cmus `shouldBe`
|
i_net ivk `shouldBe` 1
|
||||||
SaplingWitness
|
describe "Use viewing keys" $ do
|
||||||
|
describe "FVKs" $ do
|
||||||
|
let fvk =
|
||||||
|
decodeUfvk
|
||||||
|
"uviewtest1jna46ql5qns5rlg99jgs6mhf0j9tk8zxvqsm472scgvmj0vs0rqv2kvdf626gftx7dgn2tltyf0s200gvjlsdvz5celpue9wxxw78txswqmayxc3pfrt5fs5frvr3ep0jrjg8euahqzc63yx9sy4z8lql4ev6q3asptl9rhsfzzrup2g5slwnlvy3dgft44jw3l08xtzypjmsrwxskgnp5s03xlc2kg5520a25pa6fdjxhzutam4wkwr6mh4zeq3qndpks8dk0y90y7gucgsp0j5k2xnhh90m3krk5glz4794dj93pf59h85dqms6337f85ccvpxhays94kvsj2hyjsltf52tygqs8y0vp2yf39drxl687the6xkp8nxkfffc3kqlkhw53t5plplde0vk9rwv340ys04gg48fs0pxfp35rvt2f2pvxjmgmln6lp5k2yzkm0r87k89p6xqv68a6uyfpsauswh9fsckfqey02pjedz5gs934qa"
|
||||||
|
let addrFromWallet =
|
||||||
|
"utest1act45pg36s7345emmp8lpxx560d4tjy2ef7vzzqvdqmt8d5gjxn7x4aarskvqzqccgyjrv5gc4mr6nf2elz6ylpu8hq3rgm0gj43jkl3elrugr49swlk0pv5edvcgnmhrqswkck6kvswvr89h2q0m6gtwktxzdkjp80c86nlp7x02kd0ttpsylsjddk488nmagtj85xclluug793h8n"
|
||||||
|
let cua =
|
||||||
|
"utest1zcjhrp39ux52ype4j6055fngdufet0h2d6hx564s48cgnzthm3xma3eca4x8sh5a89jk88nerngvy5uq9tyxgxq552k64rs93ell63f8sd2rurhn34lr6fjznw64uf473mehpn39gy2k0m86r3gpp5lcdh2senl7kwgl6hku03n0gpqvcfc7c48kjv9z49yp52etntgwkltsz3zvj0m"
|
||||||
|
let oa =
|
||||||
|
OrchardAction
|
||||||
(hexString
|
(hexString
|
||||||
"01bd8a3f3cfc964332a2ada8c09a0da9dfc24174befb938abb086b9be5ca049e49013607f5e51826c8e5f660571ddfae14cd6fb1dc026bcd6855459b4e9339b20521100000019f0d7efb00169bb2202152d3266059d208ab17d14642c3339f9075e997160657000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39038cd7f6e2238d16ef49420963348dd4e4c7d23d5e5dac69507fba8937f63eb626f6856115bea2fa8db3a65a0ab294db41c51435d3b7ea27c7b2835aca28e82a2c1d9634efe07449a47c251518ac6f92c49f3a1ef119948f6a824d1e7ff7d0443e0101e49992fdd071d90bf56242d1aa625bbe267a34e0debd4307818a686d05b45447010c4b26766d89bf6cdb4fd3b0317b4e9a2fb3850f6a24869f32fe7cb0fd512e1803000121c06ee1f1584f79d50785797a694c742be2ded600367ab7d54f3ed49e3adf7201808304b4d7c4fc407f5ce28247a7119013aeaaf1481902419c42bc8b21575c15")
|
"33d6bf1d78f6414b725b5b43bfbb92b460d81cf04a352831d74bbc3c3aa86c2a")
|
||||||
it "Orchard" $ do
|
|
||||||
let wit =
|
|
||||||
OrchardWitness $
|
|
||||||
hexString
|
|
||||||
"016225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631001f0000011d6f5da3f619bfaab957fc643c17eb144db0101c90f422da2fcbe0e80d74412e000000000001746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000040e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e0504bfbc12edc35e05042c16bbfb8fed591f01f18fe128eeb57f2c456c9eb222d6d261c549e95d9007bce4c6ae0b86bc865711cdd9f0fa92e2d5b5e149b51f3be127df3b1d2372adf6c811b2e456c1d64d0e9eb167a995f9c6b66a03c9cbda250101c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e000200019df5b9366d0f21caa678d1567390b5bfd3cfa0438271bcfe301b5558a2863301"
|
|
||||||
let cmxs =
|
|
||||||
[ hexString
|
|
||||||
"712ba86615ff4447e8d7c7b59f3873f03c03a173438b8e4c8d416756ed4fae10"
|
|
||||||
, hexString
|
|
||||||
"c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e"
|
|
||||||
, hexString
|
|
||||||
"ac20b8170b008888c19fc6e16f5e30a5ef1653e5219d0cd0c9353c3aa8f79823"
|
|
||||||
]
|
|
||||||
updateOrchardWitness wit cmxs `shouldBe`
|
|
||||||
OrchardWitness
|
|
||||||
(hexString
|
(hexString
|
||||||
"016225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631001f0000011d6f5da3f619bfaab957fc643c17eb144db0101c90f422da2fcbe0e80d74412e000000000001746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000040e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e0504bfbc12edc35e05042c16bbfb8fed591f01f18fe128eeb57f2c456c9eb222d6d261c549e95d9007bce4c6ae0b86bc865711cdd9f0fa92e2d5b5e149b51f3be127df3b1d2372adf6c811b2e456c1d64d0e9eb167a995f9c6b66a03c9cbda250101c094201bae3b4ef582a3e8654f65a72fbd41e20e1ec9a43d3f4101afc868731e0002010cfb50d8c877eb39e9c07082a032dd99d34be7c19fa7f30e9fecf5f14736240f019df5b9366d0f21caa678d1567390b5bfd3cfa0438271bcfe301b5558a2863301")
|
"ce6d2090bf747ddce410ad967ea98e727120710f9814a6d77ebdd593c6f9660b")
|
||||||
|
(hexString
|
||||||
|
"567be1d3c5e2b8aba20fba30edd357810eb40647f1f5f9bb4e23691a9c174235")
|
||||||
|
(hexString
|
||||||
|
"b4ee13a27e1b7f2674c7b3924c2178b4c010c05750b78b65cb741b10476d1c24")
|
||||||
|
(hexString
|
||||||
|
"e8c37d9a2ea88f2ef266fed77753744da9afedf2530940b15ad882cc187a69d6116c5c34cdaf94e1f178ec50ef95d49b46ab6a7206c2a6b57d9d55f65cc7f5f57ccb91d71e827af5286897a4c8ca9c3fc2dad60208adbc8bd3d81eb5febf4c3c75e69b83627fdff730a946bb2e6e6703c4c676675e34ece1b073ce61490298a93503fa10f2b86fbd1274825c72e26b2340d1ed338d3b254803614b2fc9778155c988516d6ce1f334aeca076063c06588961c0d7dfa1bafd59cbca1782fcd863fce1f25abdf151c9718dce3708f8cede130d9e785ed4798aebfca8fec386f4a4d38a75c7b054c453676ad9ce7de32f4c4687f6932686f52e381bd41508a468ca684ea2755d56522a7b4138f58d0b10e1195a6fe27393ca382d0525a74acde5e0f6f2cb8ff3d74221f2a02fe2fd1874a2cf6f542bfa8f0107a21728249ca549bbba66a5422fd9aeaaeff09d1edfecb711c15290c9e8d031baf41fe47a5da3f9a614016f45886fb4d3ea2795802bf7785c1c9e3de15dc18300891f6abb9569851a7c4bf4cd054f8f593969b42c80968bf732ebaa90abf1a7614d1d325e8ed930161e0fbf82333c96cea455743c3e3e3cd1cdd754383a6f2364eacc162059e31885045eee7f2d60b068e78e29490a4df0f34e690b3bb17923669b828d245727bf11b0fe1e0fc4b97b62be37f7a7944db5b5b13221b0000f74c3cdcf9c246e60e77327c4f853f4037eeb2feb9f5d84961e4321c54c30d193866897872b31113a5f819dc2a264d2ef7b91edd16504ad75b6ee622dad79dadaadcd005215932d66232738a7dd8d2")
|
||||||
|
(hexString
|
||||||
|
"0b7be09c8f69e068d3277f345a0a4bf11057ff4c46e7657bb8a61a1c2b4c0d61e8e561131f935053f02cb46360f13179dc4647a243fabdd9ac59ba9ac2529a3b7af0ea5020d2b4c17466ebf309448491")
|
||||||
|
(hexString
|
||||||
|
"81939f32c4ca40c0a4c9334cffd68339e207afc322b533cb9cbb7b156758dc94")
|
||||||
|
(hexString
|
||||||
|
"44e3d8c4fbac16fc0edfd634b396b0a4822fc9a2cfdc8ec293a5c6ffc2001e96d2840c303463e3bc9add8c9263c56569e5b7ac14cf8d84316735f4b77493c136")
|
||||||
|
let so =
|
||||||
|
ShieldedOutput
|
||||||
|
(hexString
|
||||||
|
"dae2e33897847cc968d4719efc6ff6ea69c7ea8f8567883ba891c3d99b7fc7f3")
|
||||||
|
(hexString
|
||||||
|
"3d7c752b89af7dd63430d458d54c60643533ed6db9c57f55131eb7303daf7844")
|
||||||
|
(hexString
|
||||||
|
"8f7bd84a946a9068cb2030dd8d1f7446bba2ff22a5cce5ac97cc5c46f1c9bba9")
|
||||||
|
(hexString
|
||||||
|
"bc7b212e7c0a598a1237493a014688ee1232f631928e50583df6a1980adefb867dca6f97aa468f3c3a3882db8f359fc0d29205a808173645c22ba8a815e307fec633ffd01d34830e639e4dda548cd6e3ea32054206ac77e60ae09b0bf911066caf2be0bc8e3936edfa3e05c74f2e8a8bf5bbd8867eb83fd7fe24107612f6a0eaa586c6997b19fbe43c3b7d3f8cd5f40ae1a5431cf9d0d336516fb22ce4e295f77326ada3b453b9813a4a63981a52b9ba65af43cc6ec198b384417247b8f1bb15199fba5e90e435c946d03f97c62f7b40fbfef85e456dcb8fdaec94585a600cb40b2ed6c23c08eba5115719944528c156bea996b993d6e1730a17c6cf036deee43a18bd6afbd6e0f55f6c35ab5557df8e1356866514784ab4dd5ff158f0c5bfb6011adefae26c6dcee7472b7086680a72859e231829b7cf408683ced04171065e8740abde2b528c790fbec34d80e15ca869aaa100640c7ab167d7538a48174ea7caac91297455f85a41a03ab760565dd899b6b10b7034b221f4390373bd2dc1e3766629f7d5b606449ef07057995da06a63b6bb07aa117fd26e7154e55636ab8df21c3e3665574899eb1186d2106a55cc20b7eee2bc9b5970acddbac4a74f2f5599d7b42c21e65f340363748b208e61800ce6317e43c7e55757e1c9210bc716a93edb5ca2ed26ead4c14510086fb6752a8bfa089787360cca5c6b053744ad1487f7032ba027ba7758ce842a372b2f7dd418ecbd6353ca199629faa8848dfb7f228610aa2f76324eb7092ca05c6e2e7c7e9972cf33009c716ad43adc492a25fb8d1d67e72f")
|
||||||
|
(hexString
|
||||||
|
"ebe23f6ad66a16f9e5faece7139ae55aae93631b8b36ba2b5d21885f29b39dab224549afef0137c612d0c7a8ec597e98ea5a08334392079e5ea5c061cef2ebe296e71b6845e6bea09291bba505a76a03")
|
||||||
|
(hexString
|
||||||
|
"ad238bb5d88ccc438998bbcda831b499775f76c706f67bd9e56b8c3d6a6479afcf562a459c8db54003b641f1ac83d2dfa83baf8e04d6c2ab335eec290b3f581b0063cb088b53eb30b372ce80ac86a904448b9766d02624caa42fd9828ba4912e075b786fcbed921bc4cd25555031b2cd92509894d8ade8f4da92007b010b506c5664802e4e80c3363cd6e16c2a67abdcb4f3aef7638095091ab74cf79b6dcb919f7b38547e9576a7512f0f128504bb3461b8fee69ab7774320f56b2af13a6c9d")
|
||||||
|
it "Orchard external receiver from fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k ->
|
||||||
|
genOrchardReceiverFvk 0 External (o_key k) `shouldNotBe` Nothing
|
||||||
|
it "Orchard internal receiver from fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k ->
|
||||||
|
genOrchardReceiverFvk 0 Internal (o_key k) `shouldNotBe` Nothing
|
||||||
|
it "Decrypt Orchard action with FVK" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k ->
|
||||||
|
a_nullifier <$>
|
||||||
|
decryptOrchardActionFvk k External oa `shouldBe`
|
||||||
|
Just (hexString "00")
|
||||||
|
it "Sapling external receiver from fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> genSaplingReceiverFvk 0 (s_key k) `shouldNotBe` Nothing
|
||||||
|
it "Sapling internal receiver from fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k ->
|
||||||
|
genSaplingInternalAddressFvk (s_key k) `shouldNotBe` Nothing
|
||||||
|
it "Decode external Sapling with fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k ->
|
||||||
|
a_nullifier <$>
|
||||||
|
decodeSaplingOutputFvk (s_key k) so External 234878 `shouldBe`
|
||||||
|
Just (hexString "00")
|
||||||
|
it "Transparent external receiver from fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> do
|
||||||
|
recv <- genTransparentReceiverFvk 0 External (t_key k)
|
||||||
|
recv `shouldNotBe` Nothing
|
||||||
|
it "Transparent internal receiver from fvk" $ do
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> do
|
||||||
|
recv <- genTransparentReceiverFvk 0 Internal (t_key k)
|
||||||
|
recv `shouldNotBe` Nothing
|
||||||
|
it "Generate UA from FVK" $ do
|
||||||
|
let parsedUA = parseAddress addrFromWallet
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> do
|
||||||
|
case parsedUA of
|
||||||
|
Nothing -> assertFailure "Failed to parse UA"
|
||||||
|
Just va -> do
|
||||||
|
case va of
|
||||||
|
Unified ua -> do
|
||||||
|
let orec = genOrchardReceiverFvk 0 External (o_key k)
|
||||||
|
let srec = genSaplingReceiverFvk 0 (s_key k)
|
||||||
|
trec <- genTransparentReceiverFvk 0 External (t_key k)
|
||||||
|
let myUa = UnifiedAddress TestNet orec srec trec
|
||||||
|
myUa `shouldBe` ua
|
||||||
|
_any -> assertFailure "Address to UA"
|
||||||
|
it "Generate change UA from FVK" $ do
|
||||||
|
let parsedCua = parseAddress cua
|
||||||
|
case fvk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> do
|
||||||
|
case parsedCua of
|
||||||
|
Nothing -> assertFailure "Failed to parse UA"
|
||||||
|
Just va -> do
|
||||||
|
case va of
|
||||||
|
Unified ua -> do
|
||||||
|
let orec = genOrchardReceiverFvk 0 Internal (o_key k)
|
||||||
|
let srec = genSaplingInternalAddressFvk (s_key k)
|
||||||
|
trec <- genTransparentReceiverFvk 0 Internal (t_key k)
|
||||||
|
let myUa = UnifiedAddress TestNet orec srec trec
|
||||||
|
myUa `shouldBe` ua
|
||||||
|
_any -> assertFailure "Address to UA"
|
||||||
|
describe "IVKs" $ do
|
||||||
|
let ivk =
|
||||||
|
decodeUivk
|
||||||
|
"uivktest10yy38f5v5sz5hnne93flkrpfqr4geyfuaq97u4fe9zkrng20ppeqsu7a6fkfttn0phjj9kutlnn4nzvfls233xujcv3fw6ax9w8pqzsw792py78dl8p4cyhv3eyusu589382qwf4pwz3vs7n6pv4qj7j6apg5nvw4yl4u5g033tpr2a7jjzt3f3khjm09wj7er7myr8vy04595nj6pqcdp3ndp98ckg82y0w08d8wnx7wynrzhmqrxh9pf0m50tj332vjld08uz027xwyegakyzem745y462khv9xzlc4h5rxwsqfklvak3x26excpcjn54e3cd2zttxujnuzv3rrtrpuld9e2"
|
||||||
|
let addrFromWallet =
|
||||||
|
"utest1act45pg36s7345emmp8lpxx560d4tjy2ef7vzzqvdqmt8d5gjxn7x4aarskvqzqccgyjrv5gc4mr6nf2elz6ylpu8hq3rgm0gj43jkl3elrugr49swlk0pv5edvcgnmhrqswkck6kvswvr89h2q0m6gtwktxzdkjp80c86nlp7x02kd0ttpsylsjddk488nmagtj85xclluug793h8n"
|
||||||
|
let oa =
|
||||||
|
OrchardAction
|
||||||
|
(hexString
|
||||||
|
"33d6bf1d78f6414b725b5b43bfbb92b460d81cf04a352831d74bbc3c3aa86c2a")
|
||||||
|
(hexString
|
||||||
|
"ce6d2090bf747ddce410ad967ea98e727120710f9814a6d77ebdd593c6f9660b")
|
||||||
|
(hexString
|
||||||
|
"567be1d3c5e2b8aba20fba30edd357810eb40647f1f5f9bb4e23691a9c174235")
|
||||||
|
(hexString
|
||||||
|
"b4ee13a27e1b7f2674c7b3924c2178b4c010c05750b78b65cb741b10476d1c24")
|
||||||
|
(hexString
|
||||||
|
"e8c37d9a2ea88f2ef266fed77753744da9afedf2530940b15ad882cc187a69d6116c5c34cdaf94e1f178ec50ef95d49b46ab6a7206c2a6b57d9d55f65cc7f5f57ccb91d71e827af5286897a4c8ca9c3fc2dad60208adbc8bd3d81eb5febf4c3c75e69b83627fdff730a946bb2e6e6703c4c676675e34ece1b073ce61490298a93503fa10f2b86fbd1274825c72e26b2340d1ed338d3b254803614b2fc9778155c988516d6ce1f334aeca076063c06588961c0d7dfa1bafd59cbca1782fcd863fce1f25abdf151c9718dce3708f8cede130d9e785ed4798aebfca8fec386f4a4d38a75c7b054c453676ad9ce7de32f4c4687f6932686f52e381bd41508a468ca684ea2755d56522a7b4138f58d0b10e1195a6fe27393ca382d0525a74acde5e0f6f2cb8ff3d74221f2a02fe2fd1874a2cf6f542bfa8f0107a21728249ca549bbba66a5422fd9aeaaeff09d1edfecb711c15290c9e8d031baf41fe47a5da3f9a614016f45886fb4d3ea2795802bf7785c1c9e3de15dc18300891f6abb9569851a7c4bf4cd054f8f593969b42c80968bf732ebaa90abf1a7614d1d325e8ed930161e0fbf82333c96cea455743c3e3e3cd1cdd754383a6f2364eacc162059e31885045eee7f2d60b068e78e29490a4df0f34e690b3bb17923669b828d245727bf11b0fe1e0fc4b97b62be37f7a7944db5b5b13221b0000f74c3cdcf9c246e60e77327c4f853f4037eeb2feb9f5d84961e4321c54c30d193866897872b31113a5f819dc2a264d2ef7b91edd16504ad75b6ee622dad79dadaadcd005215932d66232738a7dd8d2")
|
||||||
|
(hexString
|
||||||
|
"0b7be09c8f69e068d3277f345a0a4bf11057ff4c46e7657bb8a61a1c2b4c0d61e8e561131f935053f02cb46360f13179dc4647a243fabdd9ac59ba9ac2529a3b7af0ea5020d2b4c17466ebf309448491")
|
||||||
|
(hexString
|
||||||
|
"81939f32c4ca40c0a4c9334cffd68339e207afc322b533cb9cbb7b156758dc94")
|
||||||
|
(hexString
|
||||||
|
"44e3d8c4fbac16fc0edfd634b396b0a4822fc9a2cfdc8ec293a5c6ffc2001e96d2840c303463e3bc9add8c9263c56569e5b7ac14cf8d84316735f4b77493c136")
|
||||||
|
let so =
|
||||||
|
ShieldedOutput
|
||||||
|
(hexString
|
||||||
|
"dae2e33897847cc968d4719efc6ff6ea69c7ea8f8567883ba891c3d99b7fc7f3")
|
||||||
|
(hexString
|
||||||
|
"3d7c752b89af7dd63430d458d54c60643533ed6db9c57f55131eb7303daf7844")
|
||||||
|
(hexString
|
||||||
|
"8f7bd84a946a9068cb2030dd8d1f7446bba2ff22a5cce5ac97cc5c46f1c9bba9")
|
||||||
|
(hexString
|
||||||
|
"bc7b212e7c0a598a1237493a014688ee1232f631928e50583df6a1980adefb867dca6f97aa468f3c3a3882db8f359fc0d29205a808173645c22ba8a815e307fec633ffd01d34830e639e4dda548cd6e3ea32054206ac77e60ae09b0bf911066caf2be0bc8e3936edfa3e05c74f2e8a8bf5bbd8867eb83fd7fe24107612f6a0eaa586c6997b19fbe43c3b7d3f8cd5f40ae1a5431cf9d0d336516fb22ce4e295f77326ada3b453b9813a4a63981a52b9ba65af43cc6ec198b384417247b8f1bb15199fba5e90e435c946d03f97c62f7b40fbfef85e456dcb8fdaec94585a600cb40b2ed6c23c08eba5115719944528c156bea996b993d6e1730a17c6cf036deee43a18bd6afbd6e0f55f6c35ab5557df8e1356866514784ab4dd5ff158f0c5bfb6011adefae26c6dcee7472b7086680a72859e231829b7cf408683ced04171065e8740abde2b528c790fbec34d80e15ca869aaa100640c7ab167d7538a48174ea7caac91297455f85a41a03ab760565dd899b6b10b7034b221f4390373bd2dc1e3766629f7d5b606449ef07057995da06a63b6bb07aa117fd26e7154e55636ab8df21c3e3665574899eb1186d2106a55cc20b7eee2bc9b5970acddbac4a74f2f5599d7b42c21e65f340363748b208e61800ce6317e43c7e55757e1c9210bc716a93edb5ca2ed26ead4c14510086fb6752a8bfa089787360cca5c6b053744ad1487f7032ba027ba7758ce842a372b2f7dd418ecbd6353ca199629faa8848dfb7f228610aa2f76324eb7092ca05c6e2e7c7e9972cf33009c716ad43adc492a25fb8d1d67e72f")
|
||||||
|
(hexString
|
||||||
|
"ebe23f6ad66a16f9e5faece7139ae55aae93631b8b36ba2b5d21885f29b39dab224549afef0137c612d0c7a8ec597e98ea5a08334392079e5ea5c061cef2ebe296e71b6845e6bea09291bba505a76a03")
|
||||||
|
(hexString
|
||||||
|
"ad238bb5d88ccc438998bbcda831b499775f76c706f67bd9e56b8c3d6a6479afcf562a459c8db54003b641f1ac83d2dfa83baf8e04d6c2ab335eec290b3f581b0063cb088b53eb30b372ce80ac86a904448b9766d02624caa42fd9828ba4912e075b786fcbed921bc4cd25555031b2cd92509894d8ade8f4da92007b010b506c5664802e4e80c3363cd6e16c2a67abdcb4f3aef7638095091ab74cf79b6dcb919f7b38547e9576a7512f0f128504bb3461b8fee69ab7774320f56b2af13a6c9d")
|
||||||
|
it "Orchard external receiver from ivk" $ do
|
||||||
|
case ivk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> genOrchardReceiverIvk 0 (i_o_key k) `shouldNotBe` Nothing
|
||||||
|
it "Decrypt Orchard action with IVK" $ do
|
||||||
|
case ivk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> decryptOrchardActionIvk k oa `shouldNotBe` Nothing
|
||||||
|
it "Sapling external receiver from ivk" $ do
|
||||||
|
case ivk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> genSaplingReceiverIvk 0 (i_s_key k) `shouldNotBe` Nothing
|
||||||
|
it "Decode external Sapling with ivk" $ do
|
||||||
|
case ivk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k ->
|
||||||
|
decodeSaplingOutputIvk (i_s_key k) so `shouldNotBe` Nothing
|
||||||
|
it "Transparent external receiver from ivk" $ do
|
||||||
|
case ivk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> do
|
||||||
|
recv <- genTransparentReceiverIvk 0 (i_t_key k)
|
||||||
|
recv `shouldNotBe` Nothing
|
||||||
|
it "Generate UA from IVK" $ do
|
||||||
|
let parsedUA = parseAddress addrFromWallet
|
||||||
|
case ivk of
|
||||||
|
Nothing -> assertFailure "Failed to parse VK"
|
||||||
|
Just k -> do
|
||||||
|
case parsedUA of
|
||||||
|
Nothing -> assertFailure "Failed to parse UA"
|
||||||
|
Just va -> do
|
||||||
|
case va of
|
||||||
|
Unified ua -> do
|
||||||
|
let orec = genOrchardReceiverIvk 0 (i_o_key k)
|
||||||
|
let srec = genSaplingReceiverIvk 0 (i_s_key k)
|
||||||
|
trec <- genTransparentReceiverIvk 0 (i_t_key k)
|
||||||
|
let myUa = UnifiedAddress TestNet orec srec trec
|
||||||
|
myUa `shouldBe` ua
|
||||||
|
_any -> assertFailure "Address to UA"
|
||||||
|
|
||||||
-- | Properties
|
-- | Properties
|
||||||
prop_PhraseLength :: Property
|
prop_PhraseLength :: Property
|
||||||
|
|
|
@ -5,7 +5,7 @@ cabal-version: 3.0
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
|
|
||||||
name: zcash-haskell
|
name: zcash-haskell
|
||||||
version: 0.6.2.1
|
version: 0.8.1.0
|
||||||
synopsis: Utilities to interact with the Zcash blockchain
|
synopsis: Utilities to interact with the Zcash blockchain
|
||||||
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
|
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
|
||||||
category: Blockchain
|
category: Blockchain
|
||||||
|
@ -59,6 +59,7 @@ library
|
||||||
, text
|
, text
|
||||||
, haskoin-core
|
, haskoin-core
|
||||||
, secp256k1-haskell >= 1.1
|
, secp256k1-haskell >= 1.1
|
||||||
|
, vector
|
||||||
, utf8-string
|
, utf8-string
|
||||||
build-tool-depends:
|
build-tool-depends:
|
||||||
c2hs:c2hs
|
c2hs:c2hs
|
||||||
|
@ -85,5 +86,6 @@ test-suite zcash-haskell-test
|
||||||
, binary
|
, binary
|
||||||
, cryptonite
|
, cryptonite
|
||||||
, secp256k1-haskell
|
, secp256k1-haskell
|
||||||
|
, http-conduit
|
||||||
pkgconfig-depends: rustzcash_wrapper
|
pkgconfig-depends: rustzcash_wrapper
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
Loading…
Add table
Reference in a new issue