@aztec/txe 3.0.3 → 3.9.9-nightly.20260312
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/constants.d.ts +3 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +2 -0
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +85 -52
- package/dest/oracle/interfaces.d.ts +9 -6
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +4 -4
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +9 -11
- package/dest/oracle/txe_oracle_top_level_context.d.ts +21 -13
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +180 -72
- package/dest/rpc_translator.d.ts +29 -17
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +124 -57
- package/dest/state_machine/archiver.d.ts +20 -55
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +67 -108
- package/dest/state_machine/dummy_p2p_client.d.ts +20 -15
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +42 -25
- package/dest/state_machine/global_variable_builder.d.ts +4 -3
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +13 -1
- package/dest/state_machine/index.d.ts +7 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +41 -24
- package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +14 -7
- package/dest/state_machine/synchronizer.d.ts +3 -3
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/txe_session.d.ts +22 -11
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +154 -49
- package/dest/util/encoding.d.ts +617 -18
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/txe_account_store.d.ts +10 -0
- package/dest/util/txe_account_store.d.ts.map +1 -0
- package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
- package/dest/util/txe_public_contract_data_source.d.ts +5 -6
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +12 -29
- package/dest/utils/block_creation.d.ts +18 -4
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +37 -3
- package/dest/utils/tx_effect_creation.d.ts +2 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +3 -6
- package/package.json +16 -16
- package/src/constants.ts +3 -0
- package/src/index.ts +97 -60
- package/src/oracle/interfaces.ts +11 -4
- package/src/oracle/txe_oracle_public_context.ts +9 -16
- package/src/oracle/txe_oracle_top_level_context.ts +223 -110
- package/src/rpc_translator.ts +141 -58
- package/src/state_machine/archiver.ts +61 -129
- package/src/state_machine/dummy_p2p_client.ts +58 -33
- package/src/state_machine/global_variable_builder.ts +19 -2
- package/src/state_machine/index.ts +61 -22
- package/src/state_machine/mock_epoch_cache.ts +15 -11
- package/src/state_machine/synchronizer.ts +2 -2
- package/src/txe_session.ts +213 -94
- package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
- package/src/util/txe_public_contract_data_source.ts +16 -42
- package/src/utils/block_creation.ts +47 -14
- package/src/utils/tx_effect_creation.ts +3 -11
- package/dest/util/txe_account_data_provider.d.ts +0 -10
- package/dest/util/txe_account_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.d.ts +0 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.js +0 -22
- package/src/util/txe_contract_data_provider.ts +0 -36
|
@@ -3,9 +3,8 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
5
5
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
6
|
-
import {
|
|
6
|
+
import type { L2Block } from '@aztec/stdlib/block';
|
|
7
7
|
import { computePublicDataTreeLeafSlot, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
8
|
-
import { makeAppendOnlyTreeSnapshot } from '@aztec/stdlib/testing';
|
|
9
8
|
import {
|
|
10
9
|
MerkleTreeId,
|
|
11
10
|
type MerkleTreeWriteOperations,
|
|
@@ -14,7 +13,7 @@ import {
|
|
|
14
13
|
} from '@aztec/stdlib/trees';
|
|
15
14
|
import { GlobalVariables, TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
16
15
|
|
|
17
|
-
import { insertTxEffectIntoWorldTrees,
|
|
16
|
+
import { insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
18
17
|
import type { IAvmExecutionOracle } from './interfaces.js';
|
|
19
18
|
|
|
20
19
|
export class TXEOraclePublicContext implements IAvmExecutionOracle {
|
|
@@ -79,13 +78,11 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
|
|
|
79
78
|
this.transientUniqueNoteHashes.push(siloedNoteHash);
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
async avmOpcodeNullifierExists(
|
|
83
|
-
const nullifier = await siloNullifier(targetAddress, innerNullifier!);
|
|
84
|
-
|
|
81
|
+
async avmOpcodeNullifierExists(siloedNullifier: Fr): Promise<boolean> {
|
|
85
82
|
const treeIndex = (
|
|
86
|
-
await this.forkedWorldTrees.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [
|
|
83
|
+
await this.forkedWorldTrees.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [siloedNullifier.toBuffer()])
|
|
87
84
|
)[0];
|
|
88
|
-
const transientIndex = this.transientSiloedNullifiers.find(n => n.equals(
|
|
85
|
+
const transientIndex = this.transientSiloedNullifiers.find(n => n.equals(siloedNullifier));
|
|
89
86
|
|
|
90
87
|
return treeIndex !== undefined || transientIndex !== undefined;
|
|
91
88
|
}
|
|
@@ -102,8 +99,8 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
|
|
|
102
99
|
]);
|
|
103
100
|
}
|
|
104
101
|
|
|
105
|
-
async avmOpcodeStorageRead(slot: Fr): Promise<Fr> {
|
|
106
|
-
const leafSlot = await computePublicDataTreeLeafSlot(
|
|
102
|
+
async avmOpcodeStorageRead(slot: Fr, contractAddress: AztecAddress): Promise<Fr> {
|
|
103
|
+
const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
107
104
|
|
|
108
105
|
const lowLeafResult = await this.forkedWorldTrees.getPreviousValueIndex(
|
|
109
106
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
@@ -120,7 +117,7 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
|
|
|
120
117
|
)) as PublicDataTreeLeafPreimage
|
|
121
118
|
).leaf.value;
|
|
122
119
|
|
|
123
|
-
this.logger.debug('AVM storage read', { slot, value });
|
|
120
|
+
this.logger.debug('AVM storage read', { slot, contractAddress, value });
|
|
124
121
|
|
|
125
122
|
return value;
|
|
126
123
|
}
|
|
@@ -133,11 +130,7 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
|
|
|
133
130
|
const txEffect = this.makeTxEffect();
|
|
134
131
|
await insertTxEffectIntoWorldTrees(txEffect, this.forkedWorldTrees);
|
|
135
132
|
|
|
136
|
-
const block =
|
|
137
|
-
makeAppendOnlyTreeSnapshot(),
|
|
138
|
-
await makeTXEBlockHeader(this.forkedWorldTrees, this.globalVariables),
|
|
139
|
-
new Body([txEffect]),
|
|
140
|
-
);
|
|
133
|
+
const block = await makeTXEBlock(this.forkedWorldTrees, this.globalVariables, [txEffect]);
|
|
141
134
|
|
|
142
135
|
await this.forkedWorldTrees.close();
|
|
143
136
|
|
|
@@ -12,10 +12,17 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
12
12
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
13
13
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
14
14
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
15
16
|
import {
|
|
16
|
-
|
|
17
|
+
AddressStore,
|
|
18
|
+
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
20
|
+
NoteStore,
|
|
17
21
|
ORACLE_VERSION,
|
|
18
|
-
|
|
22
|
+
PrivateEventStore,
|
|
23
|
+
RecipientTaggingStore,
|
|
24
|
+
SenderAddressBookStore,
|
|
25
|
+
SenderTaggingStore,
|
|
19
26
|
enrichPublicSimulationError,
|
|
20
27
|
} from '@aztec/pxe/server';
|
|
21
28
|
import {
|
|
@@ -44,11 +51,10 @@ import {
|
|
|
44
51
|
PublicContractsDB,
|
|
45
52
|
PublicProcessor,
|
|
46
53
|
} from '@aztec/simulator/server';
|
|
47
|
-
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
54
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
48
55
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
49
56
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
50
57
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
51
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
52
58
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
53
59
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
54
60
|
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
@@ -59,7 +65,7 @@ import {
|
|
|
59
65
|
PublicCallRequest,
|
|
60
66
|
} from '@aztec/stdlib/kernel';
|
|
61
67
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
62
|
-
import {
|
|
68
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
63
69
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
64
70
|
import {
|
|
65
71
|
CallContext,
|
|
@@ -76,15 +82,11 @@ import {
|
|
|
76
82
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
77
83
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
78
84
|
|
|
85
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
79
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
80
|
-
import type {
|
|
81
|
-
import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
|
|
87
|
+
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
82
88
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
83
|
-
import {
|
|
84
|
-
getSingleTxBlockRequestHash,
|
|
85
|
-
insertTxEffectIntoWorldTrees,
|
|
86
|
-
makeTXEBlockHeader,
|
|
87
|
-
} from '../utils/block_creation.js';
|
|
89
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
88
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
89
91
|
|
|
90
92
|
export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
|
|
@@ -95,11 +97,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
95
97
|
|
|
96
98
|
constructor(
|
|
97
99
|
private stateMachine: TXEStateMachine,
|
|
98
|
-
private
|
|
100
|
+
private contractStore: ContractStore,
|
|
101
|
+
private noteStore: NoteStore,
|
|
99
102
|
private keyStore: KeyStore,
|
|
100
|
-
private
|
|
101
|
-
private
|
|
102
|
-
private
|
|
103
|
+
private addressStore: AddressStore,
|
|
104
|
+
private accountStore: TXEAccountStore,
|
|
105
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
106
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
107
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
108
|
+
private capsuleStore: CapsuleStore,
|
|
109
|
+
private privateEventStore: PrivateEventStore,
|
|
103
110
|
private nextBlockTimestamp: bigint,
|
|
104
111
|
private version: Fr,
|
|
105
112
|
private chainId: Fr,
|
|
@@ -124,13 +131,18 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
124
131
|
}
|
|
125
132
|
|
|
126
133
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
127
|
-
|
|
134
|
+
utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
128
135
|
if (!LogLevels[level]) {
|
|
129
|
-
throw new Error(`Invalid
|
|
136
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
130
137
|
}
|
|
131
138
|
const levelName = LogLevels[level];
|
|
132
139
|
|
|
133
140
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
141
|
+
return Promise.resolve();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
txeGetDefaultAddress(): AztecAddress {
|
|
145
|
+
return DEFAULT_ADDRESS;
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
async txeGetNextBlockNumber(): Promise<BlockNumber> {
|
|
@@ -146,7 +158,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
async txeGetLastTxEffects() {
|
|
149
|
-
const
|
|
161
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
162
|
+
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
150
163
|
|
|
151
164
|
if (block!.body.txEffects.length != 1) {
|
|
152
165
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -158,6 +171,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
158
171
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
159
172
|
}
|
|
160
173
|
|
|
174
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
175
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
176
|
+
this.logger.debug(`Skipping sync in txeGetPrivateEvents because the events correspond to the default address.`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
181
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
182
|
+
contractAddress,
|
|
183
|
+
null,
|
|
184
|
+
async (call, execScopes) => {
|
|
185
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
186
|
+
},
|
|
187
|
+
blockHeader,
|
|
188
|
+
jobId,
|
|
189
|
+
[scope],
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
194
|
+
return (
|
|
195
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
196
|
+
contractAddress,
|
|
197
|
+
scopes: [scope],
|
|
198
|
+
fromBlock: 0,
|
|
199
|
+
toBlock: (await this.getLastBlockNumber()) + 1,
|
|
200
|
+
})
|
|
201
|
+
).map(e => e.packedEvent);
|
|
202
|
+
}
|
|
203
|
+
|
|
161
204
|
async txeAdvanceBlocksBy(blocks: number) {
|
|
162
205
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
163
206
|
|
|
@@ -185,8 +228,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
185
228
|
if (!secret.equals(Fr.ZERO)) {
|
|
186
229
|
await this.txeAddAccount(artifact, instance, secret);
|
|
187
230
|
} else {
|
|
188
|
-
await this.
|
|
189
|
-
await this.
|
|
231
|
+
await this.contractStore.addContractInstance(instance);
|
|
232
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
190
233
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
191
234
|
}
|
|
192
235
|
}
|
|
@@ -195,29 +238,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
195
238
|
const partialAddress = await computePartialAddress(instance);
|
|
196
239
|
|
|
197
240
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
198
|
-
await this.
|
|
199
|
-
await this.
|
|
241
|
+
await this.contractStore.addContractInstance(instance);
|
|
242
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
200
243
|
|
|
201
244
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
202
|
-
await this.
|
|
203
|
-
await this.
|
|
245
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
246
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
204
247
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
205
248
|
|
|
206
249
|
return completeAddress;
|
|
207
250
|
}
|
|
208
251
|
|
|
209
252
|
async txeCreateAccount(secret: Fr) {
|
|
210
|
-
// This is a
|
|
253
|
+
// This is a foot gun !
|
|
211
254
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
212
|
-
await this.
|
|
213
|
-
await this.
|
|
255
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
256
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
214
257
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
215
258
|
|
|
216
259
|
return completeAddress;
|
|
217
260
|
}
|
|
218
261
|
|
|
219
262
|
async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
220
|
-
const account = await this.
|
|
263
|
+
const account = await this.accountStore.getAccount(address);
|
|
221
264
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
222
265
|
|
|
223
266
|
const schnorr = new Schnorr();
|
|
@@ -238,19 +281,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
238
281
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
239
282
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
240
283
|
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
version: this.version,
|
|
249
|
-
chainId: this.chainId,
|
|
250
|
-
}),
|
|
251
|
-
),
|
|
252
|
-
new Body([txEffect]),
|
|
253
|
-
);
|
|
284
|
+
const globals = makeGlobalVariables(undefined, {
|
|
285
|
+
blockNumber,
|
|
286
|
+
timestamp: this.nextBlockTimestamp,
|
|
287
|
+
version: this.version,
|
|
288
|
+
chainId: this.chainId,
|
|
289
|
+
});
|
|
290
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
254
291
|
|
|
255
292
|
await forkedWorldTrees.close();
|
|
256
293
|
|
|
@@ -266,12 +303,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
266
303
|
args: Fr[],
|
|
267
304
|
argsHash: Fr = Fr.zero(),
|
|
268
305
|
isStaticCall: boolean = false,
|
|
306
|
+
jobId: string,
|
|
269
307
|
) {
|
|
270
308
|
this.logger.verbose(
|
|
271
|
-
`Executing external function ${await this.
|
|
309
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
272
310
|
);
|
|
273
311
|
|
|
274
|
-
const artifact = await this.
|
|
312
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
275
313
|
if (!artifact) {
|
|
276
314
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
277
315
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -279,51 +317,77 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
279
317
|
throw new Error(message);
|
|
280
318
|
}
|
|
281
319
|
|
|
320
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
321
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
322
|
+
const effectiveScopes = from.isZero() ? [] : [from];
|
|
323
|
+
|
|
324
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
325
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
326
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
330
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
331
|
+
targetContractAddress,
|
|
332
|
+
functionSelector,
|
|
333
|
+
utilityExecutor,
|
|
334
|
+
blockHeader,
|
|
335
|
+
jobId,
|
|
336
|
+
effectiveScopes,
|
|
337
|
+
);
|
|
338
|
+
|
|
282
339
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
283
340
|
|
|
284
341
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
285
342
|
|
|
286
343
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
287
|
-
|
|
288
344
|
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
289
|
-
|
|
290
345
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
291
346
|
|
|
292
347
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
293
348
|
|
|
294
|
-
const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
|
|
295
|
-
|
|
296
349
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
297
350
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
351
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
352
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
353
|
+
// marking all side effects as revertible.
|
|
354
|
+
const minRevertibleSideEffectCounter = 1;
|
|
355
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
298
356
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
299
357
|
|
|
300
358
|
const simulator = new WASMSimulator();
|
|
301
359
|
|
|
302
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
360
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
303
361
|
argsHash,
|
|
304
362
|
txContext,
|
|
305
363
|
callContext,
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
[],
|
|
312
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
364
|
+
anchorBlockHeader: blockHeader,
|
|
365
|
+
utilityExecutor,
|
|
366
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
367
|
+
capsules: [],
|
|
368
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
313
369
|
noteCache,
|
|
314
370
|
taggingIndexCache,
|
|
315
|
-
this.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
371
|
+
contractStore: this.contractStore,
|
|
372
|
+
noteStore: this.noteStore,
|
|
373
|
+
keyStore: this.keyStore,
|
|
374
|
+
addressStore: this.addressStore,
|
|
375
|
+
aztecNode: this.stateMachine.node,
|
|
376
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
377
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
378
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
379
|
+
capsuleStore: this.capsuleStore,
|
|
380
|
+
privateEventStore: this.privateEventStore,
|
|
381
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
382
|
+
jobId,
|
|
383
|
+
totalPublicCalldataCount: 0,
|
|
384
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
385
|
+
scopes: effectiveScopes,
|
|
386
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
387
|
+
// contract would perform, including setting senderForTags.
|
|
388
|
+
senderForTags: from,
|
|
325
389
|
simulator,
|
|
326
|
-
);
|
|
390
|
+
});
|
|
327
391
|
|
|
328
392
|
// Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
|
|
329
393
|
let result: PrivateExecutionResult;
|
|
@@ -350,19 +414,22 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
350
414
|
}),
|
|
351
415
|
);
|
|
352
416
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
417
|
+
noteCache.finish();
|
|
418
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
419
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
357
420
|
} catch (err) {
|
|
358
421
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
359
422
|
}
|
|
360
423
|
|
|
361
|
-
// According to the protocol rules,
|
|
362
|
-
//
|
|
363
|
-
//
|
|
364
|
-
const
|
|
365
|
-
|
|
424
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
425
|
+
// the nonce generator for the note hashes.
|
|
426
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
427
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
428
|
+
result,
|
|
429
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
430
|
+
this.stateMachine.node,
|
|
431
|
+
minRevertibleSideEffectCounter,
|
|
432
|
+
);
|
|
366
433
|
|
|
367
434
|
const globals = makeGlobalVariables();
|
|
368
435
|
globals.blockNumber = blockNumber;
|
|
@@ -373,7 +440,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
373
440
|
|
|
374
441
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
375
442
|
|
|
376
|
-
const
|
|
443
|
+
const bindings = this.logger.getBindings();
|
|
444
|
+
const contractsDB = new PublicContractsDB(
|
|
445
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
446
|
+
bindings,
|
|
447
|
+
);
|
|
377
448
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
378
449
|
const config = PublicSimulatorConfig.from({
|
|
379
450
|
skipFeeEnforcement: true,
|
|
@@ -386,8 +457,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
386
457
|
globals,
|
|
387
458
|
guardedMerkleTrees,
|
|
388
459
|
contractsDB,
|
|
389
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
460
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
390
461
|
new TestDateProvider(),
|
|
462
|
+
undefined,
|
|
463
|
+
createLogger('simulator:public-processor', bindings),
|
|
391
464
|
);
|
|
392
465
|
|
|
393
466
|
const tx = await Tx.create({
|
|
@@ -412,7 +485,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
412
485
|
} else if (!processedTx.revertCode.isOK()) {
|
|
413
486
|
if (processedTx.revertReason) {
|
|
414
487
|
try {
|
|
415
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
488
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
416
489
|
// eslint-disable-next-line no-empty
|
|
417
490
|
} catch {}
|
|
418
491
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -441,13 +514,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
441
514
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
442
515
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
443
516
|
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
const l2Block = new L2Block(
|
|
447
|
-
makeAppendOnlyTreeSnapshot(),
|
|
448
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
449
|
-
body,
|
|
450
|
-
);
|
|
517
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
451
518
|
|
|
452
519
|
await this.stateMachine.handleL2Block(l2Block);
|
|
453
520
|
|
|
@@ -463,7 +530,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
463
530
|
isStaticCall: boolean,
|
|
464
531
|
) {
|
|
465
532
|
this.logger.verbose(
|
|
466
|
-
`Executing public function ${await this.
|
|
533
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
467
534
|
);
|
|
468
535
|
|
|
469
536
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
@@ -476,7 +543,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
476
543
|
|
|
477
544
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
478
545
|
|
|
479
|
-
const anchorBlockHeader = await this.
|
|
546
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
480
547
|
|
|
481
548
|
const calldataHash = await computeCalldataHash(calldata);
|
|
482
549
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -490,7 +557,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
490
557
|
|
|
491
558
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
492
559
|
|
|
493
|
-
const
|
|
560
|
+
const bindings2 = this.logger.getBindings();
|
|
561
|
+
const contractsDB = new PublicContractsDB(
|
|
562
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
563
|
+
bindings2,
|
|
564
|
+
);
|
|
494
565
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
495
566
|
const config = PublicSimulatorConfig.from({
|
|
496
567
|
skipFeeEnforcement: true,
|
|
@@ -499,8 +570,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
499
570
|
collectStatistics: false,
|
|
500
571
|
collectCallMetadata: true,
|
|
501
572
|
});
|
|
502
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
503
|
-
const processor = new PublicProcessor(
|
|
573
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
574
|
+
const processor = new PublicProcessor(
|
|
575
|
+
globals,
|
|
576
|
+
guardedMerkleTrees,
|
|
577
|
+
contractsDB,
|
|
578
|
+
simulator,
|
|
579
|
+
new TestDateProvider(),
|
|
580
|
+
undefined,
|
|
581
|
+
createLogger('simulator:public-processor', bindings2),
|
|
582
|
+
);
|
|
504
583
|
|
|
505
584
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
506
585
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -531,7 +610,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
531
610
|
constantData,
|
|
532
611
|
/*gasUsed=*/ new Gas(0, 0),
|
|
533
612
|
/*feePayer=*/ AztecAddress.zero(),
|
|
534
|
-
/*
|
|
613
|
+
/*expirationTimestamp=*/ 0n,
|
|
535
614
|
inputsForPublic,
|
|
536
615
|
undefined,
|
|
537
616
|
);
|
|
@@ -558,7 +637,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
558
637
|
} else if (!processedTx.revertCode.isOK()) {
|
|
559
638
|
if (processedTx.revertReason) {
|
|
560
639
|
try {
|
|
561
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
640
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
562
641
|
// eslint-disable-next-line no-empty
|
|
563
642
|
} catch {}
|
|
564
643
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -590,13 +669,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
590
669
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
591
670
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
592
671
|
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
const l2Block = new L2Block(
|
|
596
|
-
makeAppendOnlyTreeSnapshot(),
|
|
597
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
598
|
-
body,
|
|
599
|
-
);
|
|
672
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
600
673
|
|
|
601
674
|
await this.stateMachine.handleL2Block(l2Block);
|
|
602
675
|
|
|
@@ -605,23 +678,46 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
605
678
|
return returnValues ?? [];
|
|
606
679
|
}
|
|
607
680
|
|
|
608
|
-
async
|
|
681
|
+
async txeExecuteUtilityFunction(
|
|
609
682
|
targetContractAddress: AztecAddress,
|
|
610
683
|
functionSelector: FunctionSelector,
|
|
611
684
|
args: Fr[],
|
|
685
|
+
jobId: string,
|
|
612
686
|
) {
|
|
613
|
-
const artifact = await this.
|
|
687
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
614
688
|
if (!artifact) {
|
|
615
689
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
616
690
|
}
|
|
617
691
|
|
|
618
|
-
|
|
692
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
693
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
694
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
695
|
+
targetContractAddress,
|
|
696
|
+
functionSelector,
|
|
697
|
+
async (call, execScopes) => {
|
|
698
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
699
|
+
},
|
|
700
|
+
blockHeader,
|
|
701
|
+
jobId,
|
|
702
|
+
'ALL_SCOPES',
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
const call = FunctionCall.from({
|
|
619
706
|
name: artifact.name,
|
|
620
|
-
selector: functionSelector,
|
|
621
707
|
to: targetContractAddress,
|
|
622
|
-
|
|
708
|
+
selector: functionSelector,
|
|
709
|
+
type: FunctionType.UTILITY,
|
|
710
|
+
hideMsgSender: false,
|
|
711
|
+
isStatic: false,
|
|
712
|
+
args,
|
|
713
|
+
returnTypes: [],
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
|
|
717
|
+
}
|
|
623
718
|
|
|
624
|
-
|
|
719
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
|
|
720
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
625
721
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
626
722
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
627
723
|
}
|
|
@@ -632,9 +728,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
632
728
|
});
|
|
633
729
|
|
|
634
730
|
try {
|
|
635
|
-
const
|
|
731
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
732
|
+
const oracle = new UtilityExecutionOracle({
|
|
733
|
+
contractAddress: call.to,
|
|
734
|
+
authWitnesses: [],
|
|
735
|
+
capsules: [],
|
|
736
|
+
anchorBlockHeader,
|
|
737
|
+
contractStore: this.contractStore,
|
|
738
|
+
noteStore: this.noteStore,
|
|
739
|
+
keyStore: this.keyStore,
|
|
740
|
+
addressStore: this.addressStore,
|
|
741
|
+
aztecNode: this.stateMachine.node,
|
|
742
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
743
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
744
|
+
capsuleStore: this.capsuleStore,
|
|
745
|
+
privateEventStore: this.privateEventStore,
|
|
746
|
+
jobId,
|
|
747
|
+
scopes,
|
|
748
|
+
});
|
|
636
749
|
const acirExecutionResult = await new WASMSimulator()
|
|
637
|
-
.executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
750
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
638
751
|
.catch((err: Error) => {
|
|
639
752
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
640
753
|
throw new ExecutionError(
|
|
@@ -648,10 +761,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
648
761
|
);
|
|
649
762
|
});
|
|
650
763
|
|
|
651
|
-
this.logger.verbose(`Utility
|
|
764
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
652
765
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
653
766
|
} catch (err) {
|
|
654
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
767
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
655
768
|
}
|
|
656
769
|
}
|
|
657
770
|
|