@aztec/txe 4.0.0-nightly.20250907 → 4.0.0-nightly.20260107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bin/index.d.ts +1 -1
- package/dest/bin/index.js +1 -1
- 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 +8 -4
- package/dest/oracle/interfaces.d.ts +57 -0
- package/dest/oracle/interfaces.d.ts.map +1 -0
- package/dest/oracle/interfaces.js +3 -0
- package/dest/oracle/txe_oracle_public_context.d.ts +12 -12
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +30 -34
- package/dest/oracle/txe_oracle_top_level_context.d.ts +65 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_top_level_context.js +463 -0
- package/dest/rpc_translator.d.ts +246 -0
- package/dest/rpc_translator.d.ts.map +1 -0
- package/dest/{txe_service/txe_service.js → rpc_translator.js} +201 -124
- package/dest/state_machine/archiver.d.ts +34 -13
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +111 -16
- package/dest/state_machine/dummy_p2p_client.d.ts +5 -2
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +9 -1
- package/dest/state_machine/global_variable_builder.d.ts +5 -16
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +15 -22
- package/dest/state_machine/index.d.ts +5 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +17 -21
- package/dest/state_machine/mock_epoch_cache.d.ts +6 -5
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +8 -7
- package/dest/state_machine/synchronizer.d.ts +5 -4
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +5 -4
- package/dest/txe_session.d.ts +42 -46
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +241 -93
- package/dest/util/encoding.d.ts +623 -24
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +1 -1
- package/dest/util/expected_failure_error.d.ts +1 -1
- package/dest/util/expected_failure_error.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_contract_store.d.ts +12 -0
- package/dest/util/txe_contract_store.d.ts.map +1 -0
- package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +4 -4
- package/dest/util/txe_public_contract_data_source.d.ts +8 -6
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +14 -12
- package/dest/utils/block_creation.d.ts +28 -0
- package/dest/utils/block_creation.d.ts.map +1 -0
- package/dest/utils/block_creation.js +45 -0
- package/dest/utils/tx_effect_creation.d.ts +6 -0
- package/dest/utils/tx_effect_creation.d.ts.map +1 -0
- package/dest/utils/tx_effect_creation.js +16 -0
- package/package.json +18 -17
- package/src/bin/index.ts +1 -1
- package/src/constants.ts +3 -0
- package/src/index.ts +20 -20
- package/src/oracle/interfaces.ts +86 -0
- package/src/oracle/txe_oracle_public_context.ts +37 -75
- package/src/oracle/txe_oracle_top_level_context.ts +716 -0
- package/src/{txe_service/txe_service.ts → rpc_translator.ts} +261 -125
- package/src/state_machine/archiver.ts +147 -29
- package/src/state_machine/dummy_p2p_client.ts +13 -2
- package/src/state_machine/global_variable_builder.ts +24 -41
- package/src/state_machine/index.ts +24 -21
- package/src/state_machine/mock_epoch_cache.ts +12 -11
- package/src/state_machine/synchronizer.ts +8 -7
- package/src/txe_session.ts +416 -115
- package/src/util/encoding.ts +1 -1
- package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
- package/src/util/{txe_contract_data_provider.ts → txe_contract_store.ts} +5 -4
- package/src/util/txe_public_contract_data_source.ts +16 -13
- package/src/utils/block_creation.ts +94 -0
- package/src/utils/tx_effect_creation.ts +38 -0
- package/dest/oracle/txe_oracle.d.ts +0 -124
- package/dest/oracle/txe_oracle.d.ts.map +0 -1
- package/dest/oracle/txe_oracle.js +0 -770
- package/dest/oracle/txe_typed_oracle.d.ts +0 -42
- package/dest/oracle/txe_typed_oracle.d.ts.map +0 -1
- package/dest/oracle/txe_typed_oracle.js +0 -83
- package/dest/txe_constants.d.ts +0 -2
- package/dest/txe_constants.d.ts.map +0 -1
- package/dest/txe_constants.js +0 -7
- package/dest/txe_service/txe_service.d.ts +0 -231
- package/dest/txe_service/txe_service.d.ts.map +0 -1
- 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 -11
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/src/oracle/txe_oracle.ts +0 -1287
- package/src/oracle/txe_typed_oracle.ts +0 -142
- package/src/txe_constants.ts +0 -9
|
@@ -1,770 +0,0 @@
|
|
|
1
|
-
import { Body, L2Block, Note } from '@aztec/aztec.js';
|
|
2
|
-
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT, DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PRIVATE_CONTEXT_INPUTS_LENGTH } from '@aztec/constants';
|
|
3
|
-
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
4
|
-
import { Aes128, Schnorr } from '@aztec/foundation/crypto';
|
|
5
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
6
|
-
import { applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
7
|
-
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
8
|
-
import { ORACLE_VERSION, PXEOracleInterface, enrichPublicSimulationError } from '@aztec/pxe/server';
|
|
9
|
-
import { ExecutionNoteCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, executePrivateFunction, generateSimulatedProvingResult, pickNotes } from '@aztec/pxe/simulator';
|
|
10
|
-
import { WASMSimulator, extractCallStack, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
|
|
11
|
-
import { ExecutionError, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, PublicTxSimulator, createSimulationError, resolveAssertionMessageFromError } from '@aztec/simulator/server';
|
|
12
|
-
import { FunctionSelector, FunctionType, countArgumentsSize } from '@aztec/stdlib/abi';
|
|
13
|
-
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
14
|
-
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
15
|
-
import { computePartialAddress } from '@aztec/stdlib/contract';
|
|
16
|
-
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
17
|
-
import { computeCalldataHash, computeNoteHashNonce, computePublicDataTreeLeafSlot, computeUniqueNoteHash, computeVarArgsHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
18
|
-
import { PartialPrivateTailPublicInputsForPublic, PrivateContextInputs, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
|
|
19
|
-
import { ClientIvcProof } from '@aztec/stdlib/proofs';
|
|
20
|
-
import { makeAppendOnlyTreeSnapshot, makeContentCommitment, makeGlobalVariables, makeHeader } from '@aztec/stdlib/testing';
|
|
21
|
-
import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
22
|
-
import { BlockHeader, CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
|
|
23
|
-
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
24
|
-
import { GENESIS_TIMESTAMP } from '../txe_constants.js';
|
|
25
|
-
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
26
|
-
import { TXETypedOracle } from './txe_typed_oracle.js';
|
|
27
|
-
export class TXE extends TXETypedOracle {
|
|
28
|
-
keyStore;
|
|
29
|
-
contractDataProvider;
|
|
30
|
-
noteDataProvider;
|
|
31
|
-
capsuleDataProvider;
|
|
32
|
-
taggingDataProvider;
|
|
33
|
-
addressDataProvider;
|
|
34
|
-
privateEventDataProvider;
|
|
35
|
-
accountDataProvider;
|
|
36
|
-
contractAddress;
|
|
37
|
-
baseFork;
|
|
38
|
-
stateMachine;
|
|
39
|
-
logger;
|
|
40
|
-
blockNumber;
|
|
41
|
-
timestamp;
|
|
42
|
-
sideEffectCounter;
|
|
43
|
-
msgSender;
|
|
44
|
-
functionSelector;
|
|
45
|
-
pxeOracleInterface;
|
|
46
|
-
privateLogs;
|
|
47
|
-
committedBlocks;
|
|
48
|
-
ROLLUP_VERSION;
|
|
49
|
-
CHAIN_ID;
|
|
50
|
-
node;
|
|
51
|
-
simulator;
|
|
52
|
-
noteCache;
|
|
53
|
-
authwits;
|
|
54
|
-
// Used by privateSetSenderForTags and privateGetSenderForTags oracles.
|
|
55
|
-
senderForTags;
|
|
56
|
-
executionCache;
|
|
57
|
-
constructor(keyStore, contractDataProvider, noteDataProvider, capsuleDataProvider, taggingDataProvider, addressDataProvider, privateEventDataProvider, accountDataProvider, contractAddress, baseFork, stateMachine){
|
|
58
|
-
super(), this.keyStore = keyStore, this.contractDataProvider = contractDataProvider, this.noteDataProvider = noteDataProvider, this.capsuleDataProvider = capsuleDataProvider, this.taggingDataProvider = taggingDataProvider, this.addressDataProvider = addressDataProvider, this.privateEventDataProvider = privateEventDataProvider, this.accountDataProvider = accountDataProvider, this.contractAddress = contractAddress, this.baseFork = baseFork, this.stateMachine = stateMachine, this.blockNumber = 1, this.timestamp = GENESIS_TIMESTAMP, this.sideEffectCounter = 0, this.functionSelector = FunctionSelector.fromField(new Fr(0)), this.privateLogs = [], this.committedBlocks = new Set(), this.ROLLUP_VERSION = 1, this.CHAIN_ID = 1, this.simulator = new WASMSimulator(), this.authwits = new Map();
|
|
59
|
-
this.logger = createLogger('txe:oracle');
|
|
60
|
-
this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
|
|
61
|
-
this.node = stateMachine.node;
|
|
62
|
-
// Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
|
|
63
|
-
this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
|
|
64
|
-
this.executionCache = new HashedValuesCache();
|
|
65
|
-
this.pxeOracleInterface = new PXEOracleInterface(this.node, this.keyStore, this.contractDataProvider, this.noteDataProvider, this.capsuleDataProvider, this.stateMachine.syncDataProvider, this.taggingDataProvider, this.addressDataProvider, this.privateEventDataProvider, this.logger);
|
|
66
|
-
}
|
|
67
|
-
// Utils
|
|
68
|
-
utilityGetChainId() {
|
|
69
|
-
return Promise.resolve(new Fr(this.CHAIN_ID));
|
|
70
|
-
}
|
|
71
|
-
utilityGetVersion() {
|
|
72
|
-
return Promise.resolve(new Fr(this.ROLLUP_VERSION));
|
|
73
|
-
}
|
|
74
|
-
getMsgSender() {
|
|
75
|
-
return this.msgSender;
|
|
76
|
-
}
|
|
77
|
-
txeSetContractAddress(contractAddress) {
|
|
78
|
-
this.contractAddress = contractAddress;
|
|
79
|
-
}
|
|
80
|
-
// TODO: Currently this is only ever used to increment this.blockNumber by 1. Refactor this as `advanceBlock()`.
|
|
81
|
-
setBlockNumber(blockNumber) {
|
|
82
|
-
this.blockNumber = blockNumber;
|
|
83
|
-
}
|
|
84
|
-
async txeAdvanceBlocksBy(blocks) {
|
|
85
|
-
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
86
|
-
for(let i = 0; i < blocks; i++){
|
|
87
|
-
const blockNumber = await this.utilityGetBlockNumber();
|
|
88
|
-
await this.commitState();
|
|
89
|
-
this.setBlockNumber(blockNumber + 1);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
txeAdvanceTimestampBy(duration) {
|
|
93
|
-
this.logger.debug(`time traveling ${duration} seconds`);
|
|
94
|
-
this.timestamp = this.timestamp + duration;
|
|
95
|
-
}
|
|
96
|
-
async txeDeploy(artifact, instance, secret) {
|
|
97
|
-
// Emit deployment nullifier
|
|
98
|
-
await this.noteCache.nullifierCreated(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), instance.address.toField());
|
|
99
|
-
// Make sure the deployment nullifier gets included in a tx in a block
|
|
100
|
-
const blockNumber = await this.utilityGetBlockNumber();
|
|
101
|
-
await this.commitState();
|
|
102
|
-
this.setBlockNumber(blockNumber + 1);
|
|
103
|
-
if (!secret.equals(Fr.ZERO)) {
|
|
104
|
-
await this.txeAddAccount(artifact, instance, secret);
|
|
105
|
-
} else {
|
|
106
|
-
await this.addContractInstance(instance);
|
|
107
|
-
await this.addContractArtifact(instance.currentContractClassId, artifact);
|
|
108
|
-
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
async txeAddAccount(artifact, instance, secret) {
|
|
112
|
-
const partialAddress = await computePartialAddress(instance);
|
|
113
|
-
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
114
|
-
await this.addContractInstance(instance);
|
|
115
|
-
await this.addContractArtifact(instance.currentContractClassId, artifact);
|
|
116
|
-
const keyStore = this.getKeyStore();
|
|
117
|
-
const completeAddress = await keyStore.addAccount(secret, partialAddress);
|
|
118
|
-
const accountDataProvider = this.getAccountDataProvider();
|
|
119
|
-
await accountDataProvider.setAccount(completeAddress.address, completeAddress);
|
|
120
|
-
const addressDataProvider = this.getAddressDataProvider();
|
|
121
|
-
await addressDataProvider.addCompleteAddress(completeAddress);
|
|
122
|
-
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
123
|
-
return completeAddress;
|
|
124
|
-
}
|
|
125
|
-
async txeCreateAccount(secret) {
|
|
126
|
-
const keyStore = this.getKeyStore();
|
|
127
|
-
// This is a footgun !
|
|
128
|
-
const completeAddress = await keyStore.addAccount(secret, secret);
|
|
129
|
-
const accountDataProvider = this.getAccountDataProvider();
|
|
130
|
-
await accountDataProvider.setAccount(completeAddress.address, completeAddress);
|
|
131
|
-
const addressDataProvider = this.getAddressDataProvider();
|
|
132
|
-
await addressDataProvider.addCompleteAddress(completeAddress);
|
|
133
|
-
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
134
|
-
return completeAddress;
|
|
135
|
-
}
|
|
136
|
-
getContractDataProvider() {
|
|
137
|
-
return this.contractDataProvider;
|
|
138
|
-
}
|
|
139
|
-
getKeyStore() {
|
|
140
|
-
return this.keyStore;
|
|
141
|
-
}
|
|
142
|
-
getAccountDataProvider() {
|
|
143
|
-
return this.accountDataProvider;
|
|
144
|
-
}
|
|
145
|
-
getAddressDataProvider() {
|
|
146
|
-
return this.addressDataProvider;
|
|
147
|
-
}
|
|
148
|
-
async addContractInstance(contractInstance) {
|
|
149
|
-
await this.contractDataProvider.addContractInstance(contractInstance);
|
|
150
|
-
}
|
|
151
|
-
async addContractArtifact(contractClassId, artifact) {
|
|
152
|
-
await this.contractDataProvider.addContractArtifact(contractClassId, artifact);
|
|
153
|
-
}
|
|
154
|
-
async txeGetPrivateContextInputs(blockNumber, sideEffectsCounter = this.sideEffectCounter, isStaticCall = false) {
|
|
155
|
-
// If blockNumber or timestamp is null, use the values corresponding to the latest historical block (number of
|
|
156
|
-
// the block being built - 1)
|
|
157
|
-
blockNumber = blockNumber ?? this.blockNumber - 1;
|
|
158
|
-
const snap = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber);
|
|
159
|
-
const previousBlockState = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber - 1);
|
|
160
|
-
const stateReference = await snap.getStateReference();
|
|
161
|
-
const inputs = PrivateContextInputs.empty();
|
|
162
|
-
inputs.txContext.chainId = new Fr(this.CHAIN_ID);
|
|
163
|
-
inputs.txContext.version = new Fr(this.ROLLUP_VERSION);
|
|
164
|
-
inputs.historicalHeader.globalVariables.blockNumber = blockNumber;
|
|
165
|
-
inputs.historicalHeader.globalVariables.timestamp = await this.getBlockTimestamp(blockNumber);
|
|
166
|
-
inputs.historicalHeader.state = stateReference;
|
|
167
|
-
inputs.historicalHeader.lastArchive.root = Fr.fromBuffer((await previousBlockState.getTreeInfo(MerkleTreeId.ARCHIVE)).root);
|
|
168
|
-
inputs.callContext = new CallContext(this.msgSender, this.contractAddress, this.functionSelector, isStaticCall);
|
|
169
|
-
inputs.startSideEffectCounter = sideEffectsCounter;
|
|
170
|
-
this.logger.info(`Created private context for block ${blockNumber}`);
|
|
171
|
-
return inputs;
|
|
172
|
-
}
|
|
173
|
-
async txeAddAuthWitness(address, messageHash) {
|
|
174
|
-
const account = await this.accountDataProvider.getAccount(address);
|
|
175
|
-
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
176
|
-
const schnorr = new Schnorr();
|
|
177
|
-
const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
|
|
178
|
-
const authWitness = new AuthWitness(messageHash, [
|
|
179
|
-
...signature.toBuffer()
|
|
180
|
-
]);
|
|
181
|
-
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
182
|
-
}
|
|
183
|
-
async checkNullifiersNotInTree(contractAddress, nullifiers) {
|
|
184
|
-
const siloedNullifiers = await Promise.all(nullifiers.map((nullifier)=>siloNullifier(contractAddress, nullifier)));
|
|
185
|
-
const db = this.baseFork;
|
|
186
|
-
const nullifierIndexesInTree = await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers.map((n)=>n.toBuffer()));
|
|
187
|
-
if (nullifierIndexesInTree.some((index)=>index !== undefined)) {
|
|
188
|
-
throw new Error(`Rejecting tx for emitting duplicate nullifiers`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// TypedOracle
|
|
192
|
-
utilityAssertCompatibleOracleVersion(version) {
|
|
193
|
-
if (version !== ORACLE_VERSION) {
|
|
194
|
-
throw new Error(`Incompatible oracle version. PXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
utilityGetBlockNumber() {
|
|
198
|
-
return Promise.resolve(this.blockNumber);
|
|
199
|
-
}
|
|
200
|
-
utilityGetTimestamp() {
|
|
201
|
-
return Promise.resolve(this.timestamp);
|
|
202
|
-
}
|
|
203
|
-
txeGetLastBlockTimestamp() {
|
|
204
|
-
return this.getBlockTimestamp(this.blockNumber - 1);
|
|
205
|
-
}
|
|
206
|
-
utilityGetContractAddress() {
|
|
207
|
-
return Promise.resolve(this.contractAddress);
|
|
208
|
-
}
|
|
209
|
-
utilityGetRandomField() {
|
|
210
|
-
return Fr.random();
|
|
211
|
-
}
|
|
212
|
-
privateStoreInExecutionCache(values, hash) {
|
|
213
|
-
return this.executionCache.store(values, hash);
|
|
214
|
-
}
|
|
215
|
-
privateLoadFromExecutionCache(hash) {
|
|
216
|
-
const preimage = this.executionCache.getPreimage(hash);
|
|
217
|
-
if (!preimage) {
|
|
218
|
-
throw new Error(`Preimage for hash ${hash.toString()} not found in cache`);
|
|
219
|
-
}
|
|
220
|
-
return Promise.resolve(preimage);
|
|
221
|
-
}
|
|
222
|
-
utilityGetKeyValidationRequest(pkMHash) {
|
|
223
|
-
return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
|
|
224
|
-
}
|
|
225
|
-
utilityGetContractInstance(address) {
|
|
226
|
-
return this.pxeOracleInterface.getContractInstance(address);
|
|
227
|
-
}
|
|
228
|
-
utilityGetMembershipWitness(blockNumber, treeId, leafValue) {
|
|
229
|
-
return this.pxeOracleInterface.getMembershipWitness(blockNumber, treeId, leafValue);
|
|
230
|
-
}
|
|
231
|
-
utilityGetNullifierMembershipWitness(blockNumber, nullifier) {
|
|
232
|
-
return this.pxeOracleInterface.getNullifierMembershipWitness(blockNumber, nullifier);
|
|
233
|
-
}
|
|
234
|
-
utilityGetPublicDataWitness(blockNumber, leafSlot) {
|
|
235
|
-
return this.pxeOracleInterface.getPublicDataWitness(blockNumber, leafSlot);
|
|
236
|
-
}
|
|
237
|
-
utilityGetLowNullifierMembershipWitness(blockNumber, nullifier) {
|
|
238
|
-
return this.pxeOracleInterface.getLowNullifierMembershipWitness(blockNumber, nullifier);
|
|
239
|
-
}
|
|
240
|
-
utilityGetBlockHeader(blockNumber) {
|
|
241
|
-
return this.stateMachine.archiver.getBlockHeader(blockNumber);
|
|
242
|
-
}
|
|
243
|
-
utilityGetCompleteAddress(account) {
|
|
244
|
-
return Promise.resolve(this.accountDataProvider.getAccount(account));
|
|
245
|
-
}
|
|
246
|
-
utilityGetAuthWitness(messageHash) {
|
|
247
|
-
const authwit = this.authwits.get(messageHash.toString());
|
|
248
|
-
return Promise.resolve(authwit?.witness);
|
|
249
|
-
}
|
|
250
|
-
async utilityGetNotes(storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status) {
|
|
251
|
-
// Nullified pending notes are already removed from the list.
|
|
252
|
-
const pendingNotes = this.noteCache.getNotes(this.contractAddress, storageSlot);
|
|
253
|
-
const pendingNullifiers = this.noteCache.getNullifiers(this.contractAddress);
|
|
254
|
-
const dbNotes = await this.pxeOracleInterface.getNotes(this.contractAddress, storageSlot, status);
|
|
255
|
-
const dbNotesFiltered = dbNotes.filter((n)=>!pendingNullifiers.has(n.siloedNullifier.value));
|
|
256
|
-
const notes = pickNotes([
|
|
257
|
-
...dbNotesFiltered,
|
|
258
|
-
...pendingNotes
|
|
259
|
-
], {
|
|
260
|
-
selects: selectByIndexes.slice(0, numSelects).map((index, i)=>({
|
|
261
|
-
selector: {
|
|
262
|
-
index,
|
|
263
|
-
offset: selectByOffsets[i],
|
|
264
|
-
length: selectByLengths[i]
|
|
265
|
-
},
|
|
266
|
-
value: selectValues[i],
|
|
267
|
-
comparator: selectComparators[i]
|
|
268
|
-
})),
|
|
269
|
-
sorts: sortByIndexes.map((index, i)=>({
|
|
270
|
-
selector: {
|
|
271
|
-
index,
|
|
272
|
-
offset: sortByOffsets[i],
|
|
273
|
-
length: sortByLengths[i]
|
|
274
|
-
},
|
|
275
|
-
order: sortOrder[i]
|
|
276
|
-
})),
|
|
277
|
-
limit,
|
|
278
|
-
offset
|
|
279
|
-
});
|
|
280
|
-
this.logger.debug(`Returning ${notes.length} notes for ${this.contractAddress} at ${storageSlot}: ${notes.map((n)=>`${n.noteNonce.toString()}:[${n.note.items.map((i)=>i.toString()).join(',')}]`).join(', ')}`);
|
|
281
|
-
if (notes.length > 0) {
|
|
282
|
-
const noteLength = notes[0].note.items.length;
|
|
283
|
-
if (!notes.every(({ note })=>noteLength === note.items.length)) {
|
|
284
|
-
throw new Error('Notes should all be the same length.');
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return notes;
|
|
288
|
-
}
|
|
289
|
-
privateNotifyCreatedNote(storageSlot, _noteTypeId, noteItems, noteHash, counter) {
|
|
290
|
-
const note = new Note(noteItems);
|
|
291
|
-
this.noteCache.addNewNote({
|
|
292
|
-
contractAddress: this.contractAddress,
|
|
293
|
-
storageSlot,
|
|
294
|
-
noteNonce: Fr.ZERO,
|
|
295
|
-
note,
|
|
296
|
-
siloedNullifier: undefined,
|
|
297
|
-
noteHash
|
|
298
|
-
}, counter);
|
|
299
|
-
this.sideEffectCounter = counter + 1;
|
|
300
|
-
}
|
|
301
|
-
async privateNotifyNullifiedNote(innerNullifier, noteHash, counter) {
|
|
302
|
-
await this.checkNullifiersNotInTree(this.contractAddress, [
|
|
303
|
-
innerNullifier
|
|
304
|
-
]);
|
|
305
|
-
await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
306
|
-
this.sideEffectCounter = counter + 1;
|
|
307
|
-
}
|
|
308
|
-
async privateNotifyCreatedNullifier(innerNullifier) {
|
|
309
|
-
await this.checkNullifiersNotInTree(this.contractAddress, [
|
|
310
|
-
innerNullifier
|
|
311
|
-
]);
|
|
312
|
-
await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
|
|
313
|
-
}
|
|
314
|
-
async utilityCheckNullifierExists(innerNullifier) {
|
|
315
|
-
const snap = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
|
|
316
|
-
const nullifier = await siloNullifier(this.contractAddress, innerNullifier);
|
|
317
|
-
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [
|
|
318
|
-
nullifier.toBuffer()
|
|
319
|
-
]);
|
|
320
|
-
const inPendingCache = this.noteCache.getNullifiers(this.contractAddress).has(nullifier.toBigInt());
|
|
321
|
-
return index !== undefined || inPendingCache;
|
|
322
|
-
}
|
|
323
|
-
getL1ToL2MembershipWitness(_contractAddress, _messageHash, _secret) {
|
|
324
|
-
throw new Error('Method not implemented.');
|
|
325
|
-
}
|
|
326
|
-
async utilityStorageRead(contractAddress, startStorageSlot, blockNumber, numberOfElements) {
|
|
327
|
-
let db;
|
|
328
|
-
if (blockNumber === this.blockNumber) {
|
|
329
|
-
db = this.baseFork;
|
|
330
|
-
} else {
|
|
331
|
-
db = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber);
|
|
332
|
-
}
|
|
333
|
-
const values = [];
|
|
334
|
-
for(let i = 0n; i < numberOfElements; i++){
|
|
335
|
-
const storageSlot = startStorageSlot.add(new Fr(i));
|
|
336
|
-
const leafSlot = (await computePublicDataTreeLeafSlot(contractAddress, storageSlot)).toBigInt();
|
|
337
|
-
const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
|
|
338
|
-
let value = Fr.ZERO;
|
|
339
|
-
if (lowLeafResult && lowLeafResult.alreadyPresent) {
|
|
340
|
-
const preimage = await db.getLeafPreimage(MerkleTreeId.PUBLIC_DATA_TREE, lowLeafResult.index);
|
|
341
|
-
value = preimage.leaf.value;
|
|
342
|
-
}
|
|
343
|
-
this.logger.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
|
|
344
|
-
values.push(value);
|
|
345
|
-
}
|
|
346
|
-
return values;
|
|
347
|
-
}
|
|
348
|
-
async commitState() {
|
|
349
|
-
const blockNumber = await this.utilityGetBlockNumber();
|
|
350
|
-
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
351
|
-
if (this.committedBlocks.has(blockNumber)) {
|
|
352
|
-
throw new Error('Already committed state');
|
|
353
|
-
} else {
|
|
354
|
-
this.committedBlocks.add(blockNumber);
|
|
355
|
-
}
|
|
356
|
-
const fork = this.baseFork;
|
|
357
|
-
const txEffect = TxEffect.empty();
|
|
358
|
-
const nonceGenerator = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
359
|
-
let i = 0;
|
|
360
|
-
const uniqueNoteHashesFromPrivate = await Promise.all(this.noteCache.getAllNotes().map(async (pendingNote)=>computeUniqueNoteHash(await computeNoteHashNonce(nonceGenerator, i++), await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption))));
|
|
361
|
-
txEffect.noteHashes = uniqueNoteHashesFromPrivate;
|
|
362
|
-
txEffect.nullifiers = this.noteCache.getAllNullifiers();
|
|
363
|
-
if (usedTxRequestHashForNonces) {
|
|
364
|
-
txEffect.nullifiers.unshift(this.getTxRequestHash());
|
|
365
|
-
}
|
|
366
|
-
txEffect.privateLogs = this.privateLogs;
|
|
367
|
-
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
368
|
-
const body = new Body([
|
|
369
|
-
txEffect
|
|
370
|
-
]);
|
|
371
|
-
const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(blockNumber + 1), makeHeader(0, blockNumber, blockNumber), body);
|
|
372
|
-
const paddedTxEffects = l2Block.body.txEffects;
|
|
373
|
-
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
374
|
-
{
|
|
375
|
-
const noteHashesPadded = paddedTxEffects.flatMap((txEffect)=>padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX));
|
|
376
|
-
await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
|
|
377
|
-
await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
378
|
-
}
|
|
379
|
-
{
|
|
380
|
-
for (const txEffect of paddedTxEffects){
|
|
381
|
-
// We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
|
|
382
|
-
// the batchInsert was not working when updating a previously updated slot.
|
|
383
|
-
// FIXME: public data writes, note hashes, nullifiers, messages should all be handled in the same way.
|
|
384
|
-
// They are all relevant to subsequent enqueued calls and txs.
|
|
385
|
-
const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
|
|
386
|
-
await fork.batchInsert(MerkleTreeId.NULLIFIER_TREE, nullifiersPadded.map((nullifier)=>nullifier.toBuffer()), NULLIFIER_SUBTREE_HEIGHT);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
const stateReference = await fork.getStateReference();
|
|
390
|
-
const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
391
|
-
const header = new BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, makeGlobalVariables(), Fr.ZERO, Fr.ZERO);
|
|
392
|
-
header.globalVariables.blockNumber = blockNumber;
|
|
393
|
-
header.globalVariables.timestamp = await this.utilityGetTimestamp();
|
|
394
|
-
header.globalVariables.version = new Fr(this.ROLLUP_VERSION);
|
|
395
|
-
header.globalVariables.chainId = new Fr(this.CHAIN_ID);
|
|
396
|
-
this.logger.info(`Created block ${blockNumber} with timestamp ${header.globalVariables.timestamp}`);
|
|
397
|
-
l2Block.header = header;
|
|
398
|
-
await fork.updateArchive(l2Block.header);
|
|
399
|
-
await this.stateMachine.handleL2Block(l2Block);
|
|
400
|
-
this.privateLogs = [];
|
|
401
|
-
this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
|
|
402
|
-
}
|
|
403
|
-
getTxRequestHash() {
|
|
404
|
-
// Using block number itself is invalid since indexed trees come prefilled with the first slots.
|
|
405
|
-
return new Fr(this.blockNumber + 6969);
|
|
406
|
-
}
|
|
407
|
-
notifyCreatedContractClassLog(_log, _counter) {
|
|
408
|
-
throw new Error('Method not implemented.');
|
|
409
|
-
}
|
|
410
|
-
async simulateUtilityFunction(targetContractAddress, functionSelector, argsHash) {
|
|
411
|
-
const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
412
|
-
if (!artifact) {
|
|
413
|
-
throw new Error(`Cannot call ${functionSelector} as there is artifact found at ${targetContractAddress}.`);
|
|
414
|
-
}
|
|
415
|
-
const call = {
|
|
416
|
-
name: artifact.name,
|
|
417
|
-
selector: functionSelector,
|
|
418
|
-
to: targetContractAddress
|
|
419
|
-
};
|
|
420
|
-
const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
|
|
421
|
-
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
422
|
-
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
423
|
-
}
|
|
424
|
-
const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface, undefined, undefined);
|
|
425
|
-
try {
|
|
426
|
-
this.logger.verbose(`Executing utility function ${entryPointArtifact.name}`, {
|
|
427
|
-
contract: call.to,
|
|
428
|
-
selector: call.selector
|
|
429
|
-
});
|
|
430
|
-
const args = await this.privateLoadFromExecutionCache(argsHash);
|
|
431
|
-
const initialWitness = toACVMWitness(0, args);
|
|
432
|
-
const acirExecutionResult = await this.simulator.executeUserCircuit(initialWitness, entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
|
|
433
|
-
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
434
|
-
throw new ExecutionError(err.message, {
|
|
435
|
-
contractAddress: call.to,
|
|
436
|
-
functionSelector: call.selector
|
|
437
|
-
}, extractCallStack(err, entryPointArtifact.debug), {
|
|
438
|
-
cause: err
|
|
439
|
-
});
|
|
440
|
-
});
|
|
441
|
-
const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness);
|
|
442
|
-
this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
|
|
443
|
-
const returnHash = await computeVarArgsHash(returnWitness);
|
|
444
|
-
this.privateStoreInExecutionCache(returnWitness, returnHash);
|
|
445
|
-
return returnHash;
|
|
446
|
-
} catch (err) {
|
|
447
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
async getInitialWitness(abi, argsHash, sideEffectCounter, isStaticCall) {
|
|
451
|
-
const argumentsSize = countArgumentsSize(abi);
|
|
452
|
-
const args = this.executionCache.getPreimage(argsHash);
|
|
453
|
-
if (args?.length !== argumentsSize) {
|
|
454
|
-
throw new Error('Invalid arguments size');
|
|
455
|
-
}
|
|
456
|
-
const historicalBlockNumber = this.blockNumber - 1; // i.e. last
|
|
457
|
-
const privateContextInputs = await this.txeGetPrivateContextInputs(historicalBlockNumber, sideEffectCounter, isStaticCall);
|
|
458
|
-
const privateContextInputsAsFields = privateContextInputs.toFields();
|
|
459
|
-
if (privateContextInputsAsFields.length !== PRIVATE_CONTEXT_INPUTS_LENGTH) {
|
|
460
|
-
throw new Error('Invalid private context inputs size');
|
|
461
|
-
}
|
|
462
|
-
const fields = [
|
|
463
|
-
...privateContextInputsAsFields,
|
|
464
|
-
...args
|
|
465
|
-
];
|
|
466
|
-
return toACVMWitness(0, fields);
|
|
467
|
-
}
|
|
468
|
-
async getDebugFunctionName(address, selector) {
|
|
469
|
-
return await this.contractDataProvider.getDebugFunctionName(address, selector);
|
|
470
|
-
}
|
|
471
|
-
utilityDebugLog(message, fields) {
|
|
472
|
-
this.logger.verbose(`${applyStringFormatting(message, fields)}`, {
|
|
473
|
-
module: `${this.logger.module}:debug_log`
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
async privateIncrementAppTaggingSecretIndexAsSender(sender, recipient) {
|
|
477
|
-
await this.pxeOracleInterface.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
|
|
478
|
-
}
|
|
479
|
-
async utilityGetIndexedTaggingSecretAsSender(sender, recipient) {
|
|
480
|
-
return await this.pxeOracleInterface.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
|
|
481
|
-
}
|
|
482
|
-
async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot) {
|
|
483
|
-
await this.pxeOracleInterface.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot);
|
|
484
|
-
await this.pxeOracleInterface.removeNullifiedNotes(this.contractAddress);
|
|
485
|
-
return Promise.resolve();
|
|
486
|
-
}
|
|
487
|
-
async utilityValidateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot) {
|
|
488
|
-
await this.pxeOracleInterface.validateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot);
|
|
489
|
-
}
|
|
490
|
-
async utilityBulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot) {
|
|
491
|
-
return await this.pxeOracleInterface.bulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot);
|
|
492
|
-
}
|
|
493
|
-
utilityStoreCapsule(contractAddress, slot, capsule) {
|
|
494
|
-
if (!contractAddress.equals(this.contractAddress)) {
|
|
495
|
-
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
496
|
-
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
497
|
-
}
|
|
498
|
-
return this.pxeOracleInterface.storeCapsule(this.contractAddress, slot, capsule);
|
|
499
|
-
}
|
|
500
|
-
utilityLoadCapsule(contractAddress, slot) {
|
|
501
|
-
if (!contractAddress.equals(this.contractAddress)) {
|
|
502
|
-
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
503
|
-
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
504
|
-
}
|
|
505
|
-
return this.pxeOracleInterface.loadCapsule(this.contractAddress, slot);
|
|
506
|
-
}
|
|
507
|
-
utilityDeleteCapsule(contractAddress, slot) {
|
|
508
|
-
if (!contractAddress.equals(this.contractAddress)) {
|
|
509
|
-
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
510
|
-
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
511
|
-
}
|
|
512
|
-
return this.pxeOracleInterface.deleteCapsule(this.contractAddress, slot);
|
|
513
|
-
}
|
|
514
|
-
utilityCopyCapsule(contractAddress, srcSlot, dstSlot, numEntries) {
|
|
515
|
-
if (!contractAddress.equals(this.contractAddress)) {
|
|
516
|
-
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
517
|
-
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
518
|
-
}
|
|
519
|
-
return this.pxeOracleInterface.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
|
|
520
|
-
}
|
|
521
|
-
utilityAes128Decrypt(ciphertext, iv, symKey) {
|
|
522
|
-
const aes128 = new Aes128();
|
|
523
|
-
return aes128.decryptBufferCBC(ciphertext, iv, symKey);
|
|
524
|
-
}
|
|
525
|
-
utilityGetSharedSecret(address, ephPk) {
|
|
526
|
-
return this.pxeOracleInterface.getSharedSecret(address, ephPk);
|
|
527
|
-
}
|
|
528
|
-
privateGetSenderForTags() {
|
|
529
|
-
return Promise.resolve(this.senderForTags);
|
|
530
|
-
}
|
|
531
|
-
privateSetSenderForTags(senderForTags) {
|
|
532
|
-
this.senderForTags = senderForTags;
|
|
533
|
-
return Promise.resolve();
|
|
534
|
-
}
|
|
535
|
-
async txePrivateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false) {
|
|
536
|
-
this.logger.verbose(`Executing external function ${await this.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
537
|
-
const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
538
|
-
if (artifact === undefined) {
|
|
539
|
-
if (functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))) {
|
|
540
|
-
throw new Error('Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.');
|
|
541
|
-
} else {
|
|
542
|
-
throw new Error('Function Artifact does not exist');
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
546
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
547
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
548
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
549
|
-
const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
|
|
550
|
-
const blockHeader = await this.pxeOracleInterface.getBlockHeader();
|
|
551
|
-
const noteCache = new ExecutionNoteCache(this.getTxRequestHash());
|
|
552
|
-
const privateExecutionOracle = new PrivateExecutionOracle(argsHash, txContext, callContext, /** Header of a block whose state is used during private execution (not the block the transaction is included in). */ blockHeader, /** List of transient auth witnesses to be used during this simulation */ Array.from(this.authwits.values()), /** List of transient auth witnesses to be used during this simulation */ [], HashedValuesCache.create(), noteCache, this.pxeOracleInterface, this.simulator, 0, 1, undefined, undefined, /**
|
|
553
|
-
* In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
554
|
-
* contract would perform, including setting senderForTags.
|
|
555
|
-
*/ from);
|
|
556
|
-
privateExecutionOracle.privateStoreInExecutionCache(args, argsHash);
|
|
557
|
-
// 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.
|
|
558
|
-
let result;
|
|
559
|
-
let executionResult;
|
|
560
|
-
try {
|
|
561
|
-
executionResult = await executePrivateFunction(this.simulator, privateExecutionOracle, artifact, targetContractAddress, functionSelector);
|
|
562
|
-
const { usedTxRequestHashForNonces } = noteCache.finish();
|
|
563
|
-
const firstNullifierHint = usedTxRequestHashForNonces ? Fr.ZERO : noteCache.getAllNullifiers()[0];
|
|
564
|
-
const publicCallRequests = collectNested([
|
|
565
|
-
executionResult
|
|
566
|
-
], (r)=>r.publicInputs.publicCallRequests.getActiveItems().map((r)=>r.inner).concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [
|
|
567
|
-
r.publicInputs.publicTeardownCallRequest
|
|
568
|
-
]));
|
|
569
|
-
const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
|
|
570
|
-
const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
|
|
571
|
-
return new HashedValues(calldata, r.calldataHash);
|
|
572
|
-
}));
|
|
573
|
-
result = new PrivateExecutionResult(executionResult, firstNullifierHint, publicFunctionsCalldata);
|
|
574
|
-
} catch (err) {
|
|
575
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
576
|
-
}
|
|
577
|
-
if (executionResult.returnValues !== undefined) {
|
|
578
|
-
const { returnValues } = executionResult;
|
|
579
|
-
// This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
|
|
580
|
-
// Investigate whether it is faster to do this or return from the oracle directly.
|
|
581
|
-
const returnValuesHash = await computeVarArgsHash(returnValues);
|
|
582
|
-
this.privateStoreInExecutionCache(returnValues, returnValuesHash);
|
|
583
|
-
}
|
|
584
|
-
// According to the protocol rules, the nonce generator for the note hashes
|
|
585
|
-
// can either be the first nullifier in the tx or the hash of the initial tx request
|
|
586
|
-
// if there are none.
|
|
587
|
-
const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? this.getTxRequestHash() : result.firstNullifier;
|
|
588
|
-
const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
|
|
589
|
-
const globals = makeGlobalVariables();
|
|
590
|
-
globals.blockNumber = this.blockNumber;
|
|
591
|
-
globals.timestamp = this.timestamp;
|
|
592
|
-
globals.chainId = new Fr(this.CHAIN_ID);
|
|
593
|
-
globals.version = new Fr(this.ROLLUP_VERSION);
|
|
594
|
-
globals.gasFees = GasFees.empty();
|
|
595
|
-
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
|
|
596
|
-
const guardedMerkleTrees = new GuardedMerkleTreeOperations(this.baseFork);
|
|
597
|
-
const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
|
|
598
|
-
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
|
|
599
|
-
const tx = await Tx.create({
|
|
600
|
-
data: publicInputs,
|
|
601
|
-
clientIvcProof: ClientIvcProof.empty(),
|
|
602
|
-
contractClassLogFields: [],
|
|
603
|
-
publicFunctionCalldata: result.publicFunctionCalldata
|
|
604
|
-
});
|
|
605
|
-
let checkpoint;
|
|
606
|
-
if (isStaticCall) {
|
|
607
|
-
checkpoint = await ForkCheckpoint.new(this.baseFork);
|
|
608
|
-
}
|
|
609
|
-
const results = await processor.process([
|
|
610
|
-
tx
|
|
611
|
-
]);
|
|
612
|
-
const [processedTx] = results[0];
|
|
613
|
-
const failedTxs = results[1];
|
|
614
|
-
if (failedTxs.length !== 0) {
|
|
615
|
-
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
616
|
-
} else if (!processedTx.revertCode.isOK()) {
|
|
617
|
-
if (processedTx.revertReason) {
|
|
618
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
|
|
619
|
-
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
620
|
-
} else {
|
|
621
|
-
throw new Error('Contract execution has reverted');
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
if (isStaticCall) {
|
|
625
|
-
await checkpoint.revert();
|
|
626
|
-
return {
|
|
627
|
-
endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
|
|
628
|
-
returnsHash: result.entrypoint.publicInputs.returnsHash,
|
|
629
|
-
txHash: tx.getTxHash()
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
const fork = this.baseFork;
|
|
633
|
-
const txEffect = TxEffect.empty();
|
|
634
|
-
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
635
|
-
txEffect.nullifiers = processedTx.txEffect.nullifiers;
|
|
636
|
-
txEffect.privateLogs = processedTx.txEffect.privateLogs;
|
|
637
|
-
txEffect.publicLogs = processedTx.txEffect.publicLogs;
|
|
638
|
-
txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
|
|
639
|
-
txEffect.txHash = new TxHash(new Fr(this.blockNumber));
|
|
640
|
-
const body = new Body([
|
|
641
|
-
txEffect
|
|
642
|
-
]);
|
|
643
|
-
const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(this.blockNumber + 1), makeHeader(0, this.blockNumber, this.blockNumber), body);
|
|
644
|
-
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
645
|
-
await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
646
|
-
const stateReference = await fork.getStateReference();
|
|
647
|
-
const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
648
|
-
const header = new BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, globals, Fr.ZERO, Fr.ZERO);
|
|
649
|
-
header.globalVariables.blockNumber = this.blockNumber;
|
|
650
|
-
l2Block.header = header;
|
|
651
|
-
await fork.updateArchive(l2Block.header);
|
|
652
|
-
await this.stateMachine.handleL2Block(l2Block);
|
|
653
|
-
this.setBlockNumber(this.blockNumber + 1);
|
|
654
|
-
return {
|
|
655
|
-
endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
|
|
656
|
-
returnsHash: result.entrypoint.publicInputs.returnsHash,
|
|
657
|
-
txHash: tx.getTxHash()
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
async txePublicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
|
|
661
|
-
this.logger.verbose(`Executing public function ${await this.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
662
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
663
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
664
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
665
|
-
const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
|
|
666
|
-
const blockHeader = await this.pxeOracleInterface.getBlockHeader();
|
|
667
|
-
const calldataHash = await computeCalldataHash(calldata);
|
|
668
|
-
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
669
|
-
const globals = makeGlobalVariables();
|
|
670
|
-
globals.blockNumber = this.blockNumber;
|
|
671
|
-
globals.timestamp = this.timestamp;
|
|
672
|
-
globals.chainId = new Fr(this.CHAIN_ID);
|
|
673
|
-
globals.version = new Fr(this.ROLLUP_VERSION);
|
|
674
|
-
globals.gasFees = GasFees.empty();
|
|
675
|
-
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
|
|
676
|
-
const guardedMerkleTrees = new GuardedMerkleTreeOperations(this.baseFork);
|
|
677
|
-
const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
|
|
678
|
-
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
|
|
679
|
-
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
680
|
-
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
681
|
-
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
682
|
-
// unique.
|
|
683
|
-
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
684
|
-
if (!isStaticCall) {
|
|
685
|
-
nonRevertibleAccumulatedData.nullifiers[0] = this.getTxRequestHash();
|
|
686
|
-
}
|
|
687
|
-
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
688
|
-
// may require producing reverts.
|
|
689
|
-
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
690
|
-
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
|
|
691
|
-
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
|
|
692
|
-
const constantData = new TxConstantData(blockHeader, txContext, Fr.zero(), Fr.zero());
|
|
693
|
-
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*includeByTimestamp=*/ 0n, inputsForPublic, undefined);
|
|
694
|
-
const tx = await Tx.create({
|
|
695
|
-
data: txData,
|
|
696
|
-
clientIvcProof: ClientIvcProof.empty(),
|
|
697
|
-
contractClassLogFields: [],
|
|
698
|
-
publicFunctionCalldata: [
|
|
699
|
-
calldataHashedValues
|
|
700
|
-
]
|
|
701
|
-
});
|
|
702
|
-
let checkpoint;
|
|
703
|
-
if (isStaticCall) {
|
|
704
|
-
checkpoint = await ForkCheckpoint.new(this.baseFork);
|
|
705
|
-
}
|
|
706
|
-
const results = await processor.process([
|
|
707
|
-
tx
|
|
708
|
-
]);
|
|
709
|
-
const [processedTx] = results[0];
|
|
710
|
-
const failedTxs = results[1];
|
|
711
|
-
if (failedTxs.length !== 0) {
|
|
712
|
-
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
713
|
-
} else if (!processedTx.revertCode.isOK()) {
|
|
714
|
-
if (processedTx.revertReason) {
|
|
715
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
|
|
716
|
-
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
717
|
-
} else {
|
|
718
|
-
throw new Error('Contract execution has reverted');
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
const returnValues = results[3][0].values;
|
|
722
|
-
let returnValuesHash;
|
|
723
|
-
if (returnValues !== undefined) {
|
|
724
|
-
// This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
|
|
725
|
-
// Investigate whether it is faster to do this or return from the oracle directly.
|
|
726
|
-
returnValuesHash = await computeVarArgsHash(returnValues);
|
|
727
|
-
this.privateStoreInExecutionCache(returnValues, returnValuesHash);
|
|
728
|
-
}
|
|
729
|
-
if (isStaticCall) {
|
|
730
|
-
await checkpoint.revert();
|
|
731
|
-
return {
|
|
732
|
-
returnsHash: returnValuesHash ?? Fr.ZERO,
|
|
733
|
-
txHash: tx.getTxHash()
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
const fork = this.baseFork;
|
|
737
|
-
const txEffect = TxEffect.empty();
|
|
738
|
-
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
739
|
-
txEffect.nullifiers = processedTx.txEffect.nullifiers;
|
|
740
|
-
txEffect.privateLogs = processedTx.txEffect.privateLogs;
|
|
741
|
-
txEffect.publicLogs = processedTx.txEffect.publicLogs;
|
|
742
|
-
txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
|
|
743
|
-
txEffect.txHash = new TxHash(new Fr(this.blockNumber));
|
|
744
|
-
const body = new Body([
|
|
745
|
-
txEffect
|
|
746
|
-
]);
|
|
747
|
-
const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(this.blockNumber + 1), makeHeader(0, this.blockNumber, this.blockNumber), body);
|
|
748
|
-
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
749
|
-
await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
750
|
-
const stateReference = await fork.getStateReference();
|
|
751
|
-
const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
752
|
-
const header = new BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, globals, Fr.ZERO, Fr.ZERO);
|
|
753
|
-
header.globalVariables.blockNumber = this.blockNumber;
|
|
754
|
-
l2Block.header = header;
|
|
755
|
-
await fork.updateArchive(l2Block.header);
|
|
756
|
-
await this.stateMachine.handleL2Block(l2Block);
|
|
757
|
-
this.setBlockNumber(this.blockNumber + 1);
|
|
758
|
-
return {
|
|
759
|
-
returnsHash: returnValuesHash ?? Fr.ZERO,
|
|
760
|
-
txHash: tx.getTxHash()
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
async getBlockTimestamp(blockNumber) {
|
|
764
|
-
const blockHeader = await this.stateMachine.archiver.getBlockHeader(blockNumber);
|
|
765
|
-
if (!blockHeader) {
|
|
766
|
-
throw new Error(`Requested timestamp for block ${blockNumber}, which does not exist`);
|
|
767
|
-
}
|
|
768
|
-
return blockHeader.globalVariables.timestamp;
|
|
769
|
-
}
|
|
770
|
-
}
|