mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-10-16 04:21:00 -04:00
Switch to crypto to typed keys everywhere
This commit is contained in:
parent
88f69ce237
commit
848da0ae4e
180 changed files with 8532 additions and 8488 deletions
|
@ -50,9 +50,11 @@ Future<void> testDeleteDHTRecordNonexistent() async {
|
|||
Future<void> testCreateDeleteDHTRecordSimple() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 1));
|
||||
await rc.closeDHTRecord(rec.key);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 1));
|
||||
await rc.closeDHTRecord(rec.key);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -61,8 +63,10 @@ Future<void> testCreateDeleteDHTRecordSimple() async {
|
|||
Future<void> testCreateDeleteDHTRecordNoClose() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 1));
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 1));
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -71,9 +75,11 @@ Future<void> testCreateDeleteDHTRecordNoClose() async {
|
|||
Future<void> testGetDHTValueNonexistent() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 1));
|
||||
expect(await rc.getDHTValue(rec.key, 0), isNull);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 1));
|
||||
expect(await rc.getDHTValue(rec.key, 0), isNull);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -82,21 +88,23 @@ Future<void> testGetDHTValueNonexistent() async {
|
|||
Future<void> testSetGetDHTValue() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2));
|
||||
expect(await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH')),
|
||||
isNull);
|
||||
final vd2 = await rc.getDHTValue(rec.key, 0);
|
||||
expect(vd2, isNotNull);
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 2));
|
||||
expect(await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH')),
|
||||
isNull);
|
||||
final vd2 = await rc.getDHTValue(rec.key, 0);
|
||||
expect(vd2, isNotNull);
|
||||
|
||||
final vd3 = await rc.getDHTValue(rec.key, 0, forceRefresh: true);
|
||||
expect(vd3, isNotNull);
|
||||
final vd3 = await rc.getDHTValue(rec.key, 0, forceRefresh: true);
|
||||
expect(vd3, isNotNull);
|
||||
|
||||
final vd4 = await rc.getDHTValue(rec.key, 1);
|
||||
expect(vd4, isNull);
|
||||
final vd4 = await rc.getDHTValue(rec.key, 1);
|
||||
expect(vd4, isNull);
|
||||
|
||||
expect(vd2, equals(vd3));
|
||||
expect(vd2, equals(vd3));
|
||||
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -105,26 +113,30 @@ Future<void> testSetGetDHTValue() async {
|
|||
Future<void> testSetGetDHTValueWithOwner() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final cs = await Veilid.instance.bestCryptoSystem();
|
||||
final ownerKeyPair =
|
||||
KeyPair.fromBareKeyPair(cs.kind(), await cs.generateKeyPair());
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final cs = await Veilid.instance.getCryptoSystem(kind);
|
||||
|
||||
final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2),
|
||||
owner: ownerKeyPair);
|
||||
expect(await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH')),
|
||||
isNull);
|
||||
final vd2 = await rc.getDHTValue(rec.key, 0);
|
||||
expect(vd2, isNotNull);
|
||||
final ownerKeyPair = await cs.generateKeyPair();
|
||||
|
||||
final vd3 = await rc.getDHTValue(rec.key, 0, forceRefresh: true);
|
||||
expect(vd3, isNotNull);
|
||||
final rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 2),
|
||||
owner: ownerKeyPair);
|
||||
expect(
|
||||
await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH'),
|
||||
options: const SetDHTValueOptions(allowOffline: false)),
|
||||
isNull);
|
||||
final vd2 = await rc.getDHTValue(rec.key, 0);
|
||||
expect(vd2, isNotNull);
|
||||
|
||||
final vd4 = await rc.getDHTValue(rec.key, 1);
|
||||
expect(vd4, isNull);
|
||||
final vd3 = await rc.getDHTValue(rec.key, 0, forceRefresh: true);
|
||||
expect(vd3, isNotNull);
|
||||
|
||||
expect(vd2, equals(vd3));
|
||||
final vd4 = await rc.getDHTValue(rec.key, 1);
|
||||
expect(vd4, isNull);
|
||||
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
expect(vd2, equals(vd3));
|
||||
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -133,24 +145,23 @@ Future<void> testSetGetDHTValueWithOwner() async {
|
|||
Future<void> testCreateDHTRecordWithDeterministicKey() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final bestCryptoSystem = await Veilid.instance.bestCryptoSystem();
|
||||
final bestCryptoKind = bestCryptoSystem.kind();
|
||||
final ownerKeyPair = await bestCryptoSystem.generateKeyPair();
|
||||
final owner = ownerKeyPair.key;
|
||||
final secret = ownerKeyPair.secret;
|
||||
const schema = DHTSchema.dflt(oCnt: 1);
|
||||
final dhtRecordKey = await rc.getDHTRecordKey(
|
||||
schema, PublicKey(kind: bestCryptoKind, value: owner));
|
||||
final dhtRecord = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 1),
|
||||
owner: KeyPair.fromBareKeyPair(bestCryptoKind, ownerKeyPair),
|
||||
kind: bestCryptoKind);
|
||||
expect(dhtRecord.key, equals(dhtRecordKey));
|
||||
expect(
|
||||
dhtRecord.owner, equals(PublicKey(kind: bestCryptoKind, value: owner)));
|
||||
expect(dhtRecord.ownerSecret, equals(secret));
|
||||
expect(dhtRecord.schema, equals(schema));
|
||||
await rc.closeDHTRecord(dhtRecord.key);
|
||||
await rc.deleteDHTRecord(dhtRecord.key);
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final cs = await Veilid.instance.getCryptoSystem(kind);
|
||||
final ownerKeyPair = await cs.generateKeyPair();
|
||||
final owner = ownerKeyPair.key;
|
||||
final secret = ownerKeyPair.secret;
|
||||
const schema = DHTSchema.dflt(oCnt: 1);
|
||||
final dhtRecordKey = await rc.getDHTRecordKey(schema, owner);
|
||||
final dhtRecord = await rc.createDHTRecord(
|
||||
kind, const DHTSchema.dflt(oCnt: 1),
|
||||
owner: ownerKeyPair);
|
||||
expect(dhtRecord.key, equals(dhtRecordKey));
|
||||
expect(dhtRecord.owner, equals(owner));
|
||||
expect(dhtRecord.ownerSecret, equals(secret));
|
||||
expect(dhtRecord.schema, equals(schema));
|
||||
await rc.closeDHTRecord(dhtRecord.key);
|
||||
await rc.deleteDHTRecord(dhtRecord.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -159,135 +170,138 @@ Future<void> testCreateDHTRecordWithDeterministicKey() async {
|
|||
Future<void> testOpenWriterDHTValue() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
var rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2));
|
||||
final key = rec.key;
|
||||
final owner = rec.owner;
|
||||
final secret = rec.ownerSecret!;
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final cs = await Veilid.instance.getCryptoSystem(kind);
|
||||
|
||||
final cs = await Veilid.instance.getCryptoSystem(rec.key.kind);
|
||||
expect(await cs.validateKeyPair(owner.value, secret), isTrue);
|
||||
final otherKeyPair =
|
||||
KeyPair.fromBareKeyPair(cs.kind(), await cs.generateKeyPair());
|
||||
var rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 2));
|
||||
final key = rec.key;
|
||||
final owner = rec.owner;
|
||||
final secret = rec.ownerSecret!;
|
||||
|
||||
final va = utf8.encode('Qwertyuiop Asdfghjkl Zxcvbnm');
|
||||
final vb = utf8.encode('1234567890');
|
||||
final vc = utf8.encode(r'!@#$%^&*()');
|
||||
expect(await cs.validateKeyPair(owner, secret), isTrue);
|
||||
final otherKeyPair = await cs.generateKeyPair();
|
||||
|
||||
// Test subkey writes
|
||||
expect(await rc.setDHTValue(key, 1, va), isNull);
|
||||
final va = utf8.encode('Qwertyuiop Asdfghjkl Zxcvbnm');
|
||||
final vb = utf8.encode('1234567890');
|
||||
final vc = utf8.encode(r'!@#$%^&*()');
|
||||
|
||||
var vdtemp = await rc.getDHTValue(key, 1);
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(va));
|
||||
expect(vdtemp.seq, equals(0));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
// Test subkey writes
|
||||
expect(await rc.setDHTValue(key, 1, va), isNull);
|
||||
|
||||
expect(await rc.getDHTValue(key, 0), isNull);
|
||||
var vdtemp = await rc.getDHTValue(key, 1);
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(va));
|
||||
expect(vdtemp.seq, equals(0));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
|
||||
expect(await rc.setDHTValue(key, 0, vb), isNull);
|
||||
expect(await rc.getDHTValue(key, 0), isNull);
|
||||
|
||||
expect(
|
||||
await rc.getDHTValue(key, 0, forceRefresh: true),
|
||||
equals(ValueData(
|
||||
data: vb,
|
||||
seq: 0,
|
||||
writer: owner,
|
||||
)));
|
||||
expect(await rc.setDHTValue(key, 0, vb), isNull);
|
||||
|
||||
expect(
|
||||
await rc.getDHTValue(key, 1, forceRefresh: true),
|
||||
equals(ValueData(
|
||||
data: va,
|
||||
seq: 0,
|
||||
writer: owner,
|
||||
)));
|
||||
expect(
|
||||
await rc.getDHTValue(key, 0, forceRefresh: true),
|
||||
equals(ValueData(
|
||||
data: vb,
|
||||
seq: 0,
|
||||
writer: owner,
|
||||
)));
|
||||
|
||||
// Equal value should not trigger sequence number update
|
||||
expect(await rc.setDHTValue(key, 1, va), isNull);
|
||||
expect(
|
||||
await rc.getDHTValue(key, 1, forceRefresh: true),
|
||||
equals(ValueData(
|
||||
data: va,
|
||||
seq: 0,
|
||||
writer: owner,
|
||||
)));
|
||||
|
||||
// Different value should trigger sequence number update
|
||||
expect(await rc.setDHTValue(key, 1, vb), isNull);
|
||||
// Equal value should not trigger sequence number update
|
||||
expect(await rc.setDHTValue(key, 1, va), isNull);
|
||||
|
||||
await settle(rc, key, 0);
|
||||
await settle(rc, key, 1);
|
||||
// Different value should trigger sequence number update
|
||||
expect(await rc.setDHTValue(key, 1, vb), isNull);
|
||||
|
||||
// Now that we initialized some subkeys
|
||||
// and verified they stored correctly
|
||||
// Delete things locally and reopen and see if we can write
|
||||
// with the same writer key
|
||||
//
|
||||
await settle(rc, key, 0);
|
||||
await settle(rc, key, 1);
|
||||
|
||||
await rc.closeDHTRecord(key);
|
||||
await rc.deleteDHTRecord(key);
|
||||
// Now that we initialized some subkeys
|
||||
// and verified they stored correctly
|
||||
// Delete things locally and reopen and see if we can write
|
||||
// with the same writer key
|
||||
//
|
||||
|
||||
rec = await rc.openDHTRecord(key,
|
||||
writer: KeyPair.fromPublicAndBareSecret(owner, secret));
|
||||
expect(rec, isNotNull);
|
||||
expect(rec.key, equals(key));
|
||||
expect(rec.owner, equals(owner));
|
||||
expect(rec.ownerSecret, equals(secret));
|
||||
expect(rec.schema, isA<DHTSchemaDFLT>());
|
||||
expect(rec.schema.oCnt, equals(2));
|
||||
await rc.closeDHTRecord(key);
|
||||
await rc.deleteDHTRecord(key);
|
||||
|
||||
// Verify subkey 1 can be set before it is get but newer is available online
|
||||
vdtemp = await rc.setDHTValue(key, 1, vc);
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(vb));
|
||||
expect(vdtemp.seq, equals(1));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
rec = await rc.openDHTRecord(key,
|
||||
writer: KeyPair(key: owner, secret: secret));
|
||||
expect(rec, isNotNull);
|
||||
expect(rec.key, equals(key));
|
||||
expect(rec.owner, equals(owner));
|
||||
expect(rec.ownerSecret, equals(secret));
|
||||
expect(rec.schema, isA<DHTSchemaDFLT>());
|
||||
expect(rec.schema.oCnt, equals(2));
|
||||
|
||||
// Verify subkey 1 can be set a second time
|
||||
// and it updates because seq is newer
|
||||
expect(await rc.setDHTValue(key, 1, vc), isNull);
|
||||
// Verify subkey 1 can be set before it is get but newer is available online
|
||||
vdtemp = await rc.setDHTValue(key, 1, vc);
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(vb));
|
||||
expect(vdtemp.seq, equals(1));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
|
||||
// Verify the network got the subkey update with a refresh check
|
||||
vdtemp = await rc.getDHTValue(key, 1, forceRefresh: true);
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(vc));
|
||||
expect(vdtemp.seq, equals(2));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
// Verify subkey 1 can be set a second time
|
||||
// and it updates because seq is newer
|
||||
expect(await rc.setDHTValue(key, 1, vc), isNull);
|
||||
|
||||
// Delete things locally and reopen and see if we can write
|
||||
// with a different writer key (should fail)
|
||||
await rc.closeDHTRecord(key);
|
||||
await rc.deleteDHTRecord(key);
|
||||
// Verify the network got the subkey update with a refresh check
|
||||
vdtemp = await rc.getDHTValue(key, 1, forceRefresh: true);
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(vc));
|
||||
expect(vdtemp.seq, equals(2));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
|
||||
rec = await rc.openDHTRecord(key, writer: otherKeyPair);
|
||||
expect(rec, isNotNull);
|
||||
expect(rec.key, equals(key));
|
||||
expect(rec.owner, equals(owner));
|
||||
expect(rec.ownerSecret, isNull);
|
||||
expect(rec.schema, isA<DHTSchemaDFLT>());
|
||||
expect(rec.schema.oCnt, equals(2));
|
||||
// Delete things locally and reopen and see if we can write
|
||||
// with a different writer key (should fail)
|
||||
await rc.closeDHTRecord(key);
|
||||
await rc.deleteDHTRecord(key);
|
||||
|
||||
// Verify subkey 1 can NOT be set because we have the wrong writer
|
||||
await expectLater(() async => rc.setDHTValue(key, 1, va),
|
||||
throwsA(isA<VeilidAPIException>()));
|
||||
rec = await rc.openDHTRecord(key, writer: otherKeyPair);
|
||||
expect(rec, isNotNull);
|
||||
expect(rec.key, equals(key));
|
||||
expect(rec.owner, equals(owner));
|
||||
expect(rec.ownerSecret, isNull);
|
||||
expect(rec.schema, isA<DHTSchemaDFLT>());
|
||||
expect(rec.schema.oCnt, equals(2));
|
||||
|
||||
// Verify subkey 0 can NOT be set because we have the wrong writer
|
||||
await expectLater(() async => rc.setDHTValue(key, 0, va),
|
||||
throwsA(isA<VeilidAPIException>()));
|
||||
// Verify subkey 1 can NOT be set because we have the wrong writer
|
||||
await expectLater(() async => rc.setDHTValue(key, 1, va),
|
||||
throwsA(isA<VeilidAPIException>()));
|
||||
|
||||
// Verify subkey 0 can be set because override with the right writer
|
||||
// Should have prior sequence number as its returned value because it
|
||||
// exists online at seq 0
|
||||
vdtemp = await rc.setDHTValue(key, 0, va,
|
||||
options: SetDHTValueOptions(
|
||||
writer: KeyPair.fromPublicAndBareSecret(owner, secret)));
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(vb));
|
||||
expect(vdtemp.seq, equals(0));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
// Verify subkey 0 can NOT be set because we have the wrong writer
|
||||
await expectLater(() async => rc.setDHTValue(key, 0, va),
|
||||
throwsA(isA<VeilidAPIException>()));
|
||||
|
||||
// Should update the second time to seq 1
|
||||
vdtemp = await rc.setDHTValue(key, 0, va,
|
||||
options: SetDHTValueOptions(
|
||||
writer: KeyPair.fromPublicAndBareSecret(owner, secret)));
|
||||
expect(vdtemp, isNull);
|
||||
// Verify subkey 0 can be set because override with the right writer
|
||||
// Should have prior sequence number as its returned value because it
|
||||
// exists online at seq 0
|
||||
vdtemp = await rc.setDHTValue(key, 0, va,
|
||||
options:
|
||||
SetDHTValueOptions(writer: KeyPair(key: owner, secret: secret)));
|
||||
expect(vdtemp, isNotNull);
|
||||
expect(vdtemp!.data, equals(vb));
|
||||
expect(vdtemp.seq, equals(0));
|
||||
expect(vdtemp.writer, equals(owner));
|
||||
|
||||
// Clean up
|
||||
await rc.closeDHTRecord(key);
|
||||
await rc.deleteDHTRecord(key);
|
||||
// Should update the second time to seq 1
|
||||
vdtemp = await rc.setDHTValue(key, 0, va,
|
||||
options: SetDHTValueOptions(
|
||||
writer: KeyPair(key: owner, secret: secret),
|
||||
allowOffline: false));
|
||||
expect(vdtemp, isNull);
|
||||
|
||||
// Clean up
|
||||
await rc.closeDHTRecord(key);
|
||||
await rc.deleteDHTRecord(key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
@ -351,128 +365,133 @@ Future<void> testWatchDHTValues(Stream<VeilidUpdate> updateStream) async {
|
|||
final rcSet = await Veilid.instance.routingContext();
|
||||
final rcWatch = await Veilid.instance.safeRoutingContext();
|
||||
try {
|
||||
// Make a DHT record
|
||||
var rec = await rcWatch.createDHTRecord(const DHTSchema.dflt(oCnt: 10));
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
// Make a DHT record
|
||||
var rec =
|
||||
await rcWatch.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 10));
|
||||
|
||||
// Set some subkey we care about
|
||||
expect(
|
||||
await rcWatch.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH BLAH')),
|
||||
isNull);
|
||||
|
||||
// Wait for set to settle
|
||||
await settle(rcWatch, rec.key, 3);
|
||||
|
||||
// Make a watch on that subkey
|
||||
expect(await rcWatch.watchDHTValues(rec.key),
|
||||
isNot(equals(Timestamp.zero())));
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair());
|
||||
|
||||
// Now we should NOT get an update because the update
|
||||
// is the same as our local copy
|
||||
final update1 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set the subkey and trigger an update
|
||||
expect(await rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH')),
|
||||
// Set some subkey we care about
|
||||
expect(
|
||||
await rcWatch.setDHTValue(
|
||||
rec.key, 3, utf8.encode('BLAH BLAH BLAH')),
|
||||
isNull);
|
||||
|
||||
// Wait for set to settle
|
||||
await settle(rcSet, rec.key, 3);
|
||||
});
|
||||
if (update1 != null) {
|
||||
fail('should not have a change');
|
||||
}
|
||||
await settle(rcWatch, rec.key, 3);
|
||||
|
||||
// Wait for the update
|
||||
final update2 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set a subkey and trigger an update
|
||||
// Make a watch on that subkey
|
||||
expect(await rcWatch.watchDHTValues(rec.key),
|
||||
isNot(equals(Timestamp.zero())));
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair);
|
||||
|
||||
// Now we should NOT get an update because the update
|
||||
// is the same as our local copy
|
||||
final update1 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set the subkey and trigger an update
|
||||
expect(await rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH')),
|
||||
isNull);
|
||||
|
||||
// Wait for set to settle
|
||||
await settle(rcSet, rec.key, 3);
|
||||
});
|
||||
if (update1 != null) {
|
||||
fail('should not have a change');
|
||||
}
|
||||
|
||||
// Wait for the update
|
||||
final update2 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set a subkey and trigger an update
|
||||
expect(
|
||||
await rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH')), isNull);
|
||||
|
||||
await settle(rcSet, rec.key, 3);
|
||||
});
|
||||
if (update2 == null) {
|
||||
fail('should have a change');
|
||||
}
|
||||
|
||||
// Verify the update
|
||||
expect(update2.key, equals(rec.key));
|
||||
expect(update2.count, equals(0xFFFFFFFD));
|
||||
expect(update2.subkeys, equals([ValueSubkeyRange.single(3)]));
|
||||
expect(update2.value, isNull);
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcWatch.openDHTRecord(rec.key, writer: rec.ownerKeyPair);
|
||||
|
||||
// Cancel some subkeys we don't care about
|
||||
expect(
|
||||
await rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH')), isNull);
|
||||
await rcWatch.cancelDHTWatch(rec.key,
|
||||
subkeys: [ValueSubkeyRange.make(0, 2)]),
|
||||
isTrue);
|
||||
|
||||
await settle(rcSet, rec.key, 3);
|
||||
});
|
||||
if (update2 == null) {
|
||||
fail('should have a change');
|
||||
}
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair);
|
||||
|
||||
// Verify the update
|
||||
expect(update2.key, equals(rec.key));
|
||||
expect(update2.count, equals(0xFFFFFFFD));
|
||||
expect(update2.subkeys, equals([ValueSubkeyRange.single(3)]));
|
||||
expect(update2.value, isNull);
|
||||
// Wait for the update
|
||||
final update3 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set multiple subkeys and trigger an update on one of them
|
||||
expect(
|
||||
await [
|
||||
rcSet.setDHTValue(rec.key, 3, utf8.encode('BLART')),
|
||||
rcSet.setDHTValue(rec.key, 1, utf8.encode('BZORT BZORT'))
|
||||
].wait,
|
||||
equals([null, null]));
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcWatch.openDHTRecord(rec.key, writer: rec.ownerKeyPair());
|
||||
await settle(rcSet, rec.key, 3);
|
||||
await settle(rcSet, rec.key, 1);
|
||||
});
|
||||
if (update3 == null) {
|
||||
fail('should have a change');
|
||||
}
|
||||
|
||||
// Cancel some subkeys we don't care about
|
||||
expect(
|
||||
await rcWatch
|
||||
.cancelDHTWatch(rec.key, subkeys: [ValueSubkeyRange.make(0, 2)]),
|
||||
isTrue);
|
||||
// Verify the update came back but we don't get a new value because the
|
||||
// sequence number is the same
|
||||
expect(update3.key, equals(rec.key));
|
||||
expect(update3.count, equals(0xFFFFFFFC));
|
||||
expect(update3.subkeys, equals([ValueSubkeyRange.single(3)]));
|
||||
expect(update3.value, isNull);
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair());
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcWatch.openDHTRecord(rec.key, writer: rec.ownerKeyPair);
|
||||
|
||||
// Wait for the update
|
||||
final update3 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set multiple subkeys and trigger an update on one of them
|
||||
// Now cancel the update
|
||||
expect(
|
||||
await [
|
||||
rcSet.setDHTValue(rec.key, 3, utf8.encode('BLART')),
|
||||
rcSet.setDHTValue(rec.key, 1, utf8.encode('BZORT BZORT'))
|
||||
].wait,
|
||||
equals([null, null]));
|
||||
await rcWatch.cancelDHTWatch(rec.key,
|
||||
subkeys: [ValueSubkeyRange.make(3, 9)]),
|
||||
isFalse);
|
||||
|
||||
await settle(rcSet, rec.key, 3);
|
||||
await settle(rcSet, rec.key, 1);
|
||||
});
|
||||
if (update3 == null) {
|
||||
fail('should have a change');
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair);
|
||||
|
||||
// Wait for the update
|
||||
final update4 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set multiple subkeys that should not trigger an update
|
||||
expect(
|
||||
await [
|
||||
rcSet.setDHTValue(
|
||||
rec.key, 3, utf8.encode('BLAH BLAH BLAH BLAH')),
|
||||
rcSet.setDHTValue(rec.key, 5, utf8.encode('BZORT BZORT BZORT'))
|
||||
].wait,
|
||||
equals([null, null]));
|
||||
|
||||
await settle(rcSet, rec.key, 3);
|
||||
await settle(rcSet, rec.key, 5);
|
||||
});
|
||||
if (update4 != null) {
|
||||
fail('should not have a change');
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await rcSet.closeDHTRecord(rec.key);
|
||||
await rcSet.deleteDHTRecord(rec.key);
|
||||
}
|
||||
|
||||
// Verify the update came back but we don't get a new value because the
|
||||
// sequence number is the same
|
||||
expect(update3.key, equals(rec.key));
|
||||
expect(update3.count, equals(0xFFFFFFFC));
|
||||
expect(update3.subkeys, equals([ValueSubkeyRange.single(3)]));
|
||||
expect(update3.value, isNull);
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcWatch.openDHTRecord(rec.key, writer: rec.ownerKeyPair());
|
||||
|
||||
// Now cancel the update
|
||||
expect(
|
||||
await rcWatch
|
||||
.cancelDHTWatch(rec.key, subkeys: [ValueSubkeyRange.make(3, 9)]),
|
||||
isFalse);
|
||||
|
||||
// Reopen without closing to change routing context and not lose watch
|
||||
rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair());
|
||||
|
||||
// Wait for the update
|
||||
final update4 = await waitForValueChange(
|
||||
valueChangeQueue.stream, const Duration(seconds: 10), () async {
|
||||
// Now set multiple subkeys that should not trigger an update
|
||||
expect(
|
||||
await [
|
||||
rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH BLAH BLAH')),
|
||||
rcSet.setDHTValue(rec.key, 5, utf8.encode('BZORT BZORT BZORT'))
|
||||
].wait,
|
||||
equals([null, null]));
|
||||
|
||||
await settle(rcSet, rec.key, 3);
|
||||
await settle(rcSet, rec.key, 5);
|
||||
});
|
||||
if (update4 != null) {
|
||||
fail('should not have a change');
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await rcSet.closeDHTRecord(rec.key);
|
||||
await rcSet.deleteDHTRecord(rec.key);
|
||||
} finally {
|
||||
rcWatch.close();
|
||||
rcSet.close();
|
||||
|
@ -486,26 +505,28 @@ Future<void> testWatchDHTValues(Stream<VeilidUpdate> updateStream) async {
|
|||
Future<void> testInspectDHTRecord() async {
|
||||
final rc = await Veilid.instance.routingContext();
|
||||
try {
|
||||
final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2));
|
||||
for (final kind in Veilid.instance.validCryptoKinds()) {
|
||||
final rec = await rc.createDHTRecord(kind, const DHTSchema.dflt(oCnt: 2));
|
||||
|
||||
expect(await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH')),
|
||||
isNull);
|
||||
expect(
|
||||
await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH'),
|
||||
options: const SetDHTValueOptions(allowOffline: false)),
|
||||
isNull);
|
||||
|
||||
await settle(rc, rec.key, 0);
|
||||
final rr = await rc.inspectDHTRecord(rec.key);
|
||||
expect(rr.subkeys, equals([ValueSubkeyRange.make(0, 1)]));
|
||||
expect(rr.localSeqs, equals([0, null]));
|
||||
expect(rr.networkSeqs, equals([null, null]));
|
||||
|
||||
final rr = await rc.inspectDHTRecord(rec.key);
|
||||
expect(rr.subkeys, equals([ValueSubkeyRange.make(0, 1)]));
|
||||
expect(rr.localSeqs, equals([0, null]));
|
||||
expect(rr.networkSeqs, equals([null, null]));
|
||||
final rr2 =
|
||||
await rc.inspectDHTRecord(rec.key, scope: DHTReportScope.syncGet);
|
||||
expect(rr2.subkeys, equals([ValueSubkeyRange.make(0, 1)]));
|
||||
expect(rr2.localSeqs, equals([0, null]));
|
||||
expect(rr2.networkSeqs, equals([0, null]));
|
||||
|
||||
final rr2 =
|
||||
await rc.inspectDHTRecord(rec.key, scope: DHTReportScope.syncGet);
|
||||
expect(rr2.subkeys, equals([ValueSubkeyRange.make(0, 1)]));
|
||||
expect(rr2.localSeqs, equals([0, null]));
|
||||
expect(rr2.networkSeqs, equals([0, null]));
|
||||
|
||||
await rc.closeDHTRecord(rec.key);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
await rc.closeDHTRecord(rec.key);
|
||||
await rc.deleteDHTRecord(rec.key);
|
||||
}
|
||||
} finally {
|
||||
rc.close();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue