Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

devtools: Detect more key formats with zcash-inspect #1537

Merged
merged 1 commit into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions devtools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ sha2.workspace = true
zcash_address.workspace = true
zcash_client_backend ={ workspace = true, features = ["lightwalletd-tonic-transport"] }
zcash_encoding.workspace = true
zcash_keys.workspace = true
zcash_keys = { workspace = true, features = ["unstable"] }
zcash_note_encryption.workspace = true
zcash_primitives = { workspace = true, features = ["transparent-inputs"] }
zcash_proofs = { workspace = true, features = ["directories"] }
zcash_protocol.workspace = true
zcash_protocol = {workspace = true, features = ["local-consensus"] }

# Transparent
secp256k1.workspace = true
Expand Down
88 changes: 86 additions & 2 deletions devtools/src/bin/inspect/keys.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
use std::convert::TryInto;
use std::iter;

use bech32::ToBase32;
use bech32::{FromBase32, ToBase32};
use secrecy::Zeroize;
use zcash_address::{
unified::{self, Encoding},
ToAddress, ZcashAddress,
};
use zcash_keys::keys::{UnifiedAddressRequest, UnifiedFullViewingKey};
use zcash_primitives::{
legacy::{
keys::{AccountPrivKey, IncomingViewingKey},
TransparentAddress,
},
zip32,
};
use zcash_protocol::consensus::NetworkConstants;
use zcash_protocol::{
consensus::{Network, NetworkConstants, NetworkType},
local_consensus::LocalNetwork,
};

use crate::Context;

pub(crate) mod view;

pub(crate) fn inspect_mnemonic(mnemonic: bip0039::Mnemonic, context: Option<Context>) {
eprintln!("Mnemonic phrase");
eprintln!(" - Language: English");
Expand Down Expand Up @@ -162,3 +168,81 @@
"WARNING: This mnemonic phrase is now likely cached in your terminal's history buffer."
);
}

