feat: wrappers and debugging get/set for the closed groups in user groups

This commit is contained in:
0x330a
2023-08-31 15:03:29 +10:00
parent 51716e718a
commit 63e156cce5
12 changed files with 223 additions and 75 deletions

View File

@@ -11,6 +11,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.session.libsignal.utilities.Hex
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.toHexString
/**
* Instrumented test, which will execute on an Android device.
@@ -618,4 +619,36 @@ class InstrumentedTests {
}
@Test
fun testGroupInfoOtherWay() {
val (userPublic, userSecret) = keyPair
val userCurve = Sodium.ed25519PkToCurve25519(userPublic)
val groupConfig = UserGroupsConfig.newInstance(userSecret)
val group = groupConfig.createGroup()
val groupSecret = group.adminKey!!
val groupPublic = Hex.fromStringCondensed(group.groupSessionId.publicKey)
groupConfig.set(group)
val infoConf = GroupInfoConfig.newInstance(groupPublic, group.adminKey!!)
infoConf.setName("New Group")
assertEquals("New Group", infoConf.getName())
infoConf.setCreated(System.currentTimeMillis())
assertThat(infoConf.getCreated(), notNullValue())
val memberConf = GroupMemberConfig.newInstance(groupPublic, groupSecret)
memberConf.set(
GroupMember(
sessionId = "05"+Hex.toStringCondensed(userCurve),
name = "User",
admin = true
)
)
val keys = GroupKeysConfig.newInstance(
userSecretKey = userSecret,
groupPublicKey = groupPublic,
groupSecretKey = groupSecret,
info = infoConf,
members = memberConf
)
assertThat(keys.pendingKey(), notNullValue())
}
}

View File

@@ -176,4 +176,4 @@ Java_network_loki_messenger_libsession_1util_GroupInfoConfig_storageNamespace(JN
std::lock_guard guard{util::util_mutex_};
auto group_info = ptrToInfo(env, thiz);
return static_cast<jlong>(group_info->storage_namespace());
}
}

View File

@@ -2,7 +2,6 @@
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
#include "user_groups.h"
#pragma clang diagnostic push
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
extern "C"
@@ -125,6 +124,8 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki
auto conf = ptrToUserGroups(env, thiz);
auto community_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
auto legacy_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
auto closed_group_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
auto object_class = env->GetObjectClass(group_info);
if (env->IsSameObject(community_info, object_class)) {
auto deserialized = deserialize_community_info(env, group_info, conf);
@@ -132,6 +133,15 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki
} else if (env->IsSameObject(legacy_info, object_class)) {
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
conf->set(deserialized);
} else if (env->IsSameObject(closed_group_info, object_class)) {
LOGD("Closed group deserializing...")
auto deserialized = deserialize_closed_group_info(env, group_info);
LOGD("secret key deserialized: %d", deserialized.secretkey.size())
conf->set(deserialized);
auto check_group = conf->get_group(deserialized.id);
if (check_group) {
LOGD("after set: %d", check_group->secretkey.size());
}
}
}
@@ -144,17 +154,22 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_erase__Lnetwork_lo
auto conf = ptrToUserGroups(env, thiz);
auto communityInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
auto legacyInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
if (env->GetObjectClass(group_info) == communityInfo) {
auto closedGroupInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
auto object_class = env->GetObjectClass(group_info);
if (env->IsSameObject(communityInfo, object_class)) {
auto deserialized = deserialize_community_info(env, group_info, conf);
conf->erase(deserialized);
} else if (env->GetObjectClass(group_info) == legacyInfo) {
} else if (env->IsSameObject(legacyInfo, object_class)) {
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
conf->erase(deserialized);
} else if (env->IsSameObject(closedGroupInfo, object_class)) {
auto deserialized = deserialize_closed_group_info(env, group_info);
conf->erase(deserialized);
}
}
extern "C"
JNIEXPORT jint JNICALL
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeCommunityInfo(JNIEnv *env,
jobject thiz) {
std::lock_guard lock{util::util_mutex_};
@@ -163,7 +178,7 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeCommunityInfo(
}
extern "C"
JNIEXPORT jint JNICALL
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeLegacyGroupInfo(JNIEnv *env,
jobject thiz) {
std::lock_guard lock{util::util_mutex_};
@@ -172,7 +187,7 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeLegacyGroupInf
}
extern "C"
JNIEXPORT jint JNICALL
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_size(JNIEnv *env, jobject thiz) {
std::lock_guard lock{util::util_mutex_};
auto conf = ptrToConvoInfo(env, thiz);
@@ -192,6 +207,8 @@ inline jobject iterator_as_java_stack(JNIEnv *env, const session::config::UserGr
serialized = serialize_legacy_group_info(env, *lgc);
} else if (auto* community = std::get_if<session::config::community_info>(&item)) {
serialized = serialize_community_info(env, *community);
} else if (auto* closed = std::get_if<session::config::group_info>(&item)) {
serialized = serialize_closed_group_info(env, *closed);
}
if (serialized != nullptr) {
env->CallObjectMethod(our_stack, push, serialized);
@@ -271,6 +288,7 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseLegacyGroup(J
env->ReleaseStringUTFChars(session_id, session_id_bytes);
return return_bool;
}
extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getClosedGroup(JNIEnv *env,
@@ -285,7 +303,65 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getClosedGroup(JNI
env->ReleaseStringUTFChars(session_id, session_id_bytes);
if (group) {
return serialize_group_info(env, *group);
return serialize_closed_group_info(env, *group);
}
return nullptr;
}
extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getOrConstructClosedGroup(JNIEnv *env,
jobject thiz,
jstring session_id) {
std::lock_guard guard{util::util_mutex_};
auto config = ptrToUserGroups(env, thiz);
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
auto group = config->get_or_construct_group(session_id_bytes);
env->ReleaseStringUTFChars(session_id, session_id_bytes);
return serialize_closed_group_info(env, group);
}
extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_allClosedGroupInfo(JNIEnv *env,
jobject thiz) {
std::lock_guard lock{util::util_mutex_};
auto conf = ptrToUserGroups(env, thiz);
return nullptr;
}
extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_createGroup(JNIEnv *env,
jobject thiz) {
std::lock_guard guard{util::util_mutex_};
auto config = ptrToUserGroups(env, thiz);
auto group = config->create_group();
return serialize_closed_group_info(env, group);
}
extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeClosedGroup(JNIEnv *env,
jobject thiz) {
std::lock_guard guard{util::util_mutex_};
auto config = ptrToUserGroups(env, thiz);
return config->size_groups();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseClosedGroup(JNIEnv *env,
jobject thiz,
jstring session_id) {
std::lock_guard guard{util::util_mutex_};
auto config = ptrToUserGroups(env, thiz);
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
bool return_value = config->erase_group(session_id_bytes);
env->ReleaseStringUTFChars(session_id, session_id_bytes);
return return_value;
}

View File

@@ -6,6 +6,10 @@
#include "util.h"
#include "conversation.h"
#include "session/config/user_groups.hpp"
#include <android/log.h>
#define APPNAME "libsession-jni"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, APPNAME, __VA_ARGS__);
inline session::config::UserGroups* ptrToUserGroups(JNIEnv *env, jobject obj) {
jclass configClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig");
@@ -44,23 +48,23 @@ inline void deserialize_members_into(JNIEnv *env, jobject members_map, session::
inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *env, jobject info, session::config::UserGroups* conf) {
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
auto id_field = env->GetFieldID(clazz, "sessionId", "Ljava/lang/String;");
auto id_field = env->GetFieldID(clazz, "sessionId", "Lorg/session/libsignal/utilities/SessionId;");
auto name_field = env->GetFieldID(clazz, "name", "Ljava/lang/String;");
auto members_field = env->GetFieldID(clazz, "members", "Ljava/util/Map;");
auto enc_pub_key_field = env->GetFieldID(clazz, "encPubKey", "[B");
auto enc_sec_key_field = env->GetFieldID(clazz, "encSecKey", "[B");
auto priority_field = env->GetFieldID(clazz, "priority", "I");
auto priority_field = env->GetFieldID(clazz, "priority", "J");
auto disappearing_timer_field = env->GetFieldID(clazz, "disappearingTimer", "J");
auto joined_at_field = env->GetFieldID(clazz, "joinedAt", "J");
jstring id = static_cast<jstring>(env->GetObjectField(info, id_field));
jobject id = env->GetObjectField(info, id_field);
jstring name = static_cast<jstring>(env->GetObjectField(info, name_field));
jobject members_map = env->GetObjectField(info, members_field);
jbyteArray enc_pub_key = static_cast<jbyteArray>(env->GetObjectField(info, enc_pub_key_field));
jbyteArray enc_sec_key = static_cast<jbyteArray>(env->GetObjectField(info, enc_sec_key_field));
int priority = env->GetIntField(info, priority_field);
int priority = env->GetLongField(info, priority_field);
long joined_at = env->GetLongField(info, joined_at_field);
auto id_bytes = env->GetStringUTFChars(id, nullptr);
auto id_bytes = util::deserialize_session_id(env, id);
auto name_bytes = env->GetStringUTFChars(name, nullptr);
auto enc_pub_key_bytes = util::ustring_from_bytes(env, enc_pub_key);
auto enc_sec_key_bytes = util::ustring_from_bytes(env, enc_sec_key);
@@ -78,7 +82,6 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
info_deserialized.priority = priority;
info_deserialized.disappearing_timer = std::chrono::seconds(env->GetLongField(info, disappearing_timer_field));
info_deserialized.joined_at = joined_at;
env->ReleaseStringUTFChars(id, id_bytes);
env->ReleaseStringUTFChars(name, name_bytes);
return info_deserialized;
}
@@ -86,10 +89,10 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
inline session::config::community_info deserialize_community_info(JNIEnv *env, jobject info, session::config::UserGroups* conf) {
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
auto base_info = env->GetFieldID(clazz, "community", "Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;");
auto priority = env->GetFieldID(clazz, "priority", "I");
auto priority = env->GetFieldID(clazz, "priority", "J");
jobject base_community_info = env->GetObjectField(info, base_info);
auto deserialized_base_info = util::deserialize_base_community(env, base_community_info);
int deserialized_priority = env->GetIntField(info, priority);
int deserialized_priority = env->GetLongField(info, priority);
auto community_info = conf->get_or_construct_community(deserialized_base_info.base_url(), deserialized_base_info.room(), deserialized_base_info.pubkey_hex());
community_info.priority = deserialized_priority;
return community_info;
@@ -113,59 +116,59 @@ inline jobject serialize_members(JNIEnv *env, std::map<std::string, bool> member
}
inline jobject serialize_legacy_group_info(JNIEnv *env, session::config::legacy_group_info info) {
jstring session_id = env->NewStringUTF(info.session_id.data());
jobject session_id = util::serialize_session_id(env, info.session_id);
jstring name = env->NewStringUTF(info.name.data());
jobject members = serialize_members(env, info.members());
jbyteArray enc_pubkey = util::bytes_from_ustring(env, info.enc_pubkey);
jbyteArray enc_seckey = util::bytes_from_ustring(env, info.enc_seckey);
int priority = info.priority;
long joined_at = info.joined_at;
long long priority = info.priority;
long long joined_at = info.joined_at;
jclass legacy_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;[B[BIJJ)V");
jobject serialized = env->NewObject(legacy_group_class, constructor, session_id, name, members, enc_pubkey, enc_seckey, priority, (jlong) info.disappearing_timer.count(), joined_at);
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Lorg/session/libsignal/utilities/SessionId;Ljava/lang/String;Ljava/util/Map;[B[BJJJ)V");
jobject serialized = env->NewObject(legacy_group_class, constructor, session_id, name, members, enc_pubkey, enc_seckey, priority, info.disappearing_timer.count(), joined_at);
return serialized;
}
inline jobject serialize_group_info(JNIEnv* env, session::config::group_info info) {
jstring session_id = env->NewStringUTF(info.id.data());
inline jobject serialize_closed_group_info(JNIEnv* env, session::config::group_info info) {
auto session_id = util::serialize_session_id(env, info.id);
jbyteArray admin_bytes = util::bytes_from_ustring(env, info.secretkey);
jbyteArray auth_bytes = util::bytes_from_ustring(env, info.auth_sig);
LOGD("admin byte length: %d", info.secretkey.size());
jbyteArray auth_bytes = util::bytes_from_ustring(env, info.auth_data);
jclass group_info_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
jmethodID constructor = env->GetMethodID(group_info_class, "<init>", "(Ljava/lang/String;[B[B)V");
jmethodID constructor = env->GetMethodID(group_info_class, "<init>", "(Lorg/session/libsignal/utilities/SessionId;[B[B)V");
jobject return_object = env->NewObject(group_info_class,constructor,
session_id, admin_bytes, auth_bytes);
return return_object;
}
inline session::config::group_info deserialize_group_info(JNIEnv* env, jobject info_serialized) {
inline session::config::group_info deserialize_closed_group_info(JNIEnv* env, jobject info_serialized) {
jclass closed_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
jfieldID id_field = env->GetFieldID(closed_group_class, "groupSessionId", "Ljava/lang/String;");
jfieldID id_field = env->GetFieldID(closed_group_class, "groupSessionId", "Lorg/session/libsignal/utilities/SessionId;");
jfieldID secret_field = env->GetFieldID(closed_group_class, "adminKey", "[B");
jfieldID auth_field = env->GetFieldID(closed_group_class, "signingKey", "[B");
jfieldID auth_field = env->GetFieldID(closed_group_class, "authData", "[B");
jstring id_jstring = (jstring)env->GetObjectField(info_serialized, id_field);
jobject id_jobject = env->GetObjectField(info_serialized, id_field);
jbyteArray secret_jBytes = (jbyteArray)env->GetObjectField(info_serialized, secret_field);
jbyteArray auth_jBytes = (jbyteArray)env->GetObjectField(info_serialized, auth_field);
auto id_bytes = env->GetStringUTFChars(id_jstring, nullptr);
auto id_bytes = util::deserialize_session_id(env, id_jobject);
auto secret_bytes = util::ustring_from_bytes(env, secret_jBytes);
auto auth_bytes = util::ustring_from_bytes(env, auth_jBytes);
session::config::group_info group_info(id_bytes);
group_info.auth_sig = auth_bytes;
group_info.auth_data = auth_bytes;
group_info.secretkey = secret_bytes;
env->ReleaseStringUTFChars(id_jstring, id_bytes);
return group_info;
}
inline jobject serialize_community_info(JNIEnv *env, session::config::community_info info) {
auto priority = info.priority;
auto priority = (long long)info.priority;
auto serialized_info = util::serialize_base_community(env, info);
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;I)V");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;J)V");
jobject serialized = env->NewObject(clazz, constructor, serialized_info, priority);
return serialized;
}

View File

@@ -203,6 +203,27 @@ namespace util {
return env->NewStringUTF(optional->data());
}
jobject serialize_session_id(JNIEnv* env, std::string_view session_id) {
if (session_id.size() != 66) return nullptr;
jclass id_class = env->FindClass("org/session/libsignal/utilities/SessionId");
jmethodID session_id_constructor = env->GetStaticMethodID(id_class, "from", "(Ljava/lang/String;)Lorg/session/libsignal/utilities/SessionId;");
jstring session_id_string = env->NewStringUTF(session_id.data());
return env->CallStaticObjectMethod(id_class, session_id_constructor, session_id_string);
}
std::string deserialize_session_id(JNIEnv* env, jobject session_id) {
jclass session_id_class = env->FindClass("org/session/libsignal/utilities/SessionId");
jmethodID get_string = env->GetMethodID(session_id_class, "hexString", "()Ljava/lang/String;");
auto hex_jstring = (jstring)env->CallObjectMethod(session_id, get_string);
auto hex_bytes = env->GetStringUTFChars(hex_jstring, nullptr);
std::string hex_string{hex_bytes};
env->ReleaseStringUTFChars(hex_jstring, hex_bytes);
return hex_string;
}
}
extern "C"

View File

@@ -27,6 +27,8 @@ namespace util {
session::config::groups::member deserialize_group_member(JNIEnv* env, jobject member);
jobject jlongFromOptional(JNIEnv* env, std::optional<long long> optional);
jstring jstringFromOptional(JNIEnv* env, std::optional<std::string_view> optional);
jobject serialize_session_id(JNIEnv* env, std::string_view session_id);
std::string deserialize_session_id(JNIEnv* env, jobject session_id);
}
#endif

View File

@@ -192,22 +192,25 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
external fun getCommunityInfo(baseUrl: String, room: String): GroupInfo.CommunityGroupInfo?
external fun getLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo?
external fun getClosedGroup(sessionId: String): GroupInfo.ClosedGroupInfo?
external fun getOrConstructCommunityInfo(baseUrl: String, room: String, pubKeyHex: String): GroupInfo.CommunityGroupInfo
external fun getOrConstructLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo
external fun getOrConstructClosedGroup(sessionId: String): GroupInfo.ClosedGroupInfo
external fun set(groupInfo: GroupInfo)
external fun erase(communityInfo: GroupInfo)
external fun eraseCommunity(baseCommunityInfo: BaseCommunityInfo): Boolean
external fun eraseCommunity(server: String, room: String): Boolean
external fun eraseLegacyGroup(sessionId: String): Boolean
external fun sizeCommunityInfo(): Int
external fun sizeLegacyGroupInfo(): Int
external fun size(): Int
external fun eraseClosedGroup(sessionId: String): Boolean
external fun sizeCommunityInfo(): Long
external fun sizeLegacyGroupInfo(): Long
external fun sizeClosedGroup(): Long
external fun size(): Long
external fun all(): List<GroupInfo>
external fun allCommunityInfo(): List<GroupInfo.CommunityGroupInfo>
external fun allLegacyGroupInfo(): List<GroupInfo.LegacyGroupInfo>
external fun getClosedGroup(sessionId: String): GroupInfo.ClosedGroupInfo?
external fun getOrConstructClosedGroup(sessionId: String): GroupInfo.ClosedGroupInfo
external fun all():
external fun allClosedGroupInfo(): List<GroupInfo.ClosedGroupInfo>
external fun createGroup(): GroupInfo.ClosedGroupInfo
}
class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
@@ -222,7 +225,6 @@ class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
initialDump: ByteArray = byteArrayOf()
): GroupInfoConfig
}
external fun destroyGroup()
external fun getCreated(): Long?
external fun getDeleteAttachmentsBefore(): Long?

View File

@@ -1,13 +1,15 @@
package network.loki.messenger.libsession_util.util
import org.session.libsignal.utilities.SessionId
sealed class GroupInfo {
data class CommunityGroupInfo(val community: BaseCommunityInfo, val priority: Int) : GroupInfo()
data class CommunityGroupInfo(val community: BaseCommunityInfo, val priority: Long) : GroupInfo()
data class ClosedGroupInfo(
val groupSessionId: String,
val groupSessionId: SessionId,
val adminKey: ByteArray?,
val signingKey: ByteArray?
val authData: ByteArray?
): GroupInfo() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -20,10 +22,10 @@ sealed class GroupInfo {
if (other.adminKey == null) return false
if (!adminKey.contentEquals(other.adminKey)) return false
} else if (other.adminKey != null) return false
if (signingKey != null) {
if (other.signingKey == null) return false
if (!signingKey.contentEquals(other.signingKey)) return false
} else if (other.signingKey != null) return false
if (authData != null) {
if (other.authData == null) return false
if (!authData.contentEquals(other.authData)) return false
} else if (other.authData != null) return false
return true
}
@@ -31,18 +33,18 @@ sealed class GroupInfo {
override fun hashCode(): Int {
var result = groupSessionId.hashCode()
result = 31 * result + (adminKey?.contentHashCode() ?: 0)
result = 31 * result + (signingKey?.contentHashCode() ?: 0)
result = 31 * result + (authData?.contentHashCode() ?: 0)
return result
}
}
data class LegacyGroupInfo(
val sessionId: String,
val sessionId: SessionId,
val name: String,
val members: Map<String, Boolean>,
val encPubKey: ByteArray,
val encSecKey: ByteArray,
val priority: Int,
val priority: Long,
val disappearingTimer: Long,
val joinedAt: Long
): GroupInfo() {
@@ -75,11 +77,12 @@ sealed class GroupInfo {
result = 31 * result + members.hashCode()
result = 31 * result + encPubKey.contentHashCode()
result = 31 * result + encSecKey.contentHashCode()
result = 31 * result + priority
result = 31 * result + priority.hashCode()
result = 31 * result + disappearingTimer.hashCode()
result = 31 * result + joinedAt.hashCode()
return result
}
}
}