zcash-haskell/librustzcash-wrapper/src/lib.rs

1259 lines
41 KiB
Rust
Raw Normal View History

2023-12-20 20:03:42 +00:00
// Copyright 2022-2024 Vergara Technologies LLC
//
// This file is part of Zcash-Haskell.
//
2023-04-16 00:07:08 +00:00
use std::{
marker::PhantomData,
2023-08-23 20:19:31 +00:00
io::{
Write,
Cursor,
Error
2023-08-23 20:19:31 +00:00
},
2023-04-16 00:07:08 +00:00
};
use nonempty::NonEmpty;
2023-04-16 00:07:08 +00:00
use f4jumble;
use borsh::{BorshDeserialize, BorshSerialize};
2023-04-27 14:48:11 +00:00
2023-04-16 00:07:08 +00:00
use haskell_ffi::{
error::Result,
2023-05-04 14:23:05 +00:00
from_haskell::{marshall_from_haskell_var, marshall_from_haskell_fixed},
2023-04-16 00:07:08 +00:00
to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed},
FromHaskell, HaskellSize, ToHaskell
};
use incrementalmerkletree::{
frontier::CommitmentTree,
witness::IncrementalWitness
};
2024-03-05 20:43:33 +00:00
use zip32;
2023-06-15 00:09:43 +00:00
use zcash_primitives::{
merkle_tree::{
read_commitment_tree,
write_commitment_tree,
read_incremental_witness,
write_incremental_witness
},
2024-03-10 12:47:26 +00:00
zip32::{
Scope as SaplingScope,
2024-03-11 20:23:29 +00:00
ChildIndex,
2024-03-10 12:47:26 +00:00
sapling_find_address,
sapling::DiversifierKey
},
zip339::{Count, Mnemonic},
transaction::components::{
2024-03-29 18:54:21 +00:00
amount::Amount,
transparent::{
Bundle as TransparentBundle,
TxIn,
TxOut,
OutPoint,
Authorized
},
sapling::{
GrothProofBytes,
2024-03-29 18:54:21 +00:00
OutputDescription,
SpendDescription,
Authorized as SaplingAuthorized,
Bundle as SaplingBundle
}
2023-06-15 00:09:43 +00:00
},
sapling::{
Node,
MerklePath,
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
2023-06-15 00:09:43 +00:00
PaymentAddress,
note::ExtractedNoteCommitment as SaplingNoteCommitment,
2024-03-10 12:47:26 +00:00
keys::{
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
ExpandedSpendingKey,
FullViewingKey as SaplingFullViewingKey
},
2024-03-05 20:43:33 +00:00
note_encryption::SaplingDomain
2023-06-15 00:09:43 +00:00
},
2023-08-23 20:19:31 +00:00
transaction::Transaction,
2023-06-15 00:09:43 +00:00
consensus::{
2023-08-23 20:19:31 +00:00
BranchId::Nu5,
2023-06-15 00:09:43 +00:00
MainNetwork,
TestNetwork,
2023-06-15 00:09:43 +00:00
BlockHeight
}
2023-06-14 15:54:02 +00:00
};
2023-06-14 14:55:52 +00:00
2023-04-16 00:07:08 +00:00
use zcash_address::{
Network,
unified::{Address, Encoding, Ufvk, Container, Fvk, Receiver},
2023-04-18 18:58:21 +00:00
ZcashAddress
2023-04-16 00:07:08 +00:00
};
2024-03-10 12:47:26 +00:00
use zcash_client_backend::keys::sapling::{
spending_key,
2024-03-10 12:47:26 +00:00
ExtendedFullViewingKey,
ExtendedSpendingKey,
DiversifiableFullViewingKey
2024-03-10 12:47:26 +00:00
};
use zcash_primitives::zip32::DiversifierIndex;
2024-03-28 19:06:02 +00:00
use zcash_primitives::block::BlockHeader;
2023-06-14 14:55:52 +00:00
2023-05-04 14:23:05 +00:00
use orchard::{
2024-03-29 18:54:21 +00:00
Bundle as OrchardBundle,
bundle::{
Authorized as OrchardAuthorized,
Flags
},
2023-05-04 14:23:05 +00:00
Action,
2024-03-05 20:43:33 +00:00
keys::{SpendingKey, FullViewingKey, PreparedIncomingViewingKey, Scope},
2023-05-04 14:23:05 +00:00
note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment},
note_encryption::OrchardDomain,
primitives::redpallas::{VerificationKey, SpendAuth, Signature},
value::ValueCommitment
};
2023-04-27 14:48:11 +00:00
use bech32::{
Hrp,
Bech32,
Bech32m
2023-04-27 14:48:11 +00:00
};
2023-04-16 00:07:08 +00:00
pub enum RW {}
pub const RW: PhantomData<RW> = PhantomData;
2023-04-27 14:48:11 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct RawData {
hrp: Vec<u8>,
bytes: Vec<u8>
}
impl<RW> ToHaskell<RW> for RawData {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
//impl<RW> FromHaskell<RW> for RawData {
//fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
//let x = RawData::deserialize(buf)?;
//Ok(x)
//}
//}
2023-09-25 12:51:14 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HrawTx {
bytes: Vec<u8>,
s: bool,
o: bool
}
impl<RW> ToHaskell<RW> for HrawTx {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
2023-06-15 00:09:43 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HshieldedOutput {
cv: Hhex,
cmu: Hhex,
eph_key: Hhex,
enc_txt: Hhex,
out_txt: Hhex,
proof: Hhex
2023-06-15 00:09:43 +00:00
}
impl<RW> FromHaskell<RW> for HshieldedOutput {
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
let x = HshieldedOutput::deserialize(buf)?;
Ok(x)
}
}
2023-09-25 12:51:14 +00:00
impl<RW> ToHaskell<RW> for HshieldedOutput {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl HshieldedOutput {
fn from_object(s: &OutputDescription<GrothProofBytes>) -> HshieldedOutput {
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()} }
}
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
2023-09-25 12:51:14 +00:00
}
}
2024-02-06 19:10:06 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Hhex {
bytes: Vec<u8>
}
impl<RW> ToHaskell<RW> for Hhex {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
2023-05-04 14:23:05 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Haction {
2024-02-06 19:10:06 +00:00
nf: Hhex,
rk: Hhex,
cmx: Hhex,
eph_key: Hhex,
enc_txt: Hhex,
out_txt: Hhex,
cv: Hhex,
auth: Hhex
2023-05-04 14:23:05 +00:00
}
impl<RW> FromHaskell<RW> for Haction {
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
let x = Haction::deserialize(buf)?;
Ok(x)
}
}
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
}
}
2023-05-04 14:23:05 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Hnote {
note: u64,
recipient: Vec<u8>,
memo: Vec<u8>,
nullifier: Vec<u8>
2023-05-04 14:23:05 +00:00
}
impl<RW> ToHaskell<RW> for Hnote {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
2024-01-12 15:46:26 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Hua {
net: u8,
o_rec: Vec<u8>,
s_rec: Vec<u8>,
t_rec: Vec<u8>,
to_rec: Vec<u8>
}
impl<RW> ToHaskell<RW> for Hua {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl Hua {
fn add_rec(&mut self, rec: &Receiver) {
if let Receiver::Orchard(x) = rec {
self.o_rec = x.to_vec();
}
if let Receiver::Sapling(y) = rec {
self.s_rec = y.to_vec();
}
if let Receiver::P2pkh(z) = rec {
self.t_rec = z.to_vec();
}
if let Receiver::P2sh(w) = rec {
self.to_rec = w.to_vec();
}
}
}
2023-05-04 14:23:05 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Htx {
txid: Vec<u8>,
locktime: u32,
expiry: u32,
2024-03-29 18:54:21 +00:00
t_bundle: HTBundle,
s_bundle: HSBundle,
o_bundle: HOBundle
}
impl<RW> ToHaskell<RW> for Htx {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HTBundle {
empty: bool,
vin: Vec<HTxIn>,
vout: Vec<HTxOut>,
coinbase: bool
}
impl<RW> ToHaskell<RW> for HTBundle {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl HTBundle {
pub fn from_bundle(b: &TransparentBundle<Authorized>) -> HTBundle {
HTBundle {empty: false, vin: b.vin.iter().map(HTxIn::pack).collect() , vout: b.vout.iter().map(HTxOut::pack).collect(), coinbase: b.is_coinbase()}
}
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HTxIn {
outpoint: Houtpoint,
script: Vec<u8>,
sequence: u32
}
impl<RW> ToHaskell<RW> for HTxIn {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl HTxIn {
pub fn pack(t: &TxIn<Authorized>) -> HTxIn {
return HTxIn { outpoint: Houtpoint::pack(&t.prevout), script: t.script_sig.0.clone(), sequence: t.sequence}
}
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HTxOut {
amt: i64,
script: Vec<u8>
}
impl<RW> ToHaskell<RW> for HTxOut {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl 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() }
}
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Houtpoint {
hash: Vec<u8>,
index: u32
}
impl<RW> ToHaskell<RW> for Houtpoint {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl Houtpoint {
pub fn pack(o: &OutPoint) -> Houtpoint {
return Houtpoint {hash: o.hash().to_vec() , index: o.n() }
}
}
2024-03-29 18:54:21 +00:00
#[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() }
2024-03-29 18:54:21 +00:00
}
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Hspend {
cv: Hhex,
anchor: Hhex,
nullifier: Hhex,
rk: Hhex,
proof: Hhex,
authsig: Hhex
2024-03-29 18:54:21 +00:00
}
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
2024-03-29 18:54:21 +00:00
}
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HOBundle {
empty: bool,
actions: Vec<Haction>,
flags: Hflags,
2024-03-29 18:54:21 +00:00
value: i64,
anchor: Hhex,
proof: Hhex,
bindingsig: Hhex
2024-03-29 18:54:21 +00:00
}
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()}}
2024-03-29 18:54:21 +00:00
}
}
#[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()}
}
}
2023-04-27 14:48:11 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Hufvk {
net: u8,
orchard: Vec<u8>,
sapling: Vec<u8>,
transparent: Vec<u8>
}
impl<RW> ToHaskell<RW> for Hufvk {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl Hufvk {
fn add_key_section(&mut self, fvk: &Fvk) {
if let Fvk::Orchard(v) = fvk {
self.orchard = v.to_vec();
}
if let Fvk::Sapling(w) = fvk {
self.sapling = w.to_vec();
}
if let Fvk::P2pkh(x) = fvk {
self.transparent = x.to_vec();
}
}
}
2023-06-14 14:55:52 +00:00
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Hsvk {
vk: Vec<u8>,
ovk: Vec<u8>
}
impl<RW> ToHaskell<RW> for Hsvk {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
2023-05-04 14:23:05 +00:00
fn to_array<T, const N: usize>(v: Vec<T>) -> [T; N] {
v.try_into().unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
}
2023-04-16 00:07:08 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_f4jumble(
input: *const u8,
input_len: usize,
out: *mut u8,
out_len: &mut usize) {
let input: Vec<u8> = marshall_from_haskell_var(input, input_len, RW);
let result = f4jumble::f4jumble(&input).unwrap();
marshall_to_haskell_var(&result, out, out_len, RW);
}
2023-04-27 14:48:11 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_f4unjumble(
input: *const u8,
input_len: usize,
out: *mut u8,
out_len: &mut usize) {
let input: Vec<u8> = marshall_from_haskell_var(input, input_len, RW);
let result = f4jumble::f4jumble_inv(&input).unwrap();
marshall_to_haskell_var(&result, out, out_len, RW);
}
2023-04-16 00:07:08 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_ua_decode(
input: *const u8,
2024-01-12 15:46:26 +00:00
input_len: usize,
out: *mut u8,
out_len: &mut usize) {
2023-04-16 00:07:08 +00:00
let input: String = marshall_from_haskell_var(input, input_len, RW);
2024-01-12 15:46:26 +00:00
let dec_addy = Address::decode(&input);
match dec_addy {
Ok((n, ua)) => {
let x = match n {
Network::Main => 1,
Network::Test => 2,
Network::Regtest => 3
};
let mut hk = Hua { net: x, o_rec: vec![0], s_rec: vec![0], t_rec: vec![0], to_rec: vec![0] };
let recvs = ua.items();
recvs.iter().for_each(|k| hk.add_rec(k));
marshall_to_haskell_var(&hk, out, out_len, RW);
}
Err(_e) => {
let hk0 = Hua { net: 0, o_rec: vec![0], s_rec: vec![0], t_rec: vec![0], to_rec: vec![0]};
marshall_to_haskell_var(&hk0, out, out_len, RW);
}
}
2023-04-16 00:07:08 +00:00
//marshall_to_haskell_var(&result, out, out_len, RW);
}
2023-04-18 18:58:21 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_shielded_decode(
input: *const u8,
input_len: usize) -> bool {
let input: String = marshall_from_haskell_var(input, input_len, RW);
ZcashAddress::try_from_encoded(&input).is_ok()
}
2023-04-27 14:48:11 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_bech32decode(
input: *const u8,
input_len: usize,
out: *mut u8,
out_len: &mut usize
) {
let input: String = marshall_from_haskell_var(input, input_len, RW);
2024-03-04 17:58:04 +00:00
let decoded_bytes = bech32::decode(&input);
match decoded_bytes {
Ok((hrp, bytes)) => {
let rd = RawData {hrp: hrp.as_bytes().to_vec(), bytes};
2023-06-14 14:55:52 +00:00
marshall_to_haskell_var(&rd, out, out_len, RW);
}
Err(_e) => {
let rd1 = RawData {hrp: "fail".into(), bytes: vec![0]};
marshall_to_haskell_var(&rd1, out, out_len, RW);
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_bech32m_encode(
hr: *const u8,
hr_len: usize,
b: *const u8,
b_len: usize,
out: *mut u8,
out_len: &mut usize
) {
let hr: String = marshall_from_haskell_var(hr, hr_len, RW);
let hrp = Hrp::parse(&hr).unwrap();
let b: Vec<u8> = marshall_from_haskell_var(b, b_len, RW);
let string = bech32::encode::<Bech32m>(hrp, &b).unwrap();
marshall_to_haskell_var(&string, out, out_len, RW);
}
2023-06-14 14:55:52 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_svk_decode(
input: *const u8,
input_len: usize
) -> bool {
let input: Vec<u8> = marshall_from_haskell_var(input, input_len, RW);
let svk = ExtendedFullViewingKey::read(&*input);
match svk {
Ok(_k) => {
2023-06-14 14:55:52 +00:00
true
}
Err(e) => {
print!("{}", e);
false
}
}
2023-04-27 14:48:11 +00:00
}
2023-06-14 15:54:02 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_svk_check_address(
key_input: *const u8,
key_input_len: usize,
address_input: *const u8,
address_input_len: usize
) -> bool {
let key_input: Vec<u8> = marshall_from_haskell_var(key_input, key_input_len, RW);
let address_input: Vec<u8> = marshall_from_haskell_var(address_input, address_input_len, RW);
let svk = ExtendedFullViewingKey::read(&*key_input);
let sa = PaymentAddress::from_bytes(&to_array(address_input)).unwrap();
match svk {
Ok(k) => {
let (div_index, def_address) = k.default_address();
sa == def_address
}
Err(e) => {
false
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_ufvk_check_address(
key_input: *const u8,
key_input_len: usize,
address_input: *const u8,
address_input_len: usize
) -> bool {
let key: String = marshall_from_haskell_var(key_input, key_input_len, RW);
let addy: String = marshall_from_haskell_var(address_input, address_input_len, RW);
let dec_key = Ufvk::decode(&key);
let dec_addy = Address::decode(&addy);
match dec_key {
Ok((n, ufvk)) => {
let i = ufvk.items();
if let Fvk::Orchard(k) = i[0] {
let orch_key = FullViewingKey::from_bytes(&k).unwrap();
let orch_addy = orch_key.address_at(0u32, Scope::External).to_raw_address_bytes();
match dec_addy {
Ok((n, recs)) => {
let j = recs.items();
j[0] == Receiver::Orchard(orch_addy)
},
Err(_e) => {
false
}
}
} else {
false
}
},
Err(_e) => {
false
}
}
}
2023-04-27 14:48:11 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_ufvk_decode(
input: *const u8,
input_len: usize,
out: *mut u8,
out_len: &mut usize
) {
let input: String = marshall_from_haskell_var(input, input_len, RW);
2023-05-04 14:23:05 +00:00
let dec_key = Ufvk::decode(&input);
match dec_key {
Ok((n, ufvk)) => {
let x = match n {
Network::Main => 1,
Network::Test => 2,
Network::Regtest => 3
};
let mut hk = Hufvk { net: x, orchard: vec![0], sapling: vec![0], transparent: vec![0] };
let fvks = ufvk.items();
fvks.iter().for_each(|k| hk.add_key_section(k));
marshall_to_haskell_var(&hk, out, out_len, RW);
}
Err(_e) => {
let hk0 = Hufvk { net: 0, orchard: vec![0], sapling: vec![0], transparent: vec![0] };
marshall_to_haskell_var(&hk0, out, out_len, RW);
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
key: *const u8,
key_len: usize,
note: *const u8,
note_len: usize,
external: bool,
net: bool,
pos: u64,
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, pos);
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: nullifier.to_vec() };
marshall_to_haskell_var(&hn, out, out_len, RW);
},
None => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
},
Err(_e1) => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
},
Err(_e) => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
}
2023-08-22 20:05:40 +00:00
#[no_mangle]
2023-09-27 15:37:53 +00:00
pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
2023-08-22 20:05:40 +00:00
key: *const u8,
key_len: usize,
note: *const u8,
note_len: usize,
out: *mut u8,
out_len: &mut usize
){
let evk: Vec<u8> = marshall_from_haskell_var(key, key_len, RW);
2023-08-23 20:19:31 +00:00
let note_input: Vec<u8> = marshall_from_haskell_var(note,note_len,RW);
let mut note_reader = Cursor::new(note_input);
2023-08-22 20:05:40 +00:00
let svk = ExtendedFullViewingKey::read(&*evk);
match svk {
Ok(k) => {
let domain = SaplingDomain::for_height(MainNetwork, BlockHeight::from_u32(2000000));
let action2 = OutputDescription::read(&mut note_reader);
match action2 {
Ok(action3) => {
let fvk = k.to_diversifiable_full_viewing_key().to_ivk(SaplingScope::External);
let pivk = SaplingPreparedIncomingViewingKey::new(&fvk);
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action3);
match result {
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]};
marshall_to_haskell_var(&hn, out, out_len, RW);
}
None => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
},
Err(_e1) => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] , nullifier: vec![0]};
2023-08-22 20:05:40 +00:00
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
}
Err(_e) => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
2023-08-22 20:05:40 +00:00
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
}
2023-06-15 00:09:43 +00:00
2023-05-04 14:23:05 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_orchard_note_decrypt(
2023-05-04 14:23:05 +00:00
key: *const u8,
key_len: usize,
note: *const u8,
note_len: usize,
out: *mut u8,
out_len: &mut usize
){
let fvk_input: Vec<u8> = marshall_from_haskell_var(key, key_len, RW);
let note_input: Haction = marshall_from_haskell_var(note, note_len, RW);
let action: Action<Signature<SpendAuth>> = Action::from_parts(
2024-02-06 19:10:06 +00:00
Nullifier::from_bytes(&to_array(note_input.nf.bytes)).unwrap(),
VerificationKey::try_from(to_array(note_input.rk.bytes)).unwrap(),
ExtractedNoteCommitment::from_bytes(&to_array(note_input.cmx.bytes)).unwrap(),
TransmittedNoteCiphertext {epk_bytes: to_array(note_input.eph_key.bytes), enc_ciphertext: to_array(note_input.enc_txt.bytes), out_ciphertext: to_array(note_input.out_txt.bytes)},
ValueCommitment::from_bytes(&to_array(note_input.cv.bytes)).unwrap(),
Signature::from(to_array(note_input.auth.bytes)));
2023-05-04 14:23:05 +00:00
let fvk_array = to_array(fvk_input);
let domain = OrchardDomain::for_nullifier(*action.nullifier());
let dec_fvk = FullViewingKey::from_bytes(&fvk_array);
match dec_fvk {
Some(fvk) => {
let ivk = fvk.to_ivk(Scope::External);
let pivk = PreparedIncomingViewingKey::new(&ivk);
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
match result {
Some((n, r, m)) => {
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
2023-05-04 14:23:05 +00:00
marshall_to_haskell_var(&hn, out, out_len, RW);
}
None => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
2023-05-04 14:23:05 +00:00
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
},
None => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
2023-05-04 14:23:05 +00:00
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
2023-04-27 14:48:11 +00:00
}
2023-09-25 12:51:14 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_orchard_note_decrypt_sk(
key: *const u8,
key_len: usize,
note: *const u8,
note_len: usize,
external: bool,
out: *mut u8,
out_len: &mut usize
){
let sk_input: Vec<u8> = marshall_from_haskell_var(key, key_len, RW);
let note_input: Haction = marshall_from_haskell_var(note, note_len, RW);
let action: Action<Signature<SpendAuth>> = Action::from_parts(
Nullifier::from_bytes(&to_array(note_input.nf.bytes)).unwrap(),
VerificationKey::try_from(to_array(note_input.rk.bytes)).unwrap(),
ExtractedNoteCommitment::from_bytes(&to_array(note_input.cmx.bytes)).unwrap(),
TransmittedNoteCiphertext {epk_bytes: to_array(note_input.eph_key.bytes), enc_ciphertext: to_array(note_input.enc_txt.bytes), out_ciphertext: to_array(note_input.out_txt.bytes)},
ValueCommitment::from_bytes(&to_array(note_input.cv.bytes)).unwrap(),
Signature::from(to_array(note_input.auth.bytes)));
let sk_array = to_array(sk_input);
let domain = OrchardDomain::for_nullifier(*action.nullifier());
let dec_sk = SpendingKey::from_bytes(sk_array).unwrap();
let fvk = FullViewingKey::from(&dec_sk);
let ivk = if external {
fvk.to_ivk(Scope::External)
} else {
fvk.to_ivk(Scope::Internal)
};
let pivk = PreparedIncomingViewingKey::new(&ivk);
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
match result {
Some((n, r, m)) => {
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
marshall_to_haskell_var(&hn, out, out_len, RW);
}
None => {
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
marshall_to_haskell_var(&hn0, out, out_len, RW);
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_tx_read(
tx: *const u8,
tx_len: usize,
out: *mut u8,
out_len: &mut usize
){
let tx_input: Vec<u8> = marshall_from_haskell_var(tx, tx_len, RW);
let mut tx_reader = Cursor::new(tx_input);
let parsed_tx = Transaction::read(&mut tx_reader, Nu5);
match parsed_tx {
Ok(t) => {
let tb = t.transparent_bundle();
2024-03-29 18:54:21 +00:00
let sb = t.sapling_bundle();
let ob = t.orchard_bundle();
let h1 = Htx
{ txid: t.txid().as_ref().to_vec()
, locktime: t.lock_time()
, expiry: u32::from(t.expiry_height())
, t_bundle: match tb {
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]}} }
2024-03-29 18:54:21 +00:00
, 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]}}}
}
2024-03-29 18:54:21 +00:00
};
marshall_to_haskell_var(&h1, out, out_len, RW);
},
Err(_e) => {
2024-03-29 18:54:21 +00:00
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]}}
2024-03-29 18:54:21 +00:00
};
marshall_to_haskell_var(&h0, out, out_len, RW);
}
}
}
2023-09-25 12:51:14 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_tx_parse(
tx: *const u8,
tx_len: usize,
out: *mut u8,
out_len: &mut usize
){
let tx_input: Vec<u8> = marshall_from_haskell_var(tx, tx_len, RW);
let tx_bytes: Vec<u8> = tx_input.clone();
let mut tx_reader = Cursor::new(tx_input);
let s_o = false;
let o_a = false;
let parsed_tx = Transaction::read(&mut tx_reader, Nu5);
match parsed_tx {
Ok(t) => {
2023-09-28 19:50:53 +00:00
let s_bundle = t.sapling_bundle();
match s_bundle {
Some(b) => {
let mut s_output = Vec::new();
for s_each_out in b.shielded_outputs().iter() {
let mut out_bytes = Vec::new();
let _ = s_each_out.write_v4(&mut out_bytes);
s_output.push(out_bytes);
}
marshall_to_haskell_var(&s_output, out, out_len, RW);
},
None => {
let mut z = Vec::new();
z.push(vec![0]);
2023-09-28 19:50:53 +00:00
marshall_to_haskell_var(&z, out, out_len, RW);
}
2023-09-25 12:51:14 +00:00
}
},
Err(_e) => {
let mut y = Vec::new();
y.push(vec![0]);
2023-09-25 12:51:14 +00:00
marshall_to_haskell_var(&y, out, out_len, RW);
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_gen_seed_phrase(
out: *mut u8,
out_len: &mut usize
){
let mnemonic = Mnemonic::generate(Count::Words24);
let seed = mnemonic.phrase().as_bytes().to_vec();
marshall_to_haskell_var(&seed, out, out_len, RW);
}
#[no_mangle]
pub extern "C" fn rust_wrapper_recover_seed(
input: *const u8,
input_len: usize,
out: *mut u8,
out_len: &mut usize
){
let phrase: String = marshall_from_haskell_var(input, input_len, RW);
let mnemonic = Mnemonic::from_phrase(phrase);
match mnemonic {
Ok(m) => {
let s = m.to_seed("").to_vec();
marshall_to_haskell_var(&s, out, out_len, RW);
},
Err(_e) => {
marshall_to_haskell_var(&vec![0], out, out_len, RW);
}
}
}
2024-03-03 21:19:06 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_sapling_spendingkey(
seed: *const u8,
seed_len: usize,
coin_type: u32,
acc_id: u32,
2024-03-03 21:19:06 +00:00
out: *mut u8,
out_len: &mut usize
){
let s: Vec<u8> = marshall_from_haskell_var(seed, seed_len, RW);
let sk = spending_key(&s, coin_type, zcash_primitives::zip32::AccountId::try_from(acc_id).unwrap());
marshall_to_haskell_var(&sk.to_bytes().to_vec(), out, out_len, RW);
2024-03-03 21:19:06 +00:00
}
#[no_mangle]
pub extern "C" fn rust_wrapper_sapling_paymentaddress(
extspk: *const u8,
extspk_len: usize,
2024-03-10 12:47:26 +00:00
div_ix: u32,
out: *mut u8,
out_len: &mut usize
){
2024-03-10 12:47:26 +00:00
let extspk: Vec<u8> = marshall_from_haskell_var(extspk, extspk_len, RW);
if div_ix == 0 {
let sp_key = ExtendedSpendingKey::from_bytes(&extspk);
match sp_key {
Ok(sp_key_x) => {
let (def_div, def_address) = sp_key_x.default_address();
marshall_to_haskell_var(&def_address.to_bytes().to_vec(), out, out_len, RW);
},
Err(_e) => {
marshall_to_haskell_var(&vec![0], out, out_len, RW);
}
}
} else {
let expsk = ExpandedSpendingKey::from_spending_key(&extspk);
let fvk = SaplingFullViewingKey::from_expanded_spending_key(&expsk);
let dk = DiversifierKey::master(&extspk);
let result = sapling_find_address(&fvk, &dk, DiversifierIndex::from(div_ix));
match result {
Some((_d, p_address)) => {
marshall_to_haskell_var(&p_address.to_bytes().to_vec(), out, out_len, RW);
},
None => {
marshall_to_haskell_var(&vec![0], out, out_len, RW);
}
2024-03-10 12:47:26 +00:00
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_sapling_chgpaymentaddress(
extspk: *const u8,
extspk_len: usize,
out: *mut u8,
out_len: &mut usize
){
let vexspk: Vec<u8> = marshall_from_haskell_var(extspk, extspk_len, RW);
let vexspkp = &vexspk;
let extspku8 : &[u8] = &vexspkp;
let extspk = match ExtendedSpendingKey::from_bytes(&extspku8) {
Ok( k ) => k,
Err( e ) => {
// error recovering ExtendedSpendingKey
marshall_to_haskell_var(&vec![0], out, out_len, RW);
return
}
};
let dfvk = extspk.to_diversifiable_full_viewing_key();
let ( divIx, cPmtAddress ) = dfvk.change_address();
marshall_to_haskell_var(&cPmtAddress.to_bytes().to_vec(), out, out_len, RW);
}
2024-03-05 20:43:33 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_derive_orchard_spending_key(
seed: *const u8,
seed_len: usize,
coin_type: u32,
acc_id: u32,
out: *mut u8,
out_len: &mut usize
){
let s: Vec<u8> = marshall_from_haskell_var(seed, seed_len, RW);
let sk = SpendingKey::from_zip32_seed(&s, coin_type, u32::from(zip32::AccountId::try_from(acc_id).unwrap()));
2024-03-05 20:43:33 +00:00
match sk {
Ok(key) => {
2024-03-05 21:09:35 +00:00
marshall_to_haskell_var(&key.to_bytes().to_vec(), out, out_len, RW);
2024-03-05 20:43:33 +00:00
},
Err(_e) => {
marshall_to_haskell_var(&vec![0], out, out_len, RW);
}
}
}
2024-03-07 22:06:33 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_derive_orchard_receiver(
spend_key: *const u8,
spend_key_len: usize,
add_id: u32,
scope: bool,
2024-03-07 22:06:33 +00:00
out: *mut u8,
out_len: &mut usize
){
let sk_in: Vec<u8> = marshall_from_haskell_var(spend_key, spend_key_len, RW);
let sk = SpendingKey::from_bytes(sk_in[0..32].try_into().unwrap()).unwrap();
let fvk = FullViewingKey::from(&sk);
let sc = if scope {
Scope::External
} else {Scope::Internal};
let o_rec = fvk.address_at(add_id, sc);
2024-03-07 22:06:33 +00:00
marshall_to_haskell_var(&o_rec.to_raw_address_bytes().to_vec(), out, out_len, RW);
}
#[no_mangle]
pub extern "C" fn rust_wrapper_bech32_encode(
hr: *const u8,
hr_len: usize,
b: *const u8,
b_len: usize,
out: *mut u8,
out_len: &mut usize
) {
let hr: String = marshall_from_haskell_var(hr, hr_len, RW);
let hrp = Hrp::parse(&hr).unwrap();
let b: Vec<u8> = marshall_from_haskell_var(b, b_len, RW);
let string = bech32::encode::<Bech32>(hrp, &b).unwrap();
marshall_to_haskell_var(&string, out, out_len, RW);
}
#[no_mangle]
pub extern "C" fn rust_wrapper_read_sapling_commitment_tree(
tree: *const u8,
tree_len: usize,
node: *const u8,
node_len: usize,
out: *mut u8,
out_len: &mut usize
){
let tree_in: Vec<u8> = marshall_from_haskell_var(tree, tree_len, RW);
let tree_reader = Cursor::new(tree_in);
2024-04-16 00:58:26 +00:00
let mut ct = read_commitment_tree::<Node, Cursor<Vec<u8>>, SAPLING_DEPTH>(tree_reader);
match ct {
Ok(mut comm_tree) => {
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in));
if sap_note_comm.is_some().into() {
let n = Node::from_cmu(&sap_note_comm.unwrap());
comm_tree.append(n);
let mut out_bytes: Vec<u8> = Vec::new();
let result = write_commitment_tree(&comm_tree, &mut out_bytes );
match result {
Ok(()) => {
let h = Hhex { bytes: out_bytes};
marshall_to_haskell_var(&h, out, out_len, RW);
},
Err(_e) => {
let h0 = Hhex { bytes: vec![0]};
marshall_to_haskell_var(&h0, out, out_len, RW);
}
}
} else {
let h0 = Hhex { bytes: vec![0]};
marshall_to_haskell_var(&h0, out, out_len, RW);
}
},
Err(_e) => {
let h0 = Hhex { bytes: vec![0]};
marshall_to_haskell_var(&h0, out, out_len, RW);
}
}
2024-04-16 00:58:26 +00:00
}
2024-04-10 16:39:27 +00:00
#[no_mangle]
pub extern "C" fn rust_wrapper_read_sapling_witness(
tree: *const u8,
tree_len: usize,
out: *mut u8,
out_len: &mut usize
){
let tree_in: Vec<u8> = marshall_from_haskell_var(tree, tree_len, RW);
let tree_reader = Cursor::new(tree_in);
let ct: CommitmentTree<Node, SAPLING_DEPTH> = read_commitment_tree(tree_reader).unwrap();
let inc_wit = IncrementalWitness::from_tree(ct);
let mut out_bytes: Vec<u8> = Vec::new();
let result = write_incremental_witness(&inc_wit, &mut out_bytes);
match result {
Ok(()) => {
let h = Hhex { bytes: out_bytes};
marshall_to_haskell_var(&h, out, out_len, RW);
},
Err(_e) => {
let h0 = Hhex { bytes: vec![0]};
marshall_to_haskell_var(&h0, out, out_len, RW);
}
}
}
#[no_mangle]
pub extern "C" fn rust_wrapper_read_sapling_position(
wit: *const u8,
wit_len: usize,
) -> u64 {
let wit_in: Vec<u8> = marshall_from_haskell_var(wit, wit_len, RW);
let wit_reader = Cursor::new(wit_in);
let iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(wit_reader).unwrap();
let path = iw.path();
match path {
Some(p) => {
let pos = p.position();
return u64::from(pos);
},
None => {
return 0;
}
}
}