Skip to content

Commit fc64fff

Browse files
Fix signing with a secure store key (#1982)
* Add keys integration tests * Test creating a create-account tx and signing with secure store key * Use Secret's signer fn to get the signer instead of creating one using the signing key * Add secure-store-tests to makefile e2e-test * Add & start gnome-keyring for linux integration tests * Enable additional-libs for rpc-tests
1 parent 56d19c5 commit fc64fff

6 files changed

Lines changed: 134 additions & 9 deletions

File tree

.github/workflows/rpc-tests.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,20 @@ jobs:
3232
- uses: actions/checkout@v4
3333
- uses: stellar/actions/rust-cache@main
3434
- run: rustup update
35-
- run: sudo apt update && sudo apt install -y libudev-dev libdbus-1-dev
35+
- run: sudo apt update && sudo apt install -y libudev-dev libdbus-1-dev gnome-keyring
3636
if: runner.os == 'Linux'
37-
- run: cargo build
37+
- name: Start gnome-keyring
38+
if: runner.os == 'Linux'
39+
# run gnome-keyring with 'foobar' as password for the login keyring
40+
# this will create a new login keyring and unlock it
41+
# the login password doesn't matter, but the keyring must be unlocked for the tests to work
42+
# this is based on the ci workflow in the keyring crate repo
43+
run: gnome-keyring-daemon --components=secrets --daemonize --unlock <<< 'foobar'
44+
- name: Check GNOME Keyring
45+
if: runner.os == 'Linux'
46+
run: |
47+
gnome-keyring-daemon
48+
- run: cargo build --features additional-libs
3849
- run: rustup target add wasm32-unknown-unknown
3950
- run: make build-test-wasms
4051
- run: SOROBAN_PORT=8000 cargo test --features it --package soroban-test --test it -- integration --test-threads=1

cmd/crates/soroban-test/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ default = []
5555
it = []
5656
emulator-tests = ["stellar-ledger/emulator-tests"]
5757
version_lt_23 = []
58-
version_gte_23 = []
58+
version_gte_23 = []

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod dotenv;
66
mod hello_world;
77
mod init;
88
mod keys;
9+
mod secure_store;
910
mod snapshot;
1011
mod tx;
1112
mod util;

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ async fn fund() {
3333
.success();
3434
}
3535

36+
#[tokio::test]
37+
async fn secret() {
38+
let sandbox = &TestEnv::new();
39+
sandbox
40+
.new_assert_cmd("keys")
41+
.arg("generate")
42+
.arg("test2")
43+
.assert()
44+
.success();
45+
sandbox
46+
.new_assert_cmd("keys")
47+
.arg("secret")
48+
.arg("test2")
49+
.assert()
50+
.success();
51+
}
52+
3653
#[tokio::test]
3754
#[allow(clippy::too_many_lines)]
3855
async fn overwrite_identity() {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use predicates::prelude::predicate;
2+
use soroban_cli::tx::ONE_XLM;
3+
use soroban_test::{AssertExt, TestEnv};
4+
5+
fn secure_store_key(sandbox: &TestEnv, name: &str) -> String {
6+
sandbox
7+
.new_assert_cmd("keys")
8+
.args(["generate", "--fund", "--secure-store", name])
9+
.assert()
10+
.success()
11+
.stdout_as_str();
12+
13+
sandbox
14+
.new_assert_cmd("keys")
15+
.args(["address", name])
16+
.assert()
17+
.success()
18+
.stdout_as_str()
19+
}
20+
21+
// test that we can create a create-account tx and sign it with a secure-store key
22+
#[tokio::test]
23+
async fn create_account() {
24+
let sandbox = &TestEnv::new();
25+
let secure_store_address = secure_store_key(sandbox, "secure-store");
26+
27+
sandbox
28+
.new_assert_cmd("keys")
29+
.args(["generate", "--no-fund", "new"])
30+
.assert()
31+
.success();
32+
let new_address = sandbox
33+
.new_assert_cmd("keys")
34+
.args(["address", "new"])
35+
.assert()
36+
.success()
37+
.stdout_as_str();
38+
39+
let client = sandbox.network.rpc_client().unwrap();
40+
let secure_account = client.get_account(&secure_store_address).await.unwrap();
41+
42+
let starting_balance = ONE_XLM * 100;
43+
sandbox
44+
.new_assert_cmd("tx")
45+
.args([
46+
"new",
47+
"create-account",
48+
"--destination",
49+
new_address.as_str(),
50+
"--starting-balance",
51+
starting_balance.to_string().as_str(),
52+
"--source",
53+
"secure-store",
54+
])
55+
.assert()
56+
.success()
57+
.stdout_as_str();
58+
59+
let secure_account_after = client.get_account(&secure_store_address).await.unwrap();
60+
assert!(secure_account_after.balance < secure_account.balance);
61+
62+
let new_account = client.get_account(&new_address).await.unwrap();
63+
assert_eq!(new_account.balance, starting_balance);
64+
}
65+
66+
#[tokio::test]
67+
async fn get_secret_key() {
68+
let sandbox = &TestEnv::new();
69+
sandbox
70+
.new_assert_cmd("keys")
71+
.args(["generate", "secret-key-test", "--secure-store"])
72+
.assert()
73+
.success();
74+
sandbox
75+
.new_assert_cmd("keys")
76+
.arg("secret")
77+
.arg("secret-key-test")
78+
.assert()
79+
.stderr(predicate::str::contains("does not reveal secret key"))
80+
.failure();
81+
}
82+
83+
#[tokio::test]
84+
async fn public_key_with_secure_store() {
85+
let sandbox = &TestEnv::new();
86+
sandbox
87+
.new_assert_cmd("keys")
88+
.args(["generate", "public-key-test", "--secure-store"])
89+
.assert()
90+
.success();
91+
sandbox
92+
.new_assert_cmd("keys")
93+
.arg("public-key")
94+
.arg("public-key-test")
95+
.assert()
96+
.stdout(predicate::str::contains("G"))
97+
.success();
98+
}

cmd/soroban-cli/src/config/mod.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77

88
use crate::{
99
print::Print,
10-
signer::{self, LocalKey, Signer, SignerKind},
10+
signer,
1111
xdr::{self, SequenceNumber, Transaction, TransactionEnvelope},
1212
Pwd,
1313
};
@@ -89,12 +89,10 @@ impl Args {
8989

9090
#[allow(clippy::unused_async)]
9191
pub async fn sign(&self, tx: Transaction) -> Result<TransactionEnvelope, Error> {
92-
let key = self.key_pair()?;
92+
let key = &self.source_account.resolve_secret(&self.locator)?;
93+
let signer = key.signer(self.hd_path, Print::new(false)).await?;
9394
let network = &self.get_network()?;
94-
let signer = Signer {
95-
kind: SignerKind::Local(LocalKey { key }),
96-
print: Print::new(false),
97-
};
95+
9896
Ok(signer.sign_tx(tx, network).await?)
9997
}
10098

0 commit comments

Comments
 (0)