fedimint_client_module/
secret.rs1use std::fmt::Debug;
2use std::io::{Read, Write};
3
4use fedimint_core::config::FederationId;
5use fedimint_core::core::ModuleInstanceId;
6use fedimint_core::encoding::{Decodable, DecodeError, Encodable};
7use fedimint_core::module::registry::ModuleRegistry;
8use fedimint_derive_secret::{ChildId, DerivableSecret};
9use rand::{CryptoRng, Rng, RngCore};
10
11const TYPE_PRE_ROOT_SECRET_HASH: ChildId = ChildId(0);
13
14const TYPE_MODULE: ChildId = ChildId(0);
16const TYPE_BACKUP: ChildId = ChildId(1);
17
18pub trait DeriveableSecretClientExt {
19 fn derive_module_secret(&self, module_instance_id: ModuleInstanceId) -> DerivableSecret;
20 fn derive_backup_secret(&self) -> DerivableSecret;
21 fn derive_pre_root_secret_hash(&self) -> [u8; 8];
22}
23
24impl DeriveableSecretClientExt for DerivableSecret {
25 fn derive_module_secret(&self, module_instance_id: ModuleInstanceId) -> DerivableSecret {
26 assert_eq!(self.level(), 0);
27 self.child_key(TYPE_MODULE)
28 .child_key(ChildId(u64::from(module_instance_id)))
29 }
30
31 fn derive_backup_secret(&self) -> DerivableSecret {
32 assert_eq!(self.level(), 0);
33 self.child_key(TYPE_BACKUP)
34 }
35
36 fn derive_pre_root_secret_hash(&self) -> [u8; 8] {
37 self.child_key(TYPE_PRE_ROOT_SECRET_HASH).to_random_bytes()
42 }
43}
44
45pub trait RootSecretStrategy: Debug {
55 type Encoding: Clone;
57
58 fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret;
60
61 fn consensus_encode(
63 secret: &Self::Encoding,
64 writer: &mut impl std::io::Write,
65 ) -> std::io::Result<()>;
66
67 fn consensus_decode_partial(
69 reader: &mut impl std::io::Read,
70 ) -> Result<Self::Encoding, DecodeError>;
71
72 fn random<R>(rng: &mut R) -> Self::Encoding
74 where
75 R: rand::RngCore + rand::CryptoRng;
76}
77
78#[derive(Debug)]
80pub struct PlainRootSecretStrategy;
81
82impl RootSecretStrategy for PlainRootSecretStrategy {
83 type Encoding = [u8; 64];
84
85 fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret {
86 const FEDIMINT_CLIENT_NONCE: &[u8] = b"Fedimint Client Salt";
87 DerivableSecret::new_root(secret.as_ref(), FEDIMINT_CLIENT_NONCE)
88 }
89
90 fn consensus_encode(secret: &Self::Encoding, writer: &mut impl Write) -> std::io::Result<()> {
91 secret.consensus_encode(writer)
92 }
93
94 fn consensus_decode_partial(reader: &mut impl Read) -> Result<Self::Encoding, DecodeError> {
95 Self::Encoding::consensus_decode_partial(reader, &ModuleRegistry::default())
96 }
97
98 fn random<R>(rng: &mut R) -> Self::Encoding
99 where
100 R: RngCore + CryptoRng,
101 {
102 let mut secret = [0u8; 64];
103 rng.fill(&mut secret);
104 secret
105 }
106}
107
108pub fn get_default_client_secret(
117 global_root_secret: &DerivableSecret,
118 federation_id: &FederationId,
119) -> DerivableSecret {
120 let multi_federation_root_secret = global_root_secret.child_key(ChildId(0));
121 let federation_root_secret = multi_federation_root_secret.federation_key(federation_id);
122 let federation_wallet_root_secret = federation_root_secret.child_key(ChildId(0)); federation_wallet_root_secret.child_key(ChildId(0)) }