mina_node_account/
secret_key.rs1use super::AccountPublicKey;
2use mina_core::{
3 constants::GENESIS_PRODUCER_SK, EncryptedSecretKey, EncryptedSecretKeyFile, EncryptionError,
4};
5use mina_p2p_messages::{bigint::BigInt, v2::SignatureLibPrivateKeyStableV1};
6use mina_signer::{keypair::KeypairError, seckey::SecKeyError, CompressedPubKey, Keypair};
7use rand::{rngs::StdRng, CryptoRng, Rng, SeedableRng};
8use serde::{Deserialize, Serialize};
9use std::{fmt, fs, io, path::Path, str::FromStr};
10
11#[derive(Clone)]
12pub struct AccountSecretKey(Keypair);
13
14impl std::fmt::Debug for AccountSecretKey {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 f.debug_tuple("AccountSecretKey").field(&"***").finish()
17 }
18}
19
20lazy_static::lazy_static! {
21 static ref GENERATED_DETERMINISTIC: Vec<AccountSecretKey> = {
23 let mut rng = StdRng::seed_from_u64(0);
24 (0..10000)
25 .map(|_| AccountSecretKey::rand_with(&mut rng))
26 .collect()
27 };
28}
29
30impl AccountSecretKey {
31 const BASE58_CHECK_VERSION: u8 = 90;
32
33 pub fn genesis_producer() -> Self {
34 Self::from_str(GENESIS_PRODUCER_SK).unwrap()
35 }
36
37 pub fn deterministic(i: u64) -> Self {
38 GENERATED_DETERMINISTIC[i as usize].clone()
39 }
40
41 pub fn deterministic_iter() -> impl Iterator<Item = &'static AccountSecretKey> {
42 GENERATED_DETERMINISTIC.iter()
43 }
44
45 pub fn max_deterministic_count() -> usize {
46 GENERATED_DETERMINISTIC.len()
47 }
48
49 pub fn rand() -> Self {
50 Self::rand_with(rand::thread_rng())
51 }
52
53 pub fn rand_with(mut rng: impl Rng + CryptoRng) -> Self {
54 Self(Keypair::rand(&mut rng).unwrap())
55 }
56
57 pub fn from_bytes(bytes: &[u8]) -> Result<Self, KeypairError> {
58 let mut bytes: [u8; 32] = match bytes.try_into() {
59 Ok(bytes) => bytes,
60 Err(_) => return Err(KeypairError::SecretKey(SecKeyError::SecretKeyLength)),
61 };
62
63 bytes.reverse();
65
66 Ok(Self(Keypair::from_bytes(&bytes[..])?))
67 }
68
69 pub fn to_bytes(&self) -> [u8; 32] {
70 let mut bytes = hex::decode(self.0.to_hex()).unwrap();
72 bytes.reverse();
73 bytes.try_into().unwrap()
74 }
75
76 pub fn public_key(&self) -> AccountPublicKey {
77 self.0.public.clone().into()
78 }
79
80 pub fn public_key_compressed(&self) -> CompressedPubKey {
81 self.0.public.clone().into_compressed()
82 }
83
84 pub fn from_encrypted_file(
85 path: impl AsRef<Path>,
86 password: &str,
87 ) -> Result<Self, EncryptionError> {
88 Self::from_encrypted_reader(fs::File::open(path)?, password)
89 }
90
91 pub fn from_encrypted_reader(
92 reader: impl io::Read,
93 password: &str,
94 ) -> Result<Self, EncryptionError> {
95 let encrypted: EncryptedSecretKeyFile = serde_json::from_reader(reader)?;
96 Self::from_encrypted(&encrypted, password)
97 }
98
99 pub fn from_encrypted(
100 encrypted: &EncryptedSecretKeyFile,
101 password: &str,
102 ) -> Result<Self, EncryptionError> {
103 let decrypted: Vec<u8> = Self::try_decrypt(encrypted, password)?;
104 AccountSecretKey::from_bytes(&decrypted[1..])
105 .map_err(|err| EncryptionError::Other(err.to_string()))
106 }
107
108 pub fn to_encrypted_file(
109 &self,
110 path: impl AsRef<Path>,
111 password: &str,
112 ) -> Result<(), EncryptionError> {
113 if path.as_ref().exists() {
114 panic!("File {} already exists", path.as_ref().display())
115 }
116
117 let f = fs::File::create(path)?;
118 let encrypted = Self::try_encrypt(&self.to_bytes(), password)?;
119
120 serde_json::to_writer(f, &encrypted)?;
121 Ok(())
122 }
123}
124
125impl EncryptedSecretKey for AccountSecretKey {}
126
127impl From<AccountSecretKey> for Keypair {
128 fn from(value: AccountSecretKey) -> Self {
129 value.0
130 }
131}
132
133impl From<&AccountSecretKey> for SignatureLibPrivateKeyStableV1 {
134 fn from(value: &AccountSecretKey) -> Self {
135 Self(BigInt::from_bytes(value.to_bytes()))
136 }
137}
138
139impl From<AccountSecretKey> for SignatureLibPrivateKeyStableV1 {
140 fn from(value: AccountSecretKey) -> Self {
141 Self(BigInt::from_bytes(value.to_bytes()))
142 }
143}
144
145impl FromStr for AccountSecretKey {
146 type Err = anyhow::Error;
147
148 fn from_str(s: &str) -> Result<Self, Self::Err> {
149 let mut bytes = [0u8; 38];
150
151 let size = bs58::decode(s)
152 .with_check(Some(Self::BASE58_CHECK_VERSION))
153 .into(&mut bytes)?;
154 if size != 34 {
155 return Err(bs58::decode::Error::BufferTooSmall.into());
156 }
157
158 Ok(Self::from_bytes(&bytes[2..34])?)
159 }
160}
161
162impl fmt::Display for AccountSecretKey {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 let hex = self.0.to_hex();
166 let mut bytes = hex::decode(hex).expect("to_hex should return hex string");
167 bytes.reverse();
168 bytes.insert(0, 1);
169 let s = bs58::encode(&bytes)
170 .with_check_version(Self::BASE58_CHECK_VERSION)
171 .into_string();
172 f.write_str(&s)
173 }
174}
175
176impl Serialize for AccountSecretKey {
177 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
178 where
179 S: serde::Serializer,
180 {
181 serializer.serialize_str(&self.to_string())
182 }
183}
184
185impl<'de> serde::Deserialize<'de> for AccountSecretKey {
186 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
187 where
188 D: serde::Deserializer<'de>,
189 {
190 let b58: String = Deserialize::deserialize(deserializer)?;
191 b58.parse().map_err(serde::de::Error::custom)
192 }
193}