Implement transaction creation
This commit is contained in:
parent
f456332454
commit
ad9e2f074d
8 changed files with 682 additions and 58 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.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]
|
## [0.6.0.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
168
librustzcash-wrapper/Cargo.lock
generated
168
librustzcash-wrapper/Cargo.lock
generated
|
@ -318,6 +318,12 @@ dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.15.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
|
@ -703,6 +709,19 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hdwallet"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a03ba7d4c9ea41552cd4351965ff96883e629693ae85005c501bb4b9e1c48a7"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"rand_core",
|
||||||
|
"ring",
|
||||||
|
"secp256k1",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -796,6 +815,15 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.68"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jubjub"
|
name = "jubjub"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -1313,6 +1341,30 @@ version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.16.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"spin",
|
||||||
|
"untrusted",
|
||||||
|
"web-sys",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ripemd"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f"
|
||||||
|
dependencies = [
|
||||||
|
"digest 0.10.7",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.37.20"
|
version = "0.37.20"
|
||||||
|
@ -1336,10 +1388,13 @@ dependencies = [
|
||||||
"f4jumble",
|
"f4jumble",
|
||||||
"haskell-ffi",
|
"haskell-ffi",
|
||||||
"incrementalmerkletree",
|
"incrementalmerkletree",
|
||||||
|
"jubjub",
|
||||||
"nonempty",
|
"nonempty",
|
||||||
"orchard",
|
"orchard",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
"rand_core",
|
||||||
"sapling-crypto",
|
"sapling-crypto",
|
||||||
|
"secp256k1",
|
||||||
"zcash_address 0.2.0",
|
"zcash_address 0.2.0",
|
||||||
"zcash_client_backend",
|
"zcash_client_backend",
|
||||||
"zcash_note_encryption",
|
"zcash_note_encryption",
|
||||||
|
@ -1385,6 +1440,24 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secp256k1"
|
||||||
|
version = "0.26.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894"
|
||||||
|
dependencies = [
|
||||||
|
"secp256k1-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secp256k1-sys"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "secrecy"
|
name = "secrecy"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -1661,6 +1734,12 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
@ -1673,6 +1752,70 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.32",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.32",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.68"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
version = "4.4.0"
|
version = "4.4.0"
|
||||||
|
@ -1684,6 +1827,28 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
|
@ -1882,6 +2047,7 @@ dependencies = [
|
||||||
"ff",
|
"ff",
|
||||||
"fpe",
|
"fpe",
|
||||||
"group",
|
"group",
|
||||||
|
"hdwallet",
|
||||||
"hex",
|
"hex",
|
||||||
"incrementalmerkletree",
|
"incrementalmerkletree",
|
||||||
"jubjub",
|
"jubjub",
|
||||||
|
@ -1891,7 +2057,9 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"redjubjub",
|
"redjubjub",
|
||||||
|
"ripemd",
|
||||||
"sapling-crypto",
|
"sapling-crypto",
|
||||||
|
"secp256k1",
|
||||||
"sha2 0.10.6",
|
"sha2 0.10.6",
|
||||||
"subtle",
|
"subtle",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
|
@ -13,13 +13,16 @@ borsh = "0.10"
|
||||||
bech32 = "0.11"
|
bech32 = "0.11"
|
||||||
orchard = "0.7.1"
|
orchard = "0.7.1"
|
||||||
zcash_note_encryption = "0.4.0"
|
zcash_note_encryption = "0.4.0"
|
||||||
zcash_primitives = "0.14.0"
|
zcash_primitives = { version = "0.14.0", features = ["transparent-inputs"]}
|
||||||
zcash_client_backend = "0.11.1"
|
zcash_client_backend = "0.11.1"
|
||||||
sapling-crypto = "0.1.3"
|
sapling-crypto = "0.1.3"
|
||||||
zip32 = "0.1.0"
|
zip32 = "0.1.0"
|
||||||
proc-macro2 = "1.0.66"
|
proc-macro2 = "1.0.66"
|
||||||
nonempty = "0.7.0"
|
nonempty = "0.7.0"
|
||||||
incrementalmerkletree = "0.5.0"
|
incrementalmerkletree = "0.5.0"
|
||||||
|
secp256k1 = "0.26.0"
|
||||||
|
jubjub = "0.10.0"
|
||||||
|
rand_core = { version = "0.6.4", features = ["getrandom"]}
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -12,6 +12,8 @@ use std::{
|
||||||
|
|
||||||
use nonempty::NonEmpty;
|
use nonempty::NonEmpty;
|
||||||
|
|
||||||
|
use rand_core::OsRng;
|
||||||
|
|
||||||
use f4jumble;
|
use f4jumble;
|
||||||
|
|
||||||
use borsh::{BorshDeserialize, BorshSerialize};
|
use borsh::{BorshDeserialize, BorshSerialize};
|
||||||
|
@ -23,6 +25,10 @@ use haskell_ffi::{
|
||||||
FromHaskell, HaskellSize, ToHaskell
|
FromHaskell, HaskellSize, ToHaskell
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use secp256k1::SecretKey;
|
||||||
|
|
||||||
|
use jubjub::Fr;
|
||||||
|
|
||||||
use incrementalmerkletree::{
|
use incrementalmerkletree::{
|
||||||
frontier::CommitmentTree,
|
frontier::CommitmentTree,
|
||||||
witness::IncrementalWitness
|
witness::IncrementalWitness
|
||||||
|
@ -39,8 +45,13 @@ use sapling_crypto::{
|
||||||
Node,
|
Node,
|
||||||
MerklePath,
|
MerklePath,
|
||||||
PaymentAddress,
|
PaymentAddress,
|
||||||
|
Anchor as SaplingAnchor,
|
||||||
value::ValueCommitment as SaplingValueCommitment,
|
value::ValueCommitment as SaplingValueCommitment,
|
||||||
note::ExtractedNoteCommitment as SaplingNoteCommitment,
|
note::{
|
||||||
|
ExtractedNoteCommitment as SaplingNoteCommitment,
|
||||||
|
Note as SaplingNote,
|
||||||
|
Rseed
|
||||||
|
},
|
||||||
keys::{
|
keys::{
|
||||||
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
||||||
ExpandedSpendingKey,
|
ExpandedSpendingKey,
|
||||||
|
@ -57,6 +68,11 @@ use sapling_crypto::{
|
||||||
Authorized as SaplingAuthorized,
|
Authorized as SaplingAuthorized,
|
||||||
Bundle as SaplingBundle
|
Bundle as SaplingBundle
|
||||||
},
|
},
|
||||||
|
value::NoteValue as SaplingNoteValue,
|
||||||
|
circuit::{
|
||||||
|
SpendParameters,
|
||||||
|
OutputParameters
|
||||||
|
},
|
||||||
zip32::{
|
zip32::{
|
||||||
sapling_find_address,
|
sapling_find_address,
|
||||||
DiversifierKey
|
DiversifierKey
|
||||||
|
@ -70,18 +86,34 @@ use zcash_primitives::{
|
||||||
read_incremental_witness,
|
read_incremental_witness,
|
||||||
write_incremental_witness
|
write_incremental_witness
|
||||||
},
|
},
|
||||||
|
legacy::{
|
||||||
|
Script,
|
||||||
|
TransparentAddress
|
||||||
|
},
|
||||||
zip339::{Count, Mnemonic},
|
zip339::{Count, Mnemonic},
|
||||||
transaction::components::{
|
transaction::{
|
||||||
amount::Amount,
|
Transaction,
|
||||||
transparent::{
|
fees::zip317::FeeRule,
|
||||||
Bundle as TransparentBundle,
|
builder::{
|
||||||
TxIn,
|
Builder,
|
||||||
TxOut,
|
Error,
|
||||||
OutPoint,
|
BuildConfig
|
||||||
Authorized
|
},
|
||||||
|
components::{
|
||||||
|
amount::{
|
||||||
|
Amount,
|
||||||
|
NonNegativeAmount
|
||||||
|
},
|
||||||
|
transparent::{
|
||||||
|
Bundle as TransparentBundle,
|
||||||
|
TxIn,
|
||||||
|
TxOut,
|
||||||
|
OutPoint,
|
||||||
|
Authorized
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
transaction::Transaction,
|
memo::MemoBytes,
|
||||||
consensus::{
|
consensus::{
|
||||||
BranchId::Nu5,
|
BranchId::Nu5,
|
||||||
MainNetwork,
|
MainNetwork,
|
||||||
|
@ -107,6 +139,7 @@ use zcash_client_backend::keys::sapling::{
|
||||||
use zcash_primitives::zip32::DiversifierIndex;
|
use zcash_primitives::zip32::DiversifierIndex;
|
||||||
|
|
||||||
use orchard::{
|
use orchard::{
|
||||||
|
Address as OrchardAddress,
|
||||||
Bundle as OrchardBundle,
|
Bundle as OrchardBundle,
|
||||||
bundle::{
|
bundle::{
|
||||||
Authorized as OrchardAuthorized,
|
Authorized as OrchardAuthorized,
|
||||||
|
@ -114,11 +147,18 @@ use orchard::{
|
||||||
},
|
},
|
||||||
Action,
|
Action,
|
||||||
keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope},
|
keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope},
|
||||||
note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment},
|
note::{RandomSeed, Note, Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment},
|
||||||
note_encryption::OrchardDomain,
|
note_encryption::OrchardDomain,
|
||||||
primitives::redpallas::{VerificationKey, SpendAuth, Signature},
|
primitives::redpallas::{VerificationKey, SpendAuth, Signature},
|
||||||
tree::MerkleHashOrchard,
|
tree::{
|
||||||
value::ValueCommitment
|
MerklePath as OrchardMerklePath,
|
||||||
|
MerkleHashOrchard,
|
||||||
|
Anchor as OrchardAnchor
|
||||||
|
},
|
||||||
|
value::{
|
||||||
|
ValueCommitment,
|
||||||
|
NoteValue
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
use bech32::{
|
use bech32::{
|
||||||
|
@ -255,7 +295,9 @@ pub struct Hnote {
|
||||||
note: u64,
|
note: u64,
|
||||||
recipient: Vec<u8>,
|
recipient: Vec<u8>,
|
||||||
memo: Vec<u8>,
|
memo: Vec<u8>,
|
||||||
nullifier: Vec<u8>
|
nullifier: Vec<u8>,
|
||||||
|
rho: Vec<u8>,
|
||||||
|
rseed: Hrseed
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for Hnote {
|
impl<RW> ToHaskell<RW> for Hnote {
|
||||||
|
@ -265,6 +307,27 @@ impl<RW> ToHaskell<RW> for Hnote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct Hrseed {
|
||||||
|
kind: u8,
|
||||||
|
bytes: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for Hrseed {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = Hrseed::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for Hrseed {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Hua {
|
pub struct Hua {
|
||||||
net: u8,
|
net: u8,
|
||||||
|
@ -363,6 +426,13 @@ pub struct HTxOut {
|
||||||
script: Vec<u8>
|
script: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for HTxOut {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = HTxOut::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for HTxOut {
|
impl<RW> ToHaskell<RW> for HTxOut {
|
||||||
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
self.serialize(writer)?;
|
self.serialize(writer)?;
|
||||||
|
@ -374,6 +444,9 @@ impl HTxOut {
|
||||||
pub fn pack(t: &TxOut) -> HTxOut {
|
pub fn pack(t: &TxOut) -> HTxOut {
|
||||||
return HTxOut { amt: i64::from_le_bytes(t.value.to_i64_le_bytes()) , script: t.script_pubkey.0.clone() }
|
return HTxOut { amt: i64::from_le_bytes(t.value.to_i64_le_bytes()) , script: t.script_pubkey.0.clone() }
|
||||||
}
|
}
|
||||||
|
pub fn unpack(&self) -> TxOut {
|
||||||
|
TxOut { value: NonNegativeAmount::from_nonnegative_i64(self.amt).unwrap(), script_pubkey: Script(self.script.clone())}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
@ -382,6 +455,13 @@ pub struct Houtpoint {
|
||||||
index: u32
|
index: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for Houtpoint {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = Houtpoint::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for Houtpoint {
|
impl<RW> ToHaskell<RW> for Houtpoint {
|
||||||
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
self.serialize(writer)?;
|
self.serialize(writer)?;
|
||||||
|
@ -393,6 +473,31 @@ impl Houtpoint {
|
||||||
pub fn pack(o: &OutPoint) -> Houtpoint {
|
pub fn pack(o: &OutPoint) -> Houtpoint {
|
||||||
return Houtpoint {hash: o.hash().to_vec() , index: o.n() }
|
return Houtpoint {hash: o.hash().to_vec() , index: o.n() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unpack(&self) -> OutPoint {
|
||||||
|
OutPoint::new(to_array(self.hash.clone()), self.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct HtransparentInput {
|
||||||
|
sk: Vec<u8>,
|
||||||
|
utxo: Houtpoint,
|
||||||
|
coin: HTxOut
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for HtransparentInput {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = HtransparentInput::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for HtransparentInput {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
@ -447,6 +552,52 @@ impl Hspend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct HsaplingInput {
|
||||||
|
sk: Vec<u8>,
|
||||||
|
note: Hnote,
|
||||||
|
iw: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for HsaplingInput {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = HsaplingInput::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct HorchardInput {
|
||||||
|
sk: Vec<u8>,
|
||||||
|
note: Hnote,
|
||||||
|
iw: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for HorchardInput {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = HorchardInput::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct Houtput {
|
||||||
|
kind: u8,
|
||||||
|
ovk: Vec<u8>,
|
||||||
|
to: Vec<u8>,
|
||||||
|
amt: u64,
|
||||||
|
memo: Vec<u8>,
|
||||||
|
chg: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> FromHaskell<RW> for Houtput {
|
||||||
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
||||||
|
let x = Houtput::deserialize(buf)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct HOBundle {
|
pub struct HOBundle {
|
||||||
empty: bool,
|
empty: bool,
|
||||||
|
@ -771,23 +922,31 @@ pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let nullifier = n.nf(&nk, pos);
|
let nullifier = n.nf(&nk, pos);
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: nullifier.to_vec() };
|
let rseed = match n.rseed() {
|
||||||
|
Rseed::BeforeZip212(x) => {
|
||||||
|
Hrseed {kind: 1, bytes: x.to_bytes().to_vec()}
|
||||||
|
},
|
||||||
|
Rseed::AfterZip212(y) => {
|
||||||
|
Hrseed {kind: 2, bytes: y.to_vec()}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: nullifier.to_vec(), rho: vec![0], rseed };
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed{ kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_e1) => {
|
Err(_e1) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed{ kind: 0, bytes: vec![0]} };
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed{ kind: 0, bytes: vec![0]} };
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -816,23 +975,31 @@ pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
|
||||||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action3);
|
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action3);
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: vec![0]};
|
let rseed = match n.rseed() {
|
||||||
|
Rseed::BeforeZip212(x) => {
|
||||||
|
Hrseed { kind: 1, bytes: x.to_bytes().to_vec()}
|
||||||
|
},
|
||||||
|
Rseed::AfterZip212(y) => {
|
||||||
|
Hrseed { kind: 2, bytes: y.to_vec()}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: vec![0], rho: vec![0], rseed};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed {kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_e1) => {
|
Err(_e1) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] , nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] , nullifier: vec![0], rho: vec![0], rseed: Hrseed {kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed {kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -866,17 +1033,19 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt(
|
||||||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
|
let rho = n.rho().to_bytes().to_vec();
|
||||||
|
let rseed = Hrseed {kind: 3, bytes: n.rseed().as_bytes().to_vec()};
|
||||||
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0], rho, rseed};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed {kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed {kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -914,11 +1083,13 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt_sk(
|
||||||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: n.nullifier(&fvk).to_bytes().to_vec()};
|
let rho = n.rho().to_bytes().to_vec();
|
||||||
|
let rseed = Hrseed {kind: 3, bytes: n.rseed().as_bytes().to_vec()};
|
||||||
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: n.nullifier(&fvk).to_bytes().to_vec(), rho, rseed};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0], rho: vec![0], rseed: Hrseed {kind: 0, bytes: vec![0]}};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1454,8 +1625,193 @@ pub extern "C" fn rust_wrapper_decode_sapling_address(
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_wrapper_create_transaction(
|
pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
sapling: *const u8,
|
sap_wit: *const u8,
|
||||||
sapling_len: usize,
|
sap_wit_len: usize,
|
||||||
|
orch_wit: *const u8,
|
||||||
|
orch_wit_len: usize,
|
||||||
|
t_input: *const u8,
|
||||||
|
t_input_len: usize,
|
||||||
|
s_input: *const u8,
|
||||||
|
s_input_len: usize,
|
||||||
|
o_input: *const u8,
|
||||||
|
o_input_len: usize,
|
||||||
|
out_list: *const u8,
|
||||||
|
out_list_len: usize,
|
||||||
|
sapspend: *const u8,
|
||||||
|
sapspend_len: usize,
|
||||||
|
sapoutput: *const u8,
|
||||||
|
sapoutput_len: usize,
|
||||||
|
net: bool,
|
||||||
|
bl_height: u32,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
out_len: &mut usize){
|
out_len: &mut usize){
|
||||||
|
let sap_wit_in: Vec<u8> = marshall_from_haskell_var(sap_wit, sap_wit_len, RW);
|
||||||
|
let sap_wit_reader = Cursor::new(sap_wit_in);
|
||||||
|
let sap_iw: Option<IncrementalWitness<Node, SAPLING_DEPTH>> = read_incremental_witness(sap_wit_reader).ok();
|
||||||
|
let sap_anchor = match sap_iw {
|
||||||
|
Some(s_iw) => {
|
||||||
|
Some(SaplingAnchor::from(s_iw.root()))
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let orch_wit_in: Vec<u8> = marshall_from_haskell_var(orch_wit, orch_wit_len, RW);
|
||||||
|
let orch_wit_reader = Cursor::new(orch_wit_in);
|
||||||
|
let orch_iw: Option<IncrementalWitness<MerkleHashOrchard, 32>> = read_incremental_witness(orch_wit_reader).ok();
|
||||||
|
let orch_anchor = match orch_iw {
|
||||||
|
Some(o_iw) => {
|
||||||
|
Some(OrchardAnchor::from(o_iw.root()))
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let build_config = BuildConfig::Standard {sapling_anchor: sap_anchor, orchard_anchor: orch_anchor};
|
||||||
|
let mut main_builder = Builder::new(MainNetwork, BlockHeight::from(bl_height), build_config);
|
||||||
|
let mut test_builder = Builder::new(TestNetwork, BlockHeight::from(bl_height), build_config);
|
||||||
|
let trans_input: Vec<HtransparentInput> = marshall_from_haskell_var(t_input, t_input_len, RW);
|
||||||
|
for t_in in trans_input {
|
||||||
|
if t_in.sk.len() > 1 {
|
||||||
|
let k = SecretKey::from_slice(&t_in.sk).unwrap();
|
||||||
|
if net {
|
||||||
|
match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) {
|
||||||
|
Ok(()) => {
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
Err(_e) => { println!("Error reading transparent input"); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match test_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) {
|
||||||
|
Ok(()) => {
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
Err(_e) => { println!("Error reading transparent input"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let sap_input: Vec<HsaplingInput> = marshall_from_haskell_var(s_input, s_input_len, RW);
|
||||||
|
for s_in in sap_input {
|
||||||
|
if s_in.sk.len() > 1 {
|
||||||
|
let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk);
|
||||||
|
match sp_key {
|
||||||
|
Ok(sk) => {
|
||||||
|
let pay_addr = PaymentAddress::from_bytes(&to_array(s_in.note.recipient)).unwrap();
|
||||||
|
let rseed = if s_in.note.rseed.kind == 1 {
|
||||||
|
Rseed::BeforeZip212(Fr::from_bytes(&to_array(s_in.note.rseed.bytes)).unwrap())
|
||||||
|
} else {
|
||||||
|
Rseed::AfterZip212(to_array(s_in.note.rseed.bytes))
|
||||||
|
};
|
||||||
|
let note = SaplingNote::from_parts(pay_addr, SaplingNoteValue::from_raw(s_in.note.note), rseed);
|
||||||
|
let wit_reader = Cursor::new(s_in.iw);
|
||||||
|
let iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(wit_reader).unwrap();
|
||||||
|
let merkle_path = iw.path().unwrap();
|
||||||
|
if net {
|
||||||
|
let _mb = main_builder.add_sapling_spend::<String>(&sk, note, merkle_path).unwrap();
|
||||||
|
} else {
|
||||||
|
let _tb = test_builder.add_sapling_spend::<String>(&sk, note, merkle_path).unwrap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let orch_input: Vec<HorchardInput> = marshall_from_haskell_var(o_input, o_input_len, RW);
|
||||||
|
for o_in in orch_input {
|
||||||
|
if o_in.sk.len() > 1 {
|
||||||
|
let sp_key = SpendingKey::from_bytes(o_in.sk[0..32].try_into().unwrap()).unwrap();
|
||||||
|
let pay_addr = OrchardAddress::from_raw_address_bytes(&to_array(o_in.note.recipient)).unwrap();
|
||||||
|
let rho = Nullifier::from_bytes(&to_array(o_in.note.rho)).unwrap();
|
||||||
|
let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap();
|
||||||
|
let val = NoteValue::from_raw(o_in.note.note);
|
||||||
|
let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap();
|
||||||
|
let wit_reader = Cursor::new(o_in.iw);
|
||||||
|
let iw: IncrementalWitness<MerkleHashOrchard, 32> = read_incremental_witness(wit_reader).unwrap();
|
||||||
|
let merkle_path = OrchardMerklePath::from(iw.path().unwrap());
|
||||||
|
if net {
|
||||||
|
let _mb = main_builder.add_orchard_spend::<String>(&sp_key, note, merkle_path).unwrap();
|
||||||
|
} else {
|
||||||
|
let _tb = test_builder.add_orchard_spend::<String>(&sp_key, note, merkle_path).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let outputs: Vec<Houtput> = marshall_from_haskell_var(out_list, out_list_len, RW);
|
||||||
|
for output in outputs {
|
||||||
|
match output.kind {
|
||||||
|
1 => {
|
||||||
|
let recipient = TransparentAddress::PublicKeyHash(to_array(output.to));
|
||||||
|
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
||||||
|
if net {
|
||||||
|
let _mb = main_builder.add_transparent_output(&recipient, val);
|
||||||
|
} else {
|
||||||
|
let _tb = test_builder.add_transparent_output(&recipient, val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
let recipient = TransparentAddress::ScriptHash(to_array(output.to));
|
||||||
|
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
||||||
|
if net {
|
||||||
|
let _mb = main_builder.add_transparent_output(&recipient, val);
|
||||||
|
} else {
|
||||||
|
let _tb = test_builder.add_transparent_output(&recipient, val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
let ovk = Some(ExpandedSpendingKey::from_spending_key(&output.ovk).ovk);
|
||||||
|
let recipient = PaymentAddress::from_bytes(&to_array(output.to)).unwrap();
|
||||||
|
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
||||||
|
let memo = MemoBytes::from_bytes(&output.memo).unwrap();
|
||||||
|
if net {
|
||||||
|
let _mb = main_builder.add_sapling_output::<String>(ovk, recipient, val, memo);
|
||||||
|
} else {
|
||||||
|
let _tb = test_builder.add_sapling_output::<String>(ovk, recipient, val, memo);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
let sk = SpendingKey::from_bytes(output.ovk[0..32].try_into().unwrap()).unwrap();
|
||||||
|
let ovk = if output.chg {
|
||||||
|
Some(FullViewingKey::from(&sk).to_ovk(Scope::Internal))
|
||||||
|
}else {
|
||||||
|
Some(FullViewingKey::from(&sk).to_ovk(Scope::External))
|
||||||
|
};
|
||||||
|
let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap();
|
||||||
|
let val = output.amt;
|
||||||
|
let memo = MemoBytes::from_bytes(&output.memo).unwrap();
|
||||||
|
if net {
|
||||||
|
let _mb = main_builder.add_orchard_output::<String>(ovk, recipient, val, memo);
|
||||||
|
} else {
|
||||||
|
let _tb = test_builder.add_orchard_output::<String>(ovk, recipient, val, memo);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let spend_params_in: Vec<u8> = marshall_from_haskell_var(sapspend, sapspend_len, RW);
|
||||||
|
let spend_params_reader = Cursor::new(spend_params_in);
|
||||||
|
let spend_prover = SpendParameters::read(spend_params_reader, true).unwrap();
|
||||||
|
let output_params_in: Vec<u8> = marshall_from_haskell_var(sapoutput, sapoutput_len, RW);
|
||||||
|
let output_params_reader = Cursor::new(output_params_in);
|
||||||
|
let output_prover = OutputParameters::read(output_params_reader, true).unwrap();
|
||||||
|
let result = if net {
|
||||||
|
main_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard())
|
||||||
|
} else {
|
||||||
|
test_builder.build(OsRng, &spend_prover, &output_prover, &FeeRule::standard())
|
||||||
|
};
|
||||||
|
match result {
|
||||||
|
Ok(r) => {
|
||||||
|
let mut out_bytes: Vec<u8> = Vec::new();
|
||||||
|
let _t = r.transaction().write_v5(&mut out_bytes);
|
||||||
|
let h = Hhex {bytes: out_bytes};
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![0]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,3 +275,19 @@ import ZcashHaskell.Types
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_create_transaction as rustWrapperCreateTx
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `[TransparentTxSpend]'&
|
||||||
|
, toBorshVar* `[SaplingTxSpend]'&
|
||||||
|
, toBorshVar* `[OrchardTxSpend]'&
|
||||||
|
, toBorshVar* `[OutgoingNote]'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, `Bool'
|
||||||
|
, `Word64'
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
|
@ -21,8 +21,8 @@ import Crypto.Secp256k1
|
||||||
import qualified Data.ByteArray as BA
|
import qualified Data.ByteArray as BA
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
|
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
|
||||||
import Data.Char (chr)
|
|
||||||
import qualified Data.ByteString.Char8 as BC
|
import qualified Data.ByteString.Char8 as BC
|
||||||
|
import Data.Char (chr)
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
|
@ -31,6 +31,7 @@ import Haskoin.Address (Address(..))
|
||||||
import qualified Haskoin.Crypto.Hash as H
|
import qualified Haskoin.Crypto.Hash as H
|
||||||
import Haskoin.Crypto.Keys.Extended
|
import Haskoin.Crypto.Keys.Extended
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
|
|
||||||
-- ( AccountId
|
-- ( AccountId
|
||||||
-- , CoinType(..)
|
-- , CoinType(..)
|
||||||
-- , Scope(..)
|
-- , Scope(..)
|
||||||
|
@ -44,7 +45,7 @@ import ZcashHaskell.Types
|
||||||
-- , getTransparentPrefix
|
-- , getTransparentPrefix
|
||||||
-- , getValue
|
-- , getValue
|
||||||
-- )
|
-- )
|
||||||
import ZcashHaskell.Utils( encodeBech32m, decodeBech32 )
|
import ZcashHaskell.Utils (decodeBech32, encodeBech32m)
|
||||||
|
|
||||||
-- | Required for `TransparentReceiver` encoding and decoding
|
-- | Required for `TransparentReceiver` encoding and decoding
|
||||||
sha256 :: BS.ByteString -> BS.ByteString
|
sha256 :: BS.ByteString -> BS.ByteString
|
||||||
|
@ -127,26 +128,34 @@ decodeTransparentAddress taddress = do
|
||||||
189 ->
|
189 ->
|
||||||
Just $
|
Just $
|
||||||
TransparentAddress MainNet $
|
TransparentAddress MainNet $
|
||||||
TransparentReceiver P2SH (fromRawBytes transparentReceiver)
|
TransparentReceiver
|
||||||
|
P2SH
|
||||||
|
(fromRawBytes transparentReceiver)
|
||||||
186 ->
|
186 ->
|
||||||
Just $
|
Just $
|
||||||
TransparentAddress TestNet $
|
TransparentAddress TestNet $
|
||||||
TransparentReceiver P2SH (fromRawBytes transparentReceiver)
|
TransparentReceiver
|
||||||
|
P2SH
|
||||||
|
(fromRawBytes transparentReceiver)
|
||||||
184 ->
|
184 ->
|
||||||
Just $
|
Just $
|
||||||
TransparentAddress MainNet $
|
TransparentAddress MainNet $
|
||||||
TransparentReceiver P2PKH (fromRawBytes transparentReceiver)
|
TransparentReceiver
|
||||||
|
P2PKH
|
||||||
|
(fromRawBytes transparentReceiver)
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
29 ->
|
29 ->
|
||||||
if sb == 37
|
if sb == 37
|
||||||
then Just $
|
then Just $
|
||||||
TransparentAddress TestNet $
|
TransparentAddress TestNet $
|
||||||
TransparentReceiver P2PKH (fromRawBytes transparentReceiver)
|
TransparentReceiver
|
||||||
|
P2PKH
|
||||||
|
(fromRawBytes transparentReceiver)
|
||||||
else Nothing
|
else Nothing
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
-- | Encode an Exchange Addresss into HRF from TransparentReceiver
|
-- | Encode an Exchange Addresss into HRF from TransparentReceiver
|
||||||
encodeExchangeAddress:: ZcashNet -> TransparentReceiver -> Maybe T.Text
|
encodeExchangeAddress :: ZcashNet -> TransparentReceiver -> Maybe T.Text
|
||||||
encodeExchangeAddress net tr = do
|
encodeExchangeAddress net tr = do
|
||||||
case (tr_type tr) of
|
case (tr_type tr) of
|
||||||
P2PKH -> do
|
P2PKH -> do
|
||||||
|
@ -160,14 +169,14 @@ encodeExchangeAddress net tr = do
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
-- | Decode an Exchange Address into a ExchangeAddress
|
-- | Decode an Exchange Address into a ExchangeAddress
|
||||||
decodeExchangeAddress:: T.Text-> Maybe ExchangeAddress
|
decodeExchangeAddress :: T.Text -> Maybe ExchangeAddress
|
||||||
decodeExchangeAddress ex = do
|
decodeExchangeAddress ex = do
|
||||||
if (T.length ex ) > 1
|
if (T.length ex) > 1
|
||||||
then do
|
then do
|
||||||
let rawd = decodeBech32 (E.encodeUtf8 ex)
|
let rawd = decodeBech32 (E.encodeUtf8 ex)
|
||||||
let tMain = BS.unpack (BC.pack "tex")
|
let tMain = BS.unpack (BC.pack "tex")
|
||||||
let tTest = BS.unpack (BC.pack "textest")
|
let tTest = BS.unpack (BC.pack "textest")
|
||||||
let tFail = BS.unpack (BC.pack "fail")
|
let tFail = BS.unpack (BC.pack "fail")
|
||||||
let hr = BS.unpack (hrp rawd)
|
let hr = BS.unpack (hrp rawd)
|
||||||
if hr /= tFail
|
if hr /= tFail
|
||||||
then do
|
then do
|
||||||
|
@ -180,7 +189,9 @@ decodeExchangeAddress ex = do
|
||||||
if hr == tTest
|
if hr == tTest
|
||||||
then Just $
|
then Just $
|
||||||
ExchangeAddress TestNet $
|
ExchangeAddress TestNet $
|
||||||
TransparentReceiver P2PKH (fromRawBytes transparentReceiver)
|
TransparentReceiver
|
||||||
|
P2PKH
|
||||||
|
(fromRawBytes transparentReceiver)
|
||||||
else Nothing
|
else Nothing
|
||||||
else Nothing
|
else Nothing
|
||||||
else Nothing
|
else Nothing
|
|
@ -638,11 +638,60 @@ data DecodedNote = DecodedNote
|
||||||
, 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_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)
|
||||||
|
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 :: !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 SaplingTxSpend
|
||||||
|
|
||||||
|
data OrchardTxSpend = OrchardTxSpend
|
||||||
|
{ ss_sk :: !BS.ByteString
|
||||||
|
, ss_note :: !DecodedNote
|
||||||
|
, ss_iw :: !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 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
|
||||||
|
|
||||||
-- * Classes
|
-- * Classes
|
||||||
-- | Class to represent types with a bytestring representation
|
-- | Class to represent types with a bytestring representation
|
||||||
class ToBytes a where
|
class ToBytes a where
|
||||||
|
|
|
@ -5,7 +5,7 @@ cabal-version: 3.0
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
|
|
||||||
name: zcash-haskell
|
name: zcash-haskell
|
||||||
version: 0.6.0.0
|
version: 0.6.1.0
|
||||||
synopsis: Utilities to interact with the Zcash blockchain
|
synopsis: Utilities to interact with the Zcash blockchain
|
||||||
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
|
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
|
||||||
category: Blockchain
|
category: Blockchain
|
||||||
|
|
Loading…
Reference in a new issue