fedimint_client/
secret.rsuse std::fmt::Debug;
use std::io::{Read, Write};
use fedimint_core::config::FederationId;
use fedimint_core::core::ModuleInstanceId;
use fedimint_core::encoding::{Decodable, DecodeError, Encodable};
use fedimint_core::module::registry::ModuleRegistry;
use fedimint_derive_secret::{ChildId, DerivableSecret};
use rand::{CryptoRng, Rng, RngCore};
const TYPE_PRE_ROOT_SECRET_HASH: ChildId = ChildId(0);
const TYPE_MODULE: ChildId = ChildId(0);
const TYPE_BACKUP: ChildId = ChildId(1);
pub trait DeriveableSecretClientExt {
fn derive_module_secret(&self, module_instance_id: ModuleInstanceId) -> DerivableSecret;
fn derive_backup_secret(&self) -> DerivableSecret;
fn derive_pre_root_secret_hash(&self) -> [u8; 8];
}
impl DeriveableSecretClientExt for DerivableSecret {
fn derive_module_secret(&self, module_instance_id: ModuleInstanceId) -> DerivableSecret {
assert_eq!(self.level(), 0);
self.child_key(TYPE_MODULE)
.child_key(ChildId(u64::from(module_instance_id)))
}
fn derive_backup_secret(&self) -> DerivableSecret {
assert_eq!(self.level(), 0);
self.child_key(TYPE_BACKUP)
}
fn derive_pre_root_secret_hash(&self) -> [u8; 8] {
self.child_key(TYPE_PRE_ROOT_SECRET_HASH).to_random_bytes()
}
}
pub trait RootSecretStrategy: Debug {
type Encoding: Clone;
fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret;
fn consensus_encode(
secret: &Self::Encoding,
writer: &mut impl std::io::Write,
) -> std::io::Result<usize>;
fn consensus_decode(reader: &mut impl std::io::Read) -> Result<Self::Encoding, DecodeError>;
fn random<R>(rng: &mut R) -> Self::Encoding
where
R: rand::RngCore + rand::CryptoRng;
}
#[derive(Debug)]
pub struct PlainRootSecretStrategy;
impl RootSecretStrategy for PlainRootSecretStrategy {
type Encoding = [u8; 64];
fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret {
const FEDIMINT_CLIENT_NONCE: &[u8] = b"Fedimint Client Salt";
DerivableSecret::new_root(secret.as_ref(), FEDIMINT_CLIENT_NONCE)
}
fn consensus_encode(
secret: &Self::Encoding,
writer: &mut impl Write,
) -> std::io::Result<usize> {
secret.consensus_encode(writer)
}
fn consensus_decode(reader: &mut impl Read) -> Result<Self::Encoding, DecodeError> {
Self::Encoding::consensus_decode(reader, &ModuleRegistry::default())
}
fn random<R>(rng: &mut R) -> Self::Encoding
where
R: RngCore + CryptoRng,
{
let mut secret = [0u8; 64];
rng.fill(&mut secret);
secret
}
}
pub fn get_default_client_secret(
global_root_secret: &DerivableSecret,
federation_id: &FederationId,
) -> DerivableSecret {
let multi_federation_root_secret = global_root_secret.child_key(ChildId(0));
let federation_root_secret = multi_federation_root_secret.federation_key(federation_id);
let federation_wallet_root_secret = federation_root_secret.child_key(ChildId(0)); federation_wallet_root_secret.child_key(ChildId(0)) }