1use eyre::eyre;
10use libp2p::PeerId;
11use libp2p::identity::Keypair;
12use std::io::Write;
13use std::path::{Path, PathBuf};
14
15pub fn get_root_dir_and_keypair(root_dir: &Option<PathBuf>) -> eyre::Result<(PathBuf, Keypair)> {
18 match root_dir {
19 Some(dir) => {
20 std::fs::create_dir_all(dir)?;
21
22 let secret_key_path = dir.join("secret-key");
23 Ok((dir.clone(), keypair_from_path(secret_key_path)?))
24 }
25 None => {
26 let secret_key = libp2p::identity::ed25519::SecretKey::generate();
27 let keypair: Keypair =
28 libp2p::identity::ed25519::Keypair::from(secret_key.clone()).into();
29 let peer_id = keypair.public().to_peer_id();
30
31 let dir = get_antnode_root_dir(peer_id)?;
32 std::fs::create_dir_all(&dir)?;
33
34 let secret_key_path = dir.join("secret-key");
35
36 let mut file = create_secret_key_file(secret_key_path)
37 .map_err(|err| eyre!("could not create secret key file: {err}"))?;
38 file.write_all(secret_key.as_ref())?;
39
40 Ok((dir, keypair))
41 }
42 }
43}
44
45pub fn get_antnode_root_dir(peer_id: PeerId) -> eyre::Result<PathBuf> {
47 let dir = dirs_next::data_dir()
48 .ok_or_else(|| eyre!("could not obtain data dir"))?
49 .join("autonomi")
50 .join("node")
51 .join(peer_id.to_string());
52 Ok(dir)
53}
54
55fn keypair_from_path(path: impl AsRef<Path>) -> eyre::Result<Keypair> {
56 let keypair = match std::fs::read(&path) {
57 Ok(key) => {
59 let keypair = Keypair::ed25519_from_bytes(key)
60 .map_err(|err| eyre!("could not read ed25519 key from file: {err}"))?;
61
62 info!("loaded secret key from file: {:?}", path.as_ref());
63
64 keypair
65 }
66 Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
68 let secret_key = libp2p::identity::ed25519::SecretKey::generate();
69 let mut file = create_secret_key_file(&path)
70 .map_err(|err| eyre!("could not create secret key file: {err}"))?;
71 file.write_all(secret_key.as_ref())?;
72
73 info!("generated new key and stored to file: {:?}", path.as_ref());
74
75 libp2p::identity::ed25519::Keypair::from(secret_key).into()
76 }
77 Err(err) => {
79 return Err(eyre!("failed to read secret key file: {err}"));
80 }
81 };
82
83 Ok(keypair)
84}
85
86fn create_secret_key_file(path: impl AsRef<Path>) -> eyre::Result<std::fs::File, std::io::Error> {
87 let mut opt = std::fs::OpenOptions::new();
88 let _ = opt.write(true).create_new(true);
89
90 #[cfg(unix)]
92 {
93 use std::os::unix::fs::OpenOptionsExt;
94 let _ = opt.mode(0o600);
95 }
96
97 opt.open(path)
98}