cojson 0.17.8 → 0.17.10

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 (73) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +13 -0
  3. package/dist/coValueCore/SessionMap.d.ts +44 -0
  4. package/dist/coValueCore/SessionMap.d.ts.map +1 -0
  5. package/dist/coValueCore/SessionMap.js +118 -0
  6. package/dist/coValueCore/SessionMap.js.map +1 -0
  7. package/dist/coValueCore/coValueCore.d.ts +1 -0
  8. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  9. package/dist/coValueCore/coValueCore.js +40 -61
  10. package/dist/coValueCore/coValueCore.js.map +1 -1
  11. package/dist/coValueCore/verifiedState.d.ts +14 -18
  12. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  13. package/dist/coValueCore/verifiedState.js +23 -86
  14. package/dist/coValueCore/verifiedState.js.map +1 -1
  15. package/dist/coValues/account.d.ts +4 -0
  16. package/dist/coValues/account.d.ts.map +1 -1
  17. package/dist/coValues/account.js +24 -4
  18. package/dist/coValues/account.js.map +1 -1
  19. package/dist/crypto/PureJSCrypto.d.ts +31 -3
  20. package/dist/crypto/PureJSCrypto.d.ts.map +1 -1
  21. package/dist/crypto/PureJSCrypto.js +112 -0
  22. package/dist/crypto/PureJSCrypto.js.map +1 -1
  23. package/dist/crypto/WasmCrypto.d.ts +23 -4
  24. package/dist/crypto/WasmCrypto.d.ts.map +1 -1
  25. package/dist/crypto/WasmCrypto.js +44 -2
  26. package/dist/crypto/WasmCrypto.js.map +1 -1
  27. package/dist/crypto/crypto.d.ts +17 -1
  28. package/dist/crypto/crypto.d.ts.map +1 -1
  29. package/dist/crypto/crypto.js.map +1 -1
  30. package/dist/localNode.d.ts +1 -0
  31. package/dist/localNode.d.ts.map +1 -1
  32. package/dist/localNode.js +10 -5
  33. package/dist/localNode.js.map +1 -1
  34. package/dist/sync.d.ts +2 -0
  35. package/dist/sync.d.ts.map +1 -1
  36. package/dist/sync.js +8 -1
  37. package/dist/sync.js.map +1 -1
  38. package/dist/tests/PureJSCrypto.test.d.ts +2 -0
  39. package/dist/tests/PureJSCrypto.test.d.ts.map +1 -0
  40. package/dist/tests/PureJSCrypto.test.js +88 -0
  41. package/dist/tests/PureJSCrypto.test.js.map +1 -0
  42. package/dist/tests/WasmCrypto.test.d.ts +2 -0
  43. package/dist/tests/WasmCrypto.test.d.ts.map +1 -0
  44. package/dist/tests/WasmCrypto.test.js +88 -0
  45. package/dist/tests/WasmCrypto.test.js.map +1 -0
  46. package/dist/tests/coValueCore.test.js +62 -187
  47. package/dist/tests/coValueCore.test.js.map +1 -1
  48. package/dist/tests/coreWasm.test.d.ts +2 -0
  49. package/dist/tests/coreWasm.test.d.ts.map +1 -0
  50. package/dist/tests/coreWasm.test.js +80 -0
  51. package/dist/tests/coreWasm.test.js.map +1 -0
  52. package/dist/tests/sync.test.js +19 -1
  53. package/dist/tests/sync.test.js.map +1 -1
  54. package/dist/tests/testUtils.d.ts +3 -0
  55. package/dist/tests/testUtils.d.ts.map +1 -1
  56. package/dist/tests/testUtils.js +4 -1
  57. package/dist/tests/testUtils.js.map +1 -1
  58. package/package.json +3 -3
  59. package/src/coValueCore/SessionMap.ts +230 -0
  60. package/src/coValueCore/coValueCore.ts +66 -91
  61. package/src/coValueCore/verifiedState.ts +60 -129
  62. package/src/coValues/account.ts +28 -4
  63. package/src/crypto/PureJSCrypto.ts +202 -2
  64. package/src/crypto/WasmCrypto.ts +95 -4
  65. package/src/crypto/crypto.ts +38 -1
  66. package/src/localNode.ts +18 -10
  67. package/src/sync.ts +10 -0
  68. package/src/tests/PureJSCrypto.test.ts +130 -0
  69. package/src/tests/WasmCrypto.test.ts +130 -0
  70. package/src/tests/coValueCore.test.ts +84 -292
  71. package/src/tests/coreWasm.test.ts +142 -0
  72. package/src/tests/sync.test.ts +32 -0
  73. package/src/tests/testUtils.ts +9 -1
