Skip to content

Commit 835202f

Browse files
authored
feat(signer): Request wallets instead of accounts in Dirk setup (#303)
1 parent 988d606 commit 835202f

File tree

6 files changed

+36
-78
lines changed

6 files changed

+36
-78
lines changed

config.example.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,13 @@ url = "http://0xa119589bb33ef52acbb8116832bec2b58fca590fe5c85eac5d3230b44d5bc09f
171171
# server_name = "localhost-1"
172172
# Complete URL of a Dirk gateway
173173
# url = "https://localhost:8881"
174-
# Accounts to use as consensus keys
175-
# accounts = ["Wallet1/Account1", "DistributedWallet/Account1"]
174+
# Wallets to load consensus keys from
175+
# accounts = ["Wallet1", "DistributedWallet"]
176176

177177
# [[signer.dirk.hosts]]
178178
# server_name = "localhost-2"
179179
# url = "https://localhost:8882"
180-
# accounts = ["Wallet2/Account2", "DistributedWallet/Account1"]
180+
# accounts = ["Wallet2", "DistributedWallet"]
181181

182182
# Configuration for how the Signer module should store proxy delegations.
183183
# OPTIONAL

crates/common/src/config/signer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ pub struct DirkHostConfig {
3737
pub server_name: Option<String>,
3838
/// Complete URL of the Dirk server
3939
pub url: Url,
40-
/// Accounts used as consensus keys
41-
pub accounts: Vec<String>,
40+
/// Wallets to load consensus keys from
41+
pub wallets: Vec<String>,
4242
}
4343

4444
#[derive(Debug, Serialize, Deserialize, Clone)]

crates/signer/src/manager/dirk.rs

Lines changed: 26 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
use std::{
2-
collections::{HashMap, HashSet},
3-
io::Write,
4-
path::PathBuf,
5-
};
1+
use std::{collections::HashMap, io::Write, path::PathBuf};
62

73
use alloy::{hex, rpc::types::beacon::constants::BLS_SIGNATURE_BYTES_LEN};
84
use blsful::inner_types::{Field, G2Affine, G2Projective, Group, Scalar};
@@ -37,10 +33,10 @@ enum Account {
3733
}
3834

3935
impl Account {
40-
pub fn full_name(&self) -> String {
36+
pub fn name(&self) -> &str {
4137
match self {
42-
Account::Simple(account) => format!("{}/{}", account.wallet, account.name),
43-
Account::Distributed(account) => format!("{}/{}", account.wallet, account.name),
38+
Account::Simple(account) => &account.name,
39+
Account::Distributed(account) => &account.name,
4440
}
4541
}
4642
}
@@ -49,7 +45,6 @@ impl Account {
4945
struct SimpleAccount {
5046
public_key: BlsPublicKey,
5147
connection: Channel,
52-
wallet: String,
5348
name: String,
5449
}
5550

@@ -58,7 +53,6 @@ struct DistributedAccount {
5853
composite_public_key: BlsPublicKey,
5954
participants: HashMap<u32, Channel>,
6055
threshold: u32,
61-
wallet: String,
6256
name: String,
6357
}
6458

@@ -107,14 +101,8 @@ impl DirkManager {
107101
}
108102
};
109103

110-
let wallets: HashSet<String> = host
111-
.accounts
112-
.iter()
113-
.map(|account| decompose_name(account).unwrap_or_default().0)
114-
.collect();
115-
116104
let accounts_response = match ListerClient::new(channel.clone())
117-
.list_accounts(ListAccountsRequest { paths: wallets.into_iter().collect() })
105+
.list_accounts(ListAccountsRequest { paths: host.wallets.clone() })
118106
.await
119107
{
120108
Ok(res) => res,
@@ -130,12 +118,7 @@ impl DirkManager {
130118
}
131119

132120
let accounts_response = accounts_response.into_inner();
133-
load_simple_accounts(
134-
accounts_response.accounts,
135-
&host,
136-
&channel,
137-
&mut consensus_accounts,
138-
);
121+
load_simple_accounts(accounts_response.accounts, &channel, &mut consensus_accounts);
139122
load_distributed_accounts(
140123
accounts_response.distributed_accounts,
141124
&host,
@@ -144,15 +127,6 @@ impl DirkManager {
144127
)
145128
.map_err(|error| warn!("{error}"))
146129
.ok();
147-
148-
for account in host.accounts {
149-
if !consensus_accounts
150-
.values()
151-
.any(|account| account.full_name() == account.full_name())
152-
{
153-
warn!("Account {account} not found in server {}", host.url);
154-
}
155-
}
156130
}
157131

158132
debug!(
@@ -293,10 +267,7 @@ impl DirkManager {
293267
.sign(SignRequest {
294268
data: object_root.to_vec(),
295269
domain: compute_domain(self.chain, COMMIT_BOOST_DOMAIN).to_vec(),
296-
id: Some(sign_request::Id::Account(format!(
297-
"{}/{}",
298-
account.wallet, account.name
299-
))),
270+
id: Some(sign_request::Id::Account(account.name.clone())),
300271
})
301272
.map(|res| (res, *id))
302273
.await
@@ -392,7 +363,7 @@ impl DirkManager {
392363

393364
let response = AccountManagerClient::new(consensus.connection.clone())
394365
.generate(GenerateRequest {
395-
account: format!("{}/{}/{module}/{uuid}", consensus.wallet, consensus.name),
366+
account: format!("{}/{module}/{uuid}", consensus.name),
396367
passphrase: password.as_bytes().to_vec(),
397368
participants: 1,
398369
signing_threshold: 1,
@@ -418,7 +389,6 @@ impl DirkManager {
418389
inner: Account::Simple(SimpleAccount {
419390
public_key: proxy_key,
420391
connection: consensus.connection.clone(),
421-
wallet: consensus.wallet.clone(),
422392
name: format!("{}/{module}/{uuid}", consensus.name),
423393
}),
424394
};
@@ -450,7 +420,7 @@ impl DirkManager {
450420
for (id, channel) in consensus.participants.iter() {
451421
let Ok(response) = AccountManagerClient::new(channel.clone())
452422
.generate(GenerateRequest {
453-
account: format!("{}/{}/{module}/{uuid}", consensus.wallet, consensus.name),
423+
account: format!("{}/{module}/{uuid}", consensus.name),
454424
passphrase: password.as_bytes().to_vec(),
455425
participants: consensus.participants.len() as u32,
456426
signing_threshold: consensus.threshold,
@@ -479,7 +449,6 @@ impl DirkManager {
479449
composite_public_key: proxy_key,
480450
participants: consensus.participants.clone(),
481451
threshold: consensus.threshold,
482-
wallet: consensus.wallet.clone(),
483452
name: format!("{}/{module}/{uuid}", consensus.name),
484453
}),
485454
};
@@ -506,8 +475,8 @@ impl DirkManager {
506475

507476
/// Store the password for a proxy account in disk
508477
fn store_password(&self, account: &ProxyAccount, password: String) -> eyre::Result<()> {
509-
let full_name = account.inner.full_name();
510-
let (parent, name) = full_name.rsplit_once('/').ok_or_eyre("Invalid account name")?;
478+
let name = account.inner.name();
479+
let (parent, name) = name.rsplit_once('/').ok_or_eyre("Invalid account name")?;
511480
let parent_path = self.secrets_path.join(parent);
512481

513482
std::fs::create_dir_all(parent_path.clone())?;
@@ -530,7 +499,7 @@ impl DirkManager {
530499
let request = async move {
531500
let response = AccountManagerClient::new(channel.clone())
532501
.unlock(UnlockAccountRequest {
533-
account: account.full_name(),
502+
account: account.name().to_string(),
534503
passphrase: password.as_bytes().to_vec(),
535504
})
536505
.await;
@@ -584,40 +553,26 @@ async fn connect(
584553
.map_err(eyre::Error::from)
585554
}
586555

587-
/// Decompose a full account name into wallet and name
588-
fn decompose_name(full_name: &str) -> eyre::Result<(String, String)> {
589-
full_name
590-
.split_once('/')
591-
.map(|(wallet, name)| (wallet.to_string(), name.to_string()))
592-
.ok_or_else(|| eyre::eyre!("Invalid account name"))
593-
}
594-
595556
/// Load `SimpleAccount`s into the consensus accounts map
596557
fn load_simple_accounts(
597558
accounts: Vec<crate::proto::v1::Account>,
598-
host: &DirkHostConfig,
599559
channel: &Channel,
600560
consensus_accounts: &mut HashMap<BlsPublicKey, Account>,
601561
) {
602562
for account in accounts {
603-
if !host.accounts.contains(&account.name) {
563+
if name_matches_proxy(&account.name) {
564+
debug!(account = account.name, "Ignoring account assuming it's a proxy key");
604565
continue;
605566
}
606567

607-
let Ok((wallet, name)) = decompose_name(&account.name) else {
608-
warn!("Invalid account name {}", account.name);
609-
continue;
610-
};
611-
612568
match BlsPublicKey::try_from(account.public_key.as_slice()) {
613569
Ok(public_key) => {
614570
consensus_accounts.insert(
615571
public_key,
616572
Account::Simple(SimpleAccount {
617573
public_key,
618574
connection: channel.clone(),
619-
wallet,
620-
name,
575+
name: account.name,
621576
}),
622577
);
623578
}
@@ -643,7 +598,8 @@ fn load_distributed_accounts(
643598
.ok_or(eyre::eyre!("Host name not found for server {}", host.url))?;
644599

645600
for account in accounts {
646-
if !host.accounts.contains(&account.name) {
601+
if name_matches_proxy(&account.name) {
602+
debug!(account = account.name, "Ignoring account assuming it's a proxy key");
647603
continue;
648604
}
649605

@@ -677,11 +633,6 @@ fn load_distributed_accounts(
677633
}
678634
}
679635
None => {
680-
let Ok((wallet, name)) = decompose_name(&account.name) else {
681-
warn!("Invalid account name {}", account.name);
682-
continue;
683-
};
684-
685636
let mut participants = HashMap::with_capacity(account.participants.len());
686637
participants.insert(participant_id as u32, channel.clone());
687638

@@ -691,8 +642,7 @@ fn load_distributed_accounts(
691642
composite_public_key: public_key,
692643
participants,
693644
threshold: account.signing_threshold,
694-
wallet,
695-
name,
645+
name: account.name,
696646
}),
697647
);
698648
}
@@ -752,6 +702,14 @@ fn random_password() -> String {
752702
hex::encode(password_bytes)
753703
}
754704

705+
/// Returns whether the name of an account has a proxy name format.
706+
///
707+
/// i.e., `{wallet}/{consensus_proxy}/{module}/{uuid}`
708+
fn name_matches_proxy(name: &str) -> bool {
709+
name.split("/").count() > 3 &&
710+
name.rsplit_once("/").is_some_and(|(_, name)| uuid::Uuid::parse_str(name).is_ok())
711+
}
712+
755713
mod test {
756714

757715
#[test]

docs/docs/get_started/configuration.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,16 +256,16 @@ ca_cert_path = "/path/to/ca.crt"
256256
[[signer.dirk.hosts]]
257257
server_name = "localhost-1"
258258
url = "https://localhost-1:8081"
259-
accounts = ["SomeWallet/SomeAccount", "DistributedWallet/Account1"]
259+
wallets = ["SomeWallet", "DistributedWallet"]
260260

261261
[[signer.dirk.hosts]]
262262
server_name = "localhost-2"
263263
url = "https://localhost-2:8082"
264-
accounts = ["AnotherWallet/AnotherAccount", "DistributedWallet/Account1"]
264+
wallets = ["AnotherWallet", "DistributedWallet"]
265265
```
266266

267267
- `cert_path` and `key_path` are the paths to the client certificate and key used to authenticate with Dirk.
268-
- `accounts` is a list of accounts that the Signer module will consider as the consensus keys. Each account has the format `<WALLET_NAME>/<ACCOUNT>`. Accounts can be from different wallets. Generated proxy keys will have format `<WALLET_NAME>/<ACCOUNT>/<MODULE_ID>/<UUID>`.
268+
- `wallets` is a list of wallets from which the Signer module will load all accounts as consensus keys. Generated proxy keys will have format `<WALLET_NAME>/<ACCOUNT>/<MODULE_ID>/<UUID>`, so accounts found with that pattern will be ignored.
269269
- `secrets_path` is the path to the folder containing the passwords of the generated proxy accounts, which will be stored in `<secrets_path>/<WALLET_NAME>/<ACCOUNT>/<MODULE_ID>/<UUID>.pass`.
270270

271271
Additionally, you can set a proxy store so that the delegation signatures for generated proxy keys are stored locally. As these signatures are not sensitive, the only supported store type is `File`:

examples/configs/dirk_signer.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ ca_cert_path = "/path/to/ca.crt"
1818
# Example of a single Dirk host
1919
[[signer.dirk.hosts]]
2020
url = "https://gateway.dirk.url"
21-
accounts = ["wallet1/accountX", "wallet2/accountY"]
21+
wallets = ["wallet1", "wallet2"]
2222

2323
[signer.dirk.store]
2424
proxy_dir = "/path/to/proxies"

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,4 @@ clean:
194194

195195
# Runs the suite of tests for all commit-boost crates.
196196
test:
197-
cargo test --all-features
197+
cargo test --all-features

0 commit comments

Comments
 (0)