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