cojson 0.7.0-alpha.7 → 0.7.0

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.
Files changed (113) hide show
  1. package/.eslintrc.cjs +3 -2
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +3 -30
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +1106 -0
  6. package/CHANGELOG.md +98 -0
  7. package/README.md +3 -1
  8. package/dist/base64url.test.js +25 -0
  9. package/dist/base64url.test.js.map +1 -0
  10. package/dist/coValueCore.js +60 -37
  11. package/dist/coValueCore.js.map +1 -1
  12. package/dist/coValues/account.js +16 -15
  13. package/dist/coValues/account.js.map +1 -1
  14. package/dist/coValues/coList.js +1 -1
  15. package/dist/coValues/coList.js.map +1 -1
  16. package/dist/coValues/coMap.js +17 -8
  17. package/dist/coValues/coMap.js.map +1 -1
  18. package/dist/coValues/group.js +13 -14
  19. package/dist/coValues/group.js.map +1 -1
  20. package/dist/coreToCoValue.js.map +1 -1
  21. package/dist/crypto/PureJSCrypto.js +89 -0
  22. package/dist/crypto/PureJSCrypto.js.map +1 -0
  23. package/dist/crypto/WasmCrypto.js +127 -0
  24. package/dist/crypto/WasmCrypto.js.map +1 -0
  25. package/dist/crypto/crypto.js +151 -0
  26. package/dist/crypto/crypto.js.map +1 -0
  27. package/dist/ids.js +4 -2
  28. package/dist/ids.js.map +1 -1
  29. package/dist/index.js +6 -8
  30. package/dist/index.js.map +1 -1
  31. package/dist/jsonStringify.js.map +1 -1
  32. package/dist/localNode.js +41 -38
  33. package/dist/localNode.js.map +1 -1
  34. package/dist/permissions.js +6 -6
  35. package/dist/permissions.js.map +1 -1
  36. package/dist/storage/FileSystem.js +61 -0
  37. package/dist/storage/FileSystem.js.map +1 -0
  38. package/dist/storage/chunksAndKnownStates.js +97 -0
  39. package/dist/storage/chunksAndKnownStates.js.map +1 -0
  40. package/dist/storage/index.js +265 -0
  41. package/dist/storage/index.js.map +1 -0
  42. package/dist/sync.js +29 -25
  43. package/dist/sync.js.map +1 -1
  44. package/dist/tests/account.test.js +58 -0
  45. package/dist/tests/account.test.js.map +1 -0
  46. package/dist/tests/coList.test.js +76 -0
  47. package/dist/tests/coList.test.js.map +1 -0
  48. package/dist/tests/coMap.test.js +136 -0
  49. package/dist/tests/coMap.test.js.map +1 -0
  50. package/dist/tests/coStream.test.js +172 -0
  51. package/dist/tests/coStream.test.js.map +1 -0
  52. package/dist/tests/coValueCore.test.js +114 -0
  53. package/dist/tests/coValueCore.test.js.map +1 -0
  54. package/dist/tests/crypto.test.js +118 -0
  55. package/dist/tests/crypto.test.js.map +1 -0
  56. package/dist/tests/cryptoImpl.test.js +113 -0
  57. package/dist/tests/cryptoImpl.test.js.map +1 -0
  58. package/dist/tests/group.test.js +34 -0
  59. package/dist/tests/group.test.js.map +1 -0
  60. package/dist/tests/permissions.test.js +1060 -0
  61. package/dist/tests/permissions.test.js.map +1 -0
  62. package/dist/tests/sync.test.js +816 -0
  63. package/dist/tests/sync.test.js.map +1 -0
  64. package/dist/tests/testUtils.js +12 -11
  65. package/dist/tests/testUtils.js.map +1 -1
  66. package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  67. package/dist/typeUtils/isAccountID.js.map +1 -1
  68. package/dist/typeUtils/isCoValue.js.map +1 -1
  69. package/package.json +14 -27
  70. package/src/base64url.test.ts +6 -5
  71. package/src/coValue.ts +1 -1
  72. package/src/coValueCore.ts +179 -126
  73. package/src/coValues/account.ts +30 -32
  74. package/src/coValues/coList.ts +11 -11
  75. package/src/coValues/coMap.ts +27 -17
  76. package/src/coValues/coStream.ts +17 -17
  77. package/src/coValues/group.ts +93 -109
  78. package/src/coreToCoValue.ts +5 -2
  79. package/src/crypto/PureJSCrypto.ts +200 -0
  80. package/src/crypto/WasmCrypto.ts +259 -0
  81. package/src/crypto/crypto.ts +336 -0
  82. package/src/ids.ts +8 -7
  83. package/src/index.ts +24 -24
  84. package/src/jsonStringify.ts +6 -4
  85. package/src/jsonValue.ts +2 -2
  86. package/src/localNode.ts +103 -109
  87. package/src/media.ts +3 -3
  88. package/src/permissions.ts +19 -21
  89. package/src/storage/FileSystem.ts +152 -0
  90. package/src/storage/chunksAndKnownStates.ts +139 -0
  91. package/src/storage/index.ts +479 -0
  92. package/src/streamUtils.ts +12 -12
  93. package/src/sync.ts +79 -63
  94. package/src/tests/account.test.ts +15 -15
  95. package/src/tests/coList.test.ts +94 -0
  96. package/src/tests/coMap.test.ts +162 -0
  97. package/src/tests/coStream.test.ts +246 -0
  98. package/src/tests/coValueCore.test.ts +36 -37
  99. package/src/tests/crypto.test.ts +66 -72
  100. package/src/tests/cryptoImpl.test.ts +183 -0
  101. package/src/tests/group.test.ts +16 -17
  102. package/src/tests/permissions.test.ts +269 -283
  103. package/src/tests/sync.test.ts +122 -123
  104. package/src/tests/testUtils.ts +24 -21
  105. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +1 -2
  106. package/src/typeUtils/expectGroup.ts +1 -1
  107. package/src/typeUtils/isAccountID.ts +0 -1
  108. package/src/typeUtils/isCoValue.ts +1 -2
  109. package/tsconfig.json +0 -1
  110. package/dist/crypto.js +0 -254
  111. package/dist/crypto.js.map +0 -1
  112. package/src/crypto.ts +0 -484
  113. package/src/tests/coValue.test.ts +0 -497
