Skip to content

Commit 3d84673

Browse files
authored
refactor: CapsuleStore with staged writes (#19449)
Second part of the series started with #19445. This makes the CapsuleStore work based on staged writes. With this, capsules aren't written to persistent storage until PXE decides to commit the job.
2 parents 1596ab9 + b30c796 commit 3d84673

File tree

6 files changed

+421
-116
lines changed

6 files changed

+421
-116
lines changed

yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
354354
this.recipientTaggingStore,
355355
this.senderAddressBookStore,
356356
this.addressStore,
357+
this.jobId,
357358
);
358359

359360
await logService.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
@@ -385,11 +386,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
385386
// We read all note and event validation requests and process them all concurrently. This makes the process much
386387
// faster as we don't need to wait for the network round-trip.
387388
const noteValidationRequests = (
388-
await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot)
389+
await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId)
389390
).map(NoteValidationRequest.fromFields);
390391

391392
const eventValidationRequests = (
392-
await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot)
393+
await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId)
393394
).map(EventValidationRequest.fromFields);
394395

395396
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockStore);
@@ -424,8 +425,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
424425
await Promise.all([...noteDeliveries, ...eventDeliveries]);
425426

426427
// Requests are cleared once we're done.
427-
await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, []);
428-
await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, []);
428+
await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, [], this.jobId);
429+
await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
429430
}
430431

431432
public async utilityBulkRetrieveLogs(
@@ -441,7 +442,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
441442
// We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
442443
// don't need to wait for the network round-trip.
443444
const logRetrievalRequests = (
444-
await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot)
445+
await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId)
445446
).map(LogRetrievalRequest.fromFields);
446447

447448
const logService = new LogService(
@@ -452,18 +453,20 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
452453
this.recipientTaggingStore,
453454
this.senderAddressBookStore,
454455
this.addressStore,
456+
this.jobId,
455457
);
456458

457459
const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
458460

459461
// Requests are cleared once we're done.
460-
await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, []);
462+
await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, [], this.jobId);
461463

462464
// The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
463465
await this.capsuleStore.setCapsuleArray(
464466
contractAddress,
465467
logRetrievalResponsesArrayBaseSlot,
466468
maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
469+
this.jobId,
467470
);
468471
}
469472

@@ -472,7 +475,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
472475
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
473476
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
474477
}
475-
return this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule);
478+
this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule, this.jobId);
479+
return Promise.resolve();
476480
}
477481

478482
public async utilityLoadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
@@ -483,7 +487,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
483487
return (
484488
// TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
485489
this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
486-
(await this.capsuleStore.loadCapsule(this.contractAddress, slot))
490+
(await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
487491
);
488492
}
489493

@@ -492,7 +496,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
492496
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
493497
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
494498
}
495-
return this.capsuleStore.deleteCapsule(this.contractAddress, slot);
499+
this.capsuleStore.deleteCapsule(this.contractAddress, slot, this.jobId);
500+
return Promise.resolve();
496501
}
497502

498503
public utilityCopyCapsule(
@@ -505,7 +510,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
505510
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
506511
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
507512
}
508-
return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
513+
return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries, this.jobId);
509514
}
510515

511516
// TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.

yarn-project/pxe/src/logs/log_service.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ describe('LogService', () => {
5050
recipientTaggingStore,
5151
senderAddressBookStore,
5252
addressStore,
53+
'test',
5354
);
5455

5556
aztecNode.getPrivateLogsByTags.mockReset();

yarn-project/pxe/src/logs/log_service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export class LogService {
2626
private readonly recipientTaggingStore: RecipientTaggingStore,
2727
private readonly senderAddressBookStore: SenderAddressBookStore,
2828
private readonly addressStore: AddressStore,
29+
private readonly jobId: string,
2930
) {}
3031

3132
public async bulkRetrieveLogs(logRetrievalRequests: LogRetrievalRequest[]): Promise<(LogRetrievalResponse | null)[]> {
@@ -186,7 +187,7 @@ export class LogService {
186187
});
187188

188189
// TODO: This looks like it could belong more at the oracle interface level
189-
return this.capsuleStore.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs);
190+
return this.capsuleStore.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs, this.jobId);
190191
}
191192

192193
async #getCompleteAddress(account: AztecAddress): Promise<CompleteAddress> {

yarn-project/pxe/src/pxe.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export class PXE {
158158
);
159159

160160
const jobCoordinator = new JobCoordinator(store);
161+
jobCoordinator.registerStores([capsuleStore]);
161162

162163
const debugUtils = new PXEDebugUtils(contractStore, noteStore);
163164

0 commit comments

Comments
 (0)