kms_secp256k1_api/services/mocks/
mock_ethereum_keys_service.rs1use crate::{
2 config::Config,
3 constants::ETH_SECP_LEN,
4 services::{
5 crypto_service::CryptoService,
6 keys_service::{KeyEntry, KeysServiceTrait, SigEntry},
7 mocks::mock_keys_service::{KeyPair, MockKeysService},
8 },
9};
10use base64::Engine;
11use base64::engine::general_purpose::STANDARD;
12use ethers::{
13 signers::{LocalWallet, Signer},
14 types::{H256, TransactionRequest, TxHash},
15};
16use k256::{ecdsa::SigningKey, elliptic_curve::rand_core::OsRng};
17use serde_json::json;
18use std::str::FromStr;
19use tracing::error;
20
21pub struct MockEthereumKeysService {
22 inner: MockKeysService,
23}
24
25#[async_trait::async_trait]
26impl KeysServiceTrait for MockEthereumKeysService {
27 async fn create_key(&mut self, _config: &Config) -> Result<KeyEntry, String> {
32 let signing_key = SigningKey::random(&mut OsRng);
33 let verifying_key = signing_key.verifying_key();
34 let encoded_point = verifying_key.to_encoded_point(true);
35
36 let private_key_bytes = signing_key.to_bytes();
37 let private_key = hex::encode(private_key_bytes);
38
39 let pubkey_bytes = encoded_point.as_bytes();
40 let public_key = hex::encode(pubkey_bytes);
41
42 let address = self.resolve_key(&public_key)?;
43
44 {
45 let key_pair = KeyPair {
46 public_key: public_key.clone(),
47 private_key,
48 address: address.clone(),
49 };
50 let mut keys = self.inner.keys.lock().await;
51 keys.entry(address.clone()).or_insert(key_pair);
52 }
53
54 Ok(KeyEntry {
55 public_key: Some(public_key.clone()).into(),
56 address: address.clone().into(),
57 public_key_base64: STANDARD.encode(public_key).into(),
58 key_id: address.into(),
59 })
60 }
61
62 async fn sign_transaction_hash(
68 &mut self,
69 _config: &Config,
70 transaction_hash: &str,
71 key: &str,
72 ) -> Result<SigEntry, String> {
73 let key = self.resolve_key(key)?;
74
75 let key_pair = {
76 let keys = self.inner.keys.lock().await;
77 keys.get(&key)
78 .ok_or_else(|| "Public key not found".to_string())?
79 .clone()
80 };
81
82 let tx_hash_bytes = hex::decode(transaction_hash)
83 .map_err(|e| format!("Invalid transaction hash hex: {e}"))?;
84
85 if tx_hash_bytes.len() != 32 {
86 return Err("Transaction hash must be 32 bytes".into());
87 }
88
89 let tx_hash = H256::from_slice(&tx_hash_bytes);
90
91 let wallet: LocalWallet = key_pair
92 .private_key
93 .parse()
94 .map_err(|e| format!("Failed to parse secret key into wallet: {e}"))?;
95
96 let signature = wallet
97 .sign_hash(tx_hash)
98 .map_err(|e| format!("Failed to sign hash: {e}"))?;
99
100 let is_valid = self
102 .verify(
103 transaction_hash,
104 &signature.to_string(),
105 &key_pair.public_key,
106 )
107 .await?;
108
109 if !is_valid {
110 return Err("Signature verification failed".to_string());
111 }
112
113 let signature = hex::encode(signature.to_vec());
114 Ok(SigEntry {
115 address: key.into(),
116 public_key: key_pair.public_key.into(),
117 signature: signature.into(),
118 })
119 }
120
121 async fn sign_transaction(
126 &mut self,
127 _config: &Config,
128 transaction_str: &str,
129 key: &str,
130 ) -> Result<String, String> {
131 let parsed: serde_json::Value = serde_json::from_str(transaction_str)
133 .map_err(|e| format!("Failed to parse input JSON: {e}"))?;
134
135 let (transaction_value, mut signatures) = match parsed {
137 serde_json::Value::Object(mut map) => {
138 if let Some(tx) = map.remove("transaction") {
139 let sigs = map
140 .remove("signatures")
141 .and_then(|v| v.as_array().cloned())
142 .unwrap_or_default();
143 (tx, sigs)
144 } else {
145 (serde_json::Value::Object(map), vec![])
146 }
147 }
148 _ => return Err("Unsupported transaction format".to_string()),
149 };
150
151 let transaction: TransactionRequest = serde_json::from_value(transaction_value.clone())
153 .map_err(|e| format!("Failed to parse transaction: {e}"))?;
154
155 let mut transaction_hash_str = format!("{:x}", transaction.sighash());
157 transaction_hash_str = transaction_hash_str.trim_start_matches("0x").to_string();
158
159 TxHash::from_str(&transaction_hash_str).map_err(|e| {
160 error!("Invalid transaction hash: {:?}", e);
161 "Invalid transaction hash".to_string()
162 })?;
163
164 let key = self.resolve_key(key)?;
166 let key_pair = {
167 let keys = self.inner.keys.lock().await;
168 keys.get(&key)
169 .ok_or_else(|| "Public key not found".to_string())?
170 .clone()
171 };
172
173 let wallet: LocalWallet = key_pair
174 .private_key
175 .parse()
176 .map_err(|e| format!("Failed to parse secret key into wallet: {e}"))?;
177
178 let signature = wallet
180 .sign_transaction(&transaction.clone().into())
181 .await
182 .map_err(|e| format!("Failed to sign transaction: {e}"))?;
183
184 let signature_hex = signature.to_string();
185
186 let is_valid = self
188 .verify(&transaction_hash_str, &signature_hex, &key_pair.public_key)
189 .await?;
190 if !is_valid {
191 return Err("Generated signature failed verification".to_string());
192 }
193
194 signatures.push(json!({
196 "address": key,
197 "signer": &key_pair.public_key,
198 "v": format!("{:x}", signature.v),
199 "r": format!("{:x}", signature.r),
200 "s": format!("{:x}", signature.s),
201 "hash": transaction_hash_str,
202 "signature": signature_hex
203 }));
204
205 let result = json!({
207 "transaction": transaction_value,
208 "signatures": signatures
209 });
210
211 serde_json::to_string(&result)
212 .map_err(|e| format!("Failed to serialize final signed transaction: {e}"))
213 }
214
215 async fn verify(
220 &mut self,
221 transaction_hash_hex: &str,
222 signature_hex: &str,
223 key: &str,
224 ) -> Result<bool, String> {
225 let key = self.resolve_key(key)?;
226 let key_pair = {
227 let keys = self.inner.keys.lock().await;
228 keys.get(&key)
229 .ok_or_else(|| "Public key not found".to_string())?
230 .clone()
231 };
232 self.inner
233 .verify_eip155(transaction_hash_hex, signature_hex, &key_pair.public_key)
234 .map_err(|e| {
235 let msg = format!("Signature verification failed: {e}");
236 error!("{}", msg);
237 msg
238 })
239 }
240
241 async fn verify_via_kms(
246 &mut self,
247 transaction_hash_hex: &str,
248 signature_hex: &str,
249 key: &str,
250 ) -> Result<bool, String> {
251 let key = self.resolve_key(key)?;
252 let key_pair = {
253 let keys = self.inner.keys.lock().await;
254 keys.get(&key)
255 .ok_or_else(|| "Public key not found".to_string())?
256 .clone()
257 };
258 self.inner
259 .verify_via_kms_eip155(transaction_hash_hex, signature_hex, &key_pair.public_key)
260 .await
261 }
262
263 async fn delete_key(&mut self, key: &str) -> Result<bool, String> {
268 let key = self.resolve_key(key)?;
269 Ok(self.inner.delete_key(&key).await)
270 }
271
272 async fn list_keys(&mut self) -> Result<Vec<KeyEntry>, String> {
277 Ok(self.inner.list_keys().await)
278 }
279}
280
281impl MockEthereumKeysService {
282 pub fn new(config: Config, crypto_service: CryptoService) -> Result<Self, String> {
294 Ok(Self {
295 inner: MockKeysService::new(config, crypto_service),
296 })
297 }
298
299 fn resolve_key(&mut self, key: &str) -> Result<String, String> {
317 if key.len() == ETH_SECP_LEN {
318 self.inner.crypto_service.address_eth(key).map_err(|e| {
319 let msg = format!("Failed to convert public key to address: {e:?}");
320 error!("{}", &msg);
321 msg
322 })
323 } else {
324 Ok(key.to_string())
325 }
326 }
327}