@@ -5,17 +5,9 @@ import {
5
5
  KeySecret,
6
6
  Signature,
7
7
  StreamingHash,
8
- unseal,
9
- shortHash,
10
- sign,
11
- verify,
12
- encryptForTransaction,
13
8
  KeyID,
14
- decryptKeySecret,
15
- getAgentSignerID,
16
- getAgentSealerID,
17
- decryptRawForTransaction,
18
- } from "./crypto.js";
9
+ CryptoProvider,
10
+ } from "./crypto/crypto.js";
19
11
  import { JsonObject, JsonValue } from "./jsonValue.js";
20
12
  import { base58 } from "@scure/base";
21
13
  import {
@@ -44,15 +36,18 @@ export type CoValueHeader = {
44
36
  uniqueness: `z${string}` | null;
45
37
  };
46
38
 
47
- export function idforHeader(header: CoValueHeader): RawCoID {
48
- const hash = shortHash(header);
39
+ export function idforHeader(
40
+ header: CoValueHeader,
41
+ crypto: CryptoProvider,
42
+ ): RawCoID {
43
+ const hash = crypto.shortHash(header);
49
44
  return `co_z${hash.slice("shortHash_z".length)}`;
50
45
  }
51
46
 
52
47
  export function newRandomSessionID(accountID: AccountID | AgentID): SessionID {
53
48
  return `${accountID}_session_z${base58.encode(
54
49
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
- (globalThis as any).crypto.getRandomValues(new Uint8Array(8))
50
+ (globalThis as any).crypto.getRandomValues(new Uint8Array(8)),
56
51
  )}`;
57
52
  }
58
53
 
@@ -93,6 +88,7 @@ const readKeyCache = new WeakMap<CoValueCore, { [id: KeyID]: KeySecret }>();
93
88
  export class CoValueCore {
94
89
  id: RawCoID;
95
90
  node: LocalNode;
91
+ crypto: CryptoProvider;
96
92
  header: CoValueHeader;
97
93
  _sessionLogs: Map<SessionID, SessionLog>;
98
94
  _cachedContent?: RawCoValue;
@@ -108,9 +104,10 @@ export class CoValueCore {
108
104
  constructor(
109
105
  header: CoValueHeader,
110
106
  node: LocalNode,
111
- internalInitSessions: Map<SessionID, SessionLog> = new Map()
107
+ internalInitSessions: Map<SessionID, SessionLog> = new Map(),
112
108
  ) {
113
- this.id = idforHeader(header);
109
+ this.crypto = node.crypto;
110
+ this.id = idforHeader(header, node.crypto);
114
111
  this.header = header;
115
112
  this._sessionLogs = internalInitSessions;
116
113
  this.node = node;
@@ -134,11 +131,11 @@ export class CoValueCore {
134
131
 
135
132
  testWithDifferentAccount(
136
133
  account: ControlledAccountOrAgent,
137
- currentSessionID: SessionID
134
+ currentSessionID: SessionID,
138
135
  ): CoValueCore {
139
136
  const newNode = this.node.testWithDifferentAccount(
140
137
  account,
141
- currentSessionID
138
+ currentSessionID,
142
139
  );
143
140
 
144
141
  return newNode.expectCoValueLoaded(this.id);
@@ -163,7 +160,7 @@ export class CoValueCore {
163
160
  [...this.sessionLogs.entries()].map(([k, v]) => [
164
161
  k,
165
162
  v.transactions.length,
166
- ])
163
+ ]),
167
164
  ),
168
165
  };
169
166
  }
@@ -178,7 +175,7 @@ export class CoValueCore {
178
175
  this.header.meta?.type === "account"
179
176
  ? (this.node.currentSessionID.replace(
180
177
  this.node.account.id,
181
- this.node.account.currentAgentID()
178
+ this.node.account.currentAgentID(),
182
179
  ) as SessionID)
183
180
  : this.node.currentSessionID;
184
181
 
@@ -192,19 +189,19 @@ export class CoValueCore {
192
189
  sessionID: SessionID,
193
190
  newTransactions: Transaction[],
194
191
  givenExpectedNewHash: Hash | undefined,
195
- newSignature: Signature
192
+ newSignature: Signature,
196
193
  ): boolean {
197
- const signerID = getAgentSignerID(
194
+ const signerID = this.crypto.getAgentSignerID(
198
195
  this.node.resolveAccountAgent(
199
196
  accountOrAgentIDfromSessionID(sessionID),
200
- "Expected to know signer of transaction"
201
- )
197
+ "Expected to know signer of transaction",
198
+ ),
202
199
  );
203
200
 
204
201
  if (!signerID) {
205
202
  console.warn(
206
203
  "Unknown agent",
207
- accountOrAgentIDfromSessionID(sessionID)
204
+ accountOrAgentIDfromSessionID(sessionID),
208
205
  );
209
206
  return false;
210
207
  }
@@ -212,7 +209,7 @@ export class CoValueCore {
212
209
  // const beforeHash = performance.now();
213
210
  const { expectedNewHash, newStreamingHash } = this.expectedNewHashAfter(
214
211
  sessionID,
215
- newTransactions
212
+ newTransactions,
216
213
  );
217
214
  // const afterHash = performance.now();
218
215
  // console.log(
@@ -229,13 +226,13 @@ export class CoValueCore {
229
226
  }
230
227
 
231
228
  // const beforeVerify = performance.now();
232
- if (!verify(newSignature, expectedNewHash, signerID)) {
229
+ if (!this.crypto.verify(newSignature, expectedNewHash, signerID)) {
233
230
  console.warn(
234
231
  "Invalid signature in",
235
232
  this.id,
236
233
  newSignature,
237
234
  expectedNewHash,
238
- signerID
235
+ signerID,
239
236
  );
240
237
  return false;
241
238
  }
@@ -250,7 +247,8 @@ export class CoValueCore {
250
247
  newTransactions,
251
248
  newSignature,
252
249
  expectedNewHash,
253
- newStreamingHash
250
+ newStreamingHash,
251
+ "immediate",
254
252
  );
255
253
 
256
254
  return true;
@@ -260,7 +258,7 @@ export class CoValueCore {
260
258
  sessionID: SessionID,
261
259
  newTransactions: Transaction[],
262
260
  givenExpectedNewHash: Hash | undefined,
263
- newSignature: Signature
261
+ newSignature: Signature,
264
262
  ): Promise<boolean> {
265
263
  if (this.currentlyAsyncApplyingTxDone) {
266
264
  await this.currentlyAsyncApplyingTxDone;
@@ -271,23 +269,24 @@ export class CoValueCore {
271
269
  resolveDone = resolve;
272
270
  });
273
271
 
274
- const signerID = getAgentSignerID(
272
+ const signerID = this.crypto.getAgentSignerID(
275
273
  await this.node.resolveAccountAgentAsync(
276
274
  accountOrAgentIDfromSessionID(sessionID),
277
- "Expected to know signer of transaction"
278
- )
275
+ "Expected to know signer of transaction",
276
+ ),
279
277
  );
280
278
 
281
279
  if (!signerID) {
282
280
  console.warn(
283
281
  "Unknown agent",
284
- accountOrAgentIDfromSessionID(sessionID)
282
+ accountOrAgentIDfromSessionID(sessionID),
285
283
  );
286
284
  resolveDone();
287
285
  return false;
288
286
  }
289
287
 
290
- const nTxBefore = this.sessionLogs.get(sessionID)?.transactions.length ?? 0;
288
+ const nTxBefore =
289
+ this.sessionLogs.get(sessionID)?.transactions.length ?? 0;
291
290
 
292
291
  // const beforeHash = performance.now();
293
292
  const { expectedNewHash, newStreamingHash } =
@@ -298,7 +297,8 @@ export class CoValueCore {
298
297
  // afterHash - beforeHash
299
298
  // );
300
299
 
301
- const nTxAfter = this.sessionLogs.get(sessionID)?.transactions.length ?? 0;
300
+ const nTxAfter =
301
+ this.sessionLogs.get(sessionID)?.transactions.length ?? 0;
302
302
 
303
303
  if (nTxAfter !== nTxBefore) {
304
304
  const newTransactionLengthBefore = newTransactions.length;
@@ -320,30 +320,32 @@ export class CoValueCore {
320
320
  return false;
321
321
  }
322
322
 
323
- // const beforeVerify = performance.now();
324
- if (!verify(newSignature, expectedNewHash, signerID)) {
323
+ performance.mark("verifyStart" + this.id);
324
+ if (!this.crypto.verify(newSignature, expectedNewHash, signerID)) {
325
325
  console.warn(
326
326
  "Invalid signature in",
327
327
  this.id,
328
328
  newSignature,
329
329
  expectedNewHash,
330
- signerID
330
+ signerID,
331
331
  );
332
332
  resolveDone();
333
333
  return false;
334
334
  }
335
- // const afterVerify = performance.now();
336
- // console.log(
337
- // "Verify took",
338
- // afterVerify - beforeVerify
339
- // );
335
+ performance.mark("verifyEnd" + this.id);
336
+ performance.measure(
337
+ "verify" + this.id,
338
+ "verifyStart" + this.id,
339
+ "verifyEnd" + this.id,
340
+ );
340
341
 
341
342
  this.doAddTransactions(
342
343
  sessionID,
343
344
  newTransactions,
344
345
  newSignature,
345
346
  expectedNewHash,
346
- newStreamingHash
347
+ newStreamingHash,
348
+ "deferred",
347
349
  );
348
350
 
349
351
  resolveDone();
@@ -355,16 +357,19 @@ export class CoValueCore {
355
357
  newTransactions: Transaction[],
356
358
  newSignature: Signature,
357
359
  expectedNewHash: Hash,
358
- newStreamingHash: StreamingHash
360
+ newStreamingHash: StreamingHash,
361
+ notifyMode: "immediate" | "deferred",
359
362
  ) {
360
- const transactions = this.sessionLogs.get(sessionID)?.transactions ?? [];
363
+ const transactions =
364
+ this.sessionLogs.get(sessionID)?.transactions ?? [];
361
365
  transactions.push(...newTransactions);
362
366
 
363
- const signatureAfter = this.sessionLogs.get(sessionID)?.signatureAfter ?? {};
367
+ const signatureAfter =
368
+ this.sessionLogs.get(sessionID)?.signatureAfter ?? {};
364
369
 
365
370
  const lastInbetweenSignatureIdx = Object.keys(signatureAfter).reduce(
366
371
  (max, idx) => (parseInt(idx) > max ? parseInt(idx) : max),
367
- -1
372
+ -1,
368
373
  );
369
374
 
370
375
  const sizeOfTxsSinceLastInbetweenSignature = transactions
@@ -375,7 +380,7 @@ export class CoValueCore {
375
380
  (tx.privacy === "private"
376
381
  ? tx.encryptedChanges.length
377
382
  : tx.changes.length),
378
- 0
383
+ 0,
379
384
  );
380
385
 
381
386
  if (sizeOfTxsSinceLastInbetweenSignature > 100 * 1024) {
@@ -402,13 +407,33 @@ export class CoValueCore {
402
407
  this._cachedNewContentSinceEmpty = undefined;
403
408
 
404
409
  if (this.listeners.size > 0) {
405
- const content = this.getCurrentContent();
406
- for (const listener of this.listeners) {
407
- listener(content);
410
+ if (notifyMode === "immediate") {
411
+ const content = this.getCurrentContent();
412
+ for (const listener of this.listeners) {
413
+ listener(content);
414
+ }
415
+ } else {
416
+ if (!this.nextDeferredNotify) {
417
+ this.nextDeferredNotify = new Promise((resolve) => {
418
+ setTimeout(() => {
419
+ this.nextDeferredNotify = undefined;
420
+ this.deferredUpdates = 0;
421
+ const content = this.getCurrentContent();
422
+ for (const listener of this.listeners) {
423
+ listener(content);
424
+ }
425
+ resolve();
426
+ }, 0);
427
+ });
428
+ }
429
+ this.deferredUpdates++;
408
430
  }
409
431
  }
410
432
  }
411
433
 
434
+ deferredUpdates = 0;
435
+ nextDeferredNotify: Promise<void> | undefined;
436
+
412
437
  subscribe(listener: (content?: RawCoValue) => void): () => void {
413
438
  this.listeners.add(listener);
414
439
  listener(this.getCurrentContent());
@@ -420,11 +445,11 @@ export class CoValueCore {
420
445
 
421
446
  expectedNewHashAfter(
422
447
  sessionID: SessionID,
423
- newTransactions: Transaction[]
448
+ newTransactions: Transaction[],
424
449
  ): { expectedNewHash: Hash; newStreamingHash: StreamingHash } {
425
450
  const streamingHash =
426
451
  this.sessionLogs.get(sessionID)?.streamingHash.clone() ??
427
- new StreamingHash();
452
+ new StreamingHash(this.crypto);
428
453
  for (const transaction of newTransactions) {
429
454
  streamingHash.update(transaction);
430
455
  }
@@ -439,11 +464,11 @@ export class CoValueCore {
439
464
 
440
465
  async expectedNewHashAfterAsync(
441
466
  sessionID: SessionID,
442
- newTransactions: Transaction[]
467
+ newTransactions: Transaction[],
443
468
  ): Promise<{ expectedNewHash: Hash; newStreamingHash: StreamingHash }> {
444
469
  const streamingHash =
445
470
  this.sessionLogs.get(sessionID)?.streamingHash.clone() ??
446
- new StreamingHash();
471
+ new StreamingHash(this.crypto);
447
472
  let before = performance.now();
448
473
  for (const transaction of newTransactions) {
449
474
  streamingHash.update(transaction);
@@ -465,7 +490,7 @@ export class CoValueCore {
465
490
 
466
491
  makeTransaction(
467
492
  changes: JsonValue[],
468
- privacy: "private" | "trusting"
493
+ privacy: "private" | "trusting",
469
494
  ): boolean {
470
495
  const madeAt = Date.now();
471
496
 
@@ -476,14 +501,18 @@ export class CoValueCore {
476
501
 
477
502
  if (!keySecret) {
478
503
  throw new Error(
479
- "Can't make transaction without read key secret"
504
+ "Can't make transaction without read key secret",
480
505
  );
481
506
  }
482
507
 
483
- const encrypted = encryptForTransaction(changes, keySecret, {
484
- in: this.id,
485
- tx: this.nextTransactionID(),
486
- });
508
+ const encrypted = this.crypto.encryptForTransaction(
509
+ changes,
510
+ keySecret,
511
+ {
512
+ in: this.id,
513
+ tx: this.nextTransactionID(),
514
+ },
515
+ );
487
516
 
488
517
  this._decryptionCache[encrypted] = changes;
489
518
 
@@ -506,7 +535,7 @@ export class CoValueCore {
506
535
  this.header.meta?.type === "account"
507
536
  ? (this.node.currentSessionID.replace(
508
537
  this.node.account.id,
509
- this.node.account.currentAgentID()
538
+ this.node.account.currentAgentID(),
510
539
  ) as SessionID)
511
540
  : this.node.currentSessionID;
512
541
 
@@ -514,16 +543,16 @@ export class CoValueCore {
514
543
  transaction,
515
544
  ]);
516
545
 
517
- const signature = sign(
546
+ const signature = this.crypto.sign(
518
547
  this.node.account.currentSignerSecret(),
519
- expectedNewHash
548
+ expectedNewHash,
520
549
  );
521
550
 
522
551
  const success = this.tryAddTransactions(
523
552
  sessionID,
524
553
  [transaction],
525
554
  expectedNewHash,
526
- signature
555
+ signature,
527
556
  );
528
557
 
529
558
  if (success) {
@@ -533,7 +562,9 @@ export class CoValueCore {
533
562
  return success;
534
563
  }
535
564
 
536
- getCurrentContent(options?: { ignorePrivateTransactions: true }): RawCoValue {
565
+ getCurrentContent(options?: {
566
+ ignorePrivateTransactions: true;
567
+ }): RawCoValue {
537
568
  if (!options?.ignorePrivateTransactions && this._cachedContent) {
538
569
  return this._cachedContent;
539
570
  }
@@ -573,14 +604,15 @@ export class CoValueCore {
573
604
  this._decryptionCache[tx.encryptedChanges];
574
605
 
575
606
  if (!decrytedChanges) {
576
- const decryptedString = decryptRawForTransaction(
577
- tx.encryptedChanges,
578
- readKey,
579
- {
580
- in: this.id,
581
- tx: txID,
582
- }
583
- );
607
+ const decryptedString =
608
+ this.crypto.decryptRawForTransaction(
609
+ tx.encryptedChanges,
610
+ readKey,
611
+ {
612
+ in: this.id,
613
+ tx: txID,
614
+ },
615
+ );
584
616
  decrytedChanges =
585
617
  decryptedString && parseJSON(decryptedString);
586
618
  this._decryptionCache[tx.encryptedChanges] =
@@ -589,7 +621,7 @@ export class CoValueCore {
589
621
 
590
622
  if (!decrytedChanges) {
591
623
  console.error(
592
- "Failed to decrypt transaction despite having key"
624
+ "Failed to decrypt transaction despite having key",
593
625
  );
594
626
  return undefined;
595
627
  }
@@ -606,7 +638,7 @@ export class CoValueCore {
606
638
  (a, b) =>
607
639
  a.madeAt - b.madeAt ||
608
640
  (a.txID.sessionID < b.txID.sessionID ? -1 : 1) ||
609
- a.txID.txIndex - b.txID.txIndex
641
+ a.txID.txIndex - b.txID.txIndex,
610
642
  );
611
643
 
612
644
  return allTransactions;
@@ -634,7 +666,7 @@ export class CoValueCore {
634
666
  .getCurrentReadKey();
635
667
  } else {
636
668
  throw new Error(
637
- "Only groups or values owned by groups have read secrets"
669
+ "Only groups or values owned by groups have read secrets",
638
670
  );
639
671
  }
640
672
  }
@@ -658,7 +690,7 @@ export class CoValueCore {
658
690
  getUncachedReadKey(keyID: KeyID): KeySecret | undefined {
659
691
  if (this.header.ruleset.type === "group") {
660
692
  const content = expectGroup(
661
- this.getCurrentContent({ ignorePrivateTransactions: true })
693
+ this.getCurrentContent({ ignorePrivateTransactions: true }),
662
694
  );
663
695
 
664
696
  const keyForEveryone = content.get(`${keyID}_for_everyone`);
@@ -671,24 +703,24 @@ export class CoValueCore {
671
703
  : this.node.account.id;
672
704
 
673
705
  const lastReadyKeyEdit = content.lastEditAt(
674
- `${keyID}_for_${lookupAccountOrAgentID}`
706
+ `${keyID}_for_${lookupAccountOrAgentID}`,
675
707
  );
676
708
 
677
709
  if (lastReadyKeyEdit?.value) {
678
710
  const revealer = lastReadyKeyEdit.by;
679
711
  const revealerAgent = this.node.resolveAccountAgent(
680
712
  revealer,
681
- "Expected to know revealer"
713
+ "Expected to know revealer",
682
714
  );
683
715
 
684
- const secret = unseal(
716
+ const secret = this.crypto.unseal(
685
717
  lastReadyKeyEdit.value,
686
718
  this.node.account.currentSealerSecret(),
687
- getAgentSealerID(revealerAgent),
719
+ this.crypto.getAgentSealerID(revealerAgent),
688
720
  {
689
721
  in: this.id,
690
722
  tx: lastReadyKeyEdit.tx,
691
- }
723
+ },
692
724
  );
693
725
 
694
726
  if (secret) {
@@ -698,9 +730,9 @@ export class CoValueCore {
698
730
 
699
731
  // Try to find indirect revelation through previousKeys
700
732
 
701
- for (const val of content.keys()) {
702
- if (isKeyForKeyField(val) && val.startsWith(keyID)) {
703
- const encryptingKeyID = val.split("_for_")[1] as KeyID;
733
+ for (const co of content.keys()) {
734
+ if (isKeyForKeyField(co) && co.startsWith(keyID)) {
735
+ const encryptingKeyID = co.split("_for_")[1] as KeyID;
704
736
  const encryptingKeySecret =
705
737
  this.getReadKey(encryptingKeyID);
706
738
 
@@ -708,22 +740,22 @@ export class CoValueCore {
708
740
  continue;
709
741
  }
710
742
 
711
- const encryptedPreviousKey = content.get(val)!;
743
+ const encryptedPreviousKey = content.get(co)!;
712
744
 
713
- const secret = decryptKeySecret(
745
+ const secret = this.crypto.decryptKeySecret(
714
746
  {
715
747
  encryptedID: keyID,
716
748
  encryptingID: encryptingKeyID,
717
749
  encrypted: encryptedPreviousKey,
718
750
  },
719
- encryptingKeySecret
751
+ encryptingKeySecret,
720
752
  );
721
753
 
722
754
  if (secret) {
723
755
  return secret as KeySecret;
724
756
  } else {
725
757
  console.error(
726
- `Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`
758
+ `Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`,
727
759
  );
728
760
  }
729
761
  }
@@ -736,7 +768,7 @@ export class CoValueCore {
736
768
  .getReadKey(keyID);
737
769
  } else {
738
770
  throw new Error(
739
- "Only groups or values owned by groups have read secrets"
771
+ "Only groups or values owned by groups have read secrets",
740
772
  );
741
773
  }
742
774
  }
@@ -749,7 +781,7 @@ export class CoValueCore {
749
781
  return expectGroup(
750
782
  this.node
751
783
  .expectCoValueLoaded(this.header.ruleset.group)
752
- .getCurrentContent()
784
+ .getCurrentContent(),
753
785
  );
754
786
  }
755
787
 
@@ -758,7 +790,7 @@ export class CoValueCore {
758
790
  }
759
791
 
760
792
  newContentSince(
761
- knownState: CoValueKnownState | undefined
793
+ knownState: CoValueKnownState | undefined,
762
794
  ): NewContentMessage[] | undefined {
763
795
  const isKnownStateEmpty = !knownState?.header && !knownState?.sessions;
764
796
 
@@ -781,7 +813,11 @@ export class CoValueCore {
781
813
 
782
814
  let sessionsTodoAgain: Set<SessionID> | undefined | "first" = "first";
783
815
 
784
- while (sessionsTodoAgain === "first" || (sessionsTodoAgain?.size || 0 > 0)) {
816
+ while (
817
+ sessionsTodoAgain === "first" ||
818
+ sessionsTodoAgain?.size ||
819
+ 0 > 0
820
+ ) {
785
821
  if (sessionsTodoAgain === "first") {
786
822
  sessionsTodoAgain = undefined;
787
823
  }
@@ -795,13 +831,15 @@ export class CoValueCore {
795
831
  const nextKnownSignatureIdx = getNextKnownSignatureIdx(
796
832
  log,
797
833
  knownStateForSessionID,
798
- sentStateForSessionID
834
+ sentStateForSessionID,
799
835
  );
800
836
 
801
- const firstNewTxIdx = sentStateForSessionID ?? knownStateForSessionID ?? 0;
802
- const afterLastNewTxIdx = nextKnownSignatureIdx === undefined
803
- ? log.transactions.length
804
- : nextKnownSignatureIdx + 1;
837
+ const firstNewTxIdx =
838
+ sentStateForSessionID ?? knownStateForSessionID ?? 0;
839
+ const afterLastNewTxIdx =
840
+ nextKnownSignatureIdx === undefined
841
+ ? log.transactions.length
842
+ : nextKnownSignatureIdx + 1;
805
843
 
806
844
  const nNewTx = Math.max(0, afterLastNewTxIdx - firstNewTxIdx);
807
845
 
@@ -818,11 +856,16 @@ export class CoValueCore {
818
856
  }
819
857
 
820
858
  const oldPieceSize = pieceSize;
821
- for (let txIdx = firstNewTxIdx; txIdx < afterLastNewTxIdx; txIdx++) {
859
+ for (
860
+ let txIdx = firstNewTxIdx;
861
+ txIdx < afterLastNewTxIdx;
862
+ txIdx++
863
+ ) {
822
864
  const tx = log.transactions[txIdx]!;
823
- pieceSize += (tx.privacy === "private"
824
- ? tx.encryptedChanges.length
825
- : tx.changes.length);
865
+ pieceSize +=
866
+ tx.privacy === "private"
867
+ ? tx.encryptedChanges.length
868
+ : tx.changes.length;
826
869
  }
827
870
 
828
871
  if (pieceSize >= MAX_RECOMMENDED_TX_SIZE) {
@@ -839,31 +882,38 @@ export class CoValueCore {
839
882
  let sessionEntry = currentPiece.new[sessionID];
840
883
  if (!sessionEntry) {
841
884
  sessionEntry = {
842
- after: sentStateForSessionID ?? knownStateForSessionID ?? 0,
885
+ after:
886
+ sentStateForSessionID ??
887
+ knownStateForSessionID ??
888
+ 0,
843
889
  newTransactions: [],
844
890
  lastSignature: "WILL_BE_REPLACED" as Signature,
845
891
  };
846
892
  currentPiece.new[sessionID] = sessionEntry;
847
893
  }
848
894
 
849
- for (let txIdx = firstNewTxIdx; txIdx < afterLastNewTxIdx; txIdx++) {
895
+ for (
896
+ let txIdx = firstNewTxIdx;
897
+ txIdx < afterLastNewTxIdx;
898
+ txIdx++
899
+ ) {
850
900
  const tx = log.transactions[txIdx]!;
851
901
  sessionEntry.newTransactions.push(tx);
852
902
  }
853
903
 
854
-
855
904
  sessionEntry.lastSignature =
856
905
  nextKnownSignatureIdx === undefined
857
906
  ? log.lastSignature!
858
907
  : log.signatureAfter[nextKnownSignatureIdx]!;
859
908
 
860
909
  sentState[sessionID] =
861
- (sentStateForSessionID ?? knownStateForSessionID ?? 0) + nNewTx;
910
+ (sentStateForSessionID ?? knownStateForSessionID ?? 0) +
911
+ nNewTx;
862
912
  }
863
913
  }
864
914
 
865
915
  const piecesWithContent = pieces.filter(
866
- (piece) => Object.keys(piece.new).length > 0 || piece.header
916
+ (piece) => Object.keys(piece.new).length > 0 || piece.header,
867
917
  );
868
918
 
869
919
  if (piecesWithContent.length === 0) {
@@ -894,22 +944,22 @@ export class CoValueCore {
894
944
  .keys()
895
945
  .filter((k): k is AccountID => k.startsWith("co_"))
896
946
  : this.header.ruleset.type === "ownedByGroup"
897
- ? [
898
- this.header.ruleset.group,
899
- ...new Set(
900
- [...this.sessionLogs.keys()]
901
- .map((sessionID) =>
902
- accountOrAgentIDfromSessionID(
903
- sessionID as SessionID
904
- )
905
- )
906
- .filter(
907
- (session): session is AccountID =>
908
- isAccountID(session) && session !== this.id
909
- )
910
- ),
911
- ]
912
- : [];
947
+ ? [
948
+ this.header.ruleset.group,
949
+ ...new Set(
950
+ [...this.sessionLogs.keys()]
951
+ .map((sessionID) =>
952
+ accountOrAgentIDfromSessionID(
953
+ sessionID as SessionID,
954
+ ),
955
+ )
956
+ .filter(
957
+ (session): session is AccountID =>
958
+ isAccountID(session) && session !== this.id,
959
+ ),
960
+ ),
961
+ ]
962
+ : [];
913
963
  }
914
964
  }
915
965
 
@@ -921,5 +971,8 @@ function getNextKnownSignatureIdx(
921
971
  return Object.keys(log.signatureAfter)
922
972
  .map(Number)
923
973
  .sort((a, b) => a - b)
924
- .find((idx) => idx >= (sentStateForSessionID ?? knownStateForSessionID ?? -1));
974
+ .find(
975
+ (idx) =>
976
+ idx >= (sentStateForSessionID ?? knownStateForSessionID ?? -1),
977
+ );
925
978
  }