mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-09-26 02:50:52 -04:00
xfer
This commit is contained in:
parent
9d8b609844
commit
bc3ed79cc2
23 changed files with 458 additions and 275 deletions
|
@ -1,201 +0,0 @@
|
|||
import 'package:protobuf/protobuf.dart';
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'tools.dart';
|
||||
|
||||
class DHTRecord {
|
||||
final VeilidRoutingContext _dhtctx;
|
||||
final DHTRecordDescriptor _recordDescriptor;
|
||||
final int _defaultSubkey;
|
||||
final KeyPair? _writer;
|
||||
late final DHTRecordEncryption _encryption;
|
||||
|
||||
static Future<DHTRecord> create(VeilidRoutingContext dhtctx,
|
||||
{DHTSchema schema = const DHTSchema.dflt(oCnt: 1),
|
||||
int defaultSubkey = 0,
|
||||
DHTRecordEncryptionFactory crypto = DHTRecordEncryption.private}) async {
|
||||
DHTRecordDescriptor recordDescriptor = await dhtctx.createDHTRecord(schema);
|
||||
|
||||
final rec = DHTRecord(
|
||||
dhtctx: dhtctx,
|
||||
recordDescriptor: recordDescriptor,
|
||||
defaultSubkey: defaultSubkey,
|
||||
writer: recordDescriptor.ownerKeyPair());
|
||||
|
||||
rec._encryption = crypto(rec);
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
static Future<DHTRecord> openRead(
|
||||
VeilidRoutingContext dhtctx, TypedKey recordKey,
|
||||
{int defaultSubkey = 0,
|
||||
DHTRecordEncryptionFactory crypto = DHTRecordEncryption.private}) async {
|
||||
DHTRecordDescriptor recordDescriptor =
|
||||
await dhtctx.openDHTRecord(recordKey, null);
|
||||
final rec = DHTRecord(
|
||||
dhtctx: dhtctx,
|
||||
recordDescriptor: recordDescriptor,
|
||||
defaultSubkey: defaultSubkey,
|
||||
writer: null);
|
||||
|
||||
rec._encryption = crypto(rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static Future<DHTRecord> openWrite(
|
||||
VeilidRoutingContext dhtctx, TypedKey recordKey, KeyPair writer,
|
||||
{int defaultSubkey = 0,
|
||||
DHTRecordEncryptionFactory crypto = DHTRecordEncryption.private}) async {
|
||||
DHTRecordDescriptor recordDescriptor =
|
||||
await dhtctx.openDHTRecord(recordKey, writer);
|
||||
final rec = DHTRecord(
|
||||
dhtctx: dhtctx,
|
||||
recordDescriptor: recordDescriptor,
|
||||
defaultSubkey: defaultSubkey,
|
||||
writer: writer);
|
||||
rec._encryption = crypto(rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
DHTRecord(
|
||||
{required VeilidRoutingContext dhtctx,
|
||||
required DHTRecordDescriptor recordDescriptor,
|
||||
int defaultSubkey = 0,
|
||||
KeyPair? writer})
|
||||
: _dhtctx = dhtctx,
|
||||
_recordDescriptor = recordDescriptor,
|
||||
_defaultSubkey = defaultSubkey,
|
||||
_writer = writer;
|
||||
|
||||
int subkeyOrDefault(int subkey) => (subkey == -1) ? _defaultSubkey : subkey;
|
||||
|
||||
TypedKey key() {
|
||||
return _recordDescriptor.key;
|
||||
}
|
||||
|
||||
PublicKey owner() {
|
||||
return _recordDescriptor.owner;
|
||||
}
|
||||
|
||||
KeyPair? ownerKeyPair() {
|
||||
return _recordDescriptor.ownerKeyPair();
|
||||
}
|
||||
|
||||
KeyPair? writer() {
|
||||
return _writer;
|
||||
}
|
||||
|
||||
Future<void> close() async {
|
||||
await _dhtctx.closeDHTRecord(_recordDescriptor.key);
|
||||
}
|
||||
|
||||
Future<void> delete() async {
|
||||
await _dhtctx.deleteDHTRecord(_recordDescriptor.key);
|
||||
}
|
||||
|
||||
Future<T> scope<T>(Future<T> Function(DHTRecord) scopeFunction) async {
|
||||
try {
|
||||
return await scopeFunction(this);
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<T> deleteScope<T>(Future<T> Function(DHTRecord) scopeFunction) async {
|
||||
try {
|
||||
return await scopeFunction(this);
|
||||
} catch (_) {
|
||||
delete();
|
||||
rethrow;
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List?> get({int subkey = -1, bool forceRefresh = false}) async {
|
||||
subkey = subkeyOrDefault(subkey);
|
||||
ValueData? valueData =
|
||||
await _dhtctx.getDHTValue(_recordDescriptor.key, subkey, false);
|
||||
if (valueData == null) {
|
||||
return null;
|
||||
}
|
||||
return _encryption.decrypt(valueData.data, subkey);
|
||||
}
|
||||
|
||||
Future<T?> getJson<T>(T Function(Map<String, dynamic>) fromJson,
|
||||
{int subkey = -1, bool forceRefresh = false}) async {
|
||||
final data = await get(subkey: subkey, forceRefresh: forceRefresh);
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
return jsonDecodeBytes(fromJson, data);
|
||||
}
|
||||
|
||||
Future<void> eventualWriteBytes(Uint8List newValue, {int subkey = -1}) async {
|
||||
subkey = subkeyOrDefault(subkey);
|
||||
newValue = await _encryption.encrypt(newValue, subkey);
|
||||
// Get existing identity key
|
||||
ValueData? valueData;
|
||||
do {
|
||||
// Ensure it exists already
|
||||
if (valueData == null) {
|
||||
throw const FormatException("value does not exist");
|
||||
}
|
||||
|
||||
// Set the new data
|
||||
valueData =
|
||||
await _dhtctx.setDHTValue(_recordDescriptor.key, subkey, newValue);
|
||||
|
||||
// Repeat if newer data on the network was found
|
||||
} while (valueData != null);
|
||||
}
|
||||
|
||||
Future<void> eventualUpdateBytes(
|
||||
Future<Uint8List> Function(Uint8List oldValue) update,
|
||||
{int subkey = -1}) async {
|
||||
subkey = subkeyOrDefault(subkey);
|
||||
// Get existing identity key
|
||||
ValueData? valueData =
|
||||
await _dhtctx.getDHTValue(_recordDescriptor.key, subkey, false);
|
||||
do {
|
||||
// Ensure it exists already
|
||||
if (valueData == null) {
|
||||
throw const FormatException("value does not exist");
|
||||
}
|
||||
|
||||
// Update the data
|
||||
final oldData = await _encryption.decrypt(valueData.data, subkey);
|
||||
final updatedData = await update(oldData);
|
||||
final newData = await _encryption.encrypt(updatedData, subkey);
|
||||
|
||||
// Set it back
|
||||
valueData =
|
||||
await _dhtctx.setDHTValue(_recordDescriptor.key, subkey, newData);
|
||||
|
||||
// Repeat if newer data on the network was found
|
||||
} while (valueData != null);
|
||||
}
|
||||
|
||||
Future<void> eventualWriteJson<T>(T newValue, {int subkey = -1}) {
|
||||
return eventualWriteBytes(jsonEncodeBytes(newValue), subkey: subkey);
|
||||
}
|
||||
|
||||
Future<void> eventualWriteProtobuf<T extends GeneratedMessage>(T newValue,
|
||||
{int subkey = -1}) {
|
||||
return eventualWriteBytes(newValue.writeToBuffer(), subkey: subkey);
|
||||
}
|
||||
|
||||
Future<void> eventualUpdateJson<T>(
|
||||
T Function(Map<String, dynamic>) fromJson, Future<T> Function(T) update,
|
||||
{int subkey = -1}) {
|
||||
return eventualUpdateBytes(jsonUpdate(fromJson, update), subkey: subkey);
|
||||
}
|
||||
|
||||
Future<void> eventualUpdateProtobuf<T extends GeneratedMessage>(
|
||||
T Function(List<int>) fromBuffer, Future<T> Function(T) update,
|
||||
{int subkey = -1}) {
|
||||
return eventualUpdateBytes(protobufUpdate(fromBuffer, update),
|
||||
subkey: subkey);
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'tools.dart';
|
||||
|
||||
typedef DHTRecordEncryptionFactory = DHTRecordEncryption Function(DHTRecord);
|
||||
|
||||
abstract class DHTRecordEncryption {
|
||||
factory DHTRecordEncryption.private(DHTRecord record) {
|
||||
return _DHTRecordEncryptionPrivate(record);
|
||||
}
|
||||
factory DHTRecordEncryption.public(DHTRecord record) {
|
||||
return _DHTRecordEncryptionPublic(record);
|
||||
}
|
||||
|
||||
FutureOr<Uint8List> encrypt(Uint8List data, int subkey);
|
||||
FutureOr<Uint8List> decrypt(Uint8List data, int subkey);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
/// Private DHT Record: Encrypted with the owner's secret key
|
||||
class _DHTRecordEncryptionPrivate implements DHTRecordEncryption {
|
||||
_DHTRecordEncryptionPrivate(DHTRecord record) {
|
||||
// xxx derive key from record
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<Uint8List> encrypt(Uint8List data, int subkey) {}
|
||||
|
||||
@override
|
||||
FutureOr<Uint8List> decrypt(Uint8List data, int subkey) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
/// Public DHT Record: No encryption
|
||||
class _DHTRecordEncryptionPublic implements DHTRecordEncryption {
|
||||
_DHTRecordEncryptionPublic(DHTRecord record) {
|
||||
//
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<Uint8List> encrypt(Uint8List data, int subkey) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<Uint8List> decrypt(Uint8List data, int subkey) {
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:veilid/veilid.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import 'package:veilid/veilid.dart';
|
||||
|
||||
Future<T> tableScope<T>(
|
||||
String name, Future<T> Function(VeilidTableDB tdb) callback,
|
||||
{int columnCount = 1}) async {
|
||||
VeilidTableDB tableDB = await Veilid.instance.openTableDB(name, columnCount);
|
||||
try {
|
||||
return await callback(tableDB);
|
||||
} finally {
|
||||
tableDB.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<T> transactionScope<T>(
|
||||
VeilidTableDB tdb,
|
||||
Future<T> Function(VeilidTableDBTransaction tdbt) callback,
|
||||
) async {
|
||||
VeilidTableDBTransaction tdbt = tdb.transact();
|
||||
try {
|
||||
final ret = await callback(tdbt);
|
||||
if (!tdbt.isDone()) {
|
||||
await tdbt.commit();
|
||||
}
|
||||
return ret;
|
||||
} finally {
|
||||
if (!tdbt.isDone()) {
|
||||
await tdbt.rollback();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
export 'external_stream_state.dart';
|
||||
export 'dht_record.dart';
|
||||
export 'dht_record_encryption.dart';
|
||||
export 'json_tools.dart';
|
||||
export 'phono_byte.dart';
|
||||
export 'protobuf_tools.dart';
|
||||
export 'table_db.dart';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue