@aztec/pxe 0.69.0-devnet → 0.69.1

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 (32) hide show
  1. package/dest/database/kv_pxe_database.d.ts +7 -7
  2. package/dest/database/kv_pxe_database.d.ts.map +1 -1
  3. package/dest/database/kv_pxe_database.js +11 -11
  4. package/dest/database/note_dao.d.ts +105 -0
  5. package/dest/database/note_dao.d.ts.map +1 -0
  6. package/dest/database/note_dao.js +123 -0
  7. package/dest/database/outgoing_note_dao.js +3 -3
  8. package/dest/database/pxe_database.d.ts +9 -9
  9. package/dest/database/pxe_database.d.ts.map +1 -1
  10. package/dest/database/pxe_database_test_suite.js +21 -21
  11. package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +2 -2
  12. package/dest/note_decryption_utils/produce_note_daos.d.ts +2 -2
  13. package/dest/note_decryption_utils/produce_note_daos.d.ts.map +1 -1
  14. package/dest/note_decryption_utils/produce_note_daos.js +5 -5
  15. package/dest/pxe_service/pxe_service.d.ts +2 -2
  16. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  17. package/dest/pxe_service/pxe_service.js +12 -15
  18. package/dest/simulator_oracle/index.d.ts.map +1 -1
  19. package/dest/simulator_oracle/index.js +16 -16
  20. package/package.json +14 -14
  21. package/src/database/kv_pxe_database.ts +16 -16
  22. package/src/database/{incoming_note_dao.ts → note_dao.ts} +65 -48
  23. package/src/database/outgoing_note_dao.ts +2 -2
  24. package/src/database/pxe_database.ts +9 -9
  25. package/src/database/pxe_database_test_suite.ts +25 -25
  26. package/src/kernel_prover/hints/build_private_kernel_reset_private_inputs.ts +1 -1
  27. package/src/note_decryption_utils/produce_note_daos.ts +6 -6
  28. package/src/pxe_service/pxe_service.ts +19 -22
  29. package/src/simulator_oracle/index.ts +16 -16
  30. package/dest/database/incoming_note_dao.d.ts +0 -86
  31. package/dest/database/incoming_note_dao.d.ts.map +0 -1
  32. package/dest/database/incoming_note_dao.js +0 -110
@@ -34,8 +34,8 @@ import { MessageLoadOracleInputs } from '@aztec/simulator/acvm';
34
34
  import { type AcirSimulator, type DBOracle } from '@aztec/simulator/client';
35
35
 
36
36
  import { type ContractDataOracle } from '../contract_data_oracle/index.js';
37
- import { type IncomingNoteDao } from '../database/incoming_note_dao.js';
38
37
  import { type PxeDatabase } from '../database/index.js';
38
+ import { type NoteDao } from '../database/note_dao.js';
39
39
  import { produceNoteDaos } from '../note_decryption_utils/produce_note_daos.js';
40
40
  import { getAcirSimulator } from '../simulator/index.js';
41
41
  import { WINDOW_HALF_SIZE, getIndexedTaggingSecretsForTheWindow, getInitialIndexesMap } from './tagging_utils.js';
@@ -92,7 +92,7 @@ export class SimulatorOracle implements DBOracle {
92
92
  }
93
93
 
