From 5749322df3261adf9ed4ba2a4b3b200ddeccd502 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 12 Nov 2024 15:40:29 -0500 Subject: [PATCH] fix: lookup first before parsing raw key --- cmd/soroban-cli/src/config/address.rs | 2 +- cmd/soroban-cli/src/config/key.rs | 24 +++++++++-------- cmd/soroban-cli/src/config/locator.rs | 38 ++++++++++++++++++--------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index af1918103..ac2adc762 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -48,7 +48,7 @@ impl Address { Address::MuxedAccount(muxed_account) => Ok(muxed_account.clone()), Address::AliasOrSecret(alias) => alias .parse() - .or_else(|_| Ok(locator.read_identity(alias)?.public_key(hd_path)?)), + .or_else(|_| Ok(locator.get_public_key(alias, hd_path)?)), } } diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs index e6adface4..18f52b876 100644 --- a/cmd/soroban-cli/src/config/key.rs +++ b/cmd/soroban-cli/src/config/key.rs @@ -13,13 +13,15 @@ pub enum Error { Secret(#[from] secret::Error), #[error(transparent)] StrKey(#[from] stellar_strkey::DecodeError), + #[error("failed to parse key {0}")] + Parse(String), } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] #[serde(untagged)] pub enum Key { Secret(Secret), - PublicKey { public_key: PublicKey }, + PublicKey { public_key: Public }, MuxedAccount { muxed_account: MuxedAccount }, } @@ -28,7 +30,7 @@ impl Key { let bytes = match self { Key::Secret(secret) => secret.public_key(hd_path)?.0, Key::PublicKey { - public_key: PublicKey(key), + public_key: Public(key), } => key.0, Key::MuxedAccount { muxed_account: MuxedAccount(stellar_strkey::ed25519::MuxedAccount { ed25519, id }), @@ -66,14 +68,14 @@ impl FromStr for Key { if let Ok(muxed_account) = s.parse() { return Ok(Key::MuxedAccount { muxed_account }); } - todo!("Error handling for invalid key format"); + Err(Error::Parse(s.to_owned())) } } impl From for Key { fn from(value: stellar_strkey::ed25519::PublicKey) -> Self { Key::PublicKey { - public_key: PublicKey(value), + public_key: Public(value), } } } @@ -85,24 +87,24 @@ impl From<&stellar_strkey::ed25519::PublicKey> for Key { } #[derive(Debug, PartialEq, Eq, serde_with::SerializeDisplay, serde_with::DeserializeFromStr)] -pub struct PublicKey(pub stellar_strkey::ed25519::PublicKey); +pub struct Public(pub stellar_strkey::ed25519::PublicKey); -impl FromStr for PublicKey { +impl FromStr for Public { type Err = stellar_strkey::DecodeError; fn from_str(s: &str) -> Result { - Ok(PublicKey(stellar_strkey::ed25519::PublicKey::from_str(s)?)) + Ok(Public(stellar_strkey::ed25519::PublicKey::from_str(s)?)) } } -impl Display for PublicKey { +impl Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } -impl From<&PublicKey> for stellar_strkey::ed25519::MuxedAccount { - fn from(PublicKey(stellar_strkey::ed25519::PublicKey(key)): &PublicKey) -> Self { +impl From<&Public> for stellar_strkey::ed25519::MuxedAccount { + fn from(Public(stellar_strkey::ed25519::PublicKey(key)): &Public) -> Self { stellar_strkey::ed25519::MuxedAccount { id: 0, ed25519: *key, @@ -136,7 +138,7 @@ mod test { #[test] fn public_key() { let key = Key::PublicKey { - public_key: PublicKey(stellar_strkey::ed25519::PublicKey([0; 32])), + public_key: Public(stellar_strkey::ed25519::PublicKey([0; 32])), }; let serialized = toml::to_string(&key).unwrap(); println!("{serialized}"); diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 2e002b8e5..e21866872 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -11,11 +11,11 @@ use std::{ }; use stellar_strkey::{Contract, DecodeError}; -use crate::{commands::HEADING_GLOBAL, utils::find_config_dir, Pwd}; +use crate::{commands::HEADING_GLOBAL, utils::find_config_dir, xdr, Pwd}; use super::{ alias, - key::Key, + key::{self, Key}, network::{self, Network}, secret::Secret, Config, @@ -81,6 +81,10 @@ pub enum Error { UpgradeCheckReadFailed { path: PathBuf, error: io::Error }, #[error("Failed to write upgrade check file: {path}: {error}")] UpgradeCheckWriteFailed { path: PathBuf, error: io::Error }, + #[error("Only private keys and seed phrases are supported for getting private keys {0}")] + SecretKeyOnly(String), + #[error(transparent)] + Key(#[from] key::Error), } #[derive(Debug, clap::Args, Default, Clone)] @@ -239,22 +243,32 @@ impl Args { } pub fn read_identity(&self, name: &str) -> Result { - Ok(KeyType::Identity.read_with_global(name, &self.local_config()?)?) + KeyType::Identity.read_with_global(name, &self.local_config()?) } - pub fn get_private_key(&self, key_or_name: &str) -> Result { - if let Ok(signer) = key_or_name.parse::() { - Ok(signer) + pub fn read_key(&self, key_or_name: &str) -> Result { + if let Ok(key) = self.read_identity(key_or_name) { + Ok(key) } else { - match self.read_identity(key_or_name)? { - Key::Secret(s) => Ok(s), - _ => Err(Error::SecretFileRead { - path: self.alias_path(key_or_name)?, - }), - } + Ok(key_or_name.parse()?) + } + } + + pub fn get_private_key(&self, key_or_name: &str) -> Result { + match self.read_key(key_or_name)? { + Key::Secret(s) => Ok(s), + _ => Err(Error::SecretKeyOnly(key_or_name.to_string())), } } + pub fn get_public_key( + &self, + key_or_name: &str, + hd_path: Option, + ) -> Result { + Ok(self.read_key(key_or_name)?.public_key(hd_path)?) + } + pub fn read_network(&self, name: &str) -> Result { let res = KeyType::Network.read_with_global(name, &self.local_config()?); if let Err(Error::ConfigMissing(_, _)) = &res {