summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorCH Chethan Reddy <40890937+Chethan2k1@users.noreply.github.com>2020-07-18 01:46:30 +0530
committerCH Chethan Reddy <40890937+Chethan2k1@users.noreply.github.com>2020-07-30 22:10:27 +0530
commit1fcd768f88f7e84978d19283c9fa6205624f2544 (patch)
tree97afdac31c014c4eedb5d0da45362835d7c04d22 /src
parentUpdating keys of outdated encrypted users (diff)
downloadnheko-1fcd768f88f7e84978d19283c9fa6205624f2544.tar.xz
Adding Room Key Verification Stuff
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp2
-rw-r--r--src/ChatPage.h18
-rw-r--r--src/DeviceVerificationFlow.cpp665
-rw-r--r--src/DeviceVerificationFlow.h17
-rw-r--r--src/EventAccessors.cpp11
-rw-r--r--src/Olm.cpp39
-rw-r--r--src/timeline/TimelineModel.cpp187
-rw-r--r--src/timeline/TimelineModel.h8
-rw-r--r--src/timeline/TimelineViewManager.cpp76
-rw-r--r--src/timeline/TimelineViewManager.h9
-rw-r--r--src/ui/UserProfile.cpp34
-rw-r--r--src/ui/UserProfile.h4
12 files changed, 711 insertions, 359 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 1008277a..8cee3453 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -1011,7 +1011,7 @@ Cache::saveState(const mtx::responses::Sync &res)
 
         savePresence(txn, res.presence);
 
-        updateUserCache(res.device_lists);
+        // updateUserCache(res.device_lists);
 
         removeLeftRooms(txn, res.rooms.leave);
 
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 172f74fe..0e7c889f 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -167,16 +167,18 @@ signals:
 
         //! Signals for device verificaiton
         void recievedDeviceVerificationAccept(
-          const mtx::events::collections::DeviceEvents &message);
+          const mtx::events::msg::KeyVerificationAccept &message);
         void recievedDeviceVerificationRequest(
-          const mtx::events::collections::DeviceEvents &message);
+          const mtx::events::msg::KeyVerificationRequest &message,
+          std::string sender);
         void recievedDeviceVerificationCancel(
-          const mtx::events::collections::DeviceEvents &message);
-        void recievedDeviceVerificationKey(const mtx::events::collections::DeviceEvents &message);
-        void recievedDeviceVerificationMac(const mtx::events::collections::DeviceEvents &message);
-        void recievedDeviceVerificationStart(const mtx::events::collections::DeviceEvents &message);
-        void recievedDeviceVerificationReady(const mtx::events::collections::DeviceEvents &message);
-        void recievedDeviceVerificationDone(const mtx::events::collections::DeviceEvents &message);
+          const mtx::events::msg::KeyVerificationCancel &message);
+        void recievedDeviceVerificationKey(const mtx::events::msg::KeyVerificationKey &message);
+        void recievedDeviceVerificationMac(const mtx::events::msg::KeyVerificationMac &message);
+        void recievedDeviceVerificationStart(const mtx::events::msg::KeyVerificationStart &message,
+                                             std::string sender);
+        void recievedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
+        void recievedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
 
 private slots:
         void showUnreadMessageNotification(int count);
diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp
index 0122e691..69de4937 100644
--- a/src/DeviceVerificationFlow.cpp
+++ b/src/DeviceVerificationFlow.cpp
@@ -6,11 +6,13 @@
 #include <QDateTime>
 #include <QTimer>
 
+#include <iostream>
+
 static constexpr int TIMEOUT = 2 * 60 * 1000; // 2 minutes
 
 namespace msgs = mtx::events::msg;
 
-DeviceVerificationFlow::DeviceVerificationFlow(QObject *)
+DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow::Type)
 {
         timeout = new QTimer(this);
         timeout->setSingleShot(true);
@@ -26,192 +28,218 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *)
           ChatPage::instance(),
           &ChatPage::recievedDeviceVerificationStart,
           this,
