diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 649b699..05c7853 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -649,8 +649,48 @@ pub extern "C" fn rust_wrapper_sapling_paymentaddress( out: *mut u8, out_len: &mut usize ){ - let divIx : u32 = 2; - println!("Starting paymentAddress generation...."); +// 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_sapling_find_paymentaddress( + extspk: *const u8, + extspk_len: usize, + divIx: u32, + out: *mut u8, + out_len: &mut usize + ){ + println!("Starting paymentAddress generation using Find_Address()...."); let extspkb: Vec = marshall_from_haskell_var(extspk, extspk_len, RW); if ( extspkb.len() != 169 ) { // invalid ExtendedSpenndingKey Array length @@ -669,20 +709,30 @@ pub extern "C" fn rust_wrapper_sapling_paymentaddress( return } }; + println!("Obtain a DiversifierIndex from u32 parameter {:?}....",divIx); + let diversifierIndex : DiversifierIndex = divIx.into(); // 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); + let result = dfvk.find_address(diversifierIndex) + .map (|(divIx,paddress) | { + 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); +// + }) + .unwrap_or_else(|| { + // Handle the case where the function returns None + println!("Rust - Error finding payment address.... "); + marshall_to_haskell_var(&vec![0], out, out_len, RW); + return + }); } } - #[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 97ad03b..d0f100f 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -148,6 +148,14 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_sapling_find_paymentaddress as rustWrapperFindPaymentAddress + { toBorshVar* `BS.ByteString'& + , `Word32' + , getVarBuffer `Buffer (BS.ByteString)'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_derive_orchard_spending_key as rustWrapperGenOrchardSpendKey { toBorshVar* `BS.ByteString'& , `Word32' diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index 62f513f..c470417 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -23,6 +23,7 @@ import C.Zcash , rustWrapperSaplingNoteDecode , rustWrapperSaplingSpendingkey , rustWrapperPaymentAddress + , rustWrapperFindPaymentAddress , rustWrapperSaplingVkDecode , rustWrapperTxParse ) @@ -99,8 +100,14 @@ genSaplingSpendingKey seed = do 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 + +-- +-- | Attempts to generate a sapling Payment Address using an ExtendedSpendingKey +genSaplingFindPaymentAddress :: BS.ByteString -> Word32 -> BS.ByteString +genSaplingFindPaymentAddress extspk divIx = do + let pmtaddress = withPureBorshVarBuffer (rustWrapperFindPaymentAddress extspk divIx) + pmtaddress diff --git a/test/Spec.hs b/test/Spec.hs index 164329d..63cf1be 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -46,7 +46,8 @@ import ZcashHaskell.Sapling , isValidShieldedAddress , matchSaplingAddress , genSaplingSpendingKey - , genSaplingPaymentAddress + , genSaplingPaymentAddress + , genSaplingFindPaymentAddress ) import ZcashHaskell.Transparent --(encodeTransparent) @@ -532,9 +533,7 @@ main = do ] :: [Word8] let msg = genSaplingSpendingKey (word8ArrayToByteString hdseed) let msgArr = BS.unpack msg - if (length msgArr) == 169 - then True - else False + length msgArr `shouldBe` 169 describe "Sapling Payment Address generation test" $ do it "Call genSaplingPaymentAddress" $ do let hdseed1 = [206, 61, 120, 38, @@ -557,9 +556,30 @@ main = do let msg1 = genSaplingSpendingKey (word8ArrayToByteString hdseed1) let pmtaddress = genSaplingPaymentAddress msg1 --(word8ArrayToByteString hdseed1) let msgArr = BS.unpack pmtaddress - if (length msgArr) == 43 - then True - else False + length msgArr `shouldBe` 43 + describe "Sapling Payment Find Address generation test" $ do + it "Call genSaplingFindPaymentAddress" $ 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 = genSaplingFindPaymentAddress msg1 0 --(word8ArrayToByteString hdseed1) + let msgArr = BS.unpack pmtaddress + length msgArr `shouldBe` 42 -- | Properties prop_PhraseLength :: Int -> Property