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::ExtendedFullViewingKey,
|
||||||
sapling::ExtendedSpendingKey};
|
sapling::ExtendedSpendingKey};
|
||||||
|
|
||||||
use zcash_primitives::zip32::AccountId;
|
use zcash_primitives::zip32::{ AccountId, DiversifierIndex };
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
use orchard::{
|
use orchard::{
|
||||||
|
@ -621,27 +621,68 @@ pub extern "C" fn rust_wrapper_recover_seed(
|
||||||
pub extern "C" fn rust_wrapper_sapling_spendingkey(
|
pub extern "C" fn rust_wrapper_sapling_spendingkey(
|
||||||
iseed: *const u8,
|
iseed: *const u8,
|
||||||
iseed_len: usize,
|
iseed_len: usize,
|
||||||
coin_type: u32,
|
|
||||||
acc_id: u32,
|
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
out_len: &mut usize
|
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);
|
let seed: Vec<u8> = marshall_from_haskell_var(iseed, iseed_len, RW);
|
||||||
if ( seed.len() <= 0 ) {
|
if ( seed.len() != 64 ) {
|
||||||
println!("Seed error, returning a null vector...");
|
// invalid seed length
|
||||||
marshall_to_haskell_var(&vec![0], out, out_len, RW);
|
marshall_to_haskell_var(&vec![0], out, out_len, RW);
|
||||||
} else {
|
} else {
|
||||||
println!("Seed in rust : {:?}\n", seed);
|
// Obtain the ExtendedSpendingKey using the seed
|
||||||
println!("Coin Type -> {}\nAccount Id -> {}",coin_type,acc_id);
|
// Returns a byte array (169 bytes)
|
||||||
let su8 = &seed;
|
let su8 = &seed;
|
||||||
let seedu8 : &[u8] = &su8;
|
let seedu8 : &[u8] = &su8;
|
||||||
|
println!("Seed : {:?}\n", &seedu8);
|
||||||
let extsk: ExtendedSpendingKey = sapling::ExtendedSpendingKey::master(&seedu8);
|
let extsk: ExtendedSpendingKey = sapling::ExtendedSpendingKey::master(&seedu8);
|
||||||
let extsk_bytes = extsk.to_bytes().to_vec();
|
let extsk_bytes = extsk.to_bytes().to_vec();
|
||||||
marshall_to_haskell_var(&extsk_bytes, out, out_len, RW);
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_wrapper_derive_orchard_spending_key(
|
pub extern "C" fn rust_wrapper_derive_orchard_spending_key(
|
||||||
seed: *const u8,
|
seed: *const u8,
|
||||||
|
|
|
@ -136,8 +136,13 @@ import ZcashHaskell.Types
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_sapling_spendingkey as rustWrapperSaplingSpendingkey
|
{# fun unsafe rust_wrapper_sapling_spendingkey as rustWrapperSaplingSpendingkey
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, `Word32'
|
, getVarBuffer `Buffer (BS.ByteString)'&
|
||||||
, `Word32'
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_sapling_paymentaddress as rustWrapperPaymentAddress
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, getVarBuffer `Buffer (BS.ByteString)'&
|
, getVarBuffer `Buffer (BS.ByteString)'&
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
|
|
|
@ -22,6 +22,7 @@ import C.Zcash
|
||||||
, rustWrapperSaplingCheck
|
, rustWrapperSaplingCheck
|
||||||
, rustWrapperSaplingNoteDecode
|
, rustWrapperSaplingNoteDecode
|
||||||
, rustWrapperSaplingSpendingkey
|
, rustWrapperSaplingSpendingkey
|
||||||
|
, rustWrapperPaymentAddress
|
||||||
, rustWrapperSaplingVkDecode
|
, rustWrapperSaplingVkDecode
|
||||||
, rustWrapperTxParse
|
, rustWrapperTxParse
|
||||||
)
|
)
|
||||||
|
@ -92,7 +93,14 @@ instance FromJSON RawTxResponse where
|
||||||
pure $ RawTxResponse i h (getShieldedOutputs h) a ht c b
|
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
|
-- | Attempts to obtain a sapling SpendinKey using a HDSeed, a Coin Type and an Account ID
|
||||||
genSaplingSpendingKey :: BS.ByteString -> Word32-> AccountId -> BS.ByteString
|
genSaplingSpendingKey :: BS.ByteString -> BS.ByteString
|
||||||
genSaplingSpendingKey seed coin_type account_id = do
|
genSaplingSpendingKey seed = do
|
||||||
let res = withPureBorshVarBuffer (rustWrapperSaplingSpendingkey seed (fromIntegral coin_type) (fromIntegral account_id) )
|
let res = withPureBorshVarBuffer (rustWrapperSaplingSpendingkey seed )
|
||||||
res
|
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
|
, isValidShieldedAddress
|
||||||
, matchSaplingAddress
|
, matchSaplingAddress
|
||||||
, genSaplingSpendingKey
|
, genSaplingSpendingKey
|
||||||
|
, genSaplingPaymentAddress
|
||||||
)
|
)
|
||||||
import ZcashHaskell.Transparent
|
import ZcashHaskell.Transparent
|
||||||
--(encodeTransparent)
|
--(encodeTransparent)
|
||||||
|
@ -531,11 +532,33 @@ main = do
|
||||||
241, 243, 172, 178,
|
241, 243, 172, 178,
|
||||||
104, 81, 159, 144
|
104, 81, 159, 144
|
||||||
] :: [Word8]
|
] :: [Word8]
|
||||||
let cointype = getValue TestNetCoin
|
let msg = genSaplingSpendingKey (word8ArrayToByteString hdseed)
|
||||||
let account = 0 :: AccountId
|
|
||||||
let msg = genSaplingSpendingKey (word8ArrayToByteString hdseed) cointype account
|
|
||||||
let msgArr = BS.unpack msg
|
let msgArr = BS.unpack msg
|
||||||
if (length msgArr) == 169
|
if (length msgArr) == 169
|
||||||
then True
|
then True
|
||||||
else False
|
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