Sapling Spending keys and receivers #27
4 changed files with 95 additions and 18 deletions
|
@ -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<u8> = 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<u8> = 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,
|
||||
|
|
|
@ -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)'&
|
||||
}
|
||||
-> `()'
|
||||
|
|
|
@ -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) )
|
||||
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
|
||||
|
|
31
test/Spec.hs
31
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."
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue