Skip to main content

Conversation

Struct Conversation 

Source
pub struct Conversation<C: ConsensusPlugin, Sc: PeerScoringPlugin, St: StewardListPlugin> { /* private fields */ }

Implementations§

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn create<Pr>( conversation_id: &str, provider: &Pr, credential: CredentialWithKey, ciphersuite: Ciphersuite, signer: &impl Signer, scoring: Sc, steward: St, consensus: ConsensusServiceFor<C>, app_id: Arc<[u8]>, config: ConversationConfig, member_id: &[u8], ) -> Result<Self, ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Create a brand-new conversation we steward. Starts in Working with the local member installed as sole steward at epoch 0. The library seeds a fresh MLS group into provider (which it does not retain) from credential and ciphersuite. member_id names the local member — the opaque id bytes the protocol matches on.

Source

pub fn join<Pr>( provider: &Pr, welcome_bytes: &[u8], conversation_sync_bytes: &[u8], scoring: Sc, steward: St, consensus: ConsensusServiceFor<C>, app_id: Arc<[u8]>, config: ConversationConfig, member_id: &[u8], signer: &impl Signer, ) -> Result<Option<Self>, ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Build a fully-joined conversation from a welcome: the library opens the joiner-side MLS group from welcome_bytes using provider (which must hold the joiner’s key-package private keys), runs the joiner-side join side-effects, and replays the bundled ConversationSync (steward list, timing, peer scores).

Returns Ok(None) when the welcome doesn’t address one of our key packages — the “not for us” branch, not an error.

The conversation id comes from the MLS group, so the caller needs no prior knowledge of the conversation.

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn is_in_recovery_mode(&self) -> bool

Source

pub fn enter_recovery_mode(&mut self)

Source

pub fn exit_recovery_mode(&mut self)

Source

pub fn current_state(&self) -> ConversationState

Source

pub fn drain_events(&self) -> Vec<ConversationEvent>

Drain every pending ConversationEvent accumulated since the last call. Returns events in insertion order. Callers (UI fanout, audit log) invoke this once per polling cycle.

Source

pub fn next_wakeup_in(&self) -> Option<Duration>

Smallest pending deadline relative to now, or None when nothing is scheduled. Returns Some(Duration::ZERO) for an already-elapsed deadline. Covers consensus-session timeouts, auto-vote timers, and state-machine phase deadlines (Freezing window, steward / recovery inactivity). Forward to an external scheduler that calls poll() on fire; extra/early wakeups are no-ops.

Source

pub fn drain_outbound(&self) -> Vec<Outbound>

Drain every buffered Outbound accumulated since the last call, in insertion order. The integrator invokes this once per cycle (after poll / handle_inbound / an intent) and maps each item onto its own transport.

Source

pub fn leave<Pr>( &mut self, provider: &Pr, signer: &impl Signer, ) -> Result<LeaveOutcome, ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Leave this conversation. Opens a self-leave consensus round and returns LeaveOutcome::LeaveInitiated; the leave completes when the next steward commit merges the removal. signer is the local member’s MLS signer, used to authenticate the self-leave proposal.

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn process_inbound<Pr>( &mut self, provider: &Pr, sender: &[u8], payload: &[u8], signer: &impl Signer, ) -> Result<DispatchOutcome, ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Decrypt and dispatch an inbound conversation payload. Drops self-echoes. Runs the full dispatch chain internally. Returns DispatchOutcome::LeaveRequested when the conversation has completed its protocol-side teardown; the integrator must then remove the registry entry and clean up the consensus scope.

Source

