@aztec/txe 2.0.0-nightly.20250903 → 2.0.0-rc.2
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/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/oracle/txe_oracle.d.ts +2 -15
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +8 -78
- package/dest/oracle/txe_oracle_public_context.d.ts +34 -0
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_public_context.js +126 -0
- package/dest/oracle/txe_typed_oracle.d.ts +8 -2
- package/dest/oracle/txe_typed_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_typed_oracle.js +18 -0
- package/dest/txe_service/txe_service.d.ts +25 -9
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +97 -81
- package/dest/txe_session.d.ts +22 -10
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +62 -46
- package/package.json +15 -15
- package/src/index.ts +1 -0
- package/src/oracle/txe_oracle.ts +9 -93
- package/src/oracle/txe_oracle_public_context.ts +198 -0
- package/src/oracle/txe_typed_oracle.ts +26 -2
- package/src/txe_service/txe_service.ts +125 -86
- package/src/txe_session.ts +96 -58
|
@@ -5,37 +5,56 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
5
5
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
6
6
|
import { addressFromSingle, arrayOfArraysToBoundedVecOfArrays, arrayToBoundedVec, bufferToU8Array, fromArray, fromSingle, fromUintArray, fromUintBoundedVec, toArray, toForeignCallResult, toSingle } from '../util/encoding.js';
|
|
7
7
|
export class TXEService {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
stateHandler;
|
|
9
|
+
oracleHandler;
|
|
10
|
+
/**
|
|
11
|
+
* Create a new instance of `TXEService` that will translate all TXE RPC calls to and from the foreign
|
|
12
|
+
* (`ForeignCallSingle`, `ForeignCallResult`, etc.) and native TS types, delegating actual execution of the oracles
|
|
13
|
+
* to the different handlers.
|
|
14
|
+
* @param stateHandler The handler that will process TXE session state transitions, such as entering a private or
|
|
15
|
+
* public context.
|
|
16
|
+
* @param oracleHandler The handler that will process all other oracle calls that are not directly related to session
|
|
17
|
+
* state.
|
|
18
|
+
*/ constructor(stateHandler, oracleHandler){
|
|
19
|
+
this.stateHandler = stateHandler;
|
|
20
|
+
this.oracleHandler = oracleHandler;
|
|
21
|
+
}
|
|
22
|
+
// TXE session state transition functions - these get handled by the state handler
|
|
23
|
+
async txeSetTopLevelTXEContext() {
|
|
24
|
+
await this.stateHandler.setTopLevelContext();
|
|
25
|
+
return toForeignCallResult([]);
|
|
26
|
+
}
|
|
27
|
+
async txeSetPrivateTXEContext(foreignContractAddressIsSome, foreignContractAddressValue, foreignHistoricalBlockNumberIsSome, foreignHistoricalBlockNumberValue) {
|
|
28
|
+
const contractAddress = fromSingle(foreignContractAddressIsSome).toBool() ? AztecAddress.fromField(fromSingle(foreignContractAddressValue)) : undefined;
|
|
29
|
+
const historicalBlockNumber = fromSingle(foreignHistoricalBlockNumberIsSome).toBool() ? fromSingle(foreignHistoricalBlockNumberValue).toNumber() : undefined;
|
|
30
|
+
const privateContextInputs = await this.stateHandler.setPrivateContext(contractAddress, historicalBlockNumber);
|
|
31
|
+
return toForeignCallResult(privateContextInputs.toFields().map(toSingle));
|
|
11
32
|
}
|
|
12
|
-
|
|
13
|
-
|
|
33
|
+
async txeSetPublicTXEContext(foreignContractAddressIsSome, foreignContractAddressValue) {
|
|
34
|
+
const contractAddress = fromSingle(foreignContractAddressIsSome).toBool() ? AztecAddress.fromField(fromSingle(foreignContractAddressValue)) : undefined;
|
|
35
|
+
await this.stateHandler.setPublicContext(contractAddress);
|
|
36
|
+
return toForeignCallResult([]);
|
|
14
37
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return toForeignCallResult(inputs.toFields().map(toSingle));
|
|
38
|
+
async txeSetUtilityTXEContext(foreignContractAddressIsSome, foreignContractAddressValue) {
|
|
39
|
+
const contractAddress = fromSingle(foreignContractAddressIsSome).toBool() ? AztecAddress.fromField(fromSingle(foreignContractAddressValue)) : undefined;
|
|
40
|
+
await this.stateHandler.setUtilityContext(contractAddress);
|
|
41
|
+
return toForeignCallResult([]);
|
|
20
42
|
}
|
|
43
|
+
// Other oracles - these get handled by the oracle handler
|
|
44
|
+
// TXE-specific oracles
|
|
21
45
|
async txeAdvanceBlocksBy(foreignBlocks) {
|
|
22
46
|
const blocks = fromSingle(foreignBlocks).toNumber();
|
|
23
|
-
await this.
|
|
47
|
+
await this.oracleHandler.txeAdvanceBlocksBy(blocks);
|
|
24
48
|
return toForeignCallResult([]);
|
|
25
49
|
}
|
|
26
50
|
txeAdvanceTimestampBy(foreignDuration) {
|
|
27
51
|
const duration = fromSingle(foreignDuration).toBigInt();
|
|
28
|
-
this.
|
|
29
|
-
return toForeignCallResult([]);
|
|
30
|
-
}
|
|
31
|
-
txeSetContractAddress(foreignAddress) {
|
|
32
|
-
const address = addressFromSingle(foreignAddress);
|
|
33
|
-
this.executor.txeSetContractAddress(address);
|
|
52
|
+
this.oracleHandler.txeAdvanceTimestampBy(duration);
|
|
34
53
|
return toForeignCallResult([]);
|
|
35
54
|
}
|
|
36
55
|
async txeDeploy(artifact, instance, foreignSecret) {
|
|
37
56
|
const secret = fromSingle(foreignSecret);
|
|
38
|
-
await this.
|
|
57
|
+
await this.oracleHandler.txeDeploy(artifact, instance, secret);
|
|
39
58
|
return toForeignCallResult([
|
|
40
59
|
toArray([
|
|
41
60
|
instance.salt,
|
|
@@ -48,7 +67,7 @@ export class TXEService {
|
|
|
48
67
|
}
|
|
49
68
|
async txeCreateAccount(foreignSecret) {
|
|
50
69
|
const secret = fromSingle(foreignSecret);
|
|
51
|
-
const completeAddress = await this.
|
|
70
|
+
const completeAddress = await this.oracleHandler.txeCreateAccount(secret);
|
|
52
71
|
return toForeignCallResult([
|
|
53
72
|
toSingle(completeAddress.address),
|
|
54
73
|
...completeAddress.publicKeys.toFields().map(toSingle)
|
|
@@ -56,7 +75,7 @@ export class TXEService {
|
|
|
56
75
|
}
|
|
57
76
|
async txeAddAccount(artifact, instance, foreignSecret) {
|
|
58
77
|
const secret = fromSingle(foreignSecret);
|
|
59
|
-
const completeAddress = await this.
|
|
78
|
+
const completeAddress = await this.oracleHandler.txeAddAccount(artifact, instance, secret);
|
|
60
79
|
return toForeignCallResult([
|
|
61
80
|
toSingle(completeAddress.address),
|
|
62
81
|
...completeAddress.publicKeys.toFields().map(toSingle)
|
|
@@ -65,42 +84,42 @@ export class TXEService {
|
|
|
65
84
|
async txeAddAuthWitness(foreignAddress, foreignMessageHash) {
|
|
66
85
|
const address = addressFromSingle(foreignAddress);
|
|
67
86
|
const messageHash = fromSingle(foreignMessageHash);
|
|
68
|
-
await this.
|
|
87
|
+
await this.oracleHandler.txeAddAuthWitness(address, messageHash);
|
|
69
88
|
return toForeignCallResult([]);
|
|
70
89
|
}
|
|
71
90
|
// PXE oracles
|
|
72
91
|
utilityAssertCompatibleOracleVersion(foreignVersion) {
|
|
73
92
|
const version = fromSingle(foreignVersion).toNumber();
|
|
74
|
-
this.
|
|
93
|
+
this.oracleHandler.utilityAssertCompatibleOracleVersion(version);
|
|
75
94
|
return toForeignCallResult([]);
|
|
76
95
|
}
|
|
77
96
|
utilityGetRandomField() {
|
|
78
|
-
const randomField = this.
|
|
97
|
+
const randomField = this.oracleHandler.utilityGetRandomField();
|
|
79
98
|
return toForeignCallResult([
|
|
80
99
|
toSingle(randomField)
|
|
81
100
|
]);
|
|
82
101
|
}
|
|
83
102
|
async utilityGetContractAddress() {
|
|
84
|
-
const contractAddress = await this.
|
|
103
|
+
const contractAddress = await this.oracleHandler.utilityGetContractAddress();
|
|
85
104
|
return toForeignCallResult([
|
|
86
105
|
toSingle(contractAddress.toField())
|
|
87
106
|
]);
|
|
88
107
|
}
|
|
89
108
|
async utilityGetBlockNumber() {
|
|
90
|
-
const blockNumber = await this.
|
|
109
|
+
const blockNumber = await this.oracleHandler.utilityGetBlockNumber();
|
|
91
110
|
return toForeignCallResult([
|
|
92
111
|
toSingle(new Fr(blockNumber))
|
|
93
112
|
]);
|
|
94
113
|
}
|
|
95
114
|
// seems to be used to mean the timestamp of the last mined block in txe (but that's not what is done here)
|
|
96
115
|
async utilityGetTimestamp() {
|
|
97
|
-
const timestamp = await this.
|
|
116
|
+
const timestamp = await this.oracleHandler.utilityGetTimestamp();
|
|
98
117
|
return toForeignCallResult([
|
|
99
118
|
toSingle(new Fr(timestamp))
|
|
100
119
|
]);
|
|
101
120
|
}
|
|
102
121
|
async txeGetLastBlockTimestamp() {
|
|
103
|
-
const timestamp = await this.
|
|
122
|
+
const timestamp = await this.oracleHandler.txeGetLastBlockTimestamp();
|
|
104
123
|
return toForeignCallResult([
|
|
105
124
|
toSingle(new Fr(timestamp))
|
|
106
125
|
]);
|
|
@@ -109,12 +128,12 @@ export class TXEService {
|
|
|
109
128
|
privateStoreInExecutionCache(_foreignLength, foreignValues, foreignHash) {
|
|
110
129
|
const values = fromArray(foreignValues);
|
|
111
130
|
const hash = fromSingle(foreignHash);
|
|
112
|
-
this.
|
|
131
|
+
this.oracleHandler.privateStoreInExecutionCache(values, hash);
|
|
113
132
|
return toForeignCallResult([]);
|
|
114
133
|
}
|
|
115
134
|
async privateLoadFromExecutionCache(foreignHash) {
|
|
116
135
|
const hash = fromSingle(foreignHash);
|
|
117
|
-
const returns = await this.
|
|
136
|
+
const returns = await this.oracleHandler.privateLoadFromExecutionCache(hash);
|
|
118
137
|
return toForeignCallResult([
|
|
119
138
|
toArray(returns)
|
|
120
139
|
]);
|
|
@@ -123,7 +142,7 @@ export class TXEService {
|
|
|
123
142
|
utilityDebugLog(foreignMessage, _foreignLength, foreignFields) {
|
|
124
143
|
const message = fromArray(foreignMessage).map((field)=>String.fromCharCode(field.toNumber())).join('');
|
|
125
144
|
const fields = fromArray(foreignFields);
|
|
126
|
-
this.
|
|
145
|
+
this.oracleHandler.utilityDebugLog(message, fields);
|
|
127
146
|
return toForeignCallResult([]);
|
|
128
147
|
}
|
|
129
148
|
async utilityStorageRead(foreignContractAddress, foreignStartStorageSlot, foreignBlockNumber, foreignNumberOfElements) {
|
|
@@ -131,7 +150,7 @@ export class TXEService {
|
|
|
131
150
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
132
151
|
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
133
152
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
134
|
-
const values = await this.
|
|
153
|
+
const values = await this.oracleHandler.utilityStorageRead(contractAddress, startStorageSlot, blockNumber, numberOfElements);
|
|
135
154
|
return toForeignCallResult([
|
|
136
155
|
toArray(values)
|
|
137
156
|
]);
|
|
@@ -139,7 +158,7 @@ export class TXEService {
|
|
|
139
158
|
async utilityGetPublicDataWitness(foreignBlockNumber, foreignLeafSlot) {
|
|
140
159
|
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
141
160
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
142
|
-
const witness = await this.
|
|
161
|
+
const witness = await this.oracleHandler.utilityGetPublicDataWitness(blockNumber, leafSlot);
|
|
143
162
|
if (!witness) {
|
|
144
163
|
throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockNumber}.`);
|
|
145
164
|
}
|
|
@@ -162,7 +181,7 @@ export class TXEService {
|
|
|
162
181
|
const status = fromSingle(foreignStatus).toNumber();
|
|
163
182
|
const maxNotes = fromSingle(foreignMaxNotes).toNumber();
|
|
164
183
|
const packedRetrievedNoteLength = fromSingle(foreignPackedRetrievedNoteLength).toNumber();
|
|
165
|
-
const noteDatas = await this.
|
|
184
|
+
const noteDatas = await this.oracleHandler.utilityGetNotes(storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status);
|
|
166
185
|
const returnDataAsArrayOfArrays = noteDatas.map(packAsRetrievedNote);
|
|
167
186
|
// Now we convert each sub-array to an array of ForeignCallSingles
|
|
168
187
|
const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map((subArray)=>subArray.map(toSingle));
|
|
@@ -175,31 +194,31 @@ export class TXEService {
|
|
|
175
194
|
const note = fromArray(foreignNote);
|
|
176
195
|
const noteHash = fromSingle(foreignNoteHash);
|
|
177
196
|
const counter = fromSingle(foreignCounter).toNumber();
|
|
178
|
-
this.
|
|
197
|
+
this.oracleHandler.privateNotifyCreatedNote(storageSlot, noteTypeId, note, noteHash, counter);
|
|
179
198
|
return toForeignCallResult([]);
|
|
180
199
|
}
|
|
181
200
|
async privateNotifyNullifiedNote(foreignInnerNullifier, foreignNoteHash, foreignCounter) {
|
|
182
201
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
183
202
|
const noteHash = fromSingle(foreignNoteHash);
|
|
184
203
|
const counter = fromSingle(foreignCounter).toNumber();
|
|
185
|
-
await this.
|
|
204
|
+
await this.oracleHandler.privateNotifyNullifiedNote(innerNullifier, noteHash, counter);
|
|
186
205
|
return toForeignCallResult([]);
|
|
187
206
|
}
|
|
188
207
|
async privateNotifyCreatedNullifier(foreignInnerNullifier) {
|
|
189
208
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
190
|
-
await this.
|
|
209
|
+
await this.oracleHandler.privateNotifyCreatedNullifier(innerNullifier);
|
|
191
210
|
return toForeignCallResult([]);
|
|
192
211
|
}
|
|
193
212
|
async utilityCheckNullifierExists(foreignInnerNullifier) {
|
|
194
213
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
195
|
-
const exists = await this.
|
|
214
|
+
const exists = await this.oracleHandler.utilityCheckNullifierExists(innerNullifier);
|
|
196
215
|
return toForeignCallResult([
|
|
197
216
|
toSingle(new Fr(exists))
|
|
198
217
|
]);
|
|
199
218
|
}
|
|
200
219
|
async utilityGetContractInstance(foreignAddress) {
|
|
201
220
|
const address = addressFromSingle(foreignAddress);
|
|
202
|
-
const instance = await this.
|
|
221
|
+
const instance = await this.oracleHandler.utilityGetContractInstance(address);
|
|
203
222
|
return toForeignCallResult([
|
|
204
223
|
instance.salt,
|
|
205
224
|
instance.deployer.toField(),
|
|
@@ -210,7 +229,7 @@ export class TXEService {
|
|
|
210
229
|
}
|
|
211
230
|
async utilityGetPublicKeysAndPartialAddress(foreignAddress) {
|
|
212
231
|
const address = addressFromSingle(foreignAddress);
|
|
213
|
-
const { publicKeys, partialAddress } = await this.
|
|
232
|
+
const { publicKeys, partialAddress } = await this.oracleHandler.utilityGetCompleteAddress(address);
|
|
214
233
|
return toForeignCallResult([
|
|
215
234
|
toArray([
|
|
216
235
|
...publicKeys.toFields(),
|
|
@@ -220,7 +239,7 @@ export class TXEService {
|
|
|
220
239
|
}
|
|
221
240
|
async utilityGetKeyValidationRequest(foreignPkMHash) {
|
|
222
241
|
const pkMHash = fromSingle(foreignPkMHash);
|
|
223
|
-
const keyValidationRequest = await this.
|
|
242
|
+
const keyValidationRequest = await this.oracleHandler.utilityGetKeyValidationRequest(pkMHash);
|
|
224
243
|
return toForeignCallResult(keyValidationRequest.toFields().map(toSingle));
|
|
225
244
|
}
|
|
226
245
|
privateCallPrivateFunction(_foreignTargetContractAddress, _foreignFunctionSelector, _foreignArgsHash, _foreignSideEffectCounter, _foreignIsStaticCall) {
|
|
@@ -229,7 +248,7 @@ export class TXEService {
|
|
|
229
248
|
async utilityGetNullifierMembershipWitness(foreignBlockNumber, foreignNullifier) {
|
|
230
249
|
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
231
250
|
const nullifier = fromSingle(foreignNullifier);
|
|
232
|
-
const witness = await this.
|
|
251
|
+
const witness = await this.oracleHandler.utilityGetNullifierMembershipWitness(blockNumber, nullifier);
|
|
233
252
|
if (!witness) {
|
|
234
253
|
throw new Error(`Nullifier membership witness not found at block ${blockNumber}.`);
|
|
235
254
|
}
|
|
@@ -237,7 +256,7 @@ export class TXEService {
|
|
|
237
256
|
}
|
|
238
257
|
async utilityGetAuthWitness(foreignMessageHash) {
|
|
239
258
|
const messageHash = fromSingle(foreignMessageHash);
|
|
240
|
-
const authWitness = await this.
|
|
259
|
+
const authWitness = await this.oracleHandler.utilityGetAuthWitness(messageHash);
|
|
241
260
|
if (!authWitness) {
|
|
242
261
|
throw new Error(`Auth witness not found for message hash ${messageHash}.`);
|
|
243
262
|
}
|
|
@@ -255,20 +274,20 @@ export class TXEService {
|
|
|
255
274
|
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
256
275
|
}
|
|
257
276
|
async utilityGetChainId() {
|
|
258
|
-
const chainId = await this.
|
|
277
|
+
const chainId = await this.oracleHandler.utilityGetChainId();
|
|
259
278
|
return toForeignCallResult([
|
|
260
279
|
toSingle(chainId)
|
|
261
280
|
]);
|
|
262
281
|
}
|
|
263
282
|
async utilityGetVersion() {
|
|
264
|
-
const version = await this.
|
|
283
|
+
const version = await this.oracleHandler.utilityGetVersion();
|
|
265
284
|
return toForeignCallResult([
|
|
266
285
|
toSingle(version)
|
|
267
286
|
]);
|
|
268
287
|
}
|
|
269
288
|
async utilityGetBlockHeader(foreignBlockNumber) {
|
|
270
289
|
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
271
|
-
const header = await this.
|
|
290
|
+
const header = await this.oracleHandler.utilityGetBlockHeader(blockNumber);
|
|
272
291
|
if (!header) {
|
|
273
292
|
throw new Error(`Block header not found for block ${blockNumber}.`);
|
|
274
293
|
}
|
|
@@ -278,7 +297,7 @@ export class TXEService {
|
|
|
278
297
|
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
279
298
|
const treeId = fromSingle(foreignTreeId).toNumber();
|
|
280
299
|
const leafValue = fromSingle(foreignLeafValue);
|
|
281
|
-
const witness = await this.
|
|
300
|
+
const witness = await this.oracleHandler.utilityGetMembershipWitness(blockNumber, treeId, leafValue);
|
|
282
301
|
if (!witness) {
|
|
283
302
|
throw new Error(`Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${blockNumber}.`);
|
|
284
303
|
}
|
|
@@ -290,7 +309,7 @@ export class TXEService {
|
|
|
290
309
|
async utilityGetLowNullifierMembershipWitness(foreignBlockNumber, foreignNullifier) {
|
|
291
310
|
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
292
311
|
const nullifier = fromSingle(foreignNullifier);
|
|
293
|
-
const witness = await this.
|
|
312
|
+
const witness = await this.oracleHandler.utilityGetLowNullifierMembershipWitness(blockNumber, nullifier);
|
|
294
313
|
if (!witness) {
|
|
295
314
|
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockNumber}.`);
|
|
296
315
|
}
|
|
@@ -299,40 +318,40 @@ export class TXEService {
|
|
|
299
318
|
async utilityGetIndexedTaggingSecretAsSender(foreignSender, foreignRecipient) {
|
|
300
319
|
const sender = AztecAddress.fromField(fromSingle(foreignSender));
|
|
301
320
|
const recipient = AztecAddress.fromField(fromSingle(foreignRecipient));
|
|
302
|
-
const secret = await this.
|
|
321
|
+
const secret = await this.oracleHandler.utilityGetIndexedTaggingSecretAsSender(sender, recipient);
|
|
303
322
|
return toForeignCallResult(secret.toFields().map(toSingle));
|
|
304
323
|
}
|
|
305
324
|
async utilityFetchTaggedLogs(foreignPendingTaggedLogArrayBaseSlot) {
|
|
306
325
|
const pendingTaggedLogArrayBaseSlot = fromSingle(foreignPendingTaggedLogArrayBaseSlot);
|
|
307
|
-
await this.
|
|
326
|
+
await this.oracleHandler.utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot);
|
|
308
327
|
return toForeignCallResult([]);
|
|
309
328
|
}
|
|
310
329
|
async utilityValidateEnqueuedNotesAndEvents(foreignContractAddress, foreignNoteValidationRequestsArrayBaseSlot, foreignEventValidationRequestsArrayBaseSlot) {
|
|
311
330
|
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
312
331
|
const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
|
|
313
332
|
const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
|
|
314
|
-
await this.
|
|
333
|
+
await this.oracleHandler.utilityValidateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot);
|
|
315
334
|
return toForeignCallResult([]);
|
|
316
335
|
}
|
|
317
336
|
async utilityBulkRetrieveLogs(foreignContractAddress, foreignLogRetrievalRequestsArrayBaseSlot, foreignLogRetrievalResponsesArrayBaseSlot) {
|
|
318
337
|
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
319
338
|
const logRetrievalRequestsArrayBaseSlot = fromSingle(foreignLogRetrievalRequestsArrayBaseSlot);
|
|
320
339
|
const logRetrievalResponsesArrayBaseSlot = fromSingle(foreignLogRetrievalResponsesArrayBaseSlot);
|
|
321
|
-
await this.
|
|
340
|
+
await this.oracleHandler.utilityBulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot);
|
|
322
341
|
return toForeignCallResult([]);
|
|
323
342
|
}
|
|
324
343
|
async utilityStoreCapsule(foreignContractAddress, foreignSlot, foreignCapsule) {
|
|
325
344
|
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
326
345
|
const slot = fromSingle(foreignSlot);
|
|
327
346
|
const capsule = fromArray(foreignCapsule);
|
|
328
|
-
await this.
|
|
347
|
+
await this.oracleHandler.utilityStoreCapsule(contractAddress, slot, capsule);
|
|
329
348
|
return toForeignCallResult([]);
|
|
330
349
|
}
|
|
331
350
|
async utilityLoadCapsule(foreignContractAddress, foreignSlot, foreignTSize) {
|
|
332
351
|
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
333
352
|
const slot = fromSingle(foreignSlot);
|
|
334
353
|
const tSize = fromSingle(foreignTSize).toNumber();
|
|
335
|
-
const values = await this.
|
|
354
|
+
const values = await this.oracleHandler.utilityLoadCapsule(contractAddress, slot);
|
|
336
355
|
// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
|
|
337
356
|
// with two fields: `some` (a boolean) and `value` (a field array in this case).
|
|
338
357
|
if (values === null) {
|
|
@@ -352,7 +371,7 @@ export class TXEService {
|
|
|
352
371
|
async utilityDeleteCapsule(foreignContractAddress, foreignSlot) {
|
|
353
372
|
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
354
373
|
const slot = fromSingle(foreignSlot);
|
|
355
|
-
await this.
|
|
374
|
+
await this.oracleHandler.utilityDeleteCapsule(contractAddress, slot);
|
|
356
375
|
return toForeignCallResult([]);
|
|
357
376
|
}
|
|
358
377
|
async utilityCopyCapsule(foreignContractAddress, foreignSrcSlot, foreignDstSlot, foreignNumEntries) {
|
|
@@ -360,7 +379,7 @@ export class TXEService {
|
|
|
360
379
|
const srcSlot = fromSingle(foreignSrcSlot);
|
|
361
380
|
const dstSlot = fromSingle(foreignDstSlot);
|
|
362
381
|
const numEntries = fromSingle(foreignNumEntries).toNumber();
|
|
363
|
-
await this.
|
|
382
|
+
await this.oracleHandler.utilityCopyCapsule(contractAddress, srcSlot, dstSlot, numEntries);
|
|
364
383
|
return toForeignCallResult([]);
|
|
365
384
|
}
|
|
366
385
|
// TODO: I forgot to add a corresponding function here, when I introduced an oracle method to txe_oracle.ts.
|
|
@@ -371,7 +390,7 @@ export class TXEService {
|
|
|
371
390
|
const ciphertext = fromUintBoundedVec(foreignCiphertextBVecStorage, foreignCiphertextLength, 8);
|
|
372
391
|
const iv = fromUintArray(foreignIv, 8);
|
|
373
392
|
const symKey = fromUintArray(foreignSymKey, 8);
|
|
374
|
-
const plaintextBuffer = await this.
|
|
393
|
+
const plaintextBuffer = await this.oracleHandler.utilityAes128Decrypt(ciphertext, iv, symKey);
|
|
375
394
|
return toForeignCallResult(arrayToBoundedVec(bufferToU8Array(plaintextBuffer), foreignCiphertextBVecStorage.length));
|
|
376
395
|
}
|
|
377
396
|
async utilityGetSharedSecret(foreignAddress, foreignEphPKField0, foreignEphPKField1, foreignEphPKField2) {
|
|
@@ -381,7 +400,7 @@ export class TXEService {
|
|
|
381
400
|
fromSingle(foreignEphPKField1),
|
|
382
401
|
fromSingle(foreignEphPKField2)
|
|
383
402
|
]);
|
|
384
|
-
const secret = await this.
|
|
403
|
+
const secret = await this.oracleHandler.utilityGetSharedSecret(address, ephPK);
|
|
385
404
|
return toForeignCallResult(secret.toFields().map(toSingle));
|
|
386
405
|
}
|
|
387
406
|
emitOffchainEffect(_foreignData) {
|
|
@@ -394,7 +413,7 @@ export class TXEService {
|
|
|
394
413
|
}
|
|
395
414
|
async avmOpcodeStorageRead(foreignSlot) {
|
|
396
415
|
const slot = fromSingle(foreignSlot);
|
|
397
|
-
const value = (await this.
|
|
416
|
+
const value = (await this.oracleHandler.avmOpcodeStorageRead(slot)).value;
|
|
398
417
|
return toForeignCallResult([
|
|
399
418
|
toSingle(new Fr(value))
|
|
400
419
|
]);
|
|
@@ -402,14 +421,12 @@ export class TXEService {
|
|
|
402
421
|
async avmOpcodeStorageWrite(foreignSlot, foreignValue) {
|
|
403
422
|
const slot = fromSingle(foreignSlot);
|
|
404
423
|
const value = fromSingle(foreignValue);
|
|
405
|
-
await this.
|
|
406
|
-
value
|
|
407
|
-
]);
|
|
424
|
+
await this.oracleHandler.avmOpcodeStorageWrite(slot, value);
|
|
408
425
|
return toForeignCallResult([]);
|
|
409
426
|
}
|
|
410
427
|
async avmOpcodeGetContractInstanceDeployer(foreignAddress) {
|
|
411
428
|
const address = addressFromSingle(foreignAddress);
|
|
412
|
-
const instance = await this.
|
|
429
|
+
const instance = await this.oracleHandler.utilityGetContractInstance(address);
|
|
413
430
|
return toForeignCallResult([
|
|
414
431
|
toSingle(instance.deployer),
|
|
415
432
|
// AVM requires an extra boolean indicating the instance was found
|
|
@@ -418,7 +435,7 @@ export class TXEService {
|
|
|
418
435
|
}
|
|
419
436
|
async avmOpcodeGetContractInstanceClassId(foreignAddress) {
|
|
420
437
|
const address = addressFromSingle(foreignAddress);
|
|
421
|
-
const instance = await this.
|
|
438
|
+
const instance = await this.oracleHandler.utilityGetContractInstance(address);
|
|
422
439
|
return toForeignCallResult([
|
|
423
440
|
toSingle(instance.currentContractClassId),
|
|
424
441
|
// AVM requires an extra boolean indicating the instance was found
|
|
@@ -427,7 +444,7 @@ export class TXEService {
|
|
|
427
444
|
}
|
|
428
445
|
async avmOpcodeGetContractInstanceInitializationHash(foreignAddress) {
|
|
429
446
|
const address = addressFromSingle(foreignAddress);
|
|
430
|
-
const instance = await this.
|
|
447
|
+
const instance = await this.oracleHandler.utilityGetContractInstance(address);
|
|
431
448
|
return toForeignCallResult([
|
|
432
449
|
toSingle(instance.initializationHash),
|
|
433
450
|
// AVM requires an extra boolean indicating the instance was found
|
|
@@ -435,62 +452,61 @@ export class TXEService {
|
|
|
435
452
|
]);
|
|
436
453
|
}
|
|
437
454
|
avmOpcodeSender() {
|
|
438
|
-
const sender = this.
|
|
455
|
+
const sender = this.oracleHandler.getMsgSender();
|
|
439
456
|
return toForeignCallResult([
|
|
440
457
|
toSingle(sender)
|
|
441
458
|
]);
|
|
442
459
|
}
|
|
443
460
|
async avmOpcodeEmitNullifier(foreignNullifier) {
|
|
444
461
|
const nullifier = fromSingle(foreignNullifier);
|
|
445
|
-
await this.
|
|
462
|
+
await this.oracleHandler.avmOpcodeEmitNullifier(nullifier);
|
|
446
463
|
return toForeignCallResult([]);
|
|
447
464
|
}
|
|
448
465
|
async avmOpcodeEmitNoteHash(foreignNoteHash) {
|
|
449
466
|
const noteHash = fromSingle(foreignNoteHash);
|
|
450
|
-
await this.
|
|
467
|
+
await this.oracleHandler.avmOpcodeEmitNoteHash(noteHash);
|
|
451
468
|
return toForeignCallResult([]);
|
|
452
469
|
}
|
|
453
470
|
async avmOpcodeNullifierExists(foreignInnerNullifier, foreignTargetAddress) {
|
|
454
471
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
455
472
|
const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
|
|
456
|
-
const exists = await this.
|
|
473
|
+
const exists = await this.oracleHandler.avmOpcodeNullifierExists(innerNullifier, targetAddress);
|
|
457
474
|
return toForeignCallResult([
|
|
458
475
|
toSingle(new Fr(exists))
|
|
459
476
|
]);
|
|
460
477
|
}
|
|
461
478
|
async avmOpcodeAddress() {
|
|
462
|
-
const contractAddress = await this.
|
|
479
|
+
const contractAddress = await this.oracleHandler.avmOpcodeAddress();
|
|
463
480
|
return toForeignCallResult([
|
|
464
481
|
toSingle(contractAddress.toField())
|
|
465
482
|
]);
|
|
466
483
|
}
|
|
467
484
|
async avmOpcodeBlockNumber() {
|
|
468
|
-
const blockNumber = await this.
|
|
485
|
+
const blockNumber = await this.oracleHandler.avmOpcodeBlockNumber();
|
|
469
486
|
return toForeignCallResult([
|
|
470
487
|
toSingle(new Fr(blockNumber))
|
|
471
488
|
]);
|
|
472
489
|
}
|
|
473
490
|
async avmOpcodeTimestamp() {
|
|
474
|
-
const timestamp = await this.
|
|
491
|
+
const timestamp = await this.oracleHandler.avmOpcodeTimestamp();
|
|
475
492
|
return toForeignCallResult([
|
|
476
493
|
toSingle(new Fr(timestamp))
|
|
477
494
|
]);
|
|
478
495
|
}
|
|
479
|
-
avmOpcodeIsStaticCall() {
|
|
480
|
-
|
|
481
|
-
const isStaticCall = true;
|
|
496
|
+
async avmOpcodeIsStaticCall() {
|
|
497
|
+
const isStaticCall = await this.oracleHandler.avmOpcodeIsStaticCall();
|
|
482
498
|
return toForeignCallResult([
|
|
483
499
|
toSingle(new Fr(isStaticCall ? 1 : 0))
|
|
484
500
|
]);
|
|
485
501
|
}
|
|
486
502
|
async avmOpcodeChainId() {
|
|
487
|
-
const chainId = await this.
|
|
503
|
+
const chainId = await this.oracleHandler.avmOpcodeChainId();
|
|
488
504
|
return toForeignCallResult([
|
|
489
505
|
toSingle(chainId)
|
|
490
506
|
]);
|
|
491
507
|
}
|
|
492
508
|
async avmOpcodeVersion() {
|
|
493
|
-
const version = await this.
|
|
509
|
+
const version = await this.oracleHandler.avmOpcodeVersion();
|
|
494
510
|
return toForeignCallResult([
|
|
495
511
|
toSingle(version)
|
|
496
512
|
]);
|
|
@@ -517,7 +533,7 @@ export class TXEService {
|
|
|
517
533
|
const args = fromArray(foreignArgs);
|
|
518
534
|
const argsHash = fromSingle(foreignArgsHash);
|
|
519
535
|
const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
|
|
520
|
-
const result = await this.
|
|
536
|
+
const result = await this.oracleHandler.txePrivateCallNewFlow(from, targetContractAddress, functionSelector, args, argsHash, isStaticCall);
|
|
521
537
|
return toForeignCallResult([
|
|
522
538
|
toArray([
|
|
523
539
|
result.endSideEffectCounter,
|
|
@@ -530,7 +546,7 @@ export class TXEService {
|
|
|
530
546
|
const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
|
|
531
547
|
const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
|
|
532
548
|
const argsHash = fromSingle(foreignArgsHash);
|
|
533
|
-
const result = await this.
|
|
549
|
+
const result = await this.oracleHandler.simulateUtilityFunction(targetContractAddress, functionSelector, argsHash);
|
|
534
550
|
return toForeignCallResult([
|
|
535
551
|
toSingle(result)
|
|
536
552
|
]);
|
|
@@ -540,7 +556,7 @@ export class TXEService {
|
|
|
540
556
|
const address = addressFromSingle(foreignAddress);
|
|
541
557
|
const calldata = fromArray(foreignCalldata);
|
|
542
558
|
const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
|
|
543
|
-
const result = await this.
|
|
559
|
+
const result = await this.oracleHandler.txePublicCallNewFlow(from, address, calldata, isStaticCall);
|
|
544
560
|
return toForeignCallResult([
|
|
545
561
|
toArray([
|
|
546
562
|
result.returnsHash,
|
|
@@ -549,7 +565,7 @@ export class TXEService {
|
|
|
549
565
|
]);
|
|
550
566
|
}
|
|
551
567
|
async privateGetSenderForTags() {
|
|
552
|
-
const sender = await this.
|
|
568
|
+
const sender = await this.oracleHandler.privateGetSenderForTags();
|
|
553
569
|
// Return a Noir Option struct with `some` and `value` fields
|
|
554
570
|
if (sender === undefined) {
|
|
555
571
|
// No sender found, return Option with some=0 and value=0
|
|
@@ -567,7 +583,7 @@ export class TXEService {
|
|
|
567
583
|
}
|
|
568
584
|
async privateSetSenderForTags(foreignSenderForTags) {
|
|
569
585
|
const senderForTags = AztecAddress.fromField(fromSingle(foreignSenderForTags));
|
|
570
|
-
await this.
|
|
586
|
+
await this.oracleHandler.privateSetSenderForTags(senderForTags);
|
|
571
587
|
return toForeignCallResult([]);
|
|
572
588
|
}
|
|
573
589
|
}
|
package/dest/txe_session.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { AztecAddress } from '@aztec/aztec.js';
|
|
1
2
|
import { type Logger } from '@aztec/foundation/log';
|
|
2
3
|
import type { ProtocolContract } from '@aztec/protocol-contracts';
|
|
4
|
+
import type { PrivateContextInputs } from '@aztec/stdlib/kernel';
|
|
5
|
+
import type { UInt32 } from '@aztec/stdlib/types';
|
|
6
|
+
import { TXE } from './oracle/txe_oracle.js';
|
|
7
|
+
import type { TXETypedOracle } from './oracle/txe_typed_oracle.js';
|
|
3
8
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
4
9
|
import { TXEService } from './txe_service/txe_service.js';
|
|
5
|
-
import {
|
|
10
|
+
import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
|
|
6
11
|
/**
|
|
7
12
|
* A TXE Session can be ine one of four states, which change as the test progresses and different oracles are called.
|
|
8
13
|
* The current state determines which oracles are available.
|
|
@@ -29,8 +34,6 @@ declare enum SessionState {
|
|
|
29
34
|
*/
|
|
30
35
|
UTILITY = 3
|
|
31
36
|
}
|
|
32
|
-
declare const STATE_TRANSITION_FUNCTIONS: readonly ["txeSetTopLevelTXEContext", "txeSetPrivateTXEContext", "txeSetPublicTXEContext", "txeSetUtilityTXEContext"];
|
|
33
|
-
type TXESessionStateTransitionFunction = (typeof STATE_TRANSITION_FUNCTIONS)[number];
|
|
34
37
|
type MethodNames<T> = {
|
|
35
38
|
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
|
|
36
39
|
}[keyof T];
|
|
@@ -38,17 +41,24 @@ type MethodNames<T> = {
|
|
|
38
41
|
* The name of an oracle function that TXE supports, which are a combination of PXE oracles, non-transpiled AVM opcodes,
|
|
39
42
|
* and custom TXE oracles.
|
|
40
43
|
*/
|
|
41
|
-
export type TXEOracleFunctionName = MethodNames<TXEService
|
|
44
|
+
export type TXEOracleFunctionName = MethodNames<TXEService>;
|
|
45
|
+
export interface TXESessionStateHandler {
|
|
46
|
+
setTopLevelContext(): Promise<void>;
|
|
47
|
+
setPublicContext(contractAddress?: AztecAddress): Promise<void>;
|
|
48
|
+
setPrivateContext(contractAddress?: AztecAddress, historicalBlockNumber?: UInt32): Promise<PrivateContextInputs>;
|
|
49
|
+
setUtilityContext(contractAddress?: AztecAddress): Promise<void>;
|
|
50
|
+
}
|
|
42
51
|
/**
|
|
43
52
|
* A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
|
|
44
53
|
* state, etc., independent of all other tests running in parallel.
|
|
45
54
|
*/
|
|
46
|
-
export declare class TXESession {
|
|
55
|
+
export declare class TXESession implements TXESessionStateHandler {
|
|
47
56
|
private logger;
|
|
48
57
|
private stateMachine;
|
|
49
|
-
private
|
|
58
|
+
private oracleHandler;
|
|
59
|
+
private legacyTXEOracle;
|
|
50
60
|
state: SessionState;
|
|
51
|
-
constructor(logger: Logger, stateMachine: TXEStateMachine,
|
|
61
|
+
constructor(logger: Logger, stateMachine: TXEStateMachine, oracleHandler: TXETypedOracle, legacyTXEOracle: TXE);
|
|
52
62
|
static init(protocolContracts: ProtocolContract[]): Promise<TXESession>;
|
|
53
63
|
/**
|
|
54
64
|
* Processes an oracle function invoked by the Noir test associated to this session.
|
|
@@ -57,9 +67,11 @@ export declare class TXESession {
|
|
|
57
67
|
* @returns The oracle return values.
|
|
58
68
|
*/
|
|
59
69
|
processFunction(functionName: TXEOracleFunctionName, inputs: ForeignCallArgs): Promise<ForeignCallResult>;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
setTopLevelContext(): Promise<void>;
|
|
71
|
+
setPublicContext(contractAddress?: AztecAddress): Promise<void>;
|
|
72
|
+
setPrivateContext(contractAddress?: AztecAddress, historicalBlockNumber?: UInt32): Promise<PrivateContextInputs>;
|
|
73
|
+
setUtilityContext(contractAddress?: AztecAddress): Promise<void>;
|
|
74
|
+
private assertInTopLevelState;
|
|
63
75
|
}
|
|
64
76
|
export {};
|
|
65
77
|
//# sourceMappingURL=txe_session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"txe_session.d.ts","sourceRoot":"","sources":["../src/txe_session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"txe_session.d.ts","sourceRoot":"","sources":["../src/txe_session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAM,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAQlE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAI7E;;;GAGG;AACH,aAAK,YAAY;IACf;;;OAGG;IACH,SAAS,IAAA;IACT;;;cAGU;IACV,OAAO,IAAA;IACP;;gGAE4F;IAC5F,MAAM,IAAA;IACN;;;;OAIG;IACH,OAAO,IAAA;CACR;AAED,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK;CACjE,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,gBAAgB,CAAC,eAAe,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,CAAC,eAAe,CAAC,EAAE,YAAY,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACjH,iBAAiB,CAAC,eAAe,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAID;;;GAGG;AACH,qBAAa,UAAW,YAAW,sBAAsB;IAIrD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,eAAe;IANzB,KAAK,eAA0B;gBAGrB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,eAAe,EAC7B,aAAa,EAAE,cAAc,EAC7B,eAAe,EAAE,GAAG;WAGjB,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,EAAE;IAsCvD;;;;;OAKG;IACH,eAAe,CAAC,YAAY,EAAE,qBAAqB,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAInG,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BnC,gBAAgB,CAAC,eAAe,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB/D,iBAAiB,CACrB,eAAe,CAAC,EAAE,YAAY,EAC9B,qBAAqB,CAAC,EAAE,MAAM,GAC7B,OAAO,CAAC,oBAAoB,CAAC;IAehC,iBAAiB,CAAC,eAAe,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAahE,OAAO,CAAC,qBAAqB;CAO9B"}
|