@aztec/txe 0.0.1-commit.24de95ac → 0.0.1-commit.2606882
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/ContractClassRegistry-PII7Q556.js +3 -0
- package/dest/ContractClassRegistry-PII7Q556.js.map +7 -0
- package/dest/ContractInstanceRegistry-3MHLGFNZ.js +3 -0
- package/dest/ContractInstanceRegistry-3MHLGFNZ.js.map +7 -0
- package/dest/FeeJuice-TQV5AQK7.js +3 -0
- package/dest/FeeJuice-TQV5AQK7.js.map +7 -0
- package/dest/MultiCallEntrypoint-SBJUIJY7.js +3 -0
- package/dest/MultiCallEntrypoint-SBJUIJY7.js.map +7 -0
- package/dest/SchnorrAccount-MQXPIZ44.js +3 -0
- package/dest/SchnorrAccount-MQXPIZ44.js.map +7 -0
- package/dest/bin/check_txe_oracle_version.d.ts +2 -0
- package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
- package/dest/bin/check_txe_oracle_version.js +61 -0
- package/dest/bin/index.d.ts +1 -1
- package/dest/bin/index.js +3 -30
- package/dest/bin/index.js.map +7 -0
- package/dest/bin/oracle_test_server.d.ts +3 -0
- package/dest/bin/oracle_test_server.d.ts.map +1 -0
- package/dest/bin/oracle_test_server.js +41 -0
- package/dest/chunk-3VX4QA7B.js +265 -0
- package/dest/chunk-3VX4QA7B.js.map +7 -0
- package/dest/chunk-BJVAAXNA.js +3 -0
- package/dest/chunk-BJVAAXNA.js.map +7 -0
- package/dest/chunk-FU3LBVE4.js +304 -0
- package/dest/chunk-FU3LBVE4.js.map +7 -0
- package/dest/constants.d.ts +7 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +10 -0
- package/dest/dispatcher_pool.d.ts +67 -0
- package/dest/dispatcher_pool.d.ts.map +1 -0
- package/dest/dispatcher_pool.js +284 -0
- package/dest/index.d.ts +185 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +73 -158
- package/dest/metafile.json +38352 -0
- package/dest/msgpackr_fr_extension.d.ts +2 -0
- package/dest/msgpackr_fr_extension.d.ts.map +1 -0
- package/dest/msgpackr_fr_extension.js +21 -0
- package/dest/oracle/interfaces.d.ts +60 -31
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/test-resolver/fixtures.d.ts +43 -0
- package/dest/oracle/test-resolver/fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/fixtures.js +39 -0
- package/dest/oracle/test-resolver/index.d.ts +9 -0
- package/dest/oracle/test-resolver/index.d.ts.map +1 -0
- package/dest/oracle/test-resolver/index.js +33 -0
- package/dest/oracle/test-resolver/resolver.d.ts +34 -0
- package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
- package/dest/oracle/test-resolver/resolver.js +114 -0
- package/dest/oracle/txe_oracle_public_context.d.ts +41 -17
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +63 -23
- package/dest/oracle/txe_oracle_registry.d.ts +147 -0
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_registry.js +562 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +57 -28
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +342 -131
- package/dest/oracle/txe_oracle_version.d.ts +17 -0
- package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_version.js +14 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
- package/dest/oracle/txe_private_execution_oracle.js +15 -0
- package/dest/rpc_server.d.ts +14 -0
- package/dest/rpc_server.d.ts.map +1 -0
- package/dest/rpc_server.js +78 -0
- package/dest/rpc_translator.d.ts +96 -213
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +815 -550
- package/dest/server.bundle.js +3 -0
- package/dest/server.bundle.js.map +7 -0
- package/dest/state_machine/archiver.d.ts +23 -52
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +77 -99
- package/dest/state_machine/dummy_p2p_client.d.ts +28 -15
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +54 -22
- package/dest/state_machine/global_variable_builder.d.ts +11 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +21 -3
- package/dest/state_machine/index.d.ts +11 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +60 -25
- package/dest/state_machine/mock_epoch_cache.d.ts +29 -12
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +50 -15
- package/dest/state_machine/synchronizer.d.ts +6 -5
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +9 -8
- package/dest/txe_session.d.ts +94 -21
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +314 -68
- package/dest/utils/block_creation.d.ts +21 -6
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +38 -4
- package/dest/utils/encoding.d.ts +191 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/{util → utils}/encoding.js +8 -3
- package/dest/utils/expected_failure_error.d.ts +4 -0
- package/dest/utils/expected_failure_error.d.ts.map +1 -0
- package/dest/utils/tx_effect_creation.d.ts +3 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +4 -7
- package/dest/utils/txe_account_store.d.ts +10 -0
- package/dest/utils/txe_account_store.d.ts.map +1 -0
- package/dest/{util/txe_account_data_provider.js → utils/txe_account_store.js} +1 -1
- package/dest/utils/txe_artifact_resolver.d.ts +37 -0
- package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
- package/dest/utils/txe_artifact_resolver.js +161 -0
- package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
- package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
- package/dest/utils/txe_public_contract_data_source.js +48 -0
- package/dest/worker.bundle.js +3 -0
- package/dest/worker.bundle.js.map +7 -0
- package/dest/worker.d.ts +2 -0
- package/dest/worker.d.ts.map +1 -0
- package/dest/worker.js +92 -0
- package/package.json +40 -22
- package/src/bin/check_txe_oracle_version.ts +70 -0
- package/src/bin/index.ts +11 -2
- package/src/bin/oracle_test_server.ts +51 -0
- package/src/constants.ts +13 -0
- package/src/dispatcher_pool.ts +316 -0
- package/src/index.ts +111 -201
- package/src/msgpackr_fr_extension.ts +23 -0
- package/src/oracle/interfaces.ts +62 -36
- package/src/oracle/test-resolver/fixtures.ts +84 -0
- package/src/oracle/test-resolver/index.ts +45 -0
- package/src/oracle/test-resolver/resolver.ts +165 -0
- package/src/oracle/txe_oracle_public_context.ts +81 -28
- package/src/oracle/txe_oracle_registry.ts +401 -0
- package/src/oracle/txe_oracle_top_level_context.ts +419 -179
- package/src/oracle/txe_oracle_version.ts +17 -0
- package/src/oracle/txe_private_execution_oracle.ts +30 -0
- package/src/rpc_server.ts +87 -0
- package/src/rpc_translator.ts +999 -909
- package/src/state_machine/archiver.ts +83 -115
- package/src/state_machine/dummy_p2p_client.ts +83 -33
- package/src/state_machine/global_variable_builder.ts +39 -6
- package/src/state_machine/index.ts +82 -24
- package/src/state_machine/mock_epoch_cache.ts +63 -23
- package/src/state_machine/synchronizer.ts +10 -9
- package/src/txe_session.ts +486 -119
- package/src/utils/block_creation.ts +49 -14
- package/src/{util → utils}/encoding.ts +9 -3
- package/src/utils/tx_effect_creation.ts +5 -12
- package/src/{util/txe_account_data_provider.ts → utils/txe_account_store.ts} +1 -1
- package/src/utils/txe_artifact_resolver.ts +217 -0
- package/src/utils/txe_public_contract_data_source.ts +58 -0
- package/src/worker.ts +98 -0
- package/dest/util/encoding.d.ts +0 -121
- package/dest/util/encoding.d.ts.map +0 -1
- package/dest/util/expected_failure_error.d.ts +0 -4
- package/dest/util/expected_failure_error.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 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.js +0 -22
- package/dest/util/txe_public_contract_data_source.d.ts +0 -20
- package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
- package/dest/util/txe_public_contract_data_source.js +0 -67
- package/src/util/txe_contract_data_provider.ts +0 -36
- package/src/util/txe_public_contract_data_source.ts +0 -85
- /package/dest/{util → utils}/expected_failure_error.js +0 -0
- /package/src/{util → utils}/expected_failure_error.ts +0 -0
|
@@ -1,155 +1,256 @@
|
|
|
1
|
-
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, MAX_PRIVATE_LOGS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
4
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
5
|
import { LogLevels, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
5
6
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
6
|
-
import {
|
|
7
|
+
import { CapsuleService, ORACLE_VERSION_MAJOR, composeHooks, enrichPublicSimulationError } from '@aztec/pxe/server';
|
|
7
8
|
import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
|
|
8
9
|
import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
|
|
9
|
-
import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor
|
|
10
|
-
import { FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
10
|
+
import { CppPublicTxSimulator, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
|
|
11
|
+
import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
11
12
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
13
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
12
14
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
14
15
|
import { computePartialAddress } from '@aztec/stdlib/contract';
|
|
15
|
-
import { Gas, GasFees
|
|
16
|
-
import { computeCalldataHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
16
|
+
import { Gas, GasFees } from '@aztec/stdlib/gas';
|
|
17
|
+
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
17
18
|
import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
|
|
19
|
+
import { hashPublicKey } from '@aztec/stdlib/keys';
|
|
18
20
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
19
|
-
import {
|
|
21
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
20
22
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
21
23
|
import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
|
|
22
|
-
import { ForkCheckpoint } from '@aztec/world-state';
|
|
23
|
-
import {
|
|
24
|
-
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees,
|
|
24
|
+
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
25
|
+
import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
|
|
26
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
27
|
+
import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
|
|
25
28
|
export class TXEOracleTopLevelContext {
|
|
26
29
|
stateMachine;
|
|
27
|
-
|
|
30
|
+
contractStore;
|
|
31
|
+
noteStore;
|
|
28
32
|
keyStore;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
addressStore;
|
|
34
|
+
accountStore;
|
|
35
|
+
senderTaggingStore;
|
|
36
|
+
recipientTaggingStore;
|
|
37
|
+
senderAddressBookStore;
|
|
38
|
+
capsuleStore;
|
|
39
|
+
privateEventStore;
|
|
32
40
|
nextBlockTimestamp;
|
|
33
41
|
version;
|
|
34
42
|
chainId;
|
|
35
43
|
authwits;
|
|
44
|
+
artifactResolver;
|
|
45
|
+
rootPath;
|
|
46
|
+
packageName;
|
|
36
47
|
isMisc;
|
|
37
48
|
isTxe;
|
|
38
49
|
logger;
|
|
39
|
-
constructor(stateMachine,
|
|
50
|
+
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits, artifactResolver, rootPath, packageName){
|
|
40
51
|
this.stateMachine = stateMachine;
|
|
41
|
-
this.
|
|
52
|
+
this.contractStore = contractStore;
|
|
53
|
+
this.noteStore = noteStore;
|
|
42
54
|
this.keyStore = keyStore;
|
|
43
|
-
this.
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
55
|
+
this.addressStore = addressStore;
|
|
56
|
+
this.accountStore = accountStore;
|
|
57
|
+
this.senderTaggingStore = senderTaggingStore;
|
|
58
|
+
this.recipientTaggingStore = recipientTaggingStore;
|
|
59
|
+
this.senderAddressBookStore = senderAddressBookStore;
|
|
60
|
+
this.capsuleStore = capsuleStore;
|
|
61
|
+
this.privateEventStore = privateEventStore;
|
|
46
62
|
this.nextBlockTimestamp = nextBlockTimestamp;
|
|
47
63
|
this.version = version;
|
|
48
64
|
this.chainId = chainId;
|
|
49
65
|
this.authwits = authwits;
|
|
66
|
+
this.artifactResolver = artifactResolver;
|
|
67
|
+
this.rootPath = rootPath;
|
|
68
|
+
this.packageName = packageName;
|
|
50
69
|
this.isMisc = true;
|
|
51
70
|
this.isTxe = true;
|
|
52
71
|
this.logger = createLogger('txe:top_level_context');
|
|
53
72
|
this.logger.debug('Entering Top Level Context');
|
|
54
73
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
contractOracleVersion;
|
|
75
|
+
assertCompatibleOracleVersion(major, minor) {
|
|
76
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
77
|
+
const hint = major > ORACLE_VERSION_MAJOR ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.' : 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
78
|
+
throw new Error(`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`);
|
|
58
79
|
}
|
|
80
|
+
this.contractOracleVersion = {
|
|
81
|
+
major,
|
|
82
|
+
minor
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
86
|
+
nonOracleFunctionGetContractOracleVersion() {
|
|
87
|
+
return this.contractOracleVersion;
|
|
59
88
|
}
|
|
60
89
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
61
90
|
// setup.
|
|
62
|
-
|
|
91
|
+
getRandomField() {
|
|
63
92
|
return Fr.random();
|
|
64
93
|
}
|
|
65
94
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
66
|
-
|
|
95
|
+
log(level, message, _fieldsSize, fields) {
|
|
67
96
|
if (!LogLevels[level]) {
|
|
68
|
-
throw new Error(`Invalid
|
|
97
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
69
98
|
}
|
|
70
99
|
const levelName = LogLevels[level];
|
|
71
100
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, {
|
|
72
101
|
module: `${this.logger.module}:debug_log`
|
|
73
102
|
});
|
|
103
|
+
return Promise.resolve();
|
|
104
|
+
}
|
|
105
|
+
getDefaultAddress() {
|
|
106
|
+
return DEFAULT_ADDRESS;
|
|
74
107
|
}
|
|
75
|
-
async
|
|
76
|
-
return await this.getLastBlockNumber() + 1;
|
|
108
|
+
async getNextBlockNumber() {
|
|
109
|
+
return BlockNumber(await this.getLastBlockNumber() + 1);
|
|
77
110
|
}
|
|
78
|
-
|
|
111
|
+
getNextBlockTimestamp() {
|
|
79
112
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
80
113
|
}
|
|
81
|
-
async
|
|
82
|
-
return (await this.stateMachine.node.
|
|
114
|
+
async getLastBlockTimestamp() {
|
|
115
|
+
return (await this.stateMachine.node.getBlockData('latest')).header.globalVariables.timestamp;
|
|
83
116
|
}
|
|
84
|
-
async
|
|
85
|
-
const
|
|
117
|
+
async getLastTxEffects() {
|
|
118
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
119
|
+
const block = await this.stateMachine.archiver.getBlock({
|
|
120
|
+
number: latestBlockNumber
|
|
121
|
+
});
|
|
86
122
|
if (block.body.txEffects.length != 1) {
|
|
87
123
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
88
124
|
throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
|
|
89
125
|
}
|
|
90
126
|
const txEffects = block.body.txEffects[0];
|
|
127
|
+
const privateLogs = txEffects.privateLogs;
|
|
128
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
129
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
130
|
+
}
|
|
91
131
|
return {
|
|
92
132
|
txHash: txEffects.txHash,
|
|
93
133
|
noteHashes: txEffects.noteHashes,
|
|
94
|
-
nullifiers: txEffects.nullifiers
|
|
134
|
+
nullifiers: txEffects.nullifiers,
|
|
135
|
+
privateLogs
|
|
95
136
|
};
|
|
96
137
|
}
|
|
97
|
-
async
|
|
138
|
+
async syncContractNonOracleMethod(contractAddress, scope, jobId) {
|
|
139
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
140
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
144
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(contractAddress, null, async (call, execScopes)=>{
|
|
145
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
146
|
+
}, blockHeader, jobId, [
|
|
147
|
+
scope
|
|
148
|
+
]);
|
|
149
|
+
}
|
|
150
|
+
async getPrivateEvents(selector, contractAddress, scope) {
|
|
151
|
+
const events = (await this.privateEventStore.getPrivateEvents(selector, {
|
|
152
|
+
contractAddress,
|
|
153
|
+
scopes: [
|
|
154
|
+
scope
|
|
155
|
+
],
|
|
156
|
+
fromBlock: 0,
|
|
157
|
+
toBlock: await this.getLastBlockNumber() + 1
|
|
158
|
+
})).map((e)=>e.packedEvent);
|
|
159
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
160
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
161
|
+
}
|
|
162
|
+
if (events.some((e)=>e.length > MAX_PRIVATE_EVENT_LEN)) {
|
|
163
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
|
|
164
|
+
}
|
|
165
|
+
return events;
|
|
166
|
+
}
|
|
167
|
+
async advanceBlocksBy(blocks) {
|
|
98
168
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
99
169
|
for(let i = 0; i < blocks; i++){
|
|
100
170
|
await this.mineBlock();
|
|
101
171
|
}
|
|
102
172
|
}
|
|
103
|
-
|
|
173
|
+
advanceTimestampBy(duration) {
|
|
104
174
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
105
175
|
this.nextBlockTimestamp += duration;
|
|
106
176
|
}
|
|
107
|
-
|
|
177
|
+
deploymentNullifier(address) {
|
|
178
|
+
return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
|
|
179
|
+
}
|
|
180
|
+
async deploy(contractPath, initializer, args, secret, salt, deployer) {
|
|
181
|
+
const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
|
|
182
|
+
rootPath: this.rootPath,
|
|
183
|
+
packageName: this.packageName,
|
|
184
|
+
contractPath,
|
|
185
|
+
initializer,
|
|
186
|
+
args,
|
|
187
|
+
secret,
|
|
188
|
+
salt,
|
|
189
|
+
deployer
|
|
190
|
+
});
|
|
108
191
|
// Emit deployment nullifier
|
|
109
192
|
await this.mineBlock({
|
|
110
193
|
nullifiers: [
|
|
111
|
-
await
|
|
194
|
+
await this.deploymentNullifier(instance.address)
|
|
112
195
|
]
|
|
113
196
|
});
|
|
114
197
|
if (!secret.equals(Fr.ZERO)) {
|
|
115
|
-
await this.
|
|
198
|
+
await this.registerContractAndAddAccount(artifact, instance, secret);
|
|
116
199
|
} else {
|
|
117
|
-
await this.
|
|
118
|
-
await this.
|
|
200
|
+
await this.contractStore.addContractInstance(instance);
|
|
201
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
119
202
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
120
203
|
}
|
|
204
|
+
return [
|
|
205
|
+
instance.salt,
|
|
206
|
+
instance.deployer.toField(),
|
|
207
|
+
instance.currentContractClassId,
|
|
208
|
+
instance.initializationHash,
|
|
209
|
+
instance.immutablesHash,
|
|
210
|
+
...instance.publicKeys.toFields()
|
|
211
|
+
];
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
|
|
215
|
+
*/ async mineDeploymentNullifiers(addresses) {
|
|
216
|
+
await this.mineBlock({
|
|
217
|
+
nullifiers: await Promise.all(addresses.map((address)=>this.deploymentNullifier(address)))
|
|
218
|
+
});
|
|
121
219
|
}
|
|
122
|
-
async
|
|
220
|
+
async addAccount(secret) {
|
|
221
|
+
const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
|
|
222
|
+
return this.registerContractAndAddAccount(artifact, instance, secret);
|
|
223
|
+
}
|
|
224
|
+
async registerContractAndAddAccount(artifact, instance, secret) {
|
|
123
225
|
const partialAddress = await computePartialAddress(instance);
|
|
124
226
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
125
|
-
await this.
|
|
126
|
-
await this.
|
|
227
|
+
await this.contractStore.addContractInstance(instance);
|
|
228
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
127
229
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
128
|
-
await this.
|
|
129
|
-
await this.
|
|
230
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
231
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
130
232
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
131
233
|
return completeAddress;
|
|
132
234
|
}
|
|
133
|
-
async
|
|
134
|
-
// This is a
|
|
235
|
+
async createAccount(secret) {
|
|
236
|
+
// This is a foot gun !
|
|
135
237
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
136
|
-
await this.
|
|
137
|
-
await this.
|
|
238
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
239
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
138
240
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
139
241
|
return completeAddress;
|
|
140
242
|
}
|
|
141
|
-
async
|
|
142
|
-
const account = await this.
|
|
143
|
-
const
|
|
243
|
+
async addAuthWitness(address, messageHash) {
|
|
244
|
+
const account = await this.accountStore.getAccount(address);
|
|
245
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
246
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
144
247
|
const schnorr = new Schnorr();
|
|
145
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
146
|
-
const authWitness = new AuthWitness(messageHash,
|
|
147
|
-
...signature.toBuffer()
|
|
148
|
-
]);
|
|
248
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
249
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
149
250
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
150
251
|
}
|
|
151
252
|
async mineBlock(options = {}) {
|
|
152
|
-
const blockNumber = await this.
|
|
253
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
153
254
|
const txEffect = TxEffect.empty();
|
|
154
255
|
txEffect.nullifiers = [
|
|
155
256
|
getSingleTxBlockRequestHash(blockNumber),
|
|
@@ -158,42 +259,87 @@ export class TXEOracleTopLevelContext {
|
|
|
158
259
|
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
159
260
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
160
261
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
161
|
-
const
|
|
262
|
+
const globals = makeGlobalVariables(undefined, {
|
|
162
263
|
blockNumber,
|
|
163
264
|
timestamp: this.nextBlockTimestamp,
|
|
164
265
|
version: this.version,
|
|
165
266
|
chainId: this.chainId
|
|
166
|
-
})
|
|
267
|
+
});
|
|
268
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
167
269
|
txEffect
|
|
168
|
-
])
|
|
270
|
+
]);
|
|
169
271
|
await forkedWorldTrees.close();
|
|
170
272
|
this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
|
|
171
273
|
await this.stateMachine.handleL2Block(block);
|
|
172
274
|
}
|
|
173
|
-
async
|
|
174
|
-
this.logger.verbose(`Executing external function ${await this.
|
|
175
|
-
const artifact = await this.
|
|
275
|
+
async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, additionalScopes = [], jobId, authorizedUtilityCallTargets, gasSettings) {
|
|
276
|
+
this.logger.verbose(`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
277
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
176
278
|
if (!artifact) {
|
|
177
279
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
|
|
178
280
|
throw new Error(message);
|
|
179
281
|
}
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
282
|
+
const scopes = from === undefined ? additionalScopes : [
|
|
283
|
+
from,
|
|
284
|
+
...additionalScopes
|
|
285
|
+
];
|
|
286
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
287
|
+
const utilityExecutor = async (call, execScopes)=>{
|
|
288
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
289
|
+
};
|
|
290
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
291
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
|
|
292
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
293
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
294
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
185
295
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
|
|
296
|
+
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
297
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
298
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
299
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
300
|
+
// marking all side effects as revertible.
|
|
301
|
+
const minRevertibleSideEffectCounter = 1;
|
|
302
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
189
303
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
190
304
|
const simulator = new WASMSimulator();
|
|
191
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
305
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
306
|
+
argsHash,
|
|
307
|
+
txContext,
|
|
308
|
+
callContext,
|
|
309
|
+
anchorBlockHeader: blockHeader,
|
|
310
|
+
utilityExecutor,
|
|
311
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
312
|
+
capsules: [],
|
|
313
|
+
executionCache: HashedValuesCache.create([
|
|
314
|
+
new HashedValues(args, argsHash)
|
|
315
|
+
]),
|
|
316
|
+
noteCache,
|
|
317
|
+
taggingIndexCache,
|
|
318
|
+
contractStore: this.contractStore,
|
|
319
|
+
noteStore: this.noteStore,
|
|
320
|
+
keyStore: this.keyStore,
|
|
321
|
+
addressStore: this.addressStore,
|
|
322
|
+
aztecNode: this.stateMachine.node,
|
|
323
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
324
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
325
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
326
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
327
|
+
privateEventStore: this.privateEventStore,
|
|
328
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
329
|
+
jobId,
|
|
330
|
+
totalPublicCalldataCount: 0,
|
|
331
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
332
|
+
scopes,
|
|
333
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
334
|
+
// contract would perform, including setting senderForTags.
|
|
335
|
+
senderForTags: from,
|
|
336
|
+
simulator,
|
|
337
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
338
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
339
|
+
hooks: composeHooks({
|
|
340
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets)
|
|
341
|
+
})
|
|
342
|
+
});
|
|
197
343
|
// 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.
|
|
198
344
|
let result;
|
|
199
345
|
let executionResult;
|
|
@@ -205,21 +351,19 @@ export class TXEOracleTopLevelContext {
|
|
|
205
351
|
r.publicInputs.publicTeardownCallRequest
|
|
206
352
|
]));
|
|
207
353
|
const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
|
|
208
|
-
const calldata = await privateExecutionOracle.
|
|
354
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
209
355
|
return new HashedValues(calldata, r.calldataHash);
|
|
210
356
|
}));
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
357
|
+
noteCache.finish();
|
|
358
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
359
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
215
360
|
} catch (err) {
|
|
216
361
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
217
362
|
}
|
|
218
|
-
// According to the protocol rules,
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
const
|
|
222
|
-
const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
|
|
363
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
364
|
+
// the nonce generator for the note hashes.
|
|
365
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
366
|
+
const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>this.contractStore.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
|
|
223
367
|
const globals = makeGlobalVariables();
|
|
224
368
|
globals.blockNumber = blockNumber;
|
|
225
369
|
globals.timestamp = this.nextBlockTimestamp;
|
|
@@ -227,12 +371,17 @@ export class TXEOracleTopLevelContext {
|
|
|
227
371
|
globals.version = this.version;
|
|
228
372
|
globals.gasFees = GasFees.empty();
|
|
229
373
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
230
|
-
const
|
|
374
|
+
const bindings = this.logger.getBindings();
|
|
375
|
+
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
|
|
231
376
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
377
|
+
const config = PublicSimulatorConfig.from({
|
|
378
|
+
skipFeeEnforcement: true,
|
|
379
|
+
collectDebugLogs: true,
|
|
380
|
+
collectHints: false,
|
|
381
|
+
collectStatistics: false,
|
|
382
|
+
collectCallMetadata: true
|
|
383
|
+
});
|
|
384
|
+
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
|
|
236
385
|
const tx = await Tx.create({
|
|
237
386
|
data: publicInputs,
|
|
238
387
|
chonkProof: ChonkProof.empty(),
|
|
@@ -253,7 +402,7 @@ export class TXEOracleTopLevelContext {
|
|
|
253
402
|
} else if (!processedTx.revertCode.isOK()) {
|
|
254
403
|
if (processedTx.revertReason) {
|
|
255
404
|
try {
|
|
256
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
405
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
257
406
|
// eslint-disable-next-line no-empty
|
|
258
407
|
} catch {}
|
|
259
408
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -261,10 +410,20 @@ export class TXEOracleTopLevelContext {
|
|
|
261
410
|
throw new Error('Contract execution has reverted');
|
|
262
411
|
}
|
|
263
412
|
}
|
|
413
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
414
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
415
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
416
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
417
|
+
const offchainEffects = collectNested([
|
|
418
|
+
executionResult
|
|
419
|
+
], (r)=>r.offchainEffects.map((e)=>e.data));
|
|
264
420
|
if (isStaticCall) {
|
|
265
421
|
await checkpoint.revert();
|
|
266
422
|
await forkedWorldTrees.close();
|
|
267
|
-
return
|
|
423
|
+
return {
|
|
424
|
+
returnValues: executionResult.returnValues ?? [],
|
|
425
|
+
offchainEffects
|
|
426
|
+
};
|
|
268
427
|
}
|
|
269
428
|
const txEffect = TxEffect.empty();
|
|
270
429
|
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
@@ -275,22 +434,21 @@ export class TXEOracleTopLevelContext {
|
|
|
275
434
|
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
276
435
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
277
436
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
278
|
-
const
|
|
437
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
279
438
|
txEffect
|
|
280
439
|
]);
|
|
281
|
-
const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, globals), body);
|
|
282
440
|
await this.stateMachine.handleL2Block(l2Block);
|
|
283
441
|
await forkedWorldTrees.close();
|
|
284
|
-
return
|
|
442
|
+
return {
|
|
443
|
+
returnValues: executionResult.returnValues ?? [],
|
|
444
|
+
offchainEffects
|
|
445
|
+
};
|
|
285
446
|
}
|
|
286
|
-
async
|
|
287
|
-
this.logger.verbose(`Executing public function ${await this.
|
|
288
|
-
const blockNumber = await this.
|
|
289
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
290
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
291
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
447
|
+
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall, gasSettings) {
|
|
448
|
+
this.logger.verbose(`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
449
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
292
450
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
293
|
-
const anchorBlockHeader = await this.
|
|
451
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
294
452
|
const calldataHash = await computeCalldataHash(calldata);
|
|
295
453
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
296
454
|
const globals = makeGlobalVariables();
|
|
@@ -300,28 +458,31 @@ export class TXEOracleTopLevelContext {
|
|
|
300
458
|
globals.version = this.version;
|
|
301
459
|
globals.gasFees = GasFees.empty();
|
|
302
460
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
303
|
-
const
|
|
461
|
+
const bindings2 = this.logger.getBindings();
|
|
462
|
+
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings2);
|
|
304
463
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
464
|
+
const config = PublicSimulatorConfig.from({
|
|
465
|
+
skipFeeEnforcement: true,
|
|
466
|
+
collectDebugLogs: true,
|
|
467
|
+
collectHints: false,
|
|
468
|
+
collectStatistics: false,
|
|
469
|
+
collectCallMetadata: true
|
|
308
470
|
});
|
|
309
|
-
const
|
|
471
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
472
|
+
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings2));
|
|
310
473
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
311
474
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
312
475
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
313
476
|
// unique.
|
|
314
477
|
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
315
|
-
|
|
316
|
-
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
317
|
-
}
|
|
478
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
318
479
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
319
480
|
// may require producing reverts.
|
|
320
481
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
321
|
-
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
|
|
482
|
+
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
|
|
322
483
|
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
|
|
323
484
|
const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
|
|
324
|
-
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*
|
|
485
|
+
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
|
|
325
486
|
const tx = await Tx.create({
|
|
326
487
|
data: txData,
|
|
327
488
|
chonkProof: ChonkProof.empty(),
|
|
@@ -344,7 +505,7 @@ export class TXEOracleTopLevelContext {
|
|
|
344
505
|
} else if (!processedTx.revertCode.isOK()) {
|
|
345
506
|
if (processedTx.revertReason) {
|
|
346
507
|
try {
|
|
347
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
508
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
348
509
|
// eslint-disable-next-line no-empty
|
|
349
510
|
} catch {}
|
|
350
511
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -367,25 +528,37 @@ export class TXEOracleTopLevelContext {
|
|
|
367
528
|
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
368
529
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
369
530
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
370
|
-
const
|
|
531
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
371
532
|
txEffect
|
|
372
533
|
]);
|
|
373
|
-
const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, globals), body);
|
|
374
534
|
await this.stateMachine.handleL2Block(l2Block);
|
|
375
535
|
await forkedWorldTrees.close();
|
|
376
536
|
return returnValues ?? [];
|
|
377
537
|
}
|
|
378
|
-
async
|
|
379
|
-
const artifact = await this.
|
|
538
|
+
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId, authorizedUtilityCallTargets) {
|
|
539
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
380
540
|
if (!artifact) {
|
|
381
541
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
382
542
|
}
|
|
383
|
-
|
|
543
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
544
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
545
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, async (call, execScopes)=>{
|
|
546
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
547
|
+
}, blockHeader, jobId, await this.keyStore.getAccounts());
|
|
548
|
+
const call = FunctionCall.from({
|
|
384
549
|
name: artifact.name,
|
|
550
|
+
to: targetContractAddress,
|
|
385
551
|
selector: functionSelector,
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
552
|
+
type: FunctionType.UTILITY,
|
|
553
|
+
hideMsgSender: false,
|
|
554
|
+
isStatic: false,
|
|
555
|
+
args,
|
|
556
|
+
returnTypes: []
|
|
557
|
+
});
|
|
558
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
|
|
559
|
+
}
|
|
560
|
+
async executeUtilityCall(call, scopes, jobId, authorizedUtilityCallTargets = []) {
|
|
561
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
389
562
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
390
563
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
391
564
|
}
|
|
@@ -394,8 +567,37 @@ export class TXEOracleTopLevelContext {
|
|
|
394
567
|
selector: call.selector
|
|
395
568
|
});
|
|
396
569
|
try {
|
|
397
|
-
const
|
|
398
|
-
const
|
|
570
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
571
|
+
const simulator = new WASMSimulator();
|
|
572
|
+
const utilityExecutor = async (syncCall, execScopes)=>{
|
|
573
|
+
await this.executeUtilityCall(syncCall, execScopes, jobId);
|
|
574
|
+
};
|
|
575
|
+
const oracle = new UtilityExecutionOracle({
|
|
576
|
+
contractAddress: call.to,
|
|
577
|
+
authWitnesses: [],
|
|
578
|
+
capsules: [],
|
|
579
|
+
anchorBlockHeader,
|
|
580
|
+
contractStore: this.contractStore,
|
|
581
|
+
noteStore: this.noteStore,
|
|
582
|
+
keyStore: this.keyStore,
|
|
583
|
+
addressStore: this.addressStore,
|
|
584
|
+
aztecNode: this.stateMachine.node,
|
|
585
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
586
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
587
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
588
|
+
privateEventStore: this.privateEventStore,
|
|
589
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
590
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
591
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
592
|
+
jobId,
|
|
593
|
+
scopes,
|
|
594
|
+
simulator,
|
|
595
|
+
hooks: composeHooks({
|
|
596
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets)
|
|
597
|
+
}),
|
|
598
|
+
utilityExecutor
|
|
599
|
+
});
|
|
600
|
+
const acirExecutionResult = await simulator.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
|
|
399
601
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
400
602
|
throw new ExecutionError(err.message, {
|
|
401
603
|
contractAddress: call.to,
|
|
@@ -404,10 +606,10 @@ export class TXEOracleTopLevelContext {
|
|
|
404
606
|
cause: err
|
|
405
607
|
});
|
|
406
608
|
});
|
|
407
|
-
this.logger.verbose(`Utility
|
|
609
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
408
610
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
409
611
|
} catch (err) {
|
|
410
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
612
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
411
613
|
}
|
|
412
614
|
}
|
|
413
615
|
close() {
|
|
@@ -418,6 +620,15 @@ export class TXEOracleTopLevelContext {
|
|
|
418
620
|
];
|
|
419
621
|
}
|
|
420
622
|
async getLastBlockNumber() {
|
|
421
|
-
|
|
623
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
624
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
625
|
+
}
|
|
626
|
+
buildAuthorizeUtilityCallHook(callerContext, authorizedTargets) {
|
|
627
|
+
if (authorizedTargets.length === 0) {
|
|
628
|
+
return undefined;
|
|
629
|
+
}
|
|
630
|
+
return (req)=>Promise.resolve({
|
|
631
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some((t)=>t.equals(req.target))
|
|
632
|
+
});
|
|
422
633
|
}
|
|
423
634
|
}
|