zcash-sync/src/key2.rs

132 lines
4.6 KiB
Rust
Raw Normal View History

2022-06-08 05:48:16 -07:00
use crate::coinconfig::CoinConfig;
2022-11-17 01:13:51 -08:00
use anyhow::anyhow;
2022-06-08 05:48:16 -07:00
use bip39::{Language, Mnemonic, Seed};
2022-12-10 14:01:10 -08:00
use zcash_client_backend::encoding::{decode_extended_full_viewing_key, decode_extended_spending_key, decode_payment_address, decode_transparent_address, encode_extended_full_viewing_key, encode_extended_spending_key, encode_payment_address};
2022-11-17 01:13:51 -08:00
use zcash_client_backend::keys::UnifiedFullViewingKey;
2022-06-08 05:48:16 -07:00
use zcash_primitives::consensus::{Network, Parameters};
use zcash_primitives::zip32::{ChildIndex, ExtendedFullViewingKey, ExtendedSpendingKey};
pub fn decode_key(
coin: u8,
key: &str,
index: u32,
2022-11-17 01:13:51 -08:00
) -> anyhow::Result<(
Option<String>,
Option<String>,
String,
String,
Option<orchard::keys::FullViewingKey>,
)> {
2022-06-08 05:48:16 -07:00
let c = CoinConfig::get(coin);
let network = c.chain.network();
let res = if let Ok(mnemonic) = Mnemonic::from_phrase(key, Language::English) {
let (sk, ivk, pa) = derive_secret_key(network, &mnemonic, index)?;
2022-11-17 01:13:51 -08:00
Ok((Some(key.to_string()), Some(sk), ivk, pa, None))
} else if let Ok(sk) =
2022-06-08 05:48:16 -07:00
decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), key)
{
let (ivk, pa) = derive_viewing_key(network, &sk)?;
2022-11-17 01:13:51 -08:00
Ok((None, Some(key.to_string()), ivk, pa, None))
} else if let Ok(fvk) =
2022-06-08 05:48:16 -07:00
decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), key)
{
let pa = derive_address(network, &fvk)?;
2022-11-17 01:13:51 -08:00
Ok((None, None, key.to_string(), pa, None))
} else if let Ok(ufvk) = UnifiedFullViewingKey::decode(network, key) {
let sapling_dfvk = ufvk
.sapling()
.ok_or(anyhow!("UFVK must contain a sapling key"))?;
let sapling_efvk =
ExtendedFullViewingKey::from_diversifiable_full_viewing_key(&sapling_dfvk);
let key = encode_extended_full_viewing_key(
network.hrp_sapling_extended_full_viewing_key(),
&sapling_efvk,
);
let pa = derive_address(network, &sapling_efvk)?;
let orchard_key = ufvk.orchard().cloned();
Ok((None, None, key, pa, orchard_key))
2022-06-08 05:48:16 -07:00
} else {
Err(anyhow::anyhow!("Not a valid key"))
};
res
}
2022-11-05 05:42:55 -07:00
#[allow(dead_code)] // Used by C FFI
2022-06-08 05:48:16 -07:00
pub fn is_valid_key(coin: u8, key: &str) -> i8 {
let c = CoinConfig::get(coin);
let network = c.chain.network();
if Mnemonic::from_phrase(key, Language::English).is_ok() {
return 0;
}
2022-11-06 04:50:51 -08:00
if decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), key).is_ok() {
2022-06-08 05:48:16 -07:00
return 1;
}
2022-11-06 04:50:51 -08:00
if decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), key)
.is_ok()
2022-06-08 05:48:16 -07:00
{
return 2;
}
2022-11-17 01:13:51 -08:00
if UnifiedFullViewingKey::decode(network, key).is_ok() {
return 3;
}
2022-10-28 23:40:05 -07:00
// TODO: Accept UA viewing key
2022-06-08 05:48:16 -07:00
-1
}
2022-11-05 05:42:55 -07:00
#[allow(dead_code)] // Used by C FFI
2022-06-08 05:48:16 -07:00
pub fn is_valid_address(coin: u8, address: &str) -> bool {
let c = CoinConfig::get(coin);
let network = c.chain.network();
2022-12-10 14:01:10 -08:00
if decode_payment_address(network.hrp_sapling_payment_address(), address).is_ok() {
true
}
else if let Ok(Some(_)) = decode_transparent_address(
&network.b58_pubkey_address_prefix(),
&network.b58_script_address_prefix(),
address) {
true
}
else if zcash_client_backend::address::RecipientAddress::decode(network, address).is_some() {
true
}
else {
false
}
2022-06-08 05:48:16 -07:00
}
fn derive_secret_key(
network: &Network,
mnemonic: &Mnemonic,
index: u32,
) -> anyhow::Result<(String, String, String)> {
let seed = Seed::new(mnemonic, "");
let master = ExtendedSpendingKey::master(seed.as_bytes());
let path = [
ChildIndex::Hardened(32),
ChildIndex::Hardened(network.coin_type()),
ChildIndex::Hardened(index),
];
let extsk = ExtendedSpendingKey::from_path(&master, &path);
let sk = encode_extended_spending_key(network.hrp_sapling_extended_spending_key(), &extsk);
let (fvk, pa) = derive_viewing_key(network, &extsk)?;
Ok((sk, fvk, pa))
}
fn derive_viewing_key(
network: &Network,
extsk: &ExtendedSpendingKey,
) -> anyhow::Result<(String, String)> {
let fvk = ExtendedFullViewingKey::from(extsk);
let pa = derive_address(network, &fvk)?;
let fvk =
encode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), &fvk);
Ok((fvk, pa))
}
fn derive_address(network: &Network, fvk: &ExtendedFullViewingKey) -> anyhow::Result<String> {
let (_, payment_address) = fvk.default_address();
let address = encode_payment_address(network.hrp_sapling_payment_address(), &payment_address);
Ok(address)
}