linera_wallet_json/
keystore.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::path::Path;
5
6use linera_base::{
7    crypto::{AccountPublicKey, AccountSignature, CryptoHash, InMemorySigner, Signer},
8    identifiers::AccountOwner,
9};
10use linera_persistent::{self as persistent, Persist as _};
11
12/// A persistent keystore backed by a JSON file with exclusive locking.
13pub struct Keystore(persistent::File<InMemorySigner>);
14
15impl Signer for Keystore {
16    type Error = <InMemorySigner as Signer>::Error;
17
18    async fn sign(
19        &self,
20        owner: &AccountOwner,
21        value: &CryptoHash,
22    ) -> Result<AccountSignature, Self::Error> {
23        (*self.0).sign(owner, value).await
24    }
25
26    async fn contains_key(&self, owner: &AccountOwner) -> Result<bool, Self::Error> {
27        (*self.0).contains_key(owner).await
28    }
29}
30
31impl Keystore {
32    /// Reads an existing keystore from disk.
33    pub fn read(path: &Path) -> Result<Self, persistent::file::Error> {
34        Ok(Self(persistent::File::read(path)?))
35    }
36
37    /// Creates a new keystore at `path`. If `testing_prng_seed` is provided,
38    /// uses deterministic key generation.
39    pub fn create(
40        path: &Path,
41        testing_prng_seed: Option<u64>,
42    ) -> Result<Self, persistent::file::Error> {
43        Ok(Self(persistent::File::read_or_create(path, || {
44            Ok(InMemorySigner::new(testing_prng_seed))
45        })?))
46    }
47
48    /// Generates a new key pair, persists the keystore, and returns the public key.
49    pub async fn generate_key(&mut self) -> Result<AccountPublicKey, persistent::file::Error> {
50        let key = self.0.generate_new();
51        self.0.persist().await?;
52        Ok(key)
53    }
54
55    /// Generates `count` new key pairs, persists the keystore, and returns the public keys.
56    pub async fn generate_keys(
57        &mut self,
58        count: usize,
59    ) -> Result<Vec<AccountPublicKey>, persistent::file::Error> {
60        let keys: Vec<_> = std::iter::repeat_with(|| self.0.generate_new())
61            .take(count)
62            .collect();
63        self.0.persist().await?;
64        Ok(keys)
65    }
66
67    /// Saves the keystore to disk.
68    pub async fn save(&mut self) -> Result<(), persistent::file::Error> {
69        self.0.persist().await
70    }
71
72    /// Consumes the keystore and returns the inner signer.
73    pub fn into_signer(self) -> InMemorySigner {
74        self.0.into_value()
75    }
76}