Compare commits
18 commits
93a04c09d3
...
1f8a4cbd2b
Author | SHA1 | Date | |
---|---|---|---|
1f8a4cbd2b | |||
817c52dacf | |||
e00cf21709 | |||
2709d42266 | |||
5814cb7c9e | |||
a06fd08172 | |||
3c2e8fc994 | |||
f375467fee | |||
09411adfff | |||
2d39576dc8 | |||
938ccb4b97 | |||
8b1965b46f | |||
2f18c15c86 | |||
204275a9b6 | |||
98fb89b7b0 | |||
6ad879c155 | |||
474aadb5cd | |||
dbae2150da |
11 changed files with 484 additions and 109 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -5,6 +5,16 @@ 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.5.3.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Function to decode Sapling outputs with a spending key
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Parsing of `TxIn` for FFI
|
||||||
|
|
||||||
## [0.5.2.0]
|
## [0.5.2.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
47
librustzcash-wrapper/Cargo.lock
generated
47
librustzcash-wrapper/Cargo.lock
generated
|
@ -961,36 +961,6 @@ dependencies = [
|
||||||
"zcash_note_encryption",
|
"zcash_note_encryption",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "orchard"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fb255c3ffdccd3c84fe9ebed72aef64fdc72e6a3e4180dd411002d47abaad42"
|
|
||||||
dependencies = [
|
|
||||||
"aes",
|
|
||||||
"bitvec",
|
|
||||||
"blake2b_simd",
|
|
||||||
"ff",
|
|
||||||
"fpe",
|
|
||||||
"group",
|
|
||||||
"halo2_gadgets",
|
|
||||||
"halo2_proofs",
|
|
||||||
"hex",
|
|
||||||
"incrementalmerkletree",
|
|
||||||
"lazy_static",
|
|
||||||
"memuse",
|
|
||||||
"nonempty",
|
|
||||||
"pasta_curves",
|
|
||||||
"rand",
|
|
||||||
"reddsa",
|
|
||||||
"serde",
|
|
||||||
"subtle",
|
|
||||||
"tracing",
|
|
||||||
"zcash_note_encryption",
|
|
||||||
"zcash_spec",
|
|
||||||
"zip32",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pairing"
|
name = "pairing"
|
||||||
version = "0.23.0"
|
version = "0.23.0"
|
||||||
|
@ -1314,7 +1284,9 @@ dependencies = [
|
||||||
"borsh 0.10.3",
|
"borsh 0.10.3",
|
||||||
"f4jumble",
|
"f4jumble",
|
||||||
"haskell-ffi",
|
"haskell-ffi",
|
||||||
"orchard 0.7.1",
|
"incrementalmerkletree",
|
||||||
|
"nonempty",
|
||||||
|
"orchard",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"zcash_address 0.2.0",
|
"zcash_address 0.2.0",
|
||||||
"zcash_client_backend",
|
"zcash_client_backend",
|
||||||
|
@ -1743,7 +1715,7 @@ dependencies = [
|
||||||
"incrementalmerkletree",
|
"incrementalmerkletree",
|
||||||
"memuse",
|
"memuse",
|
||||||
"nom",
|
"nom",
|
||||||
"orchard 0.6.0",
|
"orchard",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"prost",
|
"prost",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
@ -1806,7 +1778,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"memuse",
|
"memuse",
|
||||||
"nonempty",
|
"nonempty",
|
||||||
"orchard 0.6.0",
|
"orchard",
|
||||||
"rand",
|
"rand",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"sha2 0.10.6",
|
"sha2 0.10.6",
|
||||||
|
@ -1816,15 +1788,6 @@ dependencies = [
|
||||||
"zcash_note_encryption",
|
"zcash_note_encryption",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zcash_spec"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b"
|
|
||||||
dependencies = [
|
|
||||||
"blake2b_simd",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
|
|
@ -11,12 +11,14 @@ f4jumble = "0.1"
|
||||||
zcash_address = "0.2.0"
|
zcash_address = "0.2.0"
|
||||||
borsh = "0.10"
|
borsh = "0.10"
|
||||||
bech32 = "0.11"
|
bech32 = "0.11"
|
||||||
orchard = "0.7.0"
|
orchard = "0.6.0"
|
||||||
zcash_note_encryption = "0.4.0"
|
zcash_note_encryption = "0.4.0"
|
||||||
zcash_primitives = "0.13.0"
|
zcash_primitives = "0.13.0"
|
||||||
zcash_client_backend = "0.10.0"
|
zcash_client_backend = "0.10.0"
|
||||||
zip32 = "0.1.0"
|
zip32 = "0.1.0"
|
||||||
proc-macro2 = "1.0.66"
|
proc-macro2 = "1.0.66"
|
||||||
|
nonempty = "0.7.0"
|
||||||
|
incrementalmerkletree = "0.5.0"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -10,6 +10,8 @@ use std::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use nonempty::NonEmpty;
|
||||||
|
|
||||||
use f4jumble;
|
use f4jumble;
|
||||||
|
|
||||||
use borsh::{BorshDeserialize, BorshSerialize};
|
use borsh::{BorshDeserialize, BorshSerialize};
|
||||||
|
@ -21,6 +23,8 @@ use haskell_ffi::{
|
||||||
FromHaskell, HaskellSize, ToHaskell
|
FromHaskell, HaskellSize, ToHaskell
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use incrementalmerkletree::frontier::CommitmentTree;
|
||||||
|
|
||||||
use zip32;
|
use zip32;
|
||||||
|
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
|
@ -32,6 +36,7 @@ use zcash_primitives::{
|
||||||
},
|
},
|
||||||
zip339::{Count, Mnemonic},
|
zip339::{Count, Mnemonic},
|
||||||
transaction::components::{
|
transaction::components::{
|
||||||
|
amount::Amount,
|
||||||
transparent::{
|
transparent::{
|
||||||
Bundle as TransparentBundle,
|
Bundle as TransparentBundle,
|
||||||
TxIn,
|
TxIn,
|
||||||
|
@ -41,10 +46,16 @@ use zcash_primitives::{
|
||||||
},
|
},
|
||||||
sapling::{
|
sapling::{
|
||||||
GrothProofBytes,
|
GrothProofBytes,
|
||||||
OutputDescription
|
OutputDescription,
|
||||||
|
SpendDescription,
|
||||||
|
Authorized as SaplingAuthorized,
|
||||||
|
Bundle as SaplingBundle
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sapling::{
|
sapling::{
|
||||||
|
Node,
|
||||||
|
MerklePath,
|
||||||
|
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
|
||||||
PaymentAddress,
|
PaymentAddress,
|
||||||
keys::{
|
keys::{
|
||||||
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
||||||
|
@ -57,6 +68,7 @@ use zcash_primitives::{
|
||||||
consensus::{
|
consensus::{
|
||||||
BranchId::Nu5,
|
BranchId::Nu5,
|
||||||
MainNetwork,
|
MainNetwork,
|
||||||
|
TestNetwork,
|
||||||
BlockHeight
|
BlockHeight
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -78,6 +90,11 @@ use zcash_primitives::zip32::DiversifierIndex;
|
||||||
use zcash_primitives::block::BlockHeader;
|
use zcash_primitives::block::BlockHeader;
|
||||||
|
|
||||||
use orchard::{
|
use orchard::{
|
||||||
|
Bundle as OrchardBundle,
|
||||||
|
bundle::{
|
||||||
|
Authorized as OrchardAuthorized,
|
||||||
|
Flags
|
||||||
|
},
|
||||||
Action,
|
Action,
|
||||||
keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope},
|
keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope},
|
||||||
note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment},
|
note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment},
|
||||||
|
@ -130,12 +147,12 @@ impl<RW> ToHaskell<RW> for HrawTx {
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct HshieldedOutput {
|
pub struct HshieldedOutput {
|
||||||
cv: Vec<u8>,
|
cv: Hhex,
|
||||||
cmu: Vec<u8>,
|
cmu: Hhex,
|
||||||
eph_key: Vec<u8>,
|
eph_key: Hhex,
|
||||||
enc_txt: Vec<u8>,
|
enc_txt: Hhex,
|
||||||
out_txt: Vec<u8>,
|
out_txt: Hhex,
|
||||||
proof: Vec<u8>
|
proof: Hhex
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RW> FromHaskell<RW> for HshieldedOutput {
|
impl<RW> FromHaskell<RW> for HshieldedOutput {
|
||||||
|
@ -153,9 +170,15 @@ impl<RW> ToHaskell<RW> for HshieldedOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HshieldedOutput {
|
impl HshieldedOutput {
|
||||||
fn from_object(s: OutputDescription<GrothProofBytes>) -> Result<HshieldedOutput> {
|
fn from_object(s: &OutputDescription<GrothProofBytes>) -> HshieldedOutput {
|
||||||
let o = HshieldedOutput { cv: s.cv().to_bytes().to_vec(), cmu: s.cmu().to_bytes().to_vec(), eph_key: s.ephemeral_key().0.to_vec(), enc_txt: s.enc_ciphertext().to_vec(), out_txt: s.out_ciphertext().to_vec(), proof: s.zkproof().to_vec() };
|
HshieldedOutput { cv: Hhex{ bytes: s.cv().to_bytes().to_vec()}, cmu: Hhex{ bytes: s.cmu().to_bytes().to_vec()}, eph_key: Hhex{ bytes: s.ephemeral_key().0.to_vec()}, enc_txt: Hhex{ bytes: s.enc_ciphertext().to_vec()}, out_txt: Hhex{ bytes: s.out_ciphertext().to_vec()}, proof: Hhex{ bytes: s.zkproof().to_vec()} }
|
||||||
Ok(o)
|
}
|
||||||
|
pub fn pack(sp: &[OutputDescription<GrothProofBytes>]) -> Vec<HshieldedOutput> {
|
||||||
|
let mut r = Vec::new();
|
||||||
|
for s in sp {
|
||||||
|
r.push(HshieldedOutput::from_object(s));
|
||||||
|
}
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +206,16 @@ impl<RW> FromHaskell<RW> for Haction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Haction {
|
||||||
|
pub fn pack(sp: &NonEmpty<Action<Signature<SpendAuth>>>) -> Vec<Haction> {
|
||||||
|
let mut r = Vec::new();
|
||||||
|
for s in sp {
|
||||||
|
r.push(Haction {nf: Hhex { bytes: s.nullifier().to_bytes().to_vec()}, rk: Hhex { bytes: <[u8; 32]>::from(s.rk()).to_vec()}, cmx: Hhex{bytes: s.cmx().to_bytes().to_vec()}, eph_key: Hhex{ bytes: s.encrypted_note().epk_bytes.to_vec()}, enc_txt: Hhex {bytes: s.encrypted_note().enc_ciphertext.to_vec()}, out_txt: Hhex {bytes: s.encrypted_note().out_ciphertext.to_vec()}, cv: Hhex {bytes: s.cv_net().to_bytes().to_vec()}, auth: Hhex { bytes: <[u8; 64]>::from(s.authorization()).to_vec()}});
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Hnote {
|
pub struct Hnote {
|
||||||
note: u64,
|
note: u64,
|
||||||
|
@ -235,7 +268,9 @@ pub struct Htx {
|
||||||
txid: Vec<u8>,
|
txid: Vec<u8>,
|
||||||
locktime: u32,
|
locktime: u32,
|
||||||
expiry: u32,
|
expiry: u32,
|
||||||
t_bundle: HTBundle
|
t_bundle: HTBundle,
|
||||||
|
s_bundle: HSBundle,
|
||||||
|
o_bundle: HOBundle
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for Htx {
|
impl<RW> ToHaskell<RW> for Htx {
|
||||||
|
@ -325,6 +360,105 @@ impl Houtpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct HSBundle {
|
||||||
|
empty: bool,
|
||||||
|
spends: Vec<Hspend>,
|
||||||
|
outputs: Vec<HshieldedOutput> ,
|
||||||
|
value: i64,
|
||||||
|
sig: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for HSBundle {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HSBundle {
|
||||||
|
pub fn from_bundle(sb: &SaplingBundle<SaplingAuthorized>) -> HSBundle {
|
||||||
|
let s = Cursor::new(Vec::new());
|
||||||
|
sb.authorization().binding_sig.write(s.clone()).unwrap();
|
||||||
|
return HSBundle {empty: false, spends: Hspend::pack(sb.shielded_spends()) , outputs: HshieldedOutput::pack(sb.shielded_outputs()) , value: i64::from(sb.value_balance()) , sig: s.into_inner() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct Hspend {
|
||||||
|
cv: Hhex,
|
||||||
|
anchor: Hhex,
|
||||||
|
nullifier: Hhex,
|
||||||
|
rk: Hhex,
|
||||||
|
proof: Hhex,
|
||||||
|
authsig: Hhex
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for Hspend {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hspend {
|
||||||
|
pub fn pack(sp: &[SpendDescription<SaplingAuthorized>]) -> Vec<Hspend> {
|
||||||
|
let mut r = Vec::new();
|
||||||
|
for s in sp {
|
||||||
|
let rk = Cursor::new(Vec::new());
|
||||||
|
let authsig = Cursor::new(Vec::new());
|
||||||
|
s.rk().write(rk.clone()).unwrap();
|
||||||
|
s.spend_auth_sig().write(authsig.clone()).unwrap();
|
||||||
|
r.push(Hspend {cv: Hhex{bytes:s.cv().to_bytes().to_vec()}, anchor: Hhex{bytes:s.anchor().to_bytes().to_vec()}, nullifier: Hhex{bytes:s.nullifier().to_vec()}, rk: Hhex{bytes: rk.into_inner()}, proof: Hhex{bytes:s.zkproof().to_vec()}, authsig: Hhex{bytes:authsig.into_inner()}});
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct HOBundle {
|
||||||
|
empty: bool,
|
||||||
|
actions: Vec<Haction>,
|
||||||
|
flags: Hflags,
|
||||||
|
value: i64,
|
||||||
|
anchor: Hhex,
|
||||||
|
proof: Hhex,
|
||||||
|
bindingsig: Hhex
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for HOBundle {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HOBundle {
|
||||||
|
pub fn from_bundle(b: &OrchardBundle<OrchardAuthorized, Amount>) -> HOBundle {
|
||||||
|
return HOBundle {empty: false, actions: Haction::pack(b.actions()), flags: Hflags::pack(b.flags()), value: i64::from(b.value_balance()), anchor: Hhex{ bytes: b.anchor().to_bytes().to_vec()}, proof: Hhex { bytes: b.authorization().proof().as_ref().to_vec()}, bindingsig: Hhex {bytes: <[u8; 64]>::from(b.authorization().binding_signature()).to_vec()}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct Hflags {
|
||||||
|
spends: bool,
|
||||||
|
outputs: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for Hflags {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hflags {
|
||||||
|
pub fn pack(f: &Flags) -> Hflags {
|
||||||
|
return Hflags {spends: f.spends_enabled(), outputs: f.outputs_enabled()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Hufvk {
|
pub struct Hufvk {
|
||||||
net: u8,
|
net: u8,
|
||||||
|
@ -474,7 +608,7 @@ pub extern "C" fn rust_wrapper_svk_decode(
|
||||||
let input: Vec<u8> = marshall_from_haskell_var(input, input_len, RW);
|
let input: Vec<u8> = marshall_from_haskell_var(input, input_len, RW);
|
||||||
let svk = ExtendedFullViewingKey::read(&*input);
|
let svk = ExtendedFullViewingKey::read(&*input);
|
||||||
match svk {
|
match svk {
|
||||||
Ok(k) => {
|
Ok(_k) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -570,6 +704,64 @@ pub extern "C" fn rust_wrapper_ufvk_decode(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
|
||||||
|
key: *const u8,
|
||||||
|
key_len: usize,
|
||||||
|
note: *const u8,
|
||||||
|
note_len: usize,
|
||||||
|
external: bool,
|
||||||
|
net: bool,
|
||||||
|
out: *mut u8,
|
||||||
|
out_len: &mut usize
|
||||||
|
){
|
||||||
|
let sk: Vec<u8> = marshall_from_haskell_var(key, key_len, RW);
|
||||||
|
let note_input: Vec<u8> = marshall_from_haskell_var(note,note_len,RW);
|
||||||
|
let mut note_reader = Cursor::new(note_input);
|
||||||
|
let esk = ExtendedSpendingKey::from_bytes(&sk);
|
||||||
|
let main_domain = SaplingDomain::for_height(MainNetwork, BlockHeight::from_u32(419200));
|
||||||
|
let test_domain = SaplingDomain::for_height(TestNetwork, BlockHeight::from_u32(419200));
|
||||||
|
let scope = if external {
|
||||||
|
SaplingScope::External
|
||||||
|
} else {
|
||||||
|
SaplingScope::Internal
|
||||||
|
};
|
||||||
|
match esk {
|
||||||
|
Ok(k) => {
|
||||||
|
let action = OutputDescription::read(&mut note_reader);
|
||||||
|
match action {
|
||||||
|
Ok(action2) => {
|
||||||
|
let dfvk = k.to_diversifiable_full_viewing_key();
|
||||||
|
let ivk = dfvk.to_ivk(scope);
|
||||||
|
let nk = dfvk.to_nk(scope);
|
||||||
|
let pivk = SaplingPreparedIncomingViewingKey::new(&ivk);
|
||||||
|
let result = if net { zcash_note_encryption::try_note_decryption(&main_domain, &pivk, &action2)}
|
||||||
|
else {zcash_note_encryption::try_note_decryption(&test_domain, &pivk, &action2)};
|
||||||
|
match result {
|
||||||
|
Some((n, r, m)) => {
|
||||||
|
//let nullifier = n.nf(&nk, MerklePath<Node::from_cmu(&n.cmu()), SAPLING_DEPTH>.position());
|
||||||
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec() };
|
||||||
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_e1) => {
|
||||||
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||||
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||||
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
|
pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
|
||||||
key: *const u8,
|
key: *const u8,
|
||||||
|
@ -594,11 +786,11 @@ 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() };
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec()};
|
||||||
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] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,7 +802,7 @@ pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -644,17 +836,17 @@ 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() };
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec()};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: 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] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -674,19 +866,38 @@ pub extern "C" fn rust_wrapper_tx_read(
|
||||||
match parsed_tx {
|
match parsed_tx {
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
let tb = t.transparent_bundle();
|
let tb = t.transparent_bundle();
|
||||||
match tb {
|
let sb = t.sapling_bundle();
|
||||||
Some(my_tb) => {
|
let ob = t.orchard_bundle();
|
||||||
let h = Htx {txid: t.txid().as_ref().to_vec(), locktime: t.lock_time(), expiry: u32::from(t.expiry_height()), t_bundle: HTBundle::from_bundle(my_tb) };
|
let h1 = Htx
|
||||||
marshall_to_haskell_var(&h, out, out_len, RW);
|
{ txid: t.txid().as_ref().to_vec()
|
||||||
},
|
, locktime: t.lock_time()
|
||||||
None => {
|
, expiry: u32::from(t.expiry_height())
|
||||||
let h0 = Htx {txid: t.txid().as_ref().to_vec(), locktime: t.lock_time(), expiry: u32::from(t.expiry_height()), t_bundle: HTBundle {empty: true, vin: vec![HTxIn {outpoint: Houtpoint {hash: vec![0], index: 0}, script: vec![0], sequence: 0}], vout: vec![HTxOut {amt: 0, script: vec![0]}], coinbase: true} };
|
, t_bundle: match tb {
|
||||||
marshall_to_haskell_var(&h0, out, out_len, RW);
|
Some(tb1) => {HTBundle::from_bundle(tb1)},
|
||||||
|
None => {HTBundle {empty: true, vin: vec![HTxIn {outpoint: Houtpoint {hash: vec![0], index: 0}, script: vec![0], sequence: 0}], vout: vec![HTxOut {amt: 0, script: vec![0]}], coinbase: false}}}
|
||||||
|
, s_bundle: match sb {
|
||||||
|
Some(sb1) => {HSBundle::from_bundle(sb1)},
|
||||||
|
None => {HSBundle{empty: true, spends: vec![Hspend{cv:Hhex { bytes: vec![0]} , anchor:Hhex { bytes: vec![0]} , nullifier:Hhex { bytes: vec![0]} , rk:Hhex { bytes: vec![0]} , proof:Hhex { bytes: vec![0]} , authsig:Hhex { bytes: vec![0]} }], outputs: vec![HshieldedOutput {cv: Hhex { bytes: vec![0]}, cmu: Hhex { bytes: vec![0]}, eph_key: Hhex { bytes: vec![0]}, enc_txt: Hhex { bytes: vec![0]}, out_txt: Hhex { bytes: vec![0]}, proof: Hhex { bytes: vec![0]}}], value: 0, sig: vec![0]}} }
|
||||||
|
, o_bundle: match ob {
|
||||||
|
Some(ob1) => {HOBundle::from_bundle(ob1)},
|
||||||
|
None => {HOBundle{empty: true, actions: vec![Haction {nf:Hhex { bytes: vec![0]} , rk:Hhex { bytes: vec![0]} , cmx:Hhex { bytes: vec![0]} , eph_key:Hhex { bytes: vec![0]} , enc_txt:Hhex { bytes: vec![0]} , out_txt:Hhex { bytes: vec![0]} , cv:Hhex { bytes: vec![0]} , auth:Hhex { bytes: vec![0]} }], flags: Hflags{ spends:false, outputs:false}, value: 0, anchor: Hhex { bytes: vec![0]}, proof: Hhex { bytes: vec![0]} , bindingsig: Hhex { bytes: vec![0]}}}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
marshall_to_haskell_var(&h1, out, out_len, RW);
|
||||||
},
|
},
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let h0 = Htx {txid: vec![0], locktime: 0, expiry: 0, t_bundle: HTBundle {empty: true, vin: vec![HTxIn {outpoint: Houtpoint {hash: vec![0], index: 0}, script: vec![0], sequence: 0}], vout: vec![HTxOut {amt: 0, script: vec![0]}], coinbase: true} };
|
let h0 = Htx
|
||||||
|
{txid: vec![0],
|
||||||
|
locktime: 0,
|
||||||
|
expiry: 0,
|
||||||
|
t_bundle: HTBundle
|
||||||
|
{empty: true,
|
||||||
|
vin: vec![HTxIn {outpoint: Houtpoint {hash: vec![0], index: 0}, script: vec![0], sequence: 0}],
|
||||||
|
vout: vec![HTxOut {amt: 0, script: vec![0]}],
|
||||||
|
coinbase: true},
|
||||||
|
s_bundle: HSBundle{empty: true, spends: vec![Hspend{cv:Hhex { bytes: vec![0]} , anchor:Hhex { bytes: vec![0]} , nullifier:Hhex { bytes: vec![0]} , rk:Hhex { bytes: vec![0]} , proof:Hhex { bytes: vec![0]} , authsig:Hhex { bytes: vec![0]} }], outputs: vec![HshieldedOutput {cv: Hhex { bytes: vec![0]}, cmu: Hhex { bytes: vec![0]}, eph_key: Hhex { bytes: vec![0]}, enc_txt: Hhex { bytes: vec![0]}, out_txt: Hhex { bytes: vec![0]}, proof: Hhex { bytes: vec![0]}}], value: 0, sig: vec![0]},
|
||||||
|
o_bundle: HOBundle{empty: true, actions: vec![Haction {nf:Hhex { bytes: vec![0]} , rk:Hhex { bytes: vec![0]} , cmx:Hhex { bytes: vec![0]} , eph_key:Hhex { bytes: vec![0]} , enc_txt:Hhex { bytes: vec![0]} , out_txt:Hhex { bytes: vec![0]} , cv:Hhex { bytes: vec![0]} , auth:Hhex { bytes: vec![0]} }], flags: Hflags{ spends:false, outputs:false}, value: 0, anchor: Hhex { bytes: vec![0]}, proof: Hhex { bytes: vec![0]} , bindingsig: Hhex { bytes: vec![0]}}
|
||||||
|
};
|
||||||
marshall_to_haskell_var(&h0, out, out_len, RW);
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,7 +1058,7 @@ pub extern "C" fn rust_wrapper_derive_orchard_spending_key(
|
||||||
out_len: &mut usize
|
out_len: &mut usize
|
||||||
){
|
){
|
||||||
let s: Vec<u8> = marshall_from_haskell_var(seed, seed_len, RW);
|
let s: Vec<u8> = marshall_from_haskell_var(seed, seed_len, RW);
|
||||||
let sk = SpendingKey::from_zip32_seed(&s, coin_type, zip32::AccountId::try_from(acc_id).unwrap());
|
let sk = SpendingKey::from_zip32_seed(&s, coin_type, u32::from(zip32::AccountId::try_from(acc_id).unwrap()));
|
||||||
match sk {
|
match sk {
|
||||||
Ok(key) => {
|
Ok(key) => {
|
||||||
marshall_to_haskell_var(&key.to_bytes().to_vec(), out, out_len, RW);
|
marshall_to_haskell_var(&key.to_bytes().to_vec(), out, out_len, RW);
|
||||||
|
|
|
@ -101,6 +101,16 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_esk_decrypt as rustWrapperSaplingDecodeEsk
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, `Bool'
|
||||||
|
, `Bool'
|
||||||
|
, 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'&
|
||||||
|
|
|
@ -153,3 +153,21 @@ decryptOrchardAction key encAction =
|
||||||
decodedAction =
|
decodedAction =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperOrchardNoteDecode (o_key key) encAction
|
rustWrapperOrchardNoteDecode (o_key key) encAction
|
||||||
|
|
||||||
|
chrToByteString :: [Char] -> C.ByteString
|
||||||
|
chrToByteString = C.pack
|
||||||
|
|
||||||
|
getSaplingFromUA :: BS.ByteString -> T.Text
|
||||||
|
getSaplingFromUA uadd = do
|
||||||
|
let a = isValidUnifiedAddress uadd
|
||||||
|
case a of
|
||||||
|
Nothing -> "xxx"
|
||||||
|
Just a -> do
|
||||||
|
let sraw = s_rec a
|
||||||
|
case sraw of
|
||||||
|
Nothing -> "xxx"
|
||||||
|
Just sraw -> do
|
||||||
|
let net = ua_net a
|
||||||
|
case net of
|
||||||
|
MainNet -> encodeBech32m (chrToByteString sapPaymentAddressHrp) ( getBytes sraw )
|
||||||
|
TestNet -> encodeBech32m (chrToByteString sapTestPaymentAddressHrp) ( getBytes sraw )
|
|
@ -21,6 +21,7 @@ import C.Zcash
|
||||||
( rustWrapperIsShielded
|
( rustWrapperIsShielded
|
||||||
, rustWrapperSaplingCheck
|
, rustWrapperSaplingCheck
|
||||||
, rustWrapperSaplingChgPaymentAddress
|
, rustWrapperSaplingChgPaymentAddress
|
||||||
|
, rustWrapperSaplingDecodeEsk
|
||||||
, rustWrapperSaplingNoteDecode
|
, rustWrapperSaplingNoteDecode
|
||||||
, rustWrapperSaplingPaymentAddress
|
, rustWrapperSaplingPaymentAddress
|
||||||
, rustWrapperSaplingSpendingkey
|
, rustWrapperSaplingSpendingkey
|
||||||
|
@ -29,7 +30,7 @@ import C.Zcash
|
||||||
)
|
)
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.HexString (HexString(..), toBytes)
|
import Data.HexString (HexString(..), fromText, toBytes, toText)
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Foreign.Rust.Marshall.Variable
|
import Foreign.Rust.Marshall.Variable
|
||||||
( withPureBorshVarBuffer
|
( withPureBorshVarBuffer
|
||||||
|
@ -43,9 +44,11 @@ import ZcashHaskell.Types
|
||||||
, RawTxResponse(..)
|
, RawTxResponse(..)
|
||||||
, SaplingReceiver(..)
|
, SaplingReceiver(..)
|
||||||
, SaplingSpendingKey(..)
|
, SaplingSpendingKey(..)
|
||||||
|
, Scope(..)
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
, ShieldedOutput(..)
|
, ShieldedOutput(..)
|
||||||
, ToBytes(..)
|
, ToBytes(..)
|
||||||
|
, ZcashNet(..)
|
||||||
, decodeHexText
|
, decodeHexText
|
||||||
, getValue
|
, getValue
|
||||||
)
|
)
|
||||||
|
@ -58,6 +61,15 @@ isValidShieldedAddress = rustWrapperIsShielded
|
||||||
getShieldedOutputs :: HexString -> [BS.ByteString]
|
getShieldedOutputs :: HexString -> [BS.ByteString]
|
||||||
getShieldedOutputs t = withPureBorshVarBuffer $ rustWrapperTxParse $ toBytes 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
|
||||||
isValidSaplingViewingKey k =
|
isValidSaplingViewingKey k =
|
||||||
|
@ -98,6 +110,26 @@ instance FromJSON RawTxResponse where
|
||||||
a <- o' .: "actions"
|
a <- o' .: "actions"
|
||||||
pure $ RawTxResponse i h sSpend (getShieldedOutputs h) a ht c b
|
pure $ RawTxResponse i h sSpend (getShieldedOutputs h) a ht c b
|
||||||
|
|
||||||
|
-- | Attempt to decode the given raw tx with the given Sapling spending key
|
||||||
|
decodeSaplingOutputEsk ::
|
||||||
|
SaplingSpendingKey
|
||||||
|
-> ShieldedOutput
|
||||||
|
-> ZcashNet
|
||||||
|
-> Scope
|
||||||
|
-> Maybe DecodedNote
|
||||||
|
decodeSaplingOutputEsk key out znet scope =
|
||||||
|
case a_value decodedAction of
|
||||||
|
0 -> Nothing
|
||||||
|
_ -> Just decodedAction
|
||||||
|
where
|
||||||
|
decodedAction =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperSaplingDecodeEsk
|
||||||
|
(getBytes key)
|
||||||
|
(serializeShieldedOutput out)
|
||||||
|
(znet == MainNet)
|
||||||
|
(scope == External)
|
||||||
|
|
||||||
-- | Attempts to obtain a sapling SpendingKey using a HDSeed
|
-- | Attempts to obtain a sapling SpendingKey using a HDSeed
|
||||||
genSaplingSpendingKey :: Seed -> CoinType -> Int -> Maybe SaplingSpendingKey
|
genSaplingSpendingKey :: Seed -> CoinType -> Int -> Maybe SaplingSpendingKey
|
||||||
genSaplingSpendingKey seed c i = do
|
genSaplingSpendingKey seed c i = do
|
||||||
|
|
|
@ -129,6 +129,8 @@ data Transaction = Transaction
|
||||||
, tx_conf :: !Int
|
, tx_conf :: !Int
|
||||||
, tx_expiry :: !Int
|
, tx_expiry :: !Int
|
||||||
, tx_transpBundle :: !(Maybe TransparentBundle)
|
, tx_transpBundle :: !(Maybe TransparentBundle)
|
||||||
|
, tx_saplingBundle :: !(Maybe SaplingBundle)
|
||||||
|
, tx_orchardBundle :: !(Maybe OrchardBundle)
|
||||||
} deriving (Prelude.Show, Eq, Read)
|
} deriving (Prelude.Show, Eq, Read)
|
||||||
|
|
||||||
-- | The transparent portion of a Zcash transaction
|
-- | The transparent portion of a Zcash transaction
|
||||||
|
@ -158,7 +160,7 @@ fromRawTxIn t = H.TxIn op (rti_script t) (rti_seq t)
|
||||||
then H.nullOutPoint
|
then H.nullOutPoint
|
||||||
else H.OutPoint
|
else H.OutPoint
|
||||||
((fromJust .
|
((fromJust .
|
||||||
H.hexToTxHash . E.decodeUtf8Lenient . rop_hash . rti_outpoint)
|
H.hexToTxHash . toText . fromRawBytes . rop_hash . rti_outpoint)
|
||||||
t)
|
t)
|
||||||
(rop_n $ rti_outpoint t)
|
(rop_n $ rti_outpoint t)
|
||||||
|
|
||||||
|
@ -285,6 +287,8 @@ data RawZebraTx = RawZebraTx
|
||||||
, zt_locktime :: !Word32
|
, zt_locktime :: !Word32
|
||||||
, zt_expiry :: !Word32
|
, zt_expiry :: !Word32
|
||||||
, zt_tBundle :: !RawTBundle
|
, 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 (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
@ -301,6 +305,78 @@ data RawTBundle = RawTBundle
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawTBundle
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
-- | Type for the response from the `zebrad` RPC method `getinfo`
|
-- | Type for the response from the `zebrad` RPC method `getinfo`
|
||||||
data ZebraGetInfo = ZebraGetInfo
|
data ZebraGetInfo = ZebraGetInfo
|
||||||
{ zgi_build :: !T.Text
|
{ zgi_build :: !T.Text
|
||||||
|
@ -427,7 +503,7 @@ data ShieldedOutput = ShieldedOutput
|
||||||
, s_encCipherText :: !HexString -- ^ The output note encrypted to the recipient
|
, s_encCipherText :: !HexString -- ^ The output note encrypted to the recipient
|
||||||
, s_outCipherText :: !HexString -- ^ A ciphertext enabling the sender to recover the output note
|
, s_outCipherText :: !HexString -- ^ A ciphertext enabling the sender to recover the output note
|
||||||
, s_proof :: !HexString -- ^ Zero-knowledge proof using the Sapling Output circuit
|
, s_proof :: !HexString -- ^ Zero-knowledge proof using the Sapling Output circuit
|
||||||
} 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 ShieldedOutput
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct ShieldedOutput
|
||||||
|
@ -482,10 +558,10 @@ data RawUA = RawUA
|
||||||
|
|
||||||
-- | 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)
|
||||||
|
@ -493,14 +569,14 @@ 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 :: HexString -- ^ The nullifier of the input note
|
{ nf :: !HexString -- ^ The nullifier of the input note
|
||||||
, rk :: HexString -- ^ The randomized validating key for @auth@
|
, rk :: !HexString -- ^ The randomized validating key for @auth@
|
||||||
, cmx :: HexString -- ^ 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 :: HexString -- ^ An encoding of an ephemeral Pallas public key
|
, eph_key :: !HexString -- ^ An encoding of an ephemeral Pallas public key
|
||||||
, enc_ciphertext :: HexString -- ^ The output note encrypted to the recipient
|
, enc_ciphertext :: !HexString -- ^ The output note encrypted to the recipient
|
||||||
, out_ciphertext :: HexString -- ^ A ciphertext enabling the sender to recover the output note
|
, out_ciphertext :: !HexString -- ^ A ciphertext enabling the sender to recover the output note
|
||||||
, cv :: HexString -- ^ 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 :: HexString -- ^ 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, Read)
|
} 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)
|
||||||
|
@ -521,9 +597,9 @@ instance FromJSON OrchardAction where
|
||||||
|
|
||||||
-- | 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.
|
||||||
} 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)
|
||||||
|
|
|
@ -115,3 +115,4 @@ readZebraTransaction hex =
|
||||||
else Just rawTx
|
else Just rawTx
|
||||||
where
|
where
|
||||||
rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex
|
rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex
|
||||||
|
|
||||||
|
|
88
test/Spec.hs
88
test/Spec.hs
File diff suppressed because one or more lines are too long
|
@ -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.5.2.0
|
version: 0.5.3.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