diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index 5eea232..3d2754a 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -59,7 +59,8 @@ use zcash_address::{ use zcash_client_backend::keys::sapling::{ ExtendedFullViewingKey, - ExtendedSpendingKey + ExtendedSpendingKey, + DiversifiableFullViewingKey }; use zcash_primitives::zip32::{ AccountId, DiversifierIndex }; @@ -632,7 +633,7 @@ pub extern "C" fn rust_wrapper_sapling_spendingkey( out_len: &mut usize ){ let seed: Vec = marshall_from_haskell_var(iseed, iseed_len, RW); - if ( seed.len() != 64 ) { + if seed.len() != 64 { // invalid seed length marshall_to_haskell_var(&vec![0], out, out_len, RW); } else { @@ -669,6 +670,36 @@ pub extern "C" fn rust_wrapper_sapling_paymentaddress( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_sapling_chgpaymentaddress( + extspk: *const u8, + extspk_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + println!("Entering ChangeAddress generation...."); + let vexspk: Vec = marshall_from_haskell_var(extspk, extspk_len, RW); + let vexspkp = &vexspk; + let extspku8 : &[u8] = &vexspkp; + println!("Received ExtendedSpendingKey in Bytes...\n{:?}\n",extspku8); + let extspk = match ExtendedSpendingKey::from_bytes(&extspku8) { + Ok( k ) => k, + Err( e ) => { + // error recovering ExtendedSpendingKey + println!("\n>>>> Error generating ExtendedSpendingKey"); + marshall_to_haskell_var(&vec![0], out, out_len, RW); + return + } + }; + println!("ExtendedSpendingKey -> {:?}",extspk); + let dfvk = extspk.to_diversifiable_full_viewing_key(); + let ( divIx, cPmtAddress ) = dfvk.change_address(); + println!("\nDiversifierIndex > {:?}\n\nChange Payment Address -> {:?}\n ", + divIx, cPmtAddress); + println!("Change Payment Address in bytes : \n{:?}",cPmtAddress.to_bytes()); + marshall_to_haskell_var(&cPmtAddress.to_bytes().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 1e32f93..e68404b 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -149,6 +149,13 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_sapling_chgpaymentaddress as rustWrapperSaplingChgPaymentAddress + { toBorshVar* `BS.ByteString'& + , 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 0a25661..64aa7a6 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -22,6 +22,7 @@ import C.Zcash , rustWrapperSaplingCheck , rustWrapperSaplingNoteDecode , rustWrapperSaplingPaymentAddress + , rustWrapperSaplingChgPaymentAddress , rustWrapperSaplingSpendingkey , rustWrapperSaplingVkDecode , rustWrapperTxParse @@ -115,5 +116,6 @@ genSaplingPaymentAddress extspk i = (rustWrapperSaplingPaymentAddress extspk (fromIntegral i)) -- | Generate an internal Sapling address -genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingInternalReceiver -genSaplingInternalAddress sk = undefined +genSaplingInternalAddress :: SaplingSpendingKey -> BS.ByteString -- SaplingInternalReceiver +genSaplingInternalAddress sk = withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress sk) + \ No newline at end of file diff --git a/test/Spec.hs b/test/Spec.hs index e6d6bc2..e00893b 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -42,6 +42,7 @@ import ZcashHaskell.Orchard import ZcashHaskell.Sapling ( decodeSaplingOutput , genSaplingPaymentAddress + , genSaplingInternalAddress , genSaplingSpendingKey , getShieldedOutputs , isValidSaplingViewingKey @@ -481,7 +482,7 @@ main = do Nothing -> "Bad UA" Just u -> maybe "No transparent" encodeTransparent $ t_rec u msg `shouldBe` "t1LPWuQnjCRH7JAeEErSXKixcUteLJRJjKD" - describe "Transparent Private and Publicc Key Generation" $ do + describe "Transparent Private and Public Key Generation" $ do it "Obtain a transparent extended private key from HDSeed" $ do let hdseed = [ 206 @@ -589,6 +590,191 @@ main = do genSaplingPaymentAddress (fromMaybe "" s) 0 `shouldNotBe` Nothing prop "Sapling receivers are valid" $ forAll genSapArgs $ \i -> prop_SaplingReceiver i + describe "Sapling Change Payment Address generation test" $ do + it "Call genSaplingInternalAddress" $ do + let sk = [ 3 + , 183 + , 26 + , 151 + , 89 + , 0 + , 0 + , 0 + , 128 + , 199 + , 189 + , 33 + , 169 + , 114 + , 194 + , 50 + , 0 + , 139 + , 140 + , 162 + , 100 + , 100 + , 35 + , 58 + , 226 + , 6 + , 47 + , 232 + , 34 + , 214 + , 11 + , 173 + , 142 + , 40 + , 45 + , 163 + , 190 + , 207 + , 49 + , 130 + , 158 + , 113 + , 232 + , 251 + , 79 + , 98 + , 77 + , 195 + , 196 + , 40 + , 42 + , 113 + , 133 + , 35 + , 211 + , 68 + , 146 + , 104 + , 5 + , 56 + , 244 + , 162 + , 55 + , 239 + , 55 + , 112 + , 37 + , 38 + , 189 + , 183 + , 121 + , 201 + , 1 + , 60 + , 158 + , 151 + , 141 + , 123 + , 250 + , 95 + , 169 + , 123 + , 208 + , 56 + , 103 + , 74 + , 85 + , 49 + , 152 + , 207 + , 245 + , 216 + , 58 + , 37 + , 0 + , 127 + , 186 + , 245 + , 234 + , 47 + , 68 + , 11 + , 78 + , 76 + , 12 + , 171 + , 37 + , 63 + , 172 + , 90 + , 111 + , 94 + , 88 + , 152 + , 211 + , 53 + , 243 + , 142 + , 16 + , 195 + , 142 + , 50 + , 14 + , 13 + , 32 + , 91 + , 5 + , 82 + , 182 + , 121 + , 136 + , 109 + , 125 + , 165 + , 125 + , 123 + , 226 + , 54 + , 60 + , 34 + , 62 + , 111 + , 167 + , 88 + , 254 + , 113 + , 204 + , 47 + , 181 + , 97 + , 18 + , 220 + , 46 + , 51 + , 160 + , 62 + , 16 + , 199 + , 143 + , 184 + , 200 + , 209 + , 124 + , 154 + , 175 + , 29 + , 216 + , 48 + , 201] :: [Word8] + let cAdr = [31, 232, 31, 17, 195, -- 196 + 178, 208, 227, 206, + 199, 105, 55, 147, + 23, 151, 206, 117, + 59, 249, 162, 218, + 140, 189, 17, 60, + 116, 106, 56, 64, + 203, 152, 52, 155, + 133, 179, 118, 47, + 161, 70, 155, 21, + 22, 41] :: [Word8] + let bscAdr = BS.pack cAdr + let ca = genSaplingInternalAddress (BS.pack sk) + ca `shouldBe` bscAdr -- | Properties prop_PhraseLength :: Int -> Property