@dxos/echo-db 2.33.5-dev.8e942d13 → 2.33.5-dev.97a81dd0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/api/selection/queries.d.ts.map +1 -1
- package/dist/src/api/selection/queries.js +13 -17
- package/dist/src/api/selection/queries.js.map +1 -1
- package/dist/src/api/selection/selection.d.ts.map +1 -1
- package/dist/src/api/selection/selection.js +1 -3
- package/dist/src/api/selection/selection.js.map +1 -1
- package/dist/src/api/selection/selection.test.js +4 -12
- package/dist/src/api/selection/selection.test.js.map +1 -1
- package/dist/src/database/item-demuxer.d.ts +1 -1
- package/dist/src/database/item-demuxer.d.ts.map +1 -1
- package/dist/src/database/item-demuxer.js +3 -5
- package/dist/src/database/item-demuxer.js.map +1 -1
- package/dist/src/database/item-manager.js +2 -2
- package/dist/src/database/item-manager.js.map +1 -1
- package/dist/src/database/testing.js +1 -1
- package/dist/src/database/testing.js.map +1 -1
- package/dist/src/halo/halo-factory.d.ts.map +1 -1
- package/dist/src/halo/halo-factory.js +5 -11
- package/dist/src/halo/halo-factory.js.map +1 -1
- package/dist/src/halo/halo-party.d.ts +3 -3
- package/dist/src/halo/halo-party.d.ts.map +1 -1
- package/dist/src/halo/halo-party.js +6 -4
- package/dist/src/halo/halo-party.js.map +1 -1
- package/dist/src/halo/identity.js +2 -2
- package/dist/src/halo/identity.js.map +1 -1
- package/dist/src/halo/party-opener.d.ts +1 -1
- package/dist/src/halo/party-opener.d.ts.map +1 -1
- package/dist/src/halo/party-opener.js +2 -2
- package/dist/src/halo/party-opener.js.map +1 -1
- package/dist/src/halo/preferences.d.ts.map +1 -1
- package/dist/src/halo/preferences.js +7 -10
- package/dist/src/halo/preferences.js.map +1 -1
- package/dist/src/invitations/greeting-protocol-provider.d.ts.map +1 -1
- package/dist/src/invitations/greeting-protocol-provider.js +5 -9
- package/dist/src/invitations/greeting-protocol-provider.js.map +1 -1
- package/dist/src/invitations/greeting-responder.d.ts +2 -2
- package/dist/src/invitations/greeting-responder.d.ts.map +1 -1
- package/dist/src/invitations/greeting-responder.js +8 -12
- package/dist/src/invitations/greeting-responder.js.map +1 -1
- package/dist/src/invitations/invitation-factory.d.ts +2 -2
- package/dist/src/invitations/invitation-factory.d.ts.map +1 -1
- package/dist/src/invitations/invitation-factory.js.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.d.ts.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.js +5 -7
- package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
- package/dist/src/parties/data-party.d.ts +7 -5
- package/dist/src/parties/data-party.d.ts.map +1 -1
- package/dist/src/parties/data-party.js +12 -9
- package/dist/src/parties/data-party.js.map +1 -1
- package/dist/src/parties/data-party.test.js +12 -12
- package/dist/src/parties/data-party.test.js.map +1 -1
- package/dist/src/parties/party-factory.d.ts +0 -6
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +17 -45
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-manager.d.ts.map +1 -1
- package/dist/src/parties/party-manager.js +2 -1
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/pipeline/message-selector.d.ts +2 -2
- package/dist/src/pipeline/message-selector.d.ts.map +1 -1
- package/dist/src/pipeline/message-selector.js +29 -29
- package/dist/src/pipeline/message-selector.js.map +1 -1
- package/dist/src/pipeline/party-core.d.ts +3 -2
- package/dist/src/pipeline/party-core.d.ts.map +1 -1
- package/dist/src/pipeline/party-core.js +5 -0
- package/dist/src/pipeline/party-core.js.map +1 -1
- package/dist/src/pipeline/party-core.test.js +8 -7
- package/dist/src/pipeline/party-core.test.js.map +1 -1
- package/dist/src/pipeline/party-processor.d.ts +23 -5
- package/dist/src/pipeline/party-processor.d.ts.map +1 -1
- package/dist/src/pipeline/party-processor.js.map +1 -1
- package/dist/src/pipeline/pipeline.d.ts +2 -4
- package/dist/src/pipeline/pipeline.d.ts.map +1 -1
- package/dist/src/pipeline/pipeline.js +0 -3
- package/dist/src/pipeline/pipeline.js.map +1 -1
- package/dist/src/protocol/auth-plugin.d.ts +1 -1
- package/dist/src/protocol/auth-plugin.d.ts.map +1 -1
- package/dist/src/protocol/auth-plugin.js +1 -3
- package/dist/src/protocol/auth-plugin.js.map +1 -1
- package/dist/src/protocol/authenticator.d.ts +2 -2
- package/dist/src/protocol/authenticator.d.ts.map +1 -1
- package/dist/src/protocol/authenticator.js +12 -16
- package/dist/src/protocol/authenticator.js.map +1 -1
- package/dist/src/protocol/halo-recovery-plugin.d.ts +1 -1
- package/dist/src/protocol/halo-recovery-plugin.d.ts.map +1 -1
- package/dist/src/protocol/halo-recovery-plugin.js +1 -3
- package/dist/src/protocol/halo-recovery-plugin.js.map +1 -1
- package/dist/src/protocol/identity-credentials.d.ts +2 -2
- package/dist/src/protocol/identity-credentials.d.ts.map +1 -1
- package/dist/src/protocol/identity-credentials.js +4 -4
- package/dist/src/protocol/identity-credentials.js.map +1 -1
- package/dist/src/protocol/offline-invitation-plugin.d.ts +1 -1
- package/dist/src/protocol/offline-invitation-plugin.d.ts.map +1 -1
- package/dist/src/protocol/offline-invitation-plugin.js +1 -3
- package/dist/src/protocol/offline-invitation-plugin.js.map +1 -1
- package/dist/src/protocol/party-protocol-factory.d.ts +1 -14
- package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
- package/dist/src/protocol/party-protocol-factory.js +2 -55
- package/dist/src/protocol/party-protocol-factory.js.map +1 -1
- package/dist/src/protocol/replicator-plugin.d.ts +7 -0
- package/dist/src/protocol/replicator-plugin.d.ts.map +1 -0
- package/dist/src/protocol/replicator-plugin.js +36 -0
- package/dist/src/protocol/replicator-plugin.js.map +1 -0
- package/dist/src/snapshots/snapshot-generator.d.ts +1 -1
- package/dist/src/snapshots/snapshot-generator.d.ts.map +1 -1
- package/dist/src/snapshots/snapshot-generator.js +13 -15
- package/dist/src/snapshots/snapshot-generator.js.map +1 -1
- package/dist/src/testing/benchmark.test.d.ts +2 -0
- package/dist/src/testing/benchmark.test.d.ts.map +1 -0
- package/dist/src/testing/benchmark.test.js +25 -0
- package/dist/src/testing/benchmark.test.js.map +1 -0
- package/dist/src/testing/testing-factories.js +2 -2
- package/dist/src/testing/testing-factories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -18
- package/src/api/selection/queries.ts +14 -18
- package/src/api/selection/selection.test.ts +4 -12
- package/src/api/selection/selection.ts +1 -7
- package/src/database/item-demuxer.ts +2 -4
- package/src/database/item-manager.ts +2 -2
- package/src/database/testing.ts +1 -1
- package/src/halo/halo-factory.ts +6 -18
- package/src/halo/halo-party.ts +8 -7
- package/src/halo/identity.ts +2 -2
- package/src/halo/party-opener.ts +2 -2
- package/src/halo/preferences.ts +7 -10
- package/src/invitations/greeting-protocol-provider.ts +5 -9
- package/src/invitations/greeting-responder.ts +10 -14
- package/src/invitations/invitation-factory.ts +2 -2
- package/src/invitations/offline-invitation-claimer.ts +5 -7
- package/src/parties/data-party.test.ts +12 -12
- package/src/parties/data-party.ts +17 -13
- package/src/parties/party-factory.ts +23 -69
- package/src/parties/party-manager.ts +2 -1
- package/src/pipeline/message-selector.ts +30 -34
- package/src/pipeline/party-core.test.ts +10 -13
- package/src/pipeline/party-core.ts +7 -2
- package/src/pipeline/party-processor.ts +26 -2
- package/src/pipeline/pipeline.ts +2 -6
- package/src/protocol/auth-plugin.ts +1 -3
- package/src/protocol/authenticator.ts +27 -31
- package/src/protocol/halo-recovery-plugin.ts +4 -6
- package/src/protocol/identity-credentials.ts +4 -4
- package/src/protocol/offline-invitation-plugin.ts +4 -6
- package/src/protocol/party-protocol-factory.ts +3 -56
- package/src/protocol/replicator-plugin.ts +37 -0
- package/src/snapshots/snapshot-generator.ts +12 -16
- package/src/testing/benchmark.test.ts +30 -0
- package/src/testing/testing-factories.ts +2 -2
|
@@ -60,10 +60,10 @@ export class PartyFactory {
|
|
|
60
60
|
// Connect the pipeline.
|
|
61
61
|
await party.open();
|
|
62
62
|
|
|
63
|
-
const writableFeed = await party.
|
|
63
|
+
const writableFeed = await party.getWriteFeed();
|
|
64
64
|
|
|
65
65
|
// PartyGenesis (self-signed by Party).
|
|
66
|
-
await party.
|
|
66
|
+
await party.writeCredentialsMessage(createPartyGenesisMessage(
|
|
67
67
|
identity.keyring,
|
|
68
68
|
partyKey,
|
|
69
69
|
writableFeed.key,
|
|
@@ -71,7 +71,7 @@ export class PartyFactory {
|
|
|
71
71
|
);
|
|
72
72
|
|
|
73
73
|
// KeyAdmit (IdentityGenesis in an Envelope signed by Party).
|
|
74
|
-
await party.
|
|
74
|
+
await party.writeCredentialsMessage(createEnvelopeMessage(
|
|
75
75
|
identity.keyring,
|
|
76
76
|
partyKey.publicKey,
|
|
77
77
|
wrapMessage(identity.identityGenesis),
|
|
@@ -80,7 +80,7 @@ export class PartyFactory {
|
|
|
80
80
|
|
|
81
81
|
// FeedAdmit (signed by the Device KeyChain).
|
|
82
82
|
// TODO(dmaretskyi): Is this really needed since a feed is already admitted by party genesis message.
|
|
83
|
-
await party.
|
|
83
|
+
await party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
84
84
|
identity.keyring,
|
|
85
85
|
partyKey.publicKey,
|
|
86
86
|
writableFeed.key,
|
|
@@ -89,7 +89,7 @@ export class PartyFactory {
|
|
|
89
89
|
|
|
90
90
|
// IdentityInfo in an Envelope signed by the Device KeyChain.
|
|
91
91
|
if (identity.identityInfo) {
|
|
92
|
-
await party.
|
|
92
|
+
await party.writeCredentialsMessage(createEnvelopeMessage(
|
|
93
93
|
identity.keyring,
|
|
94
94
|
partyKey.publicKey,
|
|
95
95
|
wrapMessage(identity.identityInfo),
|
|
@@ -106,50 +106,6 @@ export class PartyFactory {
|
|
|
106
106
|
return party;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
/**
|
|
110
|
-
* Constructs a party object and creates a local write feed for it.
|
|
111
|
-
* @param partyKey
|
|
112
|
-
* @param hints
|
|
113
|
-
*/
|
|
114
|
-
async addParty (partyKey: PartyKey, hints: KeyHint[] = []) {
|
|
115
|
-
const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
|
|
116
|
-
|
|
117
|
-
/*
|
|
118
|
-
* TODO(telackey): We shouldn't have to add our key here, it should be in the hints, but our hint
|
|
119
|
-
* mechanism is broken by not waiting on the messages to be processed before returning.
|
|
120
|
-
*/
|
|
121
|
-
|
|
122
|
-
const feedProvider = this._feedProviderFactory(partyKey);
|
|
123
|
-
const { feed } = await feedProvider.createOrOpenWritableFeed();
|
|
124
|
-
const feedKeyPair = identity.keyring.getKey(feed.key);
|
|
125
|
-
assert(feedKeyPair, 'Keypair for writable feed not found.');
|
|
126
|
-
const party = new DataParty(
|
|
127
|
-
partyKey,
|
|
128
|
-
this._modelFactory,
|
|
129
|
-
this._snapshotStore,
|
|
130
|
-
feedProvider,
|
|
131
|
-
identity.createCredentialsSigner(),
|
|
132
|
-
identity.preferences,
|
|
133
|
-
this._networkManager,
|
|
134
|
-
hints,
|
|
135
|
-
undefined,
|
|
136
|
-
this._options
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
await party.open();
|
|
140
|
-
const isHalo = identity.identityKey.publicKey.equals(partyKey);
|
|
141
|
-
const signingKey = isHalo ? identity.deviceKey : identity.deviceKeyChain;
|
|
142
|
-
assert(signingKey, 'No device key or keychain.');
|
|
143
|
-
// Write the Feed genesis message.
|
|
144
|
-
await party.processor.writeHaloMessage(createFeedAdmitMessage(
|
|
145
|
-
identity.keyring,
|
|
146
|
-
partyKey,
|
|
147
|
-
feedKeyPair.publicKey,
|
|
148
|
-
[signingKey]
|
|
149
|
-
));
|
|
150
|
-
return party;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
109
|
/**
|
|
154
110
|
* Constructs a party object from an existing set of feeds.
|
|
155
111
|
* @param partyKey
|
|
@@ -190,7 +146,6 @@ export class PartyFactory {
|
|
|
190
146
|
}
|
|
191
147
|
|
|
192
148
|
async joinParty (invitationDescriptor: InvitationDescriptor, secretProvider: SecretProvider): Promise<DataParty> {
|
|
193
|
-
const haloInvitation = !!invitationDescriptor.identityKey;
|
|
194
149
|
const originalInvitation = invitationDescriptor;
|
|
195
150
|
|
|
196
151
|
const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
|
|
@@ -218,19 +173,18 @@ export class PartyFactory {
|
|
|
218
173
|
|
|
219
174
|
await initiator.connect();
|
|
220
175
|
const { partyKey, hints } = await initiator.redeemInvitation(secretProvider);
|
|
221
|
-
const party = await this.
|
|
176
|
+
const party = await this.constructParty(partyKey, hints);
|
|
177
|
+
await party.open();
|
|
222
178
|
await initiator.destroy();
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
));
|
|
233
|
-
}
|
|
179
|
+
|
|
180
|
+
// Copy our signed IdentityInfo into the new Party.
|
|
181
|
+
if (identity.identityInfo) {
|
|
182
|
+
await party.writeCredentialsMessage(createEnvelopeMessage(
|
|
183
|
+
identity.keyring,
|
|
184
|
+
partyKey,
|
|
185
|
+
wrapMessage(identity.identityInfo),
|
|
186
|
+
[identity.deviceKeyChain]
|
|
187
|
+
));
|
|
234
188
|
}
|
|
235
189
|
|
|
236
190
|
return party;
|
|
@@ -247,10 +201,10 @@ export class PartyFactory {
|
|
|
247
201
|
// Connect the pipeline.
|
|
248
202
|
await party.open();
|
|
249
203
|
|
|
250
|
-
const writableFeed = await party.
|
|
204
|
+
const writableFeed = await party.getWriteFeed();
|
|
251
205
|
|
|
252
206
|
// PartyGenesis (self-signed by Party).
|
|
253
|
-
await party.
|
|
207
|
+
await party.writeCredentialsMessage(createPartyGenesisMessage(
|
|
254
208
|
identity.keyring,
|
|
255
209
|
partyKey,
|
|
256
210
|
writableFeed.key,
|
|
@@ -258,7 +212,7 @@ export class PartyFactory {
|
|
|
258
212
|
);
|
|
259
213
|
|
|
260
214
|
// KeyAdmit (IdentityGenesis in an Envelope signed by Party).
|
|
261
|
-
await party.
|
|
215
|
+
await party.writeCredentialsMessage(createEnvelopeMessage(
|
|
262
216
|
identity.keyring,
|
|
263
217
|
partyKey.publicKey,
|
|
264
218
|
wrapMessage(identity.identityGenesis),
|
|
@@ -266,7 +220,7 @@ export class PartyFactory {
|
|
|
266
220
|
));
|
|
267
221
|
|
|
268
222
|
// FeedAdmit (signed by the Device KeyChain).
|
|
269
|
-
await party.
|
|
223
|
+
await party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
270
224
|
identity.keyring,
|
|
271
225
|
partyKey.publicKey,
|
|
272
226
|
writableFeed.key,
|
|
@@ -275,7 +229,7 @@ export class PartyFactory {
|
|
|
275
229
|
|
|
276
230
|
// IdentityInfo in an Envelope signed by the Device KeyChain.
|
|
277
231
|
if (identity.identityInfo) {
|
|
278
|
-
await party.
|
|
232
|
+
await party.writeCredentialsMessage(createEnvelopeMessage(
|
|
279
233
|
identity.keyring,
|
|
280
234
|
partyKey.publicKey,
|
|
281
235
|
wrapMessage(identity.identityInfo),
|
|
@@ -285,7 +239,7 @@ export class PartyFactory {
|
|
|
285
239
|
|
|
286
240
|
// const keyAdmitMessage = snapshot.halo?.messages?.[1];
|
|
287
241
|
// assert(keyAdmitMessage);
|
|
288
|
-
// await party.
|
|
242
|
+
// await party.writeCredentialsMessage(createEnvelopeMessage(
|
|
289
243
|
// identity.signer,
|
|
290
244
|
// partyKey.publicKey,
|
|
291
245
|
// keyAdmitMessage,
|
|
@@ -293,7 +247,7 @@ export class PartyFactory {
|
|
|
293
247
|
// ));
|
|
294
248
|
|
|
295
249
|
// for(const message of snapshot.halo?.messages?.slice(2) || []) {
|
|
296
|
-
// await party.
|
|
250
|
+
// await party.writeCredentialsMessage(message);
|
|
297
251
|
// }
|
|
298
252
|
|
|
299
253
|
// Write messages to create ECHO items.
|
|
@@ -175,7 +175,8 @@ export class PartyManager {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
log(`Adding party partyKey=${partyKey.toHex()} hints=${hints.length}`);
|
|
178
|
-
const party = await this._partyFactory.
|
|
178
|
+
const party = await this._partyFactory.constructParty(partyKey, hints);
|
|
179
|
+
await party.open();
|
|
179
180
|
await this._metadataStore.addParty(party.key);
|
|
180
181
|
this._setParty(party);
|
|
181
182
|
return party;
|
|
@@ -10,7 +10,7 @@ import { PublicKey } from '@dxos/crypto';
|
|
|
10
10
|
import { MessageSelector } from '@dxos/echo-protocol';
|
|
11
11
|
|
|
12
12
|
import { TimeframeClock } from '../database';
|
|
13
|
-
import {
|
|
13
|
+
import { PartyStateProvider } from './party-processor';
|
|
14
14
|
|
|
15
15
|
const log = debug('dxos:echo-db:message-selector');
|
|
16
16
|
|
|
@@ -23,47 +23,43 @@ const log = debug('dxos:echo-db:message-selector');
|
|
|
23
23
|
* @param partyProcessor
|
|
24
24
|
* @param timeframeClock
|
|
25
25
|
*/
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const { data: { echo } } = candidates[i];
|
|
35
|
-
const feedKey = PublicKey.from(candidates[i].key);
|
|
36
|
-
if (!echo) {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
26
|
+
export const createMessageSelector = (partyProcessor: PartyStateProvider, timeframeClock: TimeframeClock): MessageSelector => candidates => {
|
|
27
|
+
// Check ECHO message candidates first since they are less expensive than HALO cancidates.
|
|
28
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
29
|
+
const { data: { echo } } = candidates[i];
|
|
30
|
+
const feedKey = PublicKey.from(candidates[i].key);
|
|
31
|
+
if (!echo) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
35
|
+
assert(echo.timeframe);
|
|
36
|
+
if (partyProcessor.isFeedAdmitted(feedKey) && !timeframeClock.hasGaps(echo.timeframe)) {
|
|
37
|
+
return i;
|
|
44
38
|
}
|
|
39
|
+
}
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
// Check HALO message candidates.
|
|
42
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
43
|
+
const { data: { halo } } = candidates[i];
|
|
44
|
+
const feedKey = PublicKey.from(candidates[i].key);
|
|
45
|
+
if (!halo) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
if (partyProcessor.isFeedAdmitted(feedKey)) {
|
|
50
|
+
return i;
|
|
51
|
+
}
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
if (partyProcessor.genesisRequired) {
|
|
54
|
+
try { // TODO(dmaretskyi): Get getPartyCredentialMessageType crashes for some reason.
|
|
59
55
|
// TODO(telackey): Add check that this is for the right Party.
|
|
60
56
|
if (getPartyCredentialMessageType(halo) === PartyCredential.Type.PARTY_GENESIS) {
|
|
61
57
|
return i;
|
|
62
58
|
}
|
|
63
|
-
}
|
|
59
|
+
} catch { }
|
|
64
60
|
}
|
|
61
|
+
}
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
63
|
+
// Not ready for this message yet.
|
|
64
|
+
log('Skipping...');
|
|
65
|
+
};
|
|
@@ -16,7 +16,8 @@ import { ObjectModel } from '@dxos/object-model';
|
|
|
16
16
|
import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
|
|
17
17
|
import { afterTest } from '@dxos/testutils';
|
|
18
18
|
|
|
19
|
-
import { MetadataStore, PartyFeedProvider
|
|
19
|
+
import { MetadataStore, PartyFeedProvider } from '../pipeline';
|
|
20
|
+
import { createReplicatorPlugin } from '../protocol/replicator-plugin';
|
|
20
21
|
import { SnapshotStore } from '../snapshots';
|
|
21
22
|
import { PartyCore } from './party-core';
|
|
22
23
|
|
|
@@ -50,7 +51,7 @@ describe('PartyCore', () => {
|
|
|
50
51
|
afterTest(async () => party.close());
|
|
51
52
|
|
|
52
53
|
// PartyGenesis (self-signed by Party).
|
|
53
|
-
await party.
|
|
54
|
+
await party.writeCredentialsMessage(createPartyGenesisMessage(
|
|
54
55
|
keyring,
|
|
55
56
|
partyKey,
|
|
56
57
|
feed.key,
|
|
@@ -58,7 +59,7 @@ describe('PartyCore', () => {
|
|
|
58
59
|
);
|
|
59
60
|
|
|
60
61
|
// FeedAdmit (signed by the Device KeyChain).
|
|
61
|
-
await party.
|
|
62
|
+
await party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
62
63
|
keyring,
|
|
63
64
|
partyKey.publicKey,
|
|
64
65
|
feed.key,
|
|
@@ -119,7 +120,7 @@ describe('PartyCore', () => {
|
|
|
119
120
|
const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
|
|
120
121
|
|
|
121
122
|
const eventFired = feedStore.feedOpenedEvent.waitForCount(1);
|
|
122
|
-
await party.
|
|
123
|
+
await party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
123
124
|
keyring,
|
|
124
125
|
party.key,
|
|
125
126
|
feedKey.publicKey,
|
|
@@ -196,7 +197,7 @@ describe('PartyCore', () => {
|
|
|
196
197
|
const fullKey = keyring.getFullKey(feedKey.publicKey);
|
|
197
198
|
const feed2 = await feedStore.openReadWriteFeed(fullKey!.publicKey, fullKey!.secretKey!);
|
|
198
199
|
|
|
199
|
-
await party.
|
|
200
|
+
await party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
200
201
|
keyring,
|
|
201
202
|
party.key,
|
|
202
203
|
feed2.key,
|
|
@@ -225,7 +226,7 @@ describe('PartyCore', () => {
|
|
|
225
226
|
const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
|
|
226
227
|
const fullKey = keyring.getFullKey(feedKey.publicKey);
|
|
227
228
|
|
|
228
|
-
await party.
|
|
229
|
+
await party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
229
230
|
keyring,
|
|
230
231
|
party.key,
|
|
231
232
|
feedKey.publicKey,
|
|
@@ -272,7 +273,7 @@ describe('PartyCore', () => {
|
|
|
272
273
|
|
|
273
274
|
const feed2 = await partyFeedProvider.createOrOpenWritableFeed();
|
|
274
275
|
|
|
275
|
-
await peer1.party.
|
|
276
|
+
await peer1.party.writeCredentialsMessage(createFeedAdmitMessage(
|
|
276
277
|
peer1.keyring,
|
|
277
278
|
peer1.party.key,
|
|
278
279
|
feed2.key,
|
|
@@ -286,12 +287,8 @@ describe('PartyCore', () => {
|
|
|
286
287
|
afterTest(async () => party2.close());
|
|
287
288
|
|
|
288
289
|
createTestProtocolPair(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
).createPlugins().map(r => r.createExtension()),
|
|
292
|
-
new ReplicatorProtocolPluginFactory(
|
|
293
|
-
partyFeedProvider
|
|
294
|
-
).createPlugins().map(r => r.createExtension())
|
|
290
|
+
[createReplicatorPlugin(peer1.partyFeedProvider).createExtension()],
|
|
291
|
+
[createReplicatorPlugin(partyFeedProvider).createExtension()]
|
|
295
292
|
);
|
|
296
293
|
|
|
297
294
|
const item1 = await peer1.party.database.createItem();
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
|
|
7
7
|
import { synchronized } from '@dxos/async';
|
|
8
|
-
import { KeyHint, KeyType } from '@dxos/credentials';
|
|
8
|
+
import { KeyHint, KeyType, Message as HaloMessage } from '@dxos/credentials';
|
|
9
9
|
import { PublicKey } from '@dxos/crypto';
|
|
10
10
|
import { timed } from '@dxos/debug';
|
|
11
|
-
import { createFeedWriter, DatabaseSnapshot, PartyKey, PartySnapshot, Timeframe } from '@dxos/echo-protocol';
|
|
11
|
+
import { createFeedWriter, DatabaseSnapshot, PartyKey, PartySnapshot, Timeframe, WriteReceipt } from '@dxos/echo-protocol';
|
|
12
12
|
import { ModelFactory } from '@dxos/model-factory';
|
|
13
13
|
import { SubscriptionGroup } from '@dxos/util';
|
|
14
14
|
|
|
@@ -202,6 +202,11 @@ export class PartyCore {
|
|
|
202
202
|
return this;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
writeCredentialsMessage (message: HaloMessage): Promise<WriteReceipt> {
|
|
206
|
+
assert(this._partyProcessor, 'Party not open');
|
|
207
|
+
return this._partyProcessor?.writeHaloMessage(message);
|
|
208
|
+
}
|
|
209
|
+
|
|
205
210
|
/**
|
|
206
211
|
* Create a snapshot of the current state.
|
|
207
212
|
*/
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
PartyState,
|
|
13
13
|
Message as HaloMessage,
|
|
14
14
|
IdentityEventType,
|
|
15
|
-
PartyEventType
|
|
15
|
+
PartyEventType,
|
|
16
|
+
SignedMessage
|
|
16
17
|
} from '@dxos/credentials';
|
|
17
18
|
import { PublicKey } from '@dxos/crypto';
|
|
18
19
|
import { FeedKey, FeedWriter, IHaloStream, PartyKey, HaloStateSnapshot, WriteReceipt } from '@dxos/echo-protocol';
|
|
@@ -20,10 +21,33 @@ import { jsonReplacer } from '@dxos/util';
|
|
|
20
21
|
|
|
21
22
|
const log = debug('dxos:echo-db:party-processor');
|
|
22
23
|
|
|
24
|
+
export interface CredentialWriter {
|
|
25
|
+
writeHaloMessage (message: HaloMessage): Promise<WriteReceipt>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CredentialProcessor {
|
|
29
|
+
processMessage (message: IHaloStream): Promise<void>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface PartyStateProvider {
|
|
33
|
+
partyKey: PublicKey
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Whether PartyGenesis was already processed.
|
|
37
|
+
*/
|
|
38
|
+
genesisRequired: boolean
|
|
39
|
+
memberKeys: PublicKey[]
|
|
40
|
+
feedKeys: PublicKey[]
|
|
41
|
+
getFeedOwningMember (feedKey: FeedKey): PublicKey | undefined
|
|
42
|
+
isFeedAdmitted (feedKey: FeedKey): boolean
|
|
43
|
+
|
|
44
|
+
getOfflineInvitation (invitationID: Buffer): SignedMessage | undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
23
47
|
/**
|
|
24
48
|
* TODO(burdon): Wrapper/Bridge between HALO APIs.
|
|
25
49
|
*/
|
|
26
|
-
export class PartyProcessor {
|
|
50
|
+
export class PartyProcessor implements CredentialWriter, CredentialProcessor, PartyStateProvider {
|
|
27
51
|
private readonly _state: PartyState;
|
|
28
52
|
|
|
29
53
|
private _outboundHaloStream: FeedWriter<HaloMessage> | undefined;
|
package/src/pipeline/pipeline.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { createReadable } from '@dxos/feed-store';
|
|
|
17
17
|
import { jsonReplacer } from '@dxos/util';
|
|
18
18
|
|
|
19
19
|
import { TimeframeClock } from '../database';
|
|
20
|
-
import {
|
|
20
|
+
import { CredentialProcessor, PartyStateProvider } from './party-processor';
|
|
21
21
|
|
|
22
22
|
interface Options {
|
|
23
23
|
readLogger?: (msg: any) => void
|
|
@@ -55,17 +55,13 @@ export class Pipeline {
|
|
|
55
55
|
* @param _options
|
|
56
56
|
*/
|
|
57
57
|
constructor (
|
|
58
|
-
private readonly _partyProcessor:
|
|
58
|
+
private readonly _partyProcessor: CredentialProcessor & PartyStateProvider,
|
|
59
59
|
private readonly _feedStorIterator: FeedStoreIterator,
|
|
60
60
|
private readonly _timeframeClock: TimeframeClock,
|
|
61
61
|
private readonly _feedWriter?: FeedWriter<FeedMessage>,
|
|
62
62
|
private readonly _options: Options = {}
|
|
63
63
|
) {}
|
|
64
64
|
|
|
65
|
-
get partyKey () {
|
|
66
|
-
return this._partyProcessor.partyKey;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
65
|
get isOpen () {
|
|
70
66
|
return this._inboundEchoStream !== undefined;
|
|
71
67
|
}
|
|
@@ -9,6 +9,4 @@ import { Replicator } from '@dxos/protocol-plugin-replicator';
|
|
|
9
9
|
/**
|
|
10
10
|
* Creates authenticator network-protocol plugin that guards access to the replicator.
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
13
|
-
return new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
|
|
14
|
-
}
|
|
12
|
+
export const createAuthPlugin = (authenticator: Authenticator, peerId: PublicKey) => new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
|
|
@@ -12,19 +12,17 @@ import { CredentialsSigner } from './credentials-signer';
|
|
|
12
12
|
|
|
13
13
|
const log = debug('dxos:echo-db:authenticator');
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
}
|
|
15
|
+
export const createAuthenticator = (partyProcessor: PartyProcessor, credentialsSigner: CredentialsSigner): Authenticator => new PartyAuthenticator(partyProcessor.state, async auth => {
|
|
16
|
+
if (auth.feedAdmit && auth.feedKey && !partyProcessor.isFeedAdmitted(auth.feedKey)) {
|
|
17
|
+
log(`Admitting feed of authenticated member: ${auth.feedKey}`);
|
|
18
|
+
await partyProcessor.writeHaloMessage(createEnvelopeMessage(
|
|
19
|
+
credentialsSigner.signer,
|
|
20
|
+
partyProcessor.partyKey,
|
|
21
|
+
auth.feedAdmit,
|
|
22
|
+
[credentialsSigner.getDeviceSigningKeys()]
|
|
23
|
+
));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
28
26
|
|
|
29
27
|
export interface CredentialsProvider {
|
|
30
28
|
/**
|
|
@@ -33,24 +31,22 @@ export interface CredentialsProvider {
|
|
|
33
31
|
get (): Buffer
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
export const createCredentialsProvider = (credentialsSigner: CredentialsSigner, partyKey: PartyKey, feedKey: FeedKey): CredentialsProvider => ({
|
|
35
|
+
get: () => {
|
|
36
|
+
const authMessage = createAuthMessage(
|
|
37
|
+
credentialsSigner.signer,
|
|
38
|
+
partyKey,
|
|
39
|
+
credentialsSigner.getIdentityKey(),
|
|
40
|
+
credentialsSigner.getDeviceSigningKeys(),
|
|
41
|
+
feedKey,
|
|
42
|
+
undefined,
|
|
43
|
+
createFeedAdmitMessage(
|
|
40
44
|
credentialsSigner.signer,
|
|
41
45
|
partyKey,
|
|
42
|
-
credentialsSigner.getIdentityKey(),
|
|
43
|
-
credentialsSigner.getDeviceSigningKeys(),
|
|
44
46
|
feedKey,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
return Buffer.from(codec.encode(authMessage));
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
47
|
+
[feedKey, credentialsSigner.getDeviceSigningKeys()]
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
return Buffer.from(codec.encode(authMessage));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
@@ -12,9 +12,7 @@ import { HaloRecoveryInitiator, InvitationFactory } from '../invitations';
|
|
|
12
12
|
* Plugin is intended to be used in HALO party swarm.
|
|
13
13
|
*
|
|
14
14
|
*/
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
);
|
|
20
|
-
}
|
|
15
|
+
export const createHaloRecoveryPlugin = (identityKey: PublicKey, invitationFactory: InvitationFactory, peerId: PublicKey) => new GreetingCommandPlugin(
|
|
16
|
+
peerId.asBuffer(),
|
|
17
|
+
HaloRecoveryInitiator.createHaloInvitationClaimHandler(identityKey, invitationFactory)
|
|
18
|
+
);
|
|
@@ -25,7 +25,7 @@ export interface IdentityCredentials {
|
|
|
25
25
|
|
|
26
26
|
export type IdentityCredentialsProvider = () => IdentityCredentials | undefined
|
|
27
27
|
|
|
28
|
-
export
|
|
28
|
+
export const createTestIdentityCredentials = async (keyring: Keyring): Promise<IdentityCredentials> => {
|
|
29
29
|
const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
|
|
30
30
|
const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
31
31
|
const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
|
|
@@ -53,9 +53,9 @@ export async function createTestIdentityCredentials (keyring: Keyring): Promise<
|
|
|
53
53
|
preferences: undefined,
|
|
54
54
|
contacts: undefined
|
|
55
55
|
};
|
|
56
|
-
}
|
|
56
|
+
};
|
|
57
57
|
|
|
58
|
-
export
|
|
58
|
+
export const deriveTestDeviceCredentials = async (identity: IdentityCredentials): Promise<IdentityCredentials> => {
|
|
59
59
|
const deviceKey = await identity.keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
60
60
|
const keyAdmit = createKeyAdmitMessage(identity.keyring, identity.identityKey.publicKey, deviceKey, [identity.identityKey]);
|
|
61
61
|
|
|
@@ -75,4 +75,4 @@ export async function deriveTestDeviceCredentials (identity: IdentityCredentials
|
|
|
75
75
|
deviceKeyChain
|
|
76
76
|
)
|
|
77
77
|
};
|
|
78
|
-
}
|
|
78
|
+
};
|
|
@@ -11,9 +11,7 @@ import { InvitationFactory, OfflineInvitationClaimer } from '../invitations';
|
|
|
11
11
|
* Creates network protocol plugin that allows peers to claim offline invitations.
|
|
12
12
|
* Plugin is intended to be used in data-party swarms.
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
);
|
|
19
|
-
}
|
|
14
|
+
export const createOfflineInvitationPlugin = (invitationFactory: InvitationFactory, peerId: PublicKey) => new GreetingCommandPlugin(
|
|
15
|
+
peerId.asBuffer(),
|
|
16
|
+
OfflineInvitationClaimer.createOfflineInvitationClaimHandler(invitationFactory)
|
|
17
|
+
);
|