pub(crate) fn inspect_sapling_extsk(

Check warning on line 172 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L172

Added line #L172 was not covered by tests
raw: Vec<bech32::u5>,
variant: bech32::Variant,
network: NetworkType,
) {
match Vec::<u8>::from_base32(&raw)
.map_err(|_| ())
.and_then(|data| sapling::zip32::ExtendedSpendingKey::read(&data[..]).map_err(|_| ()))

Check warning on line 179 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L177-L179

Added lines #L177 - L179 were not covered by tests
{
Err(_) => {
eprintln!("Invalid encoding that claims to be a Sapling extended spending key");

Check warning on line 182 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L181-L182

Added lines #L181 - L182 were not covered by tests
}
Ok(extsk) => {
eprintln!("Sapling extended spending key");
match variant {
bech32::Variant::Bech32 => (),
bech32::Variant::Bech32m => eprintln!("⚠️ Incorrectly encoded with Bech32m"),

Check warning on line 188 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L184-L188

Added lines #L184 - L188 were not covered by tests
}

let default_addr_bytes = extsk.default_address().1.to_bytes();
eprintln!(
"- Default address: {}",
bech32::encode(
network.hrp_sapling_payment_address(),
default_addr_bytes.to_base32(),
bech32::Variant::Bech32,

Check warning on line 197 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L191-L197

Added lines #L191 - L197 were not covered by tests
)
.unwrap(),

Check warning on line 199 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L199

Added line #L199 was not covered by tests
);

#[allow(deprecated)]
if let Ok(ufvk) = UnifiedFullViewingKey::from_sapling_extended_full_viewing_key(
extsk.to_extended_full_viewing_key(),

Check warning on line 204 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L204

Added line #L204 was not covered by tests
) {
let encoded_ufvk = match network {
NetworkType::Main => ufvk.encode(&Network::MainNetwork),
NetworkType::Test => ufvk.encode(&Network::TestNetwork),
NetworkType::Regtest => ufvk.encode(&LocalNetwork {
overwinter: None,
sapling: None,
blossom: None,
heartwood: None,
canopy: None,
nu5: None,
nu6: None,
#[cfg(zcash_unstable = "zfuture")]
z_future: None,

Check warning on line 218 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L206-L218

Added lines #L206 - L218 were not covered by tests
}),
};
eprintln!("- UFVK: {encoded_ufvk}");

Check warning on line 221 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L221

Added line #L221 was not covered by tests

let (default_ua, _) = ufvk
.default_address(UnifiedAddressRequest::unsafe_new(false, true, false))

Check warning on line 224 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L223-L224

Added lines #L223 - L224 were not covered by tests
.expect("should exist");
let encoded_ua = match network {
NetworkType::Main => default_ua.encode(&Network::MainNetwork),
NetworkType::Test => default_ua.encode(&Network::TestNetwork),
NetworkType::Regtest => default_ua.encode(&LocalNetwork {
overwinter: None,
sapling: None,
blossom: None,
heartwood: None,
canopy: None,
nu5: None,
nu6: None,
#[cfg(zcash_unstable = "zfuture")]
z_future: None,

Check warning on line 238 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L226-L238

Added lines #L226 - L238 were not covered by tests
}),
};
eprintln!(" - Default address: {encoded_ua}");

Check warning on line 241 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L241

Added line #L241 was not covered by tests
}
}
}

eprintln!();
eprintln!("WARNING: This spending key is now likely cached in your terminal's history buffer.");

Check warning on line 247 in devtools/src/bin/inspect/keys.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys.rs#L246-L247

Added lines #L246 - L247 were not covered by tests
}
163 changes: 163 additions & 0 deletions devtools/src/bin/inspect/keys/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use bech32::{FromBase32, ToBase32};
use zcash_address::unified::{self, Container, Encoding};
use zcash_keys::keys::{UnifiedAddressRequest, UnifiedFullViewingKey};
use zcash_protocol::{
consensus::{Network, NetworkConstants, NetworkType},
local_consensus::LocalNetwork,
};

pub(crate) fn inspect_ufvk(ufvk: unified::Ufvk, network: NetworkType) {
eprintln!("Unified full viewing key");
eprintln!(
" - Network: {}",
match network {
NetworkType::Main => "main",
NetworkType::Test => "testnet",
NetworkType::Regtest => "regtest",

Check warning on line 16 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L9-L16

Added lines #L9 - L16 were not covered by tests
}
);
eprintln!(" - Items:");
for item in ufvk.items() {
match item {
unified::Fvk::Orchard(data) => {
eprintln!(
" - Orchard ({})",
unified::Ufvk::try_from_items(vec![unified::Fvk::Orchard(data)])
.unwrap()
.encode(&network)

Check warning on line 27 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L19-L27

Added lines #L19 - L27 were not covered by tests
);
}
unified::Fvk::Sapling(data) => {
eprintln!(
" - Sapling ({})",
bech32::encode(
network.hrp_sapling_extended_full_viewing_key(),
data.to_base32(),
bech32::Variant::Bech32,

Check warning on line 36 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L30-L36

Added lines #L30 - L36 were not covered by tests
)
.unwrap(),

Check warning on line 38 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L38

Added line #L38 was not covered by tests
);
}
unified::Fvk::P2pkh(data) => {
eprintln!(" - Transparent P2PKH");
eprintln!(" - Payload: {}", hex::encode(data));

Check warning on line 43 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L41-L43

Added lines #L41 - L43 were not covered by tests
}
unified::Fvk::Unknown { typecode, data } => {
eprintln!(" - Unknown");
eprintln!(" - Typecode: {}", typecode);
eprintln!(" - Payload: {}", hex::encode(data));

Check warning on line 48 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L45-L48

Added lines #L45 - L48 were not covered by tests
}
}
}
}

