Skip to main content

de_mls/core/
provider.rs

1//! Service provider trait for dependency injection.
2//!
3//! The [`DeMlsProvider`] trait bundles all configurable services needed
4//! by DE-MLS into a single type parameter. This enables swapping out
5//! implementations for testing or custom deployments.
6//!
7//! # Architecture
8//!
9//! ```text
10//! ┌─────────────────────────────────────────────────────────────┐
11//! │                      DeMlsProvider                          │
12//! ├─────────────────────────────────────────────────────────────┤
13//! │  Storage    │  MLS + DE-MLS state persistence               │
14//! │  Scope      │  Group identifier type (usually String)       │
15//! │  CStorage   │  Consensus proposal/vote persistence          │
16//! │  EventBus   │  Consensus event distribution                 │
17//! │  Consensus  │  Voting service (hashgraph-like)              │
18//! └─────────────────────────────────────────────────────────────┘
19//! ```
20//!
21//! # Default vs Custom Providers
22//!
23//! Use [`DefaultProvider`] for production deployments:
24//! - `MemoryDeMlsStorage` for MLS state storage
25//! - `InMemoryConsensusStorage` for proposal/vote storage
26//! - `BroadcastEventBus` for consensus event distribution
27//! - `DefaultConsensusService` for hashgraph-like voting
28//!
29//! Create custom providers for:
30//! - **Testing**: Mock services that don't require network
31//! - **Persistence**: Database-backed storage
32//!
33//! # Example
34//!
35//! ```ignore
36//! use de_mls::core::{DeMlsProvider, DefaultProvider};
37//! use de_mls::app::User;
38//!
39//! // Production: use DefaultProvider
40//! let user: User<DefaultProvider> = User::with_private_key(
41//!     "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
42//!     consensus,
43//!     handler,
44//! )?;
45//! ```
46
47use hashgraph_like_consensus::{
48    api::ConsensusServiceAPI,
49    events::{BroadcastEventBus, ConsensusEventBus},
50    scope::ConsensusScope,
51    service::DefaultConsensusService,
52    storage::{ConsensusStorage, InMemoryConsensusStorage},
53};
54
55use openmls_rust_crypto::MemoryStorage;
56
57use crate::mls_crypto::{DeMlsStorage, MemoryDeMlsStorage};
58
59/// Bundles all configurable services for a DE-MLS deployment.
60///
61/// This trait uses associated types to define the concrete implementations
62/// of each service. All types must be `Send + Sync + 'static` for async use.
63///
64/// # Implementing Custom Providers
65///
66/// ```ignore
67/// struct MyProvider;
68///
69/// impl DeMlsProvider for MyProvider {
70///     // Storage backend for MLS state
71///     type Storage = SqliteDeMlsStorage;
72///
73///     // Group identifier (String works for most cases)
74///     type Scope = String;
75///
76///     // Where to store proposals and votes
77///     type ConsensusStorage = PostgresConsensusStorage<String>;
78///
79///     // How to distribute consensus events
80///     type EventBus = BroadcastEventBus<String>;
81///
82///     // The voting service implementation
83///     type Consensus = DefaultConsensusService;
84/// }
85/// ```
86pub trait DeMlsProvider: 'static {
87    /// Storage backend for MLS operations.
88    ///
89    /// Must implement `DeMlsStorage` for key package tracking and OpenMLS delegation.
90    /// Currently constrained to `MemoryStorage` for MLS storage backend.
91    ///
92    /// Default: `MemoryDeMlsStorage`
93    type Storage: DeMlsStorage<MlsStorage = MemoryStorage> + Send + Sync + 'static;
94
95    /// Consensus scope type for grouping proposals.
96    ///
97    /// This is typically `String` (the group name). Each group has its
98    /// own consensus scope, so proposals don't interfere across groups.
99    ///
100    /// Default: `String`
101    type Scope: ConsensusScope + From<String> + Send + Sync + 'static;
102
103    /// Consensus storage backend for proposals and votes.
104    ///
105    /// Stores pending proposals, vote tallies, and consensus state.
106    /// Can be in-memory for testing or database-backed for production.
107    ///
108    /// Default: `InMemoryConsensusStorage<String>`
109    type ConsensusStorage: ConsensusStorage<Self::Scope> + Send + Sync + 'static;
110
111    /// Event bus for distributing consensus outcomes.
112    ///
113    /// When consensus is reached or fails, events are broadcast to
114    /// all subscribers (typically the app layer's event loop).
115    ///
116    /// Default: `BroadcastEventBus<String>`
117    type EventBus: ConsensusEventBus<Self::Scope> + Send + Sync + 'static;
118
119    /// Consensus service implementing the voting protocol.
120    ///
121    /// Handles proposal creation, vote casting, and outcome determination.
122    /// Uses hashgraph-like consensus for Byzantine fault tolerance.
123    ///
124    /// Default: `DefaultConsensusService`
125    type Consensus: ConsensusServiceAPI<Self::Scope, Self::ConsensusStorage, Self::EventBus>
126        + Send
127        + Sync
128        + 'static;
129}
130
131/// Default provider for production deployments.
132///
133/// Uses:
134/// - `MemoryDeMlsStorage`: In-memory MLS state storage
135/// - `String` scope: Group names as consensus scopes
136/// - `InMemoryConsensusStorage`: Fast in-memory proposal/vote storage
137/// - `BroadcastEventBus`: Tokio broadcast channels for events
138/// - `DefaultConsensusService`: Hashgraph-like voting protocol
139///
140/// # Example
141///
142/// ```ignore
143/// use de_mls::core::DefaultProvider;
144/// use de_mls::app::User;
145///
146/// let user: User<DefaultProvider> = User::with_private_key(
147///     private_key,
148///     consensus,
149///     handler,
150/// )?;
151/// ```
152pub struct DefaultProvider;
153
154impl DeMlsProvider for DefaultProvider {
155    type Storage = MemoryDeMlsStorage;
156    type Scope = String;
157    type ConsensusStorage = InMemoryConsensusStorage<String>;
158    type EventBus = BroadcastEventBus<String>;
159    type Consensus = DefaultConsensusService;
160}