Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Do not overwrite existing keys when generating new ones. #1709

Merged
merged 2 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,7 @@ Generate a new identity with a seed phrase, currently 12 words
* `--fund` — Fund generated key pair

Default value: `false`
* `--overwrite` — Overwrite existing identity if it already exists



Expand Down
2 changes: 1 addition & 1 deletion cmd/crates/soroban-test/tests/it/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mod constructor;
mod cookbook;
mod custom_types;
mod dotenv;
mod fund;
mod hello_world;
mod keys;
mod snapshot;
mod tx;
mod util;
Expand Down
23 changes: 0 additions & 23 deletions cmd/crates/soroban-test/tests/it/integration/fund.rs

This file was deleted.

76 changes: 76 additions & 0 deletions cmd/crates/soroban-test/tests/it/integration/keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use predicates::prelude::predicate;
use soroban_test::AssertExt;
use soroban_test::TestEnv;

fn pubkey_for_identity(sandbox: &TestEnv, name: &str) -> String {
let output = sandbox
.new_assert_cmd("keys")
.arg("address")
.arg(name)
.assert()
.stdout_as_str();
return output;
}

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn fund() {
let sandbox = &TestEnv::new();
sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test2")
.assert()
.success();
sandbox
.new_assert_cmd("keys")
.arg("fund")
.arg("test2")
.assert()
// Don't expect error if friendbot indicated that the account is
// already fully funded to the starting balance, because the
// user's goal is to get funded, and the account is funded
// so it is success much the same.
.success();
}

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn overwrite_identity() {
let sandbox = &TestEnv::new();
sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test2")
.assert()
.success();

let initial_pubkey = sandbox
.new_assert_cmd("keys")
.arg("address")
.arg("test2")
.assert()
.stdout_as_str();

sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test2")
.assert()
.stderr(predicate::str::contains(
"error: An identity with the name 'test2' already exists",
));

assert_eq!(initial_pubkey, pubkey_for_identity(&sandbox, "test2"));

sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test2")
.arg("--overwrite")
.assert()
.stderr(predicate::str::contains("Overwriting identity 'test2'"))
.success();

assert_ne!(initial_pubkey, pubkey_for_identity(&sandbox, "test2"));
}
26 changes: 25 additions & 1 deletion cmd/soroban-cli/src/commands/keys/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ use crate::{commands::global, print::Print};
pub enum Error {
#[error(transparent)]
Config(#[from] locator::Error),

#[error(transparent)]
Secret(#[from] secret::Error),

#[error(transparent)]
Network(#[from] network::Error),

#[error("An identity with the name '{0}' already exists")]
IdentityAlreadyExists(String),
}

#[derive(Debug, clap::Parser, Clone)]
Expand Down Expand Up @@ -52,29 +57,47 @@ pub struct Cmd {
/// Fund generated key pair
#[arg(long, default_value = "false")]
pub fund: bool,

/// Overwrite existing identity if it already exists.
#[arg(long)]
pub overwrite: bool,
}

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let print = Print::new(global_args.quiet);

if self.config_locator.read_identity(&self.name).is_ok() {
if !self.overwrite {
return Err(Error::IdentityAlreadyExists(self.name.clone()));
}

print.infoln(format!("Overwriting identity '{}'", &self.name));
fnando marked this conversation as resolved.
Show resolved Hide resolved
}

if !self.fund {
Print::new(global_args.quiet).warnln(
print.warnln(
"Behavior of `generate` will change in the \
future, and it will no longer fund by default. If you want to fund please \
provide `--fund` flag. If you don't need to fund your keys in the future, ignore this \
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
};

self.config_locator.write_identity(&self.name, &secret)?;

if !self.no_fund {
let addr = secret.public_key(self.hd_path)?;
let network = self.network.get(&self.config_locator)?;
Expand All @@ -86,6 +109,7 @@ impl Cmd {
})
.unwrap_or_default();
}

Ok(())
}
}
Loading