From 54b15670117c1c3bc7adec91a3f838ffdb2651c2 Mon Sep 17 00:00:00 2001 From: "Rene V. Vergara" Date: Fri, 8 Mar 2024 14:46:41 -0500 Subject: [PATCH] Default Paymebt address and DiversifierIndex created x --- librustzcash-wrapper/src/lib.rs | 57 ++++++++++++++++++++++++++++----- src/C/Zcash.chs | 9 ++++-- src/ZcashHaskell/Sapling.hs | 16 ++++++--- test/Spec.hs | 31 +++++++++++++++--- 4 files changed, 95 insertions(+), 18 deletions(-) diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 8963325..ce35b57 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -54,7 +54,7 @@ use zcash_client_backend::keys::{ sapling::ExtendedFullViewingKey, sapling::ExtendedSpendingKey}; -use zcash_primitives::zip32::AccountId; +use zcash_primitives::zip32::{ AccountId, DiversifierIndex }; use std::slice; use orchard::{ @@ -621,27 +621,68 @@ pub extern "C" fn rust_wrapper_recover_seed( pub extern "C" fn rust_wrapper_sapling_spendingkey( iseed: *const u8, iseed_len: usize, - coin_type: u32, - acc_id: u32, out: *mut u8, out_len: &mut usize ){ - println!("From Rust\n========="); + println!("Starting extended spending key generation...."); let seed: Vec = marshall_from_haskell_var(iseed, iseed_len, RW); - if ( seed.len() <= 0 ) { - println!("Seed error, returning a null vector..."); + if ( seed.len() != 64 ) { + // invalid seed length marshall_to_haskell_var(&vec![0], out, out_len, RW); } else { - println!("Seed in rust : {:?}\n", seed); - println!("Coin Type -> {}\nAccount Id -> {}",coin_type,acc_id); + // Obtain the ExtendedSpendingKey using the seed + // Returns a byte array (169 bytes) let su8 = &seed; let seedu8 : &[u8] = &su8; + println!("Seed : {:?}\n", &seedu8); let extsk: ExtendedSpendingKey = sapling::ExtendedSpendingKey::master(&seedu8); let extsk_bytes = extsk.to_bytes().to_vec(); marshall_to_haskell_var(&extsk_bytes, out, out_len, RW); } } +#[no_mangle] +pub extern "C" fn rust_wrapper_sapling_paymentaddress( + extspk: *const u8, + extspk_len: usize, +// divIx: u32, + out: *mut u8, + out_len: &mut usize + ){ + let divIx : u32 = 2; + println!("Starting paymentAddress generation...."); + let extspkb: Vec = marshall_from_haskell_var(extspk, extspk_len, RW); + if ( extspkb.len() != 169 ) { + // invalid ExtendedSpenndingKey Array length + println!("Invalid ExtendedSpendingKey...."); + marshall_to_haskell_var(&vec![0], out, out_len, RW); + } else { + // Process + println!("Extended Spending Key validated, continue ...."); + let extspkbu8 = &extspkb; + let xsku8 : &[u8] = &extspkbu8; + let xsk = match sapling::ExtendedSpendingKey::from_bytes(&xsku8) { + Ok ( x ) => x, + Err ( err ) => { + // Error recovering ExtendedSpendingKey from bytes + marshall_to_haskell_var(&vec![0], out, out_len, RW); + return + } + }; + // Obtain the DiversifiableFullViewingKey from ExtendedSpendingKey + let dfvk = xsk.to_diversifiable_full_viewing_key(); + // Obtain the Address from the DiversifiableFullViewingKey +// println!("dfvk -> \n{:?}", dfvk); +// let divIndex : DiversifierIndex = divIx.into(); +// println!("divIndex -> {:?}", divIndex); + let (divIx, paddress) = dfvk.default_address(); + println!("Rust pmtAddress - \n{:?}\n\nRust Diversifier - \n{:?}\n", paddress, divIx); + let pmtAddress = paddress.to_bytes(); + println!("\nRust pntAddress as byte array -\n{:?}\n", pmtAddress); + marshall_to_haskell_var(&pmtAddress.to_vec(), out, out_len, RW); + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_derive_orchard_spending_key( seed: *const u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index ab3ef8d..14bfc45 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -136,8 +136,13 @@ import ZcashHaskell.Types {# fun unsafe rust_wrapper_sapling_spendingkey as rustWrapperSaplingSpendingkey { toBorshVar* `BS.ByteString'& - , `Word32' - , `Word32' + , getVarBuffer `Buffer (BS.ByteString)'& + } + -> `()' +#} + +{# fun unsafe rust_wrapper_sapling_paymentaddress as rustWrapperPaymentAddress + { toBorshVar* `BS.ByteString'& , getVarBuffer `Buffer (BS.ByteString)'& } -> `()' diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index c34314c..62f513f 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -22,6 +22,7 @@ import C.Zcash , rustWrapperSaplingCheck , rustWrapperSaplingNoteDecode , rustWrapperSaplingSpendingkey + , rustWrapperPaymentAddress , rustWrapperSaplingVkDecode , rustWrapperTxParse ) @@ -92,7 +93,14 @@ instance FromJSON RawTxResponse where pure $ RawTxResponse i h (getShieldedOutputs h) a ht c b -- -- | Attempts to obtain a sapling SpendinKey using a HDSeed, a Coin Type and an Account ID -genSaplingSpendingKey :: BS.ByteString -> Word32-> AccountId -> BS.ByteString -genSaplingSpendingKey seed coin_type account_id = do - let res = withPureBorshVarBuffer (rustWrapperSaplingSpendingkey seed (fromIntegral coin_type) (fromIntegral account_id) ) - res \ No newline at end of file +genSaplingSpendingKey :: BS.ByteString -> BS.ByteString +genSaplingSpendingKey seed = do + let res = withPureBorshVarBuffer (rustWrapperSaplingSpendingkey seed ) + res +-- +-- | Attempts to generate a sapling Payment Address using an ExtendedSpendingKey +-- | and a Diversifier Index +genSaplingPaymentAddress :: BS.ByteString -> BS.ByteString +genSaplingPaymentAddress extspk = do + let pmtaddress = withPureBorshVarBuffer (rustWrapperPaymentAddress extspk ) + pmtaddress diff --git a/test/Spec.hs b/test/Spec.hs index abfd17c..c6d5086 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -43,6 +43,7 @@ import ZcashHaskell.Sapling , isValidShieldedAddress , matchSaplingAddress , genSaplingSpendingKey + , genSaplingPaymentAddress ) import ZcashHaskell.Transparent --(encodeTransparent) @@ -531,11 +532,33 @@ main = do 241, 243, 172, 178, 104, 81, 159, 144 ] :: [Word8] - let cointype = getValue TestNetCoin - let account = 0 :: AccountId - let msg = genSaplingSpendingKey (word8ArrayToByteString hdseed) cointype account + let msg = genSaplingSpendingKey (word8ArrayToByteString hdseed) let msgArr = BS.unpack msg if (length msgArr) == 169 then True else False --- msgArr `shouldBe` "It's working." \ No newline at end of file + describe "Sapling Payment Address generation test" $ do + it "Call genSaplingPaymentAddress" $ do + let hdseed1 = [206, 61, 120, 38, + 206, 40, 201, 62, + 83, 175, 151, 131, + 218, 141, 206, 254, + 28, 244, 172, 213, + 128, 248, 156, 45, + 204, 44, 169, 3, + 162, 188, 16, 173, + 192, 164, 96, 148, + 91, 52, 244, 83, + 149, 169, 82, 196, + 199, 53, 177, 170, + 1, 6, 0, 120, + 170, 2, 238, 219, + 241, 243, 172, 178, + 104, 81, 159, 144 + ] :: [Word8] + let msg1 = genSaplingSpendingKey (word8ArrayToByteString hdseed1) + let pmtaddress = genSaplingPaymentAddress msg1 --(word8ArrayToByteString hdseed1) + let msgArr = BS.unpack pmtaddress + if (length msgArr) == 43 + then True + else False