Skip to content

Commit 343069b

Browse files
authored
Add --hd-path flag to keys add --secure-store (#2539)
1 parent 9571449 commit 343069b

4 files changed

Lines changed: 64 additions & 3 deletions

File tree

FULL_HELP_DOCS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,7 @@ Add a new identity (keypair, ledger, OS specific secure store)
11381138

11391139
- `--public-key <PUBLIC_KEY>` — Add a public key, ed25519, or muxed account, e.g. G1.., M2..
11401140
- `--overwrite` — Overwrite existing identity if it already exists. When combined with --secure-store, also replaces the existing Secure Store entry
1141+
- `--hd-path <HD_PATH>` — When importing a seed phrase into the Secure Store, which `hd_path` to derive the key at
11411142

11421143
###### **Options (Global):**
11431144

@@ -1206,7 +1207,7 @@ Generate a new identity using a 24-word seed phrase The seed phrase can be store
12061207

12071208
On Mac this uses Keychain, on Windows it is Secure Store Service, and on \*nix platforms it uses a combination of the kernel keyutils and DBus-based Secret Service.
12081209

1209-
- `--hd-path <HD_PATH>`When generating a secret key, which `hd_path` should be used from the original `seed_phrase`
1210+
- `--hd-path <HD_PATH>`With `--as-secret` or `--secure-store`, which `hd_path` to derive the key at from the seed phrase
12101211
- `--fund` — Fund generated key pair
12111212

12121213
Default value: `false`

cmd/crates/soroban-test/tests/it/integration/secure_store.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,60 @@ async fn secure_store_key_management() {
113113
.success()
114114
.stdout_as_str();
115115
assert!(new_secure_store_address.starts_with('G'));
116+
117+
// `keys add --secure-store --hd-path N` must derive and cache the public
118+
// key at the requested HD path, and persist `hd_path` in the identity TOML.
119+
let seed_phrase = "aisle reflect depart add safe fury dress artist bronze abuse warrior clap inquiry ask mandate deputy view trade debate flip priority boy depart recipe";
120+
121+
let add_default = "secure-store-add-default";
122+
sandbox
123+
.new_assert_cmd("keys")
124+
.write_stdin(format!("{seed_phrase}\n"))
125+
.args(["add", add_default, "--secure-store"])
126+
.assert()
127+
.success();
128+
let address_default = sandbox
129+
.new_assert_cmd("keys")
130+
.args(["address", add_default])
131+
.assert()
132+
.success()
133+
.stdout_as_str();
134+
135+
let add_hd_path = "secure-store-add-hd-path";
136+
sandbox
137+
.new_assert_cmd("keys")
138+
.write_stdin(format!("{seed_phrase}\n"))
139+
.args(["add", add_hd_path, "--secure-store", "--hd-path", "5"])
140+
.assert()
141+
.success();
142+
let address_hd_path = sandbox
143+
.new_assert_cmd("keys")
144+
.args(["address", add_hd_path, "--hd-path", "5"])
145+
.assert()
146+
.success()
147+
.stdout_as_str();
148+
149+
assert!(address_hd_path.starts_with('G'));
150+
assert_ne!(
151+
address_default, address_hd_path,
152+
"expected --hd-path 5 to derive a different public key than the default path"
153+
);
154+
155+
let identity_path = sandbox
156+
.config_dir()
157+
.join("identity")
158+
.join(format!("{add_hd_path}.toml"));
159+
let identity_toml = std::fs::read_to_string(&identity_path).unwrap_or_else(|err| {
160+
panic!("expected identity file at {identity_path:?}: {err}");
161+
});
162+
assert!(
163+
identity_toml.contains("hd_path = 5"),
164+
"expected hd_path = 5 to be persisted after `keys add --secure-store --hd-path 5`, \
165+
but identity file was:\n{identity_toml}"
166+
);
167+
assert!(
168+
identity_toml.contains(&format!("public_key = \"{}\"", address_hd_path.trim())),
169+
"expected cached public_key to match the address derived at hd_path 5, \
170+
but identity file was:\n{identity_toml}"
171+
);
116172
}

cmd/soroban-cli/src/commands/keys/add.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ pub struct Cmd {
6161
/// --secure-store, also replaces the existing Secure Store entry.
6262
#[arg(long)]
6363
pub overwrite: bool,
64+
65+
/// When importing a seed phrase into the Secure Store, which `hd_path` to derive the key at.
66+
#[arg(long)]
67+
pub hd_path: Option<usize>,
6468
}
6569

6670
impl Cmd {
@@ -113,7 +117,7 @@ impl Cmd {
113117
print,
114118
&self.name,
115119
&seed_phrase,
116-
None,
120+
self.hd_path,
117121
self.overwrite,
118122
)?)
119123
} else {

cmd/soroban-cli/src/commands/keys/generate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub struct Cmd {
5050
#[command(flatten)]
5151
pub config_locator: locator::Args,
5252

53-
/// When generating a secret key, which `hd_path` should be used from the original `seed_phrase`.
53+
/// With `--as-secret` or `--secure-store`, which `hd_path` to derive the key at from the seed phrase.
5454
#[arg(long)]
5555
pub hd_path: Option<usize>,
5656

0 commit comments

Comments
 (0)