Skip to content

Commit

Permalink
feat(zcash): modify master_fingerprint to seed_fingerprint
Browse files Browse the repository at this point in the history
  • Loading branch information
soralit committed Sep 29, 2024
1 parent 3fe7419 commit a38baee
Show file tree
Hide file tree
Showing 14 changed files with 89 additions and 42 deletions.
2 changes: 1 addition & 1 deletion docs/protocols/ur_registrys/draft/zcash.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ The specification uses CDDL and includes `crypto-hdkey` and `crypto-key-path` sp

```cddl
zcash-accounts = {
master-fingerprint: uint32, ; the master fingerprint to identify the wallet
seed-fingerprint: bytes.32, ; the seed fingerprint specified by ZIP-32 to identify the wallet
accounts: [+ zcash-ufvk],
? origin: text, ; source of data, e.g., Keystone
}
Expand Down
4 changes: 2 additions & 2 deletions rust/apps/wallets/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions rust/apps/wallets/src/zcash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl_public_struct!(UFVKInfo {
orchard_key_path: String
});

pub fn generate_sync_ur(key_infos: Vec<UFVKInfo>, mfp: [u8; 4]) -> URResult<ZcashAccounts> {
pub fn generate_sync_ur(key_infos: Vec<UFVKInfo>, seed_fingerprint: [u8; 32]) -> URResult<ZcashAccounts> {
let keys = key_infos
.iter()
.map(|info| {
Expand Down Expand Up @@ -67,6 +67,6 @@ pub fn generate_sync_ur(key_infos: Vec<UFVKInfo>, mfp: [u8; 4]) -> URResult<Zcas
))
})
.collect::<URResult<Vec<ZcashUnifiedFullViewingKey>>>()?;
let accounts = ZcashAccounts::new(mfp, keys);
let accounts = ZcashAccounts::new(seed_fingerprint.to_vec(), keys);
Ok(accounts)
}
4 changes: 2 additions & 2 deletions rust/keystore/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 14 additions & 3 deletions rust/keystore/src/algorithms/zcash/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::string::{String, ToString};
use alloc::{string::{String, ToString}, vec::Vec};
use ff::PrimeField;
use pasta_curves::Fq;
use rand_chacha::rand_core::SeedableRng;
Expand All @@ -8,7 +8,7 @@ use vendor::{
orchard::keys::{SpendAuthorizingKey, SpendingKey},
zcash_keys::keys::{UnifiedAddressRequest, UnifiedSpendingKey},
zcash_protocol::consensus::{MainNetwork, MAIN_NETWORK},
zip32::AccountId,
zip32::{fingerprint::SeedFingerprint, AccountId},
};
pub mod vendor;

Expand All @@ -21,14 +21,25 @@ pub fn derive_ufvk(seed: &[u8]) -> Result<String> {
Ok(ufvk.encode(&MainNetwork))
}

pub fn calculate_seed_fingerprint(seed: &[u8]) -> Result<[u8; 32]> {
let sfp = SeedFingerprint::from_seed(seed).ok_or(KeystoreError::SeedError(format!(
"Invalid seed, cannot calculate ZIP-32 Seed Fingerprint"
)))?;
Ok(sfp.to_bytes())
}

pub fn sign_message_orchard(seed: &[u8], alpha: [u8; 32], msg: &[u8]) -> Result<[u8; 64]> {
let mut alpha = alpha;
alpha.reverse();
let rng_seed = alpha.clone();
let rng = ChaCha8Rng::from_seed(rng_seed);
let osk = SpendingKey::from_zip32_seed(seed, 133, AccountId::ZERO).unwrap();
let osak = SpendAuthorizingKey::from(&osk);
let randm = Fq::from_repr(alpha).into_option().ok_or(KeystoreError::InvalidDataError(format!("invalid orchard alpha")))?;
let randm = Fq::from_repr(alpha)
.into_option()
.ok_or(KeystoreError::InvalidDataError(format!(
"invalid orchard alpha"
)))?;
let sig = osak.randomize(&randm).sign(rng, &msg);
let bytes = <[u8; 64]>::from(&sig);
Ok(bytes)
Expand Down
4 changes: 2 additions & 2 deletions rust/rust_c/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions rust/rust_c/src/wallet/src/multi_coins_wallet/src/zcash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ use third_party::ur_registry::zcash::zcash_accounts::ZcashAccounts;

#[no_mangle]
pub extern "C" fn get_connect_zcash_wallet_ur(
mfp: PtrBytes,
mfp_len: u32,
seed_fingerprint: PtrBytes,
seed_fingerprint_len: u32,
zcash_keys: Ptr<CSliceFFI<ZcashKey>>,
) -> *mut UREncodeResult {
if mfp_len != 4 {
if seed_fingerprint_len != 32 {
return UREncodeResult::from(URError::UrEncodeError(format!(
"master fingerprint length must be 4, current is {}",
mfp_len
"zip-32 seed fingerprint length must be 32, current is {}",
seed_fingerprint_len
)))
.c_ptr();
}
let mfp = extract_array!(mfp, u8, mfp_len);
let mfp = match <[u8; 4]>::try_from(mfp) {
Ok(mfp) => mfp,
let seed_fingerprint = extract_array!(seed_fingerprint, u8, seed_fingerprint_len);
let seed_fingerprint = match <[u8; 32]>::try_from(seed_fingerprint) {
Ok(seed_fingerprint) => seed_fingerprint,
Err(e) => return UREncodeResult::from(URError::UrEncodeError(e.to_string())).c_ptr(),
};
unsafe {
Expand All @@ -44,7 +44,7 @@ pub extern "C" fn get_connect_zcash_wallet_ur(
)
})
.collect();
let result = generate_sync_ur(ufvks, mfp);
let result = generate_sync_ur(ufvks, seed_fingerprint);
match result.map(|v| v.try_into()) {
Ok(v) => match v {
Ok(data) => UREncodeResult::encode(
Expand Down
22 changes: 18 additions & 4 deletions rust/rust_c/src/zcash/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#![no_std]
extern crate alloc;

use core::slice;

use alloc::boxed::Box;
use app_zcash::get_address;
use common_rust_c::{
structs::{Response, SimpleResponse},
types::{PtrBytes, PtrString},
utils::{convert_c_char, recover_c_char},
};
use keystore::algorithms::zcash::{self, derive_ufvk};
use keystore::algorithms::zcash::{self, calculate_seed_fingerprint, derive_ufvk};
use third_party::cty::c_char;
use app_zcash::get_address;

#[no_mangle]
pub extern "C" fn derive_zcash_ufvk(seed: PtrBytes, seed_len: u32) -> *mut SimpleResponse<c_char> {
Expand All @@ -22,11 +24,23 @@ pub extern "C" fn derive_zcash_ufvk(seed: PtrBytes, seed_len: u32) -> *mut Simpl
}

#[no_mangle]
pub extern "C" fn generate_zcash_default_address(ufvk_text: PtrString) -> *mut SimpleResponse<c_char> {
pub extern "C" fn calculate_zcash_seed_fingerprint(seed: PtrBytes, seed_len: u32) -> *mut SimpleResponse<u8> {
let seed = unsafe { slice::from_raw_parts(seed, seed_len as usize) };
let sfp = calculate_seed_fingerprint(seed);
match sfp {
Ok(bytes) => SimpleResponse::success(Box::into_raw(Box::new(bytes)) as *mut u8).simple_c_ptr(),
Err(e) => SimpleResponse::from(e).simple_c_ptr(),
}
}

#[no_mangle]
pub extern "C" fn generate_zcash_default_address(
ufvk_text: PtrString,
) -> *mut SimpleResponse<c_char> {
let ufvk_text = recover_c_char(ufvk_text);
let address = get_address(&ufvk_text);
match address {
Ok(text) => SimpleResponse::success(convert_c_char(text)).simple_c_ptr(),
Err(e) => SimpleResponse::from(e).simple_c_ptr(),
}
}
}
4 changes: 2 additions & 2 deletions rust/third_party/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions rust/third_party/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ rsa = { version = "0.8.2", default-features = false }
sha1 = { version = "0.10.5", default-features = false }
cty = "0.2.2"
cstr_core = "0.2.6"
ur-registry = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.33-alpha1" }
ur-parse-lib = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.33-alpha1" }
ur-registry = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.36-alpha0" }
ur-parse-lib = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.36-alpha0" }
ed25519-bip32-core = { version = "0.1.1", default-features = false }
cryptoxide = "0.4"
itertools = { version = "0.10.5", default-features = false, features = [
Expand Down
34 changes: 27 additions & 7 deletions src/managers/account_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ int32_t CreateNewAccount(uint8_t accountIndex, const uint8_t *entropy, uint8_t e
return ret;
}


int32_t CreateNewSlip39Account(uint8_t accountIndex, const uint8_t *ems, const uint8_t *entropy, uint8_t entropyLen, const char *password, uint16_t id, uint8_t ie)
{
ASSERT(accountIndex <= 2);
Expand Down Expand Up @@ -559,37 +558,58 @@ int32_t CreateNewTonAccount(uint8_t accountIndex, const char *mnemonic, const ch
return ret;
}

void SetZcashUFVK(uint8_t accountIndex, const char* ufvk) {
static void SetZcashUFVK(uint8_t accountIndex, const char* ufvk, const uint8_t* seedFingerprint) {
ASSERT(accountIndex <= 2);
g_zcashUFVKcache.accountIndex = accountIndex;
memset_s(g_zcashUFVKcache.ufvkCache, ZCASH_UFVK_MAX_LEN, '\0', ZCASH_UFVK_MAX_LEN);
strcpy_s(g_zcashUFVKcache.ufvkCache, ZCASH_UFVK_MAX_LEN, ufvk);

memset_s(g_zcashUFVKcache.seedFingerprint, 32, 0, 32);
memcpy_s(g_zcashUFVKcache.seedFingerprint, 32, seedFingerprint, 32);
printf("SetZcashUFVK, %s\r\n", g_zcashUFVKcache.ufvkCache);
}

int32_t GetZcashUFVK(uint8_t accountIndex, char* output) {
int32_t GetZcashUFVK(uint8_t accountIndex, char* outUFVK, uint8_t* outSFP) {
ASSERT(accountIndex <= 2);
if (g_zcashUFVKcache.accountIndex == accountIndex)
{
strcpy_s(output, ZCASH_UFVK_MAX_LEN, g_zcashUFVKcache.ufvkCache);
strcpy_s(outUFVK, ZCASH_UFVK_MAX_LEN, g_zcashUFVKcache.ufvkCache);
memcpy_s(outSFP, 32, g_zcashUFVKcache.seedFingerprint, 32);
return SUCCESS_CODE;
}
return ERR_ZCASH_INVALID_ACCOUNT_INDEX;
}

int32_t CalculateZcashUFVK(uint8_t accountIndex, const char* password) {
ASSERT(accountIndex <= 2);

uint8_t seed[SEED_LEN];
int32_t ret = GetAccountSeed(accountIndex, &seed, password);

SimpleResponse_c_char *response = derive_zcash_ufvk(seed, SEED_LEN);
if (response->error_code != 0)
{
ret = response->error_code;
printf("error: %s\r\n", response->error_message);
return ret;
}
printf("CalculateZcashUFVK: %s\r\n", response->data);
SetZcashUFVK(accountIndex, response->data);

char ufvk[ZCASH_UFVK_MAX_LEN] = {'\0'};
strcpy_s(ufvk, ZCASH_UFVK_MAX_LEN, response->data);
free_simple_response_c_char(response);

SimpleResponse_u8 *responseSFP = calculate_zcash_seed_fingerprint(seed, SEED_LEN);
if (responseSFP->error_code != 0)
{
ret = response->error_code;
printf("error: %s\r\n", response->error_message);
return ret;
}

uint8_t sfp[32];
memcpy_s(sfp, 32, responseSFP->data, 32);
free_simple_response_u8(responseSFP);

SetZcashUFVK(accountIndex, ufvk, sfp);
}
#endif

3 changes: 2 additions & 1 deletion src/managers/account_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef struct {
typedef struct {
uint8_t accountIndex;
char ufvkCache[ZCASH_UFVK_MAX_LEN + 1];
uint8_t seedFingerprint[32];
} ZcashUFVKCache_t;

int32_t AccountManagerInit(void);
Expand Down Expand Up @@ -97,7 +98,7 @@ uint16_t GetSlip39Id(void);
uint8_t GetSlip39Ie(void);

void AccountsDataCheck(void);
int32_t GetZcashUFVK(uint8_t accountIndex, char* output);
int32_t GetZcashUFVK(uint8_t accountIndex, char* outUFVK, uint8_t* outSFP);
int32_t CalculateZcashUFVK(uint8_t accountIndex, const char* password);

#endif
6 changes: 3 additions & 3 deletions src/ui/gui_widgets/general/gui_standard_receive_widgets.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ static void UpdateConfirmIndexBtn(void)
UpdateConfirmBtn();
}


static void RefreshSwitchAddress(void)
{
AddressDataItem_t addressDataItem;
Expand Down Expand Up @@ -931,8 +930,9 @@ static void ModelGetAddress(uint32_t index, AddressDataItem_t *item)
break;
}
case HOME_WALLET_CARD_ZEC: {
char ufvk[ZCASH_UFVK_MAX_LEN] = {0};
GetZcashUFVK(GetCurrentAccountIndex(), ufvk);
char ufvk[ZCASH_UFVK_MAX_LEN] = {'\0'};
uint8_t sfp[32];
GetZcashUFVK(GetCurrentAccountIndex(), ufvk, sfp);
result = generate_zcash_default_address(ufvk);
break;
}
Expand Down
5 changes: 3 additions & 2 deletions src/ui/gui_widgets/gui_connect_wallet_widgets.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,14 +1211,15 @@ UREncodeResult *GuiGetZecData(void)
keys->data = data;
keys->size = 1;
char ufvk[384] = {'\0'};
GetZcashUFVK(GetCurrentAccountIndex(), ufvk);
uint8_t sfp[32];
GetZcashUFVK(GetCurrentAccountIndex(), ufvk, sfp);
data[0].key_text = ufvk;
data[0].key_name = GetWalletName();
char transparent_path[24] = "m/44'/133'/0'";
char orchard_path[24] = "m/32'/133'/0'";
data[0].transparent_key_path = transparent_path;
data[0].orchard_key_path = orchard_path;
return get_connect_zcash_wallet_ur(mfp, mfp == NULL ? 0 : 4, keys);
return get_connect_zcash_wallet_ur(sfp, 32, keys);
}

void GuiPrepareArConnectWalletView(void)
Expand Down

0 comments on commit a38baee

Please sign in to comment.