pub(crate) fn inspect_uivk(uivk: unified::Uivk, network: NetworkType) {
eprintln!("Unified incoming viewing key");
eprintln!(
" - Network: {}",
match network {
NetworkType::Main => "main",
NetworkType::Test => "testnet",
NetworkType::Regtest => "regtest",

Check warning on line 61 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L54-L61

Added lines #L54 - L61 were not covered by tests
}
);
eprintln!(" - Items:");
for item in uivk.items() {
match item {
unified::Ivk::Orchard(data) => {
eprintln!(
" - Orchard ({})",
unified::Uivk::try_from_items(vec![unified::Ivk::Orchard(data)])
.unwrap()
.encode(&network)

Check warning on line 72 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L64-L72

Added lines #L64 - L72 were not covered by tests
);
}
unified::Ivk::Sapling(data) => {
eprintln!(" - Sapling");
eprintln!(" - Payload: {}", hex::encode(data));

Check warning on line 77 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L75-L77

Added lines #L75 - L77 were not covered by tests
}
unified::Ivk::P2pkh(data) => {
eprintln!(" - Transparent P2PKH");
eprintln!(" - Payload: {}", hex::encode(data));

Check warning on line 81 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L79-L81

Added lines #L79 - L81 were not covered by tests
}
unified::Ivk::Unknown { typecode, data } => {
eprintln!(" - Unknown");
eprintln!(" - Typecode: {}", typecode);
eprintln!(" - Payload: {}", hex::encode(data));

Check warning on line 86 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L83-L86

Added lines #L83 - L86 were not covered by tests
}
}
}
}

pub(crate) fn inspect_sapling_extfvk(

Check warning on line 92 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L92

Added line #L92 was not covered by tests
raw: Vec<bech32::u5>,
variant: bech32::Variant,
network: NetworkType,
) {
match Vec::<u8>::from_base32(&raw)
.map_err(|_| ())
.and_then(|data| sapling::zip32::ExtendedFullViewingKey::read(&data[..]).map_err(|_| ()))

Check warning on line 99 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L97-L99

Added lines #L97 - L99 were not covered by tests
{
Err(_) => {
eprintln!("Invalid encoding that claims to be a Sapling extended full viewing key");

Check warning on line 102 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L101-L102

Added lines #L101 - L102 were not covered by tests
}
Ok(extfvk) => {
eprintln!("Sapling extended full viewing key");
match variant {
bech32::Variant::Bech32 => (),
bech32::Variant::Bech32m => eprintln!("⚠️ Incorrectly encoded with Bech32m"),

Check warning on line 108 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L104-L108

Added lines #L104 - L108 were not covered by tests
}

let default_addr_bytes = extfvk.default_address().1.to_bytes();
eprintln!(
"- Default address: {}",
bech32::encode(
network.hrp_sapling_payment_address(),
default_addr_bytes.to_base32(),
bech32::Variant::Bech32,

Check warning on line 117 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L111-L117

Added lines #L111 - L117 were not covered by tests
)
.unwrap(),

Check warning on line 119 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L119

Added line #L119 was not covered by tests
);

if let Ok(ufvk) = UnifiedFullViewingKey::from_sapling_extended_full_viewing_key(extfvk)

Check warning on line 122 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L122

Added line #L122 was not covered by tests
{
let encoded_ufvk = match network {
NetworkType::Main => ufvk.encode(&Network::MainNetwork),
NetworkType::Test => ufvk.encode(&Network::TestNetwork),
NetworkType::Regtest => ufvk.encode(&LocalNetwork {
overwinter: None,
sapling: None,
blossom: None,
heartwood: None,
canopy: None,
nu5: None,
nu6: None,
#[cfg(zcash_unstable = "zfuture")]
z_future: None,

Check warning on line 136 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L124-L136

Added lines #L124 - L136 were not covered by tests
}),
};
eprintln!("- Equivalent UFVK: {encoded_ufvk}");

Check warning on line 139 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L139

Added line #L139 was not covered by tests

let (default_ua, _) = ufvk
.default_address(UnifiedAddressRequest::unsafe_new(false, true, false))

Check warning on line 142 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L141-L142

Added lines #L141 - L142 were not covered by tests
.expect("should exist");
let encoded_ua = match network {
NetworkType::Main => default_ua.encode(&Network::MainNetwork),
NetworkType::Test => default_ua.encode(&Network::TestNetwork),
NetworkType::Regtest => default_ua.encode(&LocalNetwork {
overwinter: None,
sapling: None,
blossom: None,
heartwood: None,
canopy: None,
nu5: None,
nu6: None,
#[cfg(zcash_unstable = "zfuture")]
z_future: None,

Check warning on line 156 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L144-L156

Added lines #L144 - L156 were not covered by tests
}),
};
eprintln!(" - Default address: {encoded_ua}");

Check warning on line 159 in devtools/src/bin/inspect/keys/view.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/keys/view.rs#L159

Added line #L159 was not covered by tests
}
}
}
}
37 changes: 36 additions & 1 deletion devtools/src/bin/inspect/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
use lazy_static::lazy_static;
use secrecy::Zeroize;
use tokio::runtime::Runtime;
use zcash_address::ZcashAddress;
use zcash_address::{
unified::{self, Encoding},
ZcashAddress,
};
use zcash_primitives::{block::BlockHeader, consensus::BranchId, transaction::Transaction};
use zcash_proofs::{default_params_folder, load_parameters, ZcashParameters};
use zcash_protocol::consensus::NetworkType;

