From d33a9fc8d1f78310e1b7f16bf8cd8fb9389d09ca Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 5 Nov 2024 11:00:43 -0500 Subject: [PATCH 01/60] feat: Add new `Key` type; allowing public keys to be named keys This will allow users to add public keys with `keys add` so that they can be referenced in commands that need public addresses and contract invoke's that take address arguments. --- Cargo.lock | 9 +- cmd/soroban-cli/Cargo.toml | 1 + cmd/soroban-cli/src/commands/keys/add.rs | 6 +- cmd/soroban-cli/src/commands/keys/address.rs | 18 ++- cmd/soroban-cli/src/commands/keys/show.rs | 7 +- cmd/soroban-cli/src/config/address.rs | 14 +- cmd/soroban-cli/src/config/key.rs | 146 +++++++++++++++++++ cmd/soroban-cli/src/config/locator.rs | 30 +++- cmd/soroban-cli/src/config/mod.rs | 1 + cmd/soroban-cli/src/config/secret.rs | 23 ++- cmd/soroban-cli/src/config/sign_with.rs | 2 +- 11 files changed, 214 insertions(+), 43 deletions(-) create mode 100644 cmd/soroban-cli/src/config/key.rs diff --git a/Cargo.lock b/Cargo.lock index 3f8fcf4ac..609b5be2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4067,9 +4067,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", @@ -4085,9 +4085,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", @@ -4336,6 +4336,7 @@ dependencies = [ "serde", "serde-aux", "serde_json", + "serde_with", "sha2 0.10.8", "shell-escape", "shlex", diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 2f2a26255..e6e205248 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -124,6 +124,7 @@ fqdn = "0.3.12" open = "5.3.0" url = "2.5.2" wasm-gen = "0.1.4" +serde_with = "3.11.0" [build-dependencies] crate-git-revision = "0.0.6" diff --git a/cmd/soroban-cli/src/commands/keys/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs index d8f528bae..5e32944e8 100644 --- a/cmd/soroban-cli/src/commands/keys/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -1,11 +1,11 @@ use clap::command; -use crate::config::{locator, secret}; +use crate::config::{key, locator, secret}; #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Secret(#[from] secret::Error), + Key(#[from] key::Error), #[error(transparent)] Config(#[from] locator::Error), @@ -28,6 +28,6 @@ impl Cmd { pub fn run(&self) -> Result<(), Error> { Ok(self .config_locator - .write_identity(&self.name, &self.secrets.read_secret()?)?) + .write_key(&self.name, &self.secrets.read_key()?)?) } } diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index d13381b49..8eda8dd83 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,15 +1,14 @@ -use crate::commands::config::secret; - -use super::super::config::locator; use clap::arg; +use crate::commands::config::{key, locator}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] Config(#[from] locator::Error), #[error(transparent)] - Secret(#[from] secret::Error), + Key(#[from] key::Error), #[error(transparent)] StrKey(#[from] stellar_strkey::DecodeError), @@ -36,10 +35,13 @@ impl Cmd { } pub fn private_key(&self) -> Result { - Ok(self - .locator - .read_identity(&self.name)? - .key_pair(self.hd_path)?) + Ok(ed25519_dalek::SigningKey::from_bytes( + &self + .locator + .read_identity(&self.name)? + .private_key(self.hd_path)? + .0, + )) } pub fn public_key(&self) -> Result { diff --git a/cmd/soroban-cli/src/commands/keys/show.rs b/cmd/soroban-cli/src/commands/keys/show.rs index 58c47740c..ae0faab03 100644 --- a/cmd/soroban-cli/src/commands/keys/show.rs +++ b/cmd/soroban-cli/src/commands/keys/show.rs @@ -1,6 +1,6 @@ use clap::arg; -use crate::config::{locator, secret}; +use crate::config::{key, locator}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -8,10 +8,7 @@ pub enum Error { Config(#[from] locator::Error), #[error(transparent)] - Secret(#[from] secret::Error), - - #[error(transparent)] - StrKey(#[from] stellar_strkey::DecodeError), + Key(#[from] key::Error), } #[derive(Debug, clap::Parser, Clone)] diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 066bc8d91..af1918103 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use crate::xdr; -use super::{locator, secret}; +use super::{key, locator, secret}; /// Address can be either a public key or eventually an alias of a address. #[derive(Clone, Debug)] @@ -22,7 +22,7 @@ pub enum Error { #[error(transparent)] Locator(#[from] locator::Error), #[error(transparent)] - Secret(#[from] secret::Error), + Key(#[from] key::Error), #[error("Address cannot be used to sign {0}")] CannotSign(xdr::MuxedAccount), } @@ -46,18 +46,16 @@ impl Address { ) -> Result { match self { Address::MuxedAccount(muxed_account) => Ok(muxed_account.clone()), - Address::AliasOrSecret(alias) => alias.parse().or_else(|_| { - Ok(xdr::MuxedAccount::Ed25519( - locator.read_identity(alias)?.public_key(hd_path)?.0.into(), - )) - }), + Address::AliasOrSecret(alias) => alias + .parse() + .or_else(|_| Ok(locator.read_identity(alias)?.public_key(hd_path)?)), } } pub fn resolve_secret(&self, locator: &locator::Args) -> Result { match &self { + Address::AliasOrSecret(alias) => Ok(locator.get_private_key(alias)?), Address::MuxedAccount(muxed_account) => Err(Error::CannotSign(muxed_account.clone())), - Address::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), } } } diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs new file mode 100644 index 000000000..e6adface4 --- /dev/null +++ b/cmd/soroban-cli/src/config/key.rs @@ -0,0 +1,146 @@ +use std::{fmt::Display, str::FromStr}; + +use serde::{Deserialize, Serialize}; + +use super::secret::{self, Secret}; +use crate::xdr; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Failed to extract public key from secret")] + SecretPublicKey, + #[error(transparent)] + Secret(#[from] secret::Error), + #[error(transparent)] + StrKey(#[from] stellar_strkey::DecodeError), +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(untagged)] +pub enum Key { + Secret(Secret), + PublicKey { public_key: PublicKey }, + MuxedAccount { muxed_account: MuxedAccount }, +} + +impl Key { + pub fn public_key(&self, hd_path: Option) -> Result { + let bytes = match self { + Key::Secret(secret) => secret.public_key(hd_path)?.0, + Key::PublicKey { + public_key: PublicKey(key), + } => key.0, + Key::MuxedAccount { + muxed_account: MuxedAccount(stellar_strkey::ed25519::MuxedAccount { ed25519, id }), + } => { + return Ok(xdr::MuxedAccount::MuxedEd25519(xdr::MuxedAccountMed25519 { + ed25519: xdr::Uint256(*ed25519), + id: *id, + })) + } + }; + Ok(xdr::MuxedAccount::Ed25519(xdr::Uint256(bytes))) + } + + pub fn private_key( + &self, + hd_path: Option, + ) -> Result { + match self { + Key::Secret(secret) => Ok(secret.private_key(hd_path)?), + _ => Err(Error::SecretPublicKey), + } + } +} + +impl FromStr for Key { + type Err = Error; + + fn from_str(s: &str) -> Result { + if let Ok(secret) = s.parse() { + return Ok(Key::Secret(secret)); + } + if let Ok(public_key) = s.parse() { + return Ok(Key::PublicKey { public_key }); + } + if let Ok(muxed_account) = s.parse() { + return Ok(Key::MuxedAccount { muxed_account }); + } + todo!("Error handling for invalid key format"); + } +} + +impl From for Key { + fn from(value: stellar_strkey::ed25519::PublicKey) -> Self { + Key::PublicKey { + public_key: PublicKey(value), + } + } +} + +impl From<&stellar_strkey::ed25519::PublicKey> for Key { + fn from(stellar_strkey::ed25519::PublicKey(key): &stellar_strkey::ed25519::PublicKey) -> Self { + stellar_strkey::ed25519::PublicKey(*key).into() + } +} + +#[derive(Debug, PartialEq, Eq, serde_with::SerializeDisplay, serde_with::DeserializeFromStr)] +pub struct PublicKey(pub stellar_strkey::ed25519::PublicKey); + +impl FromStr for PublicKey { + type Err = stellar_strkey::DecodeError; + + fn from_str(s: &str) -> Result { + Ok(PublicKey(stellar_strkey::ed25519::PublicKey::from_str(s)?)) + } +} + +impl Display for PublicKey { + 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 { + stellar_strkey::ed25519::MuxedAccount { + id: 0, + ed25519: *key, + } + } +} + +#[derive(Debug, PartialEq, Eq, serde_with::SerializeDisplay, serde_with::DeserializeFromStr)] +pub struct MuxedAccount(pub stellar_strkey::ed25519::MuxedAccount); + +impl FromStr for MuxedAccount { + type Err = stellar_strkey::DecodeError; + + fn from_str(s: &str) -> Result { + Ok(MuxedAccount( + stellar_strkey::ed25519::MuxedAccount::from_str(s)?, + )) + } +} + +impl Display for MuxedAccount { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn public_key() { + let key = Key::PublicKey { + public_key: PublicKey(stellar_strkey::ed25519::PublicKey([0; 32])), + }; + let serialized = toml::to_string(&key).unwrap(); + println!("{serialized}"); + let deserialized: Key = toml::from_str(&serialized).unwrap(); + assert_eq!(key, deserialized); + } +} diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index b6f5c75c1..07c7ee490 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -16,6 +16,7 @@ use crate::{commands::HEADING_GLOBAL, utils::find_config_dir, Pwd}; use super::{ alias, + key::Key, network::{self, Network}, secret::Secret, Config, @@ -163,7 +164,19 @@ impl Args { } pub fn write_identity(&self, name: &str, secret: &Secret) -> Result<(), Error> { - KeyType::Identity.write(name, secret, &self.config_dir()?) + self.write_key(name, &Key::Secret(secret.clone())) + } + + pub fn write_public_key( + &self, + name: &str, + public_key: &stellar_strkey::ed25519::PublicKey, + ) -> Result<(), Error> { + self.write_key(name, &public_key.into()) + } + + pub fn write_key(&self, name: &str, public_key: &Key) -> Result<(), Error> { + KeyType::Identity.write(name, public_key, &self.config_dir()?) } pub fn write_network(&self, name: &str, network: &Network) -> Result<(), Error> { @@ -228,17 +241,20 @@ impl Args { Ok(saved_networks.chain(default_networks).collect()) } - pub fn read_identity(&self, name: &str) -> Result { - Ok(KeyType::Identity - .read_with_global(name, &self.local_config()?) - .or_else(|_| name.parse())?) + pub fn read_identity(&self, name: &str) -> Result { + Ok(KeyType::Identity.read_with_global(name, &self.local_config()?)?) } - pub fn key(&self, key_or_name: &str) -> Result { + pub fn get_private_key(&self, key_or_name: &str) -> Result { if let Ok(signer) = key_or_name.parse::() { Ok(signer) } else { - self.read_identity(key_or_name) + match self.read_identity(key_or_name)? { + Key::Secret(s) => Ok(s), + _ => Err(Error::SecretFileRead { + path: self.alias_path(key_or_name)?, + }), + } } } diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index a429ff434..fb4c787fd 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -17,6 +17,7 @@ use network::Network; pub mod address; pub mod alias; pub mod data; +pub mod key; pub mod locator; pub mod network; pub mod secret; diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index a7fd86fda..995b88723 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -9,6 +9,8 @@ use crate::{ utils, }; +use super::key::{self, Key}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("invalid secret key")] @@ -39,19 +41,26 @@ pub struct Args { /// Add using 12 word seed phrase to generate `secret_key` #[arg(long, conflicts_with = "secret_key")] pub seed_phrase: bool, + + /// Add a public key, ed25519, or muxed account, e.g. G1.., M2.. + #[arg(long, conflicts_with = "seed_phrase", conflicts_with = "secret_key")] + pub public_key: Option, } impl Args { - pub fn read_secret(&self) -> Result { + pub fn read_key(&self) -> Result { + if let Some(public_key) = self.public_key.as_ref() { + return Ok(public_key.parse()?); + }; if let Ok(secret_key) = std::env::var("SOROBAN_SECRET_KEY") { - Ok(Secret::SecretKey { secret_key }) + Ok(Key::Secret(Secret::SecretKey { secret_key })) } else if self.secret_key { println!("Type a secret key: "); let secret_key = read_password()?; let secret_key = PrivateKey::from_string(&secret_key) .map_err(|_| Error::InvalidSecretKey)? .to_string(); - Ok(Secret::SecretKey { secret_key }) + Ok(Key::Secret(Secret::SecretKey { secret_key })) } else if self.seed_phrase { println!("Type a 12 word seed phrase: "); let seed_phrase = read_password()?; @@ -60,20 +69,20 @@ impl Args { // let len = seed_phrase.len(); // return Err(Error::InvalidSeedPhrase { len }); // } - Ok(Secret::SeedPhrase { + Ok(Key::Secret(Secret::SeedPhrase { seed_phrase: seed_phrase .into_iter() .map(ToString::to_string) .collect::>() .join(" "), - }) + })) } else { - Err(Error::PasswordRead {}) + Err(Error::PasswordRead {}.into()) } } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[serde(untagged)] pub enum Secret { SecretKey { secret_key: String }, diff --git a/cmd/soroban-cli/src/config/sign_with.rs b/cmd/soroban-cli/src/config/sign_with.rs index 475013bc8..c9d164914 100644 --- a/cmd/soroban-cli/src/config/sign_with.rs +++ b/cmd/soroban-cli/src/config/sign_with.rs @@ -64,7 +64,7 @@ impl Args { } } else { let key_or_name = self.sign_with_key.as_deref().ok_or(Error::NoSignWithKey)?; - let secret = locator.key(key_or_name)?; + let secret = locator.get_private_key(key_or_name)?; secret.signer(self.hd_path, print)? }; Ok(signer.sign_tx_env(tx, network)?) From 2aec046e6f0b875f1c3c819b6eab6e74377f5c94 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 12 Nov 2024 15:40:29 -0500 Subject: [PATCH 02/60] 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 07c7ee490..68a95f628 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -12,11 +12,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, @@ -84,6 +84,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)] @@ -242,22 +246,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 { From 52bd5e83d42340064de0c94d6b394f09cca7c357 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 14 Nov 2024 12:31:22 -0500 Subject: [PATCH 03/60] fix: docs --- FULL_HELP_DOCS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 55e093acc..3580f42a6 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -958,6 +958,7 @@ Add a new identity (keypair, ledger, macOS keychain) * `--secret-key` — Add using `secret_key` Can provide with `SOROBAN_SECRET_KEY` * `--seed-phrase` — Add using 12 word seed phrase to generate `secret_key` +* `--public-key ` — Add a public key, ed25519, or muxed account, e.g. G1.., M2.. * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." From 8f96343e737670663d83172f3d30c72dd5ab56d3 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 14 Nov 2024 12:55:00 -0500 Subject: [PATCH 04/60] fix: clippy --- cmd/soroban-cli/src/config/secret.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 995b88723..82008795b 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -50,7 +50,7 @@ pub struct Args { impl Args { pub fn read_key(&self) -> Result { if let Some(public_key) = self.public_key.as_ref() { - return Ok(public_key.parse()?); + return public_key.parse(); }; if let Ok(secret_key) = std::env::var("SOROBAN_SECRET_KEY") { Ok(Key::Secret(Secret::SecretKey { secret_key })) From 0cc57fead531487490dd213044d437810703289b Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 26 Nov 2024 14:38:43 -0500 Subject: [PATCH 05/60] feat: update tx new commands to use Address type Add tests using --- FULL_HELP_DOCS.md | 4 +- .../tests/it/integration/tx/operations.rs | 92 +++++++++++++++++++ cmd/soroban-cli/src/commands/tx/args.rs | 20 +++- cmd/soroban-cli/src/commands/tx/mod.rs | 2 + .../src/commands/tx/new/account_merge.rs | 15 +-- .../src/commands/tx/new/create_account.rs | 17 ++-- cmd/soroban-cli/src/commands/tx/new/mod.rs | 34 +++++-- .../src/commands/tx/new/payment.rs | 13 +-- .../src/commands/tx/new/set_options.rs | 20 ++-- .../commands/tx/new/set_trustline_flags.rs | 25 ++--- 10 files changed, 192 insertions(+), 50 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 3580f42a6..f8f211f37 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1577,7 +1577,7 @@ Transfers the XLM balance of an account to another account and removes the sourc * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' +* `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' or alias @@ -1792,7 +1792,7 @@ Allows issuing account to configure authorization and trustline flags to an asse * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--trustor ` — Account to set trustline flags for +* `--trustor ` — Account to set trustline flags for, e.g. `GBX...`, or alias, or muxed account, `M123...`` * `--asset ` — Asset to set trustline flags for * `--set-authorize` — Signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders * `--set-authorize-to-maintain-liabilities` — Denotes limited authorization that allows an account to maintain current orders but not to otherwise transact with the asset diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index 9988b2cdd..9fc843df1 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -74,6 +74,71 @@ async fn create_account() { invoke_hello_world(sandbox, &id); } +#[tokio::test] +async fn create_account_with_alias() { + let sandbox = &TestEnv::new(); + sandbox + .new_assert_cmd("keys") + .args(["generate", "--no-fund", "new"]) + .assert() + .success(); + let test = test_address(sandbox); + let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let test_account = client.get_account(&test).await.unwrap(); + println!("test account has a balance of {}", test_account.balance); + let starting_balance = ONE_XLM * 100; + sandbox + .new_assert_cmd("tx") + .args([ + "new", + "create-account", + "--destination", + "new", + "--starting-balance", + starting_balance.to_string().as_str(), + ]) + .assert() + .success(); + let test_account_after = client.get_account(&test).await.unwrap(); + assert!(test_account_after.balance < test_account.balance); + let id = deploy_contract(sandbox, HELLO_WORLD, DeployKind::Normal, Some("new")).await; + println!("{id}"); + invoke_hello_world(sandbox, &id); +} + +#[tokio::test] +async fn payment_with_alias() { + let sandbox = &TestEnv::new(); + let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let (test, test1) = setup_accounts(sandbox); + let test_account = client.get_account(&test).await.unwrap(); + println!("test account has a balance of {}", test_account.balance); + + let before = client.get_account(&test).await.unwrap(); + let test1_account_entry_before = client.get_account(&test1).await.unwrap(); + + sandbox + .new_assert_cmd("tx") + .args([ + "new", + "payment", + "--destination", + "test1", + "--amount", + ONE_XLM.to_string().as_str(), + ]) + .assert() + .success(); + let test1_account_entry = client.get_account(&test1).await.unwrap(); + assert_eq!( + ONE_XLM, + test1_account_entry.balance - test1_account_entry_before.balance, + "Should have One XLM more" + ); + let after = client.get_account(&test).await.unwrap(); + assert_eq!(before.balance - 10_000_100, after.balance); +} + #[tokio::test] async fn payment() { let sandbox = &TestEnv::new(); @@ -157,6 +222,33 @@ async fn account_merge() { assert_eq!(before.balance + before1.balance - fee, after.balance); } +#[tokio::test] +async fn account_merge_with_alias() { + let sandbox = &TestEnv::new(); + let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let (test, test1) = setup_accounts(sandbox); + let before = client.get_account(&test).await.unwrap(); + let before1 = client.get_account(&test1).await.unwrap(); + let fee = 100; + sandbox + .new_assert_cmd("tx") + .args([ + "new", + "account-merge", + "--source", + "test1", + "--account", + "test", + "--fee", + fee.to_string().as_str(), + ]) + .assert() + .success(); + let after = client.get_account(&test).await.unwrap(); + assert!(client.get_account(&test1).await.is_err()); + assert_eq!(before.balance + before1.balance - fee, after.balance); +} + #[tokio::test] async fn set_trustline_flags() { let sandbox = &TestEnv::new(); diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index 1da1f230a..c703ead6b 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -1,6 +1,10 @@ use crate::{ commands::{global, txn_result::TxnEnvelopeResult}, - config::{self, data, network, secret}, + config::{ + self, + address::{self, Address}, + data, network, secret, + }, fee, rpc::{self, Client, GetTransactionResponse}, tx::builder::{self, TxExt}, @@ -32,6 +36,8 @@ pub enum Error { Data(#[from] data::Error), #[error(transparent)] Xdr(#[from] xdr::Error), + #[error(transparent)] + Address(#[from] address::Error), } impl Args { @@ -64,7 +70,7 @@ impl Args { op: impl Into, global_args: &global::Args, ) -> Result, Error> { - let tx = self.tx(op.into()).await?; + let tx = self.tx(op).await?; self.handle_tx(tx, global_args).await } pub async fn handle_and_print( @@ -104,4 +110,14 @@ impl Args { pub fn source_account(&self) -> Result { Ok(self.config.source_account()?) } + + pub fn reslove_muxed_address(&self, address: &Address) -> Result { + Ok(address.resolve_muxed_account(&self.config.locator, self.config.hd_path)?) + } + + pub fn reslove_account_id(&self, address: &Address) -> Result { + Ok(address + .resolve_muxed_account(&self.config.locator, self.config.hd_path)? + .account_id()) + } } diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index c0390f92e..51a10cb0d 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -37,6 +37,8 @@ pub enum Error { Sign(#[from] sign::Error), #[error(transparent)] Send(#[from] send::Error), + #[error(transparent)] + Args(#[from] args::Error), } impl Cmd { diff --git a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs index ce01f5e1f..5ff834aaa 100644 --- a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs +++ b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs @@ -1,19 +1,22 @@ use clap::{command, Parser}; -use crate::{commands::tx, xdr}; +use crate::{commands::tx, config::address, xdr}; #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub tx: tx::Args, - /// Muxed Account to merge with, e.g. `GBX...`, 'MBX...' + /// Muxed Account to merge with, e.g. `GBX...`, 'MBX...' or alias #[arg(long)] - pub account: xdr::MuxedAccount, + pub account: address::Address, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { - xdr::OperationBody::AccountMerge(cmd.account.clone()) +impl TryFrom<&Cmd> for xdr::OperationBody { + type Error = tx::args::Error; + fn try_from(cmd: &Cmd) -> Result { + Ok(xdr::OperationBody::AccountMerge( + cmd.tx.reslove_muxed_address(&cmd.account)?, + )) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index 2826439e9..280fc75bd 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -1,6 +1,6 @@ use clap::{command, Parser}; -use crate::{commands::tx, tx::builder, xdr}; +use crate::{commands::tx, config::address, xdr}; #[derive(Parser, Debug, Clone)] #[group(skip)] @@ -9,17 +9,18 @@ pub struct Cmd { pub tx: tx::Args, /// Account Id to create, e.g. `GBX...` #[arg(long)] - pub destination: xdr::AccountId, + pub destination: address::Address, /// Initial balance in stroops of the account, default 1 XLM #[arg(long, default_value = "10_000_000")] pub starting_balance: builder::Amount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { - xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { - destination: cmd.destination.clone(), - starting_balance: cmd.starting_balance.into(), - }) +impl TryFrom<&Cmd> for xdr::OperationBody { + type Error = tx::args::Error; + fn try_from(cmd: &Cmd) -> Result { + Ok(xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { + destination: cmd.tx.reslove_account_id(&cmd.destination)?, + starting_balance: cmd.starting_balance, + })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/mod.rs b/cmd/soroban-cli/src/commands/tx/new/mod.rs index e5923f4ec..1d5682cc0 100644 --- a/cmd/soroban-cli/src/commands/tx/new/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/new/mod.rs @@ -1,4 +1,5 @@ use clap::Parser; +use soroban_sdk::xdr::OperationBody; use super::global; @@ -52,17 +53,34 @@ pub enum Error { Tx(#[from] super::args::Error), } +impl TryFrom<&Cmd> for OperationBody { + type Error = super::args::Error; + fn try_from(cmd: &Cmd) -> Result { + Ok(match cmd { + Cmd::AccountMerge(cmd) => cmd.try_into()?, + Cmd::BumpSequence(cmd) => cmd.into(), + Cmd::ChangeTrust(cmd) => cmd.into(), + Cmd::CreateAccount(cmd) => cmd.try_into()?, + Cmd::ManageData(cmd) => cmd.into(), + Cmd::Payment(cmd) => cmd.try_into()?, + Cmd::SetOptions(cmd) => cmd.try_into()?, + Cmd::SetTrustlineFlags(cmd) => cmd.try_into()?, + }) + } +} + impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let op = OperationBody::try_from(self)?; match self { - Cmd::AccountMerge(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::BumpSequence(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::ChangeTrust(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::CreateAccount(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::ManageData(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::Payment(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, + Cmd::AccountMerge(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::BumpSequence(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::ChangeTrust(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::CreateAccount(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::ManageData(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::Payment(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(op, global_args).await, + Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(op, global_args).await, }?; Ok(()) } diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 3cebfa532..1ab999ab9 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -1,6 +1,6 @@ use clap::{command, Parser}; -use crate::{commands::tx, tx::builder, xdr}; +use crate::{commands::tx, config::address, tx::builder, xdr}; #[derive(Parser, Debug, Clone)] #[group(skip)] @@ -9,7 +9,7 @@ pub struct Cmd { pub tx: tx::Args, /// Account to send to, e.g. `GBX...` #[arg(long)] - pub destination: xdr::MuxedAccount, + pub destination: address::Address, /// Asset to send, default native, e.i. XLM #[arg(long, default_value = "native")] pub asset: builder::Asset, @@ -18,10 +18,11 @@ pub struct Cmd { pub amount: builder::Amount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { - xdr::OperationBody::Payment(xdr::PaymentOp { - destination: cmd.destination.clone(), +impl TryFrom<&Cmd> for xdr::OperationBody { + type Error = tx::args::Error; + fn try_from(cmd: &Cmd) -> Result { + Ok(xdr::OperationBody::Payment(xdr::PaymentOp { + destination: cmd.tx.reslove_muxed_address(&cmd.destination)?, asset: cmd.asset.clone().into(), amount: cmd.amount.into(), }) diff --git a/cmd/soroban-cli/src/commands/tx/new/set_options.rs b/cmd/soroban-cli/src/commands/tx/new/set_options.rs index 69cd10745..e5fce4557 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_options.rs @@ -1,6 +1,6 @@ use clap::{command, Parser}; -use crate::{commands::tx, xdr}; +use crate::{commands::tx, config::address, xdr}; #[derive(Parser, Debug, Clone)] #[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] @@ -10,7 +10,7 @@ pub struct Cmd { pub tx: tx::Args, #[arg(long)] /// Account of the inflation destination. - pub inflation_dest: Option, + pub inflation_dest: Option, #[arg(long)] /// A number from 0-255 (inclusive) representing the weight of the master key. If the weight of the master key is updated to 0, it is effectively disabled. pub master_weight: Option, @@ -61,8 +61,9 @@ pub struct Cmd { pub clear_clawback_enabled: bool, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl TryFrom<&Cmd> for xdr::OperationBody { + type Error = tx::args::Error; + fn try_from(cmd: &Cmd) -> Result { let mut set_flags = None; let mut set_flag = |flag: xdr::AccountFlags| { *set_flags.get_or_insert(0) |= flag as u32; @@ -108,8 +109,13 @@ impl From<&Cmd> for xdr::OperationBody { } else { None }; - xdr::OperationBody::SetOptions(xdr::SetOptionsOp { - inflation_dest: cmd.inflation_dest.clone().map(Into::into), + let inflation_dest: Option = cmd + .inflation_dest + .as_ref() + .map(|dest| cmd.tx.reslove_account_id(dest)) + .transpose()?; + Ok(xdr::OperationBody::SetOptions(xdr::SetOptionsOp { + inflation_dest, clear_flags, set_flags, master_weight: cmd.master_weight.map(Into::into), @@ -118,6 +124,6 @@ impl From<&Cmd> for xdr::OperationBody { high_threshold: cmd.high_threshold.map(Into::into), home_domain: cmd.home_domain.clone().map(Into::into), signer, - }) + })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs index d9b70ecbd..318f3ff1d 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs @@ -1,6 +1,6 @@ use clap::{command, Parser}; -use crate::{commands::tx, tx::builder, xdr}; +use crate::{commands::tx, config::address, tx::builder, xdr}; #[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] #[derive(Parser, Debug, Clone)] @@ -8,9 +8,9 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, - /// Account to set trustline flags for + /// Account to set trustline flags for, e.g. `GBX...`, or alias, or muxed account, `M123...`` #[arg(long)] - pub trustor: xdr::AccountId, + pub trustor: address::Address, /// Asset to set trustline flags for #[arg(long)] pub asset: builder::Asset, @@ -32,8 +32,9 @@ pub struct Cmd { pub clear_trustline_clawback_enabled: bool, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl TryFrom<&Cmd> for xdr::OperationBody { + type Error = tx::args::Error; + fn try_from(cmd: &Cmd) -> Result { let mut set_flags = 0; let mut set_flag = |flag: xdr::TrustLineFlags| set_flags |= flag as u32; @@ -59,11 +60,13 @@ impl From<&Cmd> for xdr::OperationBody { clear_flag(xdr::TrustLineFlags::TrustlineClawbackEnabledFlag); }; - xdr::OperationBody::SetTrustLineFlags(xdr::SetTrustLineFlagsOp { - trustor: cmd.trustor.clone(), - asset: cmd.asset.clone().into(), - clear_flags, - set_flags, - }) + Ok(xdr::OperationBody::SetTrustLineFlags( + xdr::SetTrustLineFlagsOp { + trustor: cmd.tx.reslove_account_id(&cmd.trustor)?, + asset: cmd.asset.clone().into(), + clear_flags, + set_flags, + }, + )) } } From 31cde547fe055d10eec0c445dbe7af8487848268 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 29 Nov 2024 11:50:54 -0500 Subject: [PATCH 06/60] fix: rebase issue --- cmd/soroban-cli/src/commands/tx/new/create_account.rs | 4 ++-- cmd/soroban-cli/src/commands/tx/new/payment.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index 280fc75bd..4ae1c13d2 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -1,6 +1,6 @@ use clap::{command, Parser}; -use crate::{commands::tx, config::address, xdr}; +use crate::{commands::tx, config::address, tx::builder, xdr}; #[derive(Parser, Debug, Clone)] #[group(skip)] @@ -20,7 +20,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { destination: cmd.tx.reslove_account_id(&cmd.destination)?, - starting_balance: cmd.starting_balance, + starting_balance: cmd.starting_balance.into(), })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 1ab999ab9..397bf68a7 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -25,6 +25,6 @@ impl TryFrom<&Cmd> for xdr::OperationBody { destination: cmd.tx.reslove_muxed_address(&cmd.destination)?, asset: cmd.asset.clone().into(), amount: cmd.amount.into(), - }) + })) } } From a86a98fcc04d91520fcb2ea718ee3c4c25a90aae Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Mon, 2 Dec 2024 08:45:30 -0500 Subject: [PATCH 07/60] Update cmd/soroban-cli/src/config/key.rs Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- cmd/soroban-cli/src/config/key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs index 18f52b876..6c5b99a5d 100644 --- a/cmd/soroban-cli/src/config/key.rs +++ b/cmd/soroban-cli/src/config/key.rs @@ -7,7 +7,7 @@ use crate::xdr; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("Failed to extract public key from secret")] + #[error("failed to extract public key from secret")] SecretPublicKey, #[error(transparent)] Secret(#[from] secret::Error), From b36db49696d71dde61607be68c732b09d376fc8e Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Mon, 2 Dec 2024 09:57:56 -0500 Subject: [PATCH 08/60] fix: PR review --- cmd/soroban-cli/src/config/key.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs index 6c5b99a5d..dcb96775b 100644 --- a/cmd/soroban-cli/src/config/key.rs +++ b/cmd/soroban-cli/src/config/key.rs @@ -7,14 +7,14 @@ use crate::xdr; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("failed to extract public key from secret")] + #[error("failed to extract secret from public key ")] SecretPublicKey, #[error(transparent)] Secret(#[from] secret::Error), #[error(transparent)] StrKey(#[from] stellar_strkey::DecodeError), - #[error("failed to parse key {0}")] - Parse(String), + #[error("failed to parse key")] + Parse, } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] @@ -68,7 +68,7 @@ impl FromStr for Key { if let Ok(muxed_account) = s.parse() { return Ok(Key::MuxedAccount { muxed_account }); } - Err(Error::Parse(s.to_owned())) + Err(Error::Parse) } } From 8c06970bc61df353e1da60e9d81ef8da00dfe776 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 5 Nov 2024 10:39:20 -0500 Subject: [PATCH 09/60] feat: initial work into system keychain --- Cargo.lock | 111 ++++++++++++++++++++++++++ cmd/soroban-cli/Cargo.toml | 11 ++- cmd/soroban-cli/src/bin/secret.rs | 16 ++++ cmd/soroban-cli/src/signer.rs | 2 + cmd/soroban-cli/src/signer/keyring.rs | 100 +++++++++++++++++++++++ 5 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 cmd/soroban-cli/src/bin/secret.rs create mode 100644 cmd/soroban-cli/src/signer/keyring.rs diff --git a/Cargo.lock b/Cargo.lock index 3f8fcf4ac..dbf818db8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1179,6 +1179,30 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + +[[package]] +name = "dbus-secret-service" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +dependencies = [ + "dbus", + "futures-util", + "num", + "once_cell", + "rand", +] + [[package]] name = "der" version = "0.7.9" @@ -2581,6 +2605,18 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keyring" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fa83d1ca02db069b5fbe94b23b584d588e989218310c9c15015bb5571ef1a94" +dependencies = [ + "byteorder 1.5.0", + "dbus-secret-service", + "security-framework", + "windows-sys 0.59.0", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2682,6 +2718,15 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "pkg-config", +] + [[package]] name = "libm" version = "0.2.8" @@ -2870,6 +2915,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -2881,6 +2940,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2908,6 +2976,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -4320,6 +4411,7 @@ dependencies = [ "itertools 0.10.5", "jsonrpsee-core", "jsonrpsee-http-client", + "keyring", "mockito", "num-bigint", "open", @@ -4370,6 +4462,8 @@ dependencies = [ "wasm-opt", "wasmparser", "which", + "whoami", + "zeroize", ] [[package]] @@ -5587,6 +5681,12 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -5795,6 +5895,17 @@ dependencies = [ "rustix 0.38.34", ] +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] + [[package]] name = "widestring" version = "1.1.0" diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 2f2a26255..0d6da167d 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -20,6 +20,10 @@ path = "src/bin/stellar.rs" name = "soroban" path = "src/bin/soroban.rs" +[[bin]] +name = "secret" +path = "src/bin/secret.rs" + [package.metadata.binstall] pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ version }-{ target }{ archive-suffix }" bin-dir = "{ bin }{ binary-ext }" @@ -72,7 +76,8 @@ rand = "0.8.5" wasmparser = { workspace = true } sha2 = { workspace = true } csv = "1.1.6" -ed25519-dalek = { workspace = true } +# zeroize feature ensures that all sensitive data is zeroed out when dropped +ed25519-dalek = { workspace = true, features = ["zeroize"] } reqwest = { version = "0.12.7", default-features = false, features = [ "rustls-tls", "http2", @@ -124,6 +129,10 @@ fqdn = "0.3.12" open = "5.3.0" url = "2.5.2" wasm-gen = "0.1.4" +zeroize = "1.8.1" +keyring = { version = "3", features = ["apple-native", "windows-native", "sync-secret-service"] } +whoami = "1.5.2" + [build-dependencies] crate-git-revision = "0.0.6" diff --git a/cmd/soroban-cli/src/bin/secret.rs b/cmd/soroban-cli/src/bin/secret.rs new file mode 100644 index 000000000..26d1a51c7 --- /dev/null +++ b/cmd/soroban-cli/src/bin/secret.rs @@ -0,0 +1,16 @@ +use soroban_cli::signer::keyring::{add_key, get_public_key, StellarEntry}; + +fn main() { + let entry = StellarEntry::new("test").unwrap(); + if let Ok(key) = entry.get_public_key() { + println!("{key}") + }; + + let secret = soroban_cli::config::secret::Secret::from_seed(None).unwrap(); + let pub_key = secret.public_key(None).unwrap(); + let key_pair = secret.key_pair(None).unwrap(); + entry.add_password(key_pair.as_bytes()).unwrap(); + let pub_key_2 = entry.get_public_key().unwrap(); + assert_eq!(pub_key, pub_key_2); + println!("{pub_key} == {pub_key_2}"); +} diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index 5bf22499c..a141aaf6b 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -11,6 +11,8 @@ use crate::xdr::{ use crate::{config::network::Network, print::Print, utils::transaction_hash}; +pub mod keyring; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Contract addresses are not supported to sign auth entries {address}")] diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs new file mode 100644 index 000000000..eca6d8657 --- /dev/null +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -0,0 +1,100 @@ +use base64::{engine::general_purpose::STANDARD as base64, Engine as _}; +use ed25519_dalek::Signer; +use keyring::Entry; +use zeroize::Zeroize; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Keyring(#[from] keyring::Error), + #[error(transparent)] + Base64(#[from] base64::DecodeError), +} + +pub struct StellarEntry { + name: String, +} + +impl TryFrom<&StellarEntry> for Entry { + type Error = Error; + fn try_from(StellarEntry { name }: &StellarEntry) -> Result { + Ok(Entry::new( + &format!("org.stellar.cli.{name}"), + &whoami::username(), + )?) + } +} + +impl StellarEntry { + pub fn new(name: &str) -> Result { + Ok(StellarEntry { + name: name.to_string(), + }) + } + + pub fn set_password(&self, password: &[u8]) -> Result<(), Error> { + let data = base64.encode(password); + let entry: Entry = self.try_into()?; + entry.set_password(&data)?; + Ok(()) + } + + pub fn get_password(&self) -> Result, Error> { + let entry: Entry = self.try_into()?; + Ok(base64.decode(entry.get_password()?)?) + } + + pub fn get_public_key(&self) -> Result { + let mut key_vec = self.get_password()?; + let mut key_bytes: [u8; 32] = key_vec.as_slice().try_into().unwrap(); + + let pub_key = { + // Use this scope to ensure the keypair is zeroized + let keypair = ed25519_dalek::SigningKey::from_bytes(&key_bytes); + stellar_strkey::ed25519::PublicKey(*keypair.verifying_key().as_bytes()) + }; + key_vec.zeroize(); + key_bytes.zeroize(); + Ok(pub_key) + } +} + +pub fn sign_data(name: &str, data: &[u8]) -> Result, Box> { + // Retrieve the key from the secure storage + let entry = Entry::new("stellar", name)?; + let key_bytes: [u8; 32] = entry.get_secret()?.try_into().unwrap(); + // Create a keypair from the retrieved bytes + let keypair = ed25519_dalek::SigningKey::from_bytes(&key_bytes); + + // Sign the data + let signature = keypair.sign(data); + + // Clear the key from memory + let mut key_bytes = key_bytes; + key_bytes.zeroize(); + + Ok(signature.to_bytes().to_vec()) +} + +pub fn add_key(name: &str, key_bytes: &[u8]) -> Result<(), Box> { + // Create a new keyring entry for "stellar" + StellarEntry::new(name)?.set_password(key_bytes)?; + Ok(()) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_sign_data() -> Result<(), Box> { + let secret = crate::config::secret::Secret::from_seed(None)?; + let pub_key = secret.public_key(None)?; + let key_pair = secret.key_pair(None)?; + + add_key("test", &key_pair.to_bytes()).unwrap(); + let pub_key_2 = get_public_key("test")?; + assert_eq!(pub_key, pub_key_2); + Ok(()) + } +} From 883cb8cf3bb7e53817a35dc70749524ac1588137 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 5 Nov 2024 15:56:04 -0500 Subject: [PATCH 10/60] chore: clean up --- cmd/soroban-cli/src/bin/secret.rs | 7 ++-- cmd/soroban-cli/src/signer/keyring.rs | 51 ++++++++++++--------------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/cmd/soroban-cli/src/bin/secret.rs b/cmd/soroban-cli/src/bin/secret.rs index 26d1a51c7..4fc43ec6e 100644 --- a/cmd/soroban-cli/src/bin/secret.rs +++ b/cmd/soroban-cli/src/bin/secret.rs @@ -1,15 +1,16 @@ -use soroban_cli::signer::keyring::{add_key, get_public_key, StellarEntry}; +use soroban_cli::signer::keyring::StellarEntry; fn main() { let entry = StellarEntry::new("test").unwrap(); if let Ok(key) = entry.get_public_key() { - println!("{key}") + println!("{key}"); + return; }; let secret = soroban_cli::config::secret::Secret::from_seed(None).unwrap(); let pub_key = secret.public_key(None).unwrap(); let key_pair = secret.key_pair(None).unwrap(); - entry.add_password(key_pair.as_bytes()).unwrap(); + entry.set_password(key_pair.as_bytes()).unwrap(); let pub_key_2 = entry.get_public_key().unwrap(); assert_eq!(pub_key, pub_key_2); println!("{pub_key} == {pub_key_2}"); diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index eca6d8657..bde7e97d6 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -44,42 +44,37 @@ impl StellarEntry { Ok(base64.decode(entry.get_password()?)?) } - pub fn get_public_key(&self) -> Result { + fn use_key( + &self, + f: impl FnOnce(ed25519_dalek::SigningKey) -> Result, + ) -> Result { let mut key_vec = self.get_password()?; let mut key_bytes: [u8; 32] = key_vec.as_slice().try_into().unwrap(); - let pub_key = { + let result = { // Use this scope to ensure the keypair is zeroized let keypair = ed25519_dalek::SigningKey::from_bytes(&key_bytes); - stellar_strkey::ed25519::PublicKey(*keypair.verifying_key().as_bytes()) + f(keypair)? }; key_vec.zeroize(); key_bytes.zeroize(); - Ok(pub_key) + Ok(result) } -} - -pub fn sign_data(name: &str, data: &[u8]) -> Result, Box> { - // Retrieve the key from the secure storage - let entry = Entry::new("stellar", name)?; - let key_bytes: [u8; 32] = entry.get_secret()?.try_into().unwrap(); - // Create a keypair from the retrieved bytes - let keypair = ed25519_dalek::SigningKey::from_bytes(&key_bytes); - // Sign the data - let signature = keypair.sign(data); - - // Clear the key from memory - let mut key_bytes = key_bytes; - key_bytes.zeroize(); - - Ok(signature.to_bytes().to_vec()) -} + pub fn get_public_key(&self) -> Result { + self.use_key(|keypair| { + Ok(stellar_strkey::ed25519::PublicKey( + *keypair.verifying_key().as_bytes(), + )) + }) + } -pub fn add_key(name: &str, key_bytes: &[u8]) -> Result<(), Box> { - // Create a new keyring entry for "stellar" - StellarEntry::new(name)?.set_password(key_bytes)?; - Ok(()) + pub fn sign_data(&self, data: &[u8]) -> Result, Error> { + self.use_key(|keypair| { + let signature = keypair.sign(data); + Ok(signature.to_bytes().to_vec()) + }) + } } #[cfg(test)] @@ -91,9 +86,9 @@ mod test { let secret = crate::config::secret::Secret::from_seed(None)?; let pub_key = secret.public_key(None)?; let key_pair = secret.key_pair(None)?; - - add_key("test", &key_pair.to_bytes()).unwrap(); - let pub_key_2 = get_public_key("test")?; + let entry = StellarEntry::new("test")?; + entry.set_password(&key_pair.to_bytes()); + let pub_key_2 = entry.get_public_key()?; assert_eq!(pub_key, pub_key_2); Ok(()) } From eb7073402548e24101ea2f2fe4d37664b1264d79 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:23:11 -0500 Subject: [PATCH 11/60] Add KeyName struct in address --- cmd/soroban-cli/src/commands/keys/add.rs | 10 +++++-- cmd/soroban-cli/src/commands/keys/generate.rs | 4 +-- cmd/soroban-cli/src/config/address.rs | 29 +++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs index d8f528bae..fd796bb86 100644 --- a/cmd/soroban-cli/src/commands/keys/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -1,21 +1,25 @@ use clap::command; -use crate::config::{locator, secret}; +use crate::config::{ + address::{self, KeyName}, + locator, secret, +}; #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] Secret(#[from] secret::Error), - #[error(transparent)] Config(#[from] locator::Error), + #[error(transparent)] + Address(#[from] address::Error), } #[derive(Debug, clap::Parser, Clone)] #[group(skip)] pub struct Cmd { /// Name of identity - pub name: String, + pub name: KeyName, #[command(flatten)] pub secrets: secret::Args, diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index c6623386c..315fbb7ec 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -69,10 +69,10 @@ impl Cmd { if self.config_locator.read_identity(&self.name).is_ok() { if !self.overwrite { - return Err(Error::IdentityAlreadyExists(self.name.clone())); + return Err(Error::IdentityAlreadyExists(self.name.to_string())); } - print.exclaimln(format!("Overwriting identity '{}'", &self.name)); + print.exclaimln(format!("Overwriting identity '{}'", &self.name.to_string())); } if !self.fund { diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 066bc8d91..57c229c76 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -25,6 +25,8 @@ pub enum Error { Secret(#[from] secret::Error), #[error("Address cannot be used to sign {0}")] CannotSign(xdr::MuxedAccount), + #[error("Invalid key name: {0}\n only alphanumeric characters, `_`and `-` are allowed")] + InvalidKeyName(String), } impl FromStr for Address { @@ -61,3 +63,30 @@ impl Address { } } } + +#[derive(Clone, Debug)] +pub struct KeyName(pub String); + +impl std::ops::Deref for KeyName { + type Target = str; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::str::FromStr for KeyName { + type Err = Error; + fn from_str(s: &str) -> Result { + if !s.chars().all(allowed_char) { + return Err(Error::InvalidKeyName(s.to_string())); + } + if s == "ledger" { + return Err(Error::InvalidKeyName(s.to_string())); + } + Ok(KeyName(s.to_string())) + } +} + +fn allowed_char(c: char) -> bool { + c.is_ascii_alphanumeric() || c == '_' || c == '-' +} From d4e25003db21f05fef829d600e98ff25515342bc Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:25:03 -0500 Subject: [PATCH 12/60] Add Secret::Keychain --- cmd/soroban-cli/src/config/secret.rs | 97 +++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index a7fd86fda..d07e644ac 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -34,11 +34,15 @@ pub enum Error { pub struct Args { /// Add using `secret_key` /// Can provide with `SOROBAN_SECRET_KEY` - #[arg(long, conflicts_with = "seed_phrase")] + #[arg(long, conflicts_with_all = ["seed_phrase", "keychain"])] pub secret_key: bool, /// Add using 12 word seed phrase to generate `secret_key` - #[arg(long, conflicts_with = "secret_key")] + #[arg(long, conflicts_with_all = ["secret_key", "keychain"])] pub seed_phrase: bool, + + /// Add using `keychain` + #[arg(long, conflicts_with_all = ["seed_phrase", "secret_key"])] + pub keychain: bool, } impl Args { @@ -67,6 +71,15 @@ impl Args { .collect::>() .join(" "), }) + } else if self.keychain { + // generate a secret, and save it in the keychain + // return a new type of secret? + // for now, put it all in here + println!("generate a secret in the keychain"); + // let keychain = keyring::Keyring::new(" + Ok(Secret::SecretKey { + secret_key: "test".to_owned(), + }) } else { Err(Error::PasswordRead {}) } @@ -78,6 +91,7 @@ impl Args { pub enum Secret { SecretKey { secret_key: String }, SeedPhrase { seed_phrase: String }, + Keychain, } impl FromStr for Secret { @@ -92,6 +106,8 @@ impl FromStr for Secret { Ok(Secret::SeedPhrase { seed_phrase: s.to_string(), }) + } else if s == "keychain" { + Ok(Secret::Keychain) } else { Err(Error::InvalidAddress(s.to_string())) } @@ -116,6 +132,7 @@ impl Secret { .private() .0, )?, + Secret::Keychain => panic!("Keychain does not reveal secret key"), }) } @@ -132,6 +149,7 @@ impl Secret { let key = self.key_pair(index)?; SignerKind::Local(LocalKey { key }) } + Secret::Keychain => todo!(), }; Ok(Signer { kind, print }) } @@ -160,3 +178,78 @@ fn read_password() -> Result { std::io::stdout().flush().map_err(|_| Error::PasswordRead)?; rpassword::read_password().map_err(|_| Error::PasswordRead) } + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_SECRET_KEY: &str = "SBF5HLRREHMS36XZNTUSKZ6FTXDZGNXOHF4EXKUL5UCWZLPBX3NGJ4BH"; + const TEST_SEED_PHRASE: &str = + "depth decade power loud smile spatial sign movie judge february rate broccoli"; + + #[test] + fn test_secret_from_key() { + let secret = Secret::from_str(TEST_SECRET_KEY).unwrap(); + // assert that it is a Secret::SecretKey + match secret { + Secret::SecretKey { secret_key: _ } => assert!(true), + _ => assert!(false), + } + // assert that we can get the private key from it + let private_key = secret.private_key(None).unwrap(); + assert_eq!(private_key.to_string(), TEST_SECRET_KEY); + + let signer = secret.signer(None, Print::new(false)).unwrap(); + println!("signer: {:?}", signer.kind); + } + + #[test] + fn test_secret_from_seed_phrase() { + let secret = Secret::from_str(TEST_SEED_PHRASE).unwrap(); + match secret { + Secret::SeedPhrase { seed_phrase: _ } => assert!(true), + _ => assert!(false), + } + + let private_key = secret.private_key(None).unwrap(); + assert_eq!(private_key.to_string(), TEST_SECRET_KEY); + } + + #[test] + fn test_ledger_secret() { + let secret = Secret::from_str("ledger").unwrap(); + match secret { + Secret::Ledger => assert!(true), + _ => assert!(false), + } + } + + #[test] + #[should_panic] + fn test_ledger_secret_will_not_reveal_private_key() { + let secret = Secret::from_str("ledger").unwrap(); + secret.private_key(None).unwrap(); + } + + #[test] + fn test_keychain_secret() { + let keychain_secret = Secret::from_str("keychain").unwrap(); + match keychain_secret { + Secret::Keychain => assert!(true), + _ => assert!(false), + } + } + + #[test] + #[should_panic] + fn test_keychain_secret_will_not_reveal_private_key() { + let secret = Secret::from_str("keychain").unwrap(); + secret.private_key(None).unwrap(); + } + + #[test] + fn test_secret_from_invalid_string() { + let secret = Secret::from_str("invalid"); + assert!(secret.is_err()); + } +} From 3ee20b8d634e6749cc27cc30ca59ca950cddae80 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:17:36 -0500 Subject: [PATCH 13/60] keys generate: allow for generating keys that are stored in keychain --- cmd/soroban-cli/src/commands/keys/generate.rs | 108 +++++++++++++++--- cmd/soroban-cli/src/config/secret.rs | 55 +++------ 2 files changed, 111 insertions(+), 52 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 315fbb7ec..e04c22a1e 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -39,6 +39,10 @@ pub struct Cmd { #[arg(long, short = 's')] pub as_secret: bool, + /// Save in `keychain` + #[arg(long)] + pub keychain: bool, + #[command(flatten)] pub config_locator: locator::Args, @@ -63,6 +67,8 @@ pub struct Cmd { pub overwrite: bool, } +const KEYCHAIN_CONSTANT: &str = "keychain"; + impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { let print = Print::new(global_args.quiet); @@ -83,19 +89,7 @@ impl Cmd { warning. It can be suppressed with -q flag.", ); } - - let seed_phrase = if self.default_seed { - Secret::test_seed_phrase() - } else { - Secret::from_seed(self.seed.as_deref()) - }?; - - let secret = if self.as_secret { - seed_phrase.private_key(self.hd_path)?.into() - } else { - seed_phrase - }; - + let secret = self.secret()?; self.config_locator.write_identity(&self.name, &secret)?; if !self.no_fund { @@ -112,4 +106,92 @@ impl Cmd { Ok(()) } + + fn secret(&self) -> Result { + let seed_phrase = self.seed_phrase()?; + Ok(if self.as_secret { + seed_phrase.private_key(self.hd_path)?.into() + } else if self.keychain { + KEYCHAIN_CONSTANT.parse()? + } else { + seed_phrase + }) + } + + fn seed_phrase(&self) -> Result { + Ok(if self.default_seed { + Secret::test_seed_phrase() + } else { + Secret::from_seed(self.seed.as_deref()) + }?) + } +} + +#[cfg(test)] +mod tests { + use crate::config::secret::Secret; + + fn set_up_test() -> (super::locator::Args, super::Cmd) { + let temp_dir = tempfile::tempdir().unwrap(); + let locator = super::locator::Args { + global: false, + config_dir: Some(temp_dir.path().to_path_buf()), + }; + + let cmd = super::Cmd { + name: "test_name".to_string(), + no_fund: true, + seed: None, + as_secret: false, + keychain: false, + config_locator: locator.clone(), + hd_path: None, + default_seed: false, + network: Default::default(), + fund: false, + }; + + (locator, cmd) + } + + fn global_args() -> super::global::Args { + let mut global_args = super::global::Args::default(); + global_args.quiet = true; + global_args + } + + #[tokio::test] + async fn test_storing_secret_as_a_seed_phrase() { + let (test_locator, cmd) = set_up_test(); + let global_args = global_args(); + + let result = cmd.run(&global_args).await; + assert!(result.is_ok()); + let identity = test_locator.read_identity("test_name").unwrap(); + assert!(matches!(identity, Secret::SeedPhrase { .. })); + } + + #[tokio::test] + async fn test_storing_secret_as_a_secret_key() { + let (test_locator, mut cmd) = set_up_test(); + cmd.as_secret = true; + let global_args = global_args(); + + let result = cmd.run(&global_args).await; + assert!(result.is_ok()); + let identity = test_locator.read_identity("test_name").unwrap(); + assert!(matches!(identity, Secret::SecretKey { .. })); + } + + #[tokio::test] + async fn test_storing_secret_in_keychain() { + let (test_locator, mut cmd) = set_up_test(); + cmd.keychain = true; + let global_args = global_args(); + + let result = cmd.run(&global_args).await; + assert!(result.is_ok()); + let identity = test_locator.read_identity("test_name").unwrap(); + assert!(matches!(identity, Secret::Keychain { .. })); + } } diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index d07e644ac..c88eaa88c 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -9,6 +9,8 @@ use crate::{ utils, }; +const KEYCHAIN_ENTRY_NAME: &str = "org.stellar.cli"; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("invalid secret key")] @@ -72,13 +74,8 @@ impl Args { .join(" "), }) } else if self.keychain { - // generate a secret, and save it in the keychain - // return a new type of secret? - // for now, put it all in here - println!("generate a secret in the keychain"); - // let keychain = keyring::Keyring::new(" - Ok(Secret::SecretKey { - secret_key: "test".to_owned(), + Ok(Secret::Keychain { + entry_name: KEYCHAIN_ENTRY_NAME.to_owned(), }) } else { Err(Error::PasswordRead {}) @@ -91,7 +88,7 @@ impl Args { pub enum Secret { SecretKey { secret_key: String }, SeedPhrase { seed_phrase: String }, - Keychain, + Keychain { entry_name: String }, } impl FromStr for Secret { @@ -107,7 +104,9 @@ impl FromStr for Secret { seed_phrase: s.to_string(), }) } else if s == "keychain" { - Ok(Secret::Keychain) + Ok(Secret::Keychain { + entry_name: KEYCHAIN_ENTRY_NAME.to_owned(), //TODO: namespace the entry_name to the system user or key name? + }) } else { Err(Error::InvalidAddress(s.to_string())) } @@ -132,7 +131,7 @@ impl Secret { .private() .0, )?, - Secret::Keychain => panic!("Keychain does not reveal secret key"), + Secret::Keychain { entry_name: _ } => panic!("Keychain does not reveal secret key"), }) } @@ -149,7 +148,7 @@ impl Secret { let key = self.key_pair(index)?; SignerKind::Local(LocalKey { key }) } - Secret::Keychain => todo!(), + Secret::Keychain { .. } => todo!(), }; Ok(Signer { kind, print }) } @@ -191,51 +190,29 @@ mod tests { fn test_secret_from_key() { let secret = Secret::from_str(TEST_SECRET_KEY).unwrap(); // assert that it is a Secret::SecretKey - match secret { - Secret::SecretKey { secret_key: _ } => assert!(true), - _ => assert!(false), - } + assert!(matches!(secret, Secret::SecretKey { .. })); // assert that we can get the private key from it let private_key = secret.private_key(None).unwrap(); assert_eq!(private_key.to_string(), TEST_SECRET_KEY); - - let signer = secret.signer(None, Print::new(false)).unwrap(); - println!("signer: {:?}", signer.kind); } #[test] fn test_secret_from_seed_phrase() { let secret = Secret::from_str(TEST_SEED_PHRASE).unwrap(); - match secret { - Secret::SeedPhrase { seed_phrase: _ } => assert!(true), - _ => assert!(false), - } + assert!(matches!(secret, Secret::SeedPhrase { .. })); let private_key = secret.private_key(None).unwrap(); assert_eq!(private_key.to_string(), TEST_SECRET_KEY); } - #[test] - fn test_ledger_secret() { - let secret = Secret::from_str("ledger").unwrap(); - match secret { - Secret::Ledger => assert!(true), - _ => assert!(false), - } - } - - #[test] - #[should_panic] - fn test_ledger_secret_will_not_reveal_private_key() { - let secret = Secret::from_str("ledger").unwrap(); - secret.private_key(None).unwrap(); - } - #[test] fn test_keychain_secret() { let keychain_secret = Secret::from_str("keychain").unwrap(); + match keychain_secret { - Secret::Keychain => assert!(true), + Secret::Keychain { entry_name } => { + assert_eq!(entry_name, KEYCHAIN_ENTRY_NAME); + } _ => assert!(false), } } From 1a24c000314ece3306a449060f4dc99e8fb1e15a Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:16:20 -0500 Subject: [PATCH 14/60] keys generate: Namespace keychain entry to identity name --- cmd/soroban-cli/src/commands/keys/generate.rs | 40 +++++++++++++++++-- cmd/soroban-cli/src/config/secret.rs | 23 ++++++----- cmd/soroban-cli/src/signer/keyring.rs | 8 ++-- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index e04c22a1e..b7ebdba3d 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -4,7 +4,11 @@ use super::super::config::{ locator, network, secret::{self, Secret}, }; -use crate::{commands::global, print::Print}; +use crate::{ + commands::global, + print::Print, + signer::keyring::{self, StellarEntry}, +}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -19,6 +23,9 @@ pub enum Error { #[error("An identity with the name '{0}' already exists")] IdentityAlreadyExists(String), + + #[error(transparent)] + Keyring(#[from] keyring::Error), } #[derive(Debug, clap::Parser, Clone)] @@ -67,8 +74,6 @@ pub struct Cmd { pub overwrite: bool, } -const KEYCHAIN_CONSTANT: &str = "keychain"; - impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { let print = Print::new(global_args.quiet); @@ -112,7 +117,21 @@ impl Cmd { Ok(if self.as_secret { seed_phrase.private_key(self.hd_path)?.into() } else if self.keychain { - KEYCHAIN_CONSTANT.parse()? + // keychain:org.stellar.cli: + let entry_name_with_prefix = format!( + "{}{}-{}", + keyring::KEYCHAIN_ENTRY_PREFIX, + keyring::KEYCHAIN_ENTRY_SERVICE, + self.name + ); + + let secret: Secret = entry_name_with_prefix.parse()?; //checking that the entry name is valid before writing to the keychain + + if let Secret::Keychain { entry_name } = &secret { + self.write_to_keychain(entry_name.clone(), seed_phrase)?; + } + + secret } else { seed_phrase }) @@ -125,6 +144,19 @@ impl Cmd { Secret::from_seed(self.seed.as_deref()) }?) } + + fn write_to_keychain(&self, entry_name: String, seed_phrase: Secret) -> Result<(), Error> { + println!("Writing to keychain: {entry_name}"); + let entry = StellarEntry::new(&entry_name)?; + if let Ok(key) = entry.get_public_key() { + println!("A key for {entry_name} already exists in your keychain: {key}"); + } else { + println!("Saving a new key to your keychain: {entry_name}"); + let key_pair = seed_phrase.key_pair(None)?; + entry.set_password(key_pair.as_bytes())?; + } + Ok(()) + } } #[cfg(test)] diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index c88eaa88c..e6d0ce8ec 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -5,12 +5,10 @@ use stellar_strkey::ed25519::{PrivateKey, PublicKey}; use crate::{ print::Print, - signer::{self, LocalKey, Signer, SignerKind}, + signer::{self, keyring, LocalKey, Signer, SignerKind}, utils, }; -const KEYCHAIN_ENTRY_NAME: &str = "org.stellar.cli"; - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("invalid secret key")] @@ -74,9 +72,10 @@ impl Args { .join(" "), }) } else if self.keychain { - Ok(Secret::Keychain { - entry_name: KEYCHAIN_ENTRY_NAME.to_owned(), - }) + todo!(); + // Ok(Secret::Keychain { + // entry_name: KEYCHAIN_ENTRY_NAME.to_owned(), + // }) } else { Err(Error::PasswordRead {}) } @@ -103,9 +102,13 @@ impl FromStr for Secret { Ok(Secret::SeedPhrase { seed_phrase: s.to_string(), }) - } else if s == "keychain" { + } else if s.starts_with(keyring::KEYCHAIN_ENTRY_PREFIX) { + let entry_name = s + .strip_prefix(keyring::KEYCHAIN_ENTRY_PREFIX) + .ok_or(Error::InvalidAddress(s.to_string()))?; + Ok(Secret::Keychain { - entry_name: KEYCHAIN_ENTRY_NAME.to_owned(), //TODO: namespace the entry_name to the system user or key name? + entry_name: entry_name.to_owned(), }) } else { Err(Error::InvalidAddress(s.to_string())) @@ -207,11 +210,11 @@ mod tests { #[test] fn test_keychain_secret() { - let keychain_secret = Secret::from_str("keychain").unwrap(); + let keychain_secret = Secret::from_str("keychain:org.stellar.cli-alice").unwrap(); match keychain_secret { Secret::Keychain { entry_name } => { - assert_eq!(entry_name, KEYCHAIN_ENTRY_NAME); + assert_eq!(entry_name, "org.stellar.cli-alice"); } _ => assert!(false), } diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index bde7e97d6..35d72e9b4 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -3,6 +3,9 @@ use ed25519_dalek::Signer; use keyring::Entry; use zeroize::Zeroize; +pub(crate) const KEYCHAIN_ENTRY_PREFIX: &str = "keychain:"; //TODO: does this belong here, or in secret? +pub(crate) const KEYCHAIN_ENTRY_SERVICE: &str = "org.stellar.cli"; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] @@ -18,10 +21,7 @@ pub struct StellarEntry { impl TryFrom<&StellarEntry> for Entry { type Error = Error; fn try_from(StellarEntry { name }: &StellarEntry) -> Result { - Ok(Entry::new( - &format!("org.stellar.cli.{name}"), - &whoami::username(), - )?) + Ok(Entry::new(name, &whoami::username())?) } } From 4a0c900aa600792c6dc9fad9ec6006fa039d749f Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:02:01 -0500 Subject: [PATCH 15/60] keys generate: don't allow 'keychain:' as a key name --- cmd/soroban-cli/src/commands/keys/generate.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index b7ebdba3d..ce8646123 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -6,6 +6,7 @@ use super::super::config::{ }; use crate::{ commands::global, + config::address::KeyName, print::Print, signer::keyring::{self, StellarEntry}, }; @@ -33,7 +34,7 @@ pub enum Error { #[allow(clippy::struct_excessive_bools)] pub struct Cmd { /// Name of identity - pub name: String, + pub name: KeyName, /// Do not fund address #[arg(long)] pub no_fund: bool, @@ -122,7 +123,7 @@ impl Cmd { "{}{}-{}", keyring::KEYCHAIN_ENTRY_PREFIX, keyring::KEYCHAIN_ENTRY_SERVICE, - self.name + self.name.to_string() ); let secret: Secret = entry_name_with_prefix.parse()?; //checking that the entry name is valid before writing to the keychain From 755c3186997a588a89874cda1e11ca683611fe0c Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:41:02 -0500 Subject: [PATCH 16/60] keys address: use keychain entry in secret to get the pub key --- cmd/soroban-cli/src/config/secret.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index e6d0ce8ec..6364bc2c1 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -27,6 +27,8 @@ pub enum Error { InvalidAddress(String), #[error(transparent)] Signer(#[from] signer::Error), + #[error(transparent)] + Keyring(#[from] keyring::Error), } #[derive(Debug, clap::Args, Clone)] @@ -103,12 +105,8 @@ impl FromStr for Secret { seed_phrase: s.to_string(), }) } else if s.starts_with(keyring::KEYCHAIN_ENTRY_PREFIX) { - let entry_name = s - .strip_prefix(keyring::KEYCHAIN_ENTRY_PREFIX) - .ok_or(Error::InvalidAddress(s.to_string()))?; - Ok(Secret::Keychain { - entry_name: entry_name.to_owned(), + entry_name: s.to_owned(), }) } else { Err(Error::InvalidAddress(s.to_string())) @@ -139,10 +137,18 @@ impl Secret { } pub fn public_key(&self, index: Option) -> Result { - let key = self.key_pair(index)?; - Ok(stellar_strkey::ed25519::PublicKey::from_payload( - key.verifying_key().as_bytes(), - )?) + match self { + Secret::Keychain { entry_name } => { + let entry = keyring::StellarEntry::new(entry_name)?; + Ok(entry.get_public_key()?) + } + _ => { + let key = self.key_pair(index)?; + Ok(stellar_strkey::ed25519::PublicKey::from_payload( + key.verifying_key().as_bytes(), + )?) + } + } } pub fn signer(&self, index: Option, print: Print) -> Result { From dd07bf70d6d8c362a2b2e3922265e9252b04d023 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:12:50 -0500 Subject: [PATCH 17/60] tx sign: allow a keychain identity sign a tx --- cmd/soroban-cli/src/config/secret.rs | 8 +++++--- cmd/soroban-cli/src/signer.rs | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 6364bc2c1..d1e15bedc 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -5,7 +5,7 @@ use stellar_strkey::ed25519::{PrivateKey, PublicKey}; use crate::{ print::Print, - signer::{self, keyring, LocalKey, Signer, SignerKind}, + signer::{self, keyring, KeychainEntry, LocalKey, Signer, SignerKind}, utils, }; @@ -106,7 +106,7 @@ impl FromStr for Secret { }) } else if s.starts_with(keyring::KEYCHAIN_ENTRY_PREFIX) { Ok(Secret::Keychain { - entry_name: s.to_owned(), + entry_name: s.to_string(), }) } else { Err(Error::InvalidAddress(s.to_string())) @@ -157,7 +157,9 @@ impl Secret { let key = self.key_pair(index)?; SignerKind::Local(LocalKey { key }) } - Secret::Keychain { .. } => todo!(), + Secret::Keychain { entry_name } => SignerKind::Keychain(KeychainEntry { + name: entry_name.to_string(), + }), }; Ok(Signer { kind, print }) } diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index a141aaf6b..e0a1568c2 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -1,4 +1,5 @@ -use ed25519_dalek::ed25519::signature::Signer as _; +use ed25519_dalek::ed25519::signature::{self, Signer as _}; +use keyring::StellarEntry; use sha2::{Digest, Sha256}; use crate::xdr::{ @@ -35,6 +36,8 @@ pub enum Error { Open(#[from] std::io::Error), #[error("Returning a signature from Lab is not yet supported; Transaction can be found and submitted in lab")] ReturningSignatureFromLab, + #[error(transparent)] + Keyring(#[from] keyring::Error), } fn requires_auth(txn: &Transaction) -> Option { @@ -209,6 +212,7 @@ pub struct Signer { pub enum SignerKind { Local(LocalKey), Lab, + Keychain(KeychainEntry), } impl Signer { @@ -237,6 +241,7 @@ impl Signer { let decorated_signature = match &self.kind { SignerKind::Local(key) => key.sign_tx_hash(tx_hash)?, SignerKind::Lab => Lab::sign_tx_env(tx_env, network, &self.print)?, + SignerKind::Keychain(entry) => entry.sign_tx_env(tx_env)?, }; let mut sigs = signatures.clone().into_vec(); sigs.push(decorated_signature); @@ -286,3 +291,17 @@ impl Lab { Err(Error::ReturningSignatureFromLab) } } + +pub struct KeychainEntry { + pub name: String, +} + +impl KeychainEntry { + pub fn sign_tx_env(&self, tx_env: &TransactionEnvelope) -> Result { + let entry = StellarEntry::new(&self.name)?; + let signed_tx_env = entry.sign_data(tx_env.to_xdr_base64(Limits::none())?.as_bytes())?; + let hint = SignatureHint(entry.get_public_key()?.0[28..].try_into()?); + let signature = Signature(signed_tx_env.to_vec().try_into()?); + Ok(DecoratedSignature { hint, signature }) + } +} From f042d19788fd6b725d88f762ea5be0fb4577f417 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:28:50 -0500 Subject: [PATCH 18/60] Cleanup --- cmd/soroban-cli/src/commands/keys/generate.rs | 5 +++-- cmd/soroban-cli/src/config/secret.rs | 9 ++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index ce8646123..8ecaa0f4e 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -162,7 +162,7 @@ impl Cmd { #[cfg(test)] mod tests { - use crate::config::secret::Secret; + use crate::config::{self, address::KeyName, secret::Secret}; fn set_up_test() -> (super::locator::Args, super::Cmd) { let temp_dir = tempfile::tempdir().unwrap(); @@ -172,7 +172,7 @@ mod tests { }; let cmd = super::Cmd { - name: "test_name".to_string(), + name: KeyName("test_name".to_string()), no_fund: true, seed: None, as_secret: false, @@ -182,6 +182,7 @@ mod tests { default_seed: false, network: Default::default(), fund: false, + overwrite: false, }; (locator, cmd) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index d1e15bedc..ebc2b8d3f 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -73,11 +73,6 @@ impl Args { .collect::>() .join(" "), }) - } else if self.keychain { - todo!(); - // Ok(Secret::Keychain { - // entry_name: KEYCHAIN_ENTRY_NAME.to_owned(), - // }) } else { Err(Error::PasswordRead {}) } @@ -132,7 +127,7 @@ impl Secret { .private() .0, )?, - Secret::Keychain { entry_name: _ } => panic!("Keychain does not reveal secret key"), + Secret::Keychain { .. } => panic!("Keychain does not reveal secret key"), }) } @@ -222,7 +217,7 @@ mod tests { match keychain_secret { Secret::Keychain { entry_name } => { - assert_eq!(entry_name, "org.stellar.cli-alice"); + assert_eq!(entry_name, "keychain:org.stellar.cli-alice"); } _ => assert!(false), } From 9cf591606ac7ddde6676634d8b149717739f85ca Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:22:21 -0500 Subject: [PATCH 19/60] Use keyring mock for generate tests --- cmd/soroban-cli/src/commands/keys/generate.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 8ecaa0f4e..3bf2e48be 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -163,6 +163,7 @@ impl Cmd { #[cfg(test)] mod tests { use crate::config::{self, address::KeyName, secret::Secret}; + use keyring::{mock, set_default_credential_builder}; fn set_up_test() -> (super::locator::Args, super::Cmd) { let temp_dir = tempfile::tempdir().unwrap(); @@ -185,6 +186,8 @@ mod tests { overwrite: false, }; + set_default_credential_builder(mock::default_credential_builder()); + (locator, cmd) } From cd515d3d13ed0112ee1f41604b5fad020b5d5ae3 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:24:12 -0500 Subject: [PATCH 20/60] Refactor keyring: add keyring entry as StellarEntry field - previously we were creating a new keyring entry for each interaction with the keyring - this change will allow us use a mock keyring entry for testing --- cmd/soroban-cli/src/signer/keyring.rs | 47 ++++++++++++++------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index 35d72e9b4..5165dec43 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -15,33 +15,24 @@ pub enum Error { } pub struct StellarEntry { - name: String, -} - -impl TryFrom<&StellarEntry> for Entry { - type Error = Error; - fn try_from(StellarEntry { name }: &StellarEntry) -> Result { - Ok(Entry::new(name, &whoami::username())?) - } + keyring: Entry, } impl StellarEntry { pub fn new(name: &str) -> Result { Ok(StellarEntry { - name: name.to_string(), + keyring: Entry::new(name, &whoami::username())?, }) } pub fn set_password(&self, password: &[u8]) -> Result<(), Error> { let data = base64.encode(password); - let entry: Entry = self.try_into()?; - entry.set_password(&data)?; + self.keyring.set_password(&data)?; Ok(()) } pub fn get_password(&self) -> Result, Error> { - let entry: Entry = self.try_into()?; - Ok(base64.decode(entry.get_password()?)?) + Ok(base64.decode(self.keyring.get_password()?)?) } fn use_key( @@ -80,16 +71,28 @@ impl StellarEntry { #[cfg(test)] mod test { use super::*; + use keyring::{ + mock, + set_default_credential_builder, + }; #[test] - fn test_sign_data() -> Result<(), Box> { - let secret = crate::config::secret::Secret::from_seed(None)?; - let pub_key = secret.public_key(None)?; - let key_pair = secret.key_pair(None)?; - let entry = StellarEntry::new("test")?; - entry.set_password(&key_pair.to_bytes()); - let pub_key_2 = entry.get_public_key()?; - assert_eq!(pub_key, pub_key_2); - Ok(()) + fn test_sign_data() { + set_default_credential_builder(mock::default_credential_builder()); + + let secret = crate::config::secret::Secret::from_seed(None).unwrap(); + let pub_key = secret.public_key(None).unwrap(); + let key_pair = secret.key_pair(None).unwrap(); + + let entry = StellarEntry::new("test").unwrap(); + + // set the password + let set_password_result = entry.set_password(&key_pair.to_bytes()); + assert!(set_password_result.is_ok()); + + // confirm that we can get the public key from the entry and that it matches the one we set + let get_public_key_result = entry.get_public_key(); + assert!(get_public_key_result.is_ok()); + assert_eq!(pub_key, get_public_key_result.unwrap()); } } From 276558db228486205b29ded009f193b6d56c513e Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:20:22 -0500 Subject: [PATCH 21/60] Add tests for keyring --- cmd/soroban-cli/src/signer/keyring.rs | 48 +++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index 5165dec43..6c32f620d 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -71,17 +71,33 @@ impl StellarEntry { #[cfg(test)] mod test { use super::*; - use keyring::{ - mock, - set_default_credential_builder, - }; + use keyring::{mock, set_default_credential_builder}; #[test] - fn test_sign_data() { + fn test_get_password() { set_default_credential_builder(mock::default_credential_builder()); let secret = crate::config::secret::Secret::from_seed(None).unwrap(); - let pub_key = secret.public_key(None).unwrap(); + let key_pair = secret.key_pair(None).unwrap(); + + let entry = StellarEntry::new("test").unwrap(); + + // set the password + let set_password_result = entry.set_password(&key_pair.to_bytes()); + assert!(set_password_result.is_ok()); + + // get_password should return the same password we set + let get_password_result = entry.get_password(); + assert!(get_password_result.is_ok()); + assert_eq!(key_pair.to_bytes().to_vec(), get_password_result.unwrap()); + } + + #[test] + fn test_get_public_key() { + set_default_credential_builder(mock::default_credential_builder()); + + let secret = crate::config::secret::Secret::from_seed(None).unwrap(); + let public_key = secret.public_key(None).unwrap(); let key_pair = secret.key_pair(None).unwrap(); let entry = StellarEntry::new("test").unwrap(); @@ -93,6 +109,24 @@ mod test { // confirm that we can get the public key from the entry and that it matches the one we set let get_public_key_result = entry.get_public_key(); assert!(get_public_key_result.is_ok()); - assert_eq!(pub_key, get_public_key_result.unwrap()); + assert_eq!(public_key, get_public_key_result.unwrap()); + } + + #[test] + fn test_sign_data() { + set_default_credential_builder(mock::default_credential_builder()); + + //create a secret + let secret = crate::config::secret::Secret::from_seed(None).unwrap(); + let key_pair = secret.key_pair(None).unwrap(); + + // create a keyring entry and set the password + let entry = StellarEntry::new("test").unwrap(); + entry.set_password(&key_pair.to_bytes()).unwrap(); + + let tx_xdr = r#"AAAAAgAAAADh6eOnZEq1xQgKioffuH7/8D8x8+OdGFEkiYC6QKMWzQAAAGQAAACuAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAYAAAAAQAAAAAAAAAAAAAAAOHp46dkSrXFCAqKh9+4fv/wPzHz450YUSSJgLpAoxbNoFT1s8jZPCv9IJ2DsqGTA8pOtavv58JF53aDycpRPcEAAAAA+N2m5zc3EfWUmLvigYPOHKXhSy8OrWfVibc6y6PrQoYAAAAAAAAAAAAAAAA"#; + + let sign_tx_env_result = entry.sign_data(tx_xdr.as_bytes()); + assert!(sign_tx_env_result.is_ok()); } } From 20c651bc211a253472baaa719ac2ec6c1885ea76 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:17:03 -0500 Subject: [PATCH 22/60] Update config/secret tests --- cmd/soroban-cli/src/config/secret.rs | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index ebc2b8d3f..e7fbea44c 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -188,39 +188,39 @@ fn read_password() -> Result { mod tests { use super::*; + const TEST_PUBLIC_KEY: &str = "GAREAZZQWHOCBJS236KIE3AWYBVFLSBK7E5UW3ICI3TCRWQKT5LNLCEZ"; const TEST_SECRET_KEY: &str = "SBF5HLRREHMS36XZNTUSKZ6FTXDZGNXOHF4EXKUL5UCWZLPBX3NGJ4BH"; const TEST_SEED_PHRASE: &str = "depth decade power loud smile spatial sign movie judge february rate broccoli"; #[test] - fn test_secret_from_key() { + fn test_from_str_for_secret_key() { let secret = Secret::from_str(TEST_SECRET_KEY).unwrap(); - // assert that it is a Secret::SecretKey - assert!(matches!(secret, Secret::SecretKey { .. })); - // assert that we can get the private key from it + let public_key = secret.public_key(None).unwrap(); let private_key = secret.private_key(None).unwrap(); + + assert!(matches!(secret, Secret::SecretKey { .. })); + assert_eq!(public_key.to_string(), TEST_PUBLIC_KEY); assert_eq!(private_key.to_string(), TEST_SECRET_KEY); } #[test] - fn test_secret_from_seed_phrase() { + fn test_from_str_for_seed_phrase() { let secret = Secret::from_str(TEST_SEED_PHRASE).unwrap(); - assert!(matches!(secret, Secret::SeedPhrase { .. })); - + let public_key = secret.public_key(None).unwrap(); let private_key = secret.private_key(None).unwrap(); + + assert!(matches!(secret, Secret::SeedPhrase { .. })); + assert_eq!(public_key.to_string(), TEST_PUBLIC_KEY); assert_eq!(private_key.to_string(), TEST_SECRET_KEY); } #[test] - fn test_keychain_secret() { - let keychain_secret = Secret::from_str("keychain:org.stellar.cli-alice").unwrap(); + fn test_from_str_for_keychain_secret() { + //todo: add assertion for getting public key - will need to mock the keychain and add the keypair to the keychain + let secret = Secret::from_str("keychain:org.stellar.cli-alice").unwrap(); - match keychain_secret { - Secret::Keychain { entry_name } => { - assert_eq!(entry_name, "keychain:org.stellar.cli-alice"); - } - _ => assert!(false), - } + assert!(matches!(secret, Secret::Keychain { .. })); } #[test] From 66d1bfc46b2ab8bef535c66028f7d002fae65be0 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:49:06 -0500 Subject: [PATCH 23/60] Cleanup --- cmd/soroban-cli/src/commands/keys/generate.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 3bf2e48be..93ae67a3b 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -35,9 +35,11 @@ pub enum Error { pub struct Cmd { /// Name of identity pub name: KeyName, + /// Do not fund address #[arg(long)] pub no_fund: bool, + /// Optional seed to use when generating seed phrase. /// Random otherwise. #[arg(long, conflicts_with = "default_seed")] @@ -162,7 +164,7 @@ impl Cmd { #[cfg(test)] mod tests { - use crate::config::{self, address::KeyName, secret::Secret}; + use crate::config::{address::KeyName, secret::Secret}; use keyring::{mock, set_default_credential_builder}; fn set_up_test() -> (super::locator::Args, super::Cmd) { @@ -186,8 +188,6 @@ mod tests { overwrite: false, }; - set_default_credential_builder(mock::default_credential_builder()); - (locator, cmd) } @@ -222,6 +222,7 @@ mod tests { #[tokio::test] async fn test_storing_secret_in_keychain() { + set_default_credential_builder(mock::default_credential_builder()); let (test_locator, mut cmd) = set_up_test(); cmd.keychain = true; let global_args = global_args(); From 8b9763ee158eeb746eb4d7b42072478d98e2b1b6 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:58:17 -0500 Subject: [PATCH 24/60] Rename keychain arg to secure_store in generate --- cmd/soroban-cli/src/commands/keys/generate.rs | 31 ++++++++++--------- cmd/soroban-cli/src/config/secret.rs | 2 +- cmd/soroban-cli/src/signer/keyring.rs | 4 +-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 93ae67a3b..0314ddf7d 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -49,9 +49,9 @@ pub struct Cmd { #[arg(long, short = 's')] pub as_secret: bool, - /// Save in `keychain` + /// Save in OS-specific secure store #[arg(long)] - pub keychain: bool, + pub secure_store: bool, #[command(flatten)] pub config_locator: locator::Args, @@ -119,19 +119,20 @@ impl Cmd { let seed_phrase = self.seed_phrase()?; Ok(if self.as_secret { seed_phrase.private_key(self.hd_path)?.into() - } else if self.keychain { - // keychain:org.stellar.cli: + } else if self.secure_store { + // secure_store:org.stellar.cli: let entry_name_with_prefix = format!( "{}{}-{}", - keyring::KEYCHAIN_ENTRY_PREFIX, - keyring::KEYCHAIN_ENTRY_SERVICE, + keyring::SECURE_STORE_ENTRY_PREFIX, + keyring::SECURE_STORE_ENTRY_SERVICE, self.name.to_string() ); - let secret: Secret = entry_name_with_prefix.parse()?; //checking that the entry name is valid before writing to the keychain + //checking that the entry name is valid before writing to the secure store + let secret: Secret = entry_name_with_prefix.parse()?; if let Secret::Keychain { entry_name } = &secret { - self.write_to_keychain(entry_name.clone(), seed_phrase)?; + self.write_to_secure_store(entry_name.clone(), seed_phrase)?; } secret @@ -148,13 +149,13 @@ impl Cmd { }?) } - fn write_to_keychain(&self, entry_name: String, seed_phrase: Secret) -> Result<(), Error> { - println!("Writing to keychain: {entry_name}"); + fn write_to_secure_store(&self, entry_name: String, seed_phrase: Secret) -> Result<(), Error> { + println!("Writing to secure store: {entry_name}"); let entry = StellarEntry::new(&entry_name)?; if let Ok(key) = entry.get_public_key() { - println!("A key for {entry_name} already exists in your keychain: {key}"); + println!("A key for {entry_name} already exists in your operating system's secure store: {key}"); } else { - println!("Saving a new key to your keychain: {entry_name}"); + println!("Saving a new key to your operating system's secure store: {entry_name}"); let key_pair = seed_phrase.key_pair(None)?; entry.set_password(key_pair.as_bytes())?; } @@ -179,7 +180,7 @@ mod tests { no_fund: true, seed: None, as_secret: false, - keychain: false, + secure_store: false, config_locator: locator.clone(), hd_path: None, default_seed: false, @@ -221,10 +222,10 @@ mod tests { } #[tokio::test] - async fn test_storing_secret_in_keychain() { + async fn test_storing_secret_in_secure_store() { set_default_credential_builder(mock::default_credential_builder()); let (test_locator, mut cmd) = set_up_test(); - cmd.keychain = true; + cmd.secure_store = true; let global_args = global_args(); let result = cmd.run(&global_args).await; diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index e7fbea44c..5cdb30504 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -99,7 +99,7 @@ impl FromStr for Secret { Ok(Secret::SeedPhrase { seed_phrase: s.to_string(), }) - } else if s.starts_with(keyring::KEYCHAIN_ENTRY_PREFIX) { + } else if s.starts_with(keyring::SECURE_STORE_ENTRY_PREFIX) { Ok(Secret::Keychain { entry_name: s.to_string(), }) diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index 6c32f620d..f92280f7e 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -3,8 +3,8 @@ use ed25519_dalek::Signer; use keyring::Entry; use zeroize::Zeroize; -pub(crate) const KEYCHAIN_ENTRY_PREFIX: &str = "keychain:"; //TODO: does this belong here, or in secret? -pub(crate) const KEYCHAIN_ENTRY_SERVICE: &str = "org.stellar.cli"; +pub(crate) const SECURE_STORE_ENTRY_PREFIX: &str = "secure_store:"; +pub(crate) const SECURE_STORE_ENTRY_SERVICE: &str = "org.stellar.cli"; #[derive(thiserror::Error, Debug)] pub enum Error { From fdefa2aee53631c00761089fb4c7b9f162be79d7 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:02:43 -0500 Subject: [PATCH 25/60] Rename Secret::Keychain to Secret::SecureStore --- cmd/soroban-cli/src/commands/keys/generate.rs | 4 ++-- cmd/soroban-cli/src/config/secret.rs | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 0314ddf7d..492d17bd4 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -131,7 +131,7 @@ impl Cmd { //checking that the entry name is valid before writing to the secure store let secret: Secret = entry_name_with_prefix.parse()?; - if let Secret::Keychain { entry_name } = &secret { + if let Secret::SecureStore { entry_name } = &secret { self.write_to_secure_store(entry_name.clone(), seed_phrase)?; } @@ -231,6 +231,6 @@ mod tests { let result = cmd.run(&global_args).await; assert!(result.is_ok()); let identity = test_locator.read_identity("test_name").unwrap(); - assert!(matches!(identity, Secret::Keychain { .. })); + assert!(matches!(identity, Secret::SecureStore { .. })); } } diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 5cdb30504..a1adabeb8 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -84,7 +84,7 @@ impl Args { pub enum Secret { SecretKey { secret_key: String }, SeedPhrase { seed_phrase: String }, - Keychain { entry_name: String }, + SecureStore { entry_name: String }, } impl FromStr for Secret { @@ -100,7 +100,7 @@ impl FromStr for Secret { seed_phrase: s.to_string(), }) } else if s.starts_with(keyring::SECURE_STORE_ENTRY_PREFIX) { - Ok(Secret::Keychain { + Ok(Secret::SecureStore { entry_name: s.to_string(), }) } else { @@ -127,13 +127,13 @@ impl Secret { .private() .0, )?, - Secret::Keychain { .. } => panic!("Keychain does not reveal secret key"), + Secret::SecureStore { .. } => panic!("Secure Store does not reveal secret key"), }) } pub fn public_key(&self, index: Option) -> Result { match self { - Secret::Keychain { entry_name } => { + Secret::SecureStore { entry_name } => { let entry = keyring::StellarEntry::new(entry_name)?; Ok(entry.get_public_key()?) } @@ -152,7 +152,7 @@ impl Secret { let key = self.key_pair(index)?; SignerKind::Local(LocalKey { key }) } - Secret::Keychain { entry_name } => SignerKind::Keychain(KeychainEntry { + Secret::SecureStore { entry_name } => SignerKind::Keychain(KeychainEntry { name: entry_name.to_string(), }), }; @@ -216,17 +216,17 @@ mod tests { } #[test] - fn test_from_str_for_keychain_secret() { + fn test_from_str_for_secure_store_secret() { //todo: add assertion for getting public key - will need to mock the keychain and add the keypair to the keychain - let secret = Secret::from_str("keychain:org.stellar.cli-alice").unwrap(); + let secret = Secret::from_str("secure_store:org.stellar.cli-alice").unwrap(); - assert!(matches!(secret, Secret::Keychain { .. })); + assert!(matches!(secret, Secret::SecureStore { .. })); } #[test] #[should_panic] - fn test_keychain_secret_will_not_reveal_private_key() { - let secret = Secret::from_str("keychain").unwrap(); + fn test_secure_store_will_not_reveal_private_key() { + let secret = Secret::from_str("secure_store").unwrap(); secret.private_key(None).unwrap(); } From 36559eae08f54ac504d8ba90608fe71f83bd5f97 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:22:09 -0500 Subject: [PATCH 26/60] Rename SignerKind::Keychain to SignerKind::SecureStore --- cmd/soroban-cli/src/commands/keys/mod.rs | 2 +- cmd/soroban-cli/src/config/secret.rs | 12 ++++-------- cmd/soroban-cli/src/signer.rs | 10 +++++----- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs index 8729ee9af..b3309fa02 100644 --- a/cmd/soroban-cli/src/commands/keys/mod.rs +++ b/cmd/soroban-cli/src/commands/keys/mod.rs @@ -12,7 +12,7 @@ pub mod show; #[derive(Debug, Parser)] pub enum Cmd { - /// Add a new identity (keypair, ledger, macOS keychain) + /// Add a new identity (keypair, ledger, OS specific secure store) Add(add::Cmd), /// Given an identity return its address (public key) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index a1adabeb8..47ac9f401 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -5,7 +5,7 @@ use stellar_strkey::ed25519::{PrivateKey, PublicKey}; use crate::{ print::Print, - signer::{self, keyring, KeychainEntry, LocalKey, Signer, SignerKind}, + signer::{self, keyring, LocalKey, SecureStoreEntry, Signer, SignerKind}, utils, }; @@ -36,15 +36,11 @@ pub enum Error { pub struct Args { /// Add using `secret_key` /// Can provide with `SOROBAN_SECRET_KEY` - #[arg(long, conflicts_with_all = ["seed_phrase", "keychain"])] + #[arg(long, conflicts_with = "seed_phrase")] pub secret_key: bool, /// Add using 12 word seed phrase to generate `secret_key` - #[arg(long, conflicts_with_all = ["secret_key", "keychain"])] + #[arg(long, conflicts_with = "secret_key")] pub seed_phrase: bool, - - /// Add using `keychain` - #[arg(long, conflicts_with_all = ["seed_phrase", "secret_key"])] - pub keychain: bool, } impl Args { @@ -152,7 +148,7 @@ impl Secret { let key = self.key_pair(index)?; SignerKind::Local(LocalKey { key }) } - Secret::SecureStore { entry_name } => SignerKind::Keychain(KeychainEntry { + Secret::SecureStore { entry_name } => SignerKind::SecureStore(SecureStoreEntry { name: entry_name.to_string(), }), }; diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index e0a1568c2..86db2dcea 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -1,4 +1,4 @@ -use ed25519_dalek::ed25519::signature::{self, Signer as _}; +use ed25519_dalek::ed25519::signature::Signer as _; use keyring::StellarEntry; use sha2::{Digest, Sha256}; @@ -212,7 +212,7 @@ pub struct Signer { pub enum SignerKind { Local(LocalKey), Lab, - Keychain(KeychainEntry), + SecureStore(SecureStoreEntry), } impl Signer { @@ -241,7 +241,7 @@ impl Signer { let decorated_signature = match &self.kind { SignerKind::Local(key) => key.sign_tx_hash(tx_hash)?, SignerKind::Lab => Lab::sign_tx_env(tx_env, network, &self.print)?, - SignerKind::Keychain(entry) => entry.sign_tx_env(tx_env)?, + SignerKind::SecureStore(entry) => entry.sign_tx_env(tx_env)?, }; let mut sigs = signatures.clone().into_vec(); sigs.push(decorated_signature); @@ -292,11 +292,11 @@ impl Lab { } } -pub struct KeychainEntry { +pub struct SecureStoreEntry { pub name: String, } -impl KeychainEntry { +impl SecureStoreEntry { pub fn sign_tx_env(&self, tx_env: &TransactionEnvelope) -> Result { let entry = StellarEntry::new(&self.name)?; let signed_tx_env = entry.sign_data(tx_env.to_xdr_base64(Limits::none())?.as_bytes())?; From f98b709c3a09d22bdfeddba0a1d77fb1b5d64110 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:00:44 -0500 Subject: [PATCH 27/60] Use print for new fns in generate --- cmd/soroban-cli/src/commands/keys/generate.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 492d17bd4..0395a593c 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -97,7 +97,7 @@ impl Cmd { warning. It can be suppressed with -q flag.", ); } - let secret = self.secret()?; + let secret = self.secret(print)?; self.config_locator.write_identity(&self.name, &secret)?; if !self.no_fund { @@ -115,7 +115,7 @@ impl Cmd { Ok(()) } - fn secret(&self) -> Result { + fn secret(&self, print: Print) -> Result { let seed_phrase = self.seed_phrase()?; Ok(if self.as_secret { seed_phrase.private_key(self.hd_path)?.into() @@ -132,7 +132,7 @@ impl Cmd { let secret: Secret = entry_name_with_prefix.parse()?; if let Secret::SecureStore { entry_name } = &secret { - self.write_to_secure_store(entry_name.clone(), seed_phrase)?; + self.write_to_secure_store(entry_name.clone(), seed_phrase, print)?; } secret @@ -149,13 +149,20 @@ impl Cmd { }?) } - fn write_to_secure_store(&self, entry_name: String, seed_phrase: Secret) -> Result<(), Error> { + fn write_to_secure_store( + &self, + entry_name: String, + seed_phrase: Secret, + print: Print, + ) -> Result<(), Error> { println!("Writing to secure store: {entry_name}"); let entry = StellarEntry::new(&entry_name)?; if let Ok(key) = entry.get_public_key() { - println!("A key for {entry_name} already exists in your operating system's secure store: {key}"); + print.warnln(format!("A key for {entry_name} already exists in your operating system's secure store: {key}")); } else { - println!("Saving a new key to your operating system's secure store: {entry_name}"); + print.infoln(format!( + "Saving a new key to your operating system's secure store: {entry_name}" + )); let key_pair = seed_phrase.key_pair(None)?; entry.set_password(key_pair.as_bytes())?; } From 0f3106b2cc3d84d6fc6d28e1b29b66010e03f52e Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:08:09 -0500 Subject: [PATCH 28/60] Return error when trying to get Secure Store secret --- cmd/soroban-cli/src/config/secret.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 47ac9f401..49887074c 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -29,6 +29,8 @@ pub enum Error { Signer(#[from] signer::Error), #[error(transparent)] Keyring(#[from] keyring::Error), + #[error("Secure Store does not reveal secret key")] + SecureStoreDoesNotRevealSecretKey, } #[derive(Debug, clap::Args, Clone)] @@ -123,7 +125,9 @@ impl Secret { .private() .0, )?, - Secret::SecureStore { .. } => panic!("Secure Store does not reveal secret key"), + Secret::SecureStore { .. } => { + return Err(Error::SecureStoreDoesNotRevealSecretKey); + } }) } From e120595a440760cc8b7c737928d56cbf37929a5d Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:58:49 -0500 Subject: [PATCH 29/60] Cleanup tests --- cmd/soroban-cli/src/config/secret.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 49887074c..b0070b28c 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -205,7 +205,7 @@ mod tests { } #[test] - fn test_from_str_for_seed_phrase() { + fn test_secret_from_seed_phrase() { let secret = Secret::from_str(TEST_SEED_PHRASE).unwrap(); let public_key = secret.public_key(None).unwrap(); let private_key = secret.private_key(None).unwrap(); @@ -216,18 +216,17 @@ mod tests { } #[test] - fn test_from_str_for_secure_store_secret() { + fn test_secret_from_secure_store() { //todo: add assertion for getting public key - will need to mock the keychain and add the keypair to the keychain let secret = Secret::from_str("secure_store:org.stellar.cli-alice").unwrap(); - assert!(matches!(secret, Secret::SecureStore { .. })); - } - #[test] - #[should_panic] - fn test_secure_store_will_not_reveal_private_key() { - let secret = Secret::from_str("secure_store").unwrap(); - secret.private_key(None).unwrap(); + let private_key_result = secret.private_key(None); + assert!(private_key_result.is_err()); + assert!(matches!( + private_key_result.unwrap_err(), + Error::SecureStoreDoesNotRevealSecretKey + )); } #[test] From 57ba3a489a8294421aae822eb8f2942013c3f98a Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:19:02 -0500 Subject: [PATCH 30/60] Install libdbus for rpc-tests and bindings-ts workflows required for keyring crate --- .github/workflows/bindings-ts.yml | 1 + .github/workflows/rpc-tests.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index 957661c4c..10cf23007 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -35,6 +35,7 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - run: rustup update + - run: sudo apt install -y libdbus-1-dev - run: cargo build - run: rustup target add wasm32-unknown-unknown - run: make build-test-wasms diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index 75b6d7760..5392d9830 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -39,6 +39,7 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - run: rustup update + - run: sudo apt install -y libdbus-1-dev - run: cargo build - run: rustup target add wasm32-unknown-unknown - run: make build-test-wasms From 0814e4b1ea4cca9258de3b615fb1a3b539f971bc Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:14:03 -0500 Subject: [PATCH 31/60] Update generated docs --- FULL_HELP_DOCS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index a755ef18a..70e0d19ff 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -933,7 +933,7 @@ Create and manage identities including keys and addresses ###### **Subcommands:** -* `add` — Add a new identity (keypair, ledger, macOS keychain) +* `add` — Add a new identity (keypair, ledger, OS specific secure store) * `address` — Given an identity return its address (public key) * `fund` — Fund an identity on a test network * `generate` — Generate a new identity with a seed phrase, currently 12 words @@ -946,7 +946,7 @@ Create and manage identities including keys and addresses ## `stellar keys add` -Add a new identity (keypair, ledger, macOS keychain) +Add a new identity (keypair, ledger, OS specific secure store) **Usage:** `stellar keys add [OPTIONS] ` @@ -1018,6 +1018,7 @@ Generate a new identity with a seed phrase, currently 12 words * `--no-fund` — Do not fund address * `--seed ` — Optional seed to use when generating seed phrase. Random otherwise * `-s`, `--as-secret` — Output the generated identity as a secret key +* `--secure-store` — Save in OS-specific secure store * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." * `--hd-path ` — When generating a secret key, which `hd_path` should be used from the original `seed_phrase` From 74fa05b75e093fd3c1449ab890c31c2692026a6d Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:17:23 -0500 Subject: [PATCH 32/60] Install libdbus for binaries workflow when target aarch64-unknown-linux-gnu --- .github/workflows/binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index d913cf23d..f22865da8 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -46,7 +46,7 @@ jobs: - run: rustup target add ${{ matrix.sys.target }} - if: matrix.sys.target == 'aarch64-unknown-linux-gnu' - run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev + run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev libdbus-1-dev - name: Setup vars run: | From 7ff1f6a4907b7f7c76969952bc4a16f0ea6babcc Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:45:53 -0500 Subject: [PATCH 33/60] Clippy --- cmd/soroban-cli/src/commands/keys/generate.rs | 28 +++++++++---------- cmd/soroban-cli/src/config/secret.rs | 19 ++++++------- cmd/soroban-cli/src/signer.rs | 2 +- cmd/soroban-cli/src/signer/keyring.rs | 2 +- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 0395a593c..72597aff3 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -97,7 +97,7 @@ impl Cmd { warning. It can be suppressed with -q flag.", ); } - let secret = self.secret(print)?; + let secret = self.secret(&print)?; self.config_locator.write_identity(&self.name, &secret)?; if !self.no_fund { @@ -115,14 +115,14 @@ impl Cmd { Ok(()) } - fn secret(&self, print: Print) -> Result { + fn secret(&self, print: &Print) -> Result { let seed_phrase = self.seed_phrase()?; Ok(if self.as_secret { seed_phrase.private_key(self.hd_path)?.into() } else if self.secure_store { // secure_store:org.stellar.cli: let entry_name_with_prefix = format!( - "{}{}-{}", + "{}{}-{:?}", keyring::SECURE_STORE_ENTRY_PREFIX, keyring::SECURE_STORE_ENTRY_SERVICE, self.name.to_string() @@ -132,7 +132,7 @@ impl Cmd { let secret: Secret = entry_name_with_prefix.parse()?; if let Secret::SecureStore { entry_name } = &secret { - self.write_to_secure_store(entry_name.clone(), seed_phrase, print)?; + Self::write_to_secure_store(entry_name, &seed_phrase, print)?; } secret @@ -150,13 +150,12 @@ impl Cmd { } fn write_to_secure_store( - &self, - entry_name: String, - seed_phrase: Secret, - print: Print, + entry_name: &String, + seed_phrase: &Secret, + print: &Print, ) -> Result<(), Error> { - println!("Writing to secure store: {entry_name}"); - let entry = StellarEntry::new(&entry_name)?; + print.infoln(format!("Writing to secure store: {entry_name}")); + let entry = StellarEntry::new(entry_name)?; if let Ok(key) = entry.get_public_key() { print.warnln(format!("A key for {entry_name} already exists in your operating system's secure store: {key}")); } else { @@ -191,7 +190,7 @@ mod tests { config_locator: locator.clone(), hd_path: None, default_seed: false, - network: Default::default(), + network: super::network::Args::default(), fund: false, overwrite: false, }; @@ -200,9 +199,10 @@ mod tests { } fn global_args() -> super::global::Args { - let mut global_args = super::global::Args::default(); - global_args.quiet = true; - global_args + super::global::Args { + quiet: true, + ..Default::default() + } } #[tokio::test] diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index b0070b28c..cd3bc908a 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -132,17 +132,14 @@ impl Secret { } pub fn public_key(&self, index: Option) -> Result { - match self { - Secret::SecureStore { entry_name } => { - let entry = keyring::StellarEntry::new(entry_name)?; - Ok(entry.get_public_key()?) - } - _ => { - let key = self.key_pair(index)?; - Ok(stellar_strkey::ed25519::PublicKey::from_payload( - key.verifying_key().as_bytes(), - )?) - } + if let Secret::SecureStore { entry_name } = self { + let entry = keyring::StellarEntry::new(entry_name)?; + Ok(entry.get_public_key()?) + } else { + let key = self.key_pair(index)?; + Ok(stellar_strkey::ed25519::PublicKey::from_payload( + key.verifying_key().as_bytes(), + )?) } } diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index 86db2dcea..ba9ba8667 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -301,7 +301,7 @@ impl SecureStoreEntry { let entry = StellarEntry::new(&self.name)?; let signed_tx_env = entry.sign_data(tx_env.to_xdr_base64(Limits::none())?.as_bytes())?; let hint = SignatureHint(entry.get_public_key()?.0[28..].try_into()?); - let signature = Signature(signed_tx_env.to_vec().try_into()?); + let signature = Signature(signed_tx_env.clone().try_into()?); Ok(DecoratedSignature { hint, signature }) } } diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index f92280f7e..b5a63a398 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -124,7 +124,7 @@ mod test { let entry = StellarEntry::new("test").unwrap(); entry.set_password(&key_pair.to_bytes()).unwrap(); - let tx_xdr = r#"AAAAAgAAAADh6eOnZEq1xQgKioffuH7/8D8x8+OdGFEkiYC6QKMWzQAAAGQAAACuAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAYAAAAAQAAAAAAAAAAAAAAAOHp46dkSrXFCAqKh9+4fv/wPzHz450YUSSJgLpAoxbNoFT1s8jZPCv9IJ2DsqGTA8pOtavv58JF53aDycpRPcEAAAAA+N2m5zc3EfWUmLvigYPOHKXhSy8OrWfVibc6y6PrQoYAAAAAAAAAAAAAAAA"#; + let tx_xdr = r"AAAAAgAAAADh6eOnZEq1xQgKioffuH7/8D8x8+OdGFEkiYC6QKMWzQAAAGQAAACuAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAYAAAAAQAAAAAAAAAAAAAAAOHp46dkSrXFCAqKh9+4fv/wPzHz450YUSSJgLpAoxbNoFT1s8jZPCv9IJ2DsqGTA8pOtavv58JF53aDycpRPcEAAAAA+N2m5zc3EfWUmLvigYPOHKXhSy8OrWfVibc6y6PrQoYAAAAAAAAAAAAAAAA"; let sign_tx_env_result = entry.sign_data(tx_xdr.as_bytes()); assert!(sign_tx_env_result.is_ok()); From f263d8dfcd5ed764470be40d92aef48b81abc174 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:17:52 -0500 Subject: [PATCH 34/60] Install libdbus for rust workflow --- .github/workflows/rust.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index f3c9b1920..ff4f7d399 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -49,6 +49,7 @@ jobs: - uses: actions/checkout@v4 - uses: stellar/actions/rust-cache@main - run: rustup update + - run: sudo apt install -y libdbus-1-dev - run: make generate-full-help-doc - run: git add -N . && git diff HEAD --exit-code @@ -90,7 +91,7 @@ jobs: - run: rustup target add ${{ matrix.sys.target }} - run: rustup target add wasm32-unknown-unknown - if: runner.os == 'Linux' - run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev + run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev libdbus-1-dev - run: cargo clippy --all-targets --target ${{ matrix.sys.target }} - run: make test env: From e2b734204020df530b302eb3666e735a45fa3edb Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:33:12 -0500 Subject: [PATCH 35/60] Install libdbus-1-dev in binaries workflow for build step --- .github/workflows/binaries.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index f22865da8..ebfcf927c 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -69,6 +69,7 @@ jobs: env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc working-directory: ${{ env.BUILD_WORKING_DIR }} + run: sudo apt-get update && sudo apt-get -y install libdbus-1-dev run: cargo build --target-dir="$GITHUB_WORKSPACE/target" --package ${{ matrix.crate.name }} --features opt --release --target ${{ matrix.sys.target }} - name: Build provenance for attestation (release only) From dabbb2739f1ef63eebef22bc76ab3532a064fd63 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:30:02 -0500 Subject: [PATCH 36/60] Impl Display for KeyName this change was made so that we can concat the KeyName with secure story prefix and service --- cmd/soroban-cli/src/commands/keys/generate.rs | 4 ++-- cmd/soroban-cli/src/config/address.rs | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 72597aff3..bd9f8c2f6 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -122,10 +122,10 @@ impl Cmd { } else if self.secure_store { // secure_store:org.stellar.cli: let entry_name_with_prefix = format!( - "{}{}-{:?}", + "{}{}-{}", keyring::SECURE_STORE_ENTRY_PREFIX, keyring::SECURE_STORE_ENTRY_SERVICE, - self.name.to_string() + self.name ); //checking that the entry name is valid before writing to the secure store diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 57c229c76..961c26bb6 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -1,4 +1,7 @@ -use std::str::FromStr; +use std::{ + fmt::{self, Display, Formatter}, + str::FromStr, +}; use crate::xdr; @@ -87,6 +90,12 @@ impl std::str::FromStr for KeyName { } } +impl Display for KeyName { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + fn allowed_char(c: char) -> bool { c.is_ascii_alphanumeric() || c == '_' || c == '-' } From d9131b402fa343bd114d020fa7fb20db818b45cd Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:19:52 -0500 Subject: [PATCH 37/60] Use resolve_muxed_account in resolve_secret --- cmd/soroban-cli/src/config/address.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 961c26bb6..b75b89fe2 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -61,8 +61,8 @@ impl Address { pub fn resolve_secret(&self, locator: &locator::Args) -> Result { match &self { - Address::MuxedAccount(muxed_account) => Err(Error::CannotSign(muxed_account.clone())), Address::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), + a => Err(Error::CannotSign(a.resolve_muxed_account(locator, None)?)), } } } From 3ad6b9b482d18f3d035560d2bfe841171c71d65d Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:23:16 -0500 Subject: [PATCH 38/60] Use resolve_muxed_account to get public key --- .../src/commands/contract/arg_parsing.rs | 18 +++++----- cmd/soroban-cli/src/commands/keys/address.rs | 34 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 21fa2f383..3681ccd88 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -14,7 +14,7 @@ use crate::xdr::{ }; use crate::commands::txn_result::TxnResult; -use crate::config::{self}; +use crate::config::{self, address, secret}; use soroban_spec_tools::Spec; #[derive(thiserror::Error, Debug)] @@ -39,6 +39,10 @@ pub enum Error { Xdr(#[from] xdr::Error), #[error(transparent)] StrVal(#[from] soroban_spec_tools::Error), + #[error(transparent)] + Address(#[from] address::Error), + #[error(transparent)] + Secret(#[from] secret::Error), #[error("Missing argument {0}")] MissingArgument(String), #[error("")] @@ -82,16 +86,12 @@ pub fn build_host_function_parameters( if let Some(mut val) = matches_.get_raw(&name) { let mut s = val.next().unwrap().to_string_lossy().to_string(); if matches!(i.type_, ScSpecTypeDef::Address) { - let cmd = crate::commands::keys::address::Cmd { - name: s.clone(), - hd_path: Some(0), - locator: config.locator.clone(), - }; - if let Ok(address) = cmd.public_key() { + let addr: address::Address = s.parse()?; + if let Ok(address) = addr.resolve_muxed_account(&config.locator, None) { s = address.to_string(); } - if let Ok(key) = cmd.private_key() { - signers.push(key); + if let Ok(key) = addr.resolve_secret(&config.locator) { + signers.push(SigningKey::from_bytes(&key.private_key(None)?.0)); } } spec.from_string(&s, &i.type_) diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index d13381b49..145d8c30a 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,8 +1,10 @@ -use crate::commands::config::secret; - -use super::super::config::locator; use clap::arg; +use crate::{ + commands::config::{address, locator, secret}, + xdr, +}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] @@ -13,13 +15,16 @@ pub enum Error { #[error(transparent)] StrKey(#[from] stellar_strkey::DecodeError), + + #[error(transparent)] + Address(#[from] address::Error), } #[derive(Debug, clap::Parser, Clone)] #[group(skip)] pub struct Cmd { /// Name of identity to lookup, default test identity used if not provided - pub name: String, + pub name: address::Address, /// If identity is a seed phrase use this hd path, default is 0 #[arg(long)] @@ -35,20 +40,15 @@ impl Cmd { Ok(()) } - pub fn private_key(&self) -> Result { - Ok(self - .locator - .read_identity(&self.name)? - .key_pair(self.hd_path)?) - } - pub fn public_key(&self) -> Result { - if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) { - Ok(key) - } else { - Ok(stellar_strkey::ed25519::PublicKey::from_payload( - self.private_key()?.verifying_key().as_bytes(), - )?) + match self + .name + .resolve_muxed_account(&self.locator, self.hd_path)? + { + xdr::MuxedAccount::Ed25519(pk) => Ok(stellar_strkey::ed25519::PublicKey(pk.0)), + xdr::MuxedAccount::MuxedEd25519(xdr::MuxedAccountMed25519 { ed25519, .. }) => { + Ok(stellar_strkey::ed25519::PublicKey(ed25519.0)) + } } } } From 9d02b01bda2c67c97951563c8e04d6c5cf3105bf Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:46:05 -0500 Subject: [PATCH 39/60] Clippy --- cmd/soroban-cli/src/config/address.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index b75b89fe2..ff926b60a 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -62,7 +62,9 @@ impl Address { pub fn resolve_secret(&self, locator: &locator::Args) -> Result { match &self { Address::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), - a => Err(Error::CannotSign(a.resolve_muxed_account(locator, None)?)), + a @ Address::MuxedAccount(_) => { + Err(Error::CannotSign(a.resolve_muxed_account(locator, None)?)) + } } } } From a72276dc540e3a98638756e57d96a5d0758a671d Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 4 Dec 2024 12:06:30 -0500 Subject: [PATCH 40/60] fix: Sign tx hash instead of tx env with keychain --- cmd/soroban-cli/src/signer.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index ba9ba8667..099ed6186 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -241,7 +241,7 @@ impl Signer { let decorated_signature = match &self.kind { SignerKind::Local(key) => key.sign_tx_hash(tx_hash)?, SignerKind::Lab => Lab::sign_tx_env(tx_env, network, &self.print)?, - SignerKind::SecureStore(entry) => entry.sign_tx_env(tx_env)?, + SignerKind::SecureStore(entry) => entry.sign_tx_hash(tx_hash)?, }; let mut sigs = signatures.clone().into_vec(); sigs.push(decorated_signature); @@ -297,11 +297,11 @@ pub struct SecureStoreEntry { } impl SecureStoreEntry { - pub fn sign_tx_env(&self, tx_env: &TransactionEnvelope) -> Result { + pub fn sign_tx_hash(&self, tx_hash: [u8; 32]) -> Result { let entry = StellarEntry::new(&self.name)?; - let signed_tx_env = entry.sign_data(tx_env.to_xdr_base64(Limits::none())?.as_bytes())?; let hint = SignatureHint(entry.get_public_key()?.0[28..].try_into()?); - let signature = Signature(signed_tx_env.clone().try_into()?); + let signed_tx_hash = entry.sign_data(&tx_hash)?; + let signature = Signature(signed_tx_hash.clone().try_into()?); Ok(DecoratedSignature { hint, signature }) } } From 9226b1b85a009f16b2567f214239ce7962cf9cc5 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 5 Dec 2024 09:43:00 -0500 Subject: [PATCH 41/60] fix: fmt --- cmd/soroban-cli/src/commands/tx/new/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/tx/new/mod.rs b/cmd/soroban-cli/src/commands/tx/new/mod.rs index 58d2b4a3d..c00d01220 100644 --- a/cmd/soroban-cli/src/commands/tx/new/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/new/mod.rs @@ -67,7 +67,6 @@ impl Cmd { Cmd::Payment(cmd) => cmd.tx.handle_and_print(op, global_args).await, Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(op, global_args).await, Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(op, global_args).await, - }?; Ok(()) } From 3a25564ab6dadaf73f4613e9d75d8162efe5412d Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 5 Dec 2024 11:47:59 -0500 Subject: [PATCH 42/60] fix: update to work with `op add` --- cmd/soroban-cli/src/commands/tx/mod.rs | 2 - .../src/commands/tx/new/account_merge.rs | 2 +- .../src/commands/tx/new/bump_sequence.rs | 6 +-- .../src/commands/tx/new/change_trust.rs | 8 ++-- .../src/commands/tx/new/create_account.rs | 4 +- .../src/commands/tx/new/manage_data.rs | 8 ++-- .../src/commands/tx/new/payment.rs | 6 +-- .../src/commands/tx/new/set_options.rs | 4 +- .../src/commands/tx/op/add/account_merge.rs | 10 +---- .../src/commands/tx/op/add/bump_sequence.rs | 10 +---- .../src/commands/tx/op/add/change_trust.rs | 10 +---- .../src/commands/tx/op/add/create_account.rs | 10 +---- .../src/commands/tx/op/add/manage_data.rs | 10 +---- cmd/soroban-cli/src/commands/tx/op/add/mod.rs | 43 +++++++++++++------ .../src/commands/tx/op/add/payment.rs | 10 +---- .../src/commands/tx/op/add/set_options.rs | 10 +---- .../commands/tx/op/add/set_trustline_flags.rs | 10 +---- 17 files changed, 67 insertions(+), 96 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index 7ea08dea1..02be68bf0 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -43,8 +43,6 @@ pub enum Error { #[error(transparent)] Sign(#[from] sign::Error), #[error(transparent)] - Send(#[from] send::Error), - #[error(transparent)] Args(#[from] args::Error), #[error(transparent)] Simulate(#[from] simulate::Error), diff --git a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs index 9b82f0247..e52e1fc42 100644 --- a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs +++ b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs @@ -22,7 +22,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::AccountMerge( - cmd.tx.reslove_muxed_address(&cmd.account)?, + cmd.tx.reslove_muxed_address(&cmd.op.account)?, )) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs b/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs index ff04e96a0..96062bba2 100644 --- a/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs +++ b/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs @@ -18,10 +18,10 @@ pub struct Args { pub bump_to: i64, } -impl From<&Args> for xdr::OperationBody { - fn from(cmd: &Args) -> Self { +impl From<&Cmd> for xdr::OperationBody { + fn from(cmd: &Cmd) -> Self { xdr::OperationBody::BumpSequence(xdr::BumpSequenceOp { - bump_to: cmd.bump_to.into(), + bump_to: cmd.op.bump_to.into(), }) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs index 2013db75b..04f17e87e 100644 --- a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs +++ b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs @@ -20,16 +20,16 @@ pub struct Args { pub limit: i64, } -impl From<&Args> for xdr::OperationBody { - fn from(cmd: &Args) -> Self { - let line = match cmd.line.0.clone() { +impl From<&Cmd> for xdr::OperationBody { + fn from(cmd: &Cmd) -> Self { + let line = match cmd.op.line.0.clone() { xdr::Asset::CreditAlphanum4(asset) => xdr::ChangeTrustAsset::CreditAlphanum4(asset), xdr::Asset::CreditAlphanum12(asset) => xdr::ChangeTrustAsset::CreditAlphanum12(asset), xdr::Asset::Native => xdr::ChangeTrustAsset::Native, }; xdr::OperationBody::ChangeTrust(xdr::ChangeTrustOp { line, - limit: cmd.limit, + limit: cmd.op.limit, }) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index efbafcc73..d062a07d5 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -25,8 +25,8 @@ impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { - destination: cmd.tx.reslove_account_id(&cmd.destination)?, - starting_balance: cmd.starting_balance.into(), + destination: cmd.tx.reslove_account_id(&cmd.op.destination)?, + starting_balance: cmd.op.starting_balance.into(), })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs index 30e9a36fd..672d8f66e 100644 --- a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs +++ b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs @@ -25,10 +25,10 @@ pub struct Args { pub data_value: Option>, } -impl From<&Args> for xdr::OperationBody { - fn from(cmd: &Args) -> Self { - let data_value = cmd.data_value.clone().map(Into::into); - let data_name = cmd.data_name.clone().into(); +impl From<&Cmd> for xdr::OperationBody { + fn from(cmd: &Cmd) -> Self { + let data_value = cmd.op.data_value.clone().map(Into::into); + let data_name = cmd.op.data_name.clone().into(); xdr::OperationBody::ManageData(xdr::ManageDataOp { data_name, data_value, diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 03d137cdc..4b472e141 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -28,9 +28,9 @@ impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::Payment(xdr::PaymentOp { - destination: cmd.tx.reslove_muxed_address(&cmd.destination)?, - asset: cmd.asset.clone().into(), - amount: cmd.amount.into(), + destination: cmd.tx.reslove_muxed_address(&cmd.op.destination)?, + asset: cmd.op.asset.clone().into(), + amount: cmd.op.amount.into(), })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/set_options.rs b/cmd/soroban-cli/src/commands/tx/new/set_options.rs index 272a1689b..42a0767b5 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_options.rs @@ -70,10 +70,12 @@ pub struct Args { impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { + let tx = &cmd.tx; let mut set_flags = None; let mut set_flag = |flag: xdr::AccountFlags| { *set_flags.get_or_insert(0) |= flag as u32; }; + let cmd = &cmd.op; if cmd.set_required { set_flag(xdr::AccountFlags::RequiredFlag); @@ -118,7 +120,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { let inflation_dest: Option = cmd .inflation_dest .as_ref() - .map(|dest| cmd.tx.reslove_account_id(dest)) + .map(|dest| tx.reslove_account_id(dest)) .transpose()?; Ok(xdr::OperationBody::SetOptions(xdr::SetOptionsOp { inflation_dest, diff --git a/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs b/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs index bd643c199..cf274fd67 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::account_merge::Args, + pub op: super::new::account_merge::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs b/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs index 907d8d2d6..640b748b3 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::bump_sequence::Args, + pub op: super::new::bump_sequence::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs b/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs index af9afae1b..5647e4cec 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::change_trust::Args, + pub op: super::new::change_trust::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs b/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs index e30ff20a1..1ca978e0f 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::create_account::Args, + pub op: super::new::create_account::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs b/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs index 962233a84..5758478c3 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::manage_data::Args, + pub op: super::new::manage_data::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs index b94fc74ce..d8860c1fc 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs @@ -1,7 +1,5 @@ -use clap::Parser; - use super::super::{global, help, xdr::tx_envelope_from_stdin}; -use crate::xdr::WriteXdr; +use crate::xdr::{OperationBody, WriteXdr}; pub(crate) use super::super::{new, xdr}; @@ -15,7 +13,7 @@ mod payment; mod set_options; mod set_trustline_flags; -#[derive(Debug, Parser)] +#[derive(Debug, clap::Parser)] #[allow(clippy::doc_markdown)] pub enum Cmd { #[command(about = help::ACCOUNT_MERGE)] @@ -44,20 +42,41 @@ pub enum Error { TxXdr(#[from] super::super::xdr::Error), #[error(transparent)] Xdr(#[from] crate::xdr::Error), + #[error(transparent)] + New(#[from] super::super::new::Error), + #[error(transparent)] + Tx(#[from] super::super::args::Error), +} + +impl TryFrom<&Cmd> for OperationBody { + type Error = super::super::new::Error; + fn try_from(cmd: &Cmd) -> Result { + Ok(match &cmd { + Cmd::AccountMerge(account_merge::Cmd { op, .. }) => op.try_into()?, + Cmd::BumpSequence(bump_sequence::Cmd { op, .. }) => op.into(), + Cmd::ChangeTrust(change_trust::Cmd { op, .. }) => op.into(), + Cmd::CreateAccount(create_account::Cmd { op, .. }) => op.try_into()?, + Cmd::ManageData(manage_data::Cmd { op, .. }) => op.into(), + Cmd::Payment(payment::Cmd { op, .. }) => op.try_into()?, + Cmd::SetOptions(set_options::Cmd { op, .. }) => op.try_into()?, + Cmd::SetTrustlineFlags(set_trustline_flags::Cmd { op, .. }) => op.try_into()?, + }) + } } impl Cmd { pub fn run(&self, _: &global::Args) -> Result<(), Error> { let tx_env = tx_envelope_from_stdin()?; + let op = OperationBody::try_from(self)?; let res = match self { - Cmd::AccountMerge(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::BumpSequence(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::ChangeTrust(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::CreateAccount(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::ManageData(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::Payment(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::SetOptions(cmd) => cmd.args.add_op(&cmd.op, tx_env), - Cmd::SetTrustlineFlags(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::AccountMerge(cmd) => cmd.args.add_op(op, tx_env), + Cmd::BumpSequence(cmd) => cmd.args.add_op(op, tx_env), + Cmd::ChangeTrust(cmd) => cmd.args.add_op(op, tx_env), + Cmd::CreateAccount(cmd) => cmd.args.add_op(op, tx_env), + Cmd::ManageData(cmd) => cmd.args.add_op(op, tx_env), + Cmd::Payment(cmd) => cmd.args.add_op(op, tx_env), + Cmd::SetOptions(cmd) => cmd.args.add_op(op, tx_env), + Cmd::SetTrustlineFlags(cmd) => cmd.args.add_op(op, tx_env), }?; println!("{}", res.to_xdr_base64(crate::xdr::Limits::none())?); Ok(()) diff --git a/cmd/soroban-cli/src/commands/tx/op/add/payment.rs b/cmd/soroban-cli/src/commands/tx/op/add/payment.rs index d8146c91a..f5f9c5fcc 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/payment.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::payment::Args, + pub op: super::new::payment::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs b/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs index 75b43124a..88323f57c 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::set_options::Args, + pub op: super::new::set_options::Cmd, } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs index 8ffee7a7b..09ee11607 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs @@ -1,14 +1,8 @@ -use clap::{command, Parser}; - -use std::fmt::Debug; - -use super::new; - -#[derive(Parser, Debug, Clone)] +#[derive(clap::Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub args: super::args::Args, #[command(flatten)] - pub op: new::set_trustline_flags::Args, + pub op: super::new::set_trustline_flags::Cmd, } From 5f55e7c642a8ae28294c06ed14ba4aa548e55796 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 5 Dec 2024 12:25:34 -0500 Subject: [PATCH 43/60] fix: simplify op::add::args::Args Should fix issue with multiple locators --- cmd/soroban-cli/src/commands/tx/args.rs | 20 +++++++++++++ cmd/soroban-cli/src/commands/tx/mod.rs | 2 -- .../src/commands/tx/op/add/args.rs | 30 +++---------------- cmd/soroban-cli/src/commands/tx/op/add/mod.rs | 20 ++++++------- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index c703ead6b..23702f4f2 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -11,6 +11,7 @@ use crate::{ xdr::{self, Limits, WriteXdr}, }; + #[derive(Debug, clap::Args, Clone)] #[group(skip)] pub struct Args { @@ -38,6 +39,8 @@ pub enum Error { Xdr(#[from] xdr::Error), #[error(transparent)] Address(#[from] address::Error), + #[error(transparent)] + TxXdr(#[from] super::xdr::Error), } impl Args { @@ -120,4 +123,21 @@ impl Args { .resolve_muxed_account(&self.config.locator, self.config.hd_path)? .account_id()) } + + + pub fn add_op( + &self, + op_body: impl Into, + tx_env: xdr::TransactionEnvelope, + op_source: Option<&address::Address>, + ) -> Result { + let source_account = op_source + .map(|a| self.reslove_muxed_address(a)) + .transpose()?; + let op = xdr::Operation { + source_account, + body: op_body.into(), + }; + Ok(super::xdr::add_op(tx_env, op)?) + } } diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index 02be68bf0..d9fd79faf 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -43,8 +43,6 @@ pub enum Error { #[error(transparent)] Sign(#[from] sign::Error), #[error(transparent)] - Args(#[from] args::Error), - #[error(transparent)] Simulate(#[from] simulate::Error), } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/args.rs b/cmd/soroban-cli/src/commands/tx/op/add/args.rs index f1858e0b0..9d9b4931b 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/args.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/args.rs @@ -1,22 +1,8 @@ -use super::xdr::add_op; -use crate::{ - config::{address, locator}, - xdr, -}; - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - Address(#[from] address::Error), - #[error(transparent)] - TxXdr(#[from] super::xdr::Error), -} +use crate::{commands::tx, config::address, xdr}; #[derive(Debug, clap::Args, Clone)] #[group(skip)] pub struct Args { - #[clap(flatten)] - pub locator: locator::Args, /// Source account used for the operation #[arg( long, @@ -31,16 +17,8 @@ impl Args { &self, op_body: impl Into, tx_env: xdr::TransactionEnvelope, - ) -> Result { - let source_account = self - .operation_source_account - .as_ref() - .map(|a| a.resolve_muxed_account(&self.locator, None)) - .transpose()?; - let op = xdr::Operation { - source_account, - body: op_body.into(), - }; - Ok(add_op(tx_env, op)?) + tx: &tx::args::Args, + ) -> Result { + tx.add_op(op_body, tx_env, self.operation_source_account.as_ref()) } } diff --git a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs index d8860c1fc..5e69cf168 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs @@ -1,7 +1,7 @@ use super::super::{global, help, xdr::tx_envelope_from_stdin}; use crate::xdr::{OperationBody, WriteXdr}; -pub(crate) use super::super::{new, xdr}; +pub(crate) use super::super::new; mod account_merge; mod args; @@ -36,8 +36,6 @@ pub enum Cmd { #[derive(thiserror::Error, Debug)] pub enum Error { - #[error(transparent)] - Args(#[from] args::Error), #[error(transparent)] TxXdr(#[from] super::super::xdr::Error), #[error(transparent)] @@ -69,14 +67,14 @@ impl Cmd { let tx_env = tx_envelope_from_stdin()?; let op = OperationBody::try_from(self)?; let res = match self { - Cmd::AccountMerge(cmd) => cmd.args.add_op(op, tx_env), - Cmd::BumpSequence(cmd) => cmd.args.add_op(op, tx_env), - Cmd::ChangeTrust(cmd) => cmd.args.add_op(op, tx_env), - Cmd::CreateAccount(cmd) => cmd.args.add_op(op, tx_env), - Cmd::ManageData(cmd) => cmd.args.add_op(op, tx_env), - Cmd::Payment(cmd) => cmd.args.add_op(op, tx_env), - Cmd::SetOptions(cmd) => cmd.args.add_op(op, tx_env), - Cmd::SetTrustlineFlags(cmd) => cmd.args.add_op(op, tx_env), + Cmd::AccountMerge(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::BumpSequence(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::ChangeTrust(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::CreateAccount(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::ManageData(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::Payment(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::SetOptions(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), + Cmd::SetTrustlineFlags(cmd) => cmd.args.add_op(op, tx_env, &cmd.op.tx), }?; println!("{}", res.to_xdr_base64(crate::xdr::Limits::none())?); Ok(()) From 0e7f08f12a675a6806d3ee8a56c5f8bbb024d303 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 5 Dec 2024 12:53:44 -0500 Subject: [PATCH 44/60] fix: remove untagged and use rename to keep same serialized output --- cmd/soroban-cli/src/commands/tx/args.rs | 2 - cmd/soroban-cli/src/commands/tx/mod.rs | 2 + cmd/soroban-cli/src/config/key.rs | 57 ++++++++++++++++--------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index 23702f4f2..c00da6fea 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -11,7 +11,6 @@ use crate::{ xdr::{self, Limits, WriteXdr}, }; - #[derive(Debug, clap::Args, Clone)] #[group(skip)] pub struct Args { @@ -124,7 +123,6 @@ impl Args { .account_id()) } - pub fn add_op( &self, op_body: impl Into, diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index d9fd79faf..02be68bf0 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -43,6 +43,8 @@ pub enum Error { #[error(transparent)] Sign(#[from] sign::Error), #[error(transparent)] + Args(#[from] args::Error), + #[error(transparent)] Simulate(#[from] simulate::Error), } diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs index dcb96775b..dab9d8ac9 100644 --- a/cmd/soroban-cli/src/config/key.rs +++ b/cmd/soroban-cli/src/config/key.rs @@ -18,23 +18,24 @@ pub enum Error { } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(untagged)] pub enum Key { + #[serde(rename = "public_key")] + PublicKey(Public), + #[serde(rename = "muxed_account")] + MuxedAccount(MuxedAccount), + #[serde(untagged)] Secret(Secret), - PublicKey { public_key: Public }, - MuxedAccount { muxed_account: MuxedAccount }, } impl Key { pub fn public_key(&self, hd_path: Option) -> Result { let bytes = match self { Key::Secret(secret) => secret.public_key(hd_path)?.0, - Key::PublicKey { - public_key: Public(key), - } => key.0, - Key::MuxedAccount { - muxed_account: MuxedAccount(stellar_strkey::ed25519::MuxedAccount { ed25519, id }), - } => { + Key::PublicKey(Public(key)) => key.0, + Key::MuxedAccount(MuxedAccount(stellar_strkey::ed25519::MuxedAccount { + ed25519, + id, + })) => { return Ok(xdr::MuxedAccount::MuxedEd25519(xdr::MuxedAccountMed25519 { ed25519: xdr::Uint256(*ed25519), id: *id, @@ -63,10 +64,10 @@ impl FromStr for Key { return Ok(Key::Secret(secret)); } if let Ok(public_key) = s.parse() { - return Ok(Key::PublicKey { public_key }); + return Ok(Key::PublicKey(public_key)); } if let Ok(muxed_account) = s.parse() { - return Ok(Key::MuxedAccount { muxed_account }); + return Ok(Key::MuxedAccount(muxed_account)); } Err(Error::Parse) } @@ -74,9 +75,7 @@ impl FromStr for Key { impl From for Key { fn from(value: stellar_strkey::ed25519::PublicKey) -> Self { - Key::PublicKey { - public_key: Public(value), - } + Key::PublicKey(Public(value)) } } @@ -135,14 +134,34 @@ impl Display for MuxedAccount { mod test { use super::*; - #[test] - fn public_key() { - let key = Key::PublicKey { - public_key: Public(stellar_strkey::ed25519::PublicKey([0; 32])), - }; + fn round_trip(key: Key) { let serialized = toml::to_string(&key).unwrap(); println!("{serialized}"); let deserialized: Key = toml::from_str(&serialized).unwrap(); assert_eq!(key, deserialized); } + + #[test] + fn public_key() { + let key = Key::PublicKey(Public(stellar_strkey::ed25519::PublicKey([0; 32]))); + round_trip(key); + } + #[test] + fn muxed_key() { + let key: stellar_strkey::ed25519::MuxedAccount = + "MA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAAAAAAAAAPCICBKU" + .parse() + .unwrap(); + let key = Key::MuxedAccount(MuxedAccount(key)); + round_trip(key); + } + #[test] + fn secret_key() { + let secret_key = stellar_strkey::ed25519::PrivateKey([0; 32]); + let secret = Secret::SecretKey { + secret_key: secret_key.to_string(), + }; + let key = Key::Secret(secret); + round_trip(key); + } } From aa8bb16d7824ee5d8ee8b971fcceadd08e7f28ea Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 5 Dec 2024 13:14:11 -0500 Subject: [PATCH 45/60] fix: docs and clippy in tests --- FULL_HELP_DOCS.md | 140 ++++++++++++++++++++++++++---- cmd/soroban-cli/src/config/key.rs | 23 +++-- 2 files changed, 136 insertions(+), 27 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 975845c0b..e453b53d8 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1536,7 +1536,7 @@ Transfers the XLM balance of an account to another account and removes the sourc * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' or alias +* `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' @@ -1825,13 +1825,26 @@ https://developers.stellar.org/docs/learn/glossary#flags Transfers the XLM balance of an account to another account and removes the source account from the ledger -**Usage:** `stellar tx operation add account-merge [OPTIONS] --account ` +**Usage:** `stellar tx operation add account-merge [OPTIONS] --source-account --account ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' @@ -1840,13 +1853,26 @@ Transfers the XLM balance of an account to another account and removes the sourc Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number -**Usage:** `stellar tx operation add bump-sequence [OPTIONS] --bump-to ` +**Usage:** `stellar tx operation add bump-sequence [OPTIONS] --source-account --bump-to ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--bump-to ` — Sequence number to bump to @@ -1857,13 +1883,26 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines -**Usage:** `stellar tx operation add change-trust [OPTIONS] --line ` +**Usage:** `stellar tx operation add change-trust [OPTIONS] --source-account --line ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--line ` * `--limit ` — Limit for the trust line, 0 to remove the trust line @@ -1875,13 +1914,26 @@ https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/a Creates and funds a new account with the specified starting balance -**Usage:** `stellar tx operation add create-account [OPTIONS] --destination ` +**Usage:** `stellar tx operation add create-account [OPTIONS] --source-account --destination ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--destination ` — Account Id to create, e.g. `GBX...` * `--starting-balance ` — Initial balance in stroops of the account, default 1 XLM @@ -1895,13 +1947,26 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries -**Usage:** `stellar tx operation add manage-data [OPTIONS] --data-name ` +**Usage:** `stellar tx operation add manage-data [OPTIONS] --source-account --data-name ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--data-name ` — String up to 64 bytes long. If this is a new Name it will add the given name/value pair to the account. If this Name is already present then the associated value will be modified * `--data-value ` — Up to 64 bytes long hex string If not present then the existing Name will be deleted. If present then this value will be set in the `DataEntry` @@ -1911,13 +1976,26 @@ https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/a Sends an amount in a specific asset to a destination account -**Usage:** `stellar tx operation add payment [OPTIONS] --destination --amount ` +**Usage:** `stellar tx operation add payment [OPTIONS] --source-account --destination --amount ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--destination ` — Account to send to, e.g. `GBX...` * `--asset ` — Asset to send, default native, e.i. XLM @@ -1936,13 +2014,26 @@ https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig -**Usage:** `stellar tx operation add set-options [OPTIONS]` +**Usage:** `stellar tx operation add set-options [OPTIONS] --source-account ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation * `--inflation-dest ` — Account of the inflation destination * `--master-weight ` — A number from 0-255 (inclusive) representing the weight of the master key. If the weight of the master key is updated to 0, it is effectively disabled * `--low-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a low threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig @@ -1970,14 +2061,27 @@ If you are modifying a trustline to a pool share, however, this is composed of t Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags -**Usage:** `stellar tx operation add set-trustline-flags [OPTIONS] --trustor --asset ` +**Usage:** `stellar tx operation add set-trustline-flags [OPTIONS] --source-account --trustor --asset ` ###### **Options:** +* `--operation-source-account ` — Source account used for the operation +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` +* `--cost` — Output the cost execution to stderr +* `--instructions ` — Number of instructions to simulate +* `--build-only` — Build the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--operation-source-account ` — Source account used for the operation -* `--trustor ` — Account to set trustline flags for +* `--trustor ` — Account to set trustline flags for, e.g. `GBX...`, or alias, or muxed account, `M123...`` * `--asset ` — Asset to set trustline flags for * `--set-authorize` — Signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders * `--set-authorize-to-maintain-liabilities` — Denotes limited authorization that allows an account to maintain current orders but not to otherwise transact with the asset diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs index dab9d8ac9..cecb83522 100644 --- a/cmd/soroban-cli/src/config/key.rs +++ b/cmd/soroban-cli/src/config/key.rs @@ -134,17 +134,17 @@ impl Display for MuxedAccount { mod test { use super::*; - fn round_trip(key: Key) { + fn round_trip(key: &Key) { let serialized = toml::to_string(&key).unwrap(); println!("{serialized}"); let deserialized: Key = toml::from_str(&serialized).unwrap(); - assert_eq!(key, deserialized); + assert_eq!(key, &deserialized); } #[test] fn public_key() { let key = Key::PublicKey(Public(stellar_strkey::ed25519::PublicKey([0; 32]))); - round_trip(key); + round_trip(&key); } #[test] fn muxed_key() { @@ -153,15 +153,20 @@ mod test { .parse() .unwrap(); let key = Key::MuxedAccount(MuxedAccount(key)); - round_trip(key); + round_trip(&key); } #[test] fn secret_key() { - let secret_key = stellar_strkey::ed25519::PrivateKey([0; 32]); - let secret = Secret::SecretKey { - secret_key: secret_key.to_string(), - }; + let secret_key = stellar_strkey::ed25519::PrivateKey([0; 32]).to_string(); + let secret = Secret::SecretKey { secret_key }; + let key = Key::Secret(secret); + round_trip(&key); + } + #[test] + fn secret_seed_phrase() { + let seed_phrase = "singer swing mango apple singer swing mango apple singer swing mango apple singer swing mango apple".to_string(); + let secret = Secret::SeedPhrase { seed_phrase }; let key = Key::Secret(secret); - round_trip(key); + round_trip(&key); } } From 428863026466e0f581dcbb4bbbd932d0e417c121 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:19:01 -0500 Subject: [PATCH 46/60] Remove unused bin/secret --- cmd/soroban-cli/Cargo.toml | 4 ---- cmd/soroban-cli/src/bin/secret.rs | 17 ----------------- 2 files changed, 21 deletions(-) delete mode 100644 cmd/soroban-cli/src/bin/secret.rs diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 0d6da167d..3d366464b 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -20,10 +20,6 @@ path = "src/bin/stellar.rs" name = "soroban" path = "src/bin/soroban.rs" -[[bin]] -name = "secret" -path = "src/bin/secret.rs" - [package.metadata.binstall] pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ version }-{ target }{ archive-suffix }" bin-dir = "{ bin }{ binary-ext }" diff --git a/cmd/soroban-cli/src/bin/secret.rs b/cmd/soroban-cli/src/bin/secret.rs deleted file mode 100644 index 4fc43ec6e..000000000 --- a/cmd/soroban-cli/src/bin/secret.rs +++ /dev/null @@ -1,17 +0,0 @@ -use soroban_cli::signer::keyring::StellarEntry; - -fn main() { - let entry = StellarEntry::new("test").unwrap(); - if let Ok(key) = entry.get_public_key() { - println!("{key}"); - return; - }; - - let secret = soroban_cli::config::secret::Secret::from_seed(None).unwrap(); - let pub_key = secret.public_key(None).unwrap(); - let key_pair = secret.key_pair(None).unwrap(); - entry.set_password(key_pair.as_bytes()).unwrap(); - let pub_key_2 = entry.get_public_key().unwrap(); - assert_eq!(pub_key, pub_key_2); - println!("{pub_key} == {pub_key_2}"); -} From 64cd37b6771367041ed37a459e014c799405f355 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 13 Dec 2024 14:54:28 -0500 Subject: [PATCH 47/60] Apply suggestions from code review Co-authored-by: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> --- cmd/soroban-cli/src/commands/tx/args.rs | 4 ++-- cmd/soroban-cli/src/config/locator.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index c00da6fea..8c0ebb387 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -113,11 +113,11 @@ impl Args { Ok(self.config.source_account()?) } - pub fn reslove_muxed_address(&self, address: &Address) -> Result { + pub fn resolve_muxed_address(&self, address: &Address) -> Result { Ok(address.resolve_muxed_account(&self.config.locator, self.config.hd_path)?) } - pub fn reslove_account_id(&self, address: &Address) -> Result { + pub fn resolve_account_id(&self, address: &Address) -> Result { Ok(address .resolve_muxed_account(&self.config.locator, self.config.hd_path)? .account_id()) diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 68a95f628..930da0ece 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -257,7 +257,7 @@ impl Args { } } - pub fn get_private_key(&self, key_or_name: &str) -> Result { + pub fn get_secret_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())), From d4ba93d1dbd902826b76be9b8b50cfe828926337 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 13 Dec 2024 14:58:48 -0500 Subject: [PATCH 48/60] Update cmd/soroban-cli/src/config/locator.rs Co-authored-by: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> --- cmd/soroban-cli/src/config/locator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 930da0ece..e769f1314 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -179,7 +179,7 @@ impl Args { self.write_key(name, &public_key.into()) } - pub fn write_key(&self, name: &str, public_key: &Key) -> Result<(), Error> { + pub fn write_key(&self, name: &str, key: &Key) -> Result<(), Error> { KeyType::Identity.write(name, public_key, &self.config_dir()?) } From 318f579b29c11fdee15d5ed305759b3c69b276ee Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 13 Dec 2024 15:03:50 -0500 Subject: [PATCH 49/60] fix: refactor with renames from PR --- cmd/soroban-cli/src/commands/tx/args.rs | 2 +- cmd/soroban-cli/src/commands/tx/new/account_merge.rs | 2 +- cmd/soroban-cli/src/commands/tx/new/create_account.rs | 2 +- cmd/soroban-cli/src/commands/tx/new/payment.rs | 2 +- cmd/soroban-cli/src/commands/tx/new/set_options.rs | 2 +- cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs | 2 +- cmd/soroban-cli/src/config/address.rs | 2 +- cmd/soroban-cli/src/config/locator.rs | 2 +- cmd/soroban-cli/src/config/sign_with.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index 8c0ebb387..5d2099d26 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -130,7 +130,7 @@ impl Args { op_source: Option<&address::Address>, ) -> Result { let source_account = op_source - .map(|a| self.reslove_muxed_address(a)) + .map(|a| self.resolve_muxed_address(a)) .transpose()?; let op = xdr::Operation { source_account, diff --git a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs index e52e1fc42..c087c6b13 100644 --- a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs +++ b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs @@ -22,7 +22,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::AccountMerge( - cmd.tx.reslove_muxed_address(&cmd.op.account)?, + cmd.tx.resolve_muxed_address(&cmd.op.account)?, )) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index d062a07d5..13bcac4d4 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -25,7 +25,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { - destination: cmd.tx.reslove_account_id(&cmd.op.destination)?, + destination: cmd.tx.resolve_account_id(&cmd.op.destination)?, starting_balance: cmd.op.starting_balance.into(), })) } diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 4b472e141..3599d7010 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -28,7 +28,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; fn try_from(cmd: &Cmd) -> Result { Ok(xdr::OperationBody::Payment(xdr::PaymentOp { - destination: cmd.tx.reslove_muxed_address(&cmd.op.destination)?, + destination: cmd.tx.resolve_muxed_address(&cmd.op.destination)?, asset: cmd.op.asset.clone().into(), amount: cmd.op.amount.into(), })) diff --git a/cmd/soroban-cli/src/commands/tx/new/set_options.rs b/cmd/soroban-cli/src/commands/tx/new/set_options.rs index 42a0767b5..cf38bf574 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_options.rs @@ -120,7 +120,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { let inflation_dest: Option = cmd .inflation_dest .as_ref() - .map(|dest| tx.reslove_account_id(dest)) + .map(|dest| tx.resolve_account_id(dest)) .transpose()?; Ok(xdr::OperationBody::SetOptions(xdr::SetOptionsOp { inflation_dest, diff --git a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs index 3e6465115..7a175915e 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs @@ -68,7 +68,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { Ok(xdr::OperationBody::SetTrustLineFlags( xdr::SetTrustLineFlagsOp { - trustor: cmd.tx.reslove_account_id(&cmd.op.trustor)?, + trustor: cmd.tx.resolve_account_id(&cmd.op.trustor)?, asset: cmd.op.asset.clone().into(), clear_flags, set_flags, diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index ac2adc762..6975d9e53 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -54,7 +54,7 @@ impl Address { pub fn resolve_secret(&self, locator: &locator::Args) -> Result { match &self { - Address::AliasOrSecret(alias) => Ok(locator.get_private_key(alias)?), + Address::AliasOrSecret(alias) => Ok(locator.get_secret_key(alias)?), Address::MuxedAccount(muxed_account) => Err(Error::CannotSign(muxed_account.clone())), } } diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index e769f1314..4ab698111 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -180,7 +180,7 @@ impl Args { } pub fn write_key(&self, name: &str, key: &Key) -> Result<(), Error> { - KeyType::Identity.write(name, public_key, &self.config_dir()?) + KeyType::Identity.write(name, key, &self.config_dir()?) } pub fn write_network(&self, name: &str, network: &Network) -> Result<(), Error> { diff --git a/cmd/soroban-cli/src/config/sign_with.rs b/cmd/soroban-cli/src/config/sign_with.rs index c9d164914..baac7a528 100644 --- a/cmd/soroban-cli/src/config/sign_with.rs +++ b/cmd/soroban-cli/src/config/sign_with.rs @@ -64,7 +64,7 @@ impl Args { } } else { let key_or_name = self.sign_with_key.as_deref().ok_or(Error::NoSignWithKey)?; - let secret = locator.get_private_key(key_or_name)?; + let secret = locator.get_secret_key(key_or_name)?; secret.signer(self.hd_path, print)? }; Ok(signer.sign_tx_env(tx, network)?) From 24269ce1db89b88ace0bff395e0f0d105606f106 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:34:55 -0500 Subject: [PATCH 50/60] Fix after merging with main --- cmd/soroban-cli/src/commands/keys/address.rs | 28 +++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index 145d8c30a..aa5a2940d 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,9 +1,6 @@ use clap::arg; -use crate::{ - commands::config::{address, locator, secret}, - xdr, -}; +use crate::commands::config::{address, locator, secret}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -24,7 +21,7 @@ pub enum Error { #[group(skip)] pub struct Cmd { /// Name of identity to lookup, default test identity used if not provided - pub name: address::Address, + pub name: String, /// If identity is a seed phrase use this hd path, default is 0 #[arg(long)] @@ -40,15 +37,20 @@ impl Cmd { Ok(()) } + pub fn private_key(&self) -> Result { + Ok(self + .locator + .read_identity(&self.name)? + .key_pair(self.hd_path)?) + } + pub fn public_key(&self) -> Result { - match self - .name - .resolve_muxed_account(&self.locator, self.hd_path)? - { - xdr::MuxedAccount::Ed25519(pk) => Ok(stellar_strkey::ed25519::PublicKey(pk.0)), - xdr::MuxedAccount::MuxedEd25519(xdr::MuxedAccountMed25519 { ed25519, .. }) => { - Ok(stellar_strkey::ed25519::PublicKey(ed25519.0)) - } + if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) { + Ok(key) + } else { + Ok(stellar_strkey::ed25519::PublicKey::from_payload( + self.private_key()?.verifying_key().as_bytes(), + )?) } } } From e95fa3a38b53cfb09045f70de0adc6c91c09773d Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:59:25 -0500 Subject: [PATCH 51/60] Apply suggestion from code review Co-authored-by: Willem Wyndham --- cmd/soroban-cli/src/signer/keyring.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index b5a63a398..4e6b19c99 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -31,7 +31,7 @@ impl StellarEntry { Ok(()) } - pub fn get_password(&self) -> Result, Error> { + fn get_password(&self) -> Result, Error> { Ok(base64.decode(self.keyring.get_password()?)?) } From 95d8b329a233b0fb7be7e74cb1daebe47b2c78d6 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 23 Dec 2024 09:47:44 -0500 Subject: [PATCH 52/60] Limit key name length --- cmd/soroban-cli/src/config/address.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 36cc90f42..dadd8853f 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -28,7 +28,11 @@ pub enum Error { Secret(#[from] secret::Error), #[error("Address cannot be used to sign {0}")] CannotSign(xdr::MuxedAccount), - #[error("Invalid key name: {0}\n only alphanumeric characters, `_`and `-` are allowed")] + #[error("Invalid key name: {0}\n only alphanumeric characters, underscores (_), and hyphens (-) are allowed.")] + InvalidKeyNameCharacters(String), + #[error("Invalid key name: {0}\n keys cannot exceed 250 characters")] + InvalidKeyNameLength(String), + #[error("Invalid key name: {0}\n keys cannot be the word \"ledger\"")] InvalidKeyName(String), } @@ -93,11 +97,14 @@ impl std::str::FromStr for KeyName { type Err = Error; fn from_str(s: &str) -> Result { if !s.chars().all(allowed_char) { - return Err(Error::InvalidKeyName(s.to_string())); + return Err(Error::InvalidKeyNameCharacters(s.to_string())); } if s == "ledger" { return Err(Error::InvalidKeyName(s.to_string())); } + if s.len() > 250 { + return Err(Error::InvalidKeyNameLength(s.to_string())); + } Ok(KeyName(s.to_string())) } } From 01c87538c6e9c79ad32737bead38a82e7591bf68 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:06:36 -0500 Subject: [PATCH 53/60] Update public_key to work with secure storage keys --- cmd/soroban-cli/src/commands/keys/address.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index aa5a2940d..1a7ab21cd 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,6 +1,9 @@ use clap::arg; -use crate::commands::config::{address, locator, secret}; +use crate::{ + commands::config::{address, locator, secret}, + config::UnresolvedMuxedAccount, +}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -47,6 +50,11 @@ impl Cmd { pub fn public_key(&self) -> Result { if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) { Ok(key) + } else if let Ok(unresolved) = self.name.parse::() { + let muxed = unresolved.resolve_muxed_account(&self.locator, self.hd_path)?; + Ok(stellar_strkey::ed25519::PublicKey::from_string( + &muxed.to_string(), + )?) } else { Ok(stellar_strkey::ed25519::PublicKey::from_payload( self.private_key()?.verifying_key().as_bytes(), From 085317fdbfdaf9ca91702d2466ab46128768cfea Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Mon, 6 Jan 2025 16:31:37 -0500 Subject: [PATCH 54/60] fix(address): remove private key function & use unresolved Address This simplifies the lookup of the address. --- .../src/commands/contract/arg_parsing.rs | 7 +---- cmd/soroban-cli/src/commands/keys/address.rs | 29 ++++++------------- cmd/soroban-cli/src/config/address.rs | 2 +- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index b522fc91e..98a6d3004 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -274,10 +274,5 @@ fn resolve_address(addr_or_alias: &str, config: &config::Args) -> Result Option { - let cmd = crate::commands::keys::address::Cmd { - name: addr_or_alias.to_string(), - hd_path: Some(0), - locator: config.locator.clone(), - }; - cmd.private_key().ok() + config.locator.key(addr_or_alias).ok()?.key_pair(None).ok() } diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index 1a7ab21cd..9727988e0 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -24,7 +24,7 @@ pub enum Error { #[group(skip)] pub struct Cmd { /// Name of identity to lookup, default test identity used if not provided - pub name: String, + pub name: UnresolvedMuxedAccount, /// If identity is a seed phrase use this hd path, default is 0 #[arg(long)] @@ -40,25 +40,14 @@ impl Cmd { Ok(()) } - pub fn private_key(&self) -> Result { - Ok(self - .locator - .read_identity(&self.name)? - .key_pair(self.hd_path)?) - } - pub fn public_key(&self) -> Result { - if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) { - Ok(key) - } else if let Ok(unresolved) = self.name.parse::() { - let muxed = unresolved.resolve_muxed_account(&self.locator, self.hd_path)?; - Ok(stellar_strkey::ed25519::PublicKey::from_string( - &muxed.to_string(), - )?) - } else { - Ok(stellar_strkey::ed25519::PublicKey::from_payload( - self.private_key()?.verifying_key().as_bytes(), - )?) - } + let muxed = self + .name + .resolve_muxed_account(&self.locator, self.hd_path)?; + let bytes = match muxed { + soroban_sdk::xdr::MuxedAccount::Ed25519(uint256) => uint256.0, + soroban_sdk::xdr::MuxedAccount::MuxedEd25519(muxed_account) => muxed_account.ed25519.0, + }; + Ok(stellar_strkey::ed25519::PublicKey(bytes)) } } diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index dadd8853f..24a40a62a 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -78,7 +78,7 @@ impl UnresolvedMuxedAccount { UnresolvedMuxedAccount::Resolved(muxed_account) => { Err(Error::CannotSign(muxed_account.clone())) } - UnresolvedMuxedAccount::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), + UnresolvedMuxedAccount::AliasOrSecret(alias) => Ok(locator.key(alias)?), } } } From aecc5ac4c40f6f52c15f51fb4947952aa8b2d597 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 7 Jan 2025 14:18:45 -0500 Subject: [PATCH 55/60] feat: store seedphrase instead of private key This will allow for exporting the phrase later --- cmd/soroban-cli/src/commands/keys/generate.rs | 28 ++--- cmd/soroban-cli/src/config/secret.rs | 38 +++++-- cmd/soroban-cli/src/signer.rs | 5 +- cmd/soroban-cli/src/signer/keyring.rs | 107 ++++++++++-------- 4 files changed, 106 insertions(+), 72 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 1e3727478..8ec0158bb 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -1,4 +1,5 @@ use clap::{arg, command}; +use sep5::SeedPhrase; use super::super::config::{ locator, network, @@ -122,9 +123,7 @@ impl Cmd { fn secret(&self, print: &Print) -> Result { let seed_phrase = self.seed_phrase()?; - Ok(if self.as_secret { - seed_phrase.private_key(self.hd_path)?.into() - } else if self.secure_store { + if self.secure_store { // secure_store:org.stellar.cli: let entry_name_with_prefix = format!( "{}{}-{}", @@ -137,38 +136,41 @@ impl Cmd { let secret: Secret = entry_name_with_prefix.parse()?; if let Secret::SecureStore { entry_name } = &secret { - Self::write_to_secure_store(entry_name, &seed_phrase, print)?; + Self::write_to_secure_store(entry_name, seed_phrase, print)?; } - secret + return Ok(secret); + } + let secret: Secret = seed_phrase.into(); + Ok(if self.as_secret { + secret.private_key(self.hd_path)?.into() } else { - seed_phrase + secret }) } - fn seed_phrase(&self) -> Result { + fn seed_phrase(&self) -> Result { Ok(if self.default_seed { - Secret::test_seed_phrase() + secret::test_seed_phrase() } else { - Secret::from_seed(self.seed.as_deref()) + secret::seed_phrase_from_seed(self.seed.as_deref()) }?) } fn write_to_secure_store( entry_name: &String, - seed_phrase: &Secret, + seed_phrase: SeedPhrase, print: &Print, ) -> Result<(), Error> { print.infoln(format!("Writing to secure store: {entry_name}")); let entry = StellarEntry::new(entry_name)?; - if let Ok(key) = entry.get_public_key() { + if let Ok(key) = entry.get_public_key(None) { print.warnln(format!("A key for {entry_name} already exists in your operating system's secure store: {key}")); } else { print.infoln(format!( "Saving a new key to your operating system's secure store: {entry_name}" )); - let key_pair = seed_phrase.key_pair(None)?; - entry.set_password(key_pair.as_bytes())?; + entry.set_seed_phrase(seed_phrase)?; } Ok(()) } diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 8f4b20c60..f32b291e8 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -1,6 +1,8 @@ use clap::arg; use serde::{Deserialize, Serialize}; use std::{io::Write, str::FromStr}; + +use sep5::SeedPhrase; use stellar_strkey::ed25519::{PrivateKey, PublicKey}; use crate::{ @@ -94,6 +96,14 @@ impl From for Secret { } } +impl From for Secret { + fn from(value: SeedPhrase) -> Self { + Secret::SeedPhrase { + seed_phrase: value.seed_phrase.into_phrase(), + } + } +} + impl Secret { pub fn private_key(&self, index: Option) -> Result { Ok(match self { @@ -113,7 +123,7 @@ impl Secret { pub fn public_key(&self, index: Option) -> Result { if let Secret::SecureStore { entry_name } = self { let entry = keyring::StellarEntry::new(entry_name)?; - Ok(entry.get_public_key()?) + Ok(entry.get_public_key(index)?) } else { let key = self.key_pair(index)?; Ok(stellar_strkey::ed25519::PublicKey::from_payload( @@ -122,14 +132,15 @@ impl Secret { } } - pub fn signer(&self, index: Option, print: Print) -> Result { + pub fn signer(&self, hd_path: Option, print: Print) -> Result { let kind = match self { Secret::SecretKey { .. } | Secret::SeedPhrase { .. } => { - let key = self.key_pair(index)?; + let key = self.key_pair(hd_path)?; SignerKind::Local(LocalKey { key }) } Secret::SecureStore { entry_name } => SignerKind::SecureStore(SecureStoreEntry { name: entry_name.to_string(), + hd_path, }), }; Ok(Signer { kind, print }) @@ -140,14 +151,7 @@ impl Secret { } pub fn from_seed(seed: Option<&str>) -> Result { - let seed_phrase = if let Some(seed) = seed.map(str::as_bytes) { - sep5::SeedPhrase::from_entropy(seed) - } else { - sep5::SeedPhrase::random(sep5::MnemonicType::Words24) - }? - .seed_phrase - .into_phrase(); - Ok(Secret::SeedPhrase { seed_phrase }) + Ok(seed_phrase_from_seed(seed)?.into()) } pub fn test_seed_phrase() -> Result { @@ -155,6 +159,18 @@ impl Secret { } } +pub fn seed_phrase_from_seed(seed: Option<&str>) -> Result { + Ok(if let Some(seed) = seed.map(str::as_bytes) { + sep5::SeedPhrase::from_entropy(seed)? + } else { + sep5::SeedPhrase::random(sep5::MnemonicType::Words24)? + }) +} + +pub fn test_seed_phrase() -> Result { + Ok("0000000000000000".parse()?) +} + fn read_password() -> Result { std::io::stdout().flush().map_err(|_| Error::PasswordRead)?; rpassword::read_password().map_err(|_| Error::PasswordRead) diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index 099ed6186..ebd650d40 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -294,13 +294,14 @@ impl Lab { pub struct SecureStoreEntry { pub name: String, + pub hd_path: Option, } impl SecureStoreEntry { pub fn sign_tx_hash(&self, tx_hash: [u8; 32]) -> Result { let entry = StellarEntry::new(&self.name)?; - let hint = SignatureHint(entry.get_public_key()?.0[28..].try_into()?); - let signed_tx_hash = entry.sign_data(&tx_hash)?; + let hint = SignatureHint(entry.get_public_key(self.hd_path)?.0[28..].try_into()?); + let signed_tx_hash = entry.sign_data(&tx_hash, self.hd_path)?; let signature = Signature(signed_tx_hash.clone().try_into()?); Ok(DecoratedSignature { hint, signature }) } diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs index 4e6b19c99..0e6c49137 100644 --- a/cmd/soroban-cli/src/signer/keyring.rs +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -1,6 +1,6 @@ -use base64::{engine::general_purpose::STANDARD as base64, Engine as _}; use ed25519_dalek::Signer; use keyring::Entry; +use sep5::seed_phrase::SeedPhrase; use zeroize::Zeroize; pub(crate) const SECURE_STORE_ENTRY_PREFIX: &str = "secure_store:"; @@ -11,7 +11,7 @@ pub enum Error { #[error(transparent)] Keyring(#[from] keyring::Error), #[error(transparent)] - Base64(#[from] base64::DecodeError), + Sep5(#[from] sep5::error::Error), } pub struct StellarEntry { @@ -25,46 +25,60 @@ impl StellarEntry { }) } - pub fn set_password(&self, password: &[u8]) -> Result<(), Error> { - let data = base64.encode(password); + pub fn set_seed_phrase(&self, seed_phrase: SeedPhrase) -> Result<(), Error> { + let mut data = seed_phrase.seed_phrase.into_phrase(); self.keyring.set_password(&data)?; + data.zeroize(); Ok(()) } - fn get_password(&self) -> Result, Error> { - Ok(base64.decode(self.keyring.get_password()?)?) + fn get_seed_phrase(&self) -> Result { + Ok(self.keyring.get_password()?.parse()?) } fn use_key( &self, f: impl FnOnce(ed25519_dalek::SigningKey) -> Result, + hd_path: Option, ) -> Result { - let mut key_vec = self.get_password()?; - let mut key_bytes: [u8; 32] = key_vec.as_slice().try_into().unwrap(); - + // The underlying Mnemonic type is zeroized when dropped + let mut key_bytes: [u8; 32] = { + self.get_seed_phrase()? + .from_path_index(hd_path.unwrap_or_default(), None)? + .private() + .0 + }; let result = { - // Use this scope to ensure the keypair is zeroized + // Use this scope to ensure the keypair is zeroized when dropped let keypair = ed25519_dalek::SigningKey::from_bytes(&key_bytes); f(keypair)? }; - key_vec.zeroize(); key_bytes.zeroize(); Ok(result) } - pub fn get_public_key(&self) -> Result { - self.use_key(|keypair| { - Ok(stellar_strkey::ed25519::PublicKey( - *keypair.verifying_key().as_bytes(), - )) - }) + pub fn get_public_key( + &self, + hd_path: Option, + ) -> Result { + self.use_key( + |keypair| { + Ok(stellar_strkey::ed25519::PublicKey( + *keypair.verifying_key().as_bytes(), + )) + }, + hd_path, + ) } - pub fn sign_data(&self, data: &[u8]) -> Result, Error> { - self.use_key(|keypair| { - let signature = keypair.sign(data); - Ok(signature.to_bytes().to_vec()) - }) + pub fn sign_data(&self, data: &[u8], hd_path: Option) -> Result, Error> { + self.use_key( + |keypair| { + let signature = keypair.sign(data); + Ok(signature.to_bytes().to_vec()) + }, + hd_path, + ) } } @@ -77,56 +91,57 @@ mod test { fn test_get_password() { set_default_credential_builder(mock::default_credential_builder()); - let secret = crate::config::secret::Secret::from_seed(None).unwrap(); - let key_pair = secret.key_pair(None).unwrap(); + let seed_phrase = crate::config::secret::seed_phrase_from_seed(None).unwrap(); + let seed_phrase_clone = seed_phrase.clone(); let entry = StellarEntry::new("test").unwrap(); - // set the password - let set_password_result = entry.set_password(&key_pair.to_bytes()); - assert!(set_password_result.is_ok()); - - // get_password should return the same password we set - let get_password_result = entry.get_password(); - assert!(get_password_result.is_ok()); - assert_eq!(key_pair.to_bytes().to_vec(), get_password_result.unwrap()); + // set the seed phrase + let set_seed_phrase_result = entry.set_seed_phrase(seed_phrase); + assert!(set_seed_phrase_result.is_ok()); + + // get_seed_phrase should return the same seed phrase we set + let get_seed_phrase_result = entry.get_seed_phrase(); + assert!(get_seed_phrase_result.is_ok()); + assert_eq!( + seed_phrase_clone.phrase(), + get_seed_phrase_result.unwrap().phrase() + ); } #[test] fn test_get_public_key() { set_default_credential_builder(mock::default_credential_builder()); - let secret = crate::config::secret::Secret::from_seed(None).unwrap(); - let public_key = secret.public_key(None).unwrap(); - let key_pair = secret.key_pair(None).unwrap(); + let seed_phrase = crate::config::secret::seed_phrase_from_seed(None).unwrap(); + let public_key = seed_phrase.from_path_index(0, None).unwrap().public().0; let entry = StellarEntry::new("test").unwrap(); - // set the password - let set_password_result = entry.set_password(&key_pair.to_bytes()); - assert!(set_password_result.is_ok()); + // set the seed_phrase + let set_seed_phrase_result = entry.set_seed_phrase(seed_phrase); + assert!(set_seed_phrase_result.is_ok()); // confirm that we can get the public key from the entry and that it matches the one we set - let get_public_key_result = entry.get_public_key(); + let get_public_key_result = entry.get_public_key(None); assert!(get_public_key_result.is_ok()); - assert_eq!(public_key, get_public_key_result.unwrap()); + assert_eq!(public_key, get_public_key_result.unwrap().0); } #[test] fn test_sign_data() { set_default_credential_builder(mock::default_credential_builder()); - //create a secret - let secret = crate::config::secret::Secret::from_seed(None).unwrap(); - let key_pair = secret.key_pair(None).unwrap(); + //create a seed phrase + let seed_phrase = crate::config::secret::seed_phrase_from_seed(None).unwrap(); - // create a keyring entry and set the password + // create a keyring entry and set the seed_phrase let entry = StellarEntry::new("test").unwrap(); - entry.set_password(&key_pair.to_bytes()).unwrap(); + entry.set_seed_phrase(seed_phrase).unwrap(); let tx_xdr = r"AAAAAgAAAADh6eOnZEq1xQgKioffuH7/8D8x8+OdGFEkiYC6QKMWzQAAAGQAAACuAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAYAAAAAQAAAAAAAAAAAAAAAOHp46dkSrXFCAqKh9+4fv/wPzHz450YUSSJgLpAoxbNoFT1s8jZPCv9IJ2DsqGTA8pOtavv58JF53aDycpRPcEAAAAA+N2m5zc3EfWUmLvigYPOHKXhSy8OrWfVibc6y6PrQoYAAAAAAAAAAAAAAAA"; - let sign_tx_env_result = entry.sign_data(tx_xdr.as_bytes()); + let sign_tx_env_result = entry.sign_data(tx_xdr.as_bytes(), None); assert!(sign_tx_env_result.is_ok()); } } From 63f247e5e3f11e858a0637b547a16e2ebae814c9 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 7 Jan 2025 15:15:59 -0500 Subject: [PATCH 56/60] fix: clean up --- cmd/soroban-cli/src/commands/contract/arg_parsing.rs | 7 +------ cmd/soroban-cli/src/commands/keys/add.rs | 8 ++------ cmd/soroban-cli/src/commands/keys/address.rs | 11 +---------- cmd/soroban-cli/src/config/address.rs | 8 +++++--- 4 files changed, 9 insertions(+), 25 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 98a6d3004..bb2d2aa76 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -14,9 +14,8 @@ use crate::xdr::{ use crate::commands::txn_result::TxnResult; use crate::config::{ - self, address, + self, sc_address::{self, UnresolvedScAddress}, - secret, }; use soroban_spec_tools::Spec; @@ -42,10 +41,6 @@ pub enum Error { Xdr(#[from] xdr::Error), #[error(transparent)] StrVal(#[from] soroban_spec_tools::Error), - #[error(transparent)] - Address(#[from] address::Error), - #[error(transparent)] - Secret(#[from] secret::Error), #[error("Missing argument {0}")] MissingArgument(String), #[error("")] diff --git a/cmd/soroban-cli/src/commands/keys/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs index 57a218ede..4c5ddbd9b 100644 --- a/cmd/soroban-cli/src/commands/keys/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -2,10 +2,7 @@ use clap::command; use crate::{ commands::global, - config::{ - address::{self, KeyName}, - locator, secret, - }, + config::{address::KeyName, locator, secret}, print::Print, }; @@ -13,10 +10,9 @@ use crate::{ pub enum Error { #[error(transparent)] Secret(#[from] secret::Error), + #[error(transparent)] Config(#[from] locator::Error), - #[error(transparent)] - Address(#[from] address::Error), } #[derive(Debug, clap::Parser, Clone)] diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index 9727988e0..51ce90ed2 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,21 +1,12 @@ use clap::arg; use crate::{ - commands::config::{address, locator, secret}, + commands::config::{address, locator}, config::UnresolvedMuxedAccount, }; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error(transparent)] - Config(#[from] locator::Error), - - #[error(transparent)] - Secret(#[from] secret::Error), - - #[error(transparent)] - StrKey(#[from] stellar_strkey::DecodeError), - #[error(transparent)] Address(#[from] address::Error), } diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 24a40a62a..f86f88ecb 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -55,8 +55,8 @@ impl UnresolvedMuxedAccount { ) -> Result { match self { UnresolvedMuxedAccount::Resolved(muxed_account) => Ok(muxed_account.clone()), - UnresolvedMuxedAccount::AliasOrSecret(alias) => { - Self::resolve_muxed_account_with_alias(alias, locator, hd_path) + UnresolvedMuxedAccount::AliasOrSecret(alias_or_secret) => { + Self::resolve_muxed_account_with_alias(alias_or_secret, locator, hd_path) } } } @@ -78,7 +78,9 @@ impl UnresolvedMuxedAccount { UnresolvedMuxedAccount::Resolved(muxed_account) => { Err(Error::CannotSign(muxed_account.clone())) } - UnresolvedMuxedAccount::AliasOrSecret(alias) => Ok(locator.key(alias)?), + UnresolvedMuxedAccount::AliasOrSecret(alias_or_secret) => { + Ok(locator.key(alias_or_secret)?) + } } } } From ed797e026e3d0c5ab86514061ab224f09a16ddae Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 9 Jan 2025 18:35:24 -0500 Subject: [PATCH 57/60] fix: wait to lookup muxed account --- Cargo.lock | 1720 +++++++++-------- cmd/soroban-cli/src/commands/keys/generate.rs | 1 + cmd/soroban-cli/src/config/address.rs | 2 +- cmd/soroban-cli/src/config/key.rs | 2 +- cmd/soroban-cli/src/config/locator.rs | 10 +- cmd/soroban-cli/src/config/sc_address.rs | 12 +- 6 files changed, 973 insertions(+), 774 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72386cbc9..20d184b0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -70,43 +70,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arbitrary" @@ -237,9 +237,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "ascii-canvas" @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.12" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" dependencies = [ "flate2", "futures-core", @@ -339,14 +339,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.0", - "futures-lite 2.3.0", + "fastrand", + "futures-lite", "slab", ] @@ -358,59 +358,30 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", - "async-io 2.3.3", - "async-lock 3.4.0", + "async-io", + "async-lock", "blocking", - "futures-lite 2.3.0", + "futures-lite", "once_cell", ] [[package]] name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ - "async-lock 3.4.0", + "async-lock", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "parking", - "polling 3.7.2", - "rustix 0.38.34", + "polling", + "rustix", "slab", "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.59.0", ] [[package]] @@ -419,72 +390,74 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-object-pool" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb901c30ebc2fc4ab46395bbfbdba9542c16559d853645d75190c3056caf3bc" +checksum = "333c456b97c3f2d50604e8b2624253b7f787208cb72eb75e64b0ad11b221652c" dependencies = [ "async-std", ] [[package]] name = "async-process" -version = "1.8.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", + "async-channel 2.3.1", + "async-io", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.34", - "windows-sys 0.48.0", + "event-listener 5.4.0", + "futures-lite", + "rustix", + "tracing", ] [[package]] name = "async-signal" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.3", - "async-lock 3.4.0", + "async-io", + "async-lock", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.34", + "rustix", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", + "futures-lite", "gloo-timers", "kv-log-macro", "log", @@ -504,13 +477,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.76" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -521,23 +494,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -611,12 +584,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" @@ -650,7 +617,7 @@ dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "piper", ] @@ -667,9 +634,9 @@ dependencies = [ "futures-util", "hex", "home", - "http 1.1.0", + "http 1.2.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-named-pipe", "hyper-rustls 0.26.0", "hyper-util", @@ -678,14 +645,14 @@ dependencies = [ "pin-project-lite", "rustls 0.22.4", "rustls-native-certs 0.7.3", - "rustls-pemfile 2.1.3", + "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_derive", "serde_json", "serde_repr", "serde_urlencoded", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "tower-service", @@ -706,12 +673,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", - "regex-automata 0.4.7", + "regex-automata 0.4.9", "serde", ] @@ -735,9 +702,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "bytes-lit" @@ -748,7 +715,7 @@ dependencies = [ "num-bigint", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -759,18 +726,18 @@ checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -786,17 +753,18 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "cc" -version = "1.1.8" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -805,11 +773,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -822,9 +796,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.14" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c937d4061031a6d0c8da4b9a4f98a172fc2976dfb1c19213a9cf7d0d3c837e36" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -841,9 +815,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.14" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85379ba512b21a328adf887e85f7742d12e96eb31f3ef077df4ffc26b506ffed" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -853,30 +827,30 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.13" +version = "4.5.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa3c596da3cf0983427b0df0dba359df9182c13bd5b519b585a482b0c351f4e8" +checksum = "33a7e468e750fa4b6be660e8b5651ad47372e8fb114030b594c2d75d48c5ffd0" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "codespan-reporting" @@ -890,18 +864,18 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -929,17 +903,27 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -966,18 +950,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -994,9 +978,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -1038,9 +1022,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -1064,7 +1048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -1091,51 +1075,66 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "cxx" -version = "1.0.112" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ab30434ea0ff6aa640a08dda5284026a366d47565496fd40b6cbfbdd7e31a2" +checksum = "ad7c7515609502d316ab9a24f67dc045132d93bfd3f00713389e90d9898bf30d" dependencies = [ "cc", + "cxxbridge-cmd", "cxxbridge-flags", "cxxbridge-macro", + "foldhash", "link-cplusplus", ] [[package]] name = "cxx-build" -version = "1.0.112" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b649d7dfae8268450d53d109388b337b9352c7cba1fc10db4a1bc23c3dc189fb" +checksum = "8bfd16fca6fd420aebbd80d643c201ee4692114a0de208b790b9cd02ceae65fb" dependencies = [ "cc", "codespan-reporting", - "once_cell", "proc-macro2", "quote", "scratch", - "syn 2.0.77", + "syn 2.0.95", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c33fd49f5d956a1b7ee5f7a9768d58580c6752838d92e39d0d56439efdedc35" +dependencies = [ + "clap", + "codespan-reporting", + "proc-macro2", + "quote", + "syn 2.0.95", ] [[package]] name = "cxxbridge-flags" -version = "1.0.112" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42281b20eba5218c539295c667c18e2f50211bb11902419194c6ed1ae808e547" +checksum = "be0f1077278fac36299cce8446effd19fe93a95eedb10d39265f3bf67b3036c9" [[package]] name = "cxxbridge-macro" -version = "1.0.112" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45506e3c66512b0a65d291a6b452128b7b1dd9841e20d1e151addbd2c00ea50" +checksum = "3da7e4d6e74af6b79031d264b2f13c3ea70af1978083741c41ffce9308f1f24f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "rustversion", + "syn 2.0.95", ] [[package]] @@ -1159,7 +1158,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -1170,7 +1169,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -1242,7 +1241,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -1329,6 +1328,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -1437,9 +1447,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -1453,14 +1463,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -1468,9 +1478,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", @@ -1487,12 +1497,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1515,20 +1525,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.3.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -1537,28 +1536,19 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "pin-project-lite", ] [[package]] name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ff" @@ -1584,9 +1574,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1594,9 +1584,9 @@ dependencies = [ [[package]] name = "float-cmp" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ "num-traits", ] @@ -1607,6 +1597,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1645,9 +1641,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1676,9 +1672,9 @@ checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1693,26 +1689,11 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-lite" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 2.1.0", + "fastrand", "futures-core", "futures-io", "parking", @@ -1727,7 +1708,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -1773,9 +1754,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -1786,27 +1767,27 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -1815,16 +1796,16 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.6.0", + "bitflags", "ignore", "walkdir", ] [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -1855,7 +1836,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.3.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -1864,17 +1845,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.3.0", + "http 1.2.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -1898,9 +1879,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -1923,12 +1904,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1952,9 +1927,9 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hickory-proto" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +checksum = "447afdcdb8afb9d0a852af6dc65d9b285ce720ed7a59e42a8bf2e931c67bc1b5" dependencies = [ "async-trait", "cfg-if", @@ -1963,11 +1938,11 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna 0.4.0", + "idna", "ipnet", "once_cell", "rand", - "thiserror", + "thiserror 1.0.69", "tinyvec", "tokio", "tracing", @@ -1976,9 +1951,9 @@ dependencies = [ [[package]] name = "hickory-resolver" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +checksum = "0a2e2aba9c389ce5267d31cf1e4dace82390ae276b0b364ea55630b1fa1b44b4" dependencies = [ "cfg-if", "futures-util", @@ -1990,7 +1965,7 @@ dependencies = [ "rand", "resolv-conf", "smallvec", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -2028,11 +2003,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2059,9 +2034,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -2086,7 +2061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -2097,16 +2072,16 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2129,7 +2104,7 @@ dependencies = [ "crossbeam-utils", "form_urlencoded", "futures-util", - "hyper 0.14.30", + "hyper 0.14.32", "lazy_static", "levenshtein", "log", @@ -2150,9 +2125,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -2165,7 +2140,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower-service", "tracing", @@ -2174,15 +2149,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "httparse", "httpdate", @@ -2200,7 +2175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" dependencies = [ "hex", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-util", "pin-project-lite", "tokio", @@ -2216,7 +2191,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.32", "log", "rustls 0.21.12", "rustls-native-certs 0.6.3", @@ -2231,8 +2206,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", "log", "rustls 0.22.4", @@ -2245,19 +2220,19 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", - "rustls 0.23.12", - "rustls-native-certs 0.8.0", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tower-service", "webpki-roots", ] @@ -2270,7 +2245,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-util", "native-tls", "tokio", @@ -2280,20 +2255,19 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.2", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -2306,7 +2280,7 @@ checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" dependencies = [ "hex", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-util", "pin-project-lite", "tokio", @@ -2315,9 +2289,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2336,6 +2310,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2344,35 +2436,36 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "idna" -version = "0.5.0" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ "crossbeam-deque", "globset", "log", "memchr", - "regex-automata 0.4.7", + "regex-automata 0.4.9", "same-file", "walkdir", "winapi-util", @@ -2411,12 +2504,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "serde", ] @@ -2426,33 +2519,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipconfig" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.7", + "socket2", "widestring", "windows-sys 0.48.0", "winreg", @@ -2460,9 +2533,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-docker" @@ -2509,9 +2582,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -2524,63 +2597,64 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "jsonrpsee-core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" +checksum = "f24ea59b037b6b9b0e2ebe2c30a3e782b56bd7c76dcc5d6d70ba55d442af56e3" dependencies = [ "anyhow", "async-trait", "beef", "futures-util", - "hyper 0.14.30", + "hyper 0.14.32", "jsonrpsee-types", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] [[package]] name = "jsonrpsee-http-client" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" +checksum = "57c7b9f95208927653e7965a98525e7fc641781cab89f0e27c43fa2974405683" dependencies = [ "async-trait", - "hyper 0.14.30", + "hyper 0.14.32", "hyper-rustls 0.24.2", "jsonrpsee-core", "jsonrpsee-types", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", - "tower", + "tower 0.4.13", "tracing", "url", ] [[package]] name = "jsonrpsee-types" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" +checksum = "3264e339143fe37ed081953842ee67bfafa99e3b91559bdded6e4abd8fc8535e" dependencies = [ "anyhow", "beef", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -2607,13 +2681,15 @@ dependencies = [ [[package]] name = "keyring" -version = "3.3.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fa83d1ca02db069b5fbe94b23b584d588e989218310c9c15015bb5571ef1a94" +checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833" dependencies = [ "byteorder 1.5.0", "dbus-secret-service", - "security-framework", + "log", + "security-framework 2.11.1", + "security-framework 3.2.0", "windows-sys 0.59.0", ] @@ -2640,7 +2716,7 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "string_cache", "term", "tiny-keccak", @@ -2654,7 +2730,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata 0.4.7", + "regex-automata 0.4.9", ] [[package]] @@ -2703,7 +2779,7 @@ dependencies = [ "ledger-transport", "libc", "log", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2714,9 +2790,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libdbus-sys" @@ -2729,9 +2805,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -2739,7 +2815,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags", "libc", ] @@ -2760,15 +2836,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] -name = "linux-raw-sys" -version = "0.4.14" +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -2827,20 +2903,19 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -2848,18 +2923,18 @@ dependencies = [ [[package]] name = "mockito" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b34bd91b9e5c5b06338d392463e1318d683cf82ec3d3af4014609be6e2108d" +checksum = "652cd6d169a36eaf9d1e6bce1a221130439a966d7f27858af66a33a66e9c4ee2" dependencies = [ "assert-json-diff", "bytes", "colored", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-util", "log", "rand", @@ -2882,7 +2957,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -2917,9 +2992,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -2931,20 +3006,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -2957,30 +3031,29 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2989,11 +3062,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -3001,27 +3073,27 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "object" -version = "0.32.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -3031,9 +3103,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open" -version = "5.3.0" +version = "5.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" +checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" dependencies = [ "is-wsl", "libc", @@ -3046,7 +3118,7 @@ version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -3063,7 +3135,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -3110,9 +3182,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -3145,7 +3217,7 @@ checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" dependencies = [ "parse-display-derive", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -3157,9 +3229,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "structmeta", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -3170,9 +3242,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pbkdf2" @@ -3196,40 +3268,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.3.0", + "indexmap 2.7.0", ] [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", - "phf_shared 0.11.2", + "phf_shared 0.11.3", ] [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared 0.11.2", + "phf_shared 0.11.3", "rand", ] [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", - "phf_shared 0.11.2", + "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -3238,16 +3310,16 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] @@ -3258,29 +3330,29 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -3290,12 +3362,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.0", + "fastrand", "futures-io", ] @@ -3311,39 +3383,23 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "polling" -version = "2.8.0" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "polling" -version = "3.7.2" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", - "rustix 0.38.34", + "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3369,9 +3425,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" dependencies = [ "anstyle", "difflib", @@ -3383,15 +3439,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" [[package]] name = "predicates-tree" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" dependencies = [ "predicates-core", "termtree", @@ -3399,9 +3455,9 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -3409,12 +3465,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705" dependencies = [ "proc-macro2", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -3428,9 +3484,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -3443,57 +3499,61 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", - "rustls 0.23.12", - "socket2 0.5.7", - "thiserror", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "socket2", + "thiserror 2.0.10", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom", "rand", "ring", - "rustc-hash 2.0.0", - "rustls 0.23.12", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.10", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" dependencies = [ + "cfg_aliases", "libc", "once_cell", - "socket2 0.5.7", + "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -3530,34 +3590,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -3571,13 +3631,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -3588,15 +3648,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64 0.22.1", "bytes", @@ -3604,13 +3664,13 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.6", + "h2 0.4.7", "hickory-resolver", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.3", + "hyper 1.5.2", + "hyper-rustls 0.27.5", "hyper-tls", "hyper-util", "ipnet", @@ -3622,9 +3682,9 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.12", - "rustls-native-certs 0.7.3", - "rustls-pemfile 2.1.3", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", + "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", @@ -3633,8 +3693,9 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tokio-util", + "tower 0.5.2", "tower-service", "url", "wasm-bindgen", @@ -3721,7 +3782,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.77", + "syn 2.0.95", "walkdir", ] @@ -3749,9 +3810,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" @@ -3764,29 +3825,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.34" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "linux-raw-sys", + "windows-sys 0.59.0", ] [[package]] @@ -3810,21 +3857,21 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -3838,7 +3885,7 @@ dependencies = [ "openssl-probe", "rustls-pemfile 1.0.4", "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] @@ -3848,23 +3895,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.3", + "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] name = "rustls-native-certs" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.3", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.2.0", ] [[package]] @@ -3878,19 +3924,21 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -3904,9 +3952,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -3915,9 +3963,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -3936,20 +3984,20 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.9" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ff467073ddaff34c3a39e5b454f25dd982484a26fff50254ca793c56a1b714" +checksum = "28e1c91382686d21b5ac7959341fcb9780fa7c03773646995a87c950fa7be640" dependencies = [ "sdd", ] [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3973,7 +4021,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4000,15 +4048,15 @@ dependencies = [ [[package]] name = "sdd" -version = "2.1.0" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177258b64c0faaa9ffd3c65cd3262c2bc7e2588dbbd9c1641d0346145c1bbda8" +checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9" [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", @@ -4023,8 +4071,21 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", - "core-foundation", + "bitflags", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -4032,9 +4093,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -4042,9 +4103,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] @@ -4057,15 +4118,15 @@ checksum = "cec6914e06f503f83e431e1762c82003c5233b1dffb6185e51e4c40dd1c26eaa" dependencies = [ "slipped10", "stellar-strkey 0.0.8", - "thiserror", + "thiserror 1.0.69", "tiny-bip39", ] [[package]] name = "serde" -version = "1.0.192" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -4083,33 +4144,34 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "serde_derive_internals" -version = "0.29.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -4126,20 +4188,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -4158,15 +4220,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.3.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -4176,21 +4238,21 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "serial_test" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" dependencies = [ "futures", "log", @@ -4202,13 +4264,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4277,9 +4339,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core", @@ -4297,6 +4359,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -4347,19 +4415,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4374,7 +4432,7 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4448,7 +4506,7 @@ dependencies = [ "tempfile", "termcolor", "termcolor_output", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "toml", @@ -4544,7 +4602,7 @@ dependencies = [ "serde", "serde_json", "stellar-xdr", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4562,7 +4620,7 @@ dependencies = [ "serde_with", "soroban-env-common", "soroban-env-host", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4604,7 +4662,7 @@ dependencies = [ "soroban-spec", "soroban-spec-rust", "stellar-xdr", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4615,7 +4673,7 @@ checksum = "413559f8b6c77af0cc97cd52cca0ecb59ad81004d3fd064711d91ea50274965a" dependencies = [ "base64 0.13.1", "stellar-xdr", - "thiserror", + "thiserror 1.0.69", "wasmparser", ] @@ -4630,7 +4688,7 @@ dependencies = [ "sha2 0.9.9", "soroban-spec", "stellar-xdr", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4645,8 +4703,8 @@ dependencies = [ "sha2 0.10.8", "soroban-spec", "stellar-xdr", - "syn 2.0.77", - "thiserror", + "syn 2.0.95", + "thiserror 1.0.69", ] [[package]] @@ -4661,7 +4719,7 @@ dependencies = [ "soroban-spec", "stellar-strkey 0.0.11", "stellar-xdr", - "thiserror", + "thiserror 1.0.69", "tokio", "wasmparser", "which", @@ -4684,7 +4742,7 @@ dependencies = [ "soroban-spec", "stellar-xdr", "temp-dir", - "thiserror", + "thiserror 1.0.69", "walkdir", ] @@ -4708,7 +4766,7 @@ dependencies = [ "soroban-spec-tools", "stellar-rpc-client", "stellar-strkey 0.0.11", - "thiserror", + "thiserror 1.0.69", "tokio", "toml", "ulid", @@ -4754,6 +4812,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -4804,7 +4868,7 @@ dependencies = [ "stellar-xdr", "test-case", "testcontainers", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -4817,7 +4881,7 @@ checksum = "d7c4daeb7f113802cc4bcce8736be32bde243e8e2bf29dda76614b949ed445cf" dependencies = [ "clap", "hex", - "http 1.1.0", + "http 1.2.0", "itertools 0.10.5", "jsonrpsee-core", "jsonrpsee-http-client", @@ -4830,7 +4894,7 @@ dependencies = [ "stellar-xdr", "termcolor", "termcolor_output", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -4843,7 +4907,7 @@ checksum = "12d2bf45e114117ea91d820a846fd1afbe3ba7d717988fee094ce8227a3bf8bd" dependencies = [ "base32", "crate-git-revision", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4854,7 +4918,7 @@ checksum = "5e3aa3ed00e70082cb43febc1c2afa5056b9bb3e348bbb43d0cd0aa88a611144" dependencies = [ "crate-git-revision", "data-encoding", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4884,7 +4948,7 @@ dependencies = [ "serde_json", "serde_with", "stellar-strkey 0.0.9", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4915,7 +4979,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4926,7 +4990,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -4985,9 +5049,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -4996,21 +5060,32 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.6.0", - "core-foundation", + "bitflags", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -5026,20 +5101,21 @@ dependencies = [ [[package]] name = "temp-dir" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", - "fastrand 2.1.0", + "fastrand", + "getrandom", "once_cell", - "rustix 0.38.34", + "rustix", "windows-sys 0.59.0", ] @@ -5081,9 +5157,9 @@ checksum = "f34dde0bb841eb3762b42bdff8db11bbdbc0a3bd7b32012955f5ce1d081f86c1" [[package]] name = "termtree" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "test-case" @@ -5103,7 +5179,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -5114,7 +5190,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", "test-case-core", ] @@ -5190,7 +5266,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util", @@ -5199,22 +5275,42 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3" +dependencies = [ + "thiserror-impl 2.0.10", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn 2.0.95", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -5229,9 +5325,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -5250,9 +5346,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -5271,7 +5367,7 @@ dependencies = [ "rand", "rustc-hash 1.1.0", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "unicode-normalization", "wasm-bindgen", "zeroize", @@ -5286,11 +5382,21 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -5303,9 +5409,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -5314,20 +5420,20 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] @@ -5363,20 +5469,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.12", - "rustls-pki-types", + "rustls 0.23.20", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -5385,9 +5490,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -5420,11 +5525,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -5441,29 +5546,43 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", - "tokio", "tower-layer", "tower-service", "tracing", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -5478,27 +5597,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "thiserror", + "thiserror 1.0.69", "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -5517,9 +5636,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -5547,54 +5666,47 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ulid" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f903f293d11f31c0c29e4148f6dc0d033a7f80cebc0282bea147611667d289" +checksum = "f294bff79170ed1c5633812aff1e565c35d993a36e757f9bc0accf5eec4e6045" dependencies = [ - "getrandom", "rand", "serde", "web-time", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -5604,16 +5716,28 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", "serde", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -5628,9 +5752,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "vcpkg" @@ -5653,12 +5777,6 @@ dependencies = [ "libc", ] -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - [[package]] name = "walkdir" version = "2.5.0" @@ -5692,46 +5810,47 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5739,22 +5858,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-gen" @@ -5777,7 +5896,7 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "tempfile", - "thiserror", + "thiserror 1.0.69", "wasm-opt-cxx-sys", "wasm-opt-sys", ] @@ -5808,9 +5927,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -5843,7 +5962,7 @@ version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.7.0", "semver", ] @@ -5858,9 +5977,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -5878,9 +5997,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -5895,7 +6014,7 @@ dependencies = [ "home", "once_cell", "regex", - "rustix 0.38.34", + "rustix", ] [[package]] @@ -6135,9 +6254,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" dependencies = [ "memchr", ] @@ -6152,11 +6271,47 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", + "synstructure", +] [[package]] name = "zerocopy" @@ -6176,7 +6331,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", + "synstructure", ] [[package]] @@ -6196,5 +6372,27 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.95", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", ] diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index b731c8c02..7b9376dcd 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -5,6 +5,7 @@ use super::super::config::{ locator, network, secret::{self, Secret}, }; + use crate::{ commands::global, config::address::KeyName, diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 202569471..6987b523c 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -56,7 +56,7 @@ impl UnresolvedMuxedAccount { match self { UnresolvedMuxedAccount::Resolved(muxed_account) => Ok(muxed_account.clone()), UnresolvedMuxedAccount::AliasOrSecret(alias_or_secret) => { - Ok(locator.read_key(alias_or_secret)?.public_key(hd_path)?) + Ok(locator.read_key(alias_or_secret)?.muxed_account(hd_path)?) } } } diff --git a/cmd/soroban-cli/src/config/key.rs b/cmd/soroban-cli/src/config/key.rs index add554f96..9d21ad061 100644 --- a/cmd/soroban-cli/src/config/key.rs +++ b/cmd/soroban-cli/src/config/key.rs @@ -28,7 +28,7 @@ pub enum Key { } impl Key { - pub fn public_key(&self, hd_path: Option) -> Result { + pub fn muxed_account(&self, hd_path: Option) -> Result { let bytes = match self { Key::Secret(secret) => secret.public_key(hd_path)?.0, Key::PublicKey(Public(key)) => key.0, diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index e43c19972..ecc31247e 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -257,11 +257,9 @@ impl Args { } pub fn read_key(&self, key_or_name: &str) -> Result { - if let Ok(key) = self.read_identity(key_or_name) { - Ok(key) - } else { - Ok(key_or_name.parse()?) - } + key_or_name + .parse() + .or_else(|_| self.read_identity(key_or_name)) } pub fn get_secret_key(&self, key_or_name: &str) -> Result { @@ -276,7 +274,7 @@ impl Args { key_or_name: &str, hd_path: Option, ) -> Result { - Ok(self.read_key(key_or_name)?.public_key(hd_path)?) + Ok(self.read_key(key_or_name)?.muxed_account(hd_path)?) } pub fn read_network(&self, name: &str) -> Result { diff --git a/cmd/soroban-cli/src/config/sc_address.rs b/cmd/soroban-cli/src/config/sc_address.rs index c66b0c13c..b580504d5 100644 --- a/cmd/soroban-cli/src/config/sc_address.rs +++ b/cmd/soroban-cli/src/config/sc_address.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use crate::xdr; -use super::{address, locator, UnresolvedContract}; +use super::{key, locator, UnresolvedContract}; /// `ScAddress` can be either a resolved `xdr::ScAddress` or an alias of a `Contract` or `MuxedAccount`. #[allow(clippy::module_name_repetitions)] @@ -23,7 +23,7 @@ pub enum Error { #[error(transparent)] Locator(#[from] locator::Error), #[error(transparent)] - Address(#[from] address::Error), + Key(#[from] key::Error), #[error("Account alias not Found{0}")] AccountAliasNotFound(String), } @@ -50,8 +50,8 @@ impl UnresolvedScAddress { UnresolvedScAddress::Alias(alias) => alias, }; let contract = UnresolvedContract::resolve_alias(&alias, locator, network_passphrase); - let muxed_account = locator.read_key(&alias)?.public_key(None); - match (contract, muxed_account) { + let key = locator.read_key(&alias); + match (contract, key) { (Ok(contract), Ok(_)) => { eprintln!( "Warning: ScAddress alias {alias} is ambiguous, assuming it is a contract" @@ -59,7 +59,9 @@ impl UnresolvedScAddress { Ok(xdr::ScAddress::Contract(xdr::Hash(contract.0))) } (Ok(contract), _) => Ok(xdr::ScAddress::Contract(xdr::Hash(contract.0))), - (_, Ok(muxed_account)) => Ok(xdr::ScAddress::Account(muxed_account.account_id())), + (_, Ok(key)) => Ok(xdr::ScAddress::Account( + key.muxed_account(None)?.account_id(), + )), _ => Err(Error::AccountAliasNotFound(alias)), } } From dc66e456741e56d70965625716046c9142e187b4 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 29 Nov 2024 12:31:23 -0500 Subject: [PATCH 58/60] feat: improve asset parsing to use named keys as issuer Previously the issuer had to be a fully resolved `xdr::AccountId`, now it can be an `Address`, which then can be resolved. Thus allowing the following: `USDC:circle` --- .../src/commands/contract/deploy/asset.rs | 6 ++- .../src/commands/contract/id/asset.rs | 7 ++- .../src/commands/snapshot/create.rs | 4 +- cmd/soroban-cli/src/commands/tx/args.rs | 8 ++- .../src/commands/tx/new/change_trust.rs | 12 +++-- cmd/soroban-cli/src/commands/tx/new/mod.rs | 2 +- .../src/commands/tx/new/payment.rs | 18 +++++-- .../commands/tx/new/set_trustline_flags.rs | 2 +- cmd/soroban-cli/src/commands/tx/op/add/mod.rs | 2 +- cmd/soroban-cli/src/tx/builder/asset.rs | 50 +++++++++++-------- cmd/soroban-cli/src/utils.rs | 4 +- 11 files changed, 74 insertions(+), 41 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs index 8c4419277..e09d327b3 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -43,6 +43,8 @@ pub enum Error { #[error(transparent)] Builder(#[from] builder::Error), #[error(transparent)] + Asset(#[from] builder::asset::Error), + #[error(transparent)] Locator(#[from] locator::Error), } @@ -107,7 +109,7 @@ impl NetworkRunnable for Cmd { ) -> Result { let config = config.unwrap_or(&self.config); // Parse asset - let asset = &self.asset; + let asset = self.asset.resolve(&config.locator)?; let network = config.get_network()?; let client = network.rpc_client()?; @@ -122,7 +124,7 @@ impl NetworkRunnable for Cmd { .await?; let sequence: i64 = account_details.seq_num.into(); let network_passphrase = &network.network_passphrase; - let contract_id = contract_id_hash_from_asset(asset, network_passphrase); + let contract_id = contract_id_hash_from_asset(&asset, network_passphrase); let tx = build_wrap_token_tx( asset, &contract_id, diff --git a/cmd/soroban-cli/src/commands/contract/id/asset.rs b/cmd/soroban-cli/src/commands/contract/id/asset.rs index 921592cf8..ddc03a715 100644 --- a/cmd/soroban-cli/src/commands/contract/id/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/id/asset.rs @@ -21,6 +21,8 @@ pub enum Error { ConfigError(#[from] config::Error), #[error(transparent)] Xdr(#[from] crate::xdr::Error), + #[error(transparent)] + Asset(#[from] builder::asset::Error), } impl Cmd { pub fn run(&self) -> Result<(), Error> { @@ -30,7 +32,10 @@ impl Cmd { pub fn contract_address(&self) -> Result { let network = self.config.get_network()?; - let contract_id = contract_id_hash_from_asset(&self.asset, &network.network_passphrase); + let contract_id = contract_id_hash_from_asset( + &self.asset.resolve(&self.config.locator)?, + &network.network_passphrase, + ); Ok(stellar_strkey::Contract(contract_id.0)) } } diff --git a/cmd/soroban-cli/src/commands/snapshot/create.rs b/cmd/soroban-cli/src/commands/snapshot/create.rs index 9ad39953f..9e2d3a292 100644 --- a/cmd/soroban-cli/src/commands/snapshot/create.rs +++ b/cmd/soroban-cli/src/commands/snapshot/create.rs @@ -328,7 +328,9 @@ impl Cmd { get_name_from_stellar_asset_contract_storage(storage) { let asset: builder::Asset = name.parse()?; - if let Some(issuer) = match asset.into() { + if let Some(issuer) = match asset + .resolve(&global_args.locator)? + { Asset::Native => None, Asset::CreditAlphanum4(a4) => Some(a4.issuer), Asset::CreditAlphanum12(a12) => Some(a12.issuer), diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index 02ba7a922..38391e248 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -7,7 +7,7 @@ use crate::{ }, fee, rpc::{self, Client, GetTransactionResponse}, - tx::builder::{self, TxExt}, + tx::builder::{self, asset, TxExt}, xdr::{self, Limits, WriteXdr}, }; @@ -39,6 +39,8 @@ pub enum Error { #[error(transparent)] Address(#[from] address::Error), #[error(transparent)] + Asset(#[from] asset::Error), + #[error(transparent)] TxXdr(#[from] super::xdr::Error), } @@ -144,4 +146,8 @@ impl Args { }; Ok(super::xdr::add_op(tx_env, op)?) } + + pub fn resolve_asset(&self, asset: &builder::Asset) -> Result { + Ok(asset.resolve(&self.config.locator)?) + } } diff --git a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs index 04f17e87e..468291f73 100644 --- a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs +++ b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs @@ -20,16 +20,18 @@ pub struct Args { pub limit: i64, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { - let line = match cmd.op.line.0.clone() { +impl TryFrom<&Cmd> for xdr::OperationBody { + type Error = tx::args::Error; + fn try_from(cmd: &Cmd) -> Result { + let asset = cmd.tx.resolve_asset(&cmd.op.line)?; + let line = match asset { xdr::Asset::CreditAlphanum4(asset) => xdr::ChangeTrustAsset::CreditAlphanum4(asset), xdr::Asset::CreditAlphanum12(asset) => xdr::ChangeTrustAsset::CreditAlphanum12(asset), xdr::Asset::Native => xdr::ChangeTrustAsset::Native, }; - xdr::OperationBody::ChangeTrust(xdr::ChangeTrustOp { + Ok(xdr::OperationBody::ChangeTrust(xdr::ChangeTrustOp { line, limit: cmd.op.limit, - }) + })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/mod.rs b/cmd/soroban-cli/src/commands/tx/new/mod.rs index c00d01220..761773418 100644 --- a/cmd/soroban-cli/src/commands/tx/new/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/new/mod.rs @@ -45,7 +45,7 @@ impl TryFrom<&Cmd> for OperationBody { Ok(match cmd { Cmd::AccountMerge(cmd) => cmd.try_into()?, Cmd::BumpSequence(cmd) => cmd.into(), - Cmd::ChangeTrust(cmd) => cmd.into(), + Cmd::ChangeTrust(cmd) => cmd.try_into()?, Cmd::CreateAccount(cmd) => cmd.try_into()?, Cmd::ManageData(cmd) => cmd.into(), Cmd::Payment(cmd) => cmd.try_into()?, diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 1e58110b0..ed03cda05 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -26,11 +26,21 @@ pub struct Args { impl TryFrom<&Cmd> for xdr::OperationBody { type Error = tx::args::Error; - fn try_from(cmd: &Cmd) -> Result { + fn try_from( + Cmd { + tx, + op: + Args { + destination, + asset, + amount, + }, + }: &Cmd, + ) -> Result { Ok(xdr::OperationBody::Payment(xdr::PaymentOp { - destination: cmd.tx.resolve_muxed_address(&cmd.op.destination)?, - asset: cmd.op.asset.clone().into(), - amount: cmd.op.amount.into(), + destination: tx.resolve_muxed_address(&destination)?, + asset: tx.resolve_asset(asset)?, + amount: amount.into(), })) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs index ac2830222..77a63f406 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs @@ -69,7 +69,7 @@ impl TryFrom<&Cmd> for xdr::OperationBody { Ok(xdr::OperationBody::SetTrustLineFlags( xdr::SetTrustLineFlagsOp { trustor: cmd.tx.resolve_account_id(&cmd.op.trustor)?, - asset: cmd.op.asset.clone().into(), + asset: cmd.tx.resolve_asset(&cmd.op.asset)?, clear_flags, set_flags, }, diff --git a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs index 5e69cf168..1a02d01a2 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs @@ -52,7 +52,7 @@ impl TryFrom<&Cmd> for OperationBody { Ok(match &cmd { Cmd::AccountMerge(account_merge::Cmd { op, .. }) => op.try_into()?, Cmd::BumpSequence(bump_sequence::Cmd { op, .. }) => op.into(), - Cmd::ChangeTrust(change_trust::Cmd { op, .. }) => op.into(), + Cmd::ChangeTrust(change_trust::Cmd { op, .. }) => op.try_into()?, Cmd::CreateAccount(create_account::Cmd { op, .. }) => op.try_into()?, Cmd::ManageData(manage_data::Cmd { op, .. }) => op.into(), Cmd::Payment(payment::Cmd { op, .. }) => op.try_into()?, diff --git a/cmd/soroban-cli/src/tx/builder/asset.rs b/cmd/soroban-cli/src/tx/builder/asset.rs index bba39804e..e2bf90d2d 100644 --- a/cmd/soroban-cli/src/tx/builder/asset.rs +++ b/cmd/soroban-cli/src/tx/builder/asset.rs @@ -1,17 +1,24 @@ use std::str::FromStr; -use crate::xdr::{self, AlphaNum12, AlphaNum4, AssetCode}; +use crate::{ + config::{address, locator}, + xdr::{self, AlphaNum12, AlphaNum4, AssetCode}, +}; #[derive(Clone, Debug)] -pub struct Asset(pub xdr::Asset); +pub enum Asset { + Asset(AssetCode, address::UnresolvedMuxedAccount), + Native, +} #[derive(thiserror::Error, Debug)] pub enum Error { #[error("cannot parse asset: {0}, expected format: 'native' or 'code:issuer'")] CannotParseAsset(String), - #[error(transparent)] Xdr(#[from] xdr::Error), + #[error(transparent)] + Address(#[from] address::Error), } impl FromStr for Asset { @@ -19,32 +26,31 @@ impl FromStr for Asset { fn from_str(value: &str) -> Result { if value == "native" { - return Ok(Asset(xdr::Asset::Native)); + return Ok(Asset::Native); } let mut iter = value.splitn(2, ':'); let (Some(code), Some(issuer), None) = (iter.next(), iter.next(), iter.next()) else { return Err(Error::CannotParseAsset(value.to_string())); }; - let issuer = issuer.parse()?; - Ok(Asset(match code.parse()? { - AssetCode::CreditAlphanum4(asset_code) => { - xdr::Asset::CreditAlphanum4(AlphaNum4 { asset_code, issuer }) - } - AssetCode::CreditAlphanum12(asset_code) => { - xdr::Asset::CreditAlphanum12(AlphaNum12 { asset_code, issuer }) - } - })) + Ok(Asset::Asset(code.parse()?, issuer.parse()?)) } } -impl From for xdr::Asset { - fn from(builder: Asset) -> Self { - builder.0 - } -} - -impl From<&Asset> for xdr::Asset { - fn from(builder: &Asset) -> Self { - builder.clone().into() +impl Asset { + pub fn resolve(&self, locator: &locator::Args) -> Result { + Ok(match self { + Asset::Asset(code, issuer) => { + let issuer = issuer.resolve_muxed_account(locator, None)?.account_id(); + match code.clone() { + AssetCode::CreditAlphanum4(asset_code) => { + xdr::Asset::CreditAlphanum4(AlphaNum4 { asset_code, issuer }) + } + AssetCode::CreditAlphanum12(asset_code) => { + xdr::Asset::CreditAlphanum12(AlphaNum12 { asset_code, issuer }) + } + } + } + Asset::Native => xdr::Asset::Native, + }) } } diff --git a/cmd/soroban-cli/src/utils.rs b/cmd/soroban-cli/src/utils.rs index 0c4207a4e..3efe619ef 100644 --- a/cmd/soroban-cli/src/utils.rs +++ b/cmd/soroban-cli/src/utils.rs @@ -125,13 +125,13 @@ pub fn is_hex_string(s: &str) -> bool { } pub fn contract_id_hash_from_asset( - asset: impl Into, + asset: &Asset, network_passphrase: &str, ) -> stellar_strkey::Contract { let network_id = Hash(Sha256::digest(network_passphrase.as_bytes()).into()); let preimage = HashIdPreimage::ContractId(HashIdPreimageContractId { network_id, - contract_id_preimage: ContractIdPreimage::Asset(asset.into()), + contract_id_preimage: ContractIdPreimage::Asset(asset.clone()), }); let preimage_xdr = preimage .to_xdr(Limits::none()) From 4dd01ebe0ab4b426b5c4f74b512ef71c0bf785ea Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 29 Nov 2024 14:52:19 -0500 Subject: [PATCH 59/60] fix: add test and fix others --- .../tests/it/integration/tx/operations.rs | 25 +++++++++++++------ .../soroban-test/tests/it/integration/wrap.rs | 14 ++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index b89bdb2bf..2e28dbc1f 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -1,4 +1,5 @@ use soroban_cli::{ + config::locator, tx::{builder, ONE_XLM}, utils::contract_id_hash_from_asset, xdr::{self, ReadXdr, SequenceNumber}, @@ -267,20 +268,24 @@ async fn account_merge_with_alias() { #[tokio::test] async fn set_trustline_flags() { let sandbox = &TestEnv::new(); - let (test, issuer) = setup_accounts(sandbox); - let asset = format!("usdc:{issuer}"); - issue_asset(sandbox, &test, &asset, 100_000, 100).await; + let (test, test1) = setup_accounts(sandbox); + let asset = "usdc:test1"; + issue_asset(sandbox, &test, asset, 100_000, 100).await; sandbox .new_assert_cmd("contract") .arg("asset") .arg("deploy") .arg("--asset") - .arg(&asset) + .arg(asset) .assert() .success(); let id = contract_id_hash_from_asset( - asset.parse::().unwrap(), - &sandbox.network.network_passphrase, + &format!("usdc:{test1}") + .parse::() + .unwrap() + .resolve(&locator::Args::default()) + .unwrap(), + &sandbox.network_passphrase, ); // sandbox // .new_assert_cmd("contract") @@ -542,8 +547,12 @@ async fn change_trust() { // wrap_cmd(&asset).run().await.unwrap(); let id = contract_id_hash_from_asset( - asset.parse::().unwrap(), - &sandbox.network.network_passphrase, + &asset + .parse::() + .unwrap() + .resolve(&locator::Args::default()) + .unwrap(), + &sandbox.network_passphrase, ); sandbox .new_assert_cmd("contract") diff --git a/cmd/crates/soroban-test/tests/it/integration/wrap.rs b/cmd/crates/soroban-test/tests/it/integration/wrap.rs index 3fef56ef9..961cd6b4a 100644 --- a/cmd/crates/soroban-test/tests/it/integration/wrap.rs +++ b/cmd/crates/soroban-test/tests/it/integration/wrap.rs @@ -1,4 +1,4 @@ -use soroban_cli::{tx::builder, utils::contract_id_hash_from_asset}; +use soroban_cli::{config::locator, tx::builder, utils::contract_id_hash_from_asset}; use soroban_test::{AssertExt, TestEnv, LOCAL_NETWORK_PASSPHRASE}; #[tokio::test] @@ -12,21 +12,23 @@ async fn burn() { .arg("test") .assert() .stdout_as_str(); - let asset = format!("native:{address}"); + let asset = "native"; sandbox .new_assert_cmd("contract") .arg("asset") .arg("deploy") .arg("--source=test") .arg("--asset") - .arg(&asset) + .arg(asset) .assert() .success(); - // wrap_cmd(&asset).run().await.unwrap(); - let asset: builder::Asset = asset.parse().unwrap(); + let asset = asset + .parse::() + .unwrap() + .resolve(&locator::Args::default()) + .unwrap(); let hash = contract_id_hash_from_asset(&asset, &network_passphrase); let id = stellar_strkey::Contract(hash.0).to_string(); - println!("{id}, {address}"); sandbox .new_assert_cmd("contract") .args([ From a47d25550e136d29a6635f61004fa6590873e4bf Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 23 Jan 2025 08:59:10 -0500 Subject: [PATCH 60/60] fix: tests --- cmd/crates/soroban-test/tests/it/integration/tx/operations.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index 2e28dbc1f..9da1ed863 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -285,7 +285,7 @@ async fn set_trustline_flags() { .unwrap() .resolve(&locator::Args::default()) .unwrap(), - &sandbox.network_passphrase, + &sandbox.network.network_passphrase, ); // sandbox // .new_assert_cmd("contract") @@ -552,7 +552,7 @@ async fn change_trust() { .unwrap() .resolve(&locator::Args::default()) .unwrap(), - &sandbox.network_passphrase, + &sandbox.network.network_passphrase, ); sandbox .new_assert_cmd("contract")