@@ -27,6 +27,7 @@ import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfrom
27
27
  import { expectGroup } from "../typeUtils/expectGroup.js";
28
28
  import { getDependedOnCoValuesFromRawData } from "./utils.js";
29
29
  import { CoValueHeader, Transaction, VerifiedState } from "./verifiedState.js";
30
+ import { SessionMap } from "./SessionMap.js";
30
31
 
31
32
  export function idforHeader(
32
33
  header: CoValueHeader,
@@ -95,12 +96,7 @@ export class CoValueCore {
95
96
  this.crypto = node.crypto;
96
97
  if ("header" in init) {
97
98
  this.id = idforHeader(init.header, node.crypto);
98
- this._verified = new VerifiedState(
99
- this.id,
100
- node.crypto,
101
- init.header,
102
- new Map(),
103
- );
99
+ this._verified = new VerifiedState(this.id, node.crypto, init.header);
104
100
  } else {
105
101
  this.id = init.id;
106
102
  this._verified = null;
@@ -298,7 +294,7 @@ export class CoValueCore {
298
294
  this.id,
299
295
  this.node.crypto,
300
296
  header,
301
- new Map(),
297
+ new SessionMap(this.id, this.node.crypto),
302
298
  streamingKnownState,
303
299
  );
304
300
 
@@ -467,19 +463,7 @@ export class CoValueCore {
467
463
  );
468
464
 
469
465
  if (result.isOk()) {
470
- if (
471
- this._cachedContent &&
472
- "processNewTransactions" in this._cachedContent &&
473
- typeof this._cachedContent.processNewTransactions === "function"
474
- ) {
475
- this._cachedContent.processNewTransactions();
476
- } else {
477
- this._cachedContent = undefined;
478
- }
479
-
480
- this._cachedDependentOn = undefined;
481
-
482
- this.notifyUpdate(notifyMode);
466
+ this.updateContentAndNotifyUpdate(notifyMode);
483
467
  }
484
468
 
485
469
  return result;
@@ -489,6 +473,22 @@ export class CoValueCore {
489
473
  deferredUpdates = 0;
490
474
  nextDeferredNotify: Promise<void> | undefined;
491
475
 
476
+ updateContentAndNotifyUpdate(notifyMode: "immediate" | "deferred") {
477
+ if (
478
+ this._cachedContent &&
479
+ "processNewTransactions" in this._cachedContent &&
480
+ typeof this._cachedContent.processNewTransactions === "function"
481
+ ) {
482
+ this._cachedContent.processNewTransactions();
483
+ } else {
484
+ this._cachedContent = undefined;
485
+ }
486
+
487
+ this._cachedDependentOn = undefined;
488
+
489
+ this.notifyUpdate(notifyMode);
490
+ }
491
+
492
492
  notifyUpdate(notifyMode: "immediate" | "deferred") {
493
493
  if (this.listeners.size === 0) {
494
494
  return;
@@ -556,9 +556,18 @@ export class CoValueCore {
556
556
  );
557
557
  }
558
558
 
559
- const madeAt = Date.now();
559
+ // This is an ugly hack to get a unique but stable session ID for editing the current account
560
+ const sessionID =
561
+ this.verified.header.meta?.type === "account"
562
+ ? (this.node.currentSessionID.replace(
563
+ this.node.getCurrentAgent().id,
564
+ this.node.getCurrentAgent().currentAgentID(),
565
+ ) as SessionID)
566
+ : this.node.currentSessionID;
567
+
568
+ const signerAgent = this.node.getCurrentAgent();
560
569
 
561
- let transaction: Transaction;
570
+ let result: { signature: Signature; transaction: Transaction };
562
571
 
563
572
  if (privacy === "private") {
564
573
  const { secret: keySecret, id: keyID } = this.getCurrentReadKey();
@@ -567,69 +576,42 @@ export class CoValueCore {
567
576
  throw new Error("Can't make transaction without read key secret");
568
577
  }
569
578
 
570
- const encrypted = this.crypto.encryptForTransaction(changes, keySecret, {
571
- in: this.id,
572
- tx: this.nextTransactionID(),
573
- });
574
-
575
- this._decryptionCache[encrypted] = changes;
579
+ result = this.verified.makeNewPrivateTransaction(
580
+ sessionID,
581
+ signerAgent,
582
+ changes,
583
+ keyID,
584
+ keySecret,
585
+ );
576
586
 
577
- transaction = {
578
- privacy: "private",
579
- madeAt,
580
- keyUsed: keyID,
581
- encryptedChanges: encrypted,
582
- };
587
+ if (result.transaction.privacy === "private") {
588
+ this._decryptionCache[result.transaction.encryptedChanges] = changes;
589
+ }
583
590
  } else {
584
- transaction = {
585
- privacy: "trusting",
586
- madeAt,
587
- changes: stableStringify(changes),
588
- };
591
+ result = this.verified.makeNewTrustingTransaction(
592
+ sessionID,
593
+ signerAgent,
594
+ changes,
595
+ );
589
596
  }
590
597
 
591
- // This is an ugly hack to get a unique but stable session ID for editing the current account
592
- const sessionID =
593
- this.verified.header.meta?.type === "account"
594
- ? (this.node.currentSessionID.replace(
595
- this.node.getCurrentAgent().id,
596
- this.node.getCurrentAgent().currentAgentID(),
597
- ) as SessionID)
598
- : this.node.currentSessionID;
598
+ const { transaction, signature } = result;
599
599
 
600
- const { expectedNewHash, newStreamingHash } =
601
- this.verified.expectedNewHashAfter(sessionID, [transaction]);
600
+ this.node.syncManager.recordTransactionsSize([transaction], "local");
602
601
 
603
- const signature = this.crypto.sign(
604
- this.node.getCurrentAgent().currentSignerSecret(),
605
- expectedNewHash,
606
- );
602
+ const session = this.verified.sessions.get(sessionID);
603
+ const txIdx = session ? session.transactions.length - 1 : 0;
607
604
 
608
- const success = this.tryAddTransactions(
605
+ this.updateContentAndNotifyUpdate("immediate");
606
+ this.node.syncManager.syncLocalTransaction(
607
+ this.verified,
608
+ transaction,
609
609
  sessionID,
610
- [transaction],
611
- expectedNewHash,
612
610
  signature,
613
- "immediate",
614
- true,
615
- newStreamingHash,
616
- )._unsafeUnwrap({ withStackTrace: true });
617
-
618
- if (success) {
619
- const session = this.verified.sessions.get(sessionID);
620
- const txIdx = session ? session.transactions.length - 1 : 0;
621
-
622
- this.node.syncManager.recordTransactionsSize([transaction], "local");
623
- this.node.syncManager.syncLocalTransaction(
624
- this.verified,
625
- transaction,
626
- sessionID,
627
- signature,
628
- txIdx,
629
- );
630
- }
611
+ txIdx,
612
+ );
631
613
 
632
- return success;
614
+ return true;
633
615
  }
634
616
 
635
617
  getCurrentContent(options?: { ignorePrivateTransactions: true }): RawCoValue {
@@ -658,6 +640,12 @@ export class CoValueCore {
658
640
  ignorePrivateTransactions: boolean;
659
641
  knownTransactions?: CoValueKnownState["sessions"];
660
642
  }): DecryptedTransaction[] {
643
+ if (!this.verified) {
644
+ throw new Error(
645
+ "CoValueCore: getValidTransactions called on coValue without verified state",
646
+ );
647
+ }
648
+
661
649
  const validTransactions = determineValidTransactions(
662
650
  this,
663
651
  options?.knownTransactions,
@@ -701,25 +689,12 @@ export class CoValueCore {
701
689
  let decryptedChanges = this._decryptionCache[tx.encryptedChanges];
702
690
 
703
691
  if (!decryptedChanges) {
704
- const decryptedString = this.crypto.decryptRawForTransaction(
705
- tx.encryptedChanges,
692
+ decryptedChanges = this.verified.decryptTransaction(
693
+ txID.sessionID,
694
+ txID.txIndex,
706
695
  readKey,
707
- {
708
- in: this.id,
709
- tx: txID,
710
- },
711
696
  );
712
697
 
713
- try {
714
- decryptedChanges = decryptedString && parseJSON(decryptedString);
715
- } catch (e) {
716
- logger.error("Failed to parse private transaction on " + this.id, {
717
- err: e,
718
- txID,
719
- changes: decryptedString?.slice(0, 50),
720
- });
721
- continue;
722
- }
723
698
  this._decryptionCache[tx.encryptedChanges] = decryptedChanges;
724
699
  }
725
700
 
@@ -10,6 +10,7 @@ import {
10
10
  Encrypted,
11
11
  Hash,
12
12
  KeyID,
13
+ KeySecret,
13
14
  Signature,
14
15
  SignerID,
15
16
  StreamingHash,
@@ -21,6 +22,8 @@ import { PermissionsDef as RulesetDef } from "../permissions.js";
21
22
  import { CoValueKnownState, NewContentMessage } from "../sync.js";
22
23
  import { InvalidHashError, InvalidSignatureError } from "./coValueCore.js";
23
24
  import { TryAddTransactionsError } from "./coValueCore.js";
25
+ import { SessionLog, SessionMap } from "./SessionMap.js";
26
+ import { ControlledAccountOrAgent } from "../coValues/account.js";
24
27
 
25
28
  export type CoValueHeader = {
26
29
  type: AnyRawCoValue["type"];
@@ -48,20 +51,11 @@ export type TrustingTransaction = {
48
51
 
49
52
  export type Transaction = PrivateTransaction | TrustingTransaction;
50
53
 
51
- type SessionLog = {
52
- readonly transactions: Transaction[];
53
- streamingHash?: StreamingHash;
54
- readonly signatureAfter: { [txIdx: number]: Signature | undefined };
55
- lastSignature: Signature;
56
- };
57
-
58
- export type ValidatedSessions = Map<SessionID, SessionLog>;
59
-
60
54
  export class VerifiedState {
61
55
  readonly id: RawCoID;
62
56
  readonly crypto: CryptoProvider;
63
57
  readonly header: CoValueHeader;
64
- readonly sessions: ValidatedSessions;
58
+ readonly sessions: SessionMap;
65
59
  private _cachedKnownState?: CoValueKnownState;
66
60
  private _cachedNewContentSinceEmpty: NewContentMessage[] | undefined;
67
61
  private streamingKnownState?: CoValueKnownState["sessions"];
@@ -71,35 +65,25 @@ export class VerifiedState {
71
65
  id: RawCoID,
72
66
  crypto: CryptoProvider,
73
67
  header: CoValueHeader,
74
- sessions: ValidatedSessions,
68
+ sessions?: SessionMap,
75
69
  streamingKnownState?: CoValueKnownState["sessions"],
76
70
  ) {
77
71
  this.id = id;
78
72
  this.crypto = crypto;
79
73
  this.header = header;
80
- this.sessions = sessions;
74
+ this.sessions = sessions ?? new SessionMap(id, crypto);
81
75
  this.streamingKnownState = streamingKnownState
82
76
  ? { ...streamingKnownState }
83
77
  : undefined;
84
78
  }
85
79
 
86
80
  clone(): VerifiedState {
87
- // do a deep clone, including the sessions
88
- const clonedSessions = new Map();
89
- for (let [sessionID, sessionLog] of this.sessions) {
90
- clonedSessions.set(sessionID, {
91
- lastSignature: sessionLog.lastSignature,
92
- streamingHash: sessionLog.streamingHash?.clone(),
93
- signatureAfter: { ...sessionLog.signatureAfter },
94
- transactions: sessionLog.transactions.slice(),
95
- } satisfies SessionLog);
96
- }
97
81
  return new VerifiedState(
98
82
  this.id,
99
83
  this.crypto,
100
84
  this.header,
101
- clonedSessions,
102
- this.streamingKnownState,
85
+ this.sessions.clone(),
86
+ this.streamingKnownState ? { ...this.streamingKnownState } : undefined,
103
87
  );
104
88
  }
105
89
 
@@ -112,130 +96,69 @@ export class VerifiedState {
112
96
  skipVerify: boolean = false,
113
97
  givenNewStreamingHash?: StreamingHash,
114
98
  ): Result<true, TryAddTransactionsError> {
115
- if (skipVerify === true) {
116
- this.doAddTransactions(
117
- sessionID,
118
- newTransactions,
119
- newSignature,
120
- givenNewStreamingHash,
121
- );
122
- } else {
123
- const { expectedNewHash, newStreamingHash } = this.expectedNewHashAfter(
124
- sessionID,
125
- newTransactions,
126
- );
127
-
128
- if (givenExpectedNewHash && givenExpectedNewHash !== expectedNewHash) {
129
- return err({
130
- type: "InvalidHash",
131
- id: this.id,
132
- expectedNewHash,
133
- givenExpectedNewHash,
134
- } satisfies InvalidHashError);
135
- }
136
-
137
- if (!this.crypto.verify(newSignature, expectedNewHash, signerID)) {
138
- return err({
139
- type: "InvalidSignature",
140
- id: this.id,
141
- newSignature,
142
- sessionID,
143
- signerID,
144
- } satisfies InvalidSignatureError);
145
- }
99
+ const result = this.sessions.addTransaction(
100
+ sessionID,
101
+ signerID,
102
+ newTransactions,
103
+ newSignature,
104
+ skipVerify,
105
+ );
146
106
 
147
- this.doAddTransactions(
148
- sessionID,
149
- newTransactions,
150
- newSignature,
151
- newStreamingHash,
152
- );
107
+ if (result.isOk()) {
108
+ this._cachedNewContentSinceEmpty = undefined;
109
+ this._cachedKnownState = undefined;
153
110
  }
154
111
 
155
- return ok(true as const);
112
+ return result;
156
113
  }
157
114
 
158
- getLastSignatureCheckpoint(sessionID: SessionID): number {
159
- const sessionLog = this.sessions.get(sessionID);
115
+ makeNewTrustingTransaction(
116
+ sessionID: SessionID,
117
+ signerAgent: ControlledAccountOrAgent,
118
+ changes: JsonValue[],
119
+ ) {
120
+ const result = this.sessions.makeNewTrustingTransaction(
121
+ sessionID,
122
+ signerAgent,
123
+ changes,
124
+ );
160
125
 
161
- if (!sessionLog?.signatureAfter) return -1;
126
+ this._cachedNewContentSinceEmpty = undefined;
127
+ this._cachedKnownState = undefined;
162
128
 
163
- return Object.keys(sessionLog.signatureAfter).reduce(
164
- (max, idx) => Math.max(max, parseInt(idx)),
165
- -1,
166
- );
129
+ return result;
167
130
  }
168
131
 
169
- private doAddTransactions(
132
+ makeNewPrivateTransaction(
170
133
  sessionID: SessionID,
171
- newTransactions: Transaction[],
172
- newSignature: Signature,
173
- newStreamingHash?: StreamingHash,
134
+ signerAgent: ControlledAccountOrAgent,
135
+ changes: JsonValue[],
136
+ keyID: KeyID,
137
+ keySecret: KeySecret,
174
138
  ) {
175
- const sessionLog = this.sessions.get(sessionID);
176
- const transactions = sessionLog?.transactions ?? [];
177
-
178
- for (const tx of newTransactions) {
179
- transactions.push(tx);
180
- }
181
-
182
- const signatureAfter = sessionLog?.signatureAfter ?? {};
183
- const lastInbetweenSignatureIdx =
184
- this.getLastSignatureCheckpoint(sessionID);
185
-
186
- const sizeOfTxsSinceLastInbetweenSignature = transactions
187
- .slice(lastInbetweenSignatureIdx + 1)
188
- .reduce((sum, tx) => sum + getTransactionSize(tx), 0);
189
-
190
- if (exceedsRecommendedSize(sizeOfTxsSinceLastInbetweenSignature)) {
191
- signatureAfter[transactions.length - 1] = newSignature;
192
- }
193
-
194
- this.sessions.set(sessionID, {
195
- transactions,
196
- streamingHash: newStreamingHash,
197
- lastSignature: newSignature,
198
- signatureAfter: signatureAfter,
199
- });
139
+ const result = this.sessions.makeNewPrivateTransaction(
140
+ sessionID,
141
+ signerAgent,
142
+ changes,
143
+ keyID,
144
+ keySecret,
145
+ );
200
146
 
201
147
  this._cachedNewContentSinceEmpty = undefined;
202
148
  this._cachedKnownState = undefined;
149
+
150
+ return result;
203
151
  }
204
152
 
205
- expectedNewHashAfter(
206
- sessionID: SessionID,
207
- newTransactions: Transaction[],
208
- ): { expectedNewHash: Hash; newStreamingHash: StreamingHash } {
153
+ getLastSignatureCheckpoint(sessionID: SessionID): number {
209
154
  const sessionLog = this.sessions.get(sessionID);
210
155
 
211
- if (!sessionLog?.streamingHash) {
212
- const streamingHash = new StreamingHash(this.crypto);
213
- const oldTransactions = sessionLog?.transactions ?? [];
214
-
215
- for (const transaction of oldTransactions) {
216
- streamingHash.update(transaction);
217
- }
218
-
219
- for (const transaction of newTransactions) {
220
- streamingHash.update(transaction);
221
- }
222
-
223
- return {
224
- expectedNewHash: streamingHash.digest(),
225
- newStreamingHash: streamingHash,
226
- };
227
- }
228
-
229
- const streamingHash = sessionLog.streamingHash.clone();
230
-
231
- for (const transaction of newTransactions) {
232
- streamingHash.update(transaction);
233
- }
156
+ if (!sessionLog?.signatureAfter) return -1;
234
157
 
235
- return {
236
- expectedNewHash: streamingHash.digest(),
237
- newStreamingHash: streamingHash,
238
- };
158
+ return Object.keys(sessionLog.signatureAfter).reduce(
159
+ (max, idx) => Math.max(max, parseInt(idx)),
160
+ -1,
161
+ );
239
162
  }
240
163
 
241
164
  newContentSince(
@@ -424,6 +347,14 @@ export class VerifiedState {
424
347
  sessions,
425
348
  };
426
349
  }
350
+
351
+ decryptTransaction(
352
+ sessionID: SessionID,
353
+ txIndex: number,
354
+ keySecret: KeySecret,
355
+ ): JsonValue[] | undefined {
356
+ return this.sessions.decryptTransaction(sessionID, txIndex, keySecret);
357
+ }
427
358
  }
428
359
 
429
360
  function getNextKnownSignatureIdx(
@@ -92,6 +92,10 @@ export class ControlledAccount implements ControlledAccountOrAgent {
92
92
  account: RawAccount<AccountMeta>;
93
93
  agentSecret: AgentSecret;
94
94
  _cachedCurrentAgentID: AgentID | undefined;
95
+ _cachedCurrentSignerID: SignerID | undefined;
96
+ _cachedCurrentSignerSecret: SignerSecret | undefined;
97
+ _cachedCurrentSealerID: SealerID | undefined;
98
+ _cachedCurrentSealerSecret: SealerSecret | undefined;
95
99
  crypto: CryptoProvider;
96
100
 
97
101
  constructor(account: RawAccount<AccountMeta>, agentSecret: AgentSecret) {
@@ -114,19 +118,39 @@ export class ControlledAccount implements ControlledAccountOrAgent {
114
118
  }
115
119
 
116
120
  currentSignerID() {
117
- return this.crypto.getAgentSignerID(this.currentAgentID());
121
+ if (this._cachedCurrentSignerID) {
122
+ return this._cachedCurrentSignerID;
123
+ }
124
+ const signerID = this.crypto.getAgentSignerID(this.currentAgentID());
125
+ this._cachedCurrentSignerID = signerID;
126
+ return signerID;
118
127
  }
119
128
 
120
129
  currentSignerSecret(): SignerSecret {
121
- return this.crypto.getAgentSignerSecret(this.agentSecret);
130
+ if (this._cachedCurrentSignerSecret) {
131
+ return this._cachedCurrentSignerSecret;
132
+ }
133
+ const signerSecret = this.crypto.getAgentSignerSecret(this.agentSecret);
134
+ this._cachedCurrentSignerSecret = signerSecret;
135
+ return signerSecret;
122
136
  }
123
137
 
124
138
  currentSealerID() {
125
- return this.crypto.getAgentSealerID(this.currentAgentID());
139
+ if (this._cachedCurrentSealerID) {
140
+ return this._cachedCurrentSealerID;
141
+ }
142
+ const sealerID = this.crypto.getAgentSealerID(this.currentAgentID());
143
+ this._cachedCurrentSealerID = sealerID;
144
+ return sealerID;
126
145
  }
127
146
 
128
147
  currentSealerSecret(): SealerSecret {
129
- return this.crypto.getAgentSealerSecret(this.agentSecret);
148
+ if (this._cachedCurrentSealerSecret) {
149
+ return this._cachedCurrentSealerSecret;
150
+ }
151
+ const sealerSecret = this.crypto.getAgentSealerSecret(this.agentSecret);
152
+ this._cachedCurrentSealerSecret = sealerSecret;
153
+ return sealerSecret;
130
154
  }
131
155
  }
132
156