Compare commits

..

258 commits

Author SHA1 Message Date
d45bd7dcf3
Milestone 3 (#101)
This PR contains all the enhancements needed for the completion of Milestone 3 of the Zenith Full Node wallet.
- Implementation of Rust Sapling parameters
- Implementation of native Haskell commitment trees
- Optimization of transaction creation

Reviewed-on: https://git.vergara.tech///Vergara_Tech/zcash-haskell/pulls/101
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-11-21 14:19:43 +00:00
5349498737
Merge pull request 'Upgrade to GHC 9.6.5' (#84) from rav001 into master
Reviewed-on: #84
2024-07-01 21:07:52 +00:00
812ff0aa70
Upgrade to GHC 9.6.5 2024-07-01 16:05:33 -05:00
874db2907e
Performance enhancement for transaction creation 2024-05-16 10:42:44 -05:00
4165cab701
Merge branch 'dev040' 2024-05-13 14:25:46 -05:00
9dddb42bb3
Merge pull request 'Implement fee calculator' (#81) from rav001 into dev040
Reviewed-on: #81
2024-05-08 18:51:34 +00:00
148abd95d0
Implement fee calculator 2024-05-08 13:49:39 -05:00
4ca5d07d1c
Merge pull request 'Fix bug in Orchard witness calculation' (#80) from rav001 into dev040
Reviewed-on: #80
2024-05-07 20:21:19 +00:00
37b485288d
Fix bug in Orchard witness calculation 2024-05-07 15:19:54 -05:00
302a2f87fa
Merge pull request 'Remove debugging' (#79) from rav001 into dev040
Reviewed-on: #79
2024-05-07 17:17:29 +00:00
2108f46afa
Remove debugging 2024-05-07 12:13:54 -05:00
22c0fe3749
Merge pull request 'Transaction creation updates' (#78) from rav001 into dev040
Reviewed-on: #78
2024-05-02 19:59:25 +00:00
1e31bb73c2
Update Rust debugging 2024-05-02 14:55:24 -05:00
c583451c83
Update debugging 2024-05-02 14:30:59 -05:00
6a632d45c1
Change error messaging 2024-05-02 14:07:54 -05:00
31c5cda65a
Improve error message 2024-05-02 13:38:12 -05:00
d5e17afc99
Debugging parameters 2024-05-02 13:34:26 -05:00
c7f2bca2c4
Remove ovk from transaction creation 2024-05-02 12:48:30 -05:00
2d14ef6b22
Update to use commitment trees for anchors 2024-05-02 12:35:36 -05:00
652e95c361
Improve error messaging 2024-05-02 12:10:53 -05:00
c144a6d624
Add more debugging to Rust 2024-05-02 07:31:01 -05:00
5fd33e7e43
Add debuggin for create transaction 2024-05-02 07:22:12 -05:00
8dbcf58a93
Merge pull request 'Fix typo in constructor' (#77) from rav001 into dev040
Reviewed-on: #77
2024-05-01 21:15:50 +00:00
bea4d2f071
Fix typo in constructor 2024-05-01 16:14:41 -05:00
61a35a034b
Merge pull request 'Add transparent key derivation' (#76) from rav001 into dev040
Reviewed-on: #76
2024-05-01 19:30:48 +00:00
bc074d0386
Add transparent key derivation 2024-05-01 14:24:18 -05:00
4a48769eeb
Merge pull request 'Add functionality for transaction creation' (#75) from rav001 into dev040
Reviewed-on: #75
2024-05-01 14:14:40 +00:00
6b391ef7d2
Merge branch 'dev040' into rav001 2024-05-01 14:14:28 +00:00
787cf40629
Add functionality for transaction creation 2024-05-01 09:12:58 -05:00
91707e13c2
Merge pull request 'Add Read instance to Rseed' (#74) from rav001 into dev040
Reviewed-on: #74
2024-05-01 00:17:18 +00:00
26a79443a7
Add Read instance to Rseed 2024-04-30 19:14:30 -05:00
c9f13643e4
Merge pull request 'Implement transaction creation' (#73) from rav001 into dev040
Reviewed-on: #73
2024-04-30 21:56:10 +00:00
ad9e2f074d
Implement transaction creation 2024-04-30 16:54:15 -05:00
f456332454
Merge pull request 'Upgrade of Rust crates' (#72) from rav001 into dev040
Reviewed-on: #72
2024-04-29 15:31:41 +00:00
201df05e9b
Merge branch 'dev040' into rav001 2024-04-29 10:29:09 -05:00
8901d97c64
Upgrade of Zcash Rust crates 2024-04-29 10:27:45 -05:00
619c80c816
Merge pull request 'Add witness update functionality' (#71) from rav001 into dev040
Reviewed-on: #71
2024-04-26 01:00:18 +00:00
24ae69cddb
Merge branch 'dev040' into rav001 2024-04-26 01:00:01 +00:00
af9806d72d
Add witness update functionality 2024-04-25 19:56:29 -05:00
00400c433d
Merge pull request 'Update note position calculation' (#70) from rav001 into dev040
Reviewed-on: #70
2024-04-24 22:28:05 +00:00
b74cd5f354
Update note position calculation 2024-04-24 16:04:56 -05:00
586cb4646c
Merge pull request 'Fix Sapling spend parsing' (#69) from rav001 into dev040
Reviewed-on: #69
2024-04-24 17:02:40 +00:00
6cf5d85c0b
Merge branch 'dev040' into rav001 2024-04-24 12:01:13 -05:00
f4612a7310
Merge pull request 'rvv040' (#67) from rvv040 into dev040
Reviewed-on: #67
2024-04-24 17:00:41 +00:00
173445612d
Merge branch 'dev040' into rvv040 2024-04-24 11:59:58 -05:00
3296909c82
Fix Sapling spend parsing 2024-04-24 11:57:00 -05:00
ebfac8438f rvv040 - decodeExchangeAddress modified to return an ExcahngeAddress object 2024-04-18 08:30:14 -04:00
f39b376380
Merge pull request 'Fix Orchard nullifier calculation' (#68) from rav001 into dev040
Reviewed-on: #68
2024-04-18 01:19:55 +00:00
7d20edd08d
Fix Orchard nullifier calculation 2024-04-17 20:14:03 -05:00
1b2c6dce24 rvv040 - Update CHANGE.LOG file 2024-04-17 20:51:12 -04:00
e6d16267ee rvv040 - Functions to create and decode an ExchangeAddress added
New DataType ExchangeAddress added.
2024-04-17 20:36:04 -04:00
4027907896
Merge pull request 'Update version' (#66) from rav001 into dev040
Reviewed-on: #66
2024-04-17 16:24:30 +00:00
e75175852b
Version bump 2024-04-17 11:21:03 -05:00
4efae180f5
Fix Rust binding for Sapling decode 2024-04-17 11:18:56 -05:00
915cd68042
Merge pull request 'Add Orchard commitment tree functionality' (#65) from rav001 into dev040
Reviewed-on: #65
2024-04-17 16:00:03 +00:00
e98ca65409
Merge branch 'dev040' into rav001 2024-04-17 10:23:30 -05:00
5abc57081a
Merge pull request 'rvv040' (#63) from rvv040 into dev040
Reviewed-on: #63
2024-04-17 14:26:38 +00:00
f94a1f83cb
Merge branch 'dev040' into rvv040 2024-04-17 09:25:46 -05:00
a56a4b1e15
Add Orchard commitment tree functionality 2024-04-17 09:21:47 -05:00
06aff8c787 rvv040 - Add encodeSaplingAddress function
Added new tests for encodeSaplingAddress and decodeSaplingAddress
2024-04-16 18:51:14 -04:00
914eb6341e
Merge pull request 'Remove debugging from Sapling decoder' (#64) from rav001 into dev040
Reviewed-on: #64
2024-04-16 20:16:46 +00:00
4f2b88974c
Remove debugging 2024-04-16 15:13:41 -05:00
058bbfe3f2 rvv040 - Added a decode Testnet Sapling Address test 2024-04-16 14:48:36 -04:00
382284a8ca rvv040 - decodeSaplingAddress Function added
SaplingAddress  data type added
2024-04-16 14:39:56 -04:00
cb985d26cd
Add debugging for Sapling decode 2024-04-16 11:19:53 -05:00
1232c3e36f
Merge pull request 'Test Sapling decoding' (#62) from rav001 into dev040
Reviewed-on: #62
2024-04-16 14:46:59 +00:00
99d772d2c7
Test Sapling decoding 2024-04-16 09:43:00 -05:00
23b8de31f1
Merge pull request 'Update Sapling commitment tree reader' (#61) from rav001 into dev040
Reviewed-on: #61
2024-04-16 01:03:01 +00:00
09ff2ed5ac
Merge branch 'dev040' into rav001 2024-04-16 01:02:38 +00:00
5402fcc072
Update Sapling commitment tree reader 2024-04-15 19:58:26 -05:00
d754498ec3
Merge pull request 'Add nullifier field to DecodedNote' (#60) from rav001 into dev040
Reviewed-on: #60
2024-04-14 22:37:52 +00:00
1b98120376
Add nullifier field to DecodedNote 2024-04-14 17:35:49 -05:00
0e52adbea4
Merge pull request 'Add new function to decode a Transparent Address in HRF' (#59) from rvv040 into dev040
Reviewed-on: #59
2024-04-14 14:27:17 +00:00
15b2f98f1d rvv040 - Fix transparent address decoding -
Function was returning the "digest" instead the "transparentReceiver"
2024-04-14 08:37:19 -04:00
95f20adb56
Merge branch 'dev040' into rvv040 2024-04-14 07:01:51 -05:00
e781ed6bd0
Add test to for transparent decoding 2024-04-14 06:57:36 -05:00
deacf373e1 rvv040 - Add new function to decode a Transparent Address in HRF
The function  retunrs a TransparentAddress object.
2024-04-13 18:27:59 -04:00
7b45bb9a6f
Merge pull request 'Add Sapling nullifier calculation' (#58) from rav001 into dev040
Reviewed-on: #58
2024-04-12 18:18:47 +00:00
6a2849aae0
Add Sapling nullifier calculation to decoding 2024-04-12 13:15:41 -05:00
0f19e376dc
Add Sapling commitment tree functionality 2024-04-11 16:01:29 -05:00
ce6a13e333
Merge branch 'dev040' into rav001 2024-04-10 11:39:27 -05:00
7efb9d0148
Merge pull request '#57 - Sapling address in Human Readable format' (#57) from rvv040 into dev040
Reviewed-on: #57
2024-04-10 16:35:39 +00:00
b6af8630b8
Merge branch 'dev040' into rvv040 2024-04-10 11:34:40 -05:00
30ca143dc9
Update changelog 2024-04-10 11:29:59 -05:00
cea8a70f44 rvva040 - Convert Sapling receiver to Human readable format
Function getSaplingFromUA -> Now returns "Maybe T.Text" instead of "T.Text"
2024-04-10 10:27:09 -04:00
3f918f734a rvv040 - Sapling address encoding to human readable format
Change Bech32m to Bech32  encoding for Sapling address
2024-04-10 09:55:41 -04:00
27b291c49a
Add function to append nodes to commitment tree 2024-04-10 07:06:04 -05:00
1f8a4cbd2b Branch rvv040 - Get Sapling Human Readable representation - In proccess
Bug - Bech32m error calculating checksum - to resolve
2024-04-09 20:23:16 -04:00
ea937f8e51
Merge pull request 'Add Orchard action decryption with spendig key' (#56) from rav001 into dev040
Reviewed-on: #56
2024-04-09 18:09:46 +00:00
7c5d4cf99f
Update version 2024-04-09 13:06:23 -05:00
4f9601f8d8
Add function to decode Orchard action with spending key 2024-04-09 13:05:57 -05:00
817c52dacf
Merge pull request 'Add Sapling output decrypting with spending key' (#55) from rav001 into dev040
Reviewed-on: #55
2024-04-08 18:01:25 +00:00
e00cf21709
Add Sapling output decrypting with spending key 2024-04-08 12:55:30 -05:00
2709d42266
Merge pull request 'Correct the parsing of the tx hash in TxIn' (#54) from rav001 into dev040
Reviewed-on: #54
2024-04-05 19:14:13 +00:00
5814cb7c9e
Correct the parsing of the tx hash in TxIn 2024-04-05 14:12:39 -05:00
a06fd08172
Merge pull request 'Fix TxIn parsing' (#53) from rav001 into dev040
Reviewed-on: #53
2024-04-05 17:52:02 +00:00
3c2e8fc994
Fix TxIn parsing 2024-04-05 12:47:17 -05:00
f375467fee
Merge pull request 'Implement identification of transparent output' (#52) from rav001 into dev040
Reviewed-on: #52
2024-04-03 21:21:08 +00:00
09411adfff
Implement test to validate transparent outputs 2024-04-03 16:16:42 -05:00
2d39576dc8
Merge branch 'dev040' into rav001 2024-04-02 14:06:07 -05:00
938ccb4b97
Add test to identify transparent outputs (#50)
Reviewed-on: #50
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-04-02 19:03:50 +00:00
8b1965b46f
Merge branch 'dev040' into rav001 2024-04-02 14:03:11 -05:00
2f18c15c86
Add test to identify transparent outputs 2024-04-02 13:42:45 -05:00
204275a9b6
Merge pull request 'Implements FFI for transactions from Zebra' (#49) from rav001 into dev040
Reviewed-on: #49
2024-04-02 17:09:42 +00:00
98fb89b7b0
Merge branch 'dev040' into rav001 2024-04-02 11:36:14 -05:00
6ad879c155
Implements FFI for transaction deserialization 2024-04-02 11:23:05 -05:00
474aadb5cd
Merge pull request 'Update Zebra block deserialization for block time' (#48) from rvv040 into dev040
Reviewed-on: #48
2024-04-01 13:09:47 +00:00
93a04c09d3
Merge branch 'dev040' into rvv040 2024-03-31 06:43:17 -05:00
58b74a4c9a
Update getBlockTime to use HexString 2024-03-29 15:51:48 -05:00
dbae2150da
Advance bundle FFI 2024-03-29 13:54:21 -05:00
7cada685ce getBlockTime function added 2024-03-28 15:06:02 -04:00
4b064af4de
Merge pull request 'Implements parsing of transparent bundles' (#47) from rav001 into dev040
Reviewed-on: #47
2024-03-27 18:25:47 +00:00
52950885c1
Implements parsing of transparent bundles 2024-03-27 13:22:34 -05:00
899b79f155
Merge pull request 'Correct the parsing of OutPoint' (#46) from rav001 into dev040
Reviewed-on: #46
2024-03-27 14:05:17 +00:00
0fb02b2514
Correct parsing of OutPoint 2024-03-27 09:00:00 -05:00
1674f9b592
Merge branch 'dev040' into rav001 2024-03-26 15:40:11 -05:00
bb9d336dc3
Implements low-level transparent components (#45)
This PR includes components for the deserialization of low-level part of transparent components.

Reviewed-on: #45
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-26 20:39:31 +00:00
f593fefd7f
Add types for low-level transparent components 2024-03-26 15:37:04 -05:00
ee27860299
Merge branch 'dev040' into rav001 2024-03-26 09:56:38 -05:00
4e86a2f5a4
Zebra Raw Tx deserialization (#44)
Implements features to deserialize the hex representation of of a Zebra Transaction

Reviewed-on: #44
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-26 14:56:10 +00:00
921d34383a
Merge remote-tracking branch 'forge/rav001' into rav001 2024-03-26 09:53:17 -05:00
b0df0480c5
Implement Transaction hex deserialization 2024-03-26 09:50:49 -05:00
03d53aa303
Merge branch 'dev040' into rav001 2024-03-22 13:04:35 -05:00
f099544162
Account for missing response fields in Zebra response (#43)
This PR adds code to account for the missing `time` field in the Zebra response for blocks and raw transactions.

Reviewed-on: #43
Co-authored-by: pitmutt <rene@vergara.network>
Co-committed-by: pitmutt <rene@vergara.network>
2024-03-22 18:04:04 +00:00
07fa36ed7d
Merge branch 'dev040' into rav001 2024-03-22 18:03:45 +00:00
5b6ce3f29b
Account for missing block time field 2024-03-21 19:27:09 -05:00
aa10e09595
Implement Sapling spends (#42)
This PR add support for Sapling spends in the communication with Zebra.

Reviewed-on: #42
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-21 20:15:49 +00:00
d659368cff
Merge branch 'dev040' into rav001 2024-03-21 15:14:13 -05:00
9c8a851ead
Implement Sapling spends 2024-03-21 15:12:22 -05:00
d7752e9866
Improve response handling for Zebra RPC (#41)
This PR includes changes to handle differences between the `zebrad` and `zcashd` RPC.

Reviewed-on: #41
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-21 18:26:13 +00:00
69bce58345
Improve exception handling of Zebra calls 2024-03-21 12:52:45 -05:00
adc7150b81
Merge branch 'dev040' into rav001 2024-03-20 14:34:11 -05:00
3af235377b
Adapt response handling to Zebra (#40)
This PR allows for the Zebra behavior of not having a `result` field in the RPC response on error conditions.

Reviewed-on: #40
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-20 19:33:36 +00:00
517b736c9a
Allow for missing result in RPC response 2024-03-20 14:16:12 -05:00
d1eaf1de4d
Merge branch 'dev040' into rav001 2024-03-20 11:29:31 -05:00
1af152dc31
Upgrade Zebra call (#39)
Reviewed-on: #39
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-20 16:15:30 +00:00
e7050f03c0
Upgrade Zebra call 2024-03-20 11:13:02 -05:00
f228eff367
Merge pull request 'Improve dependency on Haskoin for downstream' (#38) from rav001 into dev040
Reviewed-on: #38
2024-03-15 17:30:15 +00:00
5a6f31573c
Merge branch 'dev040' into rav001 2024-03-15 17:29:59 +00:00
bc1ee2430a
Improve dependency on Haskoin for downstream 2024-03-15 12:26:28 -05:00
6e86f2caf0
Merge pull request 'Complete Unified Address generation' (#37) from rav001 into dev040
Reviewed-on: #37
2024-03-15 16:31:50 +00:00
d1b0436af2
Add documentation for new functions 2024-03-15 10:26:06 -05:00
d5c50d58c5
Merge branch 'rvv040' into rav001 2024-03-15 10:11:27 -05:00
c7c4d664dc
Remove duplicate import 2024-03-15 08:15:08 -05:00
0a98246855 Transparent fix 2 2024-03-14 17:47:09 -04:00
2c58d1260a Transparent address fix 2024-03-14 17:44:18 -04:00
5b08026102
Merge pull request 'Add Read instance to Phrase' (#36) from rav001 into dev040
Reviewed-on: #36
2024-03-14 18:14:37 +00:00
c93809489b
Add Read instance to Phrase 2024-03-14 13:12:18 -05:00
749472e515
Merge pull request 'Fix #34' (#35) from rav001 into dev040
Reviewed-on: #35
2024-03-14 18:04:47 +00:00
d0ba74c7a1
Fix #34 2024-03-14 13:02:02 -05:00
4963eea68b
Merge pull request 'Type safety improvements' (#33) from rav001 into dev040
Reviewed-on: #33
2024-03-14 17:42:17 +00:00
46a28128fd
Bump version 2024-03-14 12:39:31 -05:00
4cc4c37960
Improve type safety for Orchard 2024-03-14 12:35:13 -05:00
d2619123c0
Improve type safety for Sapling 2024-03-14 11:30:54 -05:00
23472ee1c4
Improve type safety for Seed and Phrase 2024-03-14 11:13:10 -05:00
8a293f4e79
Enable for internal/external Orchard receivers 2024-03-14 11:12:31 -05:00
5815c5c326 Merge with dev040 2024-03-13 15:37:23 -04:00
0dcf6d3e9a
Merge pull request 'Correct Sapling receiver generation' (#32) from rav001 into dev040
Reviewed-on: #32
2024-03-13 19:25:43 +00:00
6e1048cd4d
Adjust Transparent generators to use indices 2024-03-13 14:12:28 -05:00
c5feb10fbc
Update Sapling spending key with coin type 2024-03-13 12:50:39 -05:00
e69a26e984
Merge pull request 'Unified Address Generation tests' (#31) from rav001 into dev040
Reviewed-on: #31
2024-03-12 21:06:06 +00:00
4f20160c36
Enable Unified Address generation tests 2024-03-12 16:03:35 -05:00
5b6f5fa8e2
Upgrade HexString 2024-03-12 16:02:35 -05:00
1d59e8f5eb After merging with dev040 2024-03-12 15:57:43 -04:00
5db66dcf39
Adjust indexing of Sapling payment addresses 2024-03-12 12:22:05 -05:00
8d437105c9
Merge pull request 'Implement test for sequential address generation' (#30) from rav001 into dev040
Reviewed-on: #30
2024-03-11 21:18:03 +00:00
30c3827cab
Merge branch 'dev040' into rav001 2024-03-11 16:09:11 -05:00
ddaabcc5cd
Add test to check that Sapling receivers are unique 2024-03-11 15:48:27 -05:00
8baf27e988
Merge pull request 'Implement Sapling child key derivation' (#29) from rav001 into dev040
Reviewed-on: #29
2024-03-11 20:25:54 +00:00
89730a8219
Merge branch 'dev040' into rav001 2024-03-11 20:25:01 +00:00
db92dd7de7
Implement Sapling child key derivation 2024-03-11 15:23:29 -05:00
46efe9cd21 Commit first version of genSaplingInternalAddress function 2024-03-10 22:19:51 -04:00
4edd789a40
Merge pull request 'Add signature for internal Sapling address' (#28) from rav001 into dev040
Reviewed-on: #28
2024-03-10 15:21:48 +00:00
4443ffeec5
Add signature for internal Sapling address 2024-03-10 10:20:10 -05:00
9cfed00380
Merge pull request 'Sapling Spending keys and receivers' (#27) from rvv040 into dev040
Reviewed-on: #27
2024-03-10 15:07:09 +00:00
1e795dbcea
Merge remote-tracking branch 'forge/rvv040' into rvv040 2024-03-10 10:01:19 -05:00
1f58f111a6
Merge branch 'rav002' into rvv040 2024-03-10 09:44:27 -05:00
7538bbfa19
Revision of Sapling receiver logic 2024-03-10 07:47:26 -05:00
477817f37f Find_Address method implemented 2024-03-09 10:28:36 -05:00
a549c8be9a Merge branch 'dev040' into rvv040 2024-03-08 15:32:36 -05:00
54b1567011 Default Paymebt address and DiversifierIndex created
x
2024-03-08 14:46:41 -05:00
e25d759b5e
Merge pull request 'Allow for optional shielded receivers' (#25) from rav001 into dev040
Reviewed-on: #25
2024-03-08 19:45:02 +00:00
ff89bbdac6
Merge branch 'dev040' into rav001 2024-03-08 19:44:43 +00:00
d3cf05d00e
Update version 2024-03-08 13:42:18 -06:00
9c4e26c9f2
Implement initial changes for ZIP-320 Rev1 2024-03-08 13:35:37 -06:00
5c4b715a24
Merge pull request 'Update UnifiedAddress to use named types for receivers' (#24) from rav001 into dev040
Reviewed-on: #24
2024-03-08 19:12:19 +00:00
6e31d83963
Update UnifiedAddress to use named types for receivers 2024-03-08 13:09:13 -06:00
db5a694e7d
Merge pull request 'Implement QuickCheck tests for Orchard components' (#23) from rav001 into dev040
Reviewed-on: #23
2024-03-08 18:47:01 +00:00
6c2dfa02fa
Implement QuickCheck tests for Orchard components 2024-03-08 12:44:10 -06:00
47e3cf71cb
Merge pull request 'Implement generation of Orchard receiver' (#22) from rav001 into dev040
Reviewed-on: #22
2024-03-07 22:11:59 +00:00
b2f56941a4
Bump version 2024-03-07 16:07:50 -06:00
72e87577a7
Add generation of Orchard receivers 2024-03-07 16:06:33 -06:00
f1174751fc
Add new types for Spending Keys and Receivers 2024-03-07 16:05:59 -06:00
e371fcdb72
Merge pull request 'Add constants to library' (#21) from rav001 into dev040
Reviewed-on: #21
2024-03-06 21:37:04 +00:00
977f4e791d
Implement Unified HRP constants 2024-03-06 15:35:03 -06:00
b568ee5ff4
Pin dependencies 2024-03-06 15:02:48 -06:00
d118a83993
Add constants to library 2024-03-06 13:05:00 -06:00
0e6f7503d4 Sapling Extended Spemding Key generation from HDSedd (64 byte array) 2024-03-05 22:10:05 -05:00
dbccb23b45 Merge branch 'dev040' into rvv040
-- Include orchard Spending Key and new types for working with
	-- zcash network and keys
2024-03-05 17:16:27 -05:00
7b65d322e6 Commit 003 - before merging with dev040 - with orchard spending key 2024-03-05 17:01:17 -05:00
815b4f16b4
Merge pull request 'Add Orchard spending key functionality' (#20) from rav001 into dev040
Reviewed-on: #20
2024-03-05 21:13:14 +00:00
c13d321da5
Bump version 2024-03-05 15:09:57 -06:00
3822e9f2ff
Add tests for Orchard spending key 2024-03-05 15:09:35 -06:00
53716685a8
Add new types for constants for Zcash protocol 2024-03-05 14:44:19 -06:00
694ab8fd17
Add new Orchard spending key generation 2024-03-05 14:44:00 -06:00
f09c3c500b
Update versions of Zcash crates 2024-03-05 14:43:33 -06:00
9acbe5b98c
Fix compilation for Spending Key 2024-03-05 07:36:45 -06:00
a6c358cd5d Commit for debuggin process
Erros with Parameters for rustWrapperSaplingSpendingkey function
   x in Sapling.hs module
2024-03-04 18:46:39 -05:00
c1507f36e0
Merge pull request 'Implement UA encoding' (#18) from rav001 into dev040
Reviewed-on: #18
2024-03-04 18:01:38 +00:00
0b1d9e0920
Implement UA encoding per ZIP-316 2024-03-04 11:59:07 -06:00
53a5b62b6b
Correct casing on Rust code 2024-03-04 11:58:04 -06:00
2ae18463fc
Increase verbosity of Rust compile 2024-03-03 15:29:50 -06:00
97b338bddc Commit for revision... 2024-03-03 16:19:06 -05:00
3cc0e96c44
Rust updates for bech32 encode/decode 2024-03-03 08:23:48 -06:00
9a5ad756b8
Add Read implementation to UnifiedAddress 2024-03-02 07:53:48 -06:00
a52d2231f1
Merge pull request 'Correct type of blockheight' (#17) from rav001 into dev040
Reviewed-on: #17
2024-02-28 17:20:35 +00:00
cb44b6d4e0
Correct type for blockheight 2024-02-27 19:06:58 -06:00
67d6e85d05
Fix typo in cabal file 2024-02-26 08:57:12 -06:00
419f041ca9
Merge pull request 'Correct cabal versioning' (#16) from rav001 into dev040
Reviewed-on: #16
2024-02-26 14:51:12 +00:00
2ada9aac41
Correct cabal versioning 2024-02-26 08:49:47 -06:00
d0d9a1837b
Merge pull request 'Update .gitignore' (#15) from rav001 into dev040
Reviewed-on: #15
2024-02-25 23:53:17 +00:00
050c36e76d
Update .gitignore 2024-02-25 17:50:47 -06:00
ef93147f22
Merge pull request 'Update the installation settings for use by other packages' (#14) from rav001 into dev040
Reviewed-on: #14
2024-02-25 22:17:51 +00:00
105e0afc70
Merge branch 'dev040' into rav001 2024-02-25 22:17:03 +00:00
6e11ae7779
Update install instructions 2024-02-25 16:14:04 -06:00
6b870d91f8
Correct needed libraries 2024-02-25 16:11:10 -06:00
26b21e882b
Remove Makefile 2024-02-25 16:10:52 -06:00
c28addbfc3
Merge pull request 'Update installation package' (#13) from rav001 into dev040
Reviewed-on: #13
2024-02-25 21:36:30 +00:00
9713203e2b
Update installation package 2024-02-25 15:22:53 -06:00
75cc947dda
Merge pull request 'Fine tune the cabal configuration' (#12) from rav001 into dev040
Reviewed-on: #12
2024-02-23 01:29:24 +00:00
a3d6da12d7
Merge branch 'dev040' into rav001 2024-02-23 01:29:03 +00:00
ee7e32feb6
Remove flags 2024-02-21 20:32:36 -06:00
f818586b33
Set the Rust tool-chain 2024-02-21 19:33:28 -06:00
9d7a88be43
Add shared flag for cabal 2024-02-21 15:44:03 -06:00
3fa771f9f5
Merge pull request 'Add static flag for cabal' (#11) from rav001 into dev040
Reviewed-on: #11
2024-02-21 21:21:01 +00:00
faaa84caa6
Add static flag for cabal 2024-02-21 15:19:23 -06:00
4885d7525f
Merge pull request 'Implement custom build with cabal' (#10) from package into dev040
Reviewed-on: #10
2024-02-21 19:06:58 +00:00
c0e8fa85ce
Implement custom build with cabal 2024-02-21 10:51:03 -06:00
5c4786f1d5
Add tests for Seed and Phrase generation 2024-02-20 07:35:05 -06:00
f39838f24b
Pin the Rust nightly to avoid ahash error 2024-02-19 08:29:39 -06:00
73d8125b83
Merge pull request 'Add host parameter for Zebra nodes' (#9) from fix080 into dev040
Reviewed-on: #9
2024-02-14 14:22:16 +00:00
f95ebc7b00
Add host parameter for Zebra nodes 2024-02-14 08:19:34 -06:00
09cee9a064
Merge pull request 'Implement Zebra RPC calling functions' (#8) from fix080 into dev040
Reviewed-on: #8
2024-02-12 18:01:06 +00:00
75c95b03dc
Implement Zebra RPC calling functions 2024-02-12 11:55:42 -06:00
c4f345b1de
Merge pull request 'Implement Read instance' (#7) from fix080 into dev040
Reviewed-on: #7
2024-02-09 19:35:35 +00:00
49438bc99b
Merge branch 'dev040' into fix080 2024-02-09 19:35:12 +00:00
790ffec717
Update change log 2024-02-09 13:28:15 -06:00
88a5189eba
Add Read implementations 2024-02-09 13:24:34 -06:00
c91e23ab9c
Add function documentation 2024-02-09 13:23:58 -06:00
6ea8698ccb
Merge pull request 'Implement HexString' (#4) from fix080 into dev040
Reviewed-on: #4
2024-02-06 19:33:02 +00:00
c001fb5343
Implement HexString 2024-02-06 13:10:06 -06:00
d5728525ce
Update docs 2024-01-18 13:21:37 -06:00
beebabcf49
Update license to MIT 2024-01-18 12:55:23 -06:00
11a951f62a Add a new line character at the start of the script 2024-01-17 18:10:53 -05:00
0858b805d0
Update version 2024-01-17 07:45:27 -06:00
ca8010145b
Add functions to generate seed phrases and seeds 2024-01-16 16:15:05 -06:00
72e3700aa6
Merge pull request 'Encode transparent addresses' (#3) from dev021 into master
Reviewed-on: #3
2024-01-12 15:54:07 +00:00
dce171d830
Encode transparent addresses 2024-01-12 09:46:26 -06:00
29 changed files with 6173 additions and 1667 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
*~ *~
librustzcash-wrapper/target/ librustzcash-wrapper/target/
stack.yaml.lock stack.yaml.lock
dist-newstyle/

View file

@ -5,7 +5,307 @@ 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).
## [Unreleased] ## [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]
### Changed
- Modified the parsing of raw transactions for shielded outputs
- Upgraded to GHC 9.6.5
## [0.6.2.0]
### Changed
- Performance enhancement for transaction creation
## [0.6.1.1]
### Added
- Type for transaction creation errors
- Types for Sapling circuit parameters
- Function to create transaction
- Function to derive distinct transparent spending keys
### Changed
- Add `Read` instance for `Rseed`
## [0.6.1.0]
### Added
- Function to create a raw transaction
- New types for transaction creation:
- `Rseed`
- `TransparentTxSpend`
- `SaplingTxSpend`
- `OrchardTxSpend`
- `OutgoingNote`
- Rust crates:
- `secp256k1`
- `jubjub`
- `rand_core`
### Changed
- `DecodedNote` type now includes a field for `rho` and one for `rseed`
## [0.6.0.0]
### Added
- Rust crates:
- `sapling-crypto` 0.1.3
### Changed
- Modified handling of `ShieldedOutput`s based on new Rust crates
- Upgraded Rust crates:
- `orchard` to 0.7.1
- `zcash_primitives` to 0.14.0
- `zcash_client_backend` to 0.11.1
## [0.5.5.4]
### Added
- Functions to update Sapling witnesses.
- Functions to update Orchard witnesses.
## [0.5.5.3]
### Added
- Added function to generate an `ExchangeAddress` in Human Readable Format Using a `TransparentAddress` in HRF
- `encodeExchangeAddress` a function to create a `ExchangeAddress` in HRF
- `decodeExchangeAddress` a function to obtain a `TransparentAddress` object from an `ExchangeAddress` in HRF
- Added new type `ExchangeAddress`
### Fixed
- Orchard note nullifier calculation
- Sapling spend field parsing
## [0.5.5.2]
### Added
- Added function to encode a Sappling Address in Human Readable Format Using a SaplingReceiver
`encodeSaplingAddress` a zcash sapling address is returned or Nothing if the function fails
- Added decoding and encoding test
## [0.5.5.1]
### Added
- Added unction to decode a Sappling Address in Human Readable Format
`decodeSaplingAddress` returns 43 byte array containing
- Added a new Datatype `SaplingAddress`
- Added a new FFI function `rust_wrapper_decode_sapling_address` to haskell-rust interface
### Changed
- `TransparentAddress` type refactored
- `TransparentReceiver` added to replace old `TransparentAddress`
- `sha256` Function moved outside of `encodeTransparentReceiver`
## [0.5.5.0]
### Added
- Added unction to decode Transparent Address in Human Readable Format
### Changed
- `TransparentAddress` type refactored
- `TransparentReceiver` added to replace old `TransparentAddress`
- `sha256` Function moved outside of `encodeTransparentReceiver`
## [0.5.4.1]
### Added
- Functions to handle Sapling commitment trees, incremental witnesses and note positions
## [0.5.4.0]
### Added
- Function to decode Orchard actions with a spending key
- Functions for Bech32 encoding
- Function to encode a Sapling address
## [0.5.3.0]
### Added
- Function to decode Sapling outputs with a spending key
### Fixed
- Parsing of `TxIn` for FFI
## [0.5.2.0]
### Added
- Functionality to parse transparent bundles from Zebra
- Types for transparent `TxIn`, `TxOut`, `OutPoint`
## [0.5.1.0]
### Added
- Functionality to capture Sapling Spends
### Changed
- Modified the `makeZebraCall` function to handle errors explicitly
- Modified the RPC response to handle missing `result` field
## [0.5.0.1]
### Added
- Function to encode a human-readable transparent address
- Function to generate a seed phrase
- Implementations of `Read` for types
- Function to make RPC calls to `zebrad`
- Function to encode unified addresses from receivers
- Function to generate an Orchard spending key
- Constants for Zcash protocol
- Types for Spending Keys and Receivers for Sapling and Orchard
- Function to generate an Orchard receiver
- Function to generate a Sapling receiver
- Function to generate a Transparent receiver
### Changed
- Update installation to `cabal`
- Updated Rust crates:
- `bech32` to 0.11
- `orchard` to 0.7.0
- `zcash_note_encryption` to 0.4.0
- `zcash_primitives` to 0.13.0
- `zcash_client_backend` to 0.10.0
- `zip32` to 0.1.0
- Changed the `UnifiedAddress` to allow for optional shielded receivers
### Removed
- `Makefile`
## [0.3.0]
### Added
- Type to represent a transparent address/receiver
### Changed
- Full decoding of Unified Address
## [0.2.0]
### Added ### Added

View file

@ -1,157 +0,0 @@
# GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
<https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the
terms and conditions of version 3 of the GNU General Public License,
supplemented by the additional permissions listed below.
## 0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the
GNU General Public License.
"The Library" refers to a covered work governed by this License, other
than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
## 1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
## 2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
- a) under this License, provided that you make a good faith effort
to ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
- b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
## 3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from a
header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
- a) Give prominent notice with each copy of the object code that
the Library is used in it and that the Library and its use are
covered by this License.
- b) Accompany the object code with a copy of the GNU GPL and this
license document.
## 4. Combined Works.
You may convey a Combined Work under terms of your choice that, taken
together, effectively do not restrict modification of the portions of
the Library contained in the Combined Work and reverse engineering for
debugging such modifications, if you also do each of the following:
- a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
- b) Accompany the Combined Work with a copy of the GNU GPL and this
license document.
- c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
- d) Do one of the following:
- 0) Convey the Minimal Corresponding Source under the terms of
this License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
- 1) Use a suitable shared library mechanism for linking with
the Library. A suitable mechanism is one that (a) uses at run
time a copy of the Library already present on the user's
computer system, and (b) will operate properly with a modified
version of the Library that is interface-compatible with the
Linked Version.
- e) Provide Installation Information, but only if you would
otherwise be required to provide such information under section 6
of the GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the Application
with a modified version of the Linked Version. (If you use option
4d0, the Installation Information must accompany the Minimal
Corresponding Source and Corresponding Application Code. If you
use option 4d1, you must provide the Installation Information in
the manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.)
## 5. Combined Libraries.
You may place library facilities that are a work based on the Library
side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
- a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities, conveyed under the terms of this License.
- b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
## 6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
as you received it specifies that a certain numbered version of the
GNU Lesser General Public License "or any later version" applies to
it, you have the option of following the terms and conditions either
of that published version or of any later version published by the
Free Software Foundation. If the Library as you received it does not
specify a version number of the GNU Lesser General Public License, you
may choose any version of the GNU Lesser General Public License ever
published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View file

@ -1,675 +0,0 @@
# GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
<https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
## Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom
to share and change all versions of a program--to make sure it remains
free software for all its users. We, the Free Software Foundation, use
the GNU General Public License for most of our software; it applies
also to any other work released this way by its authors. You can apply
it to your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you
have certain responsibilities if you distribute copies of the
software, or if you modify it: responsibilities to respect the freedom
of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the
manufacturer can do so. This is fundamentally incompatible with the
aim of protecting users' freedom to change the software. The
systematic pattern of such abuse occurs in the area of products for
individuals to use, which is precisely where it is most unacceptable.
Therefore, we have designed this version of the GPL to prohibit the
practice for those products. If such problems arise substantially in
other domains, we stand ready to extend this provision to those
domains in future versions of the GPL, as needed to protect the
freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish
to avoid the special danger that patents applied to a free program
could make it effectively proprietary. To prevent this, the GPL
assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
## TERMS AND CONDITIONS
### 0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds
of works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of
an exact copy. The resulting work is called a "modified version" of
the earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user
through a computer network, with no transfer of a copy, is not
conveying.
An interactive user interface displays "Appropriate Legal Notices" to
the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
### 1. Source Code.
The "source code" for a work means the preferred form of the work for
making modifications to it. "Object code" means any non-source form of
a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users can
regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same
work.
### 2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey,
without conditions so long as your license otherwise remains in force.
You may convey covered works to others for the sole purpose of having
them make modifications exclusively for you, or provide you with
facilities for running those works, provided that you comply with the
terms of this License in conveying all material for which you do not
control copyright. Those thus making or running the covered works for
you must do so exclusively on your behalf, under your direction and
control, on terms that prohibit them from making any copies of your
copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the
conditions stated below. Sublicensing is not allowed; section 10 makes
it unnecessary.
### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such
circumvention is effected by exercising rights under this License with
respect to the covered work, and you disclaim any intention to limit
operation or modification of the work as a means of enforcing, against
the work's users, your or third parties' legal rights to forbid
circumvention of technological measures.
### 4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
### 5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these
conditions:
- a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
- b) The work must carry prominent notices stating that it is
released under this License and any conditions added under
section 7. This requirement modifies the requirement in section 4
to "keep intact all notices".
- c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
- d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
### 6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of
sections 4 and 5, provided that you also convey the machine-readable
Corresponding Source under the terms of this License, in one of these
ways:
- a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
- b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the Corresponding
Source from a network server at no charge.
- c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
- d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
- e) Convey the object code using peer-to-peer transmission,
provided you inform other peers where the object code and
Corresponding Source of the work are being offered to the general
public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal,
family, or household purposes, or (2) anything designed or sold for
incorporation into a dwelling. In determining whether a product is a
consumer product, doubtful cases shall be resolved in favor of
coverage. For a particular product received by a particular user,
"normally used" refers to a typical or common use of that class of
product, regardless of the status of the particular user or of the way
in which the particular user actually uses, or expects or is expected
to use, the product. A product is a consumer product regardless of
whether the product has substantial commercial, industrial or
non-consumer uses, unless such uses represent the only significant
mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to
install and execute modified versions of a covered work in that User
Product from a modified version of its Corresponding Source. The
information must suffice to ensure that the continued functioning of
the modified object code is in no case prevented or interfered with
solely because modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or
updates for a work that has been modified or installed by the
recipient, or for the User Product in which it has been modified or
installed. Access to a network may be denied when the modification
itself materially and adversely affects the operation of the network
or violates the rules and protocols for communication across the
network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
### 7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders
of that material) supplement the terms of this License with terms:
- a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
- b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
- c) Prohibiting misrepresentation of the origin of that material,
or requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
- d) Limiting the use for publicity purposes of names of licensors
or authors of the material; or
- e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
- f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions
of it) with contractual assumptions of liability to the recipient,
for any liability that these contractual assumptions directly
impose on those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions; the
above requirements apply either way.
### 8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
### 9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run
a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
### 10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
### 11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims owned
or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within the
scope of its coverage, prohibits the exercise of, or is conditioned on
the non-exercise of one or more of the rights that are specifically
granted under this License. You may not convey a covered work if you
are a party to an arrangement with a third party that is in the
business of distributing software, under which you make payment to the
third party based on the extent of your activity of conveying the
work, and under which the third party grants, to any of the parties
who would receive the covered work from you, a discriminatory patent
license (a) in connection with copies of the covered work conveyed by
you (or copies made from those copies), or (b) primarily for and in
connection with specific products or compilations that contain the
covered work, unless you entered into that arrangement, or that patent
license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
### 12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under
this License and any other pertinent obligations, then as a
consequence you may not convey it at all. For example, if you agree to
terms that obligate you to collect a royalty for further conveying
from those to whom you convey the Program, the only way you could
satisfy both those terms and this License would be to refrain entirely
from conveying the Program.
### 13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
### 14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions
of the GNU General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies that a certain numbered version of the GNU General Public
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that numbered version or
of any later version published by the Free Software Foundation. If the
Program does not specify a version number of the GNU General Public
License, you may choose any version ever published by the Free
Software Foundation.
If the Program specifies that a proxy can decide which future versions
of the GNU General Public License can be used, that proxy's public
statement of acceptance of a version permanently authorizes you to
choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
### 15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
### 16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
### 17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
## How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively state
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper
mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands \`show w' and \`show c' should show the
appropriate parts of the General Public License. Of course, your
program's commands might be different; for a GUI interface, you would
use an "about box".
You should also get your employer (if you work as a programmer) or
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. For more information on this, and how to apply and follow
the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your
program into proprietary programs. If your program is a subroutine
library, you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the
GNU Lesser General Public License instead of this License. But first,
please read <https://www.gnu.org/licenses/why-not-lgpl.html>.

22
LICENSE Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2022-2024 Vergara Technologies LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,31 +0,0 @@
# Copyright 2022-2024 Vergara Technologies LLC
#
# This file is part of Zcash-Haskell.
#
# Zcash-Haskell is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Zcash-Haskell is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
# You should have received a copy of the GNU Lesser General Public License along with
# Zcash-Haskell. If not, see <https://www.gnu.org/licenses/>.
rustlib := librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug
.PHONY: all
all: haskell
test: test/Spec.hs haskell
stack test
haskell: src/ZcashHaskell/Orchard.hs src/ZcashHaskell/Sapling.hs src/ZcashHaskell/Types.hs src/ZcashHaskell/Utils.hs src/C/Zcash.chs package.yaml stack.yaml $(rustlib)/rustzcash_wrapper.h $(rustlib)/librustzcash_wrapper.a $(rustlib)/librustzcash_wrapper.so $(rustlib)/rustzcash_wrapper-uninstalled.pc
stack build
$(rustlib)/rustzcash_wrapper.h: librustzcash-wrapper/src/lib.rs librustzcash-wrapper/Cargo.toml
cd librustzcash-wrapper && cargo +nightly cbuild

View file

@ -17,7 +17,10 @@ A Haskell library to interact with the Zcash blockchain.
``` ```
./configure ./configure
``` ```
- Compile the Rust and Haskell portions: `make` - Compile the Rust and Haskell portions:
```
cabal build
```
## Use ## Use

137
Setup.hs Normal file
View file

@ -0,0 +1,137 @@
import Control.Exception (throw)
import Control.Monad (forM_, when)
import Data.Maybe (fromMaybe)
import Distribution.PackageDescription
import Distribution.Simple
import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..), localPkgDescr)
import Distribution.Simple.PreProcess
import Distribution.Simple.Program.Find
( defaultProgramSearchPath
, findProgramOnSearchPath
)
import Distribution.Simple.Setup
import Distribution.Simple.Utils
( IODataMode(IODataModeBinary)
, maybeExit
, rawSystemStdInOut
)
import Distribution.Verbosity (Verbosity)
import qualified Distribution.Verbosity as Verbosity
import GHC.Generics
import System.Directory
( XdgDirectory(..)
, copyFile
, createDirectory
, createDirectoryIfMissing
, doesDirectoryExist
, doesFileExist
, getCurrentDirectory
, getDirectoryContents
, getHomeDirectory
, getXdgDirectory
)
import System.Environment
import System.FilePath ((</>))
import Text.Regex
import Text.Regex.Base
main :: IO ()
main = defaultMainWithHooks hooks
where
hooks =
simpleUserHooks
{ preConf =
\_ flags -> do
rsMake (fromFlag $ configVerbosity flags)
pure emptyHookedBuildInfo
, hookedPreProcessors = knownSuffixHandlers
, confHook = \a flags -> confHook simpleUserHooks a flags >>= rsAddDirs
, postClean = \_ flags _ _ -> rsClean (fromFlag $ cleanVerbosity flags)
}
rsFolder :: FilePath
rsFolder = "librustzcash-wrapper"
execCargo :: Verbosity -> String -> [String] -> IO ()
execCargo verbosity command args = do
cargoPath <-
findProgramOnSearchPath Verbosity.normal defaultProgramSearchPath "cargo"
dir <- getCurrentDirectory
let cargoExec =
case cargoPath of
Just (p, _) -> p
Nothing -> "cargo"
cargoArgs = command : args
workingDir = Just (dir </> rsFolder)
thirdComponent (_, _, c) = c
maybeExit . fmap thirdComponent $
rawSystemStdInOut
verbosity
cargoExec
cargoArgs
workingDir
Nothing
Nothing
IODataModeBinary
rsMake :: Verbosity -> IO ()
rsMake verbosity = do
execCargo verbosity "cbuild" []
rsAddDirs :: LocalBuildInfo -> IO LocalBuildInfo
rsAddDirs lbi' = do
localData <- getXdgDirectory XdgData "zcash-haskell"
createDirectoryIfMissing True localData
dir <- getCurrentDirectory
let rustIncludeDir =
dir </> rsFolder </> "target/x86_64-unknown-linux-gnu/debug"
rustLibDir = dir </> rsFolder </> "target/x86_64-unknown-linux-gnu/debug"
updateLbi lbi = lbi {localPkgDescr = updatePkgDescr (localPkgDescr lbi)}
updatePkgDescr pkgDescr =
pkgDescr {library = updateLib <$> library pkgDescr}
updateLib lib = lib {libBuildInfo = updateLibBi (libBuildInfo lib)}
updateLibBi libBuild =
libBuild
{ includeDirs = rustIncludeDir : includeDirs libBuild
, extraLibDirs = rustLibDir : extraLibDirs libBuild
}
copyDir rustLibDir localData
pure $ updateLbi lbi'
rsClean :: Verbosity -> IO ()
rsClean verbosity = execCargo verbosity "clean" []
cabalFlag :: FlagName -> ConfigFlags -> Bool
cabalFlag name =
fromMaybe False . lookupFlagAssignment name . configConfigurationsFlags
unlessFlagM :: FlagName -> ConfigFlags -> IO () -> IO ()
unlessFlagM name flags action
| cabalFlag name flags = pure ()
| otherwise = action
applyUnlessM :: FlagName -> ConfigFlags -> (a -> IO a) -> a -> IO a
applyUnlessM name flags apply a
| cabalFlag name flags = pure a
| otherwise = apply a
copyDir :: FilePath -> FilePath -> IO ()
copyDir src dst = do
whenM (not <$> doesDirectoryExist src) $
throw (userError "source does not exist")
--whenM (doesFileOrDirectoryExist dst) $
--throw (userError "destination already exists")
createDirectoryIfMissing True dst
content <- getDirectoryContents src
let xs = filter (`notElem` [".", ".."]) content
forM_ xs $ \name -> do
let srcPath = src </> name
let dstPath = dst </> name
isDirectory <- doesDirectoryExist srcPath
if isDirectory
then copyDir srcPath dstPath
else copyFile srcPath dstPath
where
doesFileOrDirectoryExist x = orM [doesDirectoryExist x, doesFileExist x]
orM xs = or <$> sequence xs
whenM s r = s >>= flip when r

13
cabal.project Normal file
View file

@ -0,0 +1,13 @@
packages: ./*.cabal
with-compiler: ghc-9.6.5
source-repository-package
type: git
location: https://git.vergara.tech/Vergara_Tech/haskell-foreign-rust.git
tag: 335e804454cd30da2c526457be37e477f71e4665
source-repository-package
type: git
location: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git
tag: 39d8da7b11a80269454c2f134a5c834e0f3cb9a7

208
cabal.project.freeze Normal file
View file

@ -0,0 +1,208 @@
active-repositories: hackage.haskell.org:merge
constraints: any.Cabal ==3.10.3.0,
any.Cabal-syntax ==3.10.3.0,
any.HUnit ==1.6.2.0,
any.OneTuple ==0.4.2,
any.QuickCheck ==2.14.3,
QuickCheck -old-random +templatehaskell,
any.StateVar ==1.2.2,
any.aeson ==2.2.3.0,
aeson +ordered-keymap,
any.alex ==3.5.1.0,
any.ansi-terminal ==1.1.1,
ansi-terminal -example,
any.ansi-terminal-types ==1.1,
any.appar ==0.1.8,
any.array ==0.5.6.0,
any.asn1-encoding ==0.9.6,
any.asn1-parse ==0.9.5,
any.asn1-types ==0.3.4,
any.assoc ==1.1.1,
assoc -tagged,
any.async ==2.2.5,
async -bench,
any.attoparsec ==0.14.4,
attoparsec -developer,
any.attoparsec-aeson ==2.2.2.0,
any.base ==4.18.2.1,
any.base-orphans ==0.9.2,
any.base16 ==1.0,
any.base16-bytestring ==1.0.2.0,
any.base58-bytestring ==0.1.0,
any.base64-bytestring ==1.2.1.0,
any.basement ==0.0.16,
any.bifunctors ==5.6.2,
bifunctors +tagged,
any.binary ==0.8.9.1,
any.binary-orphans ==1.0.5,
any.bitvec ==1.1.5.0,
bitvec +simd,
any.blaze-builder ==0.4.2.3,
any.borsh ==0.3.0,
any.byteorder ==1.0.4,
any.bytes ==0.17.3,
any.bytestring ==0.11.5.3,
any.c2hs ==0.28.8,
c2hs +base3 -regression,
any.call-stack ==0.4.0,
any.case-insensitive ==1.2.1.0,
any.cborg ==0.2.10.0,
cborg +optimize-gmp,
any.cereal ==0.5.8.3,
cereal -bytestring-builder,
any.character-ps ==0.1,
any.colour ==2.3.6,
any.comonad ==5.0.8,
comonad +containers +distributive +indexed-traversable,
any.conduit ==1.3.6,
any.conduit-extra ==1.3.6,
any.containers ==0.6.7,
any.contravariant ==1.5.5,
contravariant +semigroups +statevar +tagged,
any.cookie ==0.5.0,
any.crypton ==1.0.0,
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-x509 ==1.7.7,
any.crypton-x509-store ==1.6.9,
any.crypton-x509-system ==1.6.7,
any.crypton-x509-validation ==1.6.12,
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,
any.data-default ==0.7.1.1,
any.data-default-class ==0.1.2.0,
any.data-default-instances-containers ==0.0.1,
any.data-default-instances-dlist ==0.0.1,
any.data-default-instances-old-locale ==0.0.1,
any.data-fix ==0.3.4,
any.deepseq ==1.4.8.1,
any.directory ==1.3.8.4,
any.distributive ==0.6.2.1,
distributive +semigroups +tagged,
any.dlist ==1.0,
dlist -werror,
any.entropy ==0.4.1.10,
entropy -donotgetentropy,
any.envy ==2.1.3.0,
any.exceptions ==0.10.7,
any.filepath ==1.4.300.1,
any.foreign-rust ==0.1.0,
any.generically ==0.1.1,
any.generics-sop ==0.5.1.4,
any.ghc-bignum ==1.3,
any.ghc-boot-th ==9.6.5,
any.ghc-prim ==0.10.0,
any.half ==0.3.1,
any.happy ==2.0.2,
any.happy-lib ==2.0.2,
any.hashable ==1.4.7.0,
hashable -arch-native +integer-gmp -random-initial-seed,
any.haskell-lexer ==1.1.1,
any.haskoin-core ==1.1.0,
any.hexstring ==0.12.1.0,
any.hourglass ==0.2.12,
any.hsc2hs ==0.68.10,
hsc2hs -in-ghc-tree,
any.hspec ==2.11.9,
any.hspec-core ==2.11.9,
any.hspec-discover ==2.11.9,
any.hspec-expectations ==0.8.4,
any.http-client ==0.7.17,
http-client +network-uri,
any.http-client-tls ==0.3.6.3,
any.http-conduit ==2.3.9,
http-conduit +aeson,
any.http-types ==0.12.4,
any.indexed-traversable ==0.1.4,
any.indexed-traversable-instances ==0.1.2,
any.integer-conversion ==0.1.1,
any.integer-gmp ==1.1,
any.integer-logarithms ==1.0.3.1,
integer-logarithms -check-bounds +integer-gmp,
any.iproute ==1.7.14,
any.language-c ==0.9.3,
language-c -allwarnings +iecfpextension +usebytestrings,
any.memory ==0.18.0,
memory +support_bytestring +support_deepseq,
any.mime-types ==0.1.2.0,
any.mono-traversable ==1.0.20.0,
any.mtl ==2.3.1,
any.murmur3 ==1.0.5,
any.network ==3.2.4.0,
network -devel,
any.network-uri ==2.6.4.2,
any.old-locale ==1.0.0.7,
any.old-time ==1.1.0.4,
any.os-string ==2.0.6,
any.parsec ==3.1.16.1,
any.pem ==0.2.4,
any.pretty ==1.1.3.6,
any.primitive ==0.9.0.0,
any.process ==1.6.19.0,
any.quickcheck-io ==0.2.0,
any.quickcheck-transformer ==0.3.1.2,
any.random ==1.2.1.2,
any.regex-base ==0.94.0.2,
any.regex-compat ==0.95.2.1,
any.regex-posix ==0.96.0.1,
regex-posix -_regex-posix-clib,
any.resourcet ==1.3.0,
any.rts ==1.0.2,
any.safe ==0.3.21,
any.scientific ==0.3.8.0,
scientific -integer-simple,
any.secp256k1-haskell ==1.4.0,
any.semialign ==1.3.1,
semialign +semigroupoids,
any.semigroupoids ==6.0.1,
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
any.serialise ==0.2.6.1,
serialise +newtime15,
any.socks ==0.6.1,
any.sop-core ==0.5.0.2,
any.split ==0.2.5,
any.splitmix ==0.1.0.5,
splitmix -optimised-mixer,
any.stm ==2.5.1.0,
any.streaming-commons ==0.2.2.6,
streaming-commons -use-bytestring-builder,
any.strict ==0.5.1,
any.string-conversions ==0.4.0.1,
any.tagged ==0.8.8,
tagged +deepseq +transformers,
any.template-haskell ==2.20.0.0,
any.text ==2.0.2,
any.text-iso8601 ==0.1.1,
any.text-short ==0.1.6,
text-short -asserts,
any.tf-random ==0.5,
any.th-abstraction ==0.7.0.0,
any.th-compat ==0.1.5,
any.these ==1.2.1,
any.time ==1.12.2,
any.time-compat ==1.9.7,
any.tls ==2.1.0,
tls -devel,
any.transformers ==0.6.1.0,
any.transformers-compat ==0.7.2,
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
any.typed-process ==0.2.12.0,
any.unix ==2.8.4.0,
any.unix-time ==0.4.15,
any.unliftio-core ==0.2.1.0,
any.unordered-containers ==0.2.20,
unordered-containers -debug,
any.utf8-string ==1.0.2,
any.uuid-types ==1.0.6,
any.vector ==0.13.1.0,
vector +boundschecks -internalchecks -unsafechecks -wall,
any.vector-algorithms ==0.9.0.2,
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
any.vector-stream ==0.1.0.1,
any.void ==0.7.3,
void -safe,
any.wide-word ==0.1.6.0,
any.witherable ==0.5,
any.zlib ==0.7.1.0,
zlib -bundled-c-zlib +non-blocking-ffi +pkg-config
index-state: hackage.haskell.org 2024-10-11T12:55:31Z

2
configure vendored
View file

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
echo -e "\n"
echo "export PKG_CONFIG_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$PKG_CONFIG_PATH" | tee -a ~/.bashrc echo "export PKG_CONFIG_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$PKG_CONFIG_PATH" | tee -a ~/.bashrc
echo "export LD_LIBRARY_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$LD_LIBRARY_PATH" | tee -a ~/.bashrc echo "export LD_LIBRARY_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$LD_LIBRARY_PATH" | tee -a ~/.bashrc
source ~/.bashrc source ~/.bashrc

File diff suppressed because it is too large Load diff

View file

@ -4,19 +4,28 @@ version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
haskell-ffi.git = "https://github.com/BeFunctional/haskell-rust-ffi.git" 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.10"
bech32 = "0.9.1" bech32 = "0.11"
orchard = "0.4.0" orchard = "0.10.0"
zcash_note_encryption = "0.3.0" zcash_note_encryption = "0.4.0"
zcash_primitives = "0.11.0" zcash_primitives = { version = "0.19.0", features = ["transparent-inputs"]}
zcash_client_backend = "0.9.0" zcash_client_backend = "0.14.0"
sapling-crypto = "0.3"
zip32 = "0.1.2"
proc-macro2 = "1.0.66" proc-macro2 = "1.0.66"
nonempty = "0.7.0"
incrementalmerkletree = "0.7.0"
secp256k1 = "0.27.0"
jubjub = "0.10.0"
rand_core = { version = "0.6.4", features = ["getrandom"]}
wagyu-zcash-parameters = "0.2.0"
bip0039 = "0.12.0"
[features] [features]
capi = [] capi = []

View file

@ -0,0 +1,4 @@
[toolchain]
channel = "nightly-2024-02-04"
components = [ "rustfmt", "rustc-dev"]
profile = "minimal"

File diff suppressed because it is too large Load diff

View file

@ -1,52 +0,0 @@
name: zcash-haskell
version: 0.2.1
git: "https://git.vergara.tech/Vergara_Tech/zcash-haskell"
license: LGPL-3
author: "Rene Vergara"
maintainer: "pitmutt@vergara.tech"
copyright: "(c)2022-2024 Vergara Technologies LLC"
extra-source-files:
- README.md
- CHANGELOG.md
- configure
# Metadata used when publishing your package
synopsis: Utilities to interact with the Zcash blockchain
category: Blockchain
# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
dependencies:
- base >= 4.7 && < 5
library:
source-dirs: src
dependencies:
- bytestring
- borsh >= 0.2
- text
- foreign-rust
- generics-sop
- aeson
- http-conduit
pkg-config-dependencies:
- rustzcash_wrapper-uninstalled
tests:
zcash-haskell-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- zcash-haskell
- hspec
- bytestring
- text
- aeson

View file

@ -1,19 +1,7 @@
{- 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.
Zcash-Haskell is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
Zcash-Haskell is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
Zcash-Haskell. If not, see <https://www.gnu.org/licenses/>.
-} -}
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
@ -29,10 +17,11 @@ module C.Zcash where
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import Codec.Borsh import Codec.Borsh
import Data.Text (Text) import qualified Data.Text as T
import Data.Word import Data.Word
import Data.Int import Data.Int
import Data.Structured import Data.Structured
import Data.HexString (HexString(..))
import Foreign.C.Types import Foreign.C.Types
import Foreign.Rust.Marshall.External import Foreign.Rust.Marshall.External
import Foreign.Rust.Marshall.Fixed import Foreign.Rust.Marshall.Fixed
@ -43,6 +32,20 @@ import qualified Generics.SOP as SOP
import qualified GHC.Generics as GHC import qualified GHC.Generics as GHC
import ZcashHaskell.Types import ZcashHaskell.Types
{# fun unsafe rust_wrapper_bech32decode as rustWrapperBech32Decode
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer RawData'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_bech32m_encode as rustWrapperBech32mEncode
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer (T.Text)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble {# fun unsafe rust_wrapper_f4jumble as rustWrapperF4Jumble
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
@ -58,10 +61,11 @@ import ZcashHaskell.Types
-> `()' -> `()'
#} #}
{# fun pure unsafe rust_wrapper_ua_decode as rustWrapperIsUA {# fun unsafe rust_wrapper_ua_decode as rustWrapperUADecode
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer RawUA'&
} }
-> `Bool' -> `()'
#} #}
{# fun pure unsafe rust_wrapper_shielded_decode as rustWrapperIsShielded {# fun pure unsafe rust_wrapper_shielded_decode as rustWrapperIsShielded
@ -70,13 +74,6 @@ import ZcashHaskell.Types
-> `Bool' -> `Bool'
#} #}
{# fun unsafe rust_wrapper_bech32decode as rustWrapperBech32Decode
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer RawData'&
}
-> `()'
#}
{# fun pure unsafe rust_wrapper_svk_decode as rustWrapperSaplingVkDecode {# fun pure unsafe rust_wrapper_svk_decode as rustWrapperSaplingVkDecode
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
} }
@ -99,12 +96,23 @@ import ZcashHaskell.Types
{# fun unsafe rust_wrapper_sapling_note_decrypt_v2 as rustWrapperSaplingNoteDecode {# fun unsafe rust_wrapper_sapling_note_decrypt_v2 as rustWrapperSaplingNoteDecode
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
, toBorshVar* `BS.ByteString'& , toBorshVar* `ShieldedOutput'&
, getVarBuffer `Buffer DecodedNote'& , getVarBuffer `Buffer DecodedNote'&
} }
-> `()' -> `()'
#} #}
{# fun unsafe rust_wrapper_sapling_esk_decrypt as rustWrapperSaplingDecodeEsk
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `ShieldedOutput'&
, `Bool'
, `Bool'
, `Word64'
, getVarBuffer `Buffer DecodedNote'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_ufvk_decode as rustWrapperUfvkDecode {# fun unsafe rust_wrapper_ufvk_decode as rustWrapperUfvkDecode
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer UnifiedFullViewingKey'& , getVarBuffer `Buffer UnifiedFullViewingKey'&
@ -120,9 +128,285 @@ import ZcashHaskell.Types
-> `()' -> `()'
#} #}
{# fun unsafe rust_wrapper_tx_parse as rustWrapperTxParse {# fun unsafe rust_wrapper_orchard_note_decrypt_sk as rustWrapperOrchardNoteDecodeSK
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer [BS.ByteString]'& , toBorshVar* `OrchardAction'&
, `Bool'
, getVarBuffer `Buffer DecodedNote'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_tx_parse as rustWrapperTxParse
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer [ShieldedOutput]'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_tx_read as rustWrapperTxRead
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer RawZebraTx'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_gen_seed_phrase as rustWrapperGenSeedPhrase
{ getVarBuffer `Buffer Phrase'& } -> `()'
#}
{# fun unsafe rust_wrapper_recover_seed as rustWrapperGetSeed
{ toBorshVar* `Phrase'&
, getVarBuffer `Buffer Seed'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_sapling_spendingkey as rustWrapperSaplingSpendingkey
{ toBorshVar* `BS.ByteString'&
, `Word32'
, `Word32'
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_sapling_paymentaddress as rustWrapperSaplingPaymentAddress
{ toBorshVar* `BS.ByteString'&
, `Word32'
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_sapling_chgpaymentaddress as rustWrapperSaplingChgPaymentAddress
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_derive_orchard_spending_key as rustWrapperGenOrchardSpendKey
{ toBorshVar* `BS.ByteString'&
, `Word32'
, `Word32'
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_derive_orchard_receiver as rustWrapperGenOrchardReceiver
{ toBorshVar* `BS.ByteString'&
, `Word32'
, `Bool'
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_read_sapling_commitment_tree as rustWrapperReadSaplingCommitmentTree
{ toBorshVar* `SaplingFrontier'&
, toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer SaplingFrontier'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_read_sapling_witness as rustWrapperReadSaplingWitness
{ toBorshVar* `SaplingFrontier'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# fun pure unsafe rust_wrapper_read_sapling_position as rustWrapperReadSaplingPosition
{ toBorshVar* `BS.ByteString'&
}
-> `Word64'
#}
{# fun unsafe rust_wrapper_bech32_encode as rustWrapperBech32Encode
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer (T.Text)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_read_sapling_frontier as rustWrapperReadSaplingFrontier
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer SaplingFrontier'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_decode_sapling_address as rustWrapperDecodeSaplingAddress
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_read_sapling_node as rustWrapperReadSaplingNode
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_combine_sapling_nodes as rustWrapperCombineSaplingNodes
{ `Int8'
, toBorshVar* `BS.ByteString'&
, toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# 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'&
, 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'&
}
-> `()'
#}
{# fun pure unsafe rust_wrapper_read_orchard_position as rustWrapperReadOrchardPosition
{ toBorshVar* `BS.ByteString'&
}
-> `Word64'
#}
{# fun unsafe rust_wrapper_orchard_add_node as rustWrapperOrchardAddNodeTest
{ `Int8'
, toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_update_sapling_witness as rustWrapperUpdateSaplingWitness
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `[BS.ByteString]'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_update_orchard_witness as rustWrapperUpdateOrchardWitness
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `[BS.ByteString]'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_create_transaction as rustWrapperCreateTx
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `BS.ByteString'&
, toBorshVar* `[TransparentTxSpend]'&
, toBorshVar* `[SaplingTxSpend]'&
, toBorshVar* `[OrchardTxSpend]'&
, toBorshVar* `[OutgoingNote]'&
, `Bool'
, `Word64'
, `Bool'
, getVarBuffer `Buffer HexString'&
} }
-> `()' -> `()'
#} #}

38
src/ZcashHaskell/Keys.hs Normal file
View file

@ -0,0 +1,38 @@
-- Copyright 2022-2024 Vergara Technologies LLC
-- This file is part of Zcash-Haskell.
--
-- |
-- Module : ZcashHaskell.Keys
-- Copyright : 2022-2024 Vergara Technologies
-- License : MIT
--
-- Maintainer : pitmutt@vergara.tech
-- Stability : experimental
-- Portability : unknown
--
-- Functions to generate keys for the Zcash blockchain
--
module ZcashHaskell.Keys where
import C.Zcash (rustWrapperGenSeedPhrase, rustWrapperGetSeed)
import qualified Data.ByteString as BS
import qualified Data.Text as T
import Foreign.Rust.Marshall.Variable
( withBorshVarBuffer
, withPureBorshVarBuffer
)
import ZcashHaskell.Types (Phrase, Seed(..), ToBytes(..))
-- | Generate a random seed that can be used to generate private keys for shielded addresses and transparent addresses.
generateWalletSeedPhrase :: IO Phrase
generateWalletSeedPhrase = withBorshVarBuffer rustWrapperGenSeedPhrase
-- | Derive a cryptographic seed from the given seed phrase.
getWalletSeed :: Phrase -> Maybe Seed
getWalletSeed p =
if BS.length (getBytes result) > 0
then Just result
else Nothing
where
result :: Seed
result = (withPureBorshVarBuffer . rustWrapperGetSeed) p

View file

@ -1,24 +1,13 @@
{- Copyright 2022-2024 Vergara Technologies LLC {-# LANGUAGE OverloadedStrings #-}
This file is part of Zcash-Haskell. -- Copyright 2022-2024 Vergara Technologies LLC
--
Zcash-Haskell is free software: you can redistribute it and/or modify it -- This file is part of Zcash-Haskell.
under the terms of the GNU Lesser General Public License as published by the Free --
Software Foundation, either version 3 of the License, or (at your option) any
later version.
Zcash-Haskell is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
Zcash-Haskell. If not, see <https://www.gnu.org/licenses/>.
-}
-- | -- |
-- Module : ZcashHaskell.Orchard -- Module : ZcashHaskell.Orchard
-- Copyright : 2022-2024 Vergara Technologies -- Copyright : 2022-2024 Vergara Technologies
-- License : LGPL-3 -- License : MIT
-- --
-- Maintainer : rene@vergara.network -- Maintainer : rene@vergara.network
-- Stability : experimental -- Stability : experimental
@ -29,18 +18,135 @@
module ZcashHaskell.Orchard where module ZcashHaskell.Orchard where
import C.Zcash import C.Zcash
( rustWrapperIsUA ( rustWrapperCombineOrchardNodes
, rustWrapperGenOrchardReceiver
, rustWrapperGenOrchardSpendKey
, rustWrapperGetOrchardRootTest
, rustWrapperOrchardAddNodeTest
, rustWrapperOrchardCheck , rustWrapperOrchardCheck
, rustWrapperOrchardNoteDecode , rustWrapperOrchardNoteDecode
, rustWrapperOrchardNoteDecodeSK
, rustWrapperReadOrchardCommitmentTree
, rustWrapperReadOrchardFrontier
, rustWrapperReadOrchardNode
, rustWrapperReadOrchardPathAnchor
, rustWrapperReadOrchardPosition
, rustWrapperReadOrchardTreeAnchor
, rustWrapperReadOrchardTreeParts
, rustWrapperReadOrchardWitness
, rustWrapperReadOrchardWitnessAnchor
, rustWrapperUADecode
, rustWrapperUfvkDecode , rustWrapperUfvkDecode
, rustWrapperUpdateOrchardWitness
) )
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
import Data.HexString (HexString(..), fromRawBytes, toBytes)
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
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)
-- | Derives an Orchard spending key for the given seed and account ID
genOrchardSpendingKey ::
Seed -- ^ The cryptographic seed for the wallet
-> CoinType -- ^ The coin type constant
-> AccountId -- ^ The index of the account to be used
-> Maybe OrchardSpendingKey
genOrchardSpendingKey s coinType accountId =
if BS.length k /= 32
then Nothing
else Just $ OrchardSpendingKey k
where
k =
withPureBorshVarBuffer $
rustWrapperGenOrchardSpendKey
(getBytes s)
(getValue coinType)
(fromIntegral accountId)
-- | Derives an Orchard receiver for the given spending key and index
genOrchardReceiver ::
Int -- ^ The index of the address to be created
-> Scope -- ^ `External` for wallet addresses, `Internal` for change addresses
-> OrchardSpendingKey -- ^ The spending key
-> Maybe OrchardReceiver
genOrchardReceiver i scope osk =
if BS.length k /= 43
then Nothing
else Just $ OrchardReceiver k
where
k =
withPureBorshVarBuffer $
rustWrapperGenOrchardReceiver
(getBytes osk)
(fromIntegral i)
(scope == External)
-- | Checks if given bytestring is a valid encoded unified address -- | Checks if given bytestring is a valid encoded unified address
isValidUnifiedAddress :: BS.ByteString -> Bool isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress
isValidUnifiedAddress = rustWrapperIsUA isValidUnifiedAddress str =
case raw_net decodedAddress of
0 -> Nothing
_ -> Just $ makeUA decodedAddress
where
decodedAddress = (withPureBorshVarBuffer . rustWrapperUADecode) str
whichNet =
case raw_net decodedAddress of
1 -> MainNet
2 -> TestNet
3 -> RegTestNet
makeUA x =
UnifiedAddress
whichNet
(if BS.length (raw_o x) == 43
then Just $ OrchardReceiver (raw_o x)
else Nothing)
(if BS.length (raw_s x) == 43
then Just $ SaplingReceiver (raw_s x)
else Nothing)
(if BS.length (raw_t x) > 1
then Just $ TransparentReceiver P2PKH (fromRawBytes $ raw_t x)
else if BS.length (raw_to x) > 1
then Just $ TransparentReceiver P2SH (fromRawBytes $ raw_to x)
else Nothing)
-- | Encode a 'UnifiedAddress' per [ZIP-316](https://zips.z.cash/zip-0316)
encodeUnifiedAddress :: UnifiedAddress -> T.Text
encodeUnifiedAddress ua = encodeBech32m (E.encodeUtf8 hr) b
where
hr =
case ua_net ua of
MainNet -> uniPaymentAddressHrp
TestNet -> uniTestPaymentAddressHrp
b = f4Jumble $ tReceiver <> sReceiver <> oReceiver <> padding
tReceiver =
case t_rec ua of
Nothing -> BS.empty
Just t ->
case tr_type t of
P2SH -> packReceiver 0x01 $ Just $ toBytes $ tr_bytes t
P2PKH -> packReceiver 0x00 $ Just $ toBytes $ tr_bytes t
sReceiver = packReceiver 0x02 $ getBytes <$> s_rec ua
oReceiver = packReceiver 0x03 $ getBytes <$> o_rec ua
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
-- | Attempts to decode the given bytestring into a Unified Full Viewing Key -- | Attempts to decode the given bytestring into a Unified Full Viewing Key
decodeUfvk :: BS.ByteString -> Maybe UnifiedFullViewingKey decodeUfvk :: BS.ByteString -> Maybe UnifiedFullViewingKey
@ -66,3 +172,168 @@ decryptOrchardAction key encAction =
decodedAction = decodedAction =
withPureBorshVarBuffer $ withPureBorshVarBuffer $
rustWrapperOrchardNoteDecode (o_key key) encAction rustWrapperOrchardNoteDecode (o_key key) encAction
getSaplingFromUA :: BS.ByteString -> Maybe T.Text
getSaplingFromUA uadd = do
let a = isValidUnifiedAddress uadd
case a of
Nothing -> Nothing
Just a -> do
let sraw = s_rec a
case sraw of
Nothing -> Nothing
Just sraw -> do
let net = ua_net a
case net of
MainNet ->
Just $ encodeBech32 (C.pack sapPaymentAddressHrp) (getBytes sraw)
TestNet ->
Just $
encodeBech32 (C.pack sapTestPaymentAddressHrp) (getBytes sraw)
-- | Attemtps to decode the given @OrchardAction@ using the given @OrchardSpendingKey@
decryptOrchardActionSK ::
OrchardSpendingKey -> Scope -> OrchardAction -> Maybe DecodedNote
decryptOrchardActionSK sk scope oa =
case a_value decodedAction of
0 -> Nothing
_ -> Just decodedAction
where
decodedAction =
withPureBorshVarBuffer $
rustWrapperOrchardNoteDecodeSK (getBytes sk) oa (scope == External)
getOrchardFrontier :: OrchardCommitmentTree -> Maybe OrchardFrontier
getOrchardFrontier tree =
if of_pos updatedTree > 1
then Just updatedTree
else Nothing
where
updatedTree =
withPureBorshVarBuffer $
rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree
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
getOrchardWitness :: OrchardFrontier -> Maybe OrchardWitness
getOrchardWitness tree =
if BS.length (hexBytes wit) > 1
then Just $ OrchardWitness wit
else Nothing
where
wit = withPureBorshVarBuffer $ rustWrapperReadOrchardWitness tree
-- | Get the Sapling note position from a witness
getOrchardNotePosition :: OrchardWitness -> Integer
getOrchardNotePosition =
fromIntegral . rustWrapperReadOrchardPosition . hexBytes . orchWit
-- | Update the witness of an Orchard note
updateOrchardWitness :: OrchardWitness -> [HexString] -> OrchardWitness
updateOrchardWitness wit cmus =
if not (null cmus)
then OrchardWitness $
withPureBorshVarBuffer $
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

View file

@ -1,61 +1,74 @@
{- 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.
--
Zcash-Haskell is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
Zcash-Haskell is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
Zcash-Haskell. If not, see <https://www.gnu.org/licenses/>.
-}
{-# LANGUAGE OverloadedStrings #-}
-- | -- |
-- Module : ZcashHaskell.Sapling -- Module : ZcashHaskell.Sapling
-- Copyright : 2022-2024 Vergara Technologies -- Copyright : 2022-2024 Vergara Technologies
-- License : LGPL-3 -- License : MIT
-- --
-- Maintainer : rene@vergara.network -- Maintainer : pitmutt@vergara.tech
-- Stability : experimental -- Stability : experimental
-- Portability : unknown -- Portability : unknown
-- --
-- Functions to interact with the Sapling shielded pool of the Zcash blockchain. -- Functions to interact with the Sapling shielded pool of the Zcash blockchain.
-- --
{-# LANGUAGE OverloadedStrings #-}
module ZcashHaskell.Sapling where module ZcashHaskell.Sapling where
import C.Zcash import C.Zcash
( rustWrapperIsShielded ( rustWrapperCombineSaplingNodes
, rustWrapperDecodeSaplingAddress
, rustWrapperGetSaplingRootTest
, rustWrapperIsShielded
, rustWrapperReadSaplingCommitmentTree
, rustWrapperReadSaplingFrontier
, rustWrapperReadSaplingNode
, rustWrapperReadSaplingPathAnchor
, rustWrapperReadSaplingPosition
, rustWrapperReadSaplingTreeAnchor
, rustWrapperReadSaplingTreeParts
, rustWrapperReadSaplingWitness
, rustWrapperSaplingCheck , rustWrapperSaplingCheck
, rustWrapperSaplingChgPaymentAddress
, rustWrapperSaplingDecodeEsk
, rustWrapperSaplingNoteDecode , rustWrapperSaplingNoteDecode
, rustWrapperSaplingPaymentAddress
, rustWrapperSaplingSpendingkey
, rustWrapperSaplingVkDecode , rustWrapperSaplingVkDecode
, rustWrapperTxParse , rustWrapperTxParse
, rustWrapperUpdateSaplingWitness
) )
import Data.Aeson import Data.Aeson
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import Foreign.Rust.Marshall.Variable (withPureBorshVarBuffer) import qualified Data.ByteString.Char8 as C
import ZcashHaskell.Types import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
( DecodedNote(..) import Data.Int (Int8)
, RawData(..) import qualified Data.Text as T
, RawTxResponse(..) import Data.Word
, ShieldedOutput(..) import Foreign.Rust.Marshall.Variable
, decodeHexText ( withPureBorshVarBuffer
, withPureBorshVarBuffer
) )
import ZcashHaskell.Utils (decodeBech32) import ZcashHaskell.Types
import ZcashHaskell.Utils (decodeBech32, encodeBech32, encodeBech32m)
-- | Check if given bytesting is a valid encoded shielded address -- | Check if given bytesting is a valid encoded shielded address
isValidShieldedAddress :: BS.ByteString -> Bool isValidShieldedAddress :: BS.ByteString -> Bool
isValidShieldedAddress = rustWrapperIsShielded isValidShieldedAddress = rustWrapperIsShielded
getShieldedOutputs :: BS.ByteString -> [BS.ByteString] getShieldedOutputs :: HexString -> [ShieldedOutput]
getShieldedOutputs t = withPureBorshVarBuffer $ rustWrapperTxParse t getShieldedOutputs t = withPureBorshVarBuffer $ rustWrapperTxParse $ toBytes t
serializeShieldedOutput :: ShieldedOutput -> BS.ByteString
serializeShieldedOutput so =
hexBytes . fromText $
toText (s_cv so) <>
toText (s_cmu so) <>
toText (s_ephKey so) <>
toText (s_encCipherText so) <>
toText (s_outCipherText so) <> toText (s_proof so)
-- | Check if given bytestring is a valid Sapling viewing key -- | Check if given bytestring is a valid Sapling viewing key
isValidSaplingViewingKey :: BS.ByteString -> Bool isValidSaplingViewingKey :: BS.ByteString -> Bool
@ -71,7 +84,7 @@ matchSaplingAddress :: BS.ByteString -> BS.ByteString -> Bool
matchSaplingAddress = rustWrapperSaplingCheck matchSaplingAddress = rustWrapperSaplingCheck
-- | Attempt to decode the given raw tx with the given Sapling viewing key -- | Attempt to decode the given raw tx with the given Sapling viewing key
decodeSaplingOutput :: BS.ByteString -> BS.ByteString -> Maybe DecodedNote decodeSaplingOutput :: BS.ByteString -> ShieldedOutput -> Maybe DecodedNote
decodeSaplingOutput key out = decodeSaplingOutput key out =
case a_value decodedAction of case a_value decodedAction of
0 -> Nothing 0 -> Nothing
@ -89,13 +102,18 @@ instance FromJSON RawTxResponse where
ht <- obj .: "height" ht <- obj .: "height"
c <- obj .: "confirmations" c <- obj .: "confirmations"
b <- obj .: "blocktime" b <- obj .: "blocktime"
sSpend <- obj .: "vShieldedSpend"
sOut <- obj .: "vShieldedOutput"
case o of case o of
Nothing -> Nothing ->
pure $ pure $
RawTxResponse RawTxResponse
i i
(decodeHexText h) h
(getShieldedOutputs (decodeHexText h)) sSpend
(if not (null (sOut :: [Object]))
then getShieldedOutputs h
else [])
[] []
ht ht
c c
@ -105,9 +123,198 @@ instance FromJSON RawTxResponse where
pure $ pure $
RawTxResponse RawTxResponse
i i
(decodeHexText h) h
(getShieldedOutputs (decodeHexText h)) sSpend
(if not (null sOut)
then getShieldedOutputs h
else [])
a a
ht ht
c c
b b
-- | Attempt to decode the given raw tx with the given Sapling spending key
decodeSaplingOutputEsk ::
SaplingSpendingKey
-> ShieldedOutput
-> ZcashNet
-> Scope
-> Integer
-> Maybe DecodedNote
decodeSaplingOutputEsk key out znet scope pos =
case a_value decodedAction of
0 -> Nothing
_ -> Just decodedAction
where
decodedAction =
withPureBorshVarBuffer $
rustWrapperSaplingDecodeEsk
(getBytes key)
out
(scope == External)
(znet == MainNet)
(fromIntegral pos)
-- | Attempts to obtain a sapling SpendingKey using a HDSeed
genSaplingSpendingKey :: Seed -> CoinType -> Int -> Maybe SaplingSpendingKey
genSaplingSpendingKey seed c i = do
if BS.length res == 169
then Just $ SaplingSpendingKey res
else Nothing
where
res =
withPureBorshVarBuffer
(rustWrapperSaplingSpendingkey
(getBytes seed)
(fromIntegral $ getValue c)
(fromIntegral i))
-- | Attempts to generate a sapling Payment Address using an ExtendedSpendingKey and a Diversifier Index
genSaplingPaymentAddress :: Int -> SaplingSpendingKey -> Maybe SaplingReceiver
genSaplingPaymentAddress i extspk =
if BS.length res == 43
then Just $ SaplingReceiver res
else Nothing
where
res =
withPureBorshVarBuffer
(rustWrapperSaplingPaymentAddress
(getBytes extspk)
(fromIntegral (i * 111)))
-- | Generate an internal Sapling address
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingReceiver
genSaplingInternalAddress sk =
if BS.length res == 43
then Just $ SaplingReceiver res
else Nothing
where
res =
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
getSaplingNodeValue :: BS.ByteString -> Maybe HexString
getSaplingNodeValue cmu =
if BS.length (hexBytes n) > 1
then Just n
else Nothing
where
n = withPureBorshVarBuffer $ rustWrapperReadSaplingNode cmu
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
where
updatedTree =
withPureBorshVarBuffer $
rustWrapperReadSaplingFrontier $ toBytes $ sapTree tree
-- | Update a Sapling commitment tree
updateSaplingCommitmentTree ::
SaplingFrontier -- ^ the base tree
-> HexString -- ^ the new note commitment
-> Maybe SaplingFrontier
updateSaplingCommitmentTree tree cmu =
if sf_pos updatedTree > 1
then Just updatedTree
else Nothing
where
updatedTree =
withPureBorshVarBuffer $
rustWrapperReadSaplingCommitmentTree tree (hexBytes cmu)
-- | Get the Sapling incremental witness from a commitment tree
getSaplingWitness :: SaplingFrontier -> Maybe SaplingWitness
getSaplingWitness tree =
if BS.length (hexBytes wit) > 1
then Just $ SaplingWitness wit
else Nothing
where
wit = withPureBorshVarBuffer $ rustWrapperReadSaplingWitness tree
-- | Get the Sapling note position from a witness
getSaplingNotePosition :: SaplingWitness -> Integer
getSaplingNotePosition =
fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit
updateSaplingWitness :: SaplingWitness -> [HexString] -> SaplingWitness
updateSaplingWitness wit cmus =
if not (null cmus)
then SaplingWitness $
withPureBorshVarBuffer $
rustWrapperUpdateSaplingWitness
(toBytes $ sapWit wit)
(map toBytes cmus)
else wit
-- | Encode a SaplingReceiver into HRF text
encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text
encodeSaplingAddress net sr = do
case net of
MainNet -> Just $ encodeBech32 (C.pack sapPaymentAddressHrp) (getBytes sr)
TestNet ->
Just $ encodeBech32 (C.pack sapTestPaymentAddressHrp) (getBytes sr)
-- | Helper to get de Nework Id from FFI response
getNetId :: [Word8] -> ZcashNet
getNetId [x] = do
case x of
1 -> MainNet
2 -> TestNet
-- | decode a Sapling address
decodeSaplingAddress :: BS.ByteString -> Maybe SaplingAddress
decodeSaplingAddress sapling_address = do
if BS.length sa > 1
then do
let sa0 = BS.unpack sa
Just $
SaplingAddress (getNetId (take 1 sa0)) $
SaplingReceiver (BS.pack (drop 1 sa0))
else Nothing
where
sa =
withPureBorshVarBuffer $ rustWrapperDecodeSaplingAddress sapling_address

View file

@ -0,0 +1,214 @@
{-# LANGUAGE OverloadedStrings #-}
-- Copyright 2022-2024 Vergara Technologies LLC
--
-- This file is part of Zcash-Haskell.
--
-- |
-- Module : ZcashHaskell.Transparent
-- Copyright : 2022-2024 Vergara Technologies
-- License : MIT
--
-- Maintainer : pitmutt@vergara.tech
-- Stability : experimental
-- Portability : unknown
--
-- Functions to interact with the transparent addresses in the Zcash blockchain
--
module ZcashHaskell.Transparent where
import Control.Exception (throwIO)
import Crypto.Hash
import Crypto.Secp256k1
import qualified Data.ByteArray as BA
import qualified Data.ByteString as BS
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
import qualified Data.ByteString.Char8 as BC
import Data.Char (chr)
import Data.HexString
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import Data.Word
import Haskoin.Address (Address(..))
import qualified Haskoin.Crypto.Hash as H
import Haskoin.Crypto.Keys.Extended
import ZcashHaskell.Types
-- ( AccountId
-- , CoinType(..)
-- , Scope(..)
-- , Seed(..)
-- , ToBytes(..)
-- , TransparentAddress(..)
-- , TransparentReceiver(..)
-- , TransparentSpendingKey(..)
-- , TransparentType(..)
-- , ZcashNet(..)
-- , getTransparentPrefix
-- , getValue
-- )
import ZcashHaskell.Utils (decodeBech32, encodeBech32m)
-- | Required for `TransparentReceiver` encoding and decoding
sha256 :: BS.ByteString -> BS.ByteString
sha256 bs = BA.convert (hash bs :: Digest SHA256)
-- | Encodes a `TransparentReceiver` into the human-readable format per the Zcash Protocol section 5.6.1.1
encodeTransparentReceiver ::
ZcashNet -- ^ The network, `MainNet` or `TestNet`
-> TransparentReceiver -- ^ The address to encode
-> T.Text
encodeTransparentReceiver zNet t =
encodeTransparent' (getTransparentPrefix zNet (tr_type t)) $
toBytes $ tr_bytes t
where
encodeTransparent' :: (Word8, Word8) -> BS.ByteString -> T.Text
encodeTransparent' (a, b) h =
E.decodeUtf8 $ encodeBase58 bitcoinAlphabet $ digest <> BS.take 4 checksum
where
digest = BS.pack [a, b] <> h
checksum = sha256 $ sha256 digest
-- | Generate an Extended Private Key from a known HDSeed.
genTransparentPrvKey ::
Seed -- ^ The cryptographic seed of the wallet
-> CoinType -- ^ The coin type constant to be used
-> AccountId -- ^ The index of the account to be used
-> IO TransparentSpendingKey
genTransparentPrvKey hdseed ctype accid = do
let coin = getValue ctype
ioCtx <- createContext
let path = Deriv :| 44 :| coin :| fromIntegral accid :: DerivPath
let prvKey = makeXPrvKey $ getBytes hdseed
return $ derivePath ioCtx path prvKey
-- | Generate a transparent receiver
genTransparentReceiver ::
Int -- ^ The index of the address to be created
-> Scope -- ^ `External` for wallet addresses or `Internal` for change addresses
-> XPrvKey -- ^ The transparent private key
-> IO TransparentReceiver
genTransparentReceiver i scope xprvk = do
ioCtx <- createContext
let s =
case scope of
External -> 0
Internal -> 1
let path = Deriv :/ s :/ fromIntegral i :: DerivPath
let childPrvKey = derivePath ioCtx path xprvk
let childPubKey = deriveXPubKey ioCtx childPrvKey
let x = xPubAddr ioCtx childPubKey
case x of
PubKeyAddress k -> return $ TransparentReceiver P2PKH $ fromBinary k
ScriptAddress j -> return $ TransparentReceiver P2SH $ fromBinary j
_anyOtherKind -> throwIO $ userError "Unsupported transparent address type"
-- | Generate a transparent receiver
genTransparentSecretKey ::
Int -- ^ The index of the address to be created
-> Scope -- ^ `External` for wallet addresses or `Internal` for change addresses
-> XPrvKey -- ^ The transparent private key
-> IO TransparentSpendingKey
genTransparentSecretKey i scope xprvk = do
ioCtx <- createContext
let s =
case scope of
External -> 0
Internal -> 1
let path = Deriv :/ s :/ fromIntegral i :: DerivPath
return $ derivePath ioCtx path xprvk
-- | decode a Transparent Address in HRF and return a TransparentAddress object
decodeTransparentAddress :: BS.ByteString -> Maybe TransparentAddress
decodeTransparentAddress taddress = do
if BS.length taddress < 34
then Nothing -- Not a valid transparent address
else do
let maybeDecoded = decodeBase58 bitcoinAlphabet taddress
case maybeDecoded of
Nothing -> Nothing
Just decoded -> do
let digest = BS.take 22 decoded
let chksum = BS.drop 22 decoded
let chksumd = BS.take 4 (sha256 $ sha256 digest)
if chksum /= chksumd
then Nothing -- Invalid address ( invalid checksum )
-- build the TransparentAddress Object
else do
let addressType = BS.take 2 digest
let transparentReceiver = BS.drop 2 digest
let fb = BS.index addressType 0
let sb = BS.index addressType 1
case fb of
28 ->
case sb of
189 ->
Just $
TransparentAddress MainNet $
TransparentReceiver
P2SH
(fromRawBytes transparentReceiver)
186 ->
Just $
TransparentAddress TestNet $
TransparentReceiver
P2SH
(fromRawBytes transparentReceiver)
184 ->
Just $
TransparentAddress MainNet $
TransparentReceiver
P2PKH
(fromRawBytes transparentReceiver)
_ -> Nothing
29 ->
if sb == 37
then Just $
TransparentAddress TestNet $
TransparentReceiver
P2PKH
(fromRawBytes transparentReceiver)
else Nothing
_ -> Nothing
-- | Encode an Exchange Addresss into HRF from TransparentReceiver
encodeExchangeAddress :: ZcashNet -> TransparentReceiver -> Maybe T.Text
encodeExchangeAddress net tr = do
case tr_type tr of
P2PKH -> do
case net of
MainNet -> do
let vhash = encodeBech32m "tex" (toBytes (tr_bytes tr))
Just vhash
TestNet -> do
let vhash = encodeBech32m "textest" (toBytes (tr_bytes tr))
Just vhash
_any -> Nothing
-- | Decode an Exchange Address into a ExchangeAddress
decodeExchangeAddress :: BS.ByteString -> Maybe ExchangeAddress
decodeExchangeAddress ex = do
if BS.length ex > 1
then do
let rawd = decodeBech32 ex
let tMain = "tex"
let tTest = "textest"
let tFail = "fail"
let hr = hrp rawd
if hr /= tFail
then do
let transparentReceiver = bytes rawd
if hr == tMain
then Just $
ExchangeAddress MainNet $
TransparentReceiver P2PKH (fromRawBytes transparentReceiver)
else do
if hr == tTest
then Just $
ExchangeAddress TestNet $
TransparentReceiver
P2PKH
(fromRawBytes transparentReceiver)
else Nothing
else Nothing
else Nothing

View file

@ -1,69 +1,222 @@
{- 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.
--
Zcash-Haskell is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
Zcash-Haskell is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
Zcash-Haskell. If not, see <https://www.gnu.org/licenses/>.
-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverloadedStrings #-}
-- | -- |
-- Module : ZcashHaskell.Types -- Module : ZcashHaskell.Types
-- Copyright : Vergara Technologies 2023 -- Copyright : 2022-2024 Vergara Technologies
-- License : BOSL -- License : MIT
-- --
-- Maintainer : rene@vergara.network -- Maintainer : pitmutt@vergara.tech
-- Stability : experimental -- Stability : experimental
-- Portability : unknown -- Portability : unknown
-- --
-- The types used by the ZcashHaskell library to interact with the Zcash blockchain -- The types used by the ZcashHaskell library to interact with the Zcash blockchain
-- --
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module ZcashHaskell.Types where module ZcashHaskell.Types where
import Codec.Borsh import Codec.Borsh
import Crypto.Hash
import Data.Aeson import Data.Aeson
import qualified Data.ByteArray as BA
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.UTF8 as US
import qualified Data.ByteString.Short as BS (ShortByteString, toShort)
import Data.HexString
import Data.Int import Data.Int
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.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
import Haskoin.Address (Address)
import qualified Haskoin.Crypto.Hash as H (Hash256(..))
import Haskoin.Crypto.Keys.Extended (XPrvKey)
import qualified Haskoin.Transaction.Common as H
-- * General -- * General
--
-- | A seed for generating private keys
newtype Seed =
Seed BS.ByteString
deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct Seed
instance ToBytes Seed where
getBytes (Seed x) = x
-- | A mnemonic phrase used to derive seeds
newtype Phrase =
Phrase C.ByteString
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 Phrase
instance ToBytes Phrase where
getBytes (Phrase x) = x
-- | Scope for addresses/receivers
data Scope
= External -- ^ Addresses used publically to receive payments
| Internal -- ^ Addresses used internally by wallets for change and shielding
deriving (Eq, Prelude.Show, Read)
-- | Type to represent data after Bech32 decoding -- | Type to represent data after Bech32 decoding
data RawData = RawData data RawData = RawData
{ hrp :: BS.ByteString -- ^ Human-readable part of the Bech32 encoding { hrp :: !BS.ByteString -- ^ Human-readable part of the Bech32 encoding
, bytes :: BS.ByteString -- ^ Decoded bytes , bytes :: !BS.ByteString -- ^ Decoded bytes
} deriving stock (Prelude.Show, GHC.Generic) } deriving stock (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)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawData deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawData
-- * `zcashd` RPC -- | Type for the different networks of the Zcash blockchain
data ZcashNet
= MainNet
| TestNet
| RegTestNet
deriving (Eq, Prelude.Show, Read, GHC.Generic, ToJSON, FromJSON)
type AccountId = Int
-- | Function to get the Base58 prefix for encoding a 'TransparentReceiver'
getTransparentPrefix :: ZcashNet -> TransparentType -> (Word8, Word8)
getTransparentPrefix n t =
case t of
P2SH ->
case n of
MainNet -> (0x1c, 0xbd)
_ -> (0x1c, 0xba)
P2PKH ->
case n of
MainNet -> (0x1c, 0xb8)
_ -> (0x1d, 0x25)
-- ** Constants
-- | Type for coin types on the different networks
data CoinType
= MainNetCoin
| TestNetCoin
| RegTestNetCoin
deriving (Eq, Prelude.Show, Ord)
getValue :: CoinType -> Word32
getValue c =
case c of
MainNetCoin -> 133
TestNetCoin -> 1
RegTestNetCoin -> 1
-- | A Zcash transaction
data Transaction = Transaction
{ tx_id :: !HexString
, tx_height :: !Int
, tx_conf :: !Int
, tx_expiry :: !Int
, tx_transpBundle :: !(Maybe TransparentBundle)
, tx_saplingBundle :: !(Maybe SaplingBundle)
, tx_orchardBundle :: !(Maybe OrchardBundle)
} deriving (Prelude.Show, Eq, Read)
instance ToJSON Transaction where
toJSON (Transaction t h c e tb sb ob) =
object
[ "txid" .= t
, "height" .= h
, "confirmations" .= c
, "expiry" .= e
, "transparent" .= tb
, "sapling" .= sb
, "orchard" .= ob
]
-- | The transparent portion of a Zcash transaction
data TransparentBundle = TransparentBundle
{ tb_vin :: ![H.TxIn]
, tb_vout :: ![H.TxOut]
, tb_coinbase :: !Bool
} deriving (Eq, Prelude.Show, Read)
instance ToJSON TransparentBundle where
toJSON (TransparentBundle vin vout c) =
object ["vin" .= vin, "vout" .= vout, "coinbase" .= c]
-- | Read a raw transparent bundle into the Haskell type
fromRawTBundle :: RawTBundle -> Maybe TransparentBundle
fromRawTBundle rtb =
if ztb_empty rtb
then Nothing
else Just $
TransparentBundle
(map fromRawTxIn $ ztb_vin rtb)
(map fromRawTxOut $ ztb_vout rtb)
(ztb_coinbase rtb)
fromRawTxIn :: RawTxIn -> H.TxIn
fromRawTxIn t = H.TxIn op (rti_script t) (rti_seq t)
where
op =
if rop_hash (rti_outpoint t) ==
"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
then H.nullOutPoint
else H.OutPoint
((fromJust .
H.hexToTxHash . toText . fromRawBytes . rop_hash . rti_outpoint)
t)
(rop_n $ rti_outpoint t)
fromRawTxOut :: RawTxOut -> H.TxOut
fromRawTxOut t = H.TxOut (rto_amt t) (rto_script t)
-- *** Constants for Sapling Human-readable part
sapExtSpendingKeyHrp = "secret-extended-key-main" :: String
sapExtFullViewingKeyHrp = "zxviews" :: String
sapPaymentAddressHrp = "zs" :: String
sapTestExtSpendingKeyHrp = "secret-extended-key-test" :: String
sapTestExtFullViewingKeyHrp = "zxviewtestsapling" :: String
sapTestPaymentAddressHrp = "ztestsapling" :: String
-- *** Constants for Unified Human-readable part
uniPaymentAddressHrp = "u" :: T.Text
uniFullViewingKeyHrp = "uview" :: T.Text
uniIncomingViewingKeyHrp = "uivk" :: T.Text
uniTestPaymentAddressHrp = "utest" :: T.Text
uniTestFullViewingKeyHrp = "uviewtest" :: T.Text
uniTestIncomingViewingKeyHrp = "uivktest" :: T.Text
-- * RPC
-- | A type to model Zcash RPC calls -- | A type to model Zcash RPC calls
data RpcCall = RpcCall data RpcCall = RpcCall
{ jsonrpc :: T.Text { jsonrpc :: !T.Text
, callId :: T.Text , callId :: !T.Text
, method :: T.Text , method :: !T.Text
, parameters :: [Data.Aeson.Value] , parameters :: ![Data.Aeson.Value]
} deriving stock (Prelude.Show, GHC.Generic) } deriving stock (Prelude.Show, GHC.Generic)
instance ToJSON RpcCall where instance ToJSON RpcCall where
@ -72,24 +225,24 @@ instance ToJSON RpcCall where
-- | A type to model the response of the Zcash RPC -- | A type to model the response of the Zcash RPC
data RpcResponse r = MakeRpcResponse data RpcResponse r = MakeRpcResponse
{ err :: Maybe RpcError { err :: !(Maybe RpcError)
, respId :: T.Text , respId :: !T.Text
, result :: Maybe r , result :: !(Maybe r)
} deriving stock (Prelude.Show, GHC.Generic) } deriving stock (Prelude.Show, GHC.Generic)
deriving anyclass (ToJSON) deriving anyclass (ToJSON)
instance (FromJSON r) => FromJSON (RpcResponse r) where instance (FromJSON r) => FromJSON (RpcResponse r) where
parseJSON = parseJSON =
withObject "RpcResponse" $ \obj -> do withObject "RpcResponse" $ \obj -> do
e <- obj .: "error" e <- obj .:? "error"
i <- obj .: "id" i <- obj .: "id"
r <- obj .: "result" r <- obj .:? "result"
pure $ MakeRpcResponse e i r pure $ MakeRpcResponse e i r
-- | A type to model the errors from the Zcash RPC -- | A type to model the errors from the Zcash RPC
data RpcError = RpcError data RpcError = RpcError
{ ecode :: Double { ecode :: !Double
, emessage :: T.Text , emessage :: !T.Text
} deriving stock (Prelude.Show, GHC.Generic) } deriving stock (Prelude.Show, GHC.Generic)
deriving anyclass (ToJSON) deriving anyclass (ToJSON)
@ -100,12 +253,14 @@ instance FromJSON RpcError where
m <- obj .: "message" m <- obj .: "message"
pure $ RpcError c m pure $ RpcError c m
-- ** `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_height :: Integer -- ^ Block height , bl_confirmations :: !Integer -- ^ Block confirmations
, bl_time :: Integer -- ^ Block time , bl_height :: !Integer -- ^ Block height
, bl_txs :: [T.Text] -- ^ List of transaction IDs in the block , bl_time :: !Integer -- ^ Block time
, bl_txs :: ![HexString] -- ^ List of transaction IDs in the block
} deriving (Prelude.Show, Eq) } deriving (Prelude.Show, Eq)
instance FromJSON BlockResponse where instance FromJSON BlockResponse where
@ -113,35 +268,333 @@ 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 t txs hash <- obj .: "hash"
pure $ BlockResponse hash c h (fromMaybe 0 t) txs
instance ToJSON BlockResponse where
toJSON (BlockResponse h c ht t txs) =
object
[ "hash" .= h
, "confirmations" .= c
, "height" .= ht
, "time" .= t
, "tx" .= txs
]
-- | Type to represent response from the `zcashd` RPC `getrawtransaction` -- | Type to represent response from the `zcashd` RPC `getrawtransaction`
data RawTxResponse = RawTxResponse data RawTxResponse = RawTxResponse
{ rt_id :: T.Text { rt_id :: !HexString
, rt_hex :: BS.ByteString , rt_hex :: !HexString
, rt_shieldedOutputs :: [BS.ByteString] , rt_shieldedSpends :: ![ShieldedSpend]
, rt_orchardActions :: [OrchardAction] , rt_shieldedOutputs :: ![ShieldedOutput]
, rt_blockheight :: Integer , rt_orchardActions :: ![OrchardAction]
, rt_confirmations :: Integer , rt_blockheight :: !Integer
, rt_blocktime :: Integer , rt_confirmations :: !Integer
} deriving (Prelude.Show, Eq) , rt_blocktime :: !Integer
} deriving (Prelude.Show, Eq, Read)
-- * Sapling -- ** `zebrad`
-- | Type to represent a Sapling Shielded Output as provided by the @getrawtransaction@ RPC method of @zcashd@. data ZebraTxResponse = ZebraTxResponse
data ShieldedOutput = ShieldedOutput { ztr_blockheight :: !Int
{ s_cv :: BS.ByteString -- ^ Value commitment to the input note , ztr_conf :: !Int
, s_cmu :: BS.ByteString -- ^ The u-coordinate of the note commitment for the output note , ztr_hex :: !HexString
, s_ephKey :: BS.ByteString -- ^ Ephemeral Jubjub public key } deriving (Prelude.Show, Eq, Read)
, s_encCipherText :: BS.ByteString -- ^ The output note encrypted to the recipient
, s_outCipherText :: BS.ByteString -- ^ A ciphertext enabling the sender to recover the output note instance FromJSON ZebraTxResponse where
, s_proof :: BS.ByteString -- ^ Zero-knowledge proof using the Sapling Output circuit parseJSON =
withObject "ZebraTxResponse" $ \obj -> do
hex <- obj .: "hex"
height <- obj .: "height"
c <- obj .: "confirmations"
pure $ ZebraTxResponse height c hex
-- | Type to represent a raw deserialized Zebra transaction
data RawZebraTx = RawZebraTx
{ zt_id :: !HexString
, zt_locktime :: !Word32
, zt_expiry :: !Word32
, zt_tBundle :: !RawTBundle
, zt_sBundle :: !RawSBundle
, zt_oBundle :: !RawOBundle
} deriving stock (Eq, Prelude.Show, GHC.Generic) } deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawZebraTx
-- | Type for a raw deserialized Zebra transparent bundle
data RawTBundle = RawTBundle
{ ztb_empty :: !Bool
, ztb_vin :: ![RawTxIn]
, ztb_vout :: ![RawTxOut]
, ztb_coinbase :: !Bool
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawTBundle
-- | Type for a raw deserialized Zebra Sapling bundle
data RawSBundle = RawSBundle
{ zsb_empty :: !Bool
, zsb_spends :: ![ShieldedSpend]
, zsb_outputs :: ![ShieldedOutput]
, zsb_value :: !Int64
, zsb_sig :: !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 RawSBundle
data SaplingBundle = SaplingBundle
{ sbSpends :: ![ShieldedSpend]
, sbOutputs :: ![ShieldedOutput]
, sbValue :: !Int64
, sbSig :: !HexString
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
instance ToJSON SaplingBundle where
toJSON (SaplingBundle s o v sig) =
object ["spends" .= s, "outputs" .= o, "value" .= v, "sig" .= sig]
fromRawSBundle :: RawSBundle -> Maybe SaplingBundle
fromRawSBundle b =
if zsb_empty b
then Nothing
else Just $
SaplingBundle (zsb_spends b) (zsb_outputs b) (zsb_value b) (zsb_sig b)
-- | Type for a raw deseralized Zebra Orchard bundle
data RawOBundle = RawOBundle
{ zob_empty :: !Bool
, zob_actions :: ![OrchardAction]
, zob_flags :: !OrchardFlags
, zob_value :: !Int64
, zob_anchor :: !HexString
, zob_proof :: !HexString
, zob_sig :: !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 RawOBundle
-- | Type for an Orchard Bundle
data OrchardBundle = OrchardBundle
{ obActions :: ![OrchardAction]
, obFlags :: !OrchardFlags
, obValue :: !Int64
, obAnchor :: !HexString
, obProof :: !HexString
, obSig :: !HexString
} deriving stock (Eq, Prelude.Show, GHC.Generic, Read)
instance ToJSON OrchardBundle where
toJSON (OrchardBundle a f v an p s) =
object
[ "actions" .= a
, "flags" .= f
, "value" .= v
, "anchor" .= an
, "proof" .= p
, "sig" .= s
]
fromRawOBundle :: RawOBundle -> Maybe OrchardBundle
fromRawOBundle b =
if zob_empty b
then Nothing
else Just $
OrchardBundle
(zob_actions b)
(zob_flags b)
(zob_value b)
(zob_anchor b)
(zob_proof b)
(zob_sig b)
-- | Type for the Orchard bundle flags
data OrchardFlags = OrchardFlags
{ of_spends :: !Bool
, of_outputs :: !Bool
} 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 OrchardFlags
instance ToJSON OrchardFlags where
toJSON (OrchardFlags s o) =
Data.Aeson.Array $ V.fromList [Data.Aeson.Bool s, Data.Aeson.Bool o]
-- | Type for the response from the `zebrad` RPC method `getinfo`
data ZebraGetInfo = ZebraGetInfo
{ zgi_build :: !T.Text
, zgi_subversion :: !T.Text
} deriving (Prelude.Show, Eq)
instance FromJSON ZebraGetInfo where
parseJSON =
withObject "ZebraGetInfo" $ \obj -> do
b <- obj .: "build"
s <- obj .: "subversion"
pure $ ZebraGetInfo b s
-- | Type for the response from the `zebrad` RPC method `getblockchaininfo`
data ZebraGetBlockChainInfo = ZebraGetBlockChainInfo
{ zgb_best :: !HexString
, zgb_blocks :: !Int
, zgb_net :: !ZcashNet
} deriving (Prelude.Show, Eq)
instance FromJSON ZebraGetBlockChainInfo where
parseJSON =
withObject "ZebraGetBlockChainInfo" $ \obj -> do
be <- obj .: "bestblockhash"
b <- obj .: "blocks"
c <- obj .: "chain"
pure $
ZebraGetBlockChainInfo
be
b
(case (c :: String) of
"main" -> MainNet
"test" -> TestNet
_ -> RegTestNet)
-- * Transparent
-- | Type to represent the two kinds of transparent addresses
data TransparentType
= P2SH
| P2PKH
deriving (Eq, Prelude.Show, Read)
-- | Type for transparent spending key
type TransparentSpendingKey = XPrvKey
-- | Type to represent a transparent Zcash addresses
data TransparentReceiver = TransparentReceiver
{ tr_type :: !TransparentType
, tr_bytes :: !HexString
} deriving (Eq, Prelude.Show, Read)
-- | Type to represent a transparent Zcash addresses
data TransparentAddress = TransparentAddress
{ ta_network :: !ZcashNet
, ta_receiver :: !TransparentReceiver
} deriving (Eq, Prelude.Show, Read)
-- | Type to represent a TEX Zcash addresses
data ExchangeAddress = ExchangeAddress
{ ex_network :: !ZcashNet
, ex_address :: !TransparentReceiver
} deriving (Eq, Prelude.Show, Read)
-- | Wrapper types for transparent elements
data RawTxIn = RawTxIn
{ rti_outpoint :: !RawOutPoint
, rti_script :: !BS.ByteString
, rti_seq :: !Word32
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawTxIn
data RawTxOut = RawTxOut
{ rto_amt :: !Word64
, rto_script :: !BS.ByteString
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawTxOut
data RawOutPoint = RawOutPoint
{ rop_hash :: !BS.ByteString
, rop_n :: !Word32
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawOutPoint
-- * Sapling
-- | A spending key for Sapling
newtype SaplingSpendingKey =
SaplingSpendingKey BS.ByteString
deriving stock (Eq, Prelude.Show, Read)
instance ToBytes SaplingSpendingKey where
getBytes (SaplingSpendingKey s) = s
-- | A Sapling receiver
newtype SaplingReceiver =
SaplingReceiver BS.ByteString
deriving stock (Eq, Prelude.Show, Read)
instance ToBytes SaplingReceiver where
getBytes (SaplingReceiver s) = s
data SaplingAddress = SaplingAddress
{ net_type :: !ZcashNet
, sa_receiver :: !SaplingReceiver
} deriving (Eq, Prelude.Show, Read)
-- | Type to represent a Sapling Shielded Spend as provided by the @getrawtransaction@ RPC method
data ShieldedSpend = ShieldedSpend
{ sp_cv :: !HexString
, sp_anchor :: !HexString
, sp_nullifier :: !HexString
, sp_rk :: !HexString
, sp_proof :: !HexString
, sp_auth :: !HexString
} 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 ShieldedSpend
instance ToJSON ShieldedSpend where
toJSON (ShieldedSpend cv a n rk p au) =
object
[ "cv" .= cv
, "anchor" .= a
, "nullifier" .= n
, "rk" .= rk
, "proof" .= p
, "spendAuthSig" .= au
]
instance FromJSON ShieldedSpend where
parseJSON =
withObject "ShieldedSpend" $ \obj -> do
cv <- obj .: "cv"
anchor <- obj .: "anchor"
nullifier <- obj .: "nullifier"
rk <- obj .: "rk"
p <- obj .: "proof"
sig <- obj .: "spendAuthSig"
pure $ ShieldedSpend cv anchor nullifier rk p sig
-- | Type to represent a Sapling Shielded Output as provided by the @getrawtransaction@ RPC method of @zcashd@.
data ShieldedOutput = ShieldedOutput
{ s_cv :: !HexString -- ^ Value commitment to the input note
, s_cmu :: !HexString -- ^ The u-coordinate of the note commitment for the output note
, s_ephKey :: !HexString -- ^ Ephemeral Jubjub public key
, s_encCipherText :: !HexString -- ^ The output note encrypted to the recipient
, s_outCipherText :: !HexString -- ^ A ciphertext enabling the sender to recover the output note
, s_proof :: !HexString -- ^ Zero-knowledge proof using the Sapling Output circuit
} 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 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
@ -151,22 +604,93 @@ instance FromJSON ShieldedOutput where
encText <- obj .: "encCiphertext" encText <- obj .: "encCiphertext"
outText <- obj .: "outCiphertext" outText <- obj .: "outCiphertext"
p <- obj .: "proof" p <- obj .: "proof"
pure $ pure $ ShieldedOutput cv cmu ephKey encText outText p
ShieldedOutput
(decodeHexText cv) -- | Type for a Sapling note commitment tree
(decodeHexText cmu) newtype SaplingCommitmentTree = SaplingCommitmentTree
(decodeHexText ephKey) { sapTree :: HexString
(decodeHexText encText) } deriving (Eq, Prelude.Show, Read)
(decodeHexText outText)
(decodeHexText p) 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
newtype SaplingWitness = SaplingWitness
{ sapWit :: HexString
} deriving (Eq, Prelude.Show, Read)
-- * Orchard -- * Orchard
-- | A spending key for Orchard
newtype OrchardSpendingKey =
OrchardSpendingKey BS.ByteString
deriving stock (Eq, Prelude.Show, Read)
instance ToBytes OrchardSpendingKey where
getBytes (OrchardSpendingKey o) = o
-- | An Orchard receiver
newtype OrchardReceiver =
OrchardReceiver BS.ByteString
deriving stock (Eq, Prelude.Show, Read)
instance ToBytes OrchardReceiver where
getBytes (OrchardReceiver o) = o
-- | Type to represent a Unified Address
data UnifiedAddress = UnifiedAddress
{ ua_net :: !ZcashNet
, o_rec :: !(Maybe OrchardReceiver)
, s_rec :: !(Maybe SaplingReceiver)
, t_rec :: !(Maybe TransparentReceiver)
} deriving (Prelude.Show, Eq, Read)
-- | Helper type for marshalling UAs
data RawUA = RawUA
{ raw_net :: !Word8
, raw_o :: !BS.ByteString
, raw_s :: !BS.ByteString
, raw_t :: !BS.ByteString
, raw_to :: !BS.ByteString
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawUA
-- | A type to handle user-entered addresses
data ValidAddress
= Unified !UnifiedAddress
| Sapling !SaplingAddress
| Transparent !TransparentAddress
| Exchange !ExchangeAddress
deriving stock (Eq, Prelude.Show)
-- | Type to represent a Unified Full Viewing Key -- | 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)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show) deriving anyclass (Data.Structured.Show)
@ -174,19 +698,32 @@ data UnifiedFullViewingKey = UnifiedFullViewingKey
-- | 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 :: BS.ByteString -- ^ The nullifier of the input note { nf :: !HexString -- ^ The nullifier of the input note
, rk :: BS.ByteString -- ^ The randomized validating key for @auth@ , rk :: !HexString -- ^ The randomized validating key for @auth@
, cmx :: BS.ByteString -- ^ The x-coordinate of the note commitment for the output note , cmx :: !HexString -- ^ The x-coordinate of the note commitment for the output note
, eph_key :: BS.ByteString -- ^ An encoding of an ephemeral Pallas public key , eph_key :: !HexString -- ^ An encoding of an ephemeral Pallas public key
, enc_ciphertext :: BS.ByteString -- ^ The output note encrypted to the recipient , enc_ciphertext :: !HexString -- ^ The output note encrypted to the recipient
, out_ciphertext :: BS.ByteString -- ^ A ciphertext enabling the sender to recover the output note , out_ciphertext :: !HexString -- ^ A ciphertext enabling the sender to recover the output note
, cv :: BS.ByteString -- ^ A value commitment to the net value of the input note minus the output note , cv :: !HexString -- ^ A value commitment to the net value of the input note minus the output note
, auth :: BS.ByteString -- ^ A signature authorizing the spend in this Action , auth :: !HexString -- ^ A signature authorizing the spend in this Action
} 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 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
@ -198,27 +735,139 @@ instance FromJSON OrchardAction where
outText <- obj .: "outCiphertext" outText <- obj .: "outCiphertext"
cval <- obj .: "cv" cval <- obj .: "cv"
a <- obj .: "spendAuthSig" a <- obj .: "spendAuthSig"
pure $ pure $ OrchardAction n r c ephKey encText outText cval a
OrchardAction
(decodeHexText n) data MerklePath = MerklePath
(decodeHexText r) { mp_position :: !Int32
(decodeHexText c) , mp_path :: ![HexString]
(decodeHexText ephKey) } deriving stock (Eq, Prelude.Show, GHC.Generic)
(decodeHexText encText) deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
(decodeHexText outText) deriving anyclass (Data.Structured.Show)
(decodeHexText cval) deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct MerklePath
(decodeHexText a)
-- | Type for a Orchard note commitment tree
newtype OrchardCommitmentTree = OrchardCommitmentTree
{ orchTree :: HexString
} deriving (Eq, Prelude.Show, Read)
data OrchardRawTree = OrchardRawTree
{ ort_left :: !HexString
, ort_right :: !HexString
, ort_parents :: ![HexString]
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardRawTree
data OrchardTree = OrchardTree
{ ot_left :: !(Maybe HexString)
, ot_right :: !(Maybe HexString)
, ot_parents :: ![Maybe HexString]
} deriving (Eq, Prelude.Show, Read)
data OrchardFrontier = OrchardFrontier
{ of_pos :: !Int64
, of_leaf :: !HexString
, 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
newtype OrchardWitness = OrchardWitness
{ orchWit :: HexString
} deriving (Eq, Prelude.Show, Read)
-- | Type to represent a decoded note -- | Type to represent a decoded note
data DecodedNote = DecodedNote data DecodedNote = DecodedNote
{ a_value :: Int64 -- ^ The amount of the transaction in _zatoshis_. { a_value :: !Int64 -- ^ The amount of the transaction in _zatoshis_.
, a_recipient :: BS.ByteString -- ^ The recipient Orchard receiver. , a_recipient :: !BS.ByteString -- ^ The recipient Orchard receiver.
, a_memo :: BS.ByteString -- ^ The decoded shielded memo field. , a_memo :: !BS.ByteString -- ^ The decoded shielded memo field.
, a_nullifier :: !HexString -- ^ The calculated nullifier
, a_rho :: !BS.ByteString
, a_rseed :: !Rseed
} 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)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct DecodedNote deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct DecodedNote
data Rseed = Rseed
{ rs_kind :: !Word8
, rs_bytes :: !BS.ByteString
} 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 Rseed
data TransparentTxSpend = TransparentTxSpend
{ ts_sk :: !BS.ByteString
, ts_utxo :: !RawOutPoint
, ts_coin :: !RawTxOut
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct TransparentTxSpend
data SaplingTxSpend = SaplingTxSpend
{ ss_sk :: !BS.ByteString
, ss_note :: !DecodedNote
, ss_iw :: !MerklePath
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct SaplingTxSpend
data OrchardTxSpend = OrchardTxSpend
{ ss_sk :: !BS.ByteString
, ss_note :: !DecodedNote
, ss_iw :: !MerklePath
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardTxSpend
data OutgoingNote = OutgoingNote
{ on_kind :: !Word8
, on_key :: !BS.ByteString
, on_recipient :: !BS.ByteString
, on_amt :: !Word64
, on_memo :: !BS.ByteString
, on_chg :: !Bool
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OutgoingNote
newtype SaplingSpendParams = SaplingSpendParams
{ sapSParams :: BS.ByteString
} deriving newtype (Eq, Prelude.Show, Read)
newtype SaplingOutputParams = SaplingOutputParams
{ sapOParams :: BS.ByteString
} deriving newtype (Eq, Prelude.Show, Read)
data TxError
= InsufficientFunds
| ChangeRequired
| Fee
| Balance
| TransparentBuild
| SaplingBuild
| OrchardBuild
| OrchardSpend
| OrchardRecipient
| SaplingBuilderNotAvailable
| OrchardBuilderNotAvailable
| PrivacyPolicyError !T.Text
| ZHError
deriving (Eq, Prelude.Show, Read)
-- * Classes
-- | Class to represent types with a bytestring representation
class ToBytes a where
getBytes :: a -> BS.ByteString
-- * Helpers -- * Helpers
-- | Helper function to turn a hex-encoded string to bytestring -- | Helper function to turn a hex-encoded string to bytestring
decodeHexText :: String -> BS.ByteString decodeHexText :: String -> BS.ByteString

View file

@ -1,27 +1,13 @@
{- 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.
--
Zcash-Haskell is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
Zcash-Haskell is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
Zcash-Haskell. If not, see <https://www.gnu.org/licenses/>.
-}
-- | -- |
-- Module : ZcashHaskell.Utils -- Module : ZcashHaskell.Utils
-- Copyright : Vergara Technologies (c)2023 -- Copyright : 2022-2024 Vergara Technologies LLC
-- License : BOSL -- License : MIT
-- --
-- Maintainer : rene@vergara.network -- Maintainer : pitmutt@vergara.tech
-- Stability : experimental -- Stability : experimental
-- Portability : unknown -- Portability : unknown
-- --
@ -33,21 +19,40 @@ module ZcashHaskell.Utils where
import C.Zcash import C.Zcash
( rustWrapperBech32Decode ( rustWrapperBech32Decode
, rustWrapperBech32Encode
, rustWrapperBech32mEncode
, rustWrapperCreateTx
, rustWrapperF4Jumble , rustWrapperF4Jumble
, rustWrapperF4UnJumble , rustWrapperF4UnJumble
, rustWrapperTxRead
) )
import Control.Exception (SomeException(..), try)
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Data.Aeson import Data.Aeson
import Data.Binary.Get
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import Data.HexString (HexString(..), toBytes)
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import Foreign.Rust.Marshall.Variable import Foreign.Rust.Marshall.Variable
import Network.HTTP.Client (HttpException(..))
import Network.HTTP.Simple import Network.HTTP.Simple
import ZcashHaskell.Types import ZcashHaskell.Types
-- * Utility functions
-- | Decode the given bytestring using Bech32 -- | Decode the given bytestring using Bech32
decodeBech32 :: BS.ByteString -> RawData decodeBech32 :: BS.ByteString -> RawData
decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode decodeBech32 = withPureBorshVarBuffer . rustWrapperBech32Decode
-- | Encode the given Human Readable Part and bytestring as a Bech32m string
encodeBech32m :: BS.ByteString -> BS.ByteString -> T.Text
encodeBech32m h d = withPureBorshVarBuffer $ rustWrapperBech32mEncode h d
-- | Encode the given Human Readable Part and bytestring as a Bech32 string
encodeBech32 :: BS.ByteString -> BS.ByteString -> T.Text
encodeBech32 h d = withPureBorshVarBuffer $ rustWrapperBech32Encode h d
-- | Apply the F4Jumble transformation to the given bytestring -- | Apply the F4Jumble transformation to the given bytestring
f4Jumble :: BS.ByteString -> BS.ByteString f4Jumble :: BS.ByteString -> BS.ByteString
f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble
@ -56,6 +61,7 @@ f4Jumble = withPureBorshVarBuffer . rustWrapperF4Jumble
f4UnJumble :: BS.ByteString -> BS.ByteString f4UnJumble :: BS.ByteString -> BS.ByteString
f4UnJumble = withPureBorshVarBuffer . rustWrapperF4UnJumble f4UnJumble = withPureBorshVarBuffer . rustWrapperF4UnJumble
-- * Node interaction
-- | Make a Zcash RPC call -- | Make a Zcash RPC call
makeZcashCall :: makeZcashCall ::
(MonadIO m, FromJSON a) (MonadIO m, FromJSON a)
@ -72,3 +78,86 @@ makeZcashCall username password m p = do
setRequestBasicAuth username password $ setRequestBasicAuth username password $
setRequestMethod "POST" defaultRequest setRequestMethod "POST" defaultRequest
httpJSON myRequest httpJSON myRequest
-- | Make a Zebra RPC call
makeZebraCall ::
FromJSON a
=> T.Text -- ^ Hostname for `zebrad`
-> Int -- ^ Port for `zebrad`
-> T.Text -- ^ RPC method to call
-> [Data.Aeson.Value] -- ^ List of parameters
-> IO (Either String a)
makeZebraCall host port m params = do
let payload = RpcCall "2.0" "zh" m params
let myRequest =
setRequestBodyJSON payload $
setRequestPort port $
setRequestHost (E.encodeUtf8 host) $
setRequestMethod "POST" defaultRequest
r <-
try $ httpJSON myRequest :: FromJSON a1 =>
IO (Either SomeException (Response (RpcResponse a1)))
case r of
Left ex -> return $ Left $ show ex
Right res -> do
let zebraResp = getResponseBody res
case err zebraResp of
Just zErr -> return $ Left $ T.unpack $ emessage zErr
Nothing ->
case result zebraResp of
Nothing -> return $ Left "Empty response from Zebra"
Just zR -> return $ Right zR
getBlockTime :: HexString -> Int
getBlockTime hex_block =
fromIntegral $
runGet getInt32le $
LBS.fromStrict $ BS.take 4 (BS.drop 100 $ hexBytes hex_block)
readZebraTransaction :: HexString -> Maybe RawZebraTx
readZebraTransaction hex =
if BS.length (hexBytes $ zt_id rawTx) < 1
then Nothing
else Just rawTx
where
rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex
createTransaction ::
HexString -- ^ to obtain the Sapling anchor
-> HexString -- ^ to obtain the Orchard anchor
-> [TransparentTxSpend] -- ^ the list of transparent notes to spend
-> [SaplingTxSpend] -- ^ the list of Sapling notes to spend
-> [OrchardTxSpend] -- ^ the list of Orchard notes to spend
-> [OutgoingNote] -- ^ the list of outgoing notes, including change notes
-> ZcashNet -- ^ the network to be used
-> Int -- ^ target block height
-> Bool -- ^ True to build, False to estimate fee
-> IO (Either TxError HexString)
createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do
txResult <-
withBorshBufferOfInitSize 51200 $
rustWrapperCreateTx
(hexBytes sapAnchor)
(hexBytes orchAnchor)
tSpend
sSpend
oSpend
outgoing
(znet == MainNet)
(fromIntegral bh)
build
if BS.length (hexBytes txResult) > 1
then pure $ Right txResult
else case head (BS.unpack $ hexBytes txResult) of
0 -> pure $ Left InsufficientFunds
1 -> pure $ Left ChangeRequired
2 -> pure $ Left Fee
3 -> pure $ Left Balance
4 -> pure $ Left TransparentBuild
5 -> pure $ Left SaplingBuild
6 -> pure $ Left OrchardBuild
7 -> pure $ Left OrchardSpend
8 -> pure $ Left OrchardRecipient
9 -> pure $ Left SaplingBuilderNotAvailable
10 -> pure $ Left OrchardBuilderNotAvailable
_ -> pure $ Left ZHError

View file

@ -1,75 +0,0 @@
# This file was automatically generated by 'stack init'
#
# Some commonly used options have been documented as comments in this file.
# For advanced use and comprehensive documentation of the format, please see:
# https://docs.haskellstack.org/en/stable/yaml_configuration/
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
# A snapshot resolver dictates the compiler version and the set of packages
# to be used for project dependencies. For example:
#
# resolver: lts-3.5
# resolver: nightly-2015-09-21
# resolver: ghc-7.10.2
#
# The location of a snapshot can be provided as a file or url. Stack assumes
# a snapshot provided as a file might change, whereas a url resource does not.
#
# resolver: ./custom-snapshot.yaml
# resolver: https://example.com/snapshots/2018-01-01.yaml
resolver: lts-21.21
# User packages to be built.
# Various formats can be used as shown in the example below.
#
# packages:
# - some-directory
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
# subdirs:
# - auto-update
# - wai
packages:
- .
# Dependency packages to be pulled from upstream that are not in the resolver.
# These entries can reference officially published versions as well as
# forks / in-progress versions pinned to a git hash. For example:
#
extra-deps:
# - acme-missiles-0.3
- git: https://git.vergara.tech/Vergara_Tech/haskell-foreign-rust.git
commit: 787c2e813eb3a5d16c375d4b37dfefbd2adcdf05
- git: https://github.com/well-typed/borsh.git
commit: d2fcfa159e0a844b1ec5e8ed3e232d4b380fa831
- vector-0.13.0.0@sha256:fa5cac81a17a5af388716792e8b99c24b3b66770086756d0d8b23f8272a0244c,9112
- aeson-2.1.2.1@sha256:f10f3c661bd5cf57aee46b94420e47736240b8e209ac15f4bfc1a4e4d55831fa,6344
- generically-0.1.1
- semialign-1.2.0.1@sha256:ee3468e349e72ec0a604ae05573a4de7181d97d10366254244a0cca8a76d6c35,2852
- strict-0.4.0.1@sha256:d6205a748eb8db4cd17a7179be970c94598809709294ccfa43159c7f3cc4bf5d,4187
- these-1.1.1.1@sha256:2991c13e264b0c35c696c8f5f85c428c53bc42e93b1dfbd19a582052112d948a,2748
- assoc-1.0.2@sha256:9decd0933cb6b903a40a8ace02d634bf90048ee2e5b0a514dccad7056c041881,1253
#
# extra-deps: []
# Override default flag values for local packages and extra-deps
# flags: {}
# Extra package databases containing global packages
# extra-package-dbs: []
# Control whether we use the GHC we find on the path
# system-ghc: true
#
# Require a specific version of Stack, using version ranges
# require-stack-version: -any # Default
# require-stack-version: ">=2.9"
#
# Override the architecture used by Stack, especially useful on Windows
# arch: i386
# arch: x86_64
#
# Extra directories used by Stack for building
# extra-include-dirs: [/path/to/dir]
# extra-lib-dirs: [/path/to/dir]
#
# Allow a newer minor version of GHC than the snapshot specifies
# compiler-check: newer-minor

File diff suppressed because one or more lines are too long

View file

@ -1,57 +1,73 @@
cabal-version: 1.12 cabal-version: 3.0
-- This file has been generated from package.yaml by hpack version 0.35.2. -- This file has been generated from package.yaml by hpack version 0.36.0.
-- --
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: zcash-haskell name: zcash-haskell
version: 0.2.1 version: 0.7.5.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
author: Rene Vergara author: Rene Vergara
maintainer: pitmutt@vergara.tech maintainer: pitmutt@vergara.tech
copyright: (c)2022-2024 Vergara Technologies LLC copyright: (c)2022-2024 Vergara Technologies LLC
license: LGPL-3 license: MIT
build-type: Simple license-file: LICENSE
build-type: Custom
extra-source-files: extra-source-files:
Setup.hs
extra-doc-files:
README.md README.md
CHANGELOG.md CHANGELOG.md
configure
source-repository head custom-setup
type: git setup-depends:
location: https://git.vergara.tech/Vergara_Tech/zcash-haskell base >= 4.7 && < 5
, Cabal >= 3.0.0.0
, directory >= 1.3.6.0
, filepath >= 1.3.0.2
, envy
, regex-compat
, regex-base
library library
exposed-modules: exposed-modules:
C.Zcash C.Zcash
ZcashHaskell.Keys
ZcashHaskell.Orchard ZcashHaskell.Orchard
ZcashHaskell.Sapling ZcashHaskell.Sapling
ZcashHaskell.Transparent
ZcashHaskell.Types ZcashHaskell.Types
ZcashHaskell.Utils ZcashHaskell.Utils
other-modules:
Paths_zcash_haskell
hs-source-dirs: hs-source-dirs:
src src
pkgconfig-depends:
rustzcash_wrapper-uninstalled
build-depends: build-depends:
aeson aeson
, base >=4.7 && <5 , base >=4.7 && <5
, base58-bytestring
, borsh >=0.2 , borsh >=0.2
, bytestring , bytestring
, cryptonite
, foreign-rust , foreign-rust
, generics-sop , generics-sop
, hexstring >=0.12.1
, http-conduit , http-conduit
, http-client
, memory
, binary
, text , text
, haskoin-core
, secp256k1-haskell >= 1.1
, vector
, utf8-string
build-tool-depends:
c2hs:c2hs
default-language: Haskell2010 default-language: Haskell2010
test-suite zcash-haskell-test test-suite zcash-haskell-test
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
main-is: Spec.hs main-is: Spec.hs
other-modules:
Paths_zcash_haskell
hs-source-dirs: hs-source-dirs:
test test
ghc-options: -threaded -rtsopts -with-rtsopts=-N ghc-options: -threaded -rtsopts -with-rtsopts=-N
@ -59,7 +75,17 @@ test-suite zcash-haskell-test
aeson aeson
, base >=4.7 && <5 , base >=4.7 && <5
, bytestring , bytestring
, haskoin-core
, hexstring >= 0.12.1
, hspec , hspec
, HUnit
, QuickCheck
, quickcheck-transformer
, text , text
, zcash-haskell , zcash-haskell
, binary
, cryptonite
, secp256k1-haskell
, http-conduit
pkgconfig-depends: rustzcash_wrapper
default-language: Haskell2010 default-language: Haskell2010

20
zebrablock.json Normal file
View file

@ -0,0 +1,20 @@
{
"result": {
"hash": "0041ee9cb0e256a73c92bb72d830143c402ea350152f56f19f74d23cf51418fb",
"confirmations": 3583,
"height": 2767099,
"tx": [
"d169ec3eda57dc750edfc1aa6b8ffb4ed2065780bfd5964de34b529503ec372f",
"987fcdb9bd37cbb5b205a8336de60d043f7028bebaa372828d81f3da296c7ef9"
],
"trees": {
"sapling": {
"size": 129349
},
"orchard": {
"size": 39382
}
}
},
"id": 123
}

4
zebrahexblock.json Normal file

File diff suppressed because one or more lines are too long

8
zebratx.json Normal file
View file

@ -0,0 +1,8 @@
{
"result": {
"hex": "0400008085202f8900010829d200000000001976a91484ae5002305847e7176362d7c12c19c5bdbbaf8088ac0000000023392a00f02cd200000000000192331caef004cc758fb666bed1908e61daa82d5c9835c0544afd8369589d350b04a7488a9870983860779ca2e0079a286fe71f60d5c583c3427d24ff968bad3246c1c838b90f465becc1ddfea5839b730ec219d577ed182f6da8f493350b422c86943b7c8ff42de8aee0fe01f4b91c8bb204008f06f85c3dffdb622632d2d4e8b8f0c7457cfa0f4238c7ef4c8903a89559e9307c26e844747ccb9b8dd5e7e83637983746b2fec3de051312306eb8b15db4766b3ef5fe3086d53d388cf2b3b209389ff3644e47d6bfdbe2fafef1bc2311093ad0b49f4600925f55328da337e73f01f83097acd8f2aca7a85f28e75fb4efec6551e026a1ebb35c25efde455cc44002bb8cc79288ed738423432558ebb583874aa5c356abe5be794e1bfaeaf6a7eccf67e5d938751a3a351bc21d4422d2ff0f36f5b30759d79b1ef2d83618d9c1769694454002d2f2be74de3ac10d39829369c87a70e1e9769e7d5ae7c865282a04487a8ae4cf5beeecaea6a3be1c864bdd8d61df88f08a76ac49d28a3a069d2c0d02068a10e88674b39c9d03da49256d914319d267c0d1db08ee7777668e90a94c50a065977222ee620f2291f6ca3fa464fafe8fc3fedf64a836eef5a2ca16aaae5573ee082a77f046d388750fa4ce3853c846ae3f338741c7976f72db4ade4abd4211e8d335ec8c83309bc7d7140a99dfb64a29839b9acc74de4ac0949bcbec4e76be9096a45ab6ca19b165f4097e24ab92d7b58694b0897789c3cdcca2b3d4b0a9da153fafe68f940031b6548d3c37c1301faa9adcfc41c417e613c0838340e28801f72610289d7435910fd276ca243d119541e0a121d263fdda149ac40f293e6fee6d5ddc32532ad947548eb5d20a5bfea97543965fe09313f1a5a78ce51ecac9c36b54cb573780da15d197f5ffacf1fa0d2b5495057a29104d610936c1898d1058f6f7b90e614bc2e3ff56b1e75aa4708128e3782f602dbdd29ece268311965592ddd536ea63841ea953b20677e0dd911852d23b85a3382420d22cd276b216e81638540b04966210a9308e8f9fb46958c967e3c2e36ae081a95cec8865a87d85d5689f660fe6c616ebfc2dab0f6e41d3e8c2906405fb98a506d90a8e8c6201d520a0deaa65e92e91f965288128101427d58e0b1e3ad8a49526feed27f3bcc6d505591483e2e4cc4a9b678d63f3abc905f26f91083bc595b89ff0b6cc3caa9d93013127ab7b30fbe18fad6f7f380fd6d5668fb6c3fdea3771fdd3004994e5752275ff7b186f9ad95f9d7ff01263f1165de34c1ae867e8954d66186880a90d73eace4dc1b8b17c76815242342821b4fab93755c3dc24e60aafd1cd3e283a7414de3af18c61328d92e9141916b8bb816de024a5a047a66508340a3287f698a41804e297916ff04f2921a0eeb8fcc5690c7fc024f57ab1fb6c6bc9a0caf9bf9e0e9aad64ceb2634bedbda6716235e4b93b67cd07ae06fde6abd2893143b55628be83fd4b347ce407dabf28e288f99d23b031376bfc1b1552cac1557e4730b03be581a92feae7d39fa2cf1c565a6cbe59a83b64b90ef8fc73ff6f8b9562d77fae1221df8f5ddb029f12ae80c3f128b87e56f78224b875af54a2fa1434749bb2e1c7ad9331497a71015ae0fc63903f36023e7f34b97c6ec5976ba3740845e5870c85f1b2042cdca86620881e08595215332de7d5828844e9e44124e42e1c60f6821cb71640c6643b01681553c932d310632a8b21154445176eb1a9a3c87dff22508bdbe4f1500e19131a072c42ff1d106ade135722a9e37e95e7e93917378e7907aae4be92dab78b1cd5a771d6064f6e3afc26ff84943a84de7f6ca6b0ab5993d1013b061da4053d77398cbeb329a6ae16f76493f85df1164b4f1fdff69bf113c8f18274a4ce6a05dd4c1ccbacb8d2c3760210e312c3a344294b43b23d06b7ce7263d3178e4fd530ba5838dc0e517b7d6fff2a0d9c4d69105a8fdab3f0c51a219c1ec10337b7cf05f8f3b1fb0a09f600308e5c21ae6ae06d6f87a6766d29e3a34f331f520d80524d580bd54b25716b6b937534233b856e022d20e53779b3a4a3615a3d62d1824c2bfa906e7804d629cc6712a3aee8c3703e99ec807cdb2d381acf126d63b83a2ce1d8f5cb768270bf41ae5637976acbaad8a1fa52cfb7a2f012966f3d29867cf2c28e504043a09eeff91917f6e96dc35a7df124074da73a20b87c7c8e2196f344cc08bd4c2406daaf6064488b5f9983131d90141fba82b13b0b1ff60565be66d53c36df3a9b4c772bffd428b34f94060ad32c59c9c029eba5fabd7a01b4e7252406c0ce7bb93c831034b100cc71090b37a436f96ce902973e2dca9594886b602ed6142697413aa448652529fe688a2e62fa96f8031ade066bb2bdc682f0ae3a526c7ad3c5d01e243b999a58aa5f6816dcd7a0cdd49202e128b99436f71e7fb7033bf96d8e3930e39e024530ec4b7932d334e54a66bfc3630b472336b6719d5a38e6e9bed938f71fe49e0af0b20c5db5408cabb3227b1690e904ea3116ee568330f56a5a698b914570962da4d831f5f5acde9acb257d272d0cd14e3133c89307f2d1575e32b8cc1582d1e4a680d35a1a2cace6233dfb4b0a7fea26f41785e1ac6007dd20d8b6dc3bd6857fa487c52b39f86647a67931b33910b746331305199d20ecd2e4d3b454226a134240831ea5a35c1e2d603c48eea209868b839c79a9318b6fd1078bc0f2bb9b0e931b64d63fbbcbf22b41e3cf7bee5cecb3c0e7b3ae39cf736fce8645ab33becbc9586a9154e29dd88f42ec7deecb2a4c08ac020ce54607f8006d2aa05a689ea688419215f0a10043820d85965a0001f102915fa6b2edfc4d6db7011a725db79b3974e9c1fc1636781bc9609359cfb0c5c921b83fc1115f7ed2568e49991ef93f8b8ff93a0d778251f0bcaa00ad64de8438d40aa05adbd1d1d1d2bca05ea9471a2c1a3733e92bcdf896d47dbe41b9f0d8b8b75de1ccd7cd7b7802fc01c4536a1a7b52ce70736e2cdfc547b58401023e34a608c1b09d0f13ab83d7b3fcde0e050c8cb4635508ddc143a9e6edb1e5a489a48ae0f4d5b0cede7d1b0ed8177709edbd61d859f6d9bad93a4c640684b7b8d994d8f5c0c8773da2b7a5b57d28b58d3f00c53430671d4af1537a262e8ea44a1b943c9bfc5082ad86d6690de32bb6527c815da065061bf79562d292e3d4799aa0df968fb939f64203f541dd4d006e5bd0b34b39215a972c36b229fc2f8e7f10e154b369d7b8f85f89daaaba6ec9836ad748dd79be4a58210341a458202a16e152ca2b0338a116a8490a7fa52c02",
"height": 2767099,
"confirmations": 3582
},
"id": 123
}