@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,20 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
3
|
-
|
|
4
|
-
DEFAULT_L2_GAS_LIMIT,
|
|
5
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
6
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
3
|
+
MAX_PRIVATE_LOGS_PER_TX,
|
|
7
4
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
8
5
|
} from '@aztec/constants';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
6
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
7
|
+
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
8
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
11
9
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
12
10
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
13
11
|
import type { KeyStore } from '@aztec/key-store';
|
|
14
12
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
AddressStore,
|
|
14
|
+
CapsuleService,
|
|
15
|
+
CapsuleStore,
|
|
16
|
+
type ContractStore,
|
|
17
|
+
type ExecutionHooks,
|
|
18
|
+
NoteStore,
|
|
19
|
+
ORACLE_VERSION_MAJOR,
|
|
20
|
+
PrivateEventStore,
|
|
21
|
+
RecipientTaggingStore,
|
|
22
|
+
SenderAddressBookStore,
|
|
23
|
+
SenderTaggingStore,
|
|
24
|
+
composeHooks,
|
|
18
25
|
enrichPublicSimulationError,
|
|
19
26
|
} from '@aztec/pxe/server';
|
|
20
27
|
import {
|
|
@@ -38,26 +45,27 @@ import {
|
|
|
38
45
|
witnessMapToFields,
|
|
39
46
|
} from '@aztec/simulator/client';
|
|
40
47
|
import {
|
|
48
|
+
CppPublicTxSimulator,
|
|
41
49
|
GuardedMerkleTreeOperations,
|
|
42
50
|
PublicContractsDB,
|
|
43
51
|
PublicProcessor,
|
|
44
|
-
PublicTxSimulator,
|
|
45
52
|
} from '@aztec/simulator/server';
|
|
46
|
-
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
53
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
47
54
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
55
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
48
56
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
49
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
50
57
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
51
58
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
52
|
-
import { computeCalldataHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
59
|
+
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
53
60
|
import {
|
|
54
61
|
PartialPrivateTailPublicInputsForPublic,
|
|
55
62
|
PrivateKernelTailCircuitPublicInputs,
|
|
56
63
|
PrivateToPublicAccumulatedData,
|
|
57
64
|
PublicCallRequest,
|
|
58
65
|
} from '@aztec/stdlib/kernel';
|
|
66
|
+
import { hashPublicKey } from '@aztec/stdlib/keys';
|
|
59
67
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
60
|
-
import {
|
|
68
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
61
69
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
62
70
|
import {
|
|
63
71
|
CallContext,
|
|
@@ -72,17 +80,14 @@ import {
|
|
|
72
80
|
collectNested,
|
|
73
81
|
} from '@aztec/stdlib/tx';
|
|
74
82
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
75
|
-
import { ForkCheckpoint } from '@aztec/world-state';
|
|
83
|
+
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
76
84
|
|
|
85
|
+
import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
|
|
77
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
78
|
-
import
|
|
79
|
-
import type {
|
|
80
|
-
import {
|
|
81
|
-
import {
|
|
82
|
-
getSingleTxBlockRequestHash,
|
|
83
|
-
insertTxEffectIntoWorldTrees,
|
|
84
|
-
makeTXEBlockHeader,
|
|
85
|
-
} from '../utils/block_creation.js';
|
|
87
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
88
|
+
import type { TXEAccountStore } from '../utils/txe_account_store.js';
|
|
89
|
+
import type { TXEArtifactResolver } from '../utils/txe_artifact_resolver.js';
|
|
90
|
+
import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
|
|
86
91
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
87
92
|
|
|
88
93
|
export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
|
|
@@ -93,58 +98,84 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
93
98
|
|
|
94
99
|
constructor(
|
|
95
100
|
private stateMachine: TXEStateMachine,
|
|
96
|
-
private
|
|
101
|
+
private contractStore: ContractStore,
|
|
102
|
+
private noteStore: NoteStore,
|
|
97
103
|
private keyStore: KeyStore,
|
|
98
|
-
private
|
|
99
|
-
private
|
|
100
|
-
private
|
|
104
|
+
private addressStore: AddressStore,
|
|
105
|
+
private accountStore: TXEAccountStore,
|
|
106
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
107
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
108
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
109
|
+
private capsuleStore: CapsuleStore,
|
|
110
|
+
private privateEventStore: PrivateEventStore,
|
|
101
111
|
private nextBlockTimestamp: bigint,
|
|
102
112
|
private version: Fr,
|
|
103
113
|
private chainId: Fr,
|
|
104
114
|
private authwits: Map<string, AuthWitness>,
|
|
115
|
+
private readonly artifactResolver: TXEArtifactResolver,
|
|
116
|
+
private readonly rootPath: string,
|
|
117
|
+
private readonly packageName: string,
|
|
105
118
|
) {
|
|
106
119
|
this.logger = createLogger('txe:top_level_context');
|
|
107
120
|
this.logger.debug('Entering Top Level Context');
|
|
108
121
|
}
|
|
109
122
|
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
124
|
+
|
|
125
|
+
assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
126
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
127
|
+
const hint =
|
|
128
|
+
major > ORACLE_VERSION_MAJOR
|
|
129
|
+
? '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.'
|
|
130
|
+
: '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.';
|
|
112
131
|
throw new Error(
|
|
113
|
-
`Incompatible
|
|
132
|
+
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
114
133
|
);
|
|
115
134
|
}
|
|
135
|
+
this.contractOracleVersion = { major, minor };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
139
|
+
nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
140
|
+
return this.contractOracleVersion;
|
|
116
141
|
}
|
|
117
142
|
|
|
118
143
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
119
144
|
// setup.
|
|
120
|
-
|
|
145
|
+
getRandomField(): Fr {
|
|
121
146
|
return Fr.random();
|
|
122
147
|
}
|
|
123
148
|
|
|
124
149
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
125
|
-
|
|
150
|
+
log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
|
|
126
151
|
if (!LogLevels[level]) {
|
|
127
|
-
throw new Error(`Invalid
|
|
152
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
128
153
|
}
|
|
129
154
|
const levelName = LogLevels[level];
|
|
130
155
|
|
|
131
156
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
157
|
+
return Promise.resolve();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
getDefaultAddress(): AztecAddress {
|
|
161
|
+
return DEFAULT_ADDRESS;
|
|
132
162
|
}
|
|
133
163
|
|
|
134
|
-
async
|
|
135
|
-
return (await this.getLastBlockNumber()) + 1;
|
|
164
|
+
async getNextBlockNumber(): Promise<BlockNumber> {
|
|
165
|
+
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
136
166
|
}
|
|
137
167
|
|
|
138
|
-
|
|
168
|
+
getNextBlockTimestamp(): Promise<bigint> {
|
|
139
169
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
140
170
|
}
|
|
141
171
|
|
|
142
|
-
async
|
|
143
|
-
return (await this.stateMachine.node.
|
|
172
|
+
async getLastBlockTimestamp() {
|
|
173
|
+
return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
|
|
144
174
|
}
|
|
145
175
|
|
|
146
|
-
async
|
|
147
|
-
const
|
|
176
|
+
async getLastTxEffects() {
|
|
177
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
178
|
+
const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
|
|
148
179
|
|
|
149
180
|
if (block!.body.txEffects.length != 1) {
|
|
150
181
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -153,10 +184,59 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
153
184
|
|
|
154
185
|
const txEffects = block!.body.txEffects[0];
|
|
155
186
|
|
|
156
|
-
|
|
187
|
+
const privateLogs = txEffects.privateLogs;
|
|
188
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
189
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
txHash: txEffects.txHash,
|
|
194
|
+
noteHashes: txEffects.noteHashes,
|
|
195
|
+
nullifiers: txEffects.nullifiers,
|
|
196
|
+
privateLogs,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
201
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
202
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
207
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
208
|
+
contractAddress,
|
|
209
|
+
null,
|
|
210
|
+
async (call, execScopes) => {
|
|
211
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
212
|
+
},
|
|
213
|
+
blockHeader,
|
|
214
|
+
jobId,
|
|
215
|
+
[scope],
|
|
216
|
+
);
|
|
157
217
|
}
|
|
158
218
|
|
|
159
|
-
async
|
|
219
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
220
|
+
const events = (
|
|
221
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
222
|
+
contractAddress,
|
|
223
|
+
scopes: [scope],
|
|
224
|
+
fromBlock: 0,
|
|
225
|
+
toBlock: (await this.getLastBlockNumber()) + 1,
|
|
226
|
+
})
|
|
227
|
+
).map(e => e.packedEvent);
|
|
228
|
+
|
|
229
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
230
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
231
|
+
}
|
|
232
|
+
if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
|
|
233
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return events;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async advanceBlocksBy(blocks: number) {
|
|
160
240
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
161
241
|
|
|
162
242
|
for (let i = 0; i < blocks; i++) {
|
|
@@ -164,70 +244,115 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
164
244
|
}
|
|
165
245
|
}
|
|
166
246
|
|
|
167
|
-
|
|
247
|
+
advanceTimestampBy(duration: UInt64) {
|
|
168
248
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
169
249
|
this.nextBlockTimestamp += duration;
|
|
170
250
|
}
|
|
171
251
|
|
|
172
|
-
|
|
252
|
+
private deploymentNullifier(address: AztecAddress): Promise<Fr> {
|
|
253
|
+
return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async deploy(
|
|
257
|
+
contractPath: string,
|
|
258
|
+
initializer: string,
|
|
259
|
+
args: Fr[],
|
|
260
|
+
secret: Fr,
|
|
261
|
+
salt: Fr,
|
|
262
|
+
deployer: AztecAddress,
|
|
263
|
+
): Promise<Fr[]> {
|
|
264
|
+
const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
|
|
265
|
+
rootPath: this.rootPath,
|
|
266
|
+
packageName: this.packageName,
|
|
267
|
+
contractPath,
|
|
268
|
+
initializer,
|
|
269
|
+
args,
|
|
270
|
+
secret,
|
|
271
|
+
salt,
|
|
272
|
+
deployer,
|
|
273
|
+
});
|
|
274
|
+
|
|
173
275
|
// Emit deployment nullifier
|
|
174
276
|
await this.mineBlock({
|
|
175
|
-
nullifiers: [
|
|
176
|
-
await siloNullifier(
|
|
177
|
-
AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
|
|
178
|
-
instance.address.toField(),
|
|
179
|
-
),
|
|
180
|
-
],
|
|
277
|
+
nullifiers: [await this.deploymentNullifier(instance.address)],
|
|
181
278
|
});
|
|
182
279
|
|
|
183
280
|
if (!secret.equals(Fr.ZERO)) {
|
|
184
|
-
await this.
|
|
281
|
+
await this.registerContractAndAddAccount(artifact, instance, secret);
|
|
185
282
|
} else {
|
|
186
|
-
await this.
|
|
187
|
-
await this.
|
|
283
|
+
await this.contractStore.addContractInstance(instance);
|
|
284
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
188
285
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
189
286
|
}
|
|
287
|
+
|
|
288
|
+
return [
|
|
289
|
+
instance.salt,
|
|
290
|
+
instance.deployer.toField(),
|
|
291
|
+
instance.currentContractClassId,
|
|
292
|
+
instance.initializationHash,
|
|
293
|
+
instance.immutablesHash,
|
|
294
|
+
...instance.publicKeys.toFields(),
|
|
295
|
+
];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
|
|
300
|
+
*/
|
|
301
|
+
async mineDeploymentNullifiers(addresses: AztecAddress[]) {
|
|
302
|
+
await this.mineBlock({
|
|
303
|
+
nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async addAccount(secret: Fr) {
|
|
308
|
+
const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
|
|
309
|
+
return this.registerContractAndAddAccount(artifact, instance, secret);
|
|
190
310
|
}
|
|
191
311
|
|
|
192
|
-
async
|
|
312
|
+
private async registerContractAndAddAccount(
|
|
313
|
+
artifact: ContractArtifact,
|
|
314
|
+
instance: ContractInstanceWithAddress,
|
|
315
|
+
secret: Fr,
|
|
316
|
+
) {
|
|
193
317
|
const partialAddress = await computePartialAddress(instance);
|
|
194
318
|
|
|
195
319
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
196
|
-
await this.
|
|
197
|
-
await this.
|
|
320
|
+
await this.contractStore.addContractInstance(instance);
|
|
321
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
198
322
|
|
|
199
323
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
200
|
-
await this.
|
|
201
|
-
await this.
|
|
324
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
325
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
202
326
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
203
327
|
|
|
204
328
|
return completeAddress;
|
|
205
329
|
}
|
|
206
330
|
|
|
207
|
-
async
|
|
208
|
-
// This is a
|
|
331
|
+
async createAccount(secret: Fr) {
|
|
332
|
+
// This is a foot gun !
|
|
209
333
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
210
|
-
await this.
|
|
211
|
-
await this.
|
|
334
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
335
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
212
336
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
213
337
|
|
|
214
338
|
return completeAddress;
|
|
215
339
|
}
|
|
216
340
|
|
|
217
|
-
async
|
|
218
|
-
const account = await this.
|
|
219
|
-
const
|
|
341
|
+
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
342
|
+
const account = await this.accountStore.getAccount(address);
|
|
343
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
344
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
220
345
|
|
|
221
346
|
const schnorr = new Schnorr();
|
|
222
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
347
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
223
348
|
|
|
224
|
-
const authWitness = new AuthWitness(messageHash,
|
|
349
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
225
350
|
|
|
226
351
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
227
352
|
}
|
|
228
353
|
|
|
229
354
|
async mineBlock(options: { nullifiers?: Fr[] } = {}) {
|
|
230
|
-
const blockNumber = await this.
|
|
355
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
231
356
|
|
|
232
357
|
const txEffect = TxEffect.empty();
|
|
233
358
|
txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
|
|
@@ -236,19 +361,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
236
361
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
237
362
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
238
363
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
version: this.version,
|
|
247
|
-
chainId: this.chainId,
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
250
|
-
new Body([txEffect]),
|
|
251
|
-
);
|
|
364
|
+
const globals = makeGlobalVariables(undefined, {
|
|
365
|
+
blockNumber,
|
|
366
|
+
timestamp: this.nextBlockTimestamp,
|
|
367
|
+
version: this.version,
|
|
368
|
+
chainId: this.chainId,
|
|
369
|
+
});
|
|
370
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
252
371
|
|
|
253
372
|
await forkedWorldTrees.close();
|
|
254
373
|
|
|
@@ -257,19 +376,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
257
376
|
await this.stateMachine.handleL2Block(block);
|
|
258
377
|
}
|
|
259
378
|
|
|
260
|
-
async
|
|
261
|
-
from: AztecAddress,
|
|
379
|
+
async privateCallNewFlow(
|
|
380
|
+
from: AztecAddress | undefined,
|
|
262
381
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
263
382
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
264
383
|
args: Fr[],
|
|
265
384
|
argsHash: Fr = Fr.zero(),
|
|
266
385
|
isStaticCall: boolean = false,
|
|
386
|
+
additionalScopes: AztecAddress[] = [],
|
|
387
|
+
jobId: string,
|
|
388
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
389
|
+
gasSettings: GasSettings,
|
|
267
390
|
) {
|
|
268
391
|
this.logger.verbose(
|
|
269
|
-
`Executing external function ${await this.
|
|
392
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
270
393
|
);
|
|
271
394
|
|
|
272
|
-
const artifact = await this.
|
|
395
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
273
396
|
if (!artifact) {
|
|
274
397
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
275
398
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -277,51 +400,80 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
277
400
|
throw new Error(message);
|
|
278
401
|
}
|
|
279
402
|
|
|
280
|
-
const
|
|
403
|
+
const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
|
|
281
404
|
|
|
282
|
-
|
|
405
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
406
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
|
|
407
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
408
|
+
};
|
|
283
409
|
|
|
284
|
-
const
|
|
410
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
411
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
412
|
+
targetContractAddress,
|
|
413
|
+
functionSelector,
|
|
414
|
+
utilityExecutor,
|
|
415
|
+
blockHeader,
|
|
416
|
+
jobId,
|
|
417
|
+
scopes,
|
|
418
|
+
);
|
|
285
419
|
|
|
286
|
-
const
|
|
420
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
287
421
|
|
|
288
|
-
const
|
|
422
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
423
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
289
424
|
|
|
290
425
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
291
426
|
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
427
|
+
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
428
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
429
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
430
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
431
|
+
// marking all side effects as revertible.
|
|
432
|
+
const minRevertibleSideEffectCounter = 1;
|
|
433
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
296
434
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
297
435
|
|
|
298
436
|
const simulator = new WASMSimulator();
|
|
299
437
|
|
|
300
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
438
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
301
439
|
argsHash,
|
|
302
440
|
txContext,
|
|
303
441
|
callContext,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
[],
|
|
310
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
442
|
+
anchorBlockHeader: blockHeader,
|
|
443
|
+
utilityExecutor,
|
|
444
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
445
|
+
capsules: [],
|
|
446
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
311
447
|
noteCache,
|
|
312
448
|
taggingIndexCache,
|
|
313
|
-
this.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
449
|
+
contractStore: this.contractStore,
|
|
450
|
+
noteStore: this.noteStore,
|
|
451
|
+
keyStore: this.keyStore,
|
|
452
|
+
addressStore: this.addressStore,
|
|
453
|
+
aztecNode: this.stateMachine.node,
|
|
454
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
455
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
456
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
457
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
458
|
+
privateEventStore: this.privateEventStore,
|
|
459
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
460
|
+
jobId,
|
|
461
|
+
totalPublicCalldataCount: 0,
|
|
462
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
463
|
+
scopes,
|
|
464
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
465
|
+
// contract would perform, including setting senderForTags.
|
|
466
|
+
senderForTags: from,
|
|
323
467
|
simulator,
|
|
324
|
-
|
|
468
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
469
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
470
|
+
hooks: composeHooks({
|
|
471
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
|
|
472
|
+
isStaticCall ? 'private view' : 'private',
|
|
473
|
+
authorizedUtilityCallTargets,
|
|
474
|
+
),
|
|
475
|
+
}),
|
|
476
|
+
});
|
|
325
477
|
|
|
326
478
|
// 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.
|
|
327
479
|
let result: PrivateExecutionResult;
|
|
@@ -343,24 +495,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
343
495
|
);
|
|
344
496
|
const publicFunctionsCalldata = await Promise.all(
|
|
345
497
|
publicCallRequests.map(async r => {
|
|
346
|
-
const calldata = await privateExecutionOracle.
|
|
498
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
347
499
|
return new HashedValues(calldata, r.calldataHash);
|
|
348
500
|
}),
|
|
349
501
|
);
|
|
350
502
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
503
|
+
noteCache.finish();
|
|
504
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
505
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
355
506
|
} catch (err) {
|
|
356
507
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
357
508
|
}
|
|
358
509
|
|
|
359
|
-
// According to the protocol rules,
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
const
|
|
363
|
-
|
|
510
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
511
|
+
// the nonce generator for the note hashes.
|
|
512
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
513
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
514
|
+
result,
|
|
515
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
516
|
+
this.stateMachine.node,
|
|
517
|
+
minRevertibleSideEffectCounter,
|
|
518
|
+
);
|
|
364
519
|
|
|
365
520
|
const globals = makeGlobalVariables();
|
|
366
521
|
globals.blockNumber = blockNumber;
|
|
@@ -371,17 +526,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
371
526
|
|
|
372
527
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
373
528
|
|
|
374
|
-
const
|
|
529
|
+
const bindings = this.logger.getBindings();
|
|
530
|
+
const contractsDB = new PublicContractsDB(
|
|
531
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
532
|
+
bindings,
|
|
533
|
+
);
|
|
375
534
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
535
|
+
const config = PublicSimulatorConfig.from({
|
|
536
|
+
skipFeeEnforcement: true,
|
|
537
|
+
collectDebugLogs: true,
|
|
538
|
+
collectHints: false,
|
|
539
|
+
collectStatistics: false,
|
|
540
|
+
collectCallMetadata: true,
|
|
541
|
+
});
|
|
376
542
|
const processor = new PublicProcessor(
|
|
377
543
|
globals,
|
|
378
544
|
guardedMerkleTrees,
|
|
379
545
|
contractsDB,
|
|
380
|
-
new
|
|
381
|
-
doMerkleOperations: true,
|
|
382
|
-
skipFeeEnforcement: true,
|
|
383
|
-
}),
|
|
546
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
384
547
|
new TestDateProvider(),
|
|
548
|
+
undefined,
|
|
549
|
+
createLogger('simulator:public-processor', bindings),
|
|
385
550
|
);
|
|
386
551
|
|
|
387
552
|
const tx = await Tx.create({
|
|
@@ -406,7 +571,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
406
571
|
} else if (!processedTx.revertCode.isOK()) {
|
|
407
572
|
if (processedTx.revertReason) {
|
|
408
573
|
try {
|
|
409
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
574
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
410
575
|
// eslint-disable-next-line no-empty
|
|
411
576
|
} catch {}
|
|
412
577
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -415,11 +580,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
415
580
|
}
|
|
416
581
|
}
|
|
417
582
|
|
|
583
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
584
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
585
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
586
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
587
|
+
const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
|
|
588
|
+
|
|
418
589
|
if (isStaticCall) {
|
|
419
590
|
await checkpoint!.revert();
|
|
420
591
|
|
|
421
592
|
await forkedWorldTrees.close();
|
|
422
|
-
return executionResult.returnValues ?? [];
|
|
593
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
423
594
|
}
|
|
424
595
|
|
|
425
596
|
const txEffect = TxEffect.empty();
|
|
@@ -435,42 +606,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
435
606
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
436
607
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
437
608
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
const l2Block = new L2Block(
|
|
441
|
-
makeAppendOnlyTreeSnapshot(),
|
|
442
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
443
|
-
body,
|
|
444
|
-
);
|
|
609
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
445
610
|
|
|
446
611
|
await this.stateMachine.handleL2Block(l2Block);
|
|
447
612
|
|
|
448
613
|
await forkedWorldTrees.close();
|
|
449
614
|
|
|
450
|
-
return executionResult.returnValues ?? [];
|
|
615
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
451
616
|
}
|
|
452
617
|
|
|
453
|
-
async
|
|
454
|
-
from: AztecAddress,
|
|
618
|
+
async publicCallNewFlow(
|
|
619
|
+
from: AztecAddress | undefined,
|
|
455
620
|
targetContractAddress: AztecAddress,
|
|
456
621
|
calldata: Fr[],
|
|
457
622
|
isStaticCall: boolean,
|
|
623
|
+
gasSettings: GasSettings,
|
|
458
624
|
) {
|
|
459
625
|
this.logger.verbose(
|
|
460
|
-
`Executing public function ${await this.
|
|
626
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
461
627
|
);
|
|
462
628
|
|
|
463
|
-
const blockNumber = await this.
|
|
464
|
-
|
|
465
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
466
|
-
|
|
467
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
468
|
-
|
|
469
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
629
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
470
630
|
|
|
471
631
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
472
632
|
|
|
473
|
-
const anchorBlockHeader = await this.
|
|
633
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
474
634
|
|
|
475
635
|
const calldataHash = await computeCalldataHash(calldata);
|
|
476
636
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -484,28 +644,42 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
484
644
|
|
|
485
645
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
486
646
|
|
|
487
|
-
const
|
|
647
|
+
const bindings2 = this.logger.getBindings();
|
|
648
|
+
const contractsDB = new PublicContractsDB(
|
|
649
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
650
|
+
bindings2,
|
|
651
|
+
);
|
|
488
652
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
489
|
-
const
|
|
490
|
-
doMerkleOperations: true,
|
|
653
|
+
const config = PublicSimulatorConfig.from({
|
|
491
654
|
skipFeeEnforcement: true,
|
|
655
|
+
collectDebugLogs: true,
|
|
656
|
+
collectHints: false,
|
|
657
|
+
collectStatistics: false,
|
|
658
|
+
collectCallMetadata: true,
|
|
492
659
|
});
|
|
493
|
-
const
|
|
660
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
661
|
+
const processor = new PublicProcessor(
|
|
662
|
+
globals,
|
|
663
|
+
guardedMerkleTrees,
|
|
664
|
+
contractsDB,
|
|
665
|
+
simulator,
|
|
666
|
+
new TestDateProvider(),
|
|
667
|
+
undefined,
|
|
668
|
+
createLogger('simulator:public-processor', bindings2),
|
|
669
|
+
);
|
|
494
670
|
|
|
495
671
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
496
672
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
497
673
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
498
674
|
// unique.
|
|
499
675
|
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
500
|
-
|
|
501
|
-
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
502
|
-
}
|
|
676
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
503
677
|
|
|
504
678
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
505
679
|
// may require producing reverts.
|
|
506
680
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
507
681
|
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
|
|
508
|
-
from,
|
|
682
|
+
from ?? AztecAddress.NULL_MSG_SENDER,
|
|
509
683
|
targetContractAddress,
|
|
510
684
|
isStaticCall,
|
|
511
685
|
calldataHash,
|
|
@@ -523,7 +697,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
523
697
|
constantData,
|
|
524
698
|
/*gasUsed=*/ new Gas(0, 0),
|
|
525
699
|
/*feePayer=*/ AztecAddress.zero(),
|
|
526
|
-
/*
|
|
700
|
+
/*expirationTimestamp=*/ 0n,
|
|
527
701
|
inputsForPublic,
|
|
528
702
|
undefined,
|
|
529
703
|
);
|
|
@@ -550,7 +724,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
550
724
|
} else if (!processedTx.revertCode.isOK()) {
|
|
551
725
|
if (processedTx.revertReason) {
|
|
552
726
|
try {
|
|
553
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
727
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
554
728
|
// eslint-disable-next-line no-empty
|
|
555
729
|
} catch {}
|
|
556
730
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -582,13 +756,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
582
756
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
583
757
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
584
758
|
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
const l2Block = new L2Block(
|
|
588
|
-
makeAppendOnlyTreeSnapshot(),
|
|
589
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
590
|
-
body,
|
|
591
|
-
);
|
|
759
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
592
760
|
|
|
593
761
|
await this.stateMachine.handleL2Block(l2Block);
|
|
594
762
|
|
|
@@ -597,23 +765,52 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
597
765
|
return returnValues ?? [];
|
|
598
766
|
}
|
|
599
767
|
|
|
600
|
-
async
|
|
768
|
+
async executeUtilityFunction(
|
|
601
769
|
targetContractAddress: AztecAddress,
|
|
602
770
|
functionSelector: FunctionSelector,
|
|
603
771
|
args: Fr[],
|
|
772
|
+
jobId: string,
|
|
773
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
604
774
|
) {
|
|
605
|
-
const artifact = await this.
|
|
775
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
606
776
|
if (!artifact) {
|
|
607
777
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
608
778
|
}
|
|
609
779
|
|
|
610
|
-
|
|
780
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
781
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
782
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
783
|
+
targetContractAddress,
|
|
784
|
+
functionSelector,
|
|
785
|
+
async (call, execScopes) => {
|
|
786
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
787
|
+
},
|
|
788
|
+
blockHeader,
|
|
789
|
+
jobId,
|
|
790
|
+
await this.keyStore.getAccounts(),
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
const call = FunctionCall.from({
|
|
611
794
|
name: artifact.name,
|
|
612
|
-
selector: functionSelector,
|
|
613
795
|
to: targetContractAddress,
|
|
614
|
-
|
|
796
|
+
selector: functionSelector,
|
|
797
|
+
type: FunctionType.UTILITY,
|
|
798
|
+
hideMsgSender: false,
|
|
799
|
+
isStatic: false,
|
|
800
|
+
args,
|
|
801
|
+
returnTypes: [],
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
|
|
805
|
+
}
|
|
615
806
|
|
|
616
|
-
|
|
807
|
+
private async executeUtilityCall(
|
|
808
|
+
call: FunctionCall,
|
|
809
|
+
scopes: AztecAddress[],
|
|
810
|
+
jobId: string,
|
|
811
|
+
authorizedUtilityCallTargets: AztecAddress[] = [],
|
|
812
|
+
): Promise<Fr[]> {
|
|
813
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
617
814
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
618
815
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
619
816
|
}
|
|
@@ -624,9 +821,38 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
624
821
|
});
|
|
625
822
|
|
|
626
823
|
try {
|
|
627
|
-
const
|
|
628
|
-
const
|
|
629
|
-
|
|
824
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
825
|
+
const simulator = new WASMSimulator();
|
|
826
|
+
const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
|
|
827
|
+
await this.executeUtilityCall(syncCall, execScopes, jobId);
|
|
828
|
+
};
|
|
829
|
+
const oracle = new UtilityExecutionOracle({
|
|
830
|
+
contractAddress: call.to,
|
|
831
|
+
authWitnesses: [],
|
|
832
|
+
capsules: [],
|
|
833
|
+
anchorBlockHeader,
|
|
834
|
+
contractStore: this.contractStore,
|
|
835
|
+
noteStore: this.noteStore,
|
|
836
|
+
keyStore: this.keyStore,
|
|
837
|
+
addressStore: this.addressStore,
|
|
838
|
+
aztecNode: this.stateMachine.node,
|
|
839
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
840
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
841
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
842
|
+
privateEventStore: this.privateEventStore,
|
|
843
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
844
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
845
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
846
|
+
jobId,
|
|
847
|
+
scopes,
|
|
848
|
+
simulator,
|
|
849
|
+
hooks: composeHooks({
|
|
850
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
|
|
851
|
+
}),
|
|
852
|
+
utilityExecutor,
|
|
853
|
+
});
|
|
854
|
+
const acirExecutionResult = await simulator
|
|
855
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
630
856
|
.catch((err: Error) => {
|
|
631
857
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
632
858
|
throw new ExecutionError(
|
|
@@ -640,10 +866,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
640
866
|
);
|
|
641
867
|
});
|
|
642
868
|
|
|
643
|
-
this.logger.verbose(`Utility
|
|
869
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
644
870
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
645
871
|
} catch (err) {
|
|
646
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
872
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
647
873
|
}
|
|
648
874
|
}
|
|
649
875
|
|
|
@@ -652,7 +878,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
652
878
|
return [this.nextBlockTimestamp, this.authwits];
|
|
653
879
|
}
|
|
654
880
|
|
|
655
|
-
private async getLastBlockNumber(): Promise<
|
|
656
|
-
|
|
881
|
+
private async getLastBlockNumber(): Promise<BlockNumber> {
|
|
882
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
883
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
private buildAuthorizeUtilityCallHook(
|
|
887
|
+
callerContext: 'private' | 'private view' | 'utility',
|
|
888
|
+
authorizedTargets: AztecAddress[],
|
|
889
|
+
): ExecutionHooks['authorizeUtilityCall'] | undefined {
|
|
890
|
+
if (authorizedTargets.length === 0) {
|
|
891
|
+
return undefined;
|
|
892
|
+
}
|
|
893
|
+
return req =>
|
|
894
|
+
Promise.resolve({
|
|
895
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
|
|
896
|
+
});
|
|
657
897
|
}
|
|
658
898
|
}
|