cojson 0.18.33 → 0.18.35
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +17 -0
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +2 -2
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueContentMessage.d.ts +5 -2
- package/dist/coValueContentMessage.d.ts.map +1 -1
- package/dist/coValueContentMessage.js +15 -0
- package/dist/coValueContentMessage.js.map +1 -1
- package/dist/coValueCore/SessionMap.d.ts +4 -3
- package/dist/coValueCore/SessionMap.d.ts.map +1 -1
- package/dist/coValueCore/SessionMap.js +21 -30
- package/dist/coValueCore/SessionMap.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +14 -6
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +32 -52
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +6 -4
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +21 -7
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +20 -15
- package/dist/coValues/group.js.map +1 -1
- package/dist/knownState.d.ts +9 -1
- package/dist/knownState.d.ts.map +1 -1
- package/dist/knownState.js +29 -3
- package/dist/knownState.js.map +1 -1
- package/dist/localNode.d.ts +7 -2
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +10 -15
- package/dist/localNode.js.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts +10 -9
- package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.js +53 -47
- package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
- package/dist/storage/knownState.js +2 -2
- package/dist/storage/knownState.js.map +1 -1
- package/dist/sync.d.ts +1 -2
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +15 -19
- package/dist/sync.js.map +1 -1
- package/dist/tests/coPlainText.test.js +13 -14
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coValueContentMessage.test.js +130 -1
- package/dist/tests/coValueContentMessage.test.js.map +1 -1
- package/dist/tests/coValueCore.isCompletelyDownloaded.test.js +3 -2
- package/dist/tests/coValueCore.isCompletelyDownloaded.test.js.map +1 -1
- package/dist/tests/coValueCore.isStreaming.test.js +54 -3
- package/dist/tests/coValueCore.isStreaming.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +3 -6
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/group.childKeyRotation.test.js +9 -9
- package/dist/tests/group.childKeyRotation.test.js.map +1 -1
- package/dist/tests/knownState.test.js +82 -10
- package/dist/tests/knownState.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +29 -29
- package/dist/tests/sync.mesh.test.js +38 -31
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +24 -23
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +24 -23
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +58 -58
- package/dist/tests/testUtils.d.ts +11 -9
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +26 -16
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +3 -4
- package/src/SyncStateManager.ts +8 -2
- package/src/coValueContentMessage.ts +29 -2
- package/src/coValueCore/SessionMap.ts +41 -31
- package/src/coValueCore/coValueCore.ts +41 -74
- package/src/coValueCore/verifiedState.ts +36 -11
- package/src/coValues/group.ts +40 -27
- package/src/knownState.ts +39 -4
- package/src/localNode.ts +16 -21
- package/src/queue/LocalTransactionsSyncQueue.ts +77 -93
- package/src/storage/knownState.ts +2 -2
- package/src/sync.ts +24 -26
- package/src/tests/coPlainText.test.ts +13 -14
- package/src/tests/coValueContentMessage.test.ts +197 -2
- package/src/tests/coValueCore.isCompletelyDownloaded.test.ts +3 -2
- package/src/tests/coValueCore.isStreaming.test.ts +84 -2
- package/src/tests/coValueCore.test.ts +7 -10
- package/src/tests/group.childKeyRotation.test.ts +9 -9
- package/src/tests/knownState.test.ts +106 -9
- package/src/tests/sync.load.test.ts +29 -29
- package/src/tests/sync.mesh.test.ts +38 -31
- package/src/tests/sync.storage.test.ts +24 -23
- package/src/tests/sync.storageAsync.test.ts +24 -23
- package/src/tests/sync.upload.test.ts +58 -58
- package/src/tests/testUtils.ts +30 -18
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { UpDownCounter, ValueType, metrics } from "@opentelemetry/api";
|
|
2
|
-
import { Result, err, ok } from "neverthrow";
|
|
3
2
|
import type { PeerState } from "../PeerState.js";
|
|
4
3
|
import type { RawCoValue } from "../coValue.js";
|
|
5
4
|
import type { ControlledAccountOrAgent } from "../coValues/account.js";
|
|
@@ -201,7 +200,7 @@ export class CoValueCore {
|
|
|
201
200
|
}
|
|
202
201
|
| {
|
|
203
202
|
type: "errored";
|
|
204
|
-
error:
|
|
203
|
+
error: unknown;
|
|
205
204
|
}
|
|
206
205
|
>();
|
|
207
206
|
|
|
@@ -474,12 +473,10 @@ export class CoValueCore {
|
|
|
474
473
|
new SessionMap(this.id, this.node.crypto, streamingKnownState),
|
|
475
474
|
);
|
|
476
475
|
|
|
477
|
-
this.resetKnownStateCache();
|
|
478
|
-
|
|
479
476
|
return true;
|
|
480
477
|
}
|
|
481
478
|
|
|
482
|
-
markErrored(peerId: PeerID, error:
|
|
479
|
+
markErrored(peerId: PeerID, error: unknown) {
|
|
483
480
|
const previousState = this.loadingState;
|
|
484
481
|
this.loadingStatuses.set(peerId, { type: "errored", error });
|
|
485
482
|
this.updateCounter(previousState);
|
|
@@ -531,27 +528,18 @@ export class CoValueCore {
|
|
|
531
528
|
.then((core) => core.getCurrentContent());
|
|
532
529
|
}
|
|
533
530
|
|
|
534
|
-
private _cachedKnownStateWithStreaming?: CoValueKnownState;
|
|
535
531
|
/**
|
|
536
532
|
* Returns the known state considering the known state of the streaming source
|
|
537
533
|
*
|
|
538
534
|
* Used to correctly manage the content & subscriptions during the content streaming process
|
|
539
535
|
*/
|
|
540
536
|
knownStateWithStreaming(): CoValueKnownState {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
const knownState = this.verified
|
|
546
|
-
? cloneKnownState(this.verified.knownStateWithStreaming())
|
|
547
|
-
: emptyKnownState(this.id);
|
|
548
|
-
|
|
549
|
-
this._cachedKnownStateWithStreaming = knownState;
|
|
550
|
-
|
|
551
|
-
return knownState;
|
|
537
|
+
return (
|
|
538
|
+
this.verified?.immutableKnownStateWithStreaming() ??
|
|
539
|
+
emptyKnownState(this.id)
|
|
540
|
+
);
|
|
552
541
|
}
|
|
553
542
|
|
|
554
|
-
private _cachedKnownState?: CoValueKnownState;
|
|
555
543
|
/**
|
|
556
544
|
* Returns the known state of the CoValue
|
|
557
545
|
*
|
|
@@ -560,17 +548,7 @@ export class CoValueCore {
|
|
|
560
548
|
* On change the knownState is invalidated and a new object is returned.
|
|
561
549
|
*/
|
|
562
550
|
knownState(): CoValueKnownState {
|
|
563
|
-
|
|
564
|
-
return this._cachedKnownState;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
const knownState = this.verified
|
|
568
|
-
? cloneKnownState(this.verified.knownState())
|
|
569
|
-
: emptyKnownState(this.id);
|
|
570
|
-
|
|
571
|
-
this._cachedKnownState = knownState;
|
|
572
|
-
|
|
573
|
-
return knownState;
|
|
551
|
+
return this.verified?.immutableKnownState() ?? emptyKnownState(this.id);
|
|
574
552
|
}
|
|
575
553
|
|
|
576
554
|
get meta(): JsonValue {
|
|
@@ -612,31 +590,36 @@ export class CoValueCore {
|
|
|
612
590
|
newTransactions: Transaction[],
|
|
613
591
|
newSignature: Signature,
|
|
614
592
|
skipVerify: boolean = false,
|
|
615
|
-
)
|
|
616
|
-
let
|
|
593
|
+
) {
|
|
594
|
+
let signerID: SignerID | undefined;
|
|
617
595
|
|
|
618
|
-
if (skipVerify) {
|
|
619
|
-
result =
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
accountOrAgentIDfromSessionID(sessionID),
|
|
624
|
-
"Expected to know signer of transaction",
|
|
625
|
-
)
|
|
626
|
-
.andThen((agent) => {
|
|
627
|
-
return ok(this.crypto.getAgentSignerID(agent));
|
|
628
|
-
});
|
|
629
|
-
}
|
|
596
|
+
if (!skipVerify) {
|
|
597
|
+
const result = this.node.resolveAccountAgent(
|
|
598
|
+
accountOrAgentIDfromSessionID(sessionID),
|
|
599
|
+
"Expected to know signer of transaction",
|
|
600
|
+
);
|
|
630
601
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
type: "TriedToAddTransactionsWithoutVerifiedState",
|
|
602
|
+
if (result.error || !result.value) {
|
|
603
|
+
return {
|
|
604
|
+
type: "ResolveAccountAgentError",
|
|
635
605
|
id: this.id,
|
|
636
|
-
|
|
606
|
+
error: result.error,
|
|
607
|
+
} as const;
|
|
637
608
|
}
|
|
638
609
|
|
|
639
|
-
|
|
610
|
+
signerID = this.crypto.getAgentSignerID(result.value);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (!this.verified) {
|
|
614
|
+
return {
|
|
615
|
+
type: "TriedToAddTransactionsWithoutVerifiedState",
|
|
616
|
+
id: this.id,
|
|
617
|
+
error: undefined,
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
this.verified.tryAddTransactions(
|
|
640
623
|
sessionID,
|
|
641
624
|
signerID,
|
|
642
625
|
newTransactions,
|
|
@@ -644,19 +627,11 @@ export class CoValueCore {
|
|
|
644
627
|
skipVerify,
|
|
645
628
|
);
|
|
646
629
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
return result;
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
private resetKnownStateCache() {
|
|
658
|
-
this._cachedKnownState = undefined;
|
|
659
|
-
this._cachedKnownStateWithStreaming = undefined;
|
|
630
|
+
this.processNewTransactions();
|
|
631
|
+
this.scheduleNotifyUpdate();
|
|
632
|
+
} catch (e) {
|
|
633
|
+
return { type: "InvalidSignature", id: this.id, error: e } as const;
|
|
634
|
+
}
|
|
660
635
|
}
|
|
661
636
|
|
|
662
637
|
private processNewTransactions() {
|
|
@@ -769,6 +744,8 @@ export class CoValueCore {
|
|
|
769
744
|
|
|
770
745
|
let result: { signature: Signature; transaction: Transaction };
|
|
771
746
|
|
|
747
|
+
const knownStateBefore = this.knownState();
|
|
748
|
+
|
|
772
749
|
if (privacy === "private") {
|
|
773
750
|
const { secret: keySecret, id: keyID } = this.getCurrentReadKey();
|
|
774
751
|
|
|
@@ -795,7 +772,7 @@ export class CoValueCore {
|
|
|
795
772
|
);
|
|
796
773
|
}
|
|
797
774
|
|
|
798
|
-
const { transaction
|
|
775
|
+
const { transaction } = result;
|
|
799
776
|
|
|
800
777
|
// Assign pre-parsed meta and changes to skip the parse/decrypt operation when loading
|
|
801
778
|
// this transaction in the current content
|
|
@@ -803,23 +780,13 @@ export class CoValueCore {
|
|
|
803
780
|
|
|
804
781
|
this.node.syncManager.recordTransactionsSize([transaction], "local");
|
|
805
782
|
|
|
806
|
-
const session = this.verified.sessions.get(sessionID);
|
|
807
|
-
const txIdx = session ? session.transactions.length - 1 : 0;
|
|
808
|
-
|
|
809
|
-
this.resetKnownStateCache();
|
|
810
783
|
this.processNewTransactions();
|
|
811
784
|
this.addDependenciesFromNewTransaction(transaction);
|
|
812
785
|
|
|
813
786
|
// force immediate notification because local updates may come from the UI
|
|
814
787
|
// where we need synchronous updates
|
|
815
788
|
this.notifyUpdate();
|
|
816
|
-
this.node.syncManager.syncLocalTransaction(
|
|
817
|
-
this.verified,
|
|
818
|
-
transaction,
|
|
819
|
-
sessionID,
|
|
820
|
-
signature,
|
|
821
|
-
txIdx,
|
|
822
|
-
);
|
|
789
|
+
this.node.syncManager.syncLocalTransaction(this.verified, knownStateBefore);
|
|
823
790
|
|
|
824
791
|
return true;
|
|
825
792
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Result, err, ok } from "neverthrow";
|
|
2
1
|
import { AnyRawCoValue } from "../coValue.js";
|
|
3
2
|
import {
|
|
4
3
|
createContentMessage,
|
|
5
4
|
exceedsRecommendedSize,
|
|
6
5
|
getTransactionSize,
|
|
7
6
|
addTransactionToContentMessage,
|
|
7
|
+
knownStateFromContent,
|
|
8
8
|
} from "../coValueContentMessage.js";
|
|
9
9
|
import {
|
|
10
10
|
CryptoProvider,
|
|
@@ -20,9 +20,13 @@ import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
|
20
20
|
import { PermissionsDef as RulesetDef } from "../permissions.js";
|
|
21
21
|
import { NewContentMessage } from "../sync.js";
|
|
22
22
|
import { TryAddTransactionsError } from "./coValueCore.js";
|
|
23
|
-
import {
|
|
23
|
+
import { SessionMap } from "./SessionMap.js";
|
|
24
24
|
import { ControlledAccountOrAgent } from "../coValues/account.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
CoValueKnownState,
|
|
27
|
+
getKnownStateToSend,
|
|
28
|
+
KnownStateSessions,
|
|
29
|
+
} from "../knownState.js";
|
|
26
30
|
|
|
27
31
|
export type CoValueHeader = {
|
|
28
32
|
type: AnyRawCoValue["type"];
|
|
@@ -89,16 +93,14 @@ export class VerifiedState {
|
|
|
89
93
|
newTransactions: Transaction[],
|
|
90
94
|
newSignature: Signature,
|
|
91
95
|
skipVerify: boolean = false,
|
|
92
|
-
)
|
|
93
|
-
|
|
96
|
+
) {
|
|
97
|
+
this.sessions.addTransaction(
|
|
94
98
|
sessionID,
|
|
95
99
|
signerID,
|
|
96
100
|
newTransactions,
|
|
97
101
|
newSignature,
|
|
98
102
|
skipVerify,
|
|
99
103
|
);
|
|
100
|
-
|
|
101
|
-
return result;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
makeNewTrustingTransaction(
|
|
@@ -158,6 +160,9 @@ export class VerifiedState {
|
|
|
158
160
|
|
|
159
161
|
newContentSince(
|
|
160
162
|
knownState: CoValueKnownState | undefined,
|
|
163
|
+
opts?: {
|
|
164
|
+
skipExpectContentUntil?: boolean;
|
|
165
|
+
},
|
|
161
166
|
): NewContentMessage[] | undefined {
|
|
162
167
|
let currentPiece: NewContentMessage = createContentMessage(
|
|
163
168
|
this.id,
|
|
@@ -285,10 +290,19 @@ export class VerifiedState {
|
|
|
285
290
|
);
|
|
286
291
|
|
|
287
292
|
if (piecesWithContent.length > 1 || this.isStreaming()) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
293
|
+
if (!opts?.skipExpectContentUntil) {
|
|
294
|
+
// Flag that more content is coming
|
|
295
|
+
if (knownState) {
|
|
296
|
+
firstPiece.expectContentUntil = getKnownStateToSend(
|
|
297
|
+
this.knownStateWithStreaming().sessions,
|
|
298
|
+
knownState.sessions,
|
|
299
|
+
);
|
|
300
|
+
} else {
|
|
301
|
+
firstPiece.expectContentUntil = {
|
|
302
|
+
...this.knownStateWithStreaming().sessions,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
292
306
|
}
|
|
293
307
|
|
|
294
308
|
if (piecesWithContent.length === 0) {
|
|
@@ -306,6 +320,17 @@ export class VerifiedState {
|
|
|
306
320
|
return this.sessions.knownStateWithStreaming ?? this.knownState();
|
|
307
321
|
}
|
|
308
322
|
|
|
323
|
+
immutableKnownState() {
|
|
324
|
+
return this.sessions.immutableKnownState;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
immutableKnownStateWithStreaming() {
|
|
328
|
+
return (
|
|
329
|
+
this.sessions.immutableKnownStateWithStreaming ??
|
|
330
|
+
this.immutableKnownState()
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
309
334
|
isStreaming(): boolean {
|
|
310
335
|
return Boolean(this.sessions.knownStateWithStreaming);
|
|
311
336
|
}
|
package/src/coValues/group.ts
CHANGED
|
@@ -508,12 +508,14 @@ export class RawGroup<
|
|
|
508
508
|
memberRole === "writerInvite" ||
|
|
509
509
|
memberRole === "adminInvite"
|
|
510
510
|
) {
|
|
511
|
-
const otherMemberAgent = this.core.node
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
511
|
+
const otherMemberAgent = this.core.node.resolveAccountAgent(
|
|
512
|
+
otherMemberKey,
|
|
513
|
+
"Expected member agent to be loaded",
|
|
514
|
+
).value;
|
|
515
|
+
|
|
516
|
+
if (!otherMemberAgent) {
|
|
517
|
+
throw new Error("Expected member agent to be loaded");
|
|
518
|
+
}
|
|
517
519
|
|
|
518
520
|
this.storeKeyRevelationForMember(
|
|
519
521
|
otherMemberKey,
|
|
@@ -689,9 +691,14 @@ export class RawGroup<
|
|
|
689
691
|
|
|
690
692
|
if (lastReadyKeyEdit?.value) {
|
|
691
693
|
const revealer = lastReadyKeyEdit.by;
|
|
692
|
-
const revealerAgent = core.node
|
|
693
|
-
|
|
694
|
-
|
|
694
|
+
const revealerAgent = core.node.resolveAccountAgent(
|
|
695
|
+
revealer,
|
|
696
|
+
"Expected to know revealer",
|
|
697
|
+
).value;
|
|
698
|
+
|
|
699
|
+
if (!revealerAgent) {
|
|
700
|
+
throw new Error("Expected to know revealer");
|
|
701
|
+
}
|
|
695
702
|
|
|
696
703
|
const secret = this.crypto.unseal(
|
|
697
704
|
lastReadyKeyEdit.value,
|
|
@@ -841,12 +848,14 @@ export class RawGroup<
|
|
|
841
848
|
const newReadKey = this.crypto.newRandomKeySecret();
|
|
842
849
|
|
|
843
850
|
for (const readerID of currentlyPermittedReaders) {
|
|
844
|
-
const agent = this.core.node
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
851
|
+
const agent = this.core.node.resolveAccountAgent(
|
|
852
|
+
readerID,
|
|
853
|
+
"Expected to know currently permitted reader",
|
|
854
|
+
).value;
|
|
855
|
+
|
|
856
|
+
if (!agent) {
|
|
857
|
+
throw new Error("Expected to know currently permitted reader");
|
|
858
|
+
}
|
|
850
859
|
|
|
851
860
|
this.storeKeyRevelationForMember(
|
|
852
861
|
readerID,
|
|
@@ -861,12 +870,14 @@ export class RawGroup<
|
|
|
861
870
|
* and reveal them to the other non-writeOnly members
|
|
862
871
|
*/
|
|
863
872
|
for (const writeOnlyMemberID of writeOnlyMembers) {
|
|
864
|
-
const agent = this.core.node
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
873
|
+
const agent = this.core.node.resolveAccountAgent(
|
|
874
|
+
writeOnlyMemberID,
|
|
875
|
+
"Expected to know writeOnly member",
|
|
876
|
+
).value;
|
|
877
|
+
|
|
878
|
+
if (!agent) {
|
|
879
|
+
throw new Error("Expected to know writeOnly member");
|
|
880
|
+
}
|
|
870
881
|
|
|
871
882
|
const writeOnlyKey = this.crypto.newRandomKeySecret();
|
|
872
883
|
|
|
@@ -879,12 +890,14 @@ export class RawGroup<
|
|
|
879
890
|
this.set(`writeKeyFor_${writeOnlyMemberID}`, writeOnlyKey.id, "trusting");
|
|
880
891
|
|
|
881
892
|
for (const readerID of currentlyPermittedReaders) {
|
|
882
|
-
const agent = this.core.node
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
893
|
+
const agent = this.core.node.resolveAccountAgent(
|
|
894
|
+
readerID,
|
|
895
|
+
"Expected to know currently permitted reader",
|
|
896
|
+
).value;
|
|
897
|
+
|
|
898
|
+
if (!agent) {
|
|
899
|
+
throw new Error("Expected to know currently permitted reader");
|
|
900
|
+
}
|
|
888
901
|
|
|
889
902
|
this.storeKeyRevelationForMember(
|
|
890
903
|
readerID,
|
package/src/knownState.ts
CHANGED
|
@@ -106,18 +106,53 @@ export function cloneKnownState(knownState: CoValueKnownState) {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Checks if all the local sessions have the same counters as in remote.
|
|
111
|
+
*/
|
|
112
|
+
export function areCurrentSessionsInSyncWith(
|
|
113
|
+
current: Record<string, number>,
|
|
114
|
+
target: Record<string, number>,
|
|
115
|
+
) {
|
|
116
|
+
for (const [sessionId, currentCount] of Object.entries(current)) {
|
|
117
|
+
const targetCount = target[sessionId] ?? 0;
|
|
118
|
+
if (currentCount !== targetCount) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
109
126
|
/**
|
|
110
127
|
* Checks if all the local sessions have the same counters as in remote.
|
|
111
128
|
*/
|
|
112
129
|
export function isKnownStateSubsetOf(
|
|
113
|
-
|
|
114
|
-
|
|
130
|
+
current: Record<string, number>,
|
|
131
|
+
target: Record<string, number>,
|
|
115
132
|
) {
|
|
116
|
-
for (const sessionId of Object.
|
|
117
|
-
|
|
133
|
+
for (const [sessionId, currentCount] of Object.entries(current)) {
|
|
134
|
+
const targetCount = target[sessionId] ?? 0;
|
|
135
|
+
if (currentCount > targetCount) {
|
|
118
136
|
return false;
|
|
119
137
|
}
|
|
120
138
|
}
|
|
121
139
|
|
|
122
140
|
return true;
|
|
123
141
|
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Returns the record with the sessions that need to be sent to the target
|
|
145
|
+
*/
|
|
146
|
+
export function getKnownStateToSend(
|
|
147
|
+
current: Record<string, number>,
|
|
148
|
+
target: Record<string, number>,
|
|
149
|
+
) {
|
|
150
|
+
const toSend: Record<string, number> = {};
|
|
151
|
+
for (const [sessionId, currentCount] of Object.entries(current)) {
|
|
152
|
+
const targetCount = target[sessionId] ?? 0;
|
|
153
|
+
if (currentCount > targetCount) {
|
|
154
|
+
toSend[sessionId] = currentCount;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return toSend;
|
|
158
|
+
}
|
package/src/localNode.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Result, err, ok } from "neverthrow";
|
|
2
1
|
import { GarbageCollector } from "./GarbageCollector.js";
|
|
3
2
|
import type { CoID } from "./coValue.js";
|
|
4
3
|
import type { RawCoValue } from "./coValue.js";
|
|
@@ -10,7 +9,6 @@ import {
|
|
|
10
9
|
import {
|
|
11
10
|
type CoValueHeader,
|
|
12
11
|
type CoValueUniqueness,
|
|
13
|
-
VerifiedState,
|
|
14
12
|
} from "./coValueCore/verifiedState.js";
|
|
15
13
|
import {
|
|
16
14
|
AccountMeta,
|
|
@@ -31,7 +29,7 @@ import {
|
|
|
31
29
|
type RawGroup,
|
|
32
30
|
secretSeedFromInviteSecret,
|
|
33
31
|
} from "./coValues/group.js";
|
|
34
|
-
import { CO_VALUE_LOADING_CONFIG
|
|
32
|
+
import { CO_VALUE_LOADING_CONFIG } from "./config.js";
|
|
35
33
|
import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
|
|
36
34
|
import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
|
|
37
35
|
import { logger } from "./logger.js";
|
|
@@ -41,6 +39,7 @@ import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromS
|
|
|
41
39
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
42
40
|
import { canBeBranched } from "./coValueCore/branching.js";
|
|
43
41
|
import { connectedPeers } from "./streamUtils.js";
|
|
42
|
+
import { emptyKnownState } from "./knownState.js";
|
|
44
43
|
|
|
45
44
|
/** A `LocalNode` represents a local view of a set of loaded `CoValue`s, from the perspective of a particular account (or primitive cryptographic agent).
|
|
46
45
|
|
|
@@ -380,7 +379,10 @@ export class LocalNode {
|
|
|
380
379
|
}
|
|
381
380
|
|
|
382
381
|
this.garbageCollector?.trackCoValueAccess(coValue);
|
|
383
|
-
this.syncManager.
|
|
382
|
+
this.syncManager.syncLocalTransaction(
|
|
383
|
+
coValue.verified,
|
|
384
|
+
emptyKnownState(id),
|
|
385
|
+
);
|
|
384
386
|
|
|
385
387
|
return coValue;
|
|
386
388
|
}
|
|
@@ -686,12 +688,9 @@ export class LocalNode {
|
|
|
686
688
|
}
|
|
687
689
|
|
|
688
690
|
/** @internal */
|
|
689
|
-
resolveAccountAgent(
|
|
690
|
-
id: RawAccountID | AgentID,
|
|
691
|
-
expectation?: string,
|
|
692
|
-
): Result<AgentID, ResolveAccountAgentError> {
|
|
691
|
+
resolveAccountAgent(id: RawAccountID | AgentID, expectation?: string) {
|
|
693
692
|
if (isAgentID(id)) {
|
|
694
|
-
return
|
|
693
|
+
return { value: id, error: undefined };
|
|
695
694
|
}
|
|
696
695
|
|
|
697
696
|
let coValue: AvailableCoValueCore;
|
|
@@ -699,12 +698,7 @@ export class LocalNode {
|
|
|
699
698
|
try {
|
|
700
699
|
coValue = this.expectCoValueLoaded(id, expectation);
|
|
701
700
|
} catch (e) {
|
|
702
|
-
return
|
|
703
|
-
type: "ErrorLoadingCoValueCore",
|
|
704
|
-
expectation,
|
|
705
|
-
id,
|
|
706
|
-
error: e,
|
|
707
|
-
} satisfies LoadCoValueCoreError);
|
|
701
|
+
return { value: undefined, error: e };
|
|
708
702
|
}
|
|
709
703
|
|
|
710
704
|
if (
|
|
@@ -714,14 +708,15 @@ export class LocalNode {
|
|
|
714
708
|
!("type" in coValue.verified.header.meta) ||
|
|
715
709
|
coValue.verified.header.meta.type !== "account"
|
|
716
710
|
) {
|
|
717
|
-
return
|
|
718
|
-
|
|
719
|
-
expectation,
|
|
720
|
-
|
|
721
|
-
} satisfies UnexpectedlyNotAccountError);
|
|
711
|
+
return {
|
|
712
|
+
value: undefined,
|
|
713
|
+
error: new Error(`Unexpectedly not account: ${expectation}`),
|
|
714
|
+
};
|
|
722
715
|
}
|
|
723
716
|
|
|
724
|
-
|
|
717
|
+
const account = coValue.getCurrentContent() as RawAccount;
|
|
718
|
+
|
|
719
|
+
return { value: account.currentAgentID(), error: undefined };
|
|
725
720
|
}
|
|
726
721
|
|
|
727
722
|
createGroup(
|