@aztec/pxe 0.73.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2
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/dest/bin/index.js +3 -5
- package/dest/config/index.js +18 -21
- package/dest/config/package_info.js +4 -2
- package/dest/contract_data_oracle/index.js +69 -79
- package/dest/contract_data_oracle/private_functions_tree.js +44 -50
- package/dest/database/contracts/contract_artifact_db.js +3 -2
- package/dest/database/contracts/contract_instance_db.js +3 -2
- package/dest/database/index.js +0 -1
- package/dest/database/kv_pxe_database.js +243 -259
- package/dest/database/note_dao.js +28 -43
- package/dest/database/outgoing_note_dao.js +20 -34
- package/dest/database/pxe_database.js +4 -2
- package/dest/database/pxe_database_test_suite.js +296 -151
- package/dest/index.js +0 -1
- package/dest/kernel_oracle/index.js +9 -6
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +68 -66
- package/dest/kernel_prover/hints/index.js +0 -1
- package/dest/kernel_prover/index.js +0 -1
- package/dest/kernel_prover/kernel_prover.js +60 -65
- package/dest/kernel_prover/proving_data_oracle.js +4 -2
- package/dest/note_decryption_utils/add_public_values_to_payload.js +8 -9
- package/dest/pxe_http/index.js +0 -1
- package/dest/pxe_http/pxe_http_server.js +8 -6
- package/dest/pxe_service/error_enriching.js +10 -13
- package/dest/pxe_service/index.js +0 -1
- package/dest/pxe_service/pxe_service.js +283 -288
- package/dest/pxe_service/test/pxe_test_suite.js +40 -27
- package/dest/simulator/index.js +1 -3
- package/dest/simulator_oracle/index.js +266 -231
- package/dest/simulator_oracle/tagging_utils.js +4 -6
- package/dest/synchronizer/index.js +0 -1
- package/dest/synchronizer/synchronizer.js +42 -39
- package/dest/utils/create_pxe_service.js +9 -9
- package/package.json +15 -15
- package/src/pxe_service/pxe_service.ts +12 -14
- package/src/synchronizer/synchronizer.ts +5 -2
- package/dest/bin/index.d.ts +0 -3
- package/dest/bin/index.d.ts.map +0 -1
- package/dest/config/index.d.ts +0 -46
- package/dest/config/index.d.ts.map +0 -1
- package/dest/config/package_info.d.ts +0 -5
- package/dest/config/package_info.d.ts.map +0 -1
- package/dest/contract_data_oracle/index.d.ts +0 -104
- package/dest/contract_data_oracle/index.d.ts.map +0 -1
- package/dest/contract_data_oracle/private_functions_tree.d.ts +0 -65
- package/dest/contract_data_oracle/private_functions_tree.d.ts.map +0 -1
- package/dest/database/contracts/contract_artifact_db.d.ts +0 -20
- package/dest/database/contracts/contract_artifact_db.d.ts.map +0 -1
- package/dest/database/contracts/contract_instance_db.d.ts +0 -19
- package/dest/database/contracts/contract_instance_db.d.ts.map +0 -1
- package/dest/database/index.d.ts +0 -3
- package/dest/database/index.d.ts.map +0 -1
- package/dest/database/kv_pxe_database.d.ts +0 -55
- package/dest/database/kv_pxe_database.d.ts.map +0 -1
- package/dest/database/note_dao.d.ts +0 -103
- package/dest/database/note_dao.d.ts.map +0 -1
- package/dest/database/outgoing_note_dao.d.ts +0 -73
- package/dest/database/outgoing_note_dao.d.ts.map +0 -1
- package/dest/database/pxe_database.d.ts +0 -216
- package/dest/database/pxe_database.d.ts.map +0 -1
- package/dest/database/pxe_database_test_suite.d.ts +0 -7
- package/dest/database/pxe_database_test_suite.d.ts.map +0 -1
- package/dest/index.d.ts +0 -15
- package/dest/index.d.ts.map +0 -1
- package/dest/kernel_oracle/index.d.ts +0 -34
- package/dest/kernel_oracle/index.d.ts.map +0 -1
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts +0 -28
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts.map +0 -1
- package/dest/kernel_prover/hints/index.d.ts +0 -2
- package/dest/kernel_prover/hints/index.d.ts.map +0 -1
- package/dest/kernel_prover/index.d.ts +0 -3
- package/dest/kernel_prover/index.d.ts.map +0 -1
- package/dest/kernel_prover/kernel_prover.d.ts +0 -38
- package/dest/kernel_prover/kernel_prover.d.ts.map +0 -1
- package/dest/kernel_prover/proving_data_oracle.d.ts +0 -65
- package/dest/kernel_prover/proving_data_oracle.d.ts.map +0 -1
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts +0 -10
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts.map +0 -1
- package/dest/pxe_http/index.d.ts +0 -2
- package/dest/pxe_http/index.d.ts.map +0 -1
- package/dest/pxe_http/pxe_http_server.d.ts +0 -16
- package/dest/pxe_http/pxe_http_server.d.ts.map +0 -1
- package/dest/pxe_service/error_enriching.d.ts +0 -11
- package/dest/pxe_service/error_enriching.d.ts.map +0 -1
- package/dest/pxe_service/index.d.ts +0 -4
- package/dest/pxe_service/index.d.ts.map +0 -1
- package/dest/pxe_service/pxe_service.d.ts +0 -97
- package/dest/pxe_service/pxe_service.d.ts.map +0 -1
- package/dest/pxe_service/test/pxe_test_suite.d.ts +0 -3
- package/dest/pxe_service/test/pxe_test_suite.d.ts.map +0 -1
- package/dest/simulator/index.d.ts +0 -10
- package/dest/simulator/index.d.ts.map +0 -1
- package/dest/simulator_oracle/index.d.ts +0 -129
- package/dest/simulator_oracle/index.d.ts.map +0 -1
- package/dest/simulator_oracle/tagging_utils.d.ts +0 -16
- package/dest/simulator_oracle/tagging_utils.d.ts.map +0 -1
- package/dest/synchronizer/index.d.ts +0 -2
- package/dest/synchronizer/index.d.ts.map +0 -1
- package/dest/synchronizer/synchronizer.d.ts +0 -29
- package/dest/synchronizer/synchronizer.d.ts.map +0 -1
- package/dest/utils/create_pxe_service.d.ts +0 -16
- package/dest/utils/create_pxe_service.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NoteStatus, randomTxHash } from '@aztec/circuit-types';
|
|
2
|
-
import { AztecAddress, CompleteAddress, INITIAL_L2_BLOCK_NUM, PublicKeys, SerializableContractInstance
|
|
2
|
+
import { AztecAddress, CompleteAddress, INITIAL_L2_BLOCK_NUM, PublicKeys, SerializableContractInstance } from '@aztec/circuits.js';
|
|
3
3
|
import { makeHeader } from '@aztec/circuits.js/testing';
|
|
4
4
|
import { FunctionType } from '@aztec/foundation/abi';
|
|
5
5
|
import { timesParallel } from '@aztec/foundation/collection';
|
|
@@ -12,339 +12,441 @@ import { NoteDao } from './note_dao.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* A common test suite for a PXE database.
|
|
14
14
|
* @param getDatabase - A function that returns a database instance.
|
|
15
|
-
*/
|
|
16
|
-
export function describePxeDatabase(getDatabase) {
|
|
15
|
+
*/ export function describePxeDatabase(getDatabase) {
|
|
17
16
|
let database;
|
|
18
|
-
beforeEach(()
|
|
17
|
+
beforeEach(()=>{
|
|
19
18
|
database = getDatabase();
|
|
20
19
|
});
|
|
21
|
-
describe('Database', ()
|
|
22
|
-
describe('auth witnesses', ()
|
|
23
|
-
it('stores and retrieves auth witnesses', async ()
|
|
20
|
+
describe('Database', ()=>{
|
|
21
|
+
describe('auth witnesses', ()=>{
|
|
22
|
+
it('stores and retrieves auth witnesses', async ()=>{
|
|
24
23
|
const messageHash = Fr.random();
|
|
25
|
-
const witness = [
|
|
24
|
+
const witness = [
|
|
25
|
+
Fr.random(),
|
|
26
|
+
Fr.random()
|
|
27
|
+
];
|
|
26
28
|
await database.addAuthWitness(messageHash, witness);
|
|
27
29
|
await expect(database.getAuthWitness(messageHash)).resolves.toEqual(witness);
|
|
28
30
|
});
|
|
29
|
-
it("returns undefined if it doesn't have auth witnesses for the message", async ()
|
|
31
|
+
it("returns undefined if it doesn't have auth witnesses for the message", async ()=>{
|
|
30
32
|
const messageHash = Fr.random();
|
|
31
33
|
await expect(database.getAuthWitness(messageHash)).resolves.toBeUndefined();
|
|
32
34
|
});
|
|
33
|
-
it.skip('refuses to overwrite auth witnesses for the same message', async ()
|
|
35
|
+
it.skip('refuses to overwrite auth witnesses for the same message', async ()=>{
|
|
34
36
|
const messageHash = Fr.random();
|
|
35
|
-
const witness = [
|
|
37
|
+
const witness = [
|
|
38
|
+
Fr.random(),
|
|
39
|
+
Fr.random()
|
|
40
|
+
];
|
|
36
41
|
await database.addAuthWitness(messageHash, witness);
|
|
37
42
|
await expect(database.addAuthWitness(messageHash, witness)).rejects.toThrow();
|
|
38
43
|
});
|
|
39
44
|
});
|
|
40
|
-
describe('capsules', ()
|
|
41
|
-
it('stores and retrieves capsules', async ()
|
|
42
|
-
const capsule = [
|
|
45
|
+
describe('capsules', ()=>{
|
|
46
|
+
it('stores and retrieves capsules', async ()=>{
|
|
47
|
+
const capsule = [
|
|
48
|
+
Fr.random(),
|
|
49
|
+
Fr.random()
|
|
50
|
+
];
|
|
43
51
|
await database.addCapsule(capsule);
|
|
44
52
|
await expect(database.popCapsule()).resolves.toEqual(capsule);
|
|
45
53
|
});
|
|
46
|
-
it("returns undefined if it doesn't have capsules", async ()
|
|
54
|
+
it("returns undefined if it doesn't have capsules", async ()=>{
|
|
47
55
|
await expect(database.popCapsule()).resolves.toBeUndefined();
|
|
48
56
|
});
|
|
49
|
-
it('behaves like a stack when storing capsules', async ()
|
|
50
|
-
const capsule1 = [
|
|
51
|
-
|
|
57
|
+
it('behaves like a stack when storing capsules', async ()=>{
|
|
58
|
+
const capsule1 = [
|
|
59
|
+
Fr.random(),
|
|
60
|
+
Fr.random()
|
|
61
|
+
];
|
|
62
|
+
const capsule2 = [
|
|
63
|
+
Fr.random(),
|
|
64
|
+
Fr.random()
|
|
65
|
+
];
|
|
52
66
|
await database.addCapsule(capsule1);
|
|
53
67
|
await database.addCapsule(capsule2);
|
|
54
68
|
await expect(database.popCapsule()).resolves.toEqual(capsule2);
|
|
55
69
|
await expect(database.popCapsule()).resolves.toEqual(capsule1);
|
|
56
70
|
});
|
|
57
71
|
});
|
|
58
|
-
describe('incoming notes', ()
|
|
72
|
+
describe('incoming notes', ()=>{
|
|
59
73
|
let owners;
|
|
60
74
|
let contractAddresses;
|
|
61
75
|
let storageSlots;
|
|
62
76
|
let notes;
|
|
63
77
|
const filteringTests = [
|
|
64
|
-
[() => Promise.resolve({}), () => Promise.resolve(notes)],
|
|
65
78
|
[
|
|
66
|
-
()
|
|
67
|
-
()
|
|
79
|
+
()=>Promise.resolve({}),
|
|
80
|
+
()=>Promise.resolve(notes)
|
|
68
81
|
],
|
|
69
|
-
[async () => ({ contractAddress: await AztecAddress.random() }), () => Promise.resolve([])],
|
|
70
82
|
[
|
|
71
|
-
()
|
|
72
|
-
|
|
83
|
+
()=>Promise.resolve({
|
|
84
|
+
contractAddress: contractAddresses[0]
|
|
85
|
+
}),
|
|
86
|
+
()=>Promise.resolve(notes.filter((note)=>note.contractAddress.equals(contractAddresses[0])))
|
|
73
87
|
],
|
|
74
|
-
[() => Promise.resolve({ storageSlot: Fr.random() }), () => Promise.resolve([])],
|
|
75
|
-
[() => Promise.resolve({ txHash: notes[0].txHash }), () => Promise.resolve([notes[0]])],
|
|
76
|
-
[() => Promise.resolve({ txHash: randomTxHash() }), () => Promise.resolve([])],
|
|
77
88
|
[
|
|
78
|
-
()
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
async ()=>({
|
|
90
|
+
contractAddress: await AztecAddress.random()
|
|
91
|
+
}),
|
|
92
|
+
()=>Promise.resolve([])
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
()=>Promise.resolve({
|
|
96
|
+
storageSlot: storageSlots[0]
|
|
97
|
+
}),
|
|
98
|
+
()=>Promise.resolve(notes.filter((note)=>note.storageSlot.equals(storageSlots[0])))
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
()=>Promise.resolve({
|
|
102
|
+
storageSlot: Fr.random()
|
|
103
|
+
}),
|
|
104
|
+
()=>Promise.resolve([])
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
()=>Promise.resolve({
|
|
108
|
+
txHash: notes[0].txHash
|
|
109
|
+
}),
|
|
110
|
+
()=>Promise.resolve([
|
|
111
|
+
notes[0]
|
|
112
|
+
])
|
|
83
113
|
],
|
|
84
114
|
[
|
|
85
|
-
()
|
|
86
|
-
|
|
115
|
+
()=>Promise.resolve({
|
|
116
|
+
txHash: randomTxHash()
|
|
117
|
+
}),
|
|
118
|
+
()=>Promise.resolve([])
|
|
87
119
|
],
|
|
88
120
|
[
|
|
89
|
-
()
|
|
90
|
-
|
|
121
|
+
()=>Promise.resolve({
|
|
122
|
+
owner: owners[0].address
|
|
123
|
+
}),
|
|
124
|
+
async ()=>{
|
|
125
|
+
const ownerAddressPoint = await owners[0].address.toAddressPoint();
|
|
126
|
+
return notes.filter((note)=>note.addressPoint.equals(ownerAddressPoint));
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
[
|
|
130
|
+
()=>Promise.resolve({
|
|
131
|
+
contractAddress: contractAddresses[0],
|
|
132
|
+
storageSlot: storageSlots[0]
|
|
133
|
+
}),
|
|
134
|
+
()=>Promise.resolve(notes.filter((note)=>note.contractAddress.equals(contractAddresses[0]) && note.storageSlot.equals(storageSlots[0])))
|
|
91
135
|
],
|
|
136
|
+
[
|
|
137
|
+
()=>Promise.resolve({
|
|
138
|
+
contractAddress: contractAddresses[0],
|
|
139
|
+
storageSlot: storageSlots[1]
|
|
140
|
+
}),
|
|
141
|
+
()=>Promise.resolve([])
|
|
142
|
+
]
|
|
92
143
|
];
|
|
93
|
-
beforeEach(async ()
|
|
94
|
-
owners = await timesParallel(2, ()
|
|
95
|
-
contractAddresses = await timesParallel(2, ()
|
|
96
|
-
storageSlots = times(2, ()
|
|
97
|
-
notes = await timesParallel(10, async (i)
|
|
144
|
+
beforeEach(async ()=>{
|
|
145
|
+
owners = await timesParallel(2, ()=>CompleteAddress.random());
|
|
146
|
+
contractAddresses = await timesParallel(2, ()=>AztecAddress.random());
|
|
147
|
+
storageSlots = times(2, ()=>Fr.random());
|
|
148
|
+
notes = await timesParallel(10, async (i)=>{
|
|
98
149
|
const addressPoint = await owners[i % owners.length].address.toAddressPoint();
|
|
99
150
|
return NoteDao.random({
|
|
100
151
|
contractAddress: contractAddresses[i % contractAddresses.length],
|
|
101
152
|
storageSlot: storageSlots[i % storageSlots.length],
|
|
102
153
|
addressPoint,
|
|
103
154
|
index: BigInt(i),
|
|
104
|
-
l2BlockNumber: i
|
|
155
|
+
l2BlockNumber: i
|
|
105
156
|
});
|
|
106
157
|
});
|
|
107
|
-
for (const owner of owners)
|
|
158
|
+
for (const owner of owners){
|
|
108
159
|
await database.addCompleteAddress(owner);
|
|
109
160
|
}
|
|
110
161
|
});
|
|
111
|
-
it.each(filteringTests)('stores notes in bulk and retrieves notes', async (getFilter, getExpected)
|
|
162
|
+
it.each(filteringTests)('stores notes in bulk and retrieves notes', async (getFilter, getExpected)=>{
|
|
112
163
|
await database.addNotes(notes);
|
|
113
164
|
const returnedNotes = await database.getNotes(await getFilter());
|
|
114
165
|
const expected = await getExpected();
|
|
115
166
|
expect(returnedNotes.sort()).toEqual(expected.sort());
|
|
116
167
|
});
|
|
117
|
-
it.each(filteringTests)('stores notes one by one and retrieves notes', async (getFilter, getExpected)
|
|
118
|
-
for (const note of notes)
|
|
168
|
+
it.each(filteringTests)('stores notes one by one and retrieves notes', async (getFilter, getExpected)=>{
|
|
169
|
+
for (const note of notes){
|
|
119
170
|
await database.addNote(note);
|
|
120
171
|
}
|
|
121
172
|
const returnedNotes = await database.getNotes(await getFilter());
|
|
122
173
|
const expected = await getExpected();
|
|
123
174
|
expect(returnedNotes.sort()).toEqual(expected.sort());
|
|
124
175
|
});
|
|
125
|
-
it.each(filteringTests)('retrieves nullified notes', async (getFilter, getExpected)
|
|
176
|
+
it.each(filteringTests)('retrieves nullified notes', async (getFilter, getExpected)=>{
|
|
126
177
|
await database.addNotes(notes);
|
|
127
178
|
// Nullify all notes and use the same filter as other test cases
|
|
128
|
-
for (const owner of owners)
|
|
179
|
+
for (const owner of owners){
|
|
129
180
|
const ownerAddressPoint = await owner.address.toAddressPoint();
|
|
130
|
-
const notesToNullify = notes.filter(note
|
|
131
|
-
const nullifiers = notesToNullify.map(note
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
181
|
+
const notesToNullify = notes.filter((note)=>note.addressPoint.equals(ownerAddressPoint));
|
|
182
|
+
const nullifiers = notesToNullify.map((note)=>({
|
|
183
|
+
data: note.siloedNullifier,
|
|
184
|
+
l2BlockNumber: note.l2BlockNumber,
|
|
185
|
+
l2BlockHash: note.l2BlockHash
|
|
186
|
+
}));
|
|
136
187
|
await expect(database.removeNullifiedNotes(nullifiers, ownerAddressPoint)).resolves.toEqual(notesToNullify);
|
|
137
188
|
}
|
|
138
189
|
const filter = await getFilter();
|
|
139
|
-
const returnedNotes = await database.getNotes({
|
|
190
|
+
const returnedNotes = await database.getNotes({
|
|
191
|
+
...filter,
|
|
192
|
+
status: NoteStatus.ACTIVE_OR_NULLIFIED
|
|
193
|
+
});
|
|
140
194
|
const expected = await getExpected();
|
|
141
195
|
expect(returnedNotes.sort()).toEqual(expected.sort());
|
|
142
196
|
});
|
|
143
|
-
it('skips nullified notes by default or when requesting active', async ()
|
|
197
|
+
it('skips nullified notes by default or when requesting active', async ()=>{
|
|
144
198
|
await database.addNotes(notes);
|
|
145
199
|
const ownerAddressPoint = await owners[0].address.toAddressPoint();
|
|
146
|
-
const notesToNullify = notes.filter(note
|
|
147
|
-
const nullifiers = notesToNullify.map(note
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
200
|
+
const notesToNullify = notes.filter((note)=>note.addressPoint.equals(ownerAddressPoint));
|
|
201
|
+
const nullifiers = notesToNullify.map((note)=>({
|
|
202
|
+
data: note.siloedNullifier,
|
|
203
|
+
l2BlockNumber: note.l2BlockNumber,
|
|
204
|
+
l2BlockHash: note.l2BlockHash
|
|
205
|
+
}));
|
|
152
206
|
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].addressPoint)).resolves.toEqual(notesToNullify);
|
|
153
207
|
const actualNotesWithDefault = await database.getNotes({});
|
|
154
|
-
const actualNotesWithActive = await database.getNotes({
|
|
208
|
+
const actualNotesWithActive = await database.getNotes({
|
|
209
|
+
status: NoteStatus.ACTIVE
|
|
210
|
+
});
|
|
155
211
|
expect(actualNotesWithDefault).toEqual(actualNotesWithActive);
|
|
156
|
-
expect(actualNotesWithActive).toEqual(notes.filter(note
|
|
212
|
+
expect(actualNotesWithActive).toEqual(notes.filter((note)=>!notesToNullify.includes(note)));
|
|
157
213
|
});
|
|
158
|
-
it('handles note unnullification', async ()
|
|
159
|
-
await database.setHeader(makeHeader(randomInt(1000), 100, 0 /** slot number */));
|
|
214
|
+
it('handles note unnullification', async ()=>{
|
|
215
|
+
await database.setHeader(makeHeader(randomInt(1000), 100, 0 /** slot number */ ));
|
|
160
216
|
await database.addNotes(notes);
|
|
161
217
|
const ownerAddressPoint = await owners[0].address.toAddressPoint();
|
|
162
|
-
const notesToNullify = notes.filter(note
|
|
163
|
-
const nullifiers = notesToNullify.map(note
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
218
|
+
const notesToNullify = notes.filter((note)=>note.addressPoint.equals(ownerAddressPoint));
|
|
219
|
+
const nullifiers = notesToNullify.map((note)=>({
|
|
220
|
+
data: note.siloedNullifier,
|
|
221
|
+
l2BlockNumber: 99,
|
|
222
|
+
l2BlockHash: Fr.random().toString()
|
|
223
|
+
}));
|
|
168
224
|
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].addressPoint)).resolves.toEqual(notesToNullify);
|
|
169
225
|
await expect(database.unnullifyNotesAfter(98)).resolves.toEqual(undefined);
|
|
170
|
-
const result = await database.getNotes({
|
|
171
|
-
|
|
226
|
+
const result = await database.getNotes({
|
|
227
|
+
status: NoteStatus.ACTIVE,
|
|
228
|
+
owner: owners[0].address
|
|
229
|
+
});
|
|
230
|
+
expect(result.sort()).toEqual([
|
|
231
|
+
...notesToNullify
|
|
232
|
+
].sort());
|
|
172
233
|
});
|
|
173
|
-
it('returns active and nullified notes when requesting either', async ()
|
|
234
|
+
it('returns active and nullified notes when requesting either', async ()=>{
|
|
174
235
|
await database.addNotes(notes);
|
|
175
236
|
const ownerAddressPoint = await owners[0].address.toAddressPoint();
|
|
176
|
-
const notesToNullify = notes.filter(note
|
|
177
|
-
const nullifiers = notesToNullify.map(note
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
237
|
+
const notesToNullify = notes.filter((note)=>note.addressPoint.equals(ownerAddressPoint));
|
|
238
|
+
const nullifiers = notesToNullify.map((note)=>({
|
|
239
|
+
data: note.siloedNullifier,
|
|
240
|
+
l2BlockNumber: note.l2BlockNumber,
|
|
241
|
+
l2BlockHash: note.l2BlockHash
|
|
242
|
+
}));
|
|
182
243
|
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].addressPoint)).resolves.toEqual(notesToNullify);
|
|
183
244
|
const result = await database.getNotes({
|
|
184
|
-
status: NoteStatus.ACTIVE_OR_NULLIFIED
|
|
245
|
+
status: NoteStatus.ACTIVE_OR_NULLIFIED
|
|
185
246
|
});
|
|
186
247
|
// We have to compare the sorted arrays since the database does not return the same order as when originally
|
|
187
248
|
// inserted combining active and nullified results.
|
|
188
|
-
expect(result.sort()).toEqual([
|
|
249
|
+
expect(result.sort()).toEqual([
|
|
250
|
+
...notes
|
|
251
|
+
].sort());
|
|
189
252
|
});
|
|
190
|
-
it('stores notes one by one and retrieves notes with siloed account', async ()
|
|
191
|
-
for (const note of notes.slice(0, 5))
|
|
253
|
+
it('stores notes one by one and retrieves notes with siloed account', async ()=>{
|
|
254
|
+
for (const note of notes.slice(0, 5)){
|
|
192
255
|
await database.addNote(note, owners[0].address);
|
|
193
256
|
}
|
|
194
|
-
for (const note of notes.slice(5))
|
|
257
|
+
for (const note of notes.slice(5)){
|
|
195
258
|
await database.addNote(note, owners[1].address);
|
|
196
259
|
}
|
|
197
260
|
const owner0Notes = await database.getNotes({
|
|
198
|
-
scopes: [
|
|
261
|
+
scopes: [
|
|
262
|
+
owners[0].address
|
|
263
|
+
]
|
|
199
264
|
});
|
|
200
265
|
expect(owner0Notes.sort()).toEqual(notes.slice(0, 5).sort());
|
|
201
266
|
const owner1Notes = await database.getNotes({
|
|
202
|
-
scopes: [
|
|
267
|
+
scopes: [
|
|
268
|
+
owners[1].address
|
|
269
|
+
]
|
|
203
270
|
});
|
|
204
271
|
expect(owner1Notes.sort()).toEqual(notes.slice(5).sort());
|
|
205
272
|
const bothOwnerNotes = await database.getNotes({
|
|
206
|
-
scopes: [
|
|
273
|
+
scopes: [
|
|
274
|
+
owners[0].address,
|
|
275
|
+
owners[1].address
|
|
276
|
+
]
|
|
207
277
|
});
|
|
208
278
|
expect(bothOwnerNotes.sort()).toEqual(notes.sort());
|
|
209
279
|
});
|
|
210
|
-
it('a nullified note removes notes from all accounts in the pxe', async ()
|
|
280
|
+
it('a nullified note removes notes from all accounts in the pxe', async ()=>{
|
|
211
281
|
await database.addNote(notes[0], owners[0].address);
|
|
212
282
|
await database.addNote(notes[0], owners[1].address);
|
|
213
283
|
await expect(database.getNotes({
|
|
214
|
-
scopes: [
|
|
215
|
-
|
|
284
|
+
scopes: [
|
|
285
|
+
owners[0].address
|
|
286
|
+
]
|
|
287
|
+
})).resolves.toEqual([
|
|
288
|
+
notes[0]
|
|
289
|
+
]);
|
|
216
290
|
await expect(database.getNotes({
|
|
217
|
-
scopes: [
|
|
218
|
-
|
|
291
|
+
scopes: [
|
|
292
|
+
owners[1].address
|
|
293
|
+
]
|
|
294
|
+
})).resolves.toEqual([
|
|
295
|
+
notes[0]
|
|
296
|
+
]);
|
|
219
297
|
const ownerAddressPoint = await owners[0].address.toAddressPoint();
|
|
220
298
|
await expect(database.removeNullifiedNotes([
|
|
221
299
|
{
|
|
222
300
|
data: notes[0].siloedNullifier,
|
|
223
301
|
l2BlockHash: notes[0].l2BlockHash,
|
|
224
|
-
l2BlockNumber: notes[0].l2BlockNumber
|
|
225
|
-
}
|
|
226
|
-
], ownerAddressPoint)).resolves.toEqual([
|
|
302
|
+
l2BlockNumber: notes[0].l2BlockNumber
|
|
303
|
+
}
|
|
304
|
+
], ownerAddressPoint)).resolves.toEqual([
|
|
305
|
+
notes[0]
|
|
306
|
+
]);
|
|
227
307
|
await expect(database.getNotes({
|
|
228
|
-
scopes: [
|
|
308
|
+
scopes: [
|
|
309
|
+
owners[0].address
|
|
310
|
+
]
|
|
229
311
|
})).resolves.toEqual([]);
|
|
230
312
|
await expect(database.getNotes({
|
|
231
|
-
scopes: [
|
|
313
|
+
scopes: [
|
|
314
|
+
owners[1].address
|
|
315
|
+
]
|
|
232
316
|
})).resolves.toEqual([]);
|
|
233
317
|
});
|
|
234
|
-
it('removes notes after a given block', async ()
|
|
318
|
+
it('removes notes after a given block', async ()=>{
|
|
235
319
|
await database.addNotes(notes, owners[0].address);
|
|
236
320
|
await database.removeNotesAfter(5);
|
|
237
|
-
const result = await database.getNotes({
|
|
321
|
+
const result = await database.getNotes({
|
|
322
|
+
scopes: [
|
|
323
|
+
owners[0].address
|
|
324
|
+
]
|
|
325
|
+
});
|
|
238
326
|
expect(new Set(result)).toEqual(new Set(notes.slice(0, 6)));
|
|
239
327
|
});
|
|
240
328
|
});
|
|
241
|
-
describe('block header', ()
|
|
242
|
-
it('stores and retrieves the block header', async ()
|
|
243
|
-
const header = makeHeader(randomInt(1000), INITIAL_L2_BLOCK_NUM, 0 /** slot number */);
|
|
329
|
+
describe('block header', ()=>{
|
|
330
|
+
it('stores and retrieves the block header', async ()=>{
|
|
331
|
+
const header = makeHeader(randomInt(1000), INITIAL_L2_BLOCK_NUM, 0 /** slot number */ );
|
|
244
332
|
await database.setHeader(header);
|
|
245
333
|
await expect(database.getBlockHeader()).resolves.toEqual(header);
|
|
246
334
|
});
|
|
247
|
-
it('rejects getting header if no block set', async ()
|
|
248
|
-
await expect(()
|
|
335
|
+
it('rejects getting header if no block set', async ()=>{
|
|
336
|
+
await expect(()=>database.getBlockHeader()).rejects.toThrow();
|
|
249
337
|
});
|
|
250
338
|
});
|
|
251
|
-
describe('addresses', ()
|
|
252
|
-
it('stores and retrieves addresses', async ()
|
|
339
|
+
describe('addresses', ()=>{
|
|
340
|
+
it('stores and retrieves addresses', async ()=>{
|
|
253
341
|
const address = await CompleteAddress.random();
|
|
254
342
|
await expect(database.addCompleteAddress(address)).resolves.toBe(true);
|
|
255
343
|
await expect(database.getCompleteAddress(address.address)).resolves.toEqual(address);
|
|
256
344
|
});
|
|
257
|
-
it('silently ignores an address it already knows about', async ()
|
|
345
|
+
it('silently ignores an address it already knows about', async ()=>{
|
|
258
346
|
const address = await CompleteAddress.random();
|
|
259
347
|
await expect(database.addCompleteAddress(address)).resolves.toBe(true);
|
|
260
348
|
await expect(database.addCompleteAddress(address)).resolves.toBe(false);
|
|
261
349
|
});
|
|
262
|
-
it.skip('refuses to overwrite an address with a different public key', async ()
|
|
350
|
+
it.skip('refuses to overwrite an address with a different public key', async ()=>{
|
|
263
351
|
const address = await CompleteAddress.random();
|
|
264
352
|
const otherAddress = await CompleteAddress.create(address.address, new PublicKeys(await Point.random(), await Point.random(), await Point.random(), await Point.random()), address.partialAddress);
|
|
265
353
|
await database.addCompleteAddress(address);
|
|
266
354
|
await expect(database.addCompleteAddress(otherAddress)).rejects.toThrow();
|
|
267
355
|
});
|
|
268
|
-
it('returns all addresses', async ()
|
|
269
|
-
const addresses = await timesParallel(10, ()
|
|
270
|
-
for (const address of addresses)
|
|
356
|
+
it('returns all addresses', async ()=>{
|
|
357
|
+
const addresses = await timesParallel(10, ()=>CompleteAddress.random());
|
|
358
|
+
for (const address of addresses){
|
|
271
359
|
await database.addCompleteAddress(address);
|
|
272
360
|
}
|
|
273
361
|
const result = await database.getCompleteAddresses();
|
|
274
362
|
expect(result).toEqual(expect.arrayContaining(addresses));
|
|
275
363
|
});
|
|
276
|
-
it('returns a single address', async ()
|
|
277
|
-
const addresses = await timesParallel(10, ()
|
|
278
|
-
for (const address of addresses)
|
|
364
|
+
it('returns a single address', async ()=>{
|
|
365
|
+
const addresses = await timesParallel(10, ()=>CompleteAddress.random());
|
|
366
|
+
for (const address of addresses){
|
|
279
367
|
await database.addCompleteAddress(address);
|
|
280
368
|
}
|
|
281
369
|
const result = await database.getCompleteAddress(addresses[3].address);
|
|
282
370
|
expect(result).toEqual(addresses[3]);
|
|
283
371
|
});
|
|
284
|
-
it("returns an empty array if it doesn't have addresses", async ()
|
|
372
|
+
it("returns an empty array if it doesn't have addresses", async ()=>{
|
|
285
373
|
expect(await database.getCompleteAddresses()).toEqual([]);
|
|
286
374
|
});
|
|
287
|
-
it("returns undefined if it doesn't have an address", async ()
|
|
375
|
+
it("returns undefined if it doesn't have an address", async ()=>{
|
|
288
376
|
const completeAddress = await CompleteAddress.random();
|
|
289
377
|
expect(await database.getCompleteAddress(completeAddress.address)).toBeUndefined();
|
|
290
378
|
});
|
|
291
379
|
});
|
|
292
|
-
describe('contracts', ()
|
|
293
|
-
it('stores a contract artifact', async ()
|
|
380
|
+
describe('contracts', ()=>{
|
|
381
|
+
it('stores a contract artifact', async ()=>{
|
|
294
382
|
const artifact = BenchmarkingContractArtifact;
|
|
295
383
|
const id = Fr.random();
|
|
296
384
|
await database.addContractArtifact(id, artifact);
|
|
297
385
|
await expect(database.getContractArtifact(id)).resolves.toEqual(artifact);
|
|
298
386
|
});
|
|
299
|
-
it('does not store a contract artifact with a duplicate private function selector', async ()
|
|
387
|
+
it('does not store a contract artifact with a duplicate private function selector', async ()=>{
|
|
300
388
|
const artifact = TestContractArtifact;
|
|
301
|
-
const index = artifact.functions.findIndex(fn
|
|
389
|
+
const index = artifact.functions.findIndex((fn)=>fn.functionType === FunctionType.PRIVATE);
|
|
302
390
|
const copiedFn = structuredClone(artifact.functions[index]);
|
|
303
391
|
artifact.functions.push(copiedFn);
|
|
304
392
|
const id = Fr.random();
|
|
305
393
|
await expect(database.addContractArtifact(id, artifact)).rejects.toThrow('Repeated function selectors of private functions');
|
|
306
394
|
});
|
|
307
|
-
it('stores a contract instance', async ()
|
|
395
|
+
it('stores a contract instance', async ()=>{
|
|
308
396
|
const address = await AztecAddress.random();
|
|
309
397
|
const instance = (await SerializableContractInstance.random()).withAddress(address);
|
|
310
398
|
await database.addContractInstance(instance);
|
|
311
399
|
await expect(database.getContractInstance(address)).resolves.toEqual(instance);
|
|
312
400
|
});
|
|
313
401
|
});
|
|
314
|
-
describe('contract non-volatile database', ()
|
|
402
|
+
describe('contract non-volatile database', ()=>{
|
|
315
403
|
let contract;
|
|
316
|
-
beforeEach(async ()
|
|
404
|
+
beforeEach(async ()=>{
|
|
317
405
|
// Setup mock contract address
|
|
318
406
|
contract = await AztecAddress.random();
|
|
319
407
|
});
|
|
320
|
-
it('stores and loads a single value', async ()
|
|
408
|
+
it('stores and loads a single value', async ()=>{
|
|
321
409
|
const slot = new Fr(1);
|
|
322
|
-
const values = [
|
|
410
|
+
const values = [
|
|
411
|
+
new Fr(42)
|
|
412
|
+
];
|
|
323
413
|
await database.dbStore(contract, slot, values);
|
|
324
414
|
const result = await database.dbLoad(contract, slot);
|
|
325
415
|
expect(result).toEqual(values);
|
|
326
416
|
});
|
|
327
|
-
it('stores and loads multiple values', async ()
|
|
417
|
+
it('stores and loads multiple values', async ()=>{
|
|
328
418
|
const slot = new Fr(1);
|
|
329
|
-
const values = [
|
|
419
|
+
const values = [
|
|
420
|
+
new Fr(42),
|
|
421
|
+
new Fr(43),
|
|
422
|
+
new Fr(44)
|
|
423
|
+
];
|
|
330
424
|
await database.dbStore(contract, slot, values);
|
|
331
425
|
const result = await database.dbLoad(contract, slot);
|
|
332
426
|
expect(result).toEqual(values);
|
|
333
427
|
});
|
|
334
|
-
it('overwrites existing values', async ()
|
|
428
|
+
it('overwrites existing values', async ()=>{
|
|
335
429
|
const slot = new Fr(1);
|
|
336
|
-
const initialValues = [
|
|
337
|
-
|
|
430
|
+
const initialValues = [
|
|
431
|
+
new Fr(42)
|
|
432
|
+
];
|
|
433
|
+
const newValues = [
|
|
434
|
+
new Fr(100)
|
|
435
|
+
];
|
|
338
436
|
await database.dbStore(contract, slot, initialValues);
|
|
339
437
|
await database.dbStore(contract, slot, newValues);
|
|
340
438
|
const result = await database.dbLoad(contract, slot);
|
|
341
439
|
expect(result).toEqual(newValues);
|
|
342
440
|
});
|
|
343
|
-
it('stores values for different contracts independently', async ()
|
|
441
|
+
it('stores values for different contracts independently', async ()=>{
|
|
344
442
|
const anotherContract = await AztecAddress.random();
|
|
345
443
|
const slot = new Fr(1);
|
|
346
|
-
const values1 = [
|
|
347
|
-
|
|
444
|
+
const values1 = [
|
|
445
|
+
new Fr(42)
|
|
446
|
+
];
|
|
447
|
+
const values2 = [
|
|
448
|
+
new Fr(100)
|
|
449
|
+
];
|
|
348
450
|
await database.dbStore(contract, slot, values1);
|
|
349
451
|
await database.dbStore(anotherContract, slot, values2);
|
|
350
452
|
const result1 = await database.dbLoad(contract, slot);
|
|
@@ -352,34 +454,48 @@ export function describePxeDatabase(getDatabase) {
|
|
|
352
454
|
expect(result1).toEqual(values1);
|
|
353
455
|
expect(result2).toEqual(values2);
|
|
354
456
|
});
|
|
355
|
-
it('returns null for non-existent slots', async ()
|
|
457
|
+
it('returns null for non-existent slots', async ()=>{
|
|
356
458
|
const slot = Fr.random();
|
|
357
459
|
const result = await database.dbLoad(contract, slot);
|
|
358
460
|
expect(result).toBeNull();
|
|
359
461
|
});
|
|
360
|
-
it('deletes a slot', async ()
|
|
462
|
+
it('deletes a slot', async ()=>{
|
|
361
463
|
const slot = new Fr(1);
|
|
362
|
-
const values = [
|
|
464
|
+
const values = [
|
|
465
|
+
new Fr(42)
|
|
466
|
+
];
|
|
363
467
|
await database.dbStore(contract, slot, values);
|
|
364
468
|
await database.dbDelete(contract, slot);
|
|
365
469
|
expect(await database.dbLoad(contract, slot)).toBeNull();
|
|
366
470
|
});
|
|
367
|
-
it('deletes an empty slot', async ()
|
|
471
|
+
it('deletes an empty slot', async ()=>{
|
|
368
472
|
const slot = new Fr(1);
|
|
369
473
|
await database.dbDelete(contract, slot);
|
|
370
474
|
expect(await database.dbLoad(contract, slot)).toBeNull();
|
|
371
475
|
});
|
|
372
|
-
it('copies a single value', async ()
|
|
476
|
+
it('copies a single value', async ()=>{
|
|
373
477
|
const slot = new Fr(1);
|
|
374
|
-
const values = [
|
|
478
|
+
const values = [
|
|
479
|
+
new Fr(42)
|
|
480
|
+
];
|
|
375
481
|
await database.dbStore(contract, slot, values);
|
|
376
482
|
const dstSlot = new Fr(5);
|
|
377
483
|
await database.dbCopy(contract, slot, dstSlot, 1);
|
|
378
484
|
expect(await database.dbLoad(contract, dstSlot)).toEqual(values);
|
|
379
485
|
});
|
|
380
|
-
it('copies multiple non-overlapping values', async ()
|
|
486
|
+
it('copies multiple non-overlapping values', async ()=>{
|
|
381
487
|
const src = new Fr(1);
|
|
382
|
-
const valuesArray = [
|
|
488
|
+
const valuesArray = [
|
|
489
|
+
[
|
|
490
|
+
new Fr(42)
|
|
491
|
+
],
|
|
492
|
+
[
|
|
493
|
+
new Fr(1337)
|
|
494
|
+
],
|
|
495
|
+
[
|
|
496
|
+
new Fr(13)
|
|
497
|
+
]
|
|
498
|
+
];
|
|
383
499
|
await database.dbStore(contract, src, valuesArray[0]);
|
|
384
500
|
await database.dbStore(contract, src.add(new Fr(1)), valuesArray[1]);
|
|
385
501
|
await database.dbStore(contract, src.add(new Fr(2)), valuesArray[2]);
|
|
@@ -389,9 +505,19 @@ export function describePxeDatabase(getDatabase) {
|
|
|
389
505
|
expect(await database.dbLoad(contract, dst.add(new Fr(1)))).toEqual(valuesArray[1]);
|
|
390
506
|
expect(await database.dbLoad(contract, dst.add(new Fr(2)))).toEqual(valuesArray[2]);
|
|
391
507
|
});
|
|
392
|
-
it('copies overlapping values with src ahead', async ()
|
|
508
|
+
it('copies overlapping values with src ahead', async ()=>{
|
|
393
509
|
const src = new Fr(1);
|
|
394
|
-
const valuesArray = [
|
|
510
|
+
const valuesArray = [
|
|
511
|
+
[
|
|
512
|
+
new Fr(42)
|
|
513
|
+
],
|
|
514
|
+
[
|
|
515
|
+
new Fr(1337)
|
|
516
|
+
],
|
|
517
|
+
[
|
|
518
|
+
new Fr(13)
|
|
519
|
+
]
|
|
520
|
+
];
|
|
395
521
|
await database.dbStore(contract, src, valuesArray[0]);
|
|
396
522
|
await database.dbStore(contract, src.add(new Fr(1)), valuesArray[1]);
|
|
397
523
|
await database.dbStore(contract, src.add(new Fr(2)), valuesArray[2]);
|
|
@@ -405,9 +531,19 @@ export function describePxeDatabase(getDatabase) {
|
|
|
405
531
|
expect(await database.dbLoad(contract, src.add(new Fr(1)))).toEqual(valuesArray[0]); // dst[0]
|
|
406
532
|
expect(await database.dbLoad(contract, src.add(new Fr(2)))).toEqual(valuesArray[1]); // dst[1]
|
|
407
533
|
});
|
|
408
|
-
it('copies overlapping values with dst ahead', async ()
|
|
534
|
+
it('copies overlapping values with dst ahead', async ()=>{
|
|
409
535
|
const src = new Fr(5);
|
|
410
|
-
const valuesArray = [
|
|
536
|
+
const valuesArray = [
|
|
537
|
+
[
|
|
538
|
+
new Fr(42)
|
|
539
|
+
],
|
|
540
|
+
[
|
|
541
|
+
new Fr(1337)
|
|
542
|
+
],
|
|
543
|
+
[
|
|
544
|
+
new Fr(13)
|
|
545
|
+
]
|
|
546
|
+
];
|
|
411
547
|
await database.dbStore(contract, src, valuesArray[0]);
|
|
412
548
|
await database.dbStore(contract, src.add(new Fr(1)), valuesArray[1]);
|
|
413
549
|
await database.dbStore(contract, src.add(new Fr(2)), valuesArray[2]);
|
|
@@ -421,9 +557,19 @@ export function describePxeDatabase(getDatabase) {
|
|
|
421
557
|
expect(await database.dbLoad(contract, src.add(new Fr(1)))).toEqual(valuesArray[2]); // dst[2]
|
|
422
558
|
expect(await database.dbLoad(contract, src.add(new Fr(2)))).toEqual(valuesArray[2]); // src[2] (unchanged)
|
|
423
559
|
});
|
|
424
|
-
it('copying fails if any value is empty', async ()
|
|
560
|
+
it('copying fails if any value is empty', async ()=>{
|
|
425
561
|
const src = new Fr(1);
|
|
426
|
-
const valuesArray = [
|
|
562
|
+
const valuesArray = [
|
|
563
|
+
[
|
|
564
|
+
new Fr(42)
|
|
565
|
+
],
|
|
566
|
+
[
|
|
567
|
+
new Fr(1337)
|
|
568
|
+
],
|
|
569
|
+
[
|
|
570
|
+
new Fr(13)
|
|
571
|
+
]
|
|
572
|
+
];
|
|
427
573
|
await database.dbStore(contract, src, valuesArray[0]);
|
|
428
574
|
// We skip src[1]
|
|
429
575
|
await database.dbStore(contract, src.add(new Fr(2)), valuesArray[2]);
|
|
@@ -433,4 +579,3 @@ export function describePxeDatabase(getDatabase) {
|
|
|
433
579
|
});
|
|
434
580
|
});
|
|
435
581
|
}
|
|
436
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHhlX2RhdGFiYXNlX3Rlc3Rfc3VpdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YWJhc2UvcHhlX2RhdGFiYXNlX3Rlc3Rfc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBb0IsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEYsT0FBTyxFQUNMLFlBQVksRUFDWixlQUFlLEVBQ2Ysb0JBQW9CLEVBQ3BCLFVBQVUsRUFDViw0QkFBNEIsR0FDN0IsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUNyRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUVyRSxPQUFPLEtBQUssTUFBTSxjQUFjLENBQUM7QUFFakMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUd4Qzs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsV0FBOEI7SUFDaEUsSUFBSSxRQUFxQixDQUFDO0lBRTFCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCxRQUFRLEdBQUcsV0FBVyxFQUFFLENBQUM7SUFDM0IsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtRQUN4QixRQUFRLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxFQUFFO1lBQzlC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
|