diff --git a/configure b/configure index 0af689b..21dc7bb 100755 --- a/configure +++ b/configure @@ -1,4 +1,5 @@ #!/bin/bash -export PKG_CONFIG_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug -export LD_LIBRARY_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug +echo "export PKG_CONFIG_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$PKG_CONFIG_PATH" | tee -a ~/.bashrc +echo "export LD_LIBRARY_PATH=$(pwd)/librustzcash-wrapper/target/x86_64-unknown-linux-gnu/debug:\$LD_LIBRARY_PATH" | tee -a ~/.bashrc +source ~/.bashrc diff --git a/librustzcash-wrapper/Cargo.toml b/librustzcash-wrapper/Cargo.toml index d26b3d0..44d2cca 100644 --- a/librustzcash-wrapper/Cargo.toml +++ b/librustzcash-wrapper/Cargo.toml @@ -11,6 +11,7 @@ haskell-ffi.rev = "2bf292e2e56eac8e9fb0fb2e1450cf4a4bd01274" f4jumble = "0.1" zcash_address = "0.2.0" borsh = "0.10" +bech32 = "0.9.1" [features] capi = [] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 71bac6d..07b16b9 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -8,22 +8,77 @@ use std::{ use f4jumble; use borsh::{BorshDeserialize, BorshSerialize}; + use haskell_ffi::{ error::Result, - from_haskell::{marshall_from_haskell_var}, + from_haskell::marshall_from_haskell_var, to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed}, FromHaskell, HaskellSize, ToHaskell }; use zcash_address::{ Network, - unified::{Address, Encoding}, + unified::{Address, Encoding, Ufvk, Container, Fvk}, ZcashAddress }; +use bech32::{ + decode, + u5 +}; + pub enum RW {} pub const RW: PhantomData = PhantomData; +#[derive(BorshSerialize, BorshDeserialize)] +pub struct RawData { + hrp: Vec, + bytes: Vec +} + +impl ToHaskell for RawData { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +//impl FromHaskell for RawData { + //fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + //let x = RawData::deserialize(buf)?; + //Ok(x) + //} +//} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hufvk { + net: u8, + orchard: Vec, + sapling: Vec, + transparent: Vec +} + +impl ToHaskell for Hufvk { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> 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(); + } + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_f4jumble( input: *const u8, @@ -35,6 +90,17 @@ pub extern "C" fn rust_wrapper_f4jumble( marshall_to_haskell_var(&result, out, out_len, RW); } +#[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 = marshall_from_haskell_var(input, input_len, RW); + let result = f4jumble::f4jumble_inv(&input).unwrap(); + marshall_to_haskell_var(&result, out, out_len, RW); +} + #[no_mangle] pub extern "C" fn rust_wrapper_ua_decode( input: *const u8, @@ -51,3 +117,36 @@ pub extern "C" fn rust_wrapper_shielded_decode( let input: String = marshall_from_haskell_var(input, input_len, RW); ZcashAddress::try_from_encoded(&input).is_ok() } + +#[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); + let (hrp, bytes) = bech32::decode_without_checksum(&input).unwrap(); + let rd = RawData {hrp: hrp.into(), bytes: bytes.iter().map(|&x| bech32::u5::to_u8(x)).collect()}; + marshall_to_haskell_var(&rd, out, out_len, RW); +} + +#[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); + let (n, ufvk) = Ufvk::decode(&input).unwrap(); + 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); +}