94
94
  async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus, scopes?: AztecAddress[]) {
95
- const noteDaos = await this.db.getIncomingNotes({
95
+ const noteDaos = await this.db.getNotes({
96
96
  contractAddress,
97
97
  storageSlot,
98
98
  status,
@@ -569,17 +569,17 @@ export class SimulatorOracle implements DBOracle {
569
569
  // Since we could have notes with the same index for different txs, we need
570
570
  // to keep track of them scoping by txHash
571
571
  const excludedIndices: Map<string, Set<number>> = new Map();
572
- const incomingNotes: IncomingNoteDao[] = [];
572
+ const notes: NoteDao[] = [];
573
573
 
574
574
  const txEffectsCache = new Map<string, InBlock<TxEffect> | undefined>();
575
575
 
576
576
  for (const scopedLog of scopedLogs) {
577
- const incomingNotePayload = scopedLog.isFromPublic
577
+ const notePayload = scopedLog.isFromPublic
578
578
  ? L1NotePayload.decryptAsIncomingFromPublic(scopedLog.logData, addressSecret)
579
579
  : L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
580
580
 
581
- if (incomingNotePayload) {
582
- const payload = incomingNotePayload;
581
+ if (notePayload) {
582
+ const payload = notePayload;
583
583
 
584
584
  const txEffect =
585
585
  txEffectsCache.get(scopedLog.txHash.toString()) ?? (await this.aztecNode.getTxEffect(scopedLog.txHash));
@@ -594,13 +594,13 @@ export class SimulatorOracle implements DBOracle {
594
594
  if (!excludedIndices.has(scopedLog.txHash.toString())) {
595
595
  excludedIndices.set(scopedLog.txHash.toString(), new Set());
596
596
  }
597
- const { incomingNote } = await produceNoteDaos(
597
+ const { note } = await produceNoteDaos(
598
598
  // I don't like this at all, but we need a simulator to run `computeNoteHashAndOptionallyANullifier`. This generates
599
599
  // a chicken-and-egg problem due to this oracle requiring a simulator, which in turn requires this oracle. Furthermore, since jest doesn't allow
600
600
  // mocking ESM exports, we have to pollute the method even more by providing a simulator parameter so tests can inject a fake one.
601
601
  simulator ?? getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.contractDataOracle),
602
602
  this.db,
603
- incomingNotePayload ? recipient.toAddressPoint() : undefined,
603
+ notePayload ? recipient.toAddressPoint() : undefined,
604
604
  payload!,
605
605
  txEffect.data.txHash,
606
606
  txEffect.l2BlockNumber,
@@ -611,12 +611,12 @@ export class SimulatorOracle implements DBOracle {
611
611
  this.log,
612
612
  );
613
613
 
614
- if (incomingNote) {
615
- incomingNotes.push(incomingNote);
614
+ if (note) {
615
+ notes.push(note);
616
616
  }
617
617
  }
618
618
  }
619
- return { incomingNotes };
619
+ return { notes };
620
620
  }
621
621
 
622
622
  /**
@@ -629,10 +629,10 @@ export class SimulatorOracle implements DBOracle {
629
629
  recipient: AztecAddress,
630
630
  simulator?: AcirSimulator,
631
631
  ): Promise<void> {
632
- const { incomingNotes } = await this.#decryptTaggedLogs(logs, recipient, simulator);
633
- if (incomingNotes.length) {
634
- await this.db.addNotes(incomingNotes, recipient);
635
- incomingNotes.forEach(noteDao => {
632
+ const { notes } = await this.#decryptTaggedLogs(logs, recipient, simulator);
633
+ if (notes.length) {
634
+ await this.db.addNotes(notes, recipient);
635
+ notes.forEach(noteDao => {
636
636
  this.log.verbose(`Added incoming note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
637
637
  contract: noteDao.contractAddress,
638
638
  slot: noteDao.storageSlot,
@@ -644,7 +644,7 @@ export class SimulatorOracle implements DBOracle {
644
644
 
645
645
  public async removeNullifiedNotes(contractAddress: AztecAddress) {
646
646
  for (const recipient of await this.keyStore.getAccounts()) {
647
- const currentNotesForRecipient = await this.db.getIncomingNotes({ contractAddress, owner: recipient });
647
+ const currentNotesForRecipient = await this.db.getNotes({ contractAddress, owner: recipient });
648
648
  const nullifiersToCheck = currentNotesForRecipient.map(note => note.siloedNullifier);
649
649
  const nullifierIndexes = await this.aztecNode.findNullifiersIndexesWithBlock('latest', nullifiersToCheck);
650
650
 
@@ -1,86 +0,0 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- /// <reference types="node" resolution-mode="require"/>
3
- import { type L1NotePayload, Note, TxHash } from '@aztec/circuit-types';
4
- import { AztecAddress, Fr, type PublicKey } from '@aztec/circuits.js';
5
- import { NoteSelector } from '@aztec/foundation/abi';
6
- import { BufferReader } from '@aztec/foundation/serialize';
7
- import { type NoteData } from '@aztec/simulator/acvm';
8
- import { type NoteInfo } from '../note_decryption_utils/index.js';
9
- /**
10
- * A note with contextual data which was decrypted as incoming.
11
- */
12
- export declare class IncomingNoteDao implements NoteData {
13
- /** The note as emitted from the Noir contract. */
14
- note: Note;
15
- /** The contract address this note is created in. */
16
- contractAddress: AztecAddress;
17
- /** The specific storage location of the note on the contract. */
18
- storageSlot: Fr;
19
- /** The note type identifier for the contract. */
20
- noteTypeId: NoteSelector;
21
- /** The hash of the tx the note was created in. */
22
- txHash: TxHash;
23
- /** The L2 block number in which the tx with this note was included. */
24
- l2BlockNumber: number;
25
- /** The L2 block hash in which the tx with this note was included. */
26
- l2BlockHash: string;
27
- /** The nonce of the note. */
28
- nonce: Fr;
29
- /**
30
- * A hash of the note. This is customizable by the app circuit.
31
- * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash.
32
- */
33
- noteHash: Fr;
34
- /**
35
- * The nullifier of the note (siloed by contract address).
36
- * Note: Might be set as 0 if the note was added to PXE as nullified.
37
- */
38
- siloedNullifier: Fr;
39
- /** The location of the relevant note in the note hash tree. */
40
- index: bigint;
41
- /** The public key with which the note was encrypted. */
42
- addressPoint: PublicKey;
43
- constructor(
44
- /** The note as emitted from the Noir contract. */
45
- note: Note,
46
- /** The contract address this note is created in. */
47
- contractAddress: AztecAddress,
48
- /** The specific storage location of the note on the contract. */
49
- storageSlot: Fr,
50
- /** The note type identifier for the contract. */
51
- noteTypeId: NoteSelector,
52
- /** The hash of the tx the note was created in. */
53
- txHash: TxHash,
54
- /** The L2 block number in which the tx with this note was included. */
55
- l2BlockNumber: number,
56
- /** The L2 block hash in which the tx with this note was included. */
57
- l2BlockHash: string,
58
- /** The nonce of the note. */
59
- nonce: Fr,
60
- /**
61
- * A hash of the note. This is customizable by the app circuit.
62
- * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash.
63
- */
64
- noteHash: Fr,
65
- /**
66
- * The nullifier of the note (siloed by contract address).
67
- * Note: Might be set as 0 if the note was added to PXE as nullified.
68
- */
69
- siloedNullifier: Fr,
70
- /** The location of the relevant note in the note hash tree. */
71
- index: bigint,
72
- /** The public key with which the note was encrypted. */
73
- addressPoint: PublicKey);
74
- static fromPayloadAndNoteInfo(note: Note, payload: L1NotePayload, noteInfo: NoteInfo, l2BlockNumber: number, l2BlockHash: string, dataStartIndexForTx: number, addressPoint: PublicKey): IncomingNoteDao;
75
- toBuffer(): Buffer;
76
- static fromBuffer(buffer: Buffer | BufferReader): IncomingNoteDao;
77
- toString(): string;
78
- static fromString(str: string): IncomingNoteDao;
79
- /**
80
- * Returns the size in bytes of the Note Dao.
81
- * @returns - Its size in bytes.
82
- */
83
- getSize(): number;
84
- static random({ note, contractAddress, txHash, storageSlot, noteTypeId, nonce, l2BlockNumber, l2BlockHash, noteHash, siloedNullifier, index, addressPoint, }?: Partial<IncomingNoteDao>): IncomingNoteDao;
85
- }
86
- //# sourceMappingURL=incoming_note_dao.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"incoming_note_dao.d.ts","sourceRoot":"","sources":["../../src/database/incoming_note_dao.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,EAAE,EAAS,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAElE;;GAEG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAE5C,kDAAkD;IAC3C,IAAI,EAAE,IAAI;IACjB,oDAAoD;IAC7C,eAAe,EAAE,YAAY;IACpC,iEAAiE;IAC1D,WAAW,EAAE,EAAE;IACtB,iDAAiD;IAC1C,UAAU,EAAE,YAAY;IAC/B,kDAAkD;IAC3C,MAAM,EAAE,MAAM;IACrB,uEAAuE;IAChE,aAAa,EAAE,MAAM;IAC5B,qEAAqE;IAC9D,WAAW,EAAE,MAAM;IAC1B,6BAA6B;IACtB,KAAK,EAAE,EAAE;IAChB;;;OAGG;IACI,QAAQ,EAAE,EAAE;IACnB;;;OAGG;IACI,eAAe,EAAE,EAAE;IAC1B,+DAA+D;IACxD,KAAK,EAAE,MAAM;IACpB,wDAAwD;IACjD,YAAY,EAAE,SAAS;;IA7B9B,kDAAkD;IAC3C,IAAI,EAAE,IAAI;IACjB,oDAAoD;IAC7C,eAAe,EAAE,YAAY;IACpC,iEAAiE;IAC1D,WAAW,EAAE,EAAE;IACtB,iDAAiD;IAC1C,UAAU,EAAE,YAAY;IAC/B,kDAAkD;IAC3C,MAAM,EAAE,MAAM;IACrB,uEAAuE;IAChE,aAAa,EAAE,MAAM;IAC5B,qEAAqE;IAC9D,WAAW,EAAE,MAAM;IAC1B,6BAA6B;IACtB,KAAK,EAAE,EAAE;IAChB;;;OAGG;IACI,QAAQ,EAAE,EAAE;IACnB;;;OAGG;IACI,eAAe,EAAE,EAAE;IAC1B,+DAA+D;IACxD,KAAK,EAAE,MAAM;IACpB,wDAAwD;IACjD,YAAY,EAAE,SAAS;IAGhC,MAAM,CAAC,sBAAsB,CAC3B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,SAAS;IAmBzB,QAAQ,IAAI,MAAM;IAiBlB,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY;IAgC/C,QAAQ;IAIR,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM;IAK7B;;;OAGG;IACI,OAAO;IAMd,MAAM,CAAC,MAAM,CAAC,EACZ,IAAoB,EACpB,eAAuC,EACvC,MAAuB,EACvB,WAAyB,EACzB,UAAkC,EAClC,KAAmB,EACnB,aAAgD,EAChD,WAAoC,EACpC,QAAsB,EACtB,eAA6B,EAC7B,KAA8B,EAC9B,YAA6B,GAC9B,GAAE,OAAO,CAAC,eAAe,CAAM;CAgBjC"}
@@ -1,110 +0,0 @@
1
- import { Note, TxHash, randomTxHash } from '@aztec/circuit-types';
2
- import { AztecAddress, Fr, Point } from '@aztec/circuits.js';
3
- import { NoteSelector } from '@aztec/foundation/abi';
4
- import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
5
- import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
6
- /**
7
- * A note with contextual data which was decrypted as incoming.
8
- */
9
- export class IncomingNoteDao {
10
- constructor(
11
- /** The note as emitted from the Noir contract. */
12
- note,
13
- /** The contract address this note is created in. */
14
- contractAddress,
15
- /** The specific storage location of the note on the contract. */
16
- storageSlot,
17
- /** The note type identifier for the contract. */
18
- noteTypeId,
19
- /** The hash of the tx the note was created in. */
20
- txHash,
21
- /** The L2 block number in which the tx with this note was included. */
22
- l2BlockNumber,
23
- /** The L2 block hash in which the tx with this note was included. */
24
- l2BlockHash,
25
- /** The nonce of the note. */
26
- nonce,
27
- /**
28
- * A hash of the note. This is customizable by the app circuit.
29
- * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash.
30
- */
31
- noteHash,
32
- /**
33
- * The nullifier of the note (siloed by contract address).
34
- * Note: Might be set as 0 if the note was added to PXE as nullified.
35
- */
36
- siloedNullifier,
37
- /** The location of the relevant note in the note hash tree. */
38
- index,
39
- /** The public key with which the note was encrypted. */
40
- addressPoint) {
41
- this.note = note;
42
- this.contractAddress = contractAddress;
43
- this.storageSlot = storageSlot;
44
- this.noteTypeId = noteTypeId;
45
- this.txHash = txHash;
46
- this.l2BlockNumber = l2BlockNumber;
47
- this.l2BlockHash = l2BlockHash;
48
- this.nonce = nonce;
49
- this.noteHash = noteHash;
50
- this.siloedNullifier = siloedNullifier;
51
- this.index = index;
52
- this.addressPoint = addressPoint;
53
- }
54
- static fromPayloadAndNoteInfo(note, payload, noteInfo, l2BlockNumber, l2BlockHash, dataStartIndexForTx, addressPoint) {
55
- const noteHashIndexInTheWholeTree = BigInt(dataStartIndexForTx + noteInfo.noteHashIndex);
56
- return new IncomingNoteDao(note, payload.contractAddress, payload.storageSlot, payload.noteTypeId, noteInfo.txHash, l2BlockNumber, l2BlockHash, noteInfo.nonce, noteInfo.noteHash, noteInfo.siloedNullifier, noteHashIndexInTheWholeTree, addressPoint);
57
- }
58
- toBuffer() {
59
- return serializeToBuffer([
60
- this.note,
61
- this.contractAddress,
62
- this.storageSlot,
63
- this.noteTypeId,
64
- this.txHash.buffer,
65
- this.l2BlockNumber,
66
- Fr.fromHexString(this.l2BlockHash),
67
- this.nonce,
68
- this.noteHash,
69
- this.siloedNullifier,
70
- this.index,
71
- this.addressPoint,
72
- ]);
73
- }
74
- static fromBuffer(buffer) {
75
- const reader = BufferReader.asReader(buffer);
76
- const note = Note.fromBuffer(reader);
77
- const contractAddress = AztecAddress.fromBuffer(reader);
78
- const storageSlot = Fr.fromBuffer(reader);
79
- const noteTypeId = reader.readObject(NoteSelector);
80
- const txHash = reader.readObject(TxHash);
81
- const l2BlockNumber = reader.readNumber();
82
- const l2BlockHash = Fr.fromBuffer(reader).toString();
83
- const nonce = Fr.fromBuffer(reader);
84
- const noteHash = Fr.fromBuffer(reader);
85
- const siloedNullifier = Fr.fromBuffer(reader);
86
- const index = toBigIntBE(reader.readBytes(32));
87
- const publicKey = Point.fromBuffer(reader);
88
- return new IncomingNoteDao(note, contractAddress, storageSlot, noteTypeId, txHash, l2BlockNumber, l2BlockHash, nonce, noteHash, siloedNullifier, index, publicKey);
89
- }
90
- toString() {
91
- return '0x' + this.toBuffer().toString('hex');
92
- }
93
- static fromString(str) {
94
- const hex = str.replace(/^0x/, '');
95
- return IncomingNoteDao.fromBuffer(Buffer.from(hex, 'hex'));
96
- }
97
- /**
98
- * Returns the size in bytes of the Note Dao.
99
- * @returns - Its size in bytes.
100
- */
101
- getSize() {
102
- const indexSize = Math.ceil(Math.log2(Number(this.index)));
103
- const noteSize = 4 + this.note.items.length * Fr.SIZE_IN_BYTES;
104
- return noteSize + AztecAddress.SIZE_IN_BYTES + Fr.SIZE_IN_BYTES * 4 + TxHash.SIZE + Point.SIZE_IN_BYTES + indexSize;
105
- }
106
- static random({ note = Note.random(), contractAddress = AztecAddress.random(), txHash = randomTxHash(), storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), nonce = Fr.random(), l2BlockNumber = Math.floor(Math.random() * 1000), l2BlockHash = Fr.random().toString(), noteHash = Fr.random(), siloedNullifier = Fr.random(), index = Fr.random().toBigInt(), addressPoint = Point.random(), } = {}) {
107
- return new IncomingNoteDao(note, contractAddress, storageSlot, noteTypeId, txHash, l2BlockNumber, l2BlockHash, nonce, noteHash, siloedNullifier, index, addressPoint);
108
- }
109
- }
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5jb21pbmdfbm90ZV9kYW8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YWJhc2UvaW5jb21pbmdfbm90ZV9kYW8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFzQixJQUFJLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBa0IsTUFBTSxvQkFBb0IsQ0FBQztBQUM3RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzdELE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUs5RTs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBQzFCO0lBQ0Usa0RBQWtEO0lBQzNDLElBQVU7SUFDakIsb0RBQW9EO0lBQzdDLGVBQTZCO0lBQ3BDLGlFQUFpRTtJQUMxRCxXQUFlO0lBQ3RCLGlEQUFpRDtJQUMxQyxVQUF3QjtJQUMvQixrREFBa0Q7SUFDM0MsTUFBYztJQUNyQix1RUFBdUU7SUFDaEUsYUFBcUI7SUFDNUIscUVBQXFFO0lBQzlELFdBQW1CO0lBQzFCLDZCQUE2QjtJQUN0QixLQUFTO0lBQ2hCOzs7T0FHRztJQUNJLFFBQVk7SUFDbkI7OztPQUdHO0lBQ0ksZUFBbUI7SUFDMUIsK0RBQStEO0lBQ3hELEtBQWE7SUFDcEIsd0RBQXdEO0lBQ2pELFlBQXVCO1FBNUJ2QixTQUFJLEdBQUosSUFBSSxDQUFNO1FBRVYsb0JBQWUsR0FBZixlQUFlLENBQWM7UUFFN0IsZ0JBQVcsR0FBWCxXQUFXLENBQUk7UUFFZixlQUFVLEdBQVYsVUFBVSxDQUFjO1FBRXhCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFFZCxrQkFBYSxHQUFiLGFBQWEsQ0FBUTtRQUVyQixnQkFB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