cojson 0.18.26 → 0.18.28
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/PeerKnownStates.d.ts +4 -3
- package/dist/PeerKnownStates.d.ts.map +1 -1
- package/dist/PeerKnownStates.js +27 -18
- package/dist/PeerKnownStates.js.map +1 -1
- package/dist/PeerState.d.ts +3 -2
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js.map +1 -1
- package/dist/SyncStateManager.d.ts +2 -2
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +2 -10
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueContentMessage.d.ts +1 -1
- package/dist/coValueContentMessage.d.ts.map +1 -1
- package/dist/coValueContentMessage.js +1 -1
- package/dist/coValueContentMessage.js.map +1 -1
- package/dist/coValueCore/SessionMap.d.ts +6 -3
- package/dist/coValueCore/SessionMap.d.ts.map +1 -1
- package/dist/coValueCore/SessionMap.js +41 -8
- package/dist/coValueCore/SessionMap.js.map +1 -1
- package/dist/coValueCore/branching.d.ts +5 -4
- package/dist/coValueCore/branching.d.ts.map +1 -1
- package/dist/coValueCore/branching.js +22 -4
- package/dist/coValueCore/branching.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +29 -25
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +163 -126
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts +3 -0
- package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts.map +1 -0
- package/dist/coValueCore/decryptTransactionChangesAndMeta.js +34 -0
- package/dist/coValueCore/decryptTransactionChangesAndMeta.js.map +1 -0
- package/dist/coValueCore/verifiedState.d.ts +12 -6
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +28 -56
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.d.ts.map +1 -1
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/exports.d.ts +3 -2
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +2 -1
- package/dist/exports.js.map +1 -1
- package/dist/knownState.d.ts +58 -2
- package/dist/knownState.d.ts.map +1 -1
- package/dist/knownState.js +79 -5
- package/dist/knownState.js.map +1 -1
- package/dist/localNode.js +1 -1
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +18 -20
- package/dist/permissions.js.map +1 -1
- package/dist/storage/knownState.d.ts +1 -1
- package/dist/storage/knownState.d.ts.map +1 -1
- package/dist/storage/knownState.js +2 -3
- package/dist/storage/knownState.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +2 -1
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +5 -6
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts +2 -1
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +5 -5
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/types.d.ts +2 -1
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/sync.d.ts +2 -12
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +9 -38
- package/dist/sync.js.map +1 -1
- package/dist/tests/PeerKnownStates.test.js +1 -1
- package/dist/tests/PeerKnownStates.test.js.map +1 -1
- package/dist/tests/PeerState.test.js +19 -0
- package/dist/tests/PeerState.test.js.map +1 -1
- package/dist/tests/PureJSCrypto.test.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.js +1 -1
- package/dist/tests/StorageApiAsync.test.js.map +1 -1
- package/dist/tests/StorageApiSync.test.js +1 -2
- package/dist/tests/StorageApiSync.test.js.map +1 -1
- package/dist/tests/StoreQueue.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +1 -1
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/branching.test.js +237 -28
- package/dist/tests/branching.test.js.map +1 -1
- package/dist/tests/coValueContentMessage.test.js +1 -1
- package/dist/tests/coValueContentMessage.test.js.map +1 -1
- package/dist/tests/coValueCore.loadFromStorage.test.d.ts +2 -0
- package/dist/tests/coValueCore.loadFromStorage.test.d.ts.map +1 -0
- package/dist/tests/coValueCore.loadFromStorage.test.js +395 -0
- package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -0
- package/dist/tests/coValueCore.loadingState.test.d.ts +2 -0
- package/dist/tests/coValueCore.loadingState.test.d.ts.map +1 -0
- package/dist/tests/{coValueCoreLoadingState.test.js → coValueCore.loadingState.test.js} +4 -12
- package/dist/tests/coValueCore.loadingState.test.js.map +1 -0
- package/dist/tests/coValueCore.test.js +30 -5
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/knownState.test.d.ts +2 -0
- package/dist/tests/knownState.test.d.ts.map +1 -0
- package/dist/tests/knownState.test.js +510 -0
- package/dist/tests/knownState.test.js.map +1 -0
- package/dist/tests/messagesTestUtils.d.ts.map +1 -1
- package/dist/tests/messagesTestUtils.js.map +1 -1
- package/dist/tests/priority.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +4 -34
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts +7 -1
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +12 -0
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +3 -3
- package/src/PeerKnownStates.ts +36 -22
- package/src/PeerState.ts +2 -1
- package/src/SyncStateManager.ts +4 -17
- package/src/coValueContentMessage.ts +2 -1
- package/src/coValueCore/SessionMap.ts +66 -11
- package/src/coValueCore/branching.ts +37 -13
- package/src/coValueCore/coValueCore.ts +224 -177
- package/src/coValueCore/decryptTransactionChangesAndMeta.ts +56 -0
- package/src/coValueCore/verifiedState.ts +32 -64
- package/src/coValues/coMap.ts +1 -5
- package/src/coValues/coStream.ts +1 -5
- package/src/exports.ts +2 -2
- package/src/knownState.ts +118 -12
- package/src/localNode.ts +1 -1
- package/src/permissions.ts +21 -22
- package/src/storage/knownState.ts +9 -3
- package/src/storage/storageAsync.ts +15 -7
- package/src/storage/storageSync.ts +16 -8
- package/src/storage/types.ts +2 -1
- package/src/sync.ts +14 -60
- package/src/tests/PeerKnownStates.test.ts +1 -1
- package/src/tests/PeerState.test.ts +29 -3
- package/src/tests/PureJSCrypto.test.ts +0 -1
- package/src/tests/StorageApiAsync.test.ts +3 -6
- package/src/tests/StorageApiSync.test.ts +2 -6
- package/src/tests/StoreQueue.test.ts +3 -2
- package/src/tests/SyncStateManager.test.ts +1 -1
- package/src/tests/branching.test.ts +392 -45
- package/src/tests/coValueContentMessage.test.ts +2 -2
- package/src/tests/coValueCore.loadFromStorage.test.ts +540 -0
- package/src/tests/{coValueCoreLoadingState.test.ts → coValueCore.loadingState.test.ts} +3 -16
- package/src/tests/coValueCore.test.ts +40 -5
- package/src/tests/knownState.test.ts +665 -0
- package/src/tests/messagesTestUtils.ts +2 -1
- package/src/tests/priority.test.ts +0 -2
- package/src/tests/sync.mesh.test.ts +11 -38
- package/src/tests/sync.storage.test.ts +0 -1
- package/src/tests/sync.upload.test.ts +0 -1
- package/src/tests/testUtils.ts +22 -2
- package/dist/coValueCore/decodeTransactionChangesAndMeta.d.ts +0 -3
- package/dist/coValueCore/decodeTransactionChangesAndMeta.d.ts.map +0 -1
- package/dist/coValueCore/decodeTransactionChangesAndMeta.js +0 -59
- package/dist/coValueCore/decodeTransactionChangesAndMeta.js.map +0 -1
- package/dist/tests/coValueCoreLoadingState.test.d.ts +0 -2
- package/dist/tests/coValueCoreLoadingState.test.d.ts.map +0 -1
- package/dist/tests/coValueCoreLoadingState.test.js.map +0 -1
- package/src/coValueCore/decodeTransactionChangesAndMeta.ts +0 -81
|
@@ -2,7 +2,6 @@ import { Result, err, ok } from "neverthrow";
|
|
|
2
2
|
import { ControlledAccountOrAgent } from "../coValues/account.js";
|
|
3
3
|
import type {
|
|
4
4
|
CryptoProvider,
|
|
5
|
-
Hash,
|
|
6
5
|
KeyID,
|
|
7
6
|
KeySecret,
|
|
8
7
|
SessionLogImpl,
|
|
@@ -10,12 +9,17 @@ import type {
|
|
|
10
9
|
SignerID,
|
|
11
10
|
} from "../crypto/crypto.js";
|
|
12
11
|
import { RawCoID, SessionID } from "../ids.js";
|
|
13
|
-
import { parseJSON,
|
|
12
|
+
import { parseJSON, Stringified } from "../jsonStringify.js";
|
|
14
13
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
15
|
-
import { CoValueKnownState } from "../sync.js";
|
|
16
14
|
import { TryAddTransactionsError } from "./coValueCore.js";
|
|
17
15
|
import { Transaction } from "./verifiedState.js";
|
|
18
16
|
import { exceedsRecommendedSize } from "../coValueContentMessage.js";
|
|
17
|
+
import {
|
|
18
|
+
CoValueKnownState,
|
|
19
|
+
KnownStateSessions,
|
|
20
|
+
updateSessionCounter,
|
|
21
|
+
cloneKnownState,
|
|
22
|
+
} from "../knownState.js";
|
|
19
23
|
|
|
20
24
|
export type SessionLog = {
|
|
21
25
|
signerID?: SignerID;
|
|
@@ -24,15 +28,31 @@ export type SessionLog = {
|
|
|
24
28
|
lastSignature: Signature | undefined;
|
|
25
29
|
signatureAfter: { [txIdx: number]: Signature | undefined };
|
|
26
30
|
txSizeSinceLastInbetweenSignature: number;
|
|
31
|
+
sessionID: SessionID;
|
|
27
32
|
};
|
|
28
33
|
|
|
29
34
|
export class SessionMap {
|
|
30
35
|
sessions: Map<SessionID, SessionLog> = new Map();
|
|
31
36
|
|
|
37
|
+
// Known state related properies, mutated when adding transactions to the session map
|
|
38
|
+
knownState: CoValueKnownState = { id: this.id, header: true, sessions: {} };
|
|
39
|
+
knownStateWithStreaming: CoValueKnownState | undefined;
|
|
40
|
+
streamingKnownState?: KnownStateSessions;
|
|
41
|
+
|
|
32
42
|
constructor(
|
|
33
43
|
private readonly id: RawCoID,
|
|
34
44
|
private readonly crypto: CryptoProvider,
|
|
35
|
-
|
|
45
|
+
streamingKnownState?: KnownStateSessions,
|
|
46
|
+
) {
|
|
47
|
+
if (streamingKnownState) {
|
|
48
|
+
this.streamingKnownState = { ...streamingKnownState };
|
|
49
|
+
this.knownStateWithStreaming = {
|
|
50
|
+
id: this.id,
|
|
51
|
+
header: true,
|
|
52
|
+
sessions: { ...streamingKnownState },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
36
56
|
|
|
37
57
|
get(sessionID: SessionID): SessionLog | undefined {
|
|
38
58
|
return this.sessions.get(sessionID);
|
|
@@ -51,6 +71,7 @@ export class SessionMap {
|
|
|
51
71
|
lastSignature: undefined,
|
|
52
72
|
signatureAfter: {},
|
|
53
73
|
txSizeSinceLastInbetweenSignature: 0,
|
|
74
|
+
sessionID,
|
|
54
75
|
};
|
|
55
76
|
this.sessions.set(sessionID, sessionLog);
|
|
56
77
|
}
|
|
@@ -164,18 +185,43 @@ export class SessionMap {
|
|
|
164
185
|
0,
|
|
165
186
|
);
|
|
166
187
|
|
|
188
|
+
const transactionsCount = sessionLog.transactions.length;
|
|
189
|
+
|
|
167
190
|
if (exceedsRecommendedSize(sessionLog.txSizeSinceLastInbetweenSignature)) {
|
|
168
|
-
sessionLog.signatureAfter[
|
|
191
|
+
sessionLog.signatureAfter[transactionsCount - 1] = signature;
|
|
169
192
|
sessionLog.txSizeSinceLastInbetweenSignature = 0;
|
|
170
193
|
}
|
|
171
|
-
}
|
|
172
194
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
195
|
+
// Update the known state with the new transactions count
|
|
196
|
+
updateSessionCounter(
|
|
197
|
+
this.knownState.sessions,
|
|
198
|
+
sessionLog.sessionID,
|
|
199
|
+
transactionsCount,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// Check if the updated session matched the streaming state
|
|
203
|
+
// If so, we can delete the session from the streaming state to mark it as synced
|
|
204
|
+
if (this.streamingKnownState) {
|
|
205
|
+
const streamingCount = this.streamingKnownState[sessionLog.sessionID];
|
|
206
|
+
if (streamingCount && streamingCount <= transactionsCount) {
|
|
207
|
+
delete this.streamingKnownState[sessionLog.sessionID];
|
|
208
|
+
|
|
209
|
+
if (Object.keys(this.streamingKnownState).length === 0) {
|
|
210
|
+
// Mark the streaming as done by deleting the streaming statuses
|
|
211
|
+
this.streamingKnownState = undefined;
|
|
212
|
+
this.knownStateWithStreaming = undefined;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (this.knownStateWithStreaming) {
|
|
218
|
+
// Update the streaming known state with the new transactions count
|
|
219
|
+
updateSessionCounter(
|
|
220
|
+
this.knownStateWithStreaming.sessions,
|
|
221
|
+
sessionLog.sessionID,
|
|
222
|
+
transactionsCount,
|
|
223
|
+
);
|
|
177
224
|
}
|
|
178
|
-
return { id: this.id, header: true, sessions };
|
|
179
225
|
}
|
|
180
226
|
|
|
181
227
|
decryptTransaction(
|
|
@@ -244,9 +290,18 @@ export class SessionMap {
|
|
|
244
290
|
txSizeSinceLastInbetweenSignature:
|
|
245
291
|
sessionLog.txSizeSinceLastInbetweenSignature,
|
|
246
292
|
signerID: sessionLog.signerID,
|
|
293
|
+
sessionID,
|
|
247
294
|
});
|
|
248
295
|
}
|
|
249
296
|
|
|
297
|
+
clone.streamingKnownState = this.streamingKnownState
|
|
298
|
+
? { ...this.streamingKnownState }
|
|
299
|
+
: undefined;
|
|
300
|
+
clone.knownState = cloneKnownState(this.knownState);
|
|
301
|
+
clone.knownStateWithStreaming = this.knownStateWithStreaming
|
|
302
|
+
? cloneKnownState(this.knownStateWithStreaming)
|
|
303
|
+
: undefined;
|
|
304
|
+
|
|
250
305
|
return clone;
|
|
251
306
|
}
|
|
252
307
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { logger, type CoValueCore } from "../exports.js";
|
|
2
2
|
import type { RawCoID, SessionID } from "../ids.js";
|
|
3
3
|
import { type AvailableCoValueCore, idforHeader } from "./coValueCore.js";
|
|
4
4
|
import type { CoValueHeader } from "./verifiedState.js";
|
|
5
|
-
import
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
combineKnownStateSessions,
|
|
7
|
+
KnownStateSessions,
|
|
8
|
+
} from "../knownState.js";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Commit to identify the starting point of the branch
|
|
@@ -11,7 +13,7 @@ import { combineKnownStateSessions } from "../knownState.js";
|
|
|
11
13
|
* In case of clonflicts, the first commit of this kind is considered the source of truth
|
|
12
14
|
*/
|
|
13
15
|
export type BranchStartCommit = {
|
|
14
|
-
from:
|
|
16
|
+
from: KnownStateSessions;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -27,6 +29,7 @@ export type BranchPointerCommit = {
|
|
|
27
29
|
*/
|
|
28
30
|
export type MergedTransactionMetadata = {
|
|
29
31
|
mi: number; // Transaction index and marker of a merge commit
|
|
32
|
+
t?: number; // The difference between the current time and the madeAt value of the original transaction. Used to calculate the original madeAt of the transaction, stored this way to reduce the size of the meta information.
|
|
30
33
|
s?: SessionID;
|
|
31
34
|
b?: RawCoID;
|
|
32
35
|
};
|
|
@@ -35,7 +38,7 @@ export type MergedTransactionMetadata = {
|
|
|
35
38
|
* Merge commit located in a branch to track how many transactions have already been merged
|
|
36
39
|
*/
|
|
37
40
|
export type MergeCommit = {
|
|
38
|
-
merged:
|
|
41
|
+
merged: KnownStateSessions;
|
|
39
42
|
branch: RawCoID;
|
|
40
43
|
};
|
|
41
44
|
|
|
@@ -142,6 +145,20 @@ export function createBranch(
|
|
|
142
145
|
return coValue;
|
|
143
146
|
}
|
|
144
147
|
|
|
148
|
+
const myRole = coValue.safeGetGroup()?.myRole();
|
|
149
|
+
|
|
150
|
+
// We allow branch creation to accounts with at least read access to the source group
|
|
151
|
+
if (!myRole || (myRole === "reader" && !ownerId)) {
|
|
152
|
+
logger.warn(
|
|
153
|
+
"Trying to create a branch without enough access rights, returning the source coValue",
|
|
154
|
+
);
|
|
155
|
+
return coValue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Accounts without write access store the branch pointer unencrypted to make it possible to handle it as a special case
|
|
159
|
+
// in the permissions checks
|
|
160
|
+
const privacy = myRole === "reader" ? "trusting" : "private";
|
|
161
|
+
|
|
145
162
|
const header = getBranchHeader({
|
|
146
163
|
type: coValue.verified.header.type,
|
|
147
164
|
branchName: name,
|
|
@@ -158,7 +175,7 @@ export function createBranch(
|
|
|
158
175
|
} satisfies BranchStartCommit);
|
|
159
176
|
|
|
160
177
|
// Create a branch pointer, to identify that we created a branch
|
|
161
|
-
coValue.makeTransaction([],
|
|
178
|
+
coValue.makeTransaction([], privacy, {
|
|
162
179
|
branch: name,
|
|
163
180
|
ownerId,
|
|
164
181
|
} satisfies BranchPointerCommit);
|
|
@@ -213,13 +230,10 @@ export function mergeBranch(branch: CoValueCore): CoValueCore {
|
|
|
213
230
|
|
|
214
231
|
// Look for previous merge commits, to see which transactions needs to be merged
|
|
215
232
|
// Done mostly for performance reasons, as we could merge all the transactions every time and nothing would change
|
|
216
|
-
let mergedTransactions = {} as
|
|
233
|
+
let mergedTransactions = {} as KnownStateSessions;
|
|
217
234
|
for (const item of target.getMergeCommits()) {
|
|
218
235
|
if (item.branch === branch.id) {
|
|
219
|
-
mergedTransactions
|
|
220
|
-
mergedTransactions,
|
|
221
|
-
item.merged,
|
|
222
|
-
);
|
|
236
|
+
combineKnownStateSessions(mergedTransactions, item.merged);
|
|
223
237
|
}
|
|
224
238
|
}
|
|
225
239
|
|
|
@@ -242,12 +256,21 @@ export function mergeBranch(branch: CoValueCore): CoValueCore {
|
|
|
242
256
|
// To reduce the cost of the meta we skip the repeated information
|
|
243
257
|
let lastSessionId: string | undefined = undefined;
|
|
244
258
|
let lastBranchId: string | undefined = undefined;
|
|
259
|
+
let lastOriginalMadeAt: number = 0;
|
|
260
|
+
|
|
261
|
+
const now = Date.now();
|
|
245
262
|
|
|
246
263
|
for (const tx of branchValidTransactions) {
|
|
247
264
|
const mergeMeta: MergedTransactionMetadata = {
|
|
248
265
|
mi: tx.txID.txIndex,
|
|
249
266
|
};
|
|
250
267
|
|
|
268
|
+
// We compress the original made at, to reduce the size of the meta information
|
|
269
|
+
if (tx.madeAt !== lastOriginalMadeAt) {
|
|
270
|
+
// Storing the diff with madeAt to consume less bytes in the meta information
|
|
271
|
+
mergeMeta.t = now - tx.madeAt;
|
|
272
|
+
}
|
|
273
|
+
|
|
251
274
|
if (lastSessionId !== tx.txID.sessionID) {
|
|
252
275
|
mergeMeta.s = tx.txID.sessionID;
|
|
253
276
|
}
|
|
@@ -256,16 +279,17 @@ export function mergeBranch(branch: CoValueCore): CoValueCore {
|
|
|
256
279
|
mergeMeta.b = tx.txID.branch;
|
|
257
280
|
}
|
|
258
281
|
|
|
259
|
-
target.makeTransaction(tx.changes, tx.tx.privacy, mergeMeta,
|
|
282
|
+
target.makeTransaction(tx.changes, tx.tx.privacy, mergeMeta, now);
|
|
260
283
|
lastSessionId = tx.txID.sessionID;
|
|
261
284
|
lastBranchId = tx.txID.branch;
|
|
285
|
+
lastOriginalMadeAt = tx.madeAt;
|
|
262
286
|
}
|
|
263
287
|
|
|
264
288
|
// Track the merged transactions for the branch, so future merges will know which transactions have already been merged
|
|
265
289
|
// Store only the diff of sessions between the branch and already merged transactions
|
|
266
290
|
const currentSessions = branch.knownState().sessions;
|
|
267
291
|
const prevMergedSessions = mergedTransactions;
|
|
268
|
-
const diff = {} as
|
|
292
|
+
const diff = {} as KnownStateSessions;
|
|
269
293
|
|
|
270
294
|
for (const [sessionId, count] of Object.entries(currentSessions) as [
|
|
271
295
|
SessionID,
|