Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Implement event format V2 #4483

Merged
merged 2 commits into from
Jan 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/4483.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for room version 3
2 changes: 2 additions & 0 deletions synapse/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,12 @@ class EventFormatVersions(object):
independently from the room version.
"""
V1 = 1
V2 = 2


KNOWN_EVENT_FORMAT_VERSIONS = {
EventFormatVersions.V1,
EventFormatVersions.V2,
}


Expand Down
110 changes: 94 additions & 16 deletions synapse/events/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2014-2016 OpenMarket Ltd
# Copyright 2019 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -18,11 +19,9 @@

import six

from synapse.api.constants import (
KNOWN_EVENT_FORMAT_VERSIONS,
KNOWN_ROOM_VERSIONS,
EventFormatVersions,
)
from unpaddedbase64 import encode_base64

from synapse.api.constants import KNOWN_ROOM_VERSIONS, EventFormatVersions, RoomVersions
from synapse.util.caches import intern_dict
from synapse.util.frozenutils import freeze

Expand Down Expand Up @@ -225,22 +224,91 @@ def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
rejected_reason=rejected_reason,
)

@staticmethod
def from_event(event):
e = FrozenEvent(
event.get_pdu_json()
def __str__(self):
return self.__repr__()

def __repr__(self):
return "<FrozenEvent event_id='%s', type='%s', state_key='%s'>" % (
self.get("event_id", None),
self.get("type", None),
self.get("state_key", None),
)

e.internal_metadata = event.internal_metadata

return e
class FrozenEventV2(EventBase):
format_version = EventFormatVersions.V2 # All events of this type are V2

def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
event_dict = dict(event_dict)

# Signatures is a dict of dicts, and this is faster than doing a
# copy.deepcopy
signatures = {
name: {sig_id: sig for sig_id, sig in sigs.items()}
for name, sigs in event_dict.pop("signatures", {}).items()
}

assert "event_id" not in event_dict

unsigned = dict(event_dict.pop("unsigned", {}))

# We intern these strings because they turn up a lot (especially when
# caching).
event_dict = intern_dict(event_dict)

if USE_FROZEN_DICTS:
frozen_dict = freeze(event_dict)
else:
frozen_dict = event_dict

self._event_id = None
self.type = event_dict["type"]
if "state_key" in event_dict:
self.state_key = event_dict["state_key"]

super(FrozenEventV2, self).__init__(
frozen_dict,
signatures=signatures,
unsigned=unsigned,
internal_metadata_dict=internal_metadata_dict,
rejected_reason=rejected_reason,
)

@property
def event_id(self):
# We have to import this here as otherwise we get an import loop which
# is hard to break.
from synapse.crypto.event_signing import compute_event_reference_hash

if self._event_id:
return self._event_id
self._event_id = "$" + encode_base64(compute_event_reference_hash(self)[1])
return self._event_id

def prev_event_ids(self):
"""Returns the list of prev event IDs. The order matches the order
specified in the event, though there is no meaning to it.

Returns:
list[str]: The list of event IDs of this event's prev_events
"""
return self.prev_events

def auth_event_ids(self):
"""Returns the list of auth event IDs. The order matches the order
specified in the event, though there is no meaning to it.

Returns:
list[str]: The list of event IDs of this event's auth_events
"""
return self.auth_events

def __str__(self):
return self.__repr__()

def __repr__(self):
return "<FrozenEvent event_id='%s', type='%s', state_key='%s'>" % (
self.get("event_id", None),
return "<FrozenEventV2 event_id='%s', type='%s', state_key='%s'>" % (
self.event_id,
self.get("type", None),
self.get("state_key", None),
)
Expand All @@ -259,7 +327,13 @@ def room_version_to_event_format(room_version):
# We should have already checked version, so this should not happen
raise RuntimeError("Unrecognized room version %s" % (room_version,))

return EventFormatVersions.V1
if room_version in (
RoomVersions.V1, RoomVersions.V2, RoomVersions.VDH_TEST,
RoomVersions.STATE_V2_TEST,
):
return EventFormatVersions.V1
else:
raise RuntimeError("Unrecognized room version %s" % (room_version,))


def event_type_from_format_version(format_version):
Expand All @@ -273,8 +347,12 @@ def event_type_from_format_version(format_version):
type: A type that can be initialized as per the initializer of
`FrozenEvent`
"""
if format_version not in KNOWN_EVENT_FORMAT_VERSIONS:

if format_version == EventFormatVersions.V1:
return FrozenEvent
elif format_version == EventFormatVersions.V2:
return FrozenEventV2
else:
raise Exception(
"No event format %r" % (format_version,)
)
return FrozenEvent
12 changes: 9 additions & 3 deletions synapse/events/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
KNOWN_EVENT_FORMAT_VERSIONS,
KNOWN_ROOM_VERSIONS,
MAX_DEPTH,
EventFormatVersions,
)
from synapse.crypto.event_signing import add_hashes_and_signatures
from synapse.types import EventID
Expand Down Expand Up @@ -109,8 +110,12 @@ def build(self, prev_event_ids):
self, state_ids,
)

auth_events = yield self._store.add_event_hashes(auth_ids)
prev_events = yield self._store.add_event_hashes(prev_event_ids)
if self.format_version == EventFormatVersions.V1:
auth_events = yield self._store.add_event_hashes(auth_ids)
prev_events = yield self._store.add_event_hashes(prev_event_ids)
else:
auth_events = auth_ids
prev_events = prev_event_ids

old_depth = yield self._store.get_max_depth_of(
prev_event_ids,
Expand Down Expand Up @@ -228,7 +233,8 @@ def create_local_event_from_event_dict(clock, hostname, signing_key,

time_now = int(clock.time_msec())

event_dict["event_id"] = _create_event_id(clock, hostname)
if format_version == EventFormatVersions.V1:
event_dict["event_id"] = _create_event_id(clock, hostname)

event_dict["origin"] = hostname
event_dict["origin_server_ts"] = time_now
Expand Down
3 changes: 3 additions & 0 deletions synapse/events/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ def serialize_event(e, time_now_ms, as_client_event=True,
Returns:
dict
"""

# FIXME(erikj): To handle the case of presence events and the like
if not isinstance(e, EventBase):
return e
Expand All @@ -276,6 +277,8 @@ def serialize_event(e, time_now_ms, as_client_event=True,
# Should this strip out None's?
d = {k: v for k, v in e.get_dict().items()}

d["event_id"] = e.event_id

if "age_ts" in d["unsigned"]:
d["unsigned"]["age"] = time_now_ms - d["unsigned"]["age_ts"]
del d["unsigned"]["age_ts"]
Expand Down