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
|
|
|
|
},
|
2023-04-16 00:07:08 +00:00
|
|
|
fmt::{Debug, Display, Formatter}
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
2023-06-15 00:09:43 +00:00
|
|
|
use zcash_primitives::{
|
|
|
|
zip32::Scope as SaplingScope,
|
2024-01-16 22:15:05 +00:00
|
|
|
zip339::{Count, Mnemonic},
|
2023-06-15 00:09:43 +00:00
|
|
|
transaction::components::sapling::{
|
2023-08-22 20:05:40 +00:00
|
|
|
read_zkproof,
|
2023-06-15 00:09:43 +00:00
|
|
|
GrothProofBytes,
|
|
|
|
OutputDescription,
|
|
|
|
CompactOutputDescription
|
|
|
|
},
|
|
|
|
sapling::{
|
|
|
|
value::ValueCommitment as SaplingValueCommitment,
|
2023-08-22 20:05:40 +00:00
|
|
|
keys::{
|
|
|
|
FullViewingKey as SaplingViewingKey,
|
|
|
|
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey
|
|
|
|
},
|
2023-06-15 00:09:43 +00:00
|
|
|
note_encryption::SaplingDomain,
|
|
|
|
PaymentAddress,
|
|
|
|
note::ExtractedNoteCommitment as SaplingExtractedNoteCommitment
|
|
|
|
},
|
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,
|
|
|
|
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,
|
2023-10-04 16:12:30 +00:00
|
|
|
unified::{Address, Encoding, Ufvk, Container, Fvk, Receiver},
|
2023-04-18 18:58:21 +00:00
|
|
|
ZcashAddress
|
2023-04-16 00:07:08 +00:00
|
|
|
};
|
|
|
|
|
2023-06-14 14:55:52 +00:00
|
|
|
use zcash_client_backend::keys::sapling::ExtendedFullViewingKey;
|
|
|
|
|
2023-05-04 14:23:05 +00:00
|
|
|
use orchard::{
|
|
|
|
Action,
|
|
|
|
keys::{FullViewingKey, PreparedIncomingViewingKey, Scope},
|
|
|
|
note::{Nullifier, TransmittedNoteCiphertext, ExtractedNoteCommitment},
|
|
|
|
note_encryption::OrchardDomain,
|
|
|
|
primitives::redpallas::{VerificationKey, SpendAuth, Signature},
|
|
|
|
value::ValueCommitment
|
|
|
|
};
|
|
|
|
|
2023-06-15 00:09:43 +00:00
|
|
|
use zcash_note_encryption::EphemeralKeyBytes;
|
2023-05-04 14:23:05 +00:00
|
|
|
|
2023-04-27 14:48:11 +00:00
|
|
|
use bech32::{
|
|
|
|
decode,
|
2023-06-14 14:55:52 +00:00
|
|
|
u5,
|
|
|
|
FromBase32,
|
|
|
|
ToBase32,
|
|
|
|
Variant
|
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: Vec<u8>,
|
|
|
|
cmu: Vec<u8>,
|
|
|
|
eph_key: Vec<u8>,
|
|
|
|
enc_txt: Vec<u8>,
|
|
|
|
out_txt: Vec<u8>,
|
|
|
|
proof: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
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>) -> Result<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() };
|
|
|
|
Ok(o)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-04 14:23:05 +00:00
|
|
|
#[derive(BorshSerialize, BorshDeserialize)]
|
|
|
|
pub struct Haction {
|
|
|
|
nf: Vec<u8>,
|
|
|
|
rk: Vec<u8>,
|
|
|
|
cmx: Vec<u8>,
|
|
|
|
eph_key: Vec<u8>,
|
|
|
|
enc_txt: Vec<u8>,
|
|
|
|
out_txt: Vec<u8>,
|
|
|
|
cv: Vec<u8>,
|
|
|
|
auth: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<RW> FromHaskell<RW> for Haction {
|
|
|
|
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
|
|
|
|
let x = Haction::deserialize(buf)?;
|
|
|
|
Ok(x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(BorshSerialize, BorshDeserialize)]
|
|
|
|
pub struct Hnote {
|
|
|
|
note: u64,
|
|
|
|
recipient: Vec<u8>,
|
|
|
|
memo: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
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);
|
2023-06-14 14:55:52 +00:00
|
|
|
let decodedBytes = bech32::decode(&input);
|
|
|
|
match decodedBytes {
|
|
|
|
Ok((hrp, bytes, variant)) => {
|
|
|
|
let rd = RawData {hrp: hrp.into(), bytes: Vec::<u8>::from_base32(&bytes).unwrap()};
|
|
|
|
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_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) => {
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 16:12:30 +00:00
|
|
|
#[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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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));
|
2023-09-29 19:06:56 +00:00
|
|
|
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() };
|
|
|
|
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) => {
|
2023-08-22 20:05:40 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-15 00:09:43 +00:00
|
|
|
|
2023-05-04 14:23:05 +00:00
|
|
|
#[no_mangle]
|
2023-05-04 20:26:49 +00:00
|
|
|
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(
|
|
|
|
Nullifier::from_bytes(&to_array(note_input.nf)).unwrap(),
|
|
|
|
VerificationKey::try_from(to_array(note_input.rk)).unwrap(),
|
|
|
|
ExtractedNoteCommitment::from_bytes(&to_array(note_input.cmx)).unwrap(),
|
|
|
|
TransmittedNoteCiphertext {epk_bytes: to_array(note_input.eph_key), enc_ciphertext: to_array(note_input.enc_txt), out_ciphertext: to_array(note_input.out_txt)},
|
|
|
|
ValueCommitment::from_bytes(&to_array(note_input.cv)).unwrap(),
|
|
|
|
Signature::from(to_array(note_input.auth)));
|
|
|
|
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() };
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
|
|
|
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_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 => {
|
2023-09-29 14:02:05 +00:00
|
|
|
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) => {
|
2023-09-29 14:02:05 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-16 22:15:05 +00:00
|
|
|
|
|
|
|
#[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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|