mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-03-03 10:36:47 +00:00
remove unnecessary pre key loading
This commit is contained in:
parent
eb70d7119f
commit
4cbeaf3ff7
20 changed files with 9536 additions and 1632 deletions
2054
lib/src/database/schemas/twonly_db/drift_schema_v8.json
Normal file
2054
lib/src/database/schemas/twonly_db/drift_schema_v8.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -82,7 +82,4 @@ class MessageHistories extends Table {
|
|||
TextColumn get content => text().nullable()();
|
||||
|
||||
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||
|
||||
@DataClassName('SignalContactPreKey')
|
||||
class SignalContactPreKeys extends Table {
|
||||
IntColumn get contactId =>
|
||||
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
|
||||
IntColumn get preKeyId => integer()();
|
||||
BlobColumn get preKey => blob()();
|
||||
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||
@override
|
||||
Set<Column> get primaryKey => {contactId, preKeyId};
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||
|
||||
@DataClassName('SignalContactSignedPreKey')
|
||||
class SignalContactSignedPreKeys extends Table {
|
||||
IntColumn get contactId =>
|
||||
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
|
||||
IntColumn get signedPreKeyId => integer()();
|
||||
BlobColumn get signedPreKey => blob()();
|
||||
BlobColumn get signedPreKeySignature => blob()();
|
||||
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||
@override
|
||||
Set<Column> get primaryKey => {contactId};
|
||||
}
|
||||
|
|
@ -9,15 +9,12 @@ import 'package:twonly/src/database/daos/mediafiles.dao.dart';
|
|||
import 'package:twonly/src/database/daos/messages.dao.dart';
|
||||
import 'package:twonly/src/database/daos/reactions.dao.dart';
|
||||
import 'package:twonly/src/database/daos/receipts.dao.dart';
|
||||
import 'package:twonly/src/database/daos/signal.dao.dart';
|
||||
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||
import 'package:twonly/src/database/tables/groups.table.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||
import 'package:twonly/src/database/tables/reactions.table.dart';
|
||||
import 'package:twonly/src/database/tables/receipts.table.dart';
|
||||
import 'package:twonly/src/database/tables/signal_contact_prekey.table.dart';
|
||||
import 'package:twonly/src/database/tables/signal_contact_signed_prekey.table.dart';
|
||||
import 'package:twonly/src/database/tables/signal_identity_key_store.table.dart';
|
||||
import 'package:twonly/src/database/tables/signal_pre_key_store.table.dart';
|
||||
import 'package:twonly/src/database/tables/signal_sender_key_store.table.dart';
|
||||
|
|
@ -43,15 +40,12 @@ part 'twonly.db.g.dart';
|
|||
SignalPreKeyStores,
|
||||
SignalSenderKeyStores,
|
||||
SignalSessionStores,
|
||||
SignalContactPreKeys,
|
||||
SignalContactSignedPreKeys,
|
||||
MessageActions,
|
||||
GroupHistories,
|
||||
],
|
||||
daos: [
|
||||
MessagesDao,
|
||||
ContactsDao,
|
||||
SignalDao,
|
||||
ReceiptsDao,
|
||||
GroupsDao,
|
||||
ReactionsDao,
|
||||
|
|
@ -68,7 +62,7 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 7;
|
||||
int get schemaVersion => 8;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(
|
||||
|
|
@ -99,6 +93,7 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
},
|
||||
from3To4: (m, schema) async {
|
||||
await m.alterTable(
|
||||
// ignore: experimental_member_use
|
||||
TableMigration(
|
||||
schema.groupHistories,
|
||||
columnTransformer: {
|
||||
|
|
@ -127,6 +122,15 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
schema.messages.additionalMessageData,
|
||||
);
|
||||
},
|
||||
from7To8: (m, schema) async {
|
||||
await m.deleteTable('signal_contact_pre_keys');
|
||||
await m.deleteTable('signal_contact_signed_pre_keys');
|
||||
// For message_actions
|
||||
// ignore: experimental_member_use
|
||||
await m.alterTable(TableMigration(schema.messageHistories));
|
||||
// ignore: experimental_member_use
|
||||
await m.alterTable(TableMigration(schema.messageActions));
|
||||
},
|
||||
)(m, from, to);
|
||||
},
|
||||
);
|
||||
|
|
@ -174,8 +178,6 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
senderProfileCounter: Value(0),
|
||||
),
|
||||
);
|
||||
await delete(signalContactPreKeys).go();
|
||||
await delete(signalContactSignedPreKeys).go();
|
||||
await (delete(signalPreKeyStores)
|
||||
..where(
|
||||
(t) => (t.createdAt.isSmallerThanValue(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -35,7 +35,6 @@ import 'package:twonly/src/services/flame.service.dart';
|
|||
import 'package:twonly/src/services/group.services.dart';
|
||||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||
import 'package:twonly/src/services/signal/identity.signal.dart';
|
||||
import 'package:twonly/src/services/signal/prekeys.signal.dart';
|
||||
import 'package:twonly/src/services/signal/utils.signal.dart';
|
||||
import 'package:twonly/src/services/subscription.service.dart';
|
||||
import 'package:twonly/src/utils/keyvalue.dart';
|
||||
|
|
@ -735,45 +734,6 @@ class ApiService {
|
|||
return sendRequestSync(req);
|
||||
}
|
||||
|
||||
Future<Response_SignedPreKey?> getSignedKeyByUserId(int userId) async {
|
||||
final get = ApplicationData_GetSignedPreKeyByUserId()
|
||||
..userId = Int64(userId);
|
||||
final appData = ApplicationData()..getSignedPrekeyByUserid = get;
|
||||
final req = createClientToServerFromApplicationData(appData);
|
||||
final res = await sendRequestSync(req, contactId: userId);
|
||||
if (res.isSuccess) {
|
||||
final ok = res.value as server.Response_Ok;
|
||||
if (ok.hasSignedprekey()) {
|
||||
return ok.signedprekey;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<OtherPreKeys?> getPreKeysByUserId(int userId) async {
|
||||
final get = ApplicationData_GetPrekeysByUserId()..userId = Int64(userId);
|
||||
final appData = ApplicationData()..getPrekeysByUserId = get;
|
||||
final req = createClientToServerFromApplicationData(appData);
|
||||
final res = await sendRequestSync(req, contactId: userId);
|
||||
if (res.isSuccess) {
|
||||
final ok = res.value as server.Response_Ok;
|
||||
if (ok.hasUserdata()) {
|
||||
final data = ok.userdata;
|
||||
if (data.hasSignedPrekey() &&
|
||||
data.hasSignedPrekeyId() &&
|
||||
data.hasSignedPrekeySignature()) {
|
||||
return OtherPreKeys(
|
||||
preKeys: ok.userdata.prekeys,
|
||||
signedPreKey: data.signedPrekey,
|
||||
signedPreKeyId: data.signedPrekeyId.toInt(),
|
||||
signedPreKeySignature: data.signedPrekeySignature,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Response_PlanBallance?> loadPlanBalance({bool useCache = true}) async {
|
||||
final ballance = await getPlanBallance();
|
||||
if (ballance != null) {
|
||||
|
|
|
|||
|
|
@ -91,11 +91,6 @@ Future<void> handleClient2ClientMessage(NewMessage newMessage) async {
|
|||
var retry = false;
|
||||
if (message.hasPlaintextContent()) {
|
||||
if (message.plaintextContent.hasDecryptionErrorMessage()) {
|
||||
if (message.plaintextContent.decryptionErrorMessage.type ==
|
||||
PlaintextContent_DecryptionErrorMessage_Type.PREKEY_UNKNOWN) {
|
||||
// in case there was a pre key error remove all downloaded pre keys. New pre keys will be fetched automatically.
|
||||
await twonlyDB.signalDao.purgePreKeysFromContact(fromUserId);
|
||||
}
|
||||
Log.info(
|
||||
'Got decryption error: ${message.plaintextContent.decryptionErrorMessage.type} for $receiptId',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
|||
import 'package:mutex/mutex.dart';
|
||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||
import 'package:twonly/src/services/signal/consts.signal.dart';
|
||||
import 'package:twonly/src/services/signal/prekeys.signal.dart';
|
||||
import 'package:twonly/src/services/signal/utils.signal.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
|
||||
|
|
@ -19,62 +18,7 @@ Future<CiphertextMessage?> signalEncryptMessage(
|
|||
try {
|
||||
final signalStore = (await getSignalStore())!;
|
||||
final address = SignalProtocolAddress(target.toString(), defaultDeviceId);
|
||||
|
||||
final session = SessionCipher.fromStore(signalStore, address);
|
||||
|
||||
final preKey = await getPreKeyByContactId(target);
|
||||
final signedPreKey = await getSignedPreKeyByContactId(target);
|
||||
|
||||
if (signedPreKey != null) {
|
||||
final sessionBuilder = SessionBuilder.fromSignalStore(
|
||||
signalStore,
|
||||
address,
|
||||
);
|
||||
|
||||
ECPublicKey? tempPrePublicKey;
|
||||
|
||||
if (preKey != null) {
|
||||
tempPrePublicKey = Curve.decodePoint(
|
||||
DjbECPublicKey(
|
||||
Uint8List.fromList(preKey.preKey),
|
||||
).serialize(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
final tempSignedPreKeyPublic = Curve.decodePoint(
|
||||
DjbECPublicKey(Uint8List.fromList(signedPreKey.signedPreKey))
|
||||
.serialize(),
|
||||
1,
|
||||
);
|
||||
|
||||
final tempSignedPreKeySignature = Uint8List.fromList(
|
||||
signedPreKey.signedPreKeySignature,
|
||||
);
|
||||
|
||||
final tempIdentityKey = await signalStore.getIdentity(address);
|
||||
if (tempIdentityKey != null) {
|
||||
final registrationId = await session.getRemoteRegistrationId();
|
||||
final preKeyBundle = PreKeyBundle(
|
||||
registrationId,
|
||||
defaultDeviceId,
|
||||
preKey?.preKeyId,
|
||||
tempPrePublicKey,
|
||||
signedPreKey.signedPreKeyId,
|
||||
tempSignedPreKeyPublic,
|
||||
tempSignedPreKeySignature,
|
||||
tempIdentityKey,
|
||||
);
|
||||
|
||||
try {
|
||||
await sessionBuilder.processPreKeyBundle(preKeyBundle);
|
||||
} catch (e) {
|
||||
Log.error('could not process pre key bundle: $e');
|
||||
}
|
||||
} else {
|
||||
Log.error('did not get the identity of the remote address');
|
||||
}
|
||||
}
|
||||
return await session.encrypt(plaintextContent);
|
||||
} catch (e) {
|
||||
Log.error(e.toString());
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
||||
as server;
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
|
||||
class OtherPreKeys {
|
||||
OtherPreKeys({
|
||||
required this.preKeys,
|
||||
required this.signedPreKey,
|
||||
required this.signedPreKeyId,
|
||||
required this.signedPreKeySignature,
|
||||
});
|
||||
final List<server.Response_PreKey> preKeys;
|
||||
final int signedPreKeyId;
|
||||
final List<int> signedPreKey;
|
||||
final List<int> signedPreKeySignature;
|
||||
}
|
||||
|
||||
Mutex requestNewKeys = Mutex();
|
||||
DateTime lastPreKeyRequest = clock.now().subtract(const Duration(hours: 1));
|
||||
DateTime lastSignedPreKeyRequest =
|
||||
clock.now().subtract(const Duration(hours: 1));
|
||||
|
||||
Future<void> requestNewPrekeysForContact(int contactId) async {
|
||||
if (lastPreKeyRequest
|
||||
.isAfter(clock.now().subtract(const Duration(seconds: 60)))) {
|
||||
return;
|
||||
}
|
||||
Log.info('[PREKEY] Requesting new PREKEYS for $contactId');
|
||||
lastPreKeyRequest = clock.now();
|
||||
await requestNewKeys.protect(() async {
|
||||
final otherKeys = await apiService.getPreKeysByUserId(contactId);
|
||||
if (otherKeys != null) {
|
||||
Log.info(
|
||||
'[PREKEY] Got fresh ${otherKeys.preKeys.length} pre keys from other $contactId!',
|
||||
);
|
||||
final preKeys = otherKeys.preKeys
|
||||
.map(
|
||||
(preKey) => SignalContactPreKeysCompanion(
|
||||
contactId: Value(contactId),
|
||||
preKey: Value(Uint8List.fromList(preKey.prekey)),
|
||||
preKeyId: Value(preKey.id.toInt()),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
await twonlyDB.signalDao.insertPreKeys(preKeys);
|
||||
} else {
|
||||
Log.warn('[PREKEY] Could not load new pre keys for user $contactId');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<SignalContactPreKey?> getPreKeyByContactId(int contactId) async {
|
||||
final count = await twonlyDB.signalDao.countPreKeysByContactId(contactId);
|
||||
if (count < 10) {
|
||||
unawaited(requestNewPrekeysForContact(contactId));
|
||||
}
|
||||
return twonlyDB.signalDao.popPreKeyByContactId(contactId);
|
||||
}
|
||||
|
||||
Future<void> requestNewSignedPreKeyForContact(int contactId) async {
|
||||
if (lastSignedPreKeyRequest
|
||||
.isAfter(clock.now().subtract(const Duration(seconds: 60)))) {
|
||||
Log.info('last signed pre request was 60s before');
|
||||
return;
|
||||
}
|
||||
lastSignedPreKeyRequest = clock.now();
|
||||
await requestNewKeys.protect(() async {
|
||||
final signedPreKey = await apiService.getSignedKeyByUserId(contactId);
|
||||
if (signedPreKey != null) {
|
||||
Log.info('got fresh signed pre keys from other $contactId!');
|
||||
await twonlyDB.signalDao.insertOrUpdateSignedPreKeyByContactId(
|
||||
SignalContactSignedPreKeysCompanion(
|
||||
contactId: Value(contactId),
|
||||
signedPreKey: Value(Uint8List.fromList(signedPreKey.signedPrekey)),
|
||||
signedPreKeySignature:
|
||||
Value(Uint8List.fromList(signedPreKey.signedPrekeySignature)),
|
||||
signedPreKeyId: Value(signedPreKey.signedPrekeyId.toInt()),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Log.warn('could not load new signed pre key for user $contactId');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<SignalContactSignedPreKey?> getSignedPreKeyByContactId(
|
||||
int contactId,
|
||||
) async {
|
||||
final signedPreKey =
|
||||
await twonlyDB.signalDao.getSignedPreKeyByContactId(contactId);
|
||||
|
||||
if (signedPreKey != null) {
|
||||
final fortyEightHoursAgo = clock.now().subtract(const Duration(hours: 48));
|
||||
final isOlderThan48Hours =
|
||||
signedPreKey.createdAt.isBefore(fortyEightHoursAgo);
|
||||
if (isOlderThan48Hours) {
|
||||
unawaited(requestNewSignedPreKeyForContact(contactId));
|
||||
}
|
||||
} else {
|
||||
unawaited(requestNewSignedPreKeyForContact(contactId));
|
||||
Log.warn('Contact $contactId does not have a signed pre key!');
|
||||
}
|
||||
return signedPreKey;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/internal/migrations.dart';
|
||||
import 'schema_v1.dart' as v1;
|
||||
|
|
@ -10,6 +11,7 @@ import 'schema_v4.dart' as v4;
|
|||
import 'schema_v5.dart' as v5;
|
||||
import 'schema_v6.dart' as v6;
|
||||
import 'schema_v7.dart' as v7;
|
||||
import 'schema_v8.dart' as v8;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
|
|
@ -29,10 +31,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||
return v6.DatabaseAtV6(db);
|
||||
case 7:
|
||||
return v7.DatabaseAtV7(db);
|
||||
case 8:
|
||||
return v8.DatabaseAtV8(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// dart format width=80
|
||||
import 'dart:typed_data' as i2;
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||
// ignore_for_file: type=lint,unused_import
|
||||
//
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
||||
|
|
|
|||
6360
test/drift/twonly_db/generated/schema_v8.dart
Normal file
6360
test/drift/twonly_db/generated/schema_v8.dart
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue