@aztec/txe 1.2.1 → 2.0.0-nightly.20250814
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 +34 -33
- package/dest/oracle/txe_oracle.d.ts +52 -81
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +167 -408
- package/dest/state_machine/archiver.d.ts +4 -2
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +8 -0
- package/dest/state_machine/dummy_p2p_client.d.ts +6 -3
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +8 -0
- package/dest/state_machine/mock_epoch_cache.d.ts +4 -2
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +7 -1
- package/dest/txe_constants.d.ts +0 -1
- package/dest/txe_constants.d.ts.map +1 -1
- package/dest/txe_constants.js +0 -2
- package/dest/txe_service/txe_service.d.ts +82 -90
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +305 -361
- package/dest/util/txe_public_contract_data_source.js +1 -1
- package/package.json +16 -16
- package/src/index.ts +42 -35
- package/src/oracle/txe_oracle.ts +192 -551
- package/src/state_machine/archiver.ts +10 -2
- package/src/state_machine/dummy_p2p_client.ts +29 -3
- package/src/state_machine/mock_epoch_cache.ts +10 -2
- package/src/txe_constants.ts +0 -2
- package/src/txe_service/txe_service.ts +353 -480
- package/src/util/txe_public_contract_data_source.ts +1 -1
|
@@ -1,74 +1,122 @@
|
|
|
1
1
|
import { Fr, Point } from '@aztec/aztec.js';
|
|
2
|
-
import {
|
|
2
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS } from '@aztec/constants';
|
|
3
3
|
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
4
|
-
import {
|
|
4
|
+
import { packAsRetrievedNote } from '@aztec/pxe/simulator';
|
|
5
5
|
import { FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
6
|
-
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
7
6
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
7
|
import { computePartialAddress } from '@aztec/stdlib/contract';
|
|
9
|
-
import { SimulationError } from '@aztec/stdlib/errors';
|
|
10
|
-
import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
|
|
11
8
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
12
9
|
import { TXE } from '../oracle/txe_oracle.js';
|
|
13
10
|
import { addressFromSingle, arrayOfArraysToBoundedVecOfArrays, arrayToBoundedVec, bufferToU8Array, fromArray, fromSingle, fromUintArray, fromUintBoundedVec, toArray, toForeignCallResult, toSingle } from '../util/encoding.js';
|
|
14
|
-
|
|
11
|
+
var TXEContext = /*#__PURE__*/ function(TXEContext) {
|
|
12
|
+
TXEContext[TXEContext["TOP_LEVEL"] = 0] = "TOP_LEVEL";
|
|
13
|
+
TXEContext[TXEContext["PRIVATE"] = 1] = "PRIVATE";
|
|
14
|
+
TXEContext[TXEContext["PUBLIC"] = 2] = "PUBLIC";
|
|
15
|
+
TXEContext[TXEContext["UTILITY"] = 3] = "UTILITY";
|
|
16
|
+
return TXEContext;
|
|
17
|
+
}(TXEContext || {});
|
|
15
18
|
export class TXEService {
|
|
16
19
|
logger;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
txe;
|
|
21
|
+
context;
|
|
22
|
+
contextChecksEnabled;
|
|
23
|
+
constructor(logger, txe){
|
|
20
24
|
this.logger = logger;
|
|
21
|
-
this.
|
|
22
|
-
this.
|
|
25
|
+
this.txe = txe;
|
|
26
|
+
this.context = 0;
|
|
27
|
+
this.contextChecksEnabled = false;
|
|
23
28
|
}
|
|
24
29
|
static async init(logger, protocolContracts) {
|
|
25
30
|
logger.debug(`TXE service initialized`);
|
|
26
31
|
const store = await openTmpStore('test');
|
|
27
32
|
const txe = await TXE.create(logger, store, protocolContracts);
|
|
28
33
|
const service = new TXEService(logger, txe);
|
|
29
|
-
await service.
|
|
34
|
+
await service.txeAdvanceBlocksBy(toSingle(new Fr(1n)));
|
|
30
35
|
return service;
|
|
31
36
|
}
|
|
37
|
+
// TXE Context manipulation
|
|
38
|
+
// Temporary workaround - once all tests migrate to calling the new flow, in which this oracle is called at the
|
|
39
|
+
// beginning of a txe test, we'll make the context check be mandatory
|
|
40
|
+
txeEnableContextChecks() {
|
|
41
|
+
this.contextChecksEnabled = true;
|
|
42
|
+
return toForeignCallResult([]);
|
|
43
|
+
}
|
|
44
|
+
txeSetTopLevelTXEContext() {
|
|
45
|
+
if (this.contextChecksEnabled) {
|
|
46
|
+
if (this.context == 0) {
|
|
47
|
+
throw new Error(`Call to txeSetTopLevelTXEContext while in context ${TXEContext[this.context]}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
this.context = 0;
|
|
51
|
+
return toForeignCallResult([]);
|
|
52
|
+
}
|
|
53
|
+
txeSetPrivateTXEContext() {
|
|
54
|
+
if (this.contextChecksEnabled) {
|
|
55
|
+
if (this.context != 0) {
|
|
56
|
+
throw new Error(`Call to txeSetPrivateTXEContext while in context ${TXEContext[this.context]}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
this.context = 1;
|
|
60
|
+
return toForeignCallResult([]);
|
|
61
|
+
}
|
|
62
|
+
txeSetPublicTXEContext() {
|
|
63
|
+
if (this.contextChecksEnabled) {
|
|
64
|
+
if (this.context != 0) {
|
|
65
|
+
throw new Error(`Call to txeSetPublicTXEContext while in context ${TXEContext[this.context]}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
this.context = 2;
|
|
69
|
+
return toForeignCallResult([]);
|
|
70
|
+
}
|
|
71
|
+
txeSetUtilityTXEContext() {
|
|
72
|
+
if (this.contextChecksEnabled) {
|
|
73
|
+
if (this.context != 0) {
|
|
74
|
+
throw new Error(`Call to txeSetUtilityTXEContext while in context ${TXEContext[this.context]}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
this.context = 3;
|
|
78
|
+
return toForeignCallResult([]);
|
|
79
|
+
}
|
|
32
80
|
// Cheatcodes
|
|
33
|
-
async
|
|
81
|
+
async txeGetPrivateContextInputs(blockNumberIsSome, blockNumberValue) {
|
|
34
82
|
const blockNumber = fromSingle(blockNumberIsSome).toBool() ? fromSingle(blockNumberValue).toNumber() : null;
|
|
35
|
-
const
|
|
36
|
-
|
|
83
|
+
const inputs = await this.txe.txeGetPrivateContextInputs(blockNumber);
|
|
84
|
+
this.logger.info(`Created private context for block ${inputs.historicalHeader.globalVariables.blockNumber} (requested ${blockNumber})`);
|
|
37
85
|
return toForeignCallResult(inputs.toFields().map(toSingle));
|
|
38
86
|
}
|
|
39
|
-
async
|
|
87
|
+
async txeAdvanceBlocksBy(blocks) {
|
|
40
88
|
const nBlocks = fromSingle(blocks).toNumber();
|
|
41
89
|
this.logger.debug(`time traveling ${nBlocks} blocks`);
|
|
42
90
|
for(let i = 0; i < nBlocks; i++){
|
|
43
|
-
const blockNumber = await this.
|
|
44
|
-
await this.
|
|
45
|
-
this.
|
|
91
|
+
const blockNumber = await this.txe.utilityGetBlockNumber();
|
|
92
|
+
await this.txe.commitState();
|
|
93
|
+
this.txe.setBlockNumber(blockNumber + 1);
|
|
46
94
|
}
|
|
47
95
|
return toForeignCallResult([]);
|
|
48
96
|
}
|
|
49
|
-
|
|
97
|
+
txeAdvanceTimestampBy(duration) {
|
|
50
98
|
const durationBigInt = fromSingle(duration).toBigInt();
|
|
51
99
|
this.logger.debug(`time traveling ${durationBigInt} seconds`);
|
|
52
|
-
this.
|
|
100
|
+
this.txe.txeAdvanceTimestampBy(durationBigInt);
|
|
53
101
|
return toForeignCallResult([]);
|
|
54
102
|
}
|
|
55
|
-
|
|
103
|
+
txeSetContractAddress(address) {
|
|
56
104
|
const typedAddress = addressFromSingle(address);
|
|
57
|
-
this.
|
|
105
|
+
this.txe.txeSetContractAddress(typedAddress);
|
|
58
106
|
return toForeignCallResult([]);
|
|
59
107
|
}
|
|
60
|
-
async
|
|
61
|
-
const keys = await this.typedOracle.deriveKeys(fromSingle(secret));
|
|
62
|
-
return toForeignCallResult(keys.publicKeys.toFields().map(toSingle));
|
|
63
|
-
}
|
|
64
|
-
async deploy(artifact, instance, secret) {
|
|
108
|
+
async txeDeploy(artifact, instance, secret) {
|
|
65
109
|
// Emit deployment nullifier
|
|
66
|
-
await this.
|
|
110
|
+
await this.txe.noteCache.nullifierCreated(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), instance.address.toField());
|
|
111
|
+
// Make sure the deployment nullifier gets included in a tx in a block
|
|
112
|
+
const blockNumber = await this.txe.utilityGetBlockNumber();
|
|
113
|
+
await this.txe.commitState();
|
|
114
|
+
this.txe.setBlockNumber(blockNumber + 1);
|
|
67
115
|
if (!fromSingle(secret).equals(Fr.ZERO)) {
|
|
68
|
-
await this.
|
|
116
|
+
await this.txeAddAccount(artifact, instance, secret);
|
|
69
117
|
} else {
|
|
70
|
-
await this.
|
|
71
|
-
await this.
|
|
118
|
+
await this.txe.addContractInstance(instance);
|
|
119
|
+
await this.txe.addContractArtifact(instance.currentContractClassId, artifact);
|
|
72
120
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
73
121
|
}
|
|
74
122
|
return toForeignCallResult([
|
|
@@ -81,28 +129,14 @@ export class TXEService {
|
|
|
81
129
|
])
|
|
82
130
|
]);
|
|
83
131
|
}
|
|
84
|
-
async
|
|
85
|
-
const
|
|
86
|
-
const valuesFr = fromArray(values);
|
|
87
|
-
const contractAddressFr = addressFromSingle(contractAddress);
|
|
88
|
-
const publicDataWrites = await Promise.all(valuesFr.map(async (value, i)=>{
|
|
89
|
-
const storageSlot = startStorageSlotFr.add(new Fr(i));
|
|
90
|
-
this.logger.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${value}`);
|
|
91
|
-
return new PublicDataWrite(await computePublicDataTreeLeafSlot(contractAddressFr, storageSlot), value);
|
|
92
|
-
}));
|
|
93
|
-
await this.typedOracle.addPublicDataWrites(publicDataWrites);
|
|
94
|
-
return toForeignCallResult([
|
|
95
|
-
toArray(publicDataWrites.map((write)=>write.value))
|
|
96
|
-
]);
|
|
97
|
-
}
|
|
98
|
-
async createAccount(secret) {
|
|
99
|
-
const keyStore = this.typedOracle.getKeyStore();
|
|
132
|
+
async txeCreateAccount(secret) {
|
|
133
|
+
const keyStore = this.txe.getKeyStore();
|
|
100
134
|
const secretFr = fromSingle(secret);
|
|
101
135
|
// This is a footgun !
|
|
102
136
|
const completeAddress = await keyStore.addAccount(secretFr, secretFr);
|
|
103
|
-
const accountDataProvider = this.
|
|
137
|
+
const accountDataProvider = this.txe.getAccountDataProvider();
|
|
104
138
|
await accountDataProvider.setAccount(completeAddress.address, completeAddress);
|
|
105
|
-
const addressDataProvider = this.
|
|
139
|
+
const addressDataProvider = this.txe.getAddressDataProvider();
|
|
106
140
|
await addressDataProvider.addCompleteAddress(completeAddress);
|
|
107
141
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
108
142
|
return toForeignCallResult([
|
|
@@ -110,15 +144,15 @@ export class TXEService {
|
|
|
110
144
|
...completeAddress.publicKeys.toFields().map(toSingle)
|
|
111
145
|
]);
|
|
112
146
|
}
|
|
113
|
-
async
|
|
147
|
+
async txeAddAccount(artifact, instance, secret) {
|
|
114
148
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
115
|
-
await this.
|
|
116
|
-
await this.
|
|
117
|
-
const keyStore = this.
|
|
149
|
+
await this.txe.addContractInstance(instance);
|
|
150
|
+
await this.txe.addContractArtifact(instance.currentContractClassId, artifact);
|
|
151
|
+
const keyStore = this.txe.getKeyStore();
|
|
118
152
|
const completeAddress = await keyStore.addAccount(fromSingle(secret), await computePartialAddress(instance));
|
|
119
|
-
const accountDataProvider = this.
|
|
153
|
+
const accountDataProvider = this.txe.getAccountDataProvider();
|
|
120
154
|
await accountDataProvider.setAccount(completeAddress.address, completeAddress);
|
|
121
|
-
const addressDataProvider = this.
|
|
155
|
+
const addressDataProvider = this.txe.getAddressDataProvider();
|
|
122
156
|
await addressDataProvider.addCompleteAddress(completeAddress);
|
|
123
157
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
124
158
|
return toForeignCallResult([
|
|
@@ -126,190 +160,150 @@ export class TXEService {
|
|
|
126
160
|
...completeAddress.publicKeys.toFields().map(toSingle)
|
|
127
161
|
]);
|
|
128
162
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return toForeignCallResult([
|
|
132
|
-
toSingle(new Fr(counter))
|
|
133
|
-
]);
|
|
134
|
-
}
|
|
135
|
-
async addAuthWitness(address, messageHash) {
|
|
136
|
-
await this.typedOracle.addAuthWitness(addressFromSingle(address), fromSingle(messageHash));
|
|
137
|
-
return toForeignCallResult([]);
|
|
138
|
-
}
|
|
139
|
-
async assertPublicCallFails(address, functionSelector, _length, args) {
|
|
140
|
-
const parsedAddress = addressFromSingle(address);
|
|
141
|
-
const parsedSelector = fromSingle(functionSelector);
|
|
142
|
-
const extendedArgs = [
|
|
143
|
-
parsedSelector,
|
|
144
|
-
...fromArray(args)
|
|
145
|
-
];
|
|
146
|
-
const result = await this.typedOracle.avmOpcodeCall(parsedAddress, extendedArgs, false);
|
|
147
|
-
if (result.revertCode.isOK()) {
|
|
148
|
-
throw new ExpectedFailureError('Public call did not revert');
|
|
149
|
-
}
|
|
150
|
-
return toForeignCallResult([]);
|
|
151
|
-
}
|
|
152
|
-
async assertPrivateCallFails(targetContractAddress, functionSelector, argsHash, sideEffectCounter, isStaticCall) {
|
|
153
|
-
try {
|
|
154
|
-
await this.typedOracle.callPrivateFunction(addressFromSingle(targetContractAddress), FunctionSelector.fromField(fromSingle(functionSelector)), fromSingle(argsHash), fromSingle(sideEffectCounter).toNumber(), fromSingle(isStaticCall).toBool());
|
|
155
|
-
throw new ExpectedFailureError('Private call did not fail');
|
|
156
|
-
} catch (e) {
|
|
157
|
-
if (e instanceof ExpectedFailureError) {
|
|
158
|
-
throw e;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
163
|
+
async txeAddAuthWitness(address, messageHash) {
|
|
164
|
+
await this.txe.txeAddAuthWitness(addressFromSingle(address), fromSingle(messageHash));
|
|
161
165
|
return toForeignCallResult([]);
|
|
162
166
|
}
|
|
163
167
|
// PXE oracles
|
|
164
|
-
|
|
165
|
-
if (
|
|
168
|
+
utilityGetRandomField() {
|
|
169
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
166
170
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
167
171
|
}
|
|
168
172
|
return toForeignCallResult([
|
|
169
|
-
toSingle(this.
|
|
173
|
+
toSingle(this.txe.utilityGetRandomField())
|
|
170
174
|
]);
|
|
171
175
|
}
|
|
172
|
-
async
|
|
173
|
-
if (
|
|
174
|
-
throw new Error(
|
|
176
|
+
async utilityGetContractAddress() {
|
|
177
|
+
if (this.contextChecksEnabled && this.context != 0 && this.context != 3 && this.context != 1) {
|
|
178
|
+
throw new Error(`Attempted to call utilityGetContractAddress while in context ${TXEContext[this.context]}`);
|
|
175
179
|
}
|
|
176
|
-
const contractAddress = await this.
|
|
180
|
+
const contractAddress = await this.txe.utilityGetContractAddress();
|
|
177
181
|
return toForeignCallResult([
|
|
178
182
|
toSingle(contractAddress.toField())
|
|
179
183
|
]);
|
|
180
184
|
}
|
|
181
|
-
async
|
|
182
|
-
if (
|
|
183
|
-
throw new Error(
|
|
185
|
+
async utilityGetBlockNumber() {
|
|
186
|
+
if (this.contextChecksEnabled && this.context != 0 && this.context != 3) {
|
|
187
|
+
throw new Error(`Attempted to call utilityGetBlockNumber while in context ${TXEContext[this.context]}`);
|
|
184
188
|
}
|
|
185
|
-
const blockNumber = await this.
|
|
189
|
+
const blockNumber = await this.txe.utilityGetBlockNumber();
|
|
186
190
|
return toForeignCallResult([
|
|
187
191
|
toSingle(new Fr(blockNumber))
|
|
188
192
|
]);
|
|
189
193
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
// seems to be used to mean the timestamp of the last mined block in txe (but that's not what is done here)
|
|
195
|
+
async utilityGetTimestamp() {
|
|
196
|
+
if (this.contextChecksEnabled && this.context != 0 && this.context != 3) {
|
|
197
|
+
throw new Error(`Attempted to call utilityGetTimestamp while in context ${TXEContext[this.context]}`);
|
|
193
198
|
}
|
|
194
|
-
const timestamp = await this.
|
|
199
|
+
const timestamp = await this.txe.utilityGetTimestamp();
|
|
200
|
+
return toForeignCallResult([
|
|
201
|
+
toSingle(new Fr(timestamp))
|
|
202
|
+
]);
|
|
203
|
+
}
|
|
204
|
+
async txeGetLastBlockTimestamp() {
|
|
205
|
+
if (this.contextChecksEnabled && this.context != 0) {
|
|
206
|
+
throw new Error(`Attempted to call txeGetLastBlockTimestamp while in context ${TXEContext[this.context]}`);
|
|
207
|
+
}
|
|
208
|
+
const timestamp = await this.txe.txeGetLastBlockTimestamp();
|
|
195
209
|
return toForeignCallResult([
|
|
196
210
|
toSingle(new Fr(timestamp))
|
|
197
211
|
]);
|
|
198
212
|
}
|
|
199
213
|
// Since the argument is a slice, noir automatically adds a length field to oracle call.
|
|
200
|
-
|
|
201
|
-
if (
|
|
214
|
+
privateStoreInExecutionCache(_length, values, hash) {
|
|
215
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
202
216
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
203
217
|
}
|
|
204
|
-
this.
|
|
218
|
+
this.txe.privateStoreInExecutionCache(fromArray(values), fromSingle(hash));
|
|
205
219
|
return toForeignCallResult([]);
|
|
206
220
|
}
|
|
207
|
-
async
|
|
208
|
-
if (
|
|
221
|
+
async privateLoadFromExecutionCache(hash) {
|
|
222
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
209
223
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
210
224
|
}
|
|
211
|
-
const returns = await this.
|
|
225
|
+
const returns = await this.txe.privateLoadFromExecutionCache(fromSingle(hash));
|
|
212
226
|
return toForeignCallResult([
|
|
213
227
|
toArray(returns)
|
|
214
228
|
]);
|
|
215
229
|
}
|
|
216
230
|
// Since the argument is a slice, noir automatically adds a length field to oracle call.
|
|
217
|
-
|
|
231
|
+
utilityDebugLog(message, _length, fields) {
|
|
218
232
|
const messageStr = fromArray(message).map((field)=>String.fromCharCode(field.toNumber())).join('');
|
|
219
233
|
const fieldsFr = fromArray(fields);
|
|
220
|
-
this.
|
|
234
|
+
this.txe.utilityDebugLog(messageStr, fieldsFr);
|
|
221
235
|
return toForeignCallResult([]);
|
|
222
236
|
}
|
|
223
|
-
async
|
|
224
|
-
const values = await this.
|
|
237
|
+
async utilityStorageRead(contractAddress, startStorageSlot, blockNumber, numberOfElements) {
|
|
238
|
+
const values = await this.txe.utilityStorageRead(addressFromSingle(contractAddress), fromSingle(startStorageSlot), fromSingle(blockNumber).toNumber(), fromSingle(numberOfElements).toNumber());
|
|
225
239
|
return toForeignCallResult([
|
|
226
240
|
toArray(values)
|
|
227
241
|
]);
|
|
228
242
|
}
|
|
229
|
-
async
|
|
230
|
-
|
|
231
|
-
return toForeignCallResult([
|
|
232
|
-
toArray(newValues)
|
|
233
|
-
]);
|
|
234
|
-
}
|
|
235
|
-
async getPublicDataWitness(blockNumber, leafSlot) {
|
|
236
|
-
if (!this.oraclesEnabled) {
|
|
243
|
+
async utilityGetPublicDataWitness(blockNumber, leafSlot) {
|
|
244
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
237
245
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
238
246
|
}
|
|
239
247
|
const parsedBlockNumber = fromSingle(blockNumber).toNumber();
|
|
240
248
|
const parsedLeafSlot = fromSingle(leafSlot);
|
|
241
|
-
const witness = await this.
|
|
249
|
+
const witness = await this.txe.utilityGetPublicDataWitness(parsedBlockNumber, parsedLeafSlot);
|
|
242
250
|
if (!witness) {
|
|
243
251
|
throw new Error(`Public data witness not found for slot ${parsedLeafSlot} at block ${parsedBlockNumber}.`);
|
|
244
252
|
}
|
|
245
253
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
246
254
|
}
|
|
247
|
-
async
|
|
248
|
-
if (
|
|
255
|
+
async utilityGetNotes(storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status, maxNotes, packedRetrievedNoteLength) {
|
|
256
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
249
257
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
250
258
|
}
|
|
251
|
-
const noteDatas = await this.
|
|
259
|
+
const noteDatas = await this.txe.utilityGetNotes(fromSingle(storageSlot), fromSingle(numSelects).toNumber(), fromArray(selectByIndexes).map((fr)=>fr.toNumber()), fromArray(selectByOffsets).map((fr)=>fr.toNumber()), fromArray(selectByLengths).map((fr)=>fr.toNumber()), fromArray(selectValues), fromArray(selectComparators).map((fr)=>fr.toNumber()), fromArray(sortByIndexes).map((fr)=>fr.toNumber()), fromArray(sortByOffsets).map((fr)=>fr.toNumber()), fromArray(sortByLengths).map((fr)=>fr.toNumber()), fromArray(sortOrder).map((fr)=>fr.toNumber()), fromSingle(limit).toNumber(), fromSingle(offset).toNumber(), fromSingle(status).toNumber());
|
|
252
260
|
if (noteDatas.length > 0) {
|
|
253
261
|
const noteLength = noteDatas[0].note.items.length;
|
|
254
262
|
if (!noteDatas.every(({ note })=>noteLength === note.items.length)) {
|
|
255
263
|
throw new Error('Notes should all be the same length.');
|
|
256
264
|
}
|
|
257
265
|
}
|
|
258
|
-
|
|
259
|
-
// array is structured as [contract_address, note_nonce, nonzero_note_hash_counter, ...packed_note].
|
|
260
|
-
const returnDataAsArrayOfArrays = noteDatas.map(({ contractAddress, noteNonce, index, note })=>{
|
|
261
|
-
// If index is undefined, the note is transient which implies that the nonzero_note_hash_counter has to be true
|
|
262
|
-
const noteIsTransient = index === undefined;
|
|
263
|
-
const nonzeroNoteHashCounter = noteIsTransient ? true : false;
|
|
264
|
-
// If you change the array on the next line you have to change the `unpack_retrieved_note` function in
|
|
265
|
-
// `aztec/src/note/retrieved_note.nr`
|
|
266
|
-
return [
|
|
267
|
-
contractAddress,
|
|
268
|
-
noteNonce,
|
|
269
|
-
nonzeroNoteHashCounter,
|
|
270
|
-
...note.items
|
|
271
|
-
];
|
|
272
|
-
});
|
|
266
|
+
const returnDataAsArrayOfArrays = noteDatas.map(packAsRetrievedNote);
|
|
273
267
|
// Now we convert each sub-array to an array of ForeignCallSingles
|
|
274
268
|
const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map((subArray)=>subArray.map(toSingle));
|
|
275
269
|
// At last we convert the array of arrays to a bounded vec of arrays
|
|
276
270
|
return toForeignCallResult(arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, fromSingle(maxNotes).toNumber(), fromSingle(packedRetrievedNoteLength).toNumber()));
|
|
277
271
|
}
|
|
278
|
-
|
|
279
|
-
if (
|
|
272
|
+
privateNotifyCreatedNote(storageSlot, noteTypeId, note, noteHash, counter) {
|
|
273
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
280
274
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
281
275
|
}
|
|
282
|
-
this.
|
|
276
|
+
this.txe.privateNotifyCreatedNote(fromSingle(storageSlot), NoteSelector.fromField(fromSingle(noteTypeId)), fromArray(note), fromSingle(noteHash), fromSingle(counter).toNumber());
|
|
283
277
|
return toForeignCallResult([]);
|
|
284
278
|
}
|
|
285
|
-
async
|
|
286
|
-
if (
|
|
279
|
+
async privateNotifyNullifiedNote(innerNullifier, noteHash, counter) {
|
|
280
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
287
281
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
288
282
|
}
|
|
289
|
-
await this.
|
|
283
|
+
await this.txe.privateNotifyNullifiedNote(fromSingle(innerNullifier), fromSingle(noteHash), fromSingle(counter).toNumber());
|
|
290
284
|
return toForeignCallResult([]);
|
|
291
285
|
}
|
|
292
|
-
async
|
|
293
|
-
if (
|
|
286
|
+
async privateNotifyCreatedNullifier(innerNullifier) {
|
|
287
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
294
288
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
295
289
|
}
|
|
296
|
-
await this.
|
|
290
|
+
await this.txe.privateNotifyCreatedNullifier(fromSingle(innerNullifier));
|
|
297
291
|
return toForeignCallResult([]);
|
|
298
292
|
}
|
|
299
|
-
async
|
|
300
|
-
if (
|
|
293
|
+
async utilityCheckNullifierExists(innerNullifier) {
|
|
294
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
301
295
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
302
296
|
}
|
|
303
|
-
const exists = await this.
|
|
297
|
+
const exists = await this.txe.utilityCheckNullifierExists(fromSingle(innerNullifier));
|
|
304
298
|
return toForeignCallResult([
|
|
305
299
|
toSingle(new Fr(exists))
|
|
306
300
|
]);
|
|
307
301
|
}
|
|
308
|
-
async
|
|
309
|
-
if (
|
|
302
|
+
async utilityGetContractInstance(address) {
|
|
303
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
310
304
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
311
305
|
}
|
|
312
|
-
const instance = await this.
|
|
306
|
+
const instance = await this.txe.utilityGetContractInstance(addressFromSingle(address));
|
|
313
307
|
return toForeignCallResult([
|
|
314
308
|
instance.salt,
|
|
315
309
|
instance.deployer.toField(),
|
|
@@ -318,12 +312,12 @@ export class TXEService {
|
|
|
318
312
|
...instance.publicKeys.toFields()
|
|
319
313
|
].map(toSingle));
|
|
320
314
|
}
|
|
321
|
-
async
|
|
322
|
-
if (
|
|
315
|
+
async utilityGetPublicKeysAndPartialAddress(address) {
|
|
316
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
323
317
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
324
318
|
}
|
|
325
319
|
const parsedAddress = addressFromSingle(address);
|
|
326
|
-
const { publicKeys, partialAddress } = await this.
|
|
320
|
+
const { publicKeys, partialAddress } = await this.txe.utilityGetCompleteAddress(parsedAddress);
|
|
327
321
|
return toForeignCallResult([
|
|
328
322
|
toArray([
|
|
329
323
|
...publicKeys.toFields(),
|
|
@@ -331,42 +325,33 @@ export class TXEService {
|
|
|
331
325
|
])
|
|
332
326
|
]);
|
|
333
327
|
}
|
|
334
|
-
async
|
|
335
|
-
if (
|
|
328
|
+
async utilityGetKeyValidationRequest(pkMHash) {
|
|
329
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
336
330
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
337
331
|
}
|
|
338
|
-
const keyValidationRequest = await this.
|
|
332
|
+
const keyValidationRequest = await this.txe.utilityGetKeyValidationRequest(fromSingle(pkMHash));
|
|
339
333
|
return toForeignCallResult(keyValidationRequest.toFields().map(toSingle));
|
|
340
334
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
344
|
-
}
|
|
345
|
-
const result = await this.typedOracle.callPrivateFunction(addressFromSingle(targetContractAddress), FunctionSelector.fromField(fromSingle(functionSelector)), fromSingle(argsHash), fromSingle(sideEffectCounter).toNumber(), fromSingle(isStaticCall).toBool());
|
|
346
|
-
return toForeignCallResult([
|
|
347
|
-
toArray([
|
|
348
|
-
result.endSideEffectCounter,
|
|
349
|
-
result.returnsHash
|
|
350
|
-
])
|
|
351
|
-
]);
|
|
335
|
+
privateCallPrivateFunction(_targetContractAddress, _functionSelector, _argsHash, _sideEffectCounter, _isStaticCall) {
|
|
336
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::private_context`, use `private_call` instead');
|
|
352
337
|
}
|
|
353
|
-
async
|
|
354
|
-
if (
|
|
338
|
+
async utilityGetNullifierMembershipWitness(blockNumber, nullifier) {
|
|
339
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
355
340
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
356
341
|
}
|
|
357
342
|
const parsedBlockNumber = fromSingle(blockNumber).toNumber();
|
|
358
|
-
const witness = await this.
|
|
343
|
+
const witness = await this.txe.utilityGetNullifierMembershipWitness(parsedBlockNumber, fromSingle(nullifier));
|
|
359
344
|
if (!witness) {
|
|
360
345
|
throw new Error(`Nullifier membership witness not found at block ${parsedBlockNumber}.`);
|
|
361
346
|
}
|
|
362
347
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
363
348
|
}
|
|
364
|
-
async
|
|
365
|
-
if (
|
|
349
|
+
async utilityGetAuthWitness(messageHash) {
|
|
350
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
366
351
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
367
352
|
}
|
|
368
353
|
const parsedMessageHash = fromSingle(messageHash);
|
|
369
|
-
const authWitness = await this.
|
|
354
|
+
const authWitness = await this.txe.utilityGetAuthWitness(parsedMessageHash);
|
|
370
355
|
if (!authWitness) {
|
|
371
356
|
throw new Error(`Auth witness not found for message hash ${parsedMessageHash}.`);
|
|
372
357
|
}
|
|
@@ -374,61 +359,49 @@ export class TXEService {
|
|
|
374
359
|
toArray(authWitness)
|
|
375
360
|
]);
|
|
376
361
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
380
|
-
}
|
|
381
|
-
await this.typedOracle.notifyEnqueuedPublicFunctionCall(addressFromSingle(targetContractAddress), fromSingle(calldataHash), fromSingle(sideEffectCounter).toNumber(), fromSingle(isStaticCall).toBool());
|
|
382
|
-
return toForeignCallResult([]);
|
|
362
|
+
privateNotifyEnqueuedPublicFunctionCall(_targetContractAddress, _calldataHash, _sideEffectCounter, _isStaticCall) {
|
|
363
|
+
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
383
364
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
387
|
-
}
|
|
388
|
-
await this.typedOracle.notifySetPublicTeardownFunctionCall(addressFromSingle(targetContractAddress), fromSingle(calldataHash), fromSingle(sideEffectCounter).toNumber(), fromSingle(isStaticCall).toBool());
|
|
389
|
-
return toForeignCallResult([]);
|
|
365
|
+
privateNotifySetPublicTeardownFunctionCall(_targetContractAddress, _calldataHash, _sideEffectCounter, _isStaticCall) {
|
|
366
|
+
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
390
367
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
394
|
-
}
|
|
395
|
-
await this.typedOracle.notifySetMinRevertibleSideEffectCounter(fromSingle(minRevertibleSideEffectCounter).toNumber());
|
|
396
|
-
return toForeignCallResult([]);
|
|
368
|
+
privateNotifySetMinRevertibleSideEffectCounter(_minRevertibleSideEffectCounter) {
|
|
369
|
+
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
397
370
|
}
|
|
398
|
-
async
|
|
399
|
-
if (
|
|
371
|
+
async utilityGetChainId() {
|
|
372
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
400
373
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
401
374
|
}
|
|
402
375
|
return toForeignCallResult([
|
|
403
|
-
toSingle(await this.
|
|
376
|
+
toSingle(await this.txe.utilityGetChainId())
|
|
404
377
|
]);
|
|
405
378
|
}
|
|
406
|
-
async
|
|
407
|
-
if (
|
|
379
|
+
async utilityGetVersion() {
|
|
380
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
408
381
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
409
382
|
}
|
|
410
383
|
return toForeignCallResult([
|
|
411
|
-
toSingle(await this.
|
|
384
|
+
toSingle(await this.txe.utilityGetVersion())
|
|
412
385
|
]);
|
|
413
386
|
}
|
|
414
|
-
async
|
|
415
|
-
if (
|
|
387
|
+
async utilityGetBlockHeader(blockNumber) {
|
|
388
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
416
389
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
417
390
|
}
|
|
418
|
-
const header = await this.
|
|
391
|
+
const header = await this.txe.utilityGetBlockHeader(fromSingle(blockNumber).toNumber());
|
|
419
392
|
if (!header) {
|
|
420
393
|
throw new Error(`Block header not found for block ${blockNumber}.`);
|
|
421
394
|
}
|
|
422
395
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
423
396
|
}
|
|
424
|
-
async
|
|
425
|
-
if (
|
|
397
|
+
async utilityGetMembershipWitness(blockNumber, treeId, leafValue) {
|
|
398
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
426
399
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
427
400
|
}
|
|
428
401
|
const parsedBlockNumber = fromSingle(blockNumber).toNumber();
|
|
429
402
|
const parsedTreeId = fromSingle(treeId).toNumber();
|
|
430
403
|
const parsedLeafValue = fromSingle(leafValue);
|
|
431
|
-
const witness = await this.
|
|
404
|
+
const witness = await this.txe.utilityGetMembershipWitness(parsedBlockNumber, parsedTreeId, parsedLeafValue);
|
|
432
405
|
if (!witness) {
|
|
433
406
|
throw new Error(`Membership witness in tree ${MerkleTreeId[parsedTreeId]} not found for value ${parsedLeafValue} at block ${parsedBlockNumber}.`);
|
|
434
407
|
}
|
|
@@ -437,57 +410,57 @@ export class TXEService {
|
|
|
437
410
|
toArray(witness.slice(1))
|
|
438
411
|
]);
|
|
439
412
|
}
|
|
440
|
-
async
|
|
441
|
-
if (
|
|
413
|
+
async utilityGetLowNullifierMembershipWitness(blockNumber, nullifier) {
|
|
414
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
442
415
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
443
416
|
}
|
|
444
417
|
const parsedBlockNumber = fromSingle(blockNumber).toNumber();
|
|
445
|
-
const witness = await this.
|
|
418
|
+
const witness = await this.txe.utilityGetLowNullifierMembershipWitness(parsedBlockNumber, fromSingle(nullifier));
|
|
446
419
|
if (!witness) {
|
|
447
420
|
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${parsedBlockNumber}.`);
|
|
448
421
|
}
|
|
449
422
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
450
423
|
}
|
|
451
|
-
async
|
|
452
|
-
if (
|
|
424
|
+
async utilityGetIndexedTaggingSecretAsSender(sender, recipient) {
|
|
425
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
453
426
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
454
427
|
}
|
|
455
|
-
const secret = await this.
|
|
428
|
+
const secret = await this.txe.utilityGetIndexedTaggingSecretAsSender(AztecAddress.fromField(fromSingle(sender)), AztecAddress.fromField(fromSingle(recipient)));
|
|
456
429
|
return toForeignCallResult(secret.toFields().map(toSingle));
|
|
457
430
|
}
|
|
458
|
-
async
|
|
459
|
-
if (
|
|
431
|
+
async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot) {
|
|
432
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
460
433
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
461
434
|
}
|
|
462
|
-
await this.
|
|
435
|
+
await this.txe.utilityFetchTaggedLogs(fromSingle(pendingTaggedLogArrayBaseSlot));
|
|
463
436
|
return toForeignCallResult([]);
|
|
464
437
|
}
|
|
465
|
-
async
|
|
466
|
-
if (
|
|
438
|
+
async utilityValidateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot) {
|
|
439
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
467
440
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
468
441
|
}
|
|
469
|
-
await this.
|
|
442
|
+
await this.txe.utilityValidateEnqueuedNotesAndEvents(AztecAddress.fromField(fromSingle(contractAddress)), fromSingle(noteValidationRequestsArrayBaseSlot), fromSingle(eventValidationRequestsArrayBaseSlot));
|
|
470
443
|
return toForeignCallResult([]);
|
|
471
444
|
}
|
|
472
|
-
async
|
|
473
|
-
if (
|
|
445
|
+
async utilityBulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot) {
|
|
446
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
474
447
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
475
448
|
}
|
|
476
|
-
await this.
|
|
449
|
+
await this.txe.utilityBulkRetrieveLogs(AztecAddress.fromField(fromSingle(contractAddress)), fromSingle(logRetrievalRequestsArrayBaseSlot), fromSingle(logRetrievalResponsesArrayBaseSlot));
|
|
477
450
|
return toForeignCallResult([]);
|
|
478
451
|
}
|
|
479
|
-
async
|
|
480
|
-
if (
|
|
452
|
+
async utilityStoreCapsule(contractAddress, slot, capsule) {
|
|
453
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
481
454
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
482
455
|
}
|
|
483
|
-
await this.
|
|
456
|
+
await this.txe.utilityStoreCapsule(AztecAddress.fromField(fromSingle(contractAddress)), fromSingle(slot), fromArray(capsule));
|
|
484
457
|
return toForeignCallResult([]);
|
|
485
458
|
}
|
|
486
|
-
async
|
|
487
|
-
if (
|
|
459
|
+
async utilityLoadCapsule(contractAddress, slot, tSize) {
|
|
460
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
488
461
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
489
462
|
}
|
|
490
|
-
const values = await this.
|
|
463
|
+
const values = await this.txe.utilityLoadCapsule(AztecAddress.fromField(fromSingle(contractAddress)), fromSingle(slot));
|
|
491
464
|
// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
|
|
492
465
|
// with two fields: `some` (a boolean) and `value` (a field array in this case).
|
|
493
466
|
if (values === null) {
|
|
@@ -504,39 +477,39 @@ export class TXEService {
|
|
|
504
477
|
]);
|
|
505
478
|
}
|
|
506
479
|
}
|
|
507
|
-
async
|
|
508
|
-
if (
|
|
480
|
+
async utilityDeleteCapsule(contractAddress, slot) {
|
|
481
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
509
482
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
510
483
|
}
|
|
511
|
-
await this.
|
|
484
|
+
await this.txe.utilityDeleteCapsule(AztecAddress.fromField(fromSingle(contractAddress)), fromSingle(slot));
|
|
512
485
|
return toForeignCallResult([]);
|
|
513
486
|
}
|
|
514
|
-
async
|
|
515
|
-
if (
|
|
487
|
+
async utilityCopyCapsule(contractAddress, srcSlot, dstSlot, numEntries) {
|
|
488
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
516
489
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
517
490
|
}
|
|
518
|
-
await this.
|
|
491
|
+
await this.txe.utilityCopyCapsule(AztecAddress.fromField(fromSingle(contractAddress)), fromSingle(srcSlot), fromSingle(dstSlot), fromSingle(numEntries).toNumber());
|
|
519
492
|
return toForeignCallResult([]);
|
|
520
493
|
}
|
|
521
494
|
// TODO: I forgot to add a corresponding function here, when I introduced an oracle method to txe_oracle.ts.
|
|
522
495
|
// The compiler didn't throw an error, so it took me a while to learn of the existence of this file, and that I need
|
|
523
496
|
// to implement this function here. Isn't there a way to programmatically identify that this is missing, given the
|
|
524
497
|
// existence of a txe_oracle method?
|
|
525
|
-
async
|
|
526
|
-
if (
|
|
498
|
+
async utilityAes128Decrypt(ciphertextBVecStorage, ciphertextLength, iv, symKey) {
|
|
499
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
527
500
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
528
501
|
}
|
|
529
502
|
const ciphertext = fromUintBoundedVec(ciphertextBVecStorage, ciphertextLength, 8);
|
|
530
503
|
const ivBuffer = fromUintArray(iv, 8);
|
|
531
504
|
const symKeyBuffer = fromUintArray(symKey, 8);
|
|
532
|
-
const plaintextBuffer = await this.
|
|
505
|
+
const plaintextBuffer = await this.txe.utilityAes128Decrypt(ciphertext, ivBuffer, symKeyBuffer);
|
|
533
506
|
return toForeignCallResult(arrayToBoundedVec(bufferToU8Array(plaintextBuffer), ciphertextBVecStorage.length));
|
|
534
507
|
}
|
|
535
|
-
async
|
|
536
|
-
if (
|
|
508
|
+
async utilityGetSharedSecret(address, ephPKField0, ephPKField1, ephPKField2) {
|
|
509
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
537
510
|
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
538
511
|
}
|
|
539
|
-
const secret = await this.
|
|
512
|
+
const secret = await this.txe.utilityGetSharedSecret(AztecAddress.fromField(fromSingle(address)), Point.fromFields([
|
|
540
513
|
fromSingle(ephPKField0),
|
|
541
514
|
fromSingle(ephPKField1),
|
|
542
515
|
fromSingle(ephPKField2)
|
|
@@ -544,44 +517,39 @@ export class TXEService {
|
|
|
544
517
|
return toForeignCallResult(secret.toFields().map(toSingle));
|
|
545
518
|
}
|
|
546
519
|
emitOffchainEffect(_data) {
|
|
547
|
-
|
|
548
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
549
|
-
}
|
|
550
|
-
// Offchain effects are currently discarded in the TXE tests.
|
|
551
|
-
// TODO: Expose this to the tests.
|
|
552
|
-
return toForeignCallResult([]);
|
|
520
|
+
throw new Error('Offchain effects are not yet supported in the TestEnvironment');
|
|
553
521
|
}
|
|
554
522
|
// AVM opcodes
|
|
555
523
|
avmOpcodeEmitUnencryptedLog(_message) {
|
|
556
|
-
if (
|
|
557
|
-
throw new Error(
|
|
524
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
525
|
+
throw new Error(`Attempted to call the avmOpcodeEmitUnencryptedLog oracle while in context ${TXEContext[this.context]}`);
|
|
558
526
|
}
|
|
559
527
|
// TODO(#8811): Implement
|
|
560
528
|
return toForeignCallResult([]);
|
|
561
529
|
}
|
|
562
530
|
async avmOpcodeStorageRead(slot) {
|
|
563
|
-
if (
|
|
564
|
-
throw new Error(
|
|
531
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
532
|
+
throw new Error(`Attempted to call the avmOpcodeStorageRead oracle while in context ${TXEContext[this.context]}`);
|
|
565
533
|
}
|
|
566
|
-
const value = (await this.
|
|
534
|
+
const value = (await this.txe.avmOpcodeStorageRead(fromSingle(slot))).value;
|
|
567
535
|
return toForeignCallResult([
|
|
568
536
|
toSingle(new Fr(value))
|
|
569
537
|
]);
|
|
570
538
|
}
|
|
571
539
|
async avmOpcodeStorageWrite(slot, value) {
|
|
572
|
-
if (
|
|
573
|
-
throw new Error(
|
|
540
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
541
|
+
throw new Error(`Attempted to call the avmOpcodeStorageWrite oracle while in context ${TXEContext[this.context]}`);
|
|
574
542
|
}
|
|
575
|
-
await this.
|
|
543
|
+
await this.txe.storageWrite(fromSingle(slot), [
|
|
576
544
|
fromSingle(value)
|
|
577
545
|
]);
|
|
578
546
|
return toForeignCallResult([]);
|
|
579
547
|
}
|
|
580
548
|
async avmOpcodeGetContractInstanceDeployer(address) {
|
|
581
|
-
if (
|
|
582
|
-
throw new Error(
|
|
549
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
550
|
+
throw new Error(`Attempted to call the avmOpcodeGetContractInstanceDeployer oracle while in context ${TXEContext[this.context]}`);
|
|
583
551
|
}
|
|
584
|
-
const instance = await this.
|
|
552
|
+
const instance = await this.txe.utilityGetContractInstance(addressFromSingle(address));
|
|
585
553
|
return toForeignCallResult([
|
|
586
554
|
toSingle(instance.deployer),
|
|
587
555
|
// AVM requires an extra boolean indicating the instance was found
|
|
@@ -589,10 +557,10 @@ export class TXEService {
|
|
|
589
557
|
]);
|
|
590
558
|
}
|
|
591
559
|
async avmOpcodeGetContractInstanceClassId(address) {
|
|
592
|
-
if (
|
|
593
|
-
throw new Error(
|
|
560
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
561
|
+
throw new Error(`Attempted to call the avmOpcodeGetContractInstanceClassId oracle while in context ${TXEContext[this.context]}`);
|
|
594
562
|
}
|
|
595
|
-
const instance = await this.
|
|
563
|
+
const instance = await this.txe.utilityGetContractInstance(addressFromSingle(address));
|
|
596
564
|
return toForeignCallResult([
|
|
597
565
|
toSingle(instance.currentContractClassId),
|
|
598
566
|
// AVM requires an extra boolean indicating the instance was found
|
|
@@ -600,10 +568,10 @@ export class TXEService {
|
|
|
600
568
|
]);
|
|
601
569
|
}
|
|
602
570
|
async avmOpcodeGetContractInstanceInitializationHash(address) {
|
|
603
|
-
if (
|
|
604
|
-
throw new Error(
|
|
571
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
572
|
+
throw new Error(`Attempted to call the avmOpcodeGetContractInstanceInitializationHash oracle while in context ${TXEContext[this.context]}`);
|
|
605
573
|
}
|
|
606
|
-
const instance = await this.
|
|
574
|
+
const instance = await this.txe.utilityGetContractInstance(addressFromSingle(address));
|
|
607
575
|
return toForeignCallResult([
|
|
608
576
|
toSingle(instance.initializationHash),
|
|
609
577
|
// AVM requires an extra boolean indicating the instance was found
|
|
@@ -611,181 +579,157 @@ export class TXEService {
|
|
|
611
579
|
]);
|
|
612
580
|
}
|
|
613
581
|
avmOpcodeSender() {
|
|
614
|
-
if (
|
|
615
|
-
throw new Error(
|
|
582
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
583
|
+
throw new Error(`Attempted to call the avmOpcodeSender oracle while in context ${TXEContext[this.context]}`);
|
|
616
584
|
}
|
|
617
|
-
const sender = this.
|
|
585
|
+
const sender = this.txe.getMsgSender();
|
|
618
586
|
return toForeignCallResult([
|
|
619
587
|
toSingle(sender)
|
|
620
588
|
]);
|
|
621
589
|
}
|
|
622
590
|
async avmOpcodeEmitNullifier(nullifier) {
|
|
623
|
-
if (
|
|
624
|
-
throw new Error(
|
|
591
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
592
|
+
throw new Error(`Attempted to call the avmOpcodeEmitNullifier oracle while in context ${TXEContext[this.context]}`);
|
|
625
593
|
}
|
|
626
|
-
await this.
|
|
594
|
+
await this.txe.avmOpcodeEmitNullifier(fromSingle(nullifier));
|
|
627
595
|
return toForeignCallResult([]);
|
|
628
596
|
}
|
|
629
597
|
async avmOpcodeEmitNoteHash(noteHash) {
|
|
630
|
-
if (
|
|
631
|
-
throw new Error(
|
|
598
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
599
|
+
throw new Error(`Attempted to call the avmOpcodeEmitNoteHash oracle while in context ${TXEContext[this.context]}`);
|
|
632
600
|
}
|
|
633
|
-
await this.
|
|
601
|
+
await this.txe.avmOpcodeEmitNoteHash(fromSingle(noteHash));
|
|
634
602
|
return toForeignCallResult([]);
|
|
635
603
|
}
|
|
636
604
|
async avmOpcodeNullifierExists(innerNullifier, targetAddress) {
|
|
637
|
-
if (
|
|
638
|
-
throw new Error(
|
|
605
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
606
|
+
throw new Error(`Attempted to call the avmOpcodeNullifierExists oracle while in context ${TXEContext[this.context]}`);
|
|
639
607
|
}
|
|
640
|
-
const exists = await this.
|
|
608
|
+
const exists = await this.txe.avmOpcodeNullifierExists(fromSingle(innerNullifier), AztecAddress.fromField(fromSingle(targetAddress)));
|
|
641
609
|
return toForeignCallResult([
|
|
642
610
|
toSingle(new Fr(exists))
|
|
643
611
|
]);
|
|
644
612
|
}
|
|
645
613
|
async avmOpcodeAddress() {
|
|
646
|
-
if (
|
|
647
|
-
throw new Error(
|
|
614
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
615
|
+
throw new Error(`Attempted to call the avmOpcodeAddress oracle while in context ${TXEContext[this.context]}`);
|
|
648
616
|
}
|
|
649
|
-
const contractAddress = await this.
|
|
617
|
+
const contractAddress = await this.txe.utilityGetContractAddress();
|
|
650
618
|
return toForeignCallResult([
|
|
651
619
|
toSingle(contractAddress.toField())
|
|
652
620
|
]);
|
|
653
621
|
}
|
|
654
622
|
async avmOpcodeBlockNumber() {
|
|
655
|
-
if (
|
|
656
|
-
throw new Error(
|
|
623
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
624
|
+
throw new Error(`Attempted to call the avmOpcodeBlockNumber oracle while in context ${TXEContext[this.context]}`);
|
|
657
625
|
}
|
|
658
|
-
const blockNumber = await this.
|
|
626
|
+
const blockNumber = await this.txe.utilityGetBlockNumber();
|
|
659
627
|
return toForeignCallResult([
|
|
660
628
|
toSingle(new Fr(blockNumber))
|
|
661
629
|
]);
|
|
662
630
|
}
|
|
663
631
|
async avmOpcodeTimestamp() {
|
|
664
|
-
if (
|
|
665
|
-
throw new Error(
|
|
632
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
633
|
+
throw new Error(`Attempted to call the avmOpcodeTimestamp oracle while in context ${TXEContext[this.context]}`);
|
|
666
634
|
}
|
|
667
|
-
const timestamp = await this.
|
|
635
|
+
const timestamp = await this.txe.utilityGetTimestamp();
|
|
668
636
|
return toForeignCallResult([
|
|
669
637
|
toSingle(new Fr(timestamp))
|
|
670
638
|
]);
|
|
671
639
|
}
|
|
672
640
|
avmOpcodeIsStaticCall() {
|
|
673
|
-
if (
|
|
674
|
-
throw new Error(
|
|
641
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
642
|
+
throw new Error(`Attempted to call the avmOpcodeIsStaticCall oracle while in context ${TXEContext[this.context]}`);
|
|
675
643
|
}
|
|
676
|
-
|
|
644
|
+
// TestEnvironment::public_context is always static
|
|
645
|
+
const isStaticCall = true;
|
|
677
646
|
return toForeignCallResult([
|
|
678
647
|
toSingle(new Fr(isStaticCall ? 1 : 0))
|
|
679
648
|
]);
|
|
680
649
|
}
|
|
681
650
|
async avmOpcodeChainId() {
|
|
682
|
-
if (
|
|
683
|
-
throw new Error(
|
|
651
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
652
|
+
throw new Error(`Attempted to call the avmOpcodeChainId oracle while in context ${TXEContext[this.context]}`);
|
|
684
653
|
}
|
|
685
|
-
const chainId = await this.
|
|
654
|
+
const chainId = await this.txe.utilityGetChainId();
|
|
686
655
|
return toForeignCallResult([
|
|
687
656
|
toSingle(chainId)
|
|
688
657
|
]);
|
|
689
658
|
}
|
|
690
659
|
async avmOpcodeVersion() {
|
|
691
|
-
if (
|
|
692
|
-
throw new Error(
|
|
660
|
+
if (this.contextChecksEnabled && this.context != 2) {
|
|
661
|
+
throw new Error(`Attempted to call the avmOpcodeVersion oracle while in context ${TXEContext[this.context]}`);
|
|
693
662
|
}
|
|
694
|
-
const version = await this.
|
|
663
|
+
const version = await this.txe.utilityGetVersion();
|
|
695
664
|
return toForeignCallResult([
|
|
696
665
|
toSingle(version)
|
|
697
666
|
]);
|
|
698
667
|
}
|
|
699
668
|
avmOpcodeReturndataSize() {
|
|
700
|
-
|
|
701
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
702
|
-
}
|
|
703
|
-
const size = this.typedOracle.avmOpcodeReturndataSize();
|
|
704
|
-
return toForeignCallResult([
|
|
705
|
-
toSingle(new Fr(size))
|
|
706
|
-
]);
|
|
669
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
|
|
707
670
|
}
|
|
708
|
-
avmOpcodeReturndataCopy(
|
|
709
|
-
|
|
710
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
711
|
-
}
|
|
712
|
-
const returndata = this.typedOracle.avmOpcodeReturndataCopy(fromSingle(rdOffset).toNumber(), fromSingle(copySize).toNumber());
|
|
713
|
-
// This is a slice, so we need to return the length as well.
|
|
714
|
-
return toForeignCallResult([
|
|
715
|
-
toSingle(new Fr(returndata.length)),
|
|
716
|
-
toArray(returndata)
|
|
717
|
-
]);
|
|
671
|
+
avmOpcodeReturndataCopy(_rdOffset, _copySize) {
|
|
672
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
|
|
718
673
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
722
|
-
}
|
|
723
|
-
const result = await this.typedOracle.avmOpcodeCall(addressFromSingle(address), fromArray(args), /* isStaticCall */ false);
|
|
724
|
-
// Poor man's revert handling
|
|
725
|
-
if (!result.revertCode.isOK()) {
|
|
726
|
-
if (result.revertReason && result.revertReason instanceof SimulationError) {
|
|
727
|
-
await enrichPublicSimulationError(result.revertReason, this.typedOracle.getContractDataProvider(), this.logger);
|
|
728
|
-
throw new Error(result.revertReason.message);
|
|
729
|
-
} else {
|
|
730
|
-
throw new Error(`Public function call reverted: ${result.revertReason}`);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
return toForeignCallResult([]);
|
|
674
|
+
avmOpcodeCall(_l2Gas, _daGas, _address, _length, _args) {
|
|
675
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
|
|
734
676
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
738
|
-
}
|
|
739
|
-
const result = await this.typedOracle.avmOpcodeCall(addressFromSingle(address), fromArray(args), /* isStaticCall */ true);
|
|
740
|
-
// Poor man's revert handling
|
|
741
|
-
if (!result.revertCode.isOK()) {
|
|
742
|
-
if (result.revertReason && result.revertReason instanceof SimulationError) {
|
|
743
|
-
await enrichPublicSimulationError(result.revertReason, this.typedOracle.getContractDataProvider(), this.logger);
|
|
744
|
-
throw new Error(result.revertReason.message);
|
|
745
|
-
} else {
|
|
746
|
-
throw new Error(`Public function call reverted: ${result.revertReason}`);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
return toForeignCallResult([]);
|
|
677
|
+
avmOpcodeStaticCall(_l2Gas, _daGas, _address, _length, _args) {
|
|
678
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
|
|
750
679
|
}
|
|
751
680
|
avmOpcodeSuccessCopy() {
|
|
752
|
-
|
|
753
|
-
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
754
|
-
}
|
|
755
|
-
const success = this.typedOracle.avmOpcodeSuccessCopy();
|
|
756
|
-
return toForeignCallResult([
|
|
757
|
-
toSingle(new Fr(success))
|
|
758
|
-
]);
|
|
681
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
|
|
759
682
|
}
|
|
760
|
-
async
|
|
761
|
-
const result = await this.
|
|
683
|
+
async txePrivateCallNewFlow(from, targetContractAddress, functionSelector, _argsLength, args, argsHash, isStaticCall) {
|
|
684
|
+
const result = await this.txe.txePrivateCallNewFlow(addressFromSingle(from), addressFromSingle(targetContractAddress), FunctionSelector.fromField(fromSingle(functionSelector)), fromArray(args), fromSingle(argsHash), fromSingle(isStaticCall).toBool());
|
|
762
685
|
return toForeignCallResult([
|
|
763
686
|
toArray([
|
|
764
687
|
result.endSideEffectCounter,
|
|
765
688
|
result.returnsHash,
|
|
766
|
-
result.txHash
|
|
689
|
+
result.txHash.hash
|
|
767
690
|
])
|
|
768
691
|
]);
|
|
769
692
|
}
|
|
770
|
-
disableOracles() {
|
|
771
|
-
this.oraclesEnabled = false;
|
|
772
|
-
}
|
|
773
|
-
enableOracles() {
|
|
774
|
-
this.oraclesEnabled = true;
|
|
775
|
-
}
|
|
776
693
|
async simulateUtilityFunction(targetContractAddress, functionSelector, argsHash) {
|
|
777
|
-
const result = await this.
|
|
694
|
+
const result = await this.txe.simulateUtilityFunction(addressFromSingle(targetContractAddress), FunctionSelector.fromField(fromSingle(functionSelector)), fromSingle(argsHash));
|
|
778
695
|
return toForeignCallResult([
|
|
779
696
|
toSingle(result)
|
|
780
697
|
]);
|
|
781
698
|
}
|
|
782
|
-
async
|
|
783
|
-
const result = await this.
|
|
699
|
+
async txePublicCallNewFlow(from, address, _length, calldata, isStaticCall) {
|
|
700
|
+
const result = await this.txe.txePublicCallNewFlow(addressFromSingle(from), addressFromSingle(address), fromArray(calldata), fromSingle(isStaticCall).toBool());
|
|
784
701
|
return toForeignCallResult([
|
|
785
702
|
toArray([
|
|
786
703
|
result.returnsHash,
|
|
787
|
-
result.txHash
|
|
704
|
+
result.txHash.hash
|
|
788
705
|
])
|
|
789
706
|
]);
|
|
790
707
|
}
|
|
708
|
+
async privateGetSenderForTags() {
|
|
709
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
710
|
+
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
711
|
+
}
|
|
712
|
+
const sender = await this.txe.privateGetSenderForTags();
|
|
713
|
+
// Return a Noir Option struct with `some` and `value` fields
|
|
714
|
+
if (sender === undefined) {
|
|
715
|
+
// No sender found, return Option with some=0 and value=0
|
|
716
|
+
return toForeignCallResult([
|
|
717
|
+
toSingle(0),
|
|
718
|
+
toSingle(0)
|
|
719
|
+
]);
|
|
720
|
+
} else {
|
|
721
|
+
// Sender found, return Option with some=1 and value=sender address
|
|
722
|
+
return toForeignCallResult([
|
|
723
|
+
toSingle(1),
|
|
724
|
+
toSingle(sender)
|
|
725
|
+
]);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
async privateSetSenderForTags(senderForTags) {
|
|
729
|
+
if (this.contextChecksEnabled && this.context == 0) {
|
|
730
|
+
throw new Error('Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.');
|
|
731
|
+
}
|
|
732
|
+
await this.txe.privateSetSenderForTags(AztecAddress.fromField(fromSingle(senderForTags)));
|
|
733
|
+
return toForeignCallResult([]);
|
|
734
|
+
}
|
|
791
735
|
}
|