mod context;
use context::{Context, ZUint256};
use zcash_protocol::constants;

mod address;
mod block;
Expand Down Expand Up @@ -72,6 +77,36 @@
inspect_bytes(bytes, opts.context, opts.lookup);
} else if let Ok(addr) = ZcashAddress::try_from_encoded(&opts.data) {
address::inspect(addr);
} else if let Ok((network, uivk)) = unified::Uivk::decode(&opts.data) {
keys::view::inspect_uivk(uivk, network);
} else if let Ok((network, ufvk)) = unified::Ufvk::decode(&opts.data) {
keys::view::inspect_ufvk(ufvk, network);
} else if let Ok((hrp, data, variant)) = bech32::decode(&opts.data) {
match hrp.as_str() {
constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => {
keys::view::inspect_sapling_extfvk(data, variant, NetworkType::Main);

Check warning on line 87 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L80-L87

Added lines #L80 - L87 were not covered by tests
}
constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => {
keys::view::inspect_sapling_extfvk(data, variant, NetworkType::Test);

Check warning on line 90 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L89-L90

Added lines #L89 - L90 were not covered by tests
}
constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => {
keys::view::inspect_sapling_extfvk(data, variant, NetworkType::Regtest);

Check warning on line 93 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L92-L93

Added lines #L92 - L93 were not covered by tests
}
constants::mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY => {
keys::inspect_sapling_extsk(data, variant, NetworkType::Main);

Check warning on line 96 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L95-L96

Added lines #L95 - L96 were not covered by tests
}
constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY => {
keys::inspect_sapling_extsk(data, variant, NetworkType::Test);

Check warning on line 99 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L98-L99

Added lines #L98 - L99 were not covered by tests
}
constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY => {
keys::inspect_sapling_extsk(data, variant, NetworkType::Regtest);

Check warning on line 102 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L101-L102

Added lines #L101 - L102 were not covered by tests
}
_ => {
// Unknown data format.
eprintln!("String does not match known Zcash data formats.");
process::exit(2);

Check warning on line 107 in devtools/src/bin/inspect/main.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/main.rs#L106-L107

Added lines #L106 - L107 were not covered by tests
}
}
} else {
// Unknown data format.
eprintln!("String does not match known Zcash data formats.");
Expand Down
Loading