1use ant_protocol::node::get_antnode_root_dir;
10use eyre::eyre;
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
45fn keypair_from_path(path: impl AsRef<Path>) -> eyre::Result<Keypair> {
46 let keypair = match std::fs::read(&path) {
47 Ok(key) => {
49 let keypair = Keypair::ed25519_from_bytes(key)
50 .map_err(|err| eyre!("could not read ed25519 key from file: {err}"))?;
51
52 info!("loaded secret key from file: {:?}", path.as_ref());
53
54 keypair
55 }
56 Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
58 let secret_key = libp2p::identity::ed25519::SecretKey::generate();
59 let mut file = create_secret_key_file(&path)
60 .map_err(|err| eyre!("could not create secret key file: {err}"))?;
61 file.write_all(secret_key.as_ref())?;
62
63 info!("generated new key and stored to file: {:?}", path.as_ref());
64
65 libp2p::identity::ed25519::Keypair::from(secret_key).into()
66 }
67 Err(err) => {
69 return Err(eyre!("failed to read secret key file: {err}"));
70 }
71 };
72
73 Ok(keypair)
74}
75
76fn create_secret_key_file(path: impl AsRef<Path>) -> eyre::Result<std::fs::File, std::io::Error> {
77 let mut opt = std::fs::OpenOptions::new();
78 let _ = opt.write(true).create_new(true);
79
80 #[cfg(unix)]
82 {
83 use std::os::unix::fs::OpenOptionsExt;
84 let _ = opt.mode(0o600);
85 }
86
87 opt.open(path)
88}