Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

(fix): new_keystore returns uuid as well #559

Merged
merged 4 commits into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- `abigen!` now supports multiple contracts [#498](https://github.com/gakonst/ethers-rs/pull/498)
- Use rust types as contract function inputs for human readable abi [#482](https://github.com/gakonst/ethers-rs/pull/482)
- Add EIP-712 `sign_typed_data` signer method; add ethers-core type `Eip712` trait and derive macro in ethers-derive-eip712 [#481](https://github.com/gakonst/ethers-rs/pull/481)
- `LocalWallet::new_keystore` now returns a tuple `(LocalWallet, String)` instead of `LocalWallet`, where the string represents the UUID of the newly created encrypted JSON keystore. The JSON keystore is stored as a file `/dir/uuid`. The issue [#557](https://github.com/gakonst/ethers-rs/issues/557) is addressed [#559](https://github.com/gakonst/ethers-rs/pull/559)

### 0.5.3

Expand Down
29 changes: 15 additions & 14 deletions ethers-signers/src/wallet/private_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,23 @@ impl Clone for Wallet<SigningKey> {

impl Wallet<SigningKey> {
/// Creates a new random encrypted JSON with the provided password and stores it in the
/// provided directory
/// provided directory. Returns a tuple (Wallet, String) of the wallet instance for the
/// keystore with its random UUID.
#[cfg(not(target_arch = "wasm32"))]
pub fn new_keystore<P, R, S>(dir: P, rng: &mut R, password: S) -> Result<Self, WalletError>
pub fn new_keystore<P, R, S>(
dir: P,
rng: &mut R,
password: S,
) -> Result<(Self, String), WalletError>
where
P: AsRef<Path>,
R: Rng + CryptoRng + rand_core::CryptoRng,
S: AsRef<[u8]>,
{
let (secret, _) = eth_keystore::new(dir, rng, password)?;
let (secret, uuid) = eth_keystore::new(dir, rng, password)?;
let signer = SigningKey::from_bytes(secret.as_slice())?;
let address = secret_key_to_address(&signer);
Ok(Self { signer, address, chain_id: 1 })
Ok((Self { signer, address, chain_id: 1 }, uuid))
}

/// Decrypts an encrypted JSON from the provided path to construct a Wallet instance
Expand Down Expand Up @@ -140,30 +145,26 @@ mod tests {
use super::*;
use crate::Signer;
use ethers_core::types::Address;
use std::fs;
use tempfile::tempdir;

#[tokio::test]
async fn encrypted_json_keystore() {
// create and store a random encrypted JSON keystore in this directory
let dir = tempdir().unwrap();
let mut rng = rand::thread_rng();
let key = Wallet::<SigningKey>::new_keystore(&dir, &mut rng, "randpsswd").unwrap();
let (key, uuid) = Wallet::<SigningKey>::new_keystore(&dir, &mut rng, "randpsswd").unwrap();

// sign a message using the above key
let message = "Some data";
let signature = key.sign_message(message).await.unwrap();

// read from the encrypted JSON keystore and decrypt it, while validating that the
// signatures produced by both the keys should match
let paths = fs::read_dir(dir).unwrap();
for path in paths {
let path = path.unwrap().path();
let key2 = Wallet::<SigningKey>::decrypt_keystore(&path.clone(), "randpsswd").unwrap();
let signature2 = key2.sign_message(message).await.unwrap();
assert_eq!(signature, signature2);
assert!(std::fs::remove_file(&path).is_ok());
}
let path = Path::new(dir.path()).join(uuid);
let key2 = Wallet::<SigningKey>::decrypt_keystore(&path.clone(), "randpsswd").unwrap();
let signature2 = key2.sign_message(message).await.unwrap();
assert_eq!(signature, signature2);
assert!(std::fs::remove_file(&path).is_ok());
}

#[tokio::test]
Expand Down