Skip to content

Commit

Permalink
feat: add zcash ffi interface
Browse files Browse the repository at this point in the history
  • Loading branch information
soralit committed Nov 26, 2024
1 parent b92c074 commit 7e6c58c
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 8 deletions.
1 change: 1 addition & 0 deletions libs/ur-registry-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod sui;
pub mod sync;
pub mod ton;
pub mod tron;
pub mod zcash;
mod util_internal;
pub mod utils;

Expand Down
2 changes: 2 additions & 0 deletions libs/ur-registry-ffi/src/zcash/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod zcash_pczt;
pub mod zcash_accounts;
100 changes: 100 additions & 0 deletions libs/ur-registry-ffi/src/zcash/zcash_accounts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use crate::export;
use anyhow::{format_err, Error};
use serde::{Deserialize, Serialize};
use serde_json::json;
use ur_registry::{crypto_hd_key::CryptoHDKey, registry_types::ZCASH_ACCOUNTS};

#[derive(Default, Clone, Debug, Serialize, Deserialize)]
struct ZcashAccounts {
seed_fingerprint: String,
accounts: Vec<ZcashUnifiedAccount>,
}

impl From<ur_registry::zcash::zcash_accounts::ZcashAccounts> for ZcashAccounts {
fn from(value: ur_registry::zcash::zcash_accounts::ZcashAccounts) -> Self {
Self {
seed_fingerprint: hex::encode(value.get_seed_fingerprint()),
accounts: value
.get_accounts()
.iter()
.map(|account| account.clone().into())
.collect(),
}
}
}

#[derive(Default, Clone, Debug, Serialize, Deserialize)]
struct ZcashTransparentAccount {
path: String,
xpub: String,
}

impl From<CryptoHDKey> for ZcashTransparentAccount {
fn from(value: CryptoHDKey) -> Self {
Self {
path: value.get_origin().unwrap().get_path().unwrap(),
xpub: value.get_bip32_key(),
}
}
}

#[derive(Default, Clone, Debug, Serialize, Deserialize)]
struct ZcashShieldedAccount {
path: String,
fvk: String,
}

impl From<ur_registry::zcash::zcash_full_viewing_key::ZcashFullViewingKey>
for ZcashShieldedAccount
{
fn from(value: ur_registry::zcash::zcash_full_viewing_key::ZcashFullViewingKey) -> Self {
Self {
path: value.get_key_path().get_path().unwrap(),
fvk: hex::encode(value.get_key_data()),
}
}
}

#[derive(Default, Clone, Debug, Serialize, Deserialize)]
struct ZcashUnifiedAccount {
transparent: Option<ZcashTransparentAccount>,
orchard: ZcashShieldedAccount,
name: Option<String>,
}

impl From<ur_registry::zcash::zcash_unified_full_viewing_key::ZcashUnifiedFullViewingKey>
for ZcashUnifiedAccount
{
fn from(
value: ur_registry::zcash::zcash_unified_full_viewing_key::ZcashUnifiedFullViewingKey,
) -> Self {
Self {
transparent: value.get_transparent().map(|account| account.into()),
orchard: value.get_orchard().into(),
name: value.get_name(),
}
}
}

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_parseZcashAccounts
fn parse_zcash_accounts(
ur_type: &str,
cbor_hex: &str
) -> String {
if ZCASH_ACCOUNTS.get_type() != ur_type {
return json!({"error": "type not match"}).to_string();
}
let parse_accounts = || -> Result<ZcashAccounts, Error> {
let cbor = hex::decode(cbor_hex.to_string())?;
let zcash_accounts =
ur_registry::zcash::zcash_accounts::ZcashAccounts::try_from(cbor).map_err(|_| format_err!(""))?;
let accounts = zcash_accounts.into();
Ok(accounts)
};
match parse_accounts() {
Ok(accounts) => json!(accounts).to_string(),
Err(_) => json!({"error": "zcash accounts is invalid"}).to_string(),
}
}
}
34 changes: 34 additions & 0 deletions libs/ur-registry-ffi/src/zcash/zcash_pczt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::export;
use serde_json::json;
use ur_registry::{registry_types::ZCASH_PCZT, zcash::zcash_pczt::ZcashPczt};

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_generateZcashPcZt
fn generate_zcash_pczt(
data: &str
) -> String {
let data = match data {
"" => return json!({"error": "data is required"}).to_string(),
_x => _x.to_string()
};

let bytes = match hex::decode(data) {
Ok(v) => v,
Err(_) => return json!({"error": "data is invalid"}).to_string(),
};

let cbor_bytes: Vec<u8> = match ZcashPczt::new(
bytes,
).try_into() {
Ok(v) => v,
Err(_) => return json!({"error": "data is invalid"}).to_string(),
};
let cbor_hex = hex::encode(cbor_bytes);
let ur_type = ZCASH_PCZT.get_type();
let ur = json!({
"type": ur_type,
"cbor": cbor_hex,
});
ur.to_string()
}
}
2 changes: 2 additions & 0 deletions libs/ur-registry/src/macros_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use crate::sui::sui_signature::SuiSignature;
use crate::ton::{ton_sign_request::TonSignRequest, ton_signature::TonSignature};
use crate::zcash::zcash_accounts::ZcashAccounts;
use crate::zcash::zcash_full_viewing_key::ZcashFullViewingKey;
use crate::zcash::zcash_pczt::ZcashPczt;
use crate::zcash::zcash_unified_full_viewing_key::ZcashUnifiedFullViewingKey;
use crate::{impl_cbor_bytes, impl_ur_try_from_cbor_bytes, impl_ur_try_into_cbor_bytes};
use alloc::string::ToString;
Expand Down Expand Up @@ -101,4 +102,5 @@ impl_cbor_bytes!(
ZcashAccounts,
ZcashFullViewingKey,
ZcashUnifiedFullViewingKey,
ZcashPczt,
);
9 changes: 1 addition & 8 deletions libs/ur-registry/src/zcash/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
pub mod zcash_accounts;
pub mod zcash_full_viewing_key;
pub mod zcash_unified_full_viewing_key;

#[cfg(test)]
mod tests {
#[test]
fn test_zcash_accounts() {

}
}
pub mod zcash_pczt;
58 changes: 58 additions & 0 deletions libs/ur-registry/src/zcash/zcash_pczt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use alloc::string::ToString;
use minicbor::data::Int;

use crate::{
cbor::cbor_map,
impl_template_struct,
registry_types::{RegistryType, ZCASH_PCZT},
traits::{MapSize, RegistryItem},
types::Bytes,
};

const DATA: u8 = 1;

impl_template_struct!(ZcashPczt { data: Bytes });

impl MapSize for ZcashPczt {
fn map_size(&self) -> u64 {
1
}
}

impl RegistryItem for ZcashPczt {
fn get_registry_type() -> RegistryType<'static> {
ZCASH_PCZT
}
}

impl<C> minicbor::Encode<C> for ZcashPczt {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
_ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.map(self.map_size())?;

e.int(Int::from(DATA))?.bytes(&self.data)?;

Ok(())
}
}

impl<'b, C> minicbor::Decode<'b, C> for ZcashPczt {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut result = ZcashPczt::default();
cbor_map(d, &mut result, |key, obj, d| {
let key =
u8::try_from(key).map_err(|e| minicbor::decode::Error::message(e.to_string()))?;
match key {
DATA => {
obj.data = d.bytes()?.to_vec();
}
_ => {}
}
Ok(())
})?;
Ok(result)
}
}

0 comments on commit 7e6c58c

Please sign in to comment.