-          [this](const mtx::events::collections::DeviceEvents &message) {
-                  auto msg =
-                    std::get<mtx::events::DeviceEvent<msgs::KeyVerificationStart>>(message);
-                  if (msg.content.transaction_id == this->transaction_id) {
-                          if ((std::find(msg.content.key_agreement_protocols.begin(),
-                                         msg.content.key_agreement_protocols.end(),
-                                         "curve25519-hkdf-sha256") !=
-                               msg.content.key_agreement_protocols.end()) &&
-                              (std::find(msg.content.hashes.begin(),
-                                         msg.content.hashes.end(),
-                                         "sha256") != msg.content.hashes.end()) &&
-                              (std::find(msg.content.message_authentication_codes.begin(),
-                                         msg.content.message_authentication_codes.end(),
-                                         "hmac-sha256") !=
-                               msg.content.message_authentication_codes.end())) {
-                                  if (std::find(msg.content.short_authentication_string.begin(),
-                                                msg.content.short_authentication_string.end(),
-                                                mtx::events::msg::SASMethods::Decimal) !=
-                                      msg.content.short_authentication_string.end()) {
-                                          this->method = DeviceVerificationFlow::Method::Emoji;
-                                  } else if (std::find(
-                                               msg.content.short_authentication_string.begin(),
-                                               msg.content.short_authentication_string.end(),
-                                               mtx::events::msg::SASMethods::Emoji) !=
-                                             msg.content.short_authentication_string.end()) {
-                                          this->method = DeviceVerificationFlow::Method::Decimal;
-                                  } else {
-                                          this->cancelVerification(
-                                            DeviceVerificationFlow::Error::UnknownMethod);
-                                          return;
-                                  }
-                                  this->acceptVerificationRequest();
-                                  this->canonical_json = nlohmann::json(msg.content);
-                          } else {
-                                  this->cancelVerification(
-                                    DeviceVerificationFlow::Error::UnknownMethod);
-                          }
+          [this](const mtx::events::msg::KeyVerificationStart &msg, std::string) {
+                  if (msg.transaction_id.has_value()) {
+                          if (msg.transaction_id.value() != this->transaction_id)
+                                  return;
+                  } else if (msg.relates_to.has_value()) {
+                          if (msg.relates_to.value().in_reply_to.event_id !=
+                              this->relation.in_reply_to.event_id)
+                                  return;
                   }
-          });
-        connect(
-          ChatPage::instance(),
-          &ChatPage::recievedDeviceVerificationAccept,
-          this,
-          [this](const mtx::events::collections::DeviceEvents &message) {
-                  auto msg =
-                    std::get<mtx::events::DeviceEvent<msgs::KeyVerificationAccept>>(message);
-                  if (msg.content.transaction_id == this->transaction_id) {
-                          if ((msg.content.key_agreement_protocol == "curve25519-hkdf-sha256") &&
-                              (msg.content.hash == "sha256") &&
-                              (msg.content.message_authentication_code == "hkdf-hmac-sha256")) {
-                                  this->commitment = msg.content.commitment;
-                                  if (std::find(msg.content.short_authentication_string.begin(),
-                                                msg.content.short_authentication_string.end(),
-                                                mtx::events::msg::SASMethods::Emoji) !=
-                                      msg.content.short_authentication_string.end()) {
-                                          this->method = DeviceVerificationFlow::Method::Emoji;
-                                  } else {
-                                          this->method = DeviceVerificationFlow::Method::Decimal;
-                                  }
-                                  this->mac_method = msg.content.message_authentication_code;
-                                  this->sendVerificationKey();
+                  if ((std::find(msg.key_agreement_protocols.begin(),
+                                 msg.key_agreement_protocols.end(),
+                                 "curve25519-hkdf-sha256") != msg.key_agreement_protocols.end()) &&
+                      (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") !=
+                       msg.hashes.end()) &&
+                      (std::find(msg.message_authentication_codes.begin(),
+                                 msg.message_authentication_codes.end(),
+                                 "hmac-sha256") != msg.message_authentication_codes.end())) {
+                          if (std::find(msg.short_authentication_string.begin(),
+                                        msg.short_authentication_string.end(),
+                                        mtx::events::msg::SASMethods::Decimal) !=
+                              msg.short_authentication_string.end()) {
+                                  this->method = DeviceVerificationFlow::Method::Emoji;
+                          } else if (std::find(msg.short_authentication_string.begin(),
+                                               msg.short_authentication_string.end(),
+                                               mtx::events::msg::SASMethods::Emoji) !=
+                                     msg.short_authentication_string.end()) {
+                                  this->method = DeviceVerificationFlow::Method::Decimal;
                           } else {
                                   this->cancelVerification(
                                     DeviceVerificationFlow::Error::UnknownMethod);
+                                  return;
                           }
+                          this->acceptVerificationRequest();
+                          this->canonical_json = nlohmann::json(msg);
+                  } else {
+                          this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
                   }
           });
+
+        connect(ChatPage::instance(),
+                &ChatPage::recievedDeviceVerificationAccept,
+                this,
+                [this](const mtx::events::msg::KeyVerificationAccept &msg) {
+                        if (msg.transaction_id.has_value()) {
+                                if (msg.transaction_id.value() != this->transaction_id)
+                                        return;
+                        } else if (msg.relates_to.has_value()) {
+                                if (msg.relates_to.value().in_reply_to.event_id !=
+                                    this->relation.in_reply_to.event_id)
+                                        return;
+                        }
+                        if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
+                            (msg.hash == "sha256") &&
+                            (msg.message_authentication_code == "hkdf-hmac-sha256")) {
+                                this->commitment = msg.commitment;
+                                if (std::find(msg.short_authentication_string.begin(),
+                                              msg.short_authentication_string.end(),
+                                              mtx::events::msg::SASMethods::Emoji) !=
+                                    msg.short_authentication_string.end()) {
+                                        this->method = DeviceVerificationFlow::Method::Emoji;
+                                } else {
+                                        this->method = DeviceVerificationFlow::Method::Decimal;
+                                }
+                                this->mac_method = msg.message_authentication_code;
+                                this->sendVerificationKey();
+                        } else {
+                                this->cancelVerification(
+                                  DeviceVerificationFlow::Error::UnknownMethod);
+                        }
+                });
+
         connect(ChatPage::instance(),
                 &ChatPage::recievedDeviceVerificationCancel,
                 this,
-                [this](const mtx::events::collections::DeviceEvents &message) {
-                        auto msg =
-                          std::get<mtx::events::DeviceEvent<msgs::KeyVerificationCancel>>(message);
-                        if (msg.content.transaction_id == this->transaction_id) {
-                                emit verificationCanceled();
+                [this](const mtx::events::msg::KeyVerificationCancel &msg) {
+                        if (msg.transaction_id.has_value()) {
+                                if (msg.transaction_id.value() != this->transaction_id)
+                                        return;
+                        } else if (msg.relates_to.has_value()) {
+                                if (msg.relates_to.value().in_reply_to.event_id !=
+                                    this->relation.in_reply_to.event_id)
+                                        return;
+                        }
+                        emit verificationCanceled();
+                });
+
+        connect(ChatPage::instance(),
+                &ChatPage::recievedDeviceVerificationKey,
+                this,
+                [this](const mtx::events::msg::KeyVerificationKey &msg) {
+                        if (msg.transaction_id.has_value()) {
+                                if (msg.transaction_id.value() != this->transaction_id)
+                                        return;
+                        } else if (msg.relates_to.has_value()) {
+                                if (msg.relates_to.value().in_reply_to.event_id !=
+                                    this->relation.in_reply_to.event_id)
+                                        return;
+                        }
+                        this->sas->set_their_key(msg.key);
+                        std::string info;
+                        if (this->sender == true) {
+                                info = "MATRIX_KEY_VERIFICATION_SAS|" +
+                                       http::client()->user_id().to_string() + "|" +
+                                       http::client()->device_id() + "|" + this->sas->public_key() +
+                                       "|" + this->toClient.to_string() + "|" +
+                                       this->deviceId.toStdString() + "|" + msg.key + "|" +
+                                       this->transaction_id;
+                        } else {
+                                info = "MATRIX_KEY_VERIFICATION_SAS|" + this->toClient.to_string() +
+                                       "|" + this->deviceId.toStdString() + "|" + msg.key + "|" +
+                                       http::client()->user_id().to_string() + "|" +
+                                       http::client()->device_id() + "|" + this->sas->public_key() +
+                                       "|" + this->transaction_id;
+                        }
+
+                        if (this->method == DeviceVerificationFlow::Method::Emoji) {
+                                this->sasList = this->sas->generate_bytes_emoji(info);
+                        } else if (this->method == DeviceVerificationFlow::Method::Decimal) {
+                                this->sasList = this->sas->generate_bytes_decimal(info);
+                        }
+                        if (this->sender == false) {
+                                emit this->verificationRequestAccepted(this->method);
+                                this->sendVerificationKey();
+                        } else {
+                                if (this->commitment ==
+                                    mtx::crypto::bin2base64_unpadded(
+                                      mtx::crypto::sha256(msg.key + this->canonical_json.dump()))) {
+                                        emit this->verificationRequestAccepted(this->method);
+                                } else {
+                                        this->cancelVerification(
+                                          DeviceVerificationFlow::Error::MismatchedCommitment);
+                                }
                         }
                 });
+
         connect(
           ChatPage::instance(),
-          &ChatPage::recievedDeviceVerificationKey,
+          &ChatPage::recievedDeviceVerificationMac,
           this,
-          [this](const mtx::events::collections::DeviceEvents &message) {
-                  auto msg = std::get<mtx::events::DeviceEvent<msgs::KeyVerificationKey>>(message);
-                  if (msg.content.transaction_id == this->transaction_id) {
-                          this->sas->set_their_key(msg.content.key);
-                          std::string info;
-                          if (this->sender == true) {
-                                  info = "MATRIX_KEY_VERIFICATION_SAS|" +
-                                         http::client()->user_id().to_string() + "|" +
-                                         http::client()->device_id() + "|" +
-                                         this->sas->public_key() + "|" +
-                                         this->toClient.to_string() + "|" +
-                                         this->deviceId.toStdString() + "|" + msg.content.key +
-                                         "|" + this->transaction_id;
-                          } else {
-                                  info = "MATRIX_KEY_VERIFICATION_SAS|" +
-                                         this->toClient.to_string() + "|" +
-                                         this->deviceId.toStdString() + "|" + msg.content.key +
-                                         "|" + http::client()->user_id().to_string() + "|" +
-                                         http::client()->device_id() + "|" +
-                                         this->sas->public_key() + "|" + this->transaction_id;
-                          }
-
-                          if (this->method == DeviceVerificationFlow::Method::Emoji) {
-                                  this->sasList = this->sas->generate_bytes_emoji(info);
-                          } else if (this->method == DeviceVerificationFlow::Method::Decimal) {
-                                  this->sasList = this->sas->generate_bytes_decimal(info);
-                          }
-                          if (this->sender == false) {
-                                  emit this->verificationRequestAccepted(this->method);
-                                  this->sendVerificationKey();
-                          } else {
-                                  if (this->commitment ==
-                                      mtx::crypto::bin2base64_unpadded(mtx::crypto::sha256(
-                                        msg.content.key + this->canonical_json.dump()))) {
-                                          emit this->verificationRequestAccepted(this->method);
+          [this](const mtx::events::msg::KeyVerificationMac &msg) {
+                  if (msg.transaction_id.has_value()) {
+                          if (msg.transaction_id.value() != this->transaction_id)
+                                  return;
+                  } else if (msg.relates_to.has_value()) {
+                          if (msg.relates_to.value().in_reply_to.event_id !=
+                              this->relation.in_reply_to.event_id)
+                                  return;
+                  }
+                  std::string info = "MATRIX_KEY_VERIFICATION_MAC" + this->toClient.to_string() +
+                                     this->deviceId.toStdString() +
+                                     http::client()->user_id().to_string() +
+                                     http::client()->device_id() + this->transaction_id;
+
+                  std::vector<std::string> key_list;
+                  std::string key_string;
+                  for (auto mac : msg.mac) {
+                          key_string += mac.first + ",";
+                          if (device_keys[mac.first] != "") {
+                                  if (mac.second ==
+                                      this->sas->calculate_mac(this->device_keys[mac.first],
+                                                               info + mac.first)) {
                                   } else {
                                           this->cancelVerification(
-                                            DeviceVerificationFlow::Error::MismatchedCommitment);
+                                            DeviceVerificationFlow::Error::KeyMismatch);
+                                          return;
                                   }
                           }
                   }
-          });
-        connect(
-          ChatPage::instance(),
-          &ChatPage::recievedDeviceVerificationMac,
-          this,
-          [this](const mtx::events::collections::DeviceEvents &message) {
-                  auto msg = std::get<mtx::events::DeviceEvent<msgs::KeyVerificationMac>>(message);
-                  if (msg.content.transaction_id == this->transaction_id) {
-                          std::string info =
-                            "MATRIX_KEY_VERIFICATION_MAC" + this->toClient.to_string() +
-                            this->deviceId.toStdString() + http::client()->user_id().to_string() +
-                            http::client()->device_id() + this->transaction_id;
-
-                          std::vector<std::string> key_list;
-                          std::string key_string;
-                          for (auto mac : msg.content.mac) {
-                                  key_string += mac.first + ",";
-                                  if (device_keys[mac.first] != "") {
-                                          if (mac.second ==
-                                              this->sas->calculate_mac(this->device_keys[mac.first],
-                                                                       info + mac.first)) {
-                                          } else {
-                                                  this->cancelVerification(
-                                                    DeviceVerificationFlow::Error::KeyMismatch);
-                                                  return;
-                                          }
-                                  }
-                          }
-                          key_string = key_string.substr(0, key_string.length() - 1);
-                          if (msg.content.keys ==
-                              this->sas->calculate_mac(key_string, info + "KEY_IDS")) {
-                                  // uncomment this in future to be compatible with the
-                                  // MSC2366 this->sendVerificationDone(); and remove the
-                                  // below line
-                                  if (this->isMacVerified == true) {
-                                          this->acceptDevice();
-                                  } else
-                                          this->isMacVerified = true;
-                          } else {
-                                  this->cancelVerification(
-                                    DeviceVerificationFlow::Error::KeyMismatch);
-                          }
+                  key_string = key_string.substr(0, key_string.length() - 1);
+                  if (msg.keys == this->sas->calculate_mac(key_string, info + "KEY_IDS")) {
+                          // uncomment this in future to be compatible with the
+                          // MSC2366 this->sendVerificationDone(); and remove the
+                          // below line
+                          if (this->isMacVerified == true) {
+                                  this->acceptDevice();
+                          } else
+                                  this->isMacVerified = true;
+                  } else {
+                          this->cancelVerification(DeviceVerificationFlow::Error::KeyMismatch);
                   }
           });
+
         connect(ChatPage::instance(),
                 &ChatPage::recievedDeviceVerificationReady,
                 this,
-                [this](const mtx::events::collections::DeviceEvents &message) {
-                        auto msg =
-                          std::get<mtx::events::DeviceEvent<msgs::KeyVerificationReady>>(message);
-                        if (msg.content.transaction_id == this->transaction_id) {
-                                this->startVerificationRequest();
+                [this](const mtx::events::msg::KeyVerificationReady &msg) {
+                        if (msg.transaction_id.has_value()) {
+                                if (msg.transaction_id.value() != this->transaction_id)
+                                        return;
+                        } else if (msg.relates_to.has_value()) {
+                                if (msg.relates_to.value().in_reply_to.event_id !=
+                                    this->relation.in_reply_to.event_id)
+                                        return;
                         }
+                        this->startVerificationRequest();
                 });
+
         connect(ChatPage::instance(),
                 &ChatPage::recievedDeviceVerificationDone,
                 this,
-                [this](const mtx::events::collections::DeviceEvents &message) {
-                        auto msg =
-                          std::get<mtx::events::DeviceEvent<msgs::KeyVerificationDone>>(message);
-                        if (msg.content.transaction_id == this->transaction_id) {
-                                this->acceptDevice();
+                [this](const mtx::events::msg::KeyVerificationDone &msg) {
+                        if (msg.transaction_id.has_value()) {
+                                if (msg.transaction_id.value() != this->transaction_id)
+                                        return;
+                        } else if (msg.relates_to.has_value()) {
+                                if (msg.relates_to.value().in_reply_to.event_id !=
+                                    this->relation.in_reply_to.event_id)
+                                        return;
                         }
+                        this->acceptDevice();
                 });
+
         timeout->start(TIMEOUT);
 }
 
@@ -294,18 +322,18 @@ void
 DeviceVerificationFlow::setSender(bool sender_)
 {
         this->sender = sender_;
-        if (this->sender == true)
+        if (this->sender == true && this->type == DeviceVerificationFlow::Type::ToDevice)
                 this->transaction_id = http::client()->generate_txn_id();
+        else if (this->sender == true && this->type == DeviceVerificationFlow::Type::RoomMsg)
+                this->relation.in_reply_to.event_id = http::client()->generate_txn_id();
 }
 
 //! accepts a verification
 void
 DeviceVerificationFlow::acceptVerificationRequest()
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationAccept> body;
         mtx::events::msg::KeyVerificationAccept req;
 
-        req.transaction_id              = this->transaction_id;
         req.method                      = mtx::events::msg::VerificationMethods::SASv1;
         req.key_agreement_protocol      = "curve25519-hkdf-sha256";
         req.hash                        = "sha256";
@@ -317,126 +345,152 @@ DeviceVerificationFlow::acceptVerificationRequest()
         req.commitment = mtx::crypto::bin2base64_unpadded(
           mtx::crypto::sha256(this->sas->public_key() + this->canonical_json.dump()));
 
-        body[this->toClient][this->deviceId.toStdString()] = req;
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationAccept,
-                           mtx::events::EventType::KeyVerificationAccept>(
-            this->transaction_id, body, [](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to accept verification request: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-            });
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationAccept> body;
+                req.transaction_id = this->transaction_id;
+
+                body[this->toClient][this->deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationAccept,
+                                   mtx::events::EventType::KeyVerificationAccept>(
+                    this->transaction_id, body, [](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn(
+                                      "failed to accept verification request: {} {}",
+                                      err->matrix_error.error,
+                                      static_cast<int>(err->status_code));
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
 }
 //! responds verification request
 void
 DeviceVerificationFlow::sendVerificationReady()
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationReady> body;
         mtx::events::msg::KeyVerificationReady req;
 
-        req.from_device    = http::client()->device_id();
-        req.transaction_id = this->transaction_id;
-        req.methods        = {mtx::events::msg::VerificationMethods::SASv1};
-
-        body[this->toClient][this->deviceId.toStdString()] = req;
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationReady,
-                           mtx::events::EventType::KeyVerificationReady>(
-            this->transaction_id, body, [](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to send verification ready: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-            });
+        req.from_device = http::client()->device_id();
+        req.methods     = {mtx::events::msg::VerificationMethods::SASv1};
+
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                req.transaction_id = this->transaction_id;
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationReady> body;
+
+                body[this->toClient][this->deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationReady,
+                                   mtx::events::EventType::KeyVerificationReady>(
+                    this->transaction_id, body, [](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn("failed to send verification ready: {} {}",
+                                                       err->matrix_error.error,
+                                                       static_cast<int>(err->status_code));
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
 }
 //! accepts a verification
 void
 DeviceVerificationFlow::sendVerificationDone()
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationDone> body;
         mtx::events::msg::KeyVerificationDone req;
 
-        req.transaction_id = this->transaction_id;
-
-        body[this->toClient][this->deviceId.toStdString()] = req;
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationDone,
-                           mtx::events::EventType::KeyVerificationDone>(
-            this->transaction_id, body, [](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to send verification done: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-            });
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationDone> body;
+                req.transaction_id = this->transaction_id;
+
+                body[this->toClient][this->deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationDone,
+                                   mtx::events::EventType::KeyVerificationDone>(
+                    this->transaction_id, body, [](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn("failed to send verification done: {} {}",
+                                                       err->matrix_error.error,
+                                                       static_cast<int>(err->status_code));
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
 }
 //! starts the verification flow
 void
 DeviceVerificationFlow::startVerificationRequest()
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationStart> body;
         mtx::events::msg::KeyVerificationStart req;
 
         req.from_device                  = http::client()->device_id();
-        req.transaction_id               = this->transaction_id;
         req.method                       = mtx::events::msg::VerificationMethods::SASv1;
         req.key_agreement_protocols      = {"curve25519-hkdf-sha256"};
         req.hashes                       = {"sha256"};
-        req.message_authentication_codes = {"hkdf-hmac-sha256", "hmac-sha256"};
+        req.message_authentication_codes = {"hkdf-hmac-sha256"};
         req.short_authentication_string  = {mtx::events::msg::SASMethods::Decimal,
                                            mtx::events::msg::SASMethods::Emoji};
 
-        body[this->toClient][this->deviceId.toStdString()] = req;
-        this->canonical_json                               = nlohmann::json(req);
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationStart,
-                           mtx::events::EventType::KeyVerificationStart>(
-            this->transaction_id, body, [body](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to start verification request: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-            });
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationStart> body;
+                req.transaction_id                                 = this->transaction_id;
+                this->canonical_json                               = nlohmann::json(req);
+                body[this->toClient][this->deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationStart,
+                                   mtx::events::EventType::KeyVerificationStart>(
+                    this->transaction_id, body, [body](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn(
+                                      "failed to start verification request: {} {}",
+                                      err->matrix_error.error,
+                                      static_cast<int>(err->status_code));
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
 }
 //! sends a verification request
 void
 DeviceVerificationFlow::sendVerificationRequest()
 {
-        QDateTime CurrentTime = QDateTime::currentDateTimeUtc();
-
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationRequest> body;
         mtx::events::msg::KeyVerificationRequest req;
 
-        req.from_device    = http::client()->device_id();
-        req.transaction_id = this->transaction_id;
+        req.from_device = http::client()->device_id();
         req.methods.resize(1);
         req.methods[0] = mtx::events::msg::VerificationMethods::SASv1;
-        req.timestamp  = (uint64_t)CurrentTime.toTime_t();
-
-        body[this->toClient][this->deviceId.toStdString()] = req;
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationRequest,
-                           mtx::events::EventType::KeyVerificationRequest>(
-            this->transaction_id, body, [](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to send verification request: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-            });
+
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                QDateTime CurrentTime = QDateTime::currentDateTimeUtc();
+
+                req.transaction_id = this->transaction_id;
+                req.timestamp      = (uint64_t)CurrentTime.toTime_t();
+
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationRequest> body;
+
+                body[this->toClient][this->deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationRequest,
+                                   mtx::events::EventType::KeyVerificationRequest>(
+                    this->transaction_id, body, [](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn("failed to send verification request: {} {}",
+                                                       err->matrix_error.error,
+                                                       static_cast<int>(err->status_code));
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                std::cout << "lulz" << std::endl;
+        }
 }
 //! cancels a verification flow
 void
 DeviceVerificationFlow::cancelVerification(DeviceVerificationFlow::Error error_code)
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationCancel> body;
         mtx::events::msg::KeyVerificationCancel req;
 
-        req.transaction_id = this->transaction_id;
         if (error_code == DeviceVerificationFlow::Error::UnknownMethod) {
                 req.code   = "m.unknown_method";
                 req.reason = "unknown method recieved";
@@ -457,65 +511,79 @@ DeviceVerificationFlow::cancelVerification(DeviceVerificationFlow::Error error_c
                 req.reason = "user cancelled the verification";
         }
 
-        body[this->toClient][deviceId.toStdString()] = req;
-
         emit this->verificationCanceled();
 
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationCancel,
-                           mtx::events::EventType::KeyVerificationCancel>(
-            this->transaction_id, body, [this](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to cancel verification request: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-                    auto verified_cache = cache::getVerifiedCache(this->userId.toStdString());
-                    if (verified_cache.has_value()) {
-                            verified_cache->device_blocked.push_back(this->deviceId.toStdString());
-                            cache::setVerifiedCache(this->userId.toStdString(),
-                                                    verified_cache.value());
-                    } else {
-                            cache::setVerifiedCache(
-                              this->userId.toStdString(),
-                              DeviceVerifiedCache{{}, {}, {this->deviceId.toStdString()}});
-                    }
-                    this->deleteLater();
-            });
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                req.transaction_id = this->transaction_id;
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationCancel> body;
+
+                body[this->toClient][deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationCancel,
+                                   mtx::events::EventType::KeyVerificationCancel>(
+                    this->transaction_id, body, [this](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn(
+                                      "failed to cancel verification request: {} {}",
+                                      err->matrix_error.error,
+                                      static_cast<int>(err->status_code));
+
+                            this->deleteLater();
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
+
+        // TODO : Handle Blocking user better
+        // auto verified_cache = cache::getVerifiedCache(this->userId.toStdString());
+        //     if (verified_cache.has_value()) {
+        //             verified_cache->device_blocked.push_back(this->deviceId.toStdString());
+        //             cache::setVerifiedCache(this->userId.toStdString(),
+        //                                     verified_cache.value());
+        //     } else {
+        //             cache::setVerifiedCache(
+        //               this->userId.toStdString(),
+        //               DeviceVerifiedCache{{}, {}, {this->deviceId.toStdString()}});
+        //     }
 }
 //! sends the verification key
 void
 DeviceVerificationFlow::sendVerificationKey()
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationKey> body;
         mtx::events::msg::KeyVerificationKey req;
 
-        req.key            = this->sas->public_key();
-        req.transaction_id = this->transaction_id;
-
-        body[this->toClient][deviceId.toStdString()] = req;
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationKey,
-                           mtx::events::EventType::KeyVerificationKey>(
-            this->transaction_id, body, [](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to send verification key: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-            });
+        req.key = this->sas->public_key();
+
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationKey> body;
+                req.transaction_id = this->transaction_id;
+
+                body[this->toClient][deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationKey,
+                                   mtx::events::EventType::KeyVerificationKey>(
+                    this->transaction_id, body, [](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn("failed to send verification key: {} {}",
+                                                       err->matrix_error.error,
+                                                       static_cast<int>(err->status_code));
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
 }
 //! sends the mac of the keys
 void
 DeviceVerificationFlow::sendVerificationMac()
 {
-        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationMac> body;
         mtx::events::msg::KeyVerificationMac req;
 
         std::string info = "MATRIX_KEY_VERIFICATION_MAC" + http::client()->user_id().to_string() +
                            http::client()->device_id() + this->toClient.to_string() +
                            this->deviceId.toStdString() + this->transaction_id;
 
-        req.transaction_id = this->transaction_id;
         //! this vector stores the type of the key and the key
         std::vector<std::pair<std::string, std::string>> key_list;
         key_list.push_back(make_pair("ed25519", olm::client()->identity_keys().ed25519));
@@ -531,22 +599,28 @@ DeviceVerificationFlow::sendVerificationMac()
         req.keys =
           this->sas->calculate_mac(req.keys.substr(0, req.keys.size() - 1), info + "KEY_IDS");
 
-        body[this->toClient][deviceId.toStdString()] = req;
-
-        http::client()
-          ->send_to_device<mtx::events::msg::KeyVerificationMac,
-                           mtx::events::EventType::KeyVerificationMac>(
-            this->transaction_id, body, [this](mtx::http::RequestErr err) {
-                    if (err)
-                            nhlog::net()->warn("failed to send verification MAC: {} {}",
-                                               err->matrix_error.error,
-                                               static_cast<int>(err->status_code));
-
-                    if (this->isMacVerified == true)
-                            this->acceptDevice();
-                    else
-                            this->isMacVerified = true;
-            });
+        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationMac> body;
+                req.transaction_id                           = this->transaction_id;
+                body[this->toClient][deviceId.toStdString()] = req;
+
+                http::client()
+                  ->send_to_device<mtx::events::msg::KeyVerificationMac,
+                                   mtx::events::EventType::KeyVerificationMac>(
+                    this->transaction_id, body, [this](mtx::http::RequestErr err) {
+                            if (err)
+                                    nhlog::net()->warn("failed to send verification MAC: {} {}",
+                                                       err->matrix_error.error,
+                                                       static_cast<int>(err->status_code));
+
+                            if (this->isMacVerified == true)
+                                    this->acceptDevice();
+                            else
+                                    this->isMacVerified = true;
+                    });
+        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg) {
+                req.relates_to = this->relation;
+        }
 }
 //! Completes the verification flow
 void
@@ -555,14 +629,11 @@ DeviceVerificationFlow::acceptDevice()
         auto verified_cache = cache::getVerifiedCache(this->userId.toStdString());
         if (verified_cache.has_value()) {
                 verified_cache->device_verified.push_back(this->deviceId.toStdString());
-                for (auto it = verified_cache->device_blocked.begin();
-                     it != verified_cache->device_blocked.end();
-                     it++) {
-                        if (*it == this->deviceId.toStdString()) {
-                                verified_cache->device_blocked.erase(it);
-                        }
-                }
-                cache::setVerifiedCache(this->userId.toStdString(), verified_cache.value());
+                verified_cache->device_blocked.erase(
+                  std::remove(verified_cache->device_blocked.begin(),
+                              verified_cache->device_blocked.end(),
+                              this->deviceId.toStdString()),
+                  verified_cache->device_blocked.end());
         } else {
                 cache::setVerifiedCache(
                   this->userId.toStdString(),
diff --git a/src/DeviceVerificationFlow.h b/src/DeviceVerificationFlow.h
index edff7c8e..3f999e80 100644
--- a/src/DeviceVerificationFlow.h
+++ b/src/DeviceVerificationFlow.h
@@ -2,8 +2,8 @@
 
 #include "Olm.h"
 
+#include "MatrixClient.h"
 #include "mtx/responses/crypto.hpp"
-#include <MatrixClient.h>
 #include <QObject>
 
 class QTimer;
@@ -19,15 +19,22 @@ class DeviceVerificationFlow : public QObject
         Q_PROPERTY(QString userId READ getUserId WRITE setUserId)
         Q_PROPERTY(QString deviceId READ getDeviceId WRITE setDeviceId)
         Q_PROPERTY(Method method READ getMethod WRITE setMethod)
-        Q_PROPERTY(std::vector<int> sasList READ getSasList)
+        Q_PROPERTY(std::vector<int> sasList READ getSasList CONSTANT)
 
 public:
+        enum Type
+        {
+                ToDevice,
+                RoomMsg
+        };
+
         enum Method
         {
                 Decimal,
                 Emoji
         };
         Q_ENUM(Method)
+
         enum Error
         {
                 UnknownMethod,
@@ -39,7 +46,9 @@ public:
         };
         Q_ENUM(Error)
 
-        DeviceVerificationFlow(QObject *parent = nullptr);
+        DeviceVerificationFlow(
+          QObject *parent              = nullptr,
+          DeviceVerificationFlow::Type = DeviceVerificationFlow::Type::ToDevice);
         QString getTransactionId();
         QString getUserId();
         QString getDeviceId();
@@ -90,6 +99,7 @@ private:
         QString userId;
         QString deviceId;
         Method method;
+        Type type;
         bool sender;
 
         QTimer *timeout = nullptr;
@@ -101,4 +111,5 @@ private:
         mtx::identifiers::User toClient;
         std::vector<int> sasList;
         std::map<std::string, std::string> device_keys;
+        mtx::common::ReplyRelatesTo relation;
 };
diff --git a/src/EventAccessors.cpp b/src/EventAccessors.cpp
index 0618206c..869687f4 100644
--- a/src/EventAccessors.cpp
+++ b/src/EventAccessors.cpp
@@ -72,8 +72,15 @@ struct EventBody
         template<class T>
         std::string operator()(const mtx::events::Event<T> &e)
         {
-                if constexpr (is_detected<body_t, T>::value)
-                        return e.content.body;
+                if constexpr (is_detected<body_t, T>::value) {
+                        if constexpr (std::is_same_v<std::optional<std::string>,
+                                                     std::remove_cv_t<decltype(e.content.body)>>)
+                                return e.content.body ? e.content.body.value() : "";
+                        else if constexpr (std::is_same_v<
+                                             std::string,
+                                             std::remove_cv_t<decltype(e.content.body)>>)
+                                return e.content.body;
+                }
                 return "";
         }
 };
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 7d7037c9..ff6ea2f4 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -5,10 +5,10 @@
 
 #include "Cache.h"
 #include "ChatPage.h"
+#include "DeviceVerificationFlow.h"
 #include "Logging.h"
 #include "MatrixClient.h"
 #include "Utils.h"
-#include <DeviceVerificationFlow.h>
 
 static const std::string STORAGE_SECRET_KEY("secret");
 constexpr auto MEGOLM_ALGO = "m.megolm.v1.aes-sha2";
@@ -77,21 +77,42 @@ handle_to_device_messages(const std::vector<mtx::events::collections::DeviceEven
                                   j_msg.dump(2));
                         }
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationAccept)) {
-                        ChatPage::instance()->recievedDeviceVerificationAccept(msg);
+                        auto message = std::get<
+                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationAccept>>(msg);
+                        ChatPage::instance()->recievedDeviceVerificationAccept(message.content);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationRequest)) {
-                        ChatPage::instance()->recievedDeviceVerificationRequest(msg);
+                        auto message = std::get<
+                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationRequest>>(msg);
+                        ChatPage::instance()->recievedDeviceVerificationRequest(message.content,
+                                                                                message.sender);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationCancel)) {
-                        ChatPage::instance()->recievedDeviceVerificationCancel(msg);
+                        auto message = std::get<
+                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationCancel>>(msg);
+                        ChatPage::instance()->recievedDeviceVerificationCancel(message.content);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationKey)) {
-                        ChatPage::instance()->recievedDeviceVerificationKey(msg);
+                        auto message =
+                          std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationKey>>(
+                            msg);
+                        ChatPage::instance()->recievedDeviceVerificationKey(message.content);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationMac)) {
-                        ChatPage::instance()->recievedDeviceVerificationMac(msg);
+                        auto message =
+                          std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationMac>>(
+                            msg);
+                        ChatPage::instance()->recievedDeviceVerificationMac(message.content);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationStart)) {
-                        ChatPage::instance()->recievedDeviceVerificationStart(msg);
+                        auto message = std::get<
+                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationStart>>(msg);
+                        ChatPage::instance()->recievedDeviceVerificationStart(message.content,
+                                                                              message.sender);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationReady)) {
-                        ChatPage::instance()->recievedDeviceVerificationReady(msg);
+                        auto message = std::get<
+                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationReady>>(msg);
+                        ChatPage::instance()->recievedDeviceVerificationReady(message.content);
                 } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationDone)) {
-                        ChatPage::instance()->recievedDeviceVerificationDone(msg);
+                        auto message =
+                          std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationDone>>(
+                            msg);
+                        ChatPage::instance()->recievedDeviceVerificationDone(message.content);
                 } else {
                         nhlog::crypto()->warn("unhandled event: {}", j_msg.dump(2));
                 }
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 773a5a23..71cc53c5 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -22,6 +22,8 @@
 #include "Utils.h"
 #include "dialogs/RawMessage.h"
 
+#include <iostream>
+
 Q_DECLARE_METATYPE(QModelIndex)
 
 namespace std {
@@ -116,7 +118,41 @@ struct RoomEventType
         {
                 return qml_mtx_events::EventType::VideoMessage;
         }
-
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationRequest> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationRequest;
+        }
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationStart> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationStart;
+        }
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationMac> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationMac;
+        }
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationAccept> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationAccept;
+        }
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationCancel> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationCancel;
+        }
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationKey> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationKey;
+        }
+        qml_mtx_events::EventType operator()(
+          const mtx::events::Event<mtx::events::msg::KeyVerificationDone> &)
+        {
+                return qml_mtx_events::EventType::KeyVerificationDone;
+        }
         qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Redacted> &)
         {
                 return qml_mtx_events::EventType::Redacted;
@@ -572,6 +608,155 @@ TimelineModel::updateLastMessage()
         }
 }
 
+std::vector<QString>
+TimelineModel::internalAddEvents(
+  const std::vector<mtx::events::collections::TimelineEvents> &timeline)
+{
+        std::vector<QString> ids;
+        for (auto e : timeline) {
+                QString id = QString::fromStdString(mtx::accessors::event_id(e));
+
+                if (this->events.contains(id)) {
+                        this->events.insert(id, e);
+                        int idx = idToIndex(id);
+                        emit dataChanged(index(idx, 0), index(idx, 0));
+                        continue;
+                }
+
+                QString txid = QString::fromStdString(mtx::accessors::transaction_id(e));
+                if (this->pending.removeOne(txid)) {
+                        this->events.insert(id, e);
+                        this->events.remove(txid);
+                        int idx = idToIndex(txid);
+                        if (idx < 0) {
+                                nhlog::ui()->warn("Received index out of range");
+                                continue;
+                        }
+                        eventOrder[idx] = id;
+                        emit dataChanged(index(idx, 0), index(idx, 0));
+                        continue;
+                }
+
+                if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest>>(
+                      &e)) {
+                        std::cout << "got a request" << std::endl;
+                }
+
+                if (auto cancelVerification =
+                      std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>>(
+                        &e)) {
+                        std::cout<<"it is happening"<<std::endl;
+                        if (cancelVerification->content.relates_to.has_value()) {
+                                QString event_id = QString::fromStdString(
+                                  cancelVerification->content.relates_to.value()
+                                    .in_reply_to.event_id);
+                                auto request =
+                                  std::find(eventOrder.begin(), eventOrder.end(), event_id);
+                                if (request != eventOrder.end()) {
+                                        auto event = events.value(event_id);
+                                        auto e     = std::get_if<mtx::events::RoomEvent<
+                                          mtx::events::msg::KeyVerificationRequest>>(&event);
+                                        std::cout<<json(*e)<<std::endl;
+                                }
+                        }
+                }
+
+                if (auto redaction =
+                      std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(&e)) {
+                        QString redacts = QString::fromStdString(redaction->redacts);
+                        auto redacted   = std::find(eventOrder.begin(), eventOrder.end(), redacts);
+
+                        auto event = events.value(redacts);
+                        if (auto reaction =
+                              std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
+                                &event)) {
+                                QString reactedTo =
+                                  QString::fromStdString(reaction->content.relates_to.event_id);
+                                reactions[reactedTo].removeReaction(*reaction);
+                                int idx = idToIndex(reactedTo);
+                                if (idx >= 0)
+                                        emit dataChanged(index(idx, 0), index(idx, 0));
+                        }
+
+                        if (redacted != eventOrder.end()) {
+                                auto redactedEvent = std::visit(
+                                  [](const auto &ev)
+                                    -> mtx::events::RoomEvent<mtx::events::msg::Redacted> {
+                                          mtx::events::RoomEvent<mtx::events::msg::Redacted>
+                                            replacement                = {};
+                                          replacement.event_id         = ev.event_id;
+                                          replacement.room_id          = ev.room_id;
+                                          replacement.sender           = ev.sender;
+                                          replacement.origin_server_ts = ev.origin_server_ts;
+                                          replacement.type             = ev.type;
+                                          return replacement;
+                                  },
+                                  e);
+                                events.insert(redacts, redactedEvent);
+
+                                int row = (int)std::distance(eventOrder.begin(), redacted);
+                                emit dataChanged(index(row, 0), index(row, 0));
+                        }
+
+                        continue; // don't insert redaction into timeline
+                }
+
+                if (auto reaction =
+                      std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(&e)) {
+                        QString reactedTo =
+                          QString::fromStdString(reaction->content.relates_to.event_id);
+                        events.insert(id, e);
+
+                        // remove local echo
+                        if (!txid.isEmpty()) {
+                                auto rCopy     = *reaction;
+                                rCopy.event_id = txid.toStdString();
+                                reactions[reactedTo].removeReaction(rCopy);
+                        }
+
+                        reactions[reactedTo].addReaction(room_id_.toStdString(), *reaction);
+                        int idx = idToIndex(reactedTo);
+                        if (idx >= 0)
+                                emit dataChanged(index(idx, 0), index(idx, 0));
+                        continue; // don't insert reaction into timeline
+                }
+
+                if (auto event =
+                      std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&e)) {
+                        auto e_      = decryptEvent(*event).event;
+                        auto encInfo = mtx::accessors::file(e_);
+
+                        if (encInfo)
+                                emit newEncryptedImage(encInfo.value());
+                }
+
+                this->events.insert(id, e);
+                ids.push_back(id);
+
+                auto replyTo  = mtx::accessors::in_reply_to_event(e);
+                auto qReplyTo = QString::fromStdString(replyTo);
+                if (!replyTo.empty() && !events.contains(qReplyTo)) {
+                        http::client()->get_event(
+                          this->room_id_.toStdString(),
+                          replyTo,
+                          [this, id, replyTo](
+                            const mtx::events::collections::TimelineEvents &timeline,
+                            mtx::http::RequestErr err) {
+                                  if (err) {
+                                          nhlog::net()->error(
+                                            "Failed to retrieve event with id {}, which was "
+                                            "requested to show the replyTo for event {}",
+                                            replyTo,
+                                            id.toStdString());
+                                          return;
+                                  }
+                                  emit eventFetched(id, timeline);
+                          });
+                }
+        }
+        return ids;
+}
+
 void
 TimelineModel::setCurrentIndex(int index)
 {
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 104a475c..708ed38e 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -84,6 +84,14 @@ enum EventType
         VideoMessage,
         Redacted,
         UnknownMessage,
+        KeyVerificationRequest,
+        KeyVerificationStart,
+        KeyVerificationMac,
+        KeyVerificationAccept,
+        KeyVerificationCancel,
+        KeyVerificationKey,
+        KeyVerificationDone,
+        KeyVerificationReady
 };
 Q_ENUM_NS(EventType)
 
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 81c8d6d3..02b74d20 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -101,7 +101,15 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
   , blurhashProvider(new BlurhashProvider())
   , settings(userSettings)
 {
-        qRegisterMetaType<mtx::events::collections::DeviceEvents>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationDone>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationKey>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationMac>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationReady>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationRequest>();
+        qRegisterMetaType<mtx::events::msg::KeyVerificationStart>();
+
         qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
                                          "im.nheko",
                                          1,
@@ -181,21 +189,19 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
           dynamic_cast<ChatPage *>(parent),
           &ChatPage::recievedDeviceVerificationRequest,
           this,
-          [this](const mtx::events::collections::DeviceEvents &message) {
-                  auto msg =
-                    std::get<mtx::events::DeviceEvent<msgs::KeyVerificationRequest>>(message);
+          [this](const mtx::events::msg::KeyVerificationRequest &msg, std::string sender) {
                   auto flow = new DeviceVerificationFlow(this);
-                  if (!(this->dvList->exist(QString::fromStdString(msg.content.transaction_id)))) {
-                          if (std::find(msg.content.methods.begin(),
-                                        msg.content.methods.end(),
+                  if (!(this->dvList->exist(QString::fromStdString(msg.transaction_id.value())))) {
+                          if (std::find(msg.methods.begin(),
+                                        msg.methods.end(),
                                         mtx::events::msg::VerificationMethods::SASv1) !=
-                              msg.content.methods.end()) {
+                              msg.methods.end()) {
                                   //   flow->sendVerificationReady();
                                   emit newDeviceVerificationRequest(
                                     std::move(flow),
-                                    QString::fromStdString(msg.content.transaction_id),
-                                    QString::fromStdString(msg.sender),
-                                    QString::fromStdString(msg.content.from_device));
+                                    QString::fromStdString(msg.transaction_id.value()),
+                                    QString::fromStdString(sender),
+                                    QString::fromStdString(msg.from_device));
                           } else {
                                   flow->cancelVerification(
                                     DeviceVerificationFlow::Error::UnknownMethod);
@@ -206,33 +212,29 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
           dynamic_cast<ChatPage *>(parent),
           &ChatPage::recievedDeviceVerificationStart,
           this,
-          [this](const mtx::events::collections::DeviceEvents &message) {
-                  auto msg =
-                    std::get<mtx::events::DeviceEvent<msgs::KeyVerificationStart>>(message);
+          [this](const mtx::events::msg::KeyVerificationStart &msg, std::string sender) {
                   auto flow            = new DeviceVerificationFlow(this);
-                  flow->canonical_json = nlohmann::json(msg.content);
-                  if (!(this->dvList->exist(QString::fromStdString(msg.content.transaction_id)))) {
-                          if ((std::find(msg.content.key_agreement_protocols.begin(),
-                                         msg.content.key_agreement_protocols.end(),
+                  flow->canonical_json = nlohmann::json(msg);
+                  if (!(this->dvList->exist(QString::fromStdString(msg.transaction_id.value())))) {
+                          if ((std::find(msg.key_agreement_protocols.begin(),
+                                         msg.key_agreement_protocols.end(),
                                          "curve25519-hkdf-sha256") !=
-                               msg.content.key_agreement_protocols.end()) &&
-                              (std::find(msg.content.hashes.begin(),
-                                         msg.content.hashes.end(),
-                                         "sha256") != msg.content.hashes.end()) &&
-                              (std::find(msg.content.message_authentication_codes.begin(),
-                                         msg.content.message_authentication_codes.end(),
+                               msg.key_agreement_protocols.end()) &&
+                              (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") !=
+                               msg.hashes.end()) &&
+                              (std::find(msg.message_authentication_codes.begin(),
+                                         msg.message_authentication_codes.end(),
                                          "hmac-sha256") !=
-                               msg.content.message_authentication_codes.end())) {
-                                  if (std::find(msg.content.short_authentication_string.begin(),
-                                                msg.content.short_authentication_string.end(),
+                               msg.message_authentication_codes.end())) {
+                                  if (std::find(msg.short_authentication_string.begin(),
+                                                msg.short_authentication_string.end(),
                                                 mtx::events::msg::SASMethods::Emoji) !=
-                                      msg.content.short_authentication_string.end()) {
+                                      msg.short_authentication_string.end()) {
                                           flow->setMethod(DeviceVerificationFlow::Method::Emoji);
-                                  } else if (std::find(
-                                               msg.content.short_authentication_string.begin(),
-                                               msg.content.short_authentication_string.end(),
-                                               mtx::events::msg::SASMethods::Decimal) !=
-                                             msg.content.short_authentication_string.end()) {
+                                  } else if (std::find(msg.short_authentication_string.begin(),
+                                                       msg.short_authentication_string.end(),
+                                                       mtx::events::msg::SASMethods::Decimal) !=
+                                             msg.short_authentication_string.end()) {
                                           flow->setMethod(DeviceVerificationFlow::Method::Decimal);
                                   } else {
                                           flow->cancelVerification(
@@ -241,10 +243,10 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
                                   }
                                   emit newDeviceVerificationRequest(
                                     std::move(flow),
-                                    QString::fromStdString(msg.content.transaction_id),
-                                    QString::fromStdString(msg.sender),
-                                    QString::fromStdString(msg.content.from_device));
-                                  flow->canonical_json = nlohmann::json(msg.content);
+                                    QString::fromStdString(msg.transaction_id.value()),
+                                    QString::fromStdString(sender),
+                                    QString::fromStdString(msg.from_device));
+                                  flow->canonical_json = nlohmann::json(msg);
                           } else {
                                   flow->cancelVerification(
                                     DeviceVerificationFlow::Error::UnknownMethod);
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index a438ef5e..71aee5ef 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -133,4 +133,11 @@ private:
 
         DeviceVerificationList *dvList;
 };
-Q_DECLARE_METATYPE(mtx::events::collections::DeviceEvents)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationAccept)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationCancel)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationDone)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationKey)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationMac)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationReady)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationRequest)
+Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationStart)
diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index 6ae04d0b..3499384c 100644
--- a/src/ui/UserProfile.cpp
+++ b/src/ui/UserProfile.cpp
@@ -6,6 +6,8 @@
 #include "Utils.h"
 #include "mtx/responses/crypto.hpp"
 
+#include <iostream> // only for debugging
+
 UserProfile::UserProfile(QString roomid, QString userid, QObject *parent)
   : QObject(parent)
   , roomid_(roomid)
@@ -74,6 +76,12 @@ UserProfile::avatarUrl()
         return cache::avatarUrl(roomid_, userid_);
 }
 
+bool
+UserProfile::getUserStatus()
+{
+        return isUserVerified;
+}
+
 void
 UserProfile::callback_fn(const mtx::responses::QueryKeys &res,
                          mtx::http::RequestErr err,
@@ -100,6 +108,7 @@ UserProfile::callback_fn(const mtx::responses::QueryKeys &res,
 
                 // TODO: Verify signatures and ignore those that don't pass.
                 verification::Status verified = verification::Status::UNVERIFIED;
+                isUserVerified                = device_verified->is_user_verified;
                 if (device_verified.has_value()) {
                         if (std::find(device_verified->cross_verified.begin(),
                                       device_verified->cross_verified.end(),
@@ -174,4 +183,29 @@ UserProfile::startChat()
         if (utils::localUser() != this->userid_)
                 req.invite = {this->userid_.toStdString()};
         emit ChatPage::instance()->createRoom(req);
+}
+
+void
+UserProfile::verifyUser()
+{
+        std::cout << "Checking if to start to device verification or room message verification"
+                  << std::endl;
+        auto joined_rooms = cache::joinedRooms();
+        auto room_infos   = cache::getRoomInfo(joined_rooms);
+
+        for (std::string room_id : joined_rooms) {
+                if ((room_infos[QString::fromStdString(room_id)].member_count == 2) &&
+                    cache::isRoomEncrypted(room_id)) {
+                        auto room_members = cache::roomMembers(room_id);
+                        if (std::find(room_members.begin(),
+                                      room_members.end(),
+                                      (this->userid()).toStdString()) != room_members.end()) {
+                                std::cout << "FOUND A ENCRYPTED ROOM WITH THIS USER : " << room_id
+                                          << std::endl;
+                                return;
+                        }
+                }
+        }
+
+        std::cout << "DIDN'T FIND A ENCRYPTED ROOM WITH THIS USER" << std::endl;
 }
\ No newline at end of file
diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index 4e048400..3f9cbe6f 100644
--- a/src/ui/UserProfile.h
+++ b/src/ui/UserProfile.h
@@ -81,6 +81,7 @@ class UserProfile : public QObject
         Q_PROPERTY(QString userid READ userid CONSTANT)
         Q_PROPERTY(QString avatarUrl READ avatarUrl CONSTANT)
         Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList CONSTANT)
+        Q_PROPERTY(bool isUserVerified READ getUserStatus CONSTANT)
 public:
         UserProfile(QString roomid, QString userid, QObject *parent = 0);
 
@@ -89,17 +90,20 @@ public:
         QString userid();
         QString displayName();
         QString avatarUrl();
+        bool getUserStatus();
 
         Q_INVOKABLE void fetchDeviceList(const QString &userID);
         Q_INVOKABLE void banUser();
         // Q_INVOKABLE void ignoreUser();
         Q_INVOKABLE void kickUser();
         Q_INVOKABLE void startChat();
+        Q_INVOKABLE void verifyUser();
 
 private:
         QString roomid_, userid_;
         std::optional<std::string> cross_verified;
         DeviceInfoModel deviceList_;
+        bool isUserVerified = false;
 
         void callback_fn(const mtx::responses::QueryKeys &res,
                          mtx::http::RequestErr err,