pub struct RoomEvent<S> {
pub(crate) state: S,
}Expand description
A Matrix room event in a specific lifecycle state.
RoomEvent<S> is a generic wrapper that ensures type-safe state transitions
throughout the event lifecycle. The type parameter S determines which
methods are available and which transitions are permitted.
§Type States
RoomEvent<Draft>: Initial creation from user inputRoomEvent<Contextualized>: Contextualized in the room DAGRoomEvent<Signed>: Signed with event ID and cryptographic signaturesRoomEvent<Verified>: Verified and ready for persistence/distribution
§Design Philosophy
The state-based design enforces correctness at compile-time:
- You cannot sign an event without first contextualizing it
- You cannot store an event without first verifying it
- You cannot send an event to federation without signatures
This prevents entire classes of security bugs by making invalid states unrepresentable.
Fields§
§state: SThe state-specific data
Implementations§
Source§impl RoomEvent<Draft>
impl RoomEvent<Draft>
Sourcepub fn new(
event_type: TimelineEventType,
content: Box<RawValue>,
state_key: Option<String>,
sender: OwnedUserId,
redacts: Option<OwnedEventId>,
) -> Result<Self, Error>
pub fn new( event_type: TimelineEventType, content: Box<RawValue>, state_key: Option<String>, sender: OwnedUserId, redacts: Option<OwnedEventId>, ) -> Result<Self, Error>
Creates a draft event
§Errors
Returns a serde_json::Error if the event content does not have the
fields expected of its type.
Sourcepub fn contextualize(
self,
room_id: Option<OwnedRoomId>,
room_version: KnownRoomVersionId,
depth: u64,
auth_events: EventRefs,
prev_events: EventRefs,
origin_server_ts: MilliSecondsSinceUnixEpoch,
) -> Result<RoomEvent<Contextualized>, EventContextualizationError>
pub fn contextualize( self, room_id: Option<OwnedRoomId>, room_version: KnownRoomVersionId, depth: u64, auth_events: EventRefs, prev_events: EventRefs, origin_server_ts: MilliSecondsSinceUnixEpoch, ) -> Result<RoomEvent<Contextualized>, EventContextualizationError>
Contextualize the draft into the room DAG to create a Contextualized
event.
This method places the draft event in the context of the room’s directed acyclic graph by adding references to auth events and previous events, along with server timestamp and room version information.
§Room Version
The room_version parameter determines:
- Event ID format (hashed vs. reference-based)
- Event reference format (V1 hashed vs. V3+ plain)
- Authorization rules
- Signature requirements
§Parameters
room_id: The ID of the room the event is in. If the event type ism.room.createand theroom_versionis 12 or above, this should be None.room_version: Room version rules determining event format and authorization.depth: Depth of the event in the DAG.auth_events: Auth event references for authorization chain.prev_events: Previous event references establishing DAG position.origin_server_ts: Server-assigned timestamp for the event.
§Returns
A Contextualized event ready to be signed.
Source§impl RoomEvent<Contextualized>
impl RoomEvent<Contextualized>
Sourcepub fn sign_and_verify(
self,
server_name: &ServerName,
signing_key: &Ed25519KeyPair,
previous_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
auth_events: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
current_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
) -> Result<RoomEvent<Verified>, SigningValidationError>
pub fn sign_and_verify( self, server_name: &ServerName, signing_key: &Ed25519KeyPair, previous_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>, auth_events: &HashMap<(StateEventType, String), RoomEvent<Verified>>, current_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>, ) -> Result<RoomEvent<Verified>, SigningValidationError>
Sign the event to produce a Verified event.
Check VerificationMetadata::soft_failed
to determine whether the event should be excluded from leaf events and
client relay.
This method performs the following operations:
- Canonicalizes the event JSON according to Matrix specification
- Computes the reference hash to generate the event ID
- Signs the canonical JSON with the provided key pair
- Attaches the signature to the event
- Verifies that the event follows authorization rules
- Returns a
Verifiedevent (signing implicitly verifies)
§Implicit Verification
Events signed by our own server are implicitly verified - we trust our
own signing process. This is why sign() returns Verified rather
than Signed.
§Parameters
server_name: The origin server name (e.g., “avastar.example.com”) used to namespace the signature in thesignaturesfield.signing_key: The Ed25519 key pair used to generate and verify the cryptographic signature.previous_state: The room state corresponding to the resolution of the state of this event’sprev_events.auth_events: The specific auth events referenced by this event.current_state: The room state at the time the event is being verified. If the event fails this auth check, it will be soft-failed: the returnedRoomEvent<Verified>will haveVerificationMetadata::soft_failedset totrue. See https://spec.matrix.org/v1.17/server-server-api/#soft-failure for more information.
§Returns
A RoomEvent<Verified> with event ID and signatures, ready for
persistence or federation.
§Errors
Returns SigningValidationError if:
- Event content is not a valid JSON object
- Canonical JSON generation fails
- Reference hash computation fails
- Cryptographic signing fails
- Event ID parsing fails
- Event fails authorization rules
Sourcepub fn sign_join_event(
self,
server_name: &ServerName,
signing_key: &Ed25519KeyPair,
) -> Result<Pdu, SigningError>
pub fn sign_join_event( self, server_name: &ServerName, signing_key: &Ed25519KeyPair, ) -> Result<Pdu, SigningError>
Sign a membership event, producing a PDU to send over federation This method only accepts membership events. It’s intended for use when joining rooms over federation, as specified in https://spec.matrix.org/v1.18/server-server-api/#joining-rooms
The events produced by this method should NOT be persisted directly
in the database. Instead, they should be sent over federation with the
/send_join request, where we as a response will get the state events
required to check the authorization rules.
This method performs the following operations:
- Canonicalizes the event JSON according to Matrix specification
- Computes the reference hash to generate the event ID
- Signs the canonical JSON with the provided key pair
- Attaches the signature to the event
- Returns a
Pdu
§Parameters
server_name: The origin server name (e.g., “avastar.example.com”) used to namespace the signature in thesignaturesfield.signing_key: The Ed25519 key pair used to generate and verify the cryptographic signature.
§Returns
A Pdu to be sent to another homeserver to counter-sign
§Errors
Returns SigningError if:
- Event content is not a valid JSON object
- Event is not a membership event
- Canonical JSON generation fails
- Reference hash computation fails
- Cryptographic signing fails
- Event ID parsing fails
Sourcefn sign_event(
self,
server_name: &ServerName,
signing_key: &Ed25519KeyPair,
) -> Result<RoomEvent<Verified>, SigningError>
fn sign_event( self, server_name: &ServerName, signing_key: &Ed25519KeyPair, ) -> Result<RoomEvent<Verified>, SigningError>
Signs the event
Source§impl RoomEvent<Signed>
impl RoomEvent<Signed>
Sourcepub fn new_signed(
content: Box<RawValue>,
depth: u64,
event_type: TimelineEventType,
room_id: Option<OwnedRoomId>,
sender: OwnedUserId,
state_key: Option<String>,
redacts: Option<OwnedEventId>,
room_version: KnownRoomVersionId,
auth_events: EventRefs,
prev_events: EventRefs,
prev_state: Option<EventRefs>,
membership: Option<MembershipState>,
origin: Option<OwnedServerName>,
origin_server_ts: MilliSecondsSinceUnixEpoch,
event_id: Option<OwnedEventId>,
signatures: ServerSignatures,
hashes: EventHash,
) -> Result<Self, FromPduError>
pub fn new_signed( content: Box<RawValue>, depth: u64, event_type: TimelineEventType, room_id: Option<OwnedRoomId>, sender: OwnedUserId, state_key: Option<String>, redacts: Option<OwnedEventId>, room_version: KnownRoomVersionId, auth_events: EventRefs, prev_events: EventRefs, prev_state: Option<EventRefs>, membership: Option<MembershipState>, origin: Option<OwnedServerName>, origin_server_ts: MilliSecondsSinceUnixEpoch, event_id: Option<OwnedEventId>, signatures: ServerSignatures, hashes: EventHash, ) -> Result<Self, FromPduError>
Create a new signed event (e.g. from federation)
§Parameters
content: Raw JSON content of the event.depth: Depth of the event in the DAG.event_type: Matrix event type.room_id: Room ID the event belongs to.sender: User ID that sent the event.state_key: State key for state events.redacts: Event ID that is redacted, if applicable.room_version: Room version for the event.auth_events: Auth event references required for authorization.prev_events: Previous event references preceding the event.origin_server_ts: Timestamp server assigned to the event.event_id: Event ID of the signed event, if known.signatures: Signature map of the event.hashes: Content hashes of the event.
§Errors
Returns FromPduError if:
- Event content fails draft validation
- Event refs contextualization fails
- Event ID generation fails
Sourcepub fn into_draft(self) -> Result<RoomEvent<Draft>, Error>
pub fn into_draft(self) -> Result<RoomEvent<Draft>, Error>
Recovers the authored Draft from a signed event, discarding its DAG
context, signatures and hashes.
Re-validates through Draft::new, the same gate client events pass,
so content the tolerant federation parser accepted (e.g. a redacted
event stripped to {}) cannot be re-signed under our own key.
§Errors
Returns a serde_json::Error if the content does not pass
Draft::new validation for its event type.
Sourcepub fn sign_member_event(
self,
server_name: &ServerName,
signing_key: &Ed25519KeyPair,
) -> Result<Pdu, SigningError>
pub fn sign_member_event( self, server_name: &ServerName, signing_key: &Ed25519KeyPair, ) -> Result<Pdu, SigningError>
Sign an already signed membership event, producing a PDU to send over federation.
§Errors
Returns SigningError if the event is not a membership event or
signing fails.
Sourcepub fn signed_from_pdu(
pdu: &RawValue,
room_version: KnownRoomVersionId,
) -> Result<Self, FromPduError>
pub fn signed_from_pdu( pdu: &RawValue, room_version: KnownRoomVersionId, ) -> Result<Self, FromPduError>
Deserializes a federation PDU and constructs a RoomEvent<Signed>.
§Parameters
pdu: Raw JSON PDU bytes.room_version: Room version used to validateauth_eventsandprev_eventsformat inContextualized::new.
§Errors
Returns FromPduError if:
- The PDU JSON cannot be deserialized
- Event refs do not match the room version, or exceed allowed counts
- Event content fails draft validation
- Event ID generation fails
Sourcepub fn validate_signature(
&self,
required_verify_keys: &PublicKeyMap,
) -> Result<(), ValidationError>
pub fn validate_signature( &self, required_verify_keys: &PublicKeyMap, ) -> Result<(), ValidationError>
Validate the signature of the event, without checking auth rules
Sourcepub fn verify(
self,
previous_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
auth_events: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
current_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
required_verify_keys: &PublicKeyMap,
) -> Result<RoomEvent<Verified>, ValidationError>
pub fn verify( self, previous_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>, auth_events: &HashMap<(StateEventType, String), RoomEvent<Verified>>, current_state: &HashMap<(StateEventType, String), RoomEvent<Verified>>, required_verify_keys: &PublicKeyMap, ) -> Result<RoomEvent<Verified>, ValidationError>
Verify a Signed event from federation or other external source.
Yields a RoomEvent<Verified>.
This method performs the following steps:
- Signature Verification: Cryptographically verifies all signatures in the event
against the provided
required_verify_keys. - Authorization Check: Validates the event against room state using ruma’s
state_res::check_state_dependent_auth_rules.
§Parameters
previous_state: The room state corresponding to the resolution of the state of this event’sprev_events.auth_events: The specific auth events referenced by this event.current_state: The room state at the time the event is being verified. If the event fails this auth check, it will be soft-failed: the returnedRoomEvent<Verified>will haveVerificationMetadata::soft_failedset totrue.required_verify_keys: Pre-fetched public keys used to verify the event signatures.
§Errors
Returns ValidationError if:
- Invalid signature: Cryptographic signature verification fails
- Event ID mismatch: Computed reference hash doesn’t match event ID
- Authorization fails: Event fails room authorization rules
- Canonical JSON error: Cannot canonicalize the event
Sourcepub fn build_pdu_for_auth(&self) -> Pdu
pub fn build_pdu_for_auth(&self) -> Pdu
Builds a PDU representation for use in authorization checks.
Sourcefn check_auth(
&self,
context_events: &HashMap<(StateEventType, String), RoomEvent<Verified>>,
) -> Result<(), AuthorizationError>
fn check_auth( &self, context_events: &HashMap<(StateEventType, String), RoomEvent<Verified>>, ) -> Result<(), AuthorizationError>
Checks authorization rules for the current event
Source§impl RoomEvent<Verified>
impl RoomEvent<Verified>
Sourcepub fn format_as(
&self,
event_format: &EventFormat,
ctx: ClientContext,
) -> Box<RawJsonValue>
pub fn format_as( &self, event_format: &EventFormat, ctx: ClientContext, ) -> Box<RawJsonValue>
Formats the event into a Box<RawJsonValue> representation based on the
requested formatting.
This method adapts the internal event state to match the required JSON
schema of the target consumer. Depending on the event_format
provided, it generates either:
- A Client-formatted event: Strips out federation-specific metadata and injects
client-specific context (such as room state or user relations) using the provided
ClientContext. Suitable for the Matrix Client-Server API. For more specific context checkto_client_eventmethod. - A Federation-formatted event: Retains all cryptographic data (
signatures,hashes) and DAG context (prev_events,auth_events)
§Parameters
event_format- The target format (filter::EventFormat::Clientorfilter::EventFormat::Federation).ctx- The client context required for resolving client-specific fields. Unused ifevent_formatis set toFederation.
Sourcepub fn verified_from_pdu(
pdu: &RawValue,
metadata: VerificationMetadata,
) -> Result<Self, FromPduError>
pub fn verified_from_pdu( pdu: &RawValue, metadata: VerificationMetadata, ) -> Result<Self, FromPduError>
Create a new verified event from a PDU
As this creates a new Verified event, this function is somewhat
dangerous, since it technically lets you bypass verification. Therefore,
care should be taken only to use this function on events from the
database
§Parameters
pdu: The PDU we’re loadingmetadata: Verification metadata, stored from earlier
Sourcepub fn to_pdu(&self) -> Pdu
pub fn to_pdu(&self) -> Pdu
Convert the verified event to a PDU (Persistent Data Unit) for federation.
This method serializes the event into the PDU format required by the Matrix federation protocol. The output format varies by room version.
Sourcepub fn to_client_event(&self, ctx: ClientContext) -> ClientEvent
pub fn to_client_event(&self, ctx: ClientContext) -> ClientEvent
Convert the verified event to a client event for the Matrix client-server API.
This method transforms the event into the format expected by Matrix clients, removing federation-only fields and adding client-specific metadata.
Returns a ClientEvent (boxed raw JSON) ready to be sent to a Matrix
client via sync, /rooms/{roomId}/messages, or other client API
endpoints.
§Transformations
The conversion:
- Removes federation-only fields:
auth_events,prev_events - Always includes
event_id(regardless of room version) - Adds
unsignedobject with client context:transaction_id: Local transaction ID if this was sent by the clientage: Event age in milliseconds (for sync responses)
- Removes
depthfield (not used in client API)
§Client Context
The ClientContext parameter provides client-specific metadata:
transaction_id: Set when the client sent this event, allowing them to correlate their send with the resulting eventage: Time since the event was created, useful for clients to show relative timestamps
Both fields are optional - omit them when not applicable.
§Parameters
ctx: Client-specific context containing optional transaction ID and age.
Sourcepub fn to_stripped_state_event(
&self,
) -> Result<Raw<AnyStrippedStateEvent>, EventIsNotStateEvent>
pub fn to_stripped_state_event( &self, ) -> Result<Raw<AnyStrippedStateEvent>, EventIsNotStateEvent>
Convert the verified event to a stripped state event for the client-server API.
Specifically, we are following the specification here: https://spec.matrix.org/v1.18/client-server-api/#stripped-state
The event contains the fields content, sender, state_key and
type
§Errors
This function will return an error if it’s called on a non-state event
Sourcepub fn sign(
self,
server_name: &ServerName,
signing_key: &Ed25519KeyPair,
) -> Result<Self, SigningError>
pub fn sign( self, server_name: &ServerName, signing_key: &Ed25519KeyPair, ) -> Result<Self, SigningError>
Add an additional signature to this already verified event.
§Rationale
This is used when joining a federated room. The joining server signs the event, after which the resident server counter-signs it before persisting and federating it.
§Errors
Returns a SigningError if canonical JSON construction or signing
fails for any reason
Trait Implementations§
Source§impl ContextualizedFields for RoomEvent<Contextualized>
impl ContextualizedFields for RoomEvent<Contextualized>
Source§fn auth_events(&self) -> &EventRefs
fn auth_events(&self) -> &EventRefs
auth_events field of the eventSource§fn prev_events(&self) -> &EventRefs
fn prev_events(&self) -> &EventRefs
prev_events field of the eventSource§fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch
fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch
origin_server_ts field of the eventSource§fn room_version(&self) -> KnownRoomVersionId
fn room_version(&self) -> KnownRoomVersionId
room_version field of the eventSource§impl ContextualizedFields for RoomEvent<Signed>
impl ContextualizedFields for RoomEvent<Signed>
Source§fn auth_events(&self) -> &EventRefs
fn auth_events(&self) -> &EventRefs
auth_events field of the eventSource§fn prev_events(&self) -> &EventRefs
fn prev_events(&self) -> &EventRefs
prev_events field of the eventSource§fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch
fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch
origin_server_ts field of the eventSource§fn room_version(&self) -> KnownRoomVersionId
fn room_version(&self) -> KnownRoomVersionId
room_version field of the eventSource§impl ContextualizedFields for RoomEvent<Verified>
impl ContextualizedFields for RoomEvent<Verified>
Source§fn auth_events(&self) -> &EventRefs
fn auth_events(&self) -> &EventRefs
auth_events field of the eventSource§fn prev_events(&self) -> &EventRefs
fn prev_events(&self) -> &EventRefs
prev_events field of the eventSource§fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch
fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch
origin_server_ts field of the eventSource§fn room_version(&self) -> KnownRoomVersionId
fn room_version(&self) -> KnownRoomVersionId
room_version field of the eventSource§impl<'de, S> Deserialize<'de> for RoomEvent<S>where
S: Deserialize<'de>,
impl<'de, S> Deserialize<'de> for RoomEvent<S>where
S: Deserialize<'de>,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl DraftFields for RoomEvent<Draft>
impl DraftFields for RoomEvent<Draft>
Source§fn event_type(&self) -> &TimelineEventType
fn event_type(&self) -> &TimelineEventType
Source§impl DraftFields for RoomEvent<Contextualized>
impl DraftFields for RoomEvent<Contextualized>
Source§fn event_type(&self) -> &TimelineEventType
fn event_type(&self) -> &TimelineEventType
Source§impl DraftFields for RoomEvent<Signed>
impl DraftFields for RoomEvent<Signed>
Source§fn event_type(&self) -> &TimelineEventType
fn event_type(&self) -> &TimelineEventType
Source§impl DraftFields for RoomEvent<Verified>
impl DraftFields for RoomEvent<Verified>
Source§fn event_type(&self) -> &TimelineEventType
fn event_type(&self) -> &TimelineEventType
impl<S: Eq> Eq for RoomEvent<S>
Source§impl<S: PartialEq> PartialEq for RoomEvent<S>
impl<S: PartialEq> PartialEq for RoomEvent<S>
Source§impl Redactable for RoomEvent<Signed>
impl Redactable for RoomEvent<Signed>
Source§impl Redactable for RoomEvent<Verified>
impl Redactable for RoomEvent<Verified>
Source§impl SignedFields for RoomEvent<Signed>
impl SignedFields for RoomEvent<Signed>
Source§fn signatures(&self) -> &ServerSignatures
fn signatures(&self) -> &ServerSignatures
Source§impl SignedFields for RoomEvent<Verified>
impl SignedFields for RoomEvent<Verified>
Source§fn signatures(&self) -> &ServerSignatures
fn signatures(&self) -> &ServerSignatures
impl<S: PartialEq> StructuralPartialEq for RoomEvent<S>
Source§impl VerifiedFields for RoomEvent<Verified>
impl VerifiedFields for RoomEvent<Verified>
Source§fn metadata(&self) -> &VerificationMetadata
fn metadata(&self) -> &VerificationMetadata
Source§fn soft_failed(&self) -> bool
fn soft_failed(&self) -> bool
Auto Trait Implementations§
impl<S> Freeze for RoomEvent<S>where
S: Freeze,
impl<S> RefUnwindSafe for RoomEvent<S>where
S: RefUnwindSafe,
impl<S> Send for RoomEvent<S>where
S: Send,
impl<S> Sync for RoomEvent<S>where
S: Sync,
impl<S> Unpin for RoomEvent<S>where
S: Unpin,
impl<S> UnsafeUnpin for RoomEvent<S>where
S: UnsafeUnpin,
impl<S> UnwindSafe for RoomEvent<S>where
S: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.