pub fn apply_welcome_sync<Pr>( &mut self, provider: &Pr, sync_bytes: &[u8], signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn send_message<Pr>( &mut self, provider: &Pr, message: Vec<u8>, signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Buffer a chat message for broadcast. The conversation never sends — the message is enqueued and the integrator drains it via Conversation::drain_outbound. Blocked in Freezing and Selection (epoch rotation in flight — the message might not decrypt on peers who already merged the next commit). Governance traffic has its own gate (check_proposal_allowed). signer is the local member’s MLS signer, used to authenticate the outbound message.

Source

pub fn add_member<Pr>( &mut self, provider: &Pr, key_package_bytes: &[u8], signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Invite a joiner whose key package the caller supplies out of band, endorsing the add by bundling a YES vote at submit. Any member may call. Errors unless the conversation is Working.

See Self::sponsor_member for the non-endorsing steward relay.

Source

pub fn sponsor_member<Pr>( &mut self, provider: &Pr, key_package_bytes: &[u8], signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Relay a joiner that announced its own key package, without endorsing it: the proposal is submitted unbundled (CreatorVote::Deferred) and this member votes on it like any other. Only the primary epoch steward relays immediately, so a single Add proposal is opened per joiner. Every other member records the announcement in the pending-update buffer instead — a backup proposes it from there if the epoch steward stays silent past the recovery window (drained by poll), so an offline epoch steward doesn’t strand the join. No-op outside Working.

See Self::add_member for the endorsing out-of-band invite.

Source

pub fn remove_member<Pr>( &mut self, provider: &Pr, member_id: &[u8], signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Start a RemoveMember consensus round targeting member_id. The requester’s intent is the removal → the creator’s vote is bundled as YES at submit; no vote request is shown to the requester.

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn poll<Pr>(&mut self, provider: &Pr, signer: &impl Signer) -> PollOutcome
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Drive one polling cycle: tick consensus deadlines, advance freeze state, and check steward inactivity.

Best-effort: each step runs regardless of whether the previous one failed; step errors are transient (a step that can’t act this cycle retries on the next) and are logged rather than surfaced.

Returns PollOutcome::leave_requested when the conversation is ready to be torn down; the integrator finalizes the leave.

signer is the local member’s MLS signer, threaded into the steward commit-candidate build and any auto-vote casts that fire this cycle.

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn state(&self) -> ConversationState

Current state of the conversation’s state machine.

Source

pub fn id(&self) -> &str

Name of this conversation. Identifies it in the integrator’s registry and on every crate::Outbound it produces.

Source

pub fn member_id_bytes(&self) -> &[u8]

Identity bytes of the local member in this conversation.

Source

pub fn app_id(&self) -> &[u8]

App id this conversation tags on outbound packets and uses for self-echo filtering in Conversation::process_inbound.

Source

pub fn epoch_and_retry(&self) -> Result<(u64, u32), ConversationError>

Current MLS epoch + reelection retry round. Intended for UI status display.

Source

pub fn pending_update_count(&self) -> usize

Count of buffered pending membership updates. Used by tests and the UI to verify buffer hygiene (e.g., that a joiner’s buffer is empty right after they receive the welcome).

Source

pub fn freeze_candidate_count(&self) -> (usize, usize)

Freeze round progress: (received, expected). Returns (0, 0) if not in freeze or no steward list is known.

Source

pub fn is_steward(&self) -> bool

Source

pub fn is_epoch_steward(&self) -> Result<bool, ConversationError>

true if the local member is the primary steward designated for the current epoch — the one that should commit and sponsor joiners first. Unlike Self::is_steward (true for any member on the list, backups included), this is true for exactly one member per epoch, so it gates the single-actor paths: backups defer to the primary and only step in after the recovery window. Eligibility is the same live rotation Self::member_roles uses, so all members agree on who it is.

Source

pub fn members(&self) -> Result<Vec<Vec<u8>>, ConversationError>

Identity bytes of every current member of this conversation, as reported by MLS.

Source

pub fn member_scores(&self) -> Vec<(Vec<u8>, i64)>

Source

pub fn member_score(&self, member_id: &[u8]) -> Option<i64>

Source

pub fn pending_leave_member_ids( &self, ) -> Result<Vec<Vec<u8>>, ConversationError>

Identities that have an in-flight self-leave request. Used by the UI to render a “pending leave” indicator.

Source

pub fn member_roles( &self, ) -> Result<Vec<(Vec<u8>, MemberRole)>, ConversationError>

Steward role for each member. Uses live rotation so removed or pending-leave stewards are skipped in role display.

Source

pub fn approved_proposals_for_current_epoch( &self, ) -> Vec<ConversationUpdateRequest>

Source§

impl<C, Sc, St> Conversation<C, Sc, St>

Source

pub fn initiate_proposal<Pr>( &mut self, provider: &Pr, request: ConversationUpdateRequest, creator_vote: CreatorVote, signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Open a consensus vote for request; CreatorVote picks the wire shape and the integrator event.

Errors when the state machine forbids new proposals (freeze phases, partial freeze during an active emergency). On success the proposal is on the wire and a consensus-timeout deadline is armed for tick_deadlines to fire.

Local ownership is recorded before any vote is cast: with a single expected voter the bundled YES resolves the session synchronously, and the outcome handler must already see us as the owner by then.

Source

pub fn vote<Pr>( &mut self, provider: &Pr, proposal_id: u32, vote: bool, signer: &impl Signer, ) -> Result<(), ConversationError>
where Pr: OpenMlsProvider, <Pr::StorageProvider as StorageProvider<1>>::Error: StdError + Send + Sync + 'static,

Cast the local member’s vote. Cancels the pending auto-vote so the manual choice wins. Blocked while an epoch rotation is in flight (Freezing/Selection) — the encrypted vote might not decrypt on peers that already merged the next commit.

Auto Trait Implementations§

§

impl<C, Sc, St> !Freeze for Conversation<C, Sc, St>

§

impl<C, Sc, St> RefUnwindSafe for Conversation<C, Sc, St>

§

impl<C, Sc, St> Send for Conversation<C, Sc, St>
where Sc: Send, St: Send,

§

impl<C, Sc, St> Sync for Conversation<C, Sc, St>

§

impl<C, Sc, St> Unpin for Conversation<C, Sc, St>

§

impl<C, Sc, St> UnsafeUnpin for Conversation<C, Sc, St>

§

impl<C, Sc, St> UnwindSafe for Conversation<C, Sc, St>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more