@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.b8a057fa
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/AuthRegistry-HMC7WEOJ.js +3 -0
- package/dest/AuthRegistry-HMC7WEOJ.js.map +7 -0
- package/dest/ContractClassRegistry-TXCDCFNC.js +3 -0
- package/dest/ContractClassRegistry-TXCDCFNC.js.map +7 -0
- package/dest/ContractInstanceRegistry-2TZHWOTT.js +3 -0
- package/dest/ContractInstanceRegistry-2TZHWOTT.js.map +7 -0
- package/dest/FeeJuice-FDF3J2Q5.js +3 -0
- package/dest/FeeJuice-FDF3J2Q5.js.map +7 -0
- package/dest/HandshakeRegistry-C7JF4R54.js +3 -0
- package/dest/HandshakeRegistry-C7JF4R54.js.map +7 -0
- package/dest/MultiCallEntrypoint-IGLO227K.js +3 -0
- package/dest/MultiCallEntrypoint-IGLO227K.js.map +7 -0
- package/dest/SchnorrAccount-KCIHUCXS.js +3 -0
- package/dest/SchnorrAccount-KCIHUCXS.js.map +7 -0
- package/dest/SchnorrInitializerlessAccount-PVR6XUSN.js +3 -0
- package/dest/SchnorrInitializerlessAccount-PVR6XUSN.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-32UHX7YY.js +3 -0
- package/dest/chunk-32UHX7YY.js.map +7 -0
- package/dest/chunk-FRF5YZEO.js +304 -0
- package/dest/chunk-FRF5YZEO.js.map +7 -0
- package/dest/chunk-O57S6W5S.js +260 -0
- package/dest/chunk-O57S6W5S.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 +286 -0
- package/dest/index.d.ts +51 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +75 -158
- package/dest/metafile.json +38497 -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 +65 -31
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
- package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/default_fixtures.js +207 -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 +32 -0
- package/dest/oracle/test-resolver/resolver.d.ts +48 -0
- package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
- package/dest/oracle/test-resolver/resolver.js +181 -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 +69 -23
- package/dest/oracle/txe_oracle_registry.d.ts +169 -0
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_registry.js +745 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +66 -30
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +630 -275
- 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 +112 -213
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +877 -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 +76 -99
- package/dest/state_machine/dummy_p2p_client.d.ts +31 -15
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +63 -22
- package/dest/state_machine/global_variable_builder.d.ts +10 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +20 -5
- package/dest/state_machine/index.d.ts +14 -8
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +84 -27
- 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 +15 -6
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +27 -13
- package/dest/txe_session.d.ts +102 -21
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +440 -76
- package/dest/utils/block_creation.d.ts +22 -7
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +40 -6
- package/dest/utils/encoding.d.ts +192 -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 +3 -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 +51 -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 +317 -0
- package/src/index.ts +113 -201
- package/src/msgpackr_fr_extension.ts +23 -0
- package/src/oracle/interfaces.ts +68 -36
- package/src/oracle/test-resolver/default_fixtures.ts +282 -0
- package/src/oracle/test-resolver/index.ts +44 -0
- package/src/oracle/test-resolver/resolver.ts +245 -0
- package/src/oracle/txe_oracle_public_context.ts +83 -28
- package/src/oracle/txe_oracle_registry.ts +536 -0
- package/src/oracle/txe_oracle_top_level_context.ts +539 -199
- 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 +1086 -909
- package/src/state_machine/archiver.ts +82 -115
- package/src/state_machine/dummy_p2p_client.ts +96 -33
- package/src/state_machine/global_variable_builder.ts +28 -9
- package/src/state_machine/index.ts +118 -44
- package/src/state_machine/mock_epoch_cache.ts +63 -23
- package/src/state_machine/synchronizer.ts +36 -14
- package/src/txe_session.ts +719 -125
- package/src/utils/block_creation.ts +51 -15
- package/src/{util → utils}/encoding.ts +9 -3
- package/src/utils/tx_effect_creation.ts +4 -13
- 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 +60 -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,30 +1,45 @@
|
|
|
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';
|
|
9
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
11
10
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
12
11
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
13
12
|
import type { KeyStore } from '@aztec/key-store';
|
|
14
13
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
AddressStore,
|
|
15
|
+
AnchoredContractData,
|
|
16
|
+
CapsuleService,
|
|
17
|
+
CapsuleStore,
|
|
18
|
+
type ContractStore,
|
|
19
|
+
type ExecutionHooks,
|
|
20
|
+
FactService,
|
|
21
|
+
FactStore,
|
|
22
|
+
NoteStore,
|
|
23
|
+
ORACLE_VERSION_MAJOR,
|
|
24
|
+
PrivateEventStore,
|
|
25
|
+
RecipientTaggingStore,
|
|
26
|
+
SenderTaggingStore,
|
|
27
|
+
TaggingSecretSourcesStore,
|
|
28
|
+
type TaggingSecretStrategy,
|
|
29
|
+
composeHooks,
|
|
18
30
|
enrichPublicSimulationError,
|
|
19
31
|
} from '@aztec/pxe/server';
|
|
20
32
|
import {
|
|
33
|
+
CONTRACT_INSTANCE,
|
|
21
34
|
ExecutionNoteCache,
|
|
22
35
|
ExecutionTaggingIndexCache,
|
|
23
36
|
HashedValuesCache,
|
|
24
37
|
type IMiscOracle,
|
|
25
|
-
|
|
38
|
+
type Option,
|
|
26
39
|
PrivateExecutionOracle,
|
|
40
|
+
TransientArrayService,
|
|
27
41
|
UtilityExecutionOracle,
|
|
42
|
+
buildACIRCallback,
|
|
28
43
|
executePrivateFunction,
|
|
29
44
|
generateSimulatedProvingResult,
|
|
30
45
|
} from '@aztec/pxe/simulator';
|
|
@@ -43,21 +58,24 @@ import {
|
|
|
43
58
|
PublicProcessor,
|
|
44
59
|
PublicTxSimulator,
|
|
45
60
|
} from '@aztec/simulator/server';
|
|
46
|
-
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
61
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
47
62
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
63
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
48
64
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
49
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
50
65
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
51
66
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
52
|
-
import { computeCalldataHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
67
|
+
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
53
68
|
import {
|
|
54
69
|
PartialPrivateTailPublicInputsForPublic,
|
|
55
70
|
PrivateKernelTailCircuitPublicInputs,
|
|
56
71
|
PrivateToPublicAccumulatedData,
|
|
57
72
|
PublicCallRequest,
|
|
58
73
|
} from '@aztec/stdlib/kernel';
|
|
74
|
+
import { deriveKeys, hashPublicKey } from '@aztec/stdlib/keys';
|
|
75
|
+
import type { PrivateLog } from '@aztec/stdlib/logs';
|
|
76
|
+
import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/stdlib/messaging';
|
|
59
77
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
60
|
-
import {
|
|
78
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
61
79
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
62
80
|
import {
|
|
63
81
|
CallContext,
|
|
@@ -72,17 +90,14 @@ import {
|
|
|
72
90
|
collectNested,
|
|
73
91
|
} from '@aztec/stdlib/tx';
|
|
74
92
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
75
|
-
import { ForkCheckpoint } from '@aztec/world-state';
|
|
93
|
+
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
76
94
|
|
|
95
|
+
import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
|
|
77
96
|
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';
|
|
97
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
98
|
+
import type { TXEAccountStore } from '../utils/txe_account_store.js';
|
|
99
|
+
import type { TXEArtifactResolver } from '../utils/txe_artifact_resolver.js';
|
|
100
|
+
import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
|
|
86
101
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
87
102
|
|
|
88
103
|
export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
|
|
@@ -93,58 +108,86 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
93
108
|
|
|
94
109
|
constructor(
|
|
95
110
|
private stateMachine: TXEStateMachine,
|
|
96
|
-
private
|
|
111
|
+
private contractStore: ContractStore,
|
|
112
|
+
private noteStore: NoteStore,
|
|
97
113
|
private keyStore: KeyStore,
|
|
98
|
-
private
|
|
99
|
-
private
|
|
100
|
-
private
|
|
114
|
+
private addressStore: AddressStore,
|
|
115
|
+
private accountStore: TXEAccountStore,
|
|
116
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
117
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
118
|
+
private taggingSecretSourcesStore: TaggingSecretSourcesStore,
|
|
119
|
+
private capsuleStore: CapsuleStore,
|
|
120
|
+
private factStore: FactStore,
|
|
121
|
+
private privateEventStore: PrivateEventStore,
|
|
101
122
|
private nextBlockTimestamp: bigint,
|
|
102
123
|
private version: Fr,
|
|
103
124
|
private chainId: Fr,
|
|
104
125
|
private authwits: Map<string, AuthWitness>,
|
|
126
|
+
private taggingSecretStrategy: TaggingSecretStrategy | undefined,
|
|
127
|
+
private readonly artifactResolver: TXEArtifactResolver,
|
|
128
|
+
private readonly rootPath: string,
|
|
129
|
+
private readonly packageName: string,
|
|
105
130
|
) {
|
|
106
131
|
this.logger = createLogger('txe:top_level_context');
|
|
107
132
|
this.logger.debug('Entering Top Level Context');
|
|
108
133
|
}
|
|
109
134
|
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
136
|
+
|
|
137
|
+
assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
138
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
139
|
+
const hint =
|
|
140
|
+
major > ORACLE_VERSION_MAJOR
|
|
141
|
+
? '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.'
|
|
142
|
+
: '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
143
|
throw new Error(
|
|
113
|
-
`Incompatible
|
|
144
|
+
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
114
145
|
);
|
|
115
146
|
}
|
|
147
|
+
this.contractOracleVersion = { major, minor };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
151
|
+
nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
152
|
+
return this.contractOracleVersion;
|
|
116
153
|
}
|
|
117
154
|
|
|
118
155
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
119
156
|
// setup.
|
|
120
|
-
|
|
157
|
+
getRandomField(): Fr {
|
|
121
158
|
return Fr.random();
|
|
122
159
|
}
|
|
123
160
|
|
|
124
161
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
125
|
-
|
|
162
|
+
log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
|
|
126
163
|
if (!LogLevels[level]) {
|
|
127
|
-
throw new Error(`Invalid
|
|
164
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
128
165
|
}
|
|
129
166
|
const levelName = LogLevels[level];
|
|
130
167
|
|
|
131
168
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
169
|
+
return Promise.resolve();
|
|
132
170
|
}
|
|
133
171
|
|
|
134
|
-
|
|
135
|
-
return
|
|
172
|
+
getDefaultAddress(): AztecAddress {
|
|
173
|
+
return DEFAULT_ADDRESS;
|
|
136
174
|
}
|
|
137
175
|
|
|
138
|
-
|
|
176
|
+
async getNextBlockNumber(): Promise<BlockNumber> {
|
|
177
|
+
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
getNextBlockTimestamp(): Promise<bigint> {
|
|
139
181
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
140
182
|
}
|
|
141
183
|
|
|
142
|
-
async
|
|
143
|
-
return (await this.stateMachine.node.
|
|
184
|
+
async getLastBlockTimestamp() {
|
|
185
|
+
return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
|
|
144
186
|
}
|
|
145
187
|
|
|
146
|
-
async
|
|
147
|
-
const
|
|
188
|
+
async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
|
|
189
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
190
|
+
const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
|
|
148
191
|
|
|
149
192
|
if (block!.body.txEffects.length != 1) {
|
|
150
193
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -153,10 +196,59 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
153
196
|
|
|
154
197
|
const txEffects = block!.body.txEffects[0];
|
|
155
198
|
|
|
156
|
-
|
|
199
|
+
const privateLogs = txEffects.privateLogs;
|
|
200
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
201
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
txHash: txEffects.txHash,
|
|
206
|
+
noteHashes: txEffects.noteHashes,
|
|
207
|
+
nullifiers: txEffects.nullifiers,
|
|
208
|
+
privateLogs,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
213
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
214
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
219
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
220
|
+
contractAddress,
|
|
221
|
+
null,
|
|
222
|
+
async (call, execScopes) => {
|
|
223
|
+
await this.executeUtilityCall(call, { scopes: execScopes, jobId });
|
|
224
|
+
},
|
|
225
|
+
blockHeader,
|
|
226
|
+
jobId,
|
|
227
|
+
[scope],
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
232
|
+
const events = (
|
|
233
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
234
|
+
contractAddress,
|
|
235
|
+
scopes: [scope],
|
|
236
|
+
fromBlock: 0,
|
|
237
|
+
toBlock: (await this.getLastBlockNumber()) + 1,
|
|
238
|
+
})
|
|
239
|
+
).map(e => e.packedEvent);
|
|
240
|
+
|
|
241
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
242
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
243
|
+
}
|
|
244
|
+
if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
|
|
245
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return events;
|
|
157
249
|
}
|
|
158
250
|
|
|
159
|
-
async
|
|
251
|
+
async advanceBlocksBy(blocks: number) {
|
|
160
252
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
161
253
|
|
|
162
254
|
for (let i = 0; i < blocks; i++) {
|
|
@@ -164,112 +256,179 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
164
256
|
}
|
|
165
257
|
}
|
|
166
258
|
|
|
167
|
-
|
|
259
|
+
advanceTimestampBy(duration: UInt64) {
|
|
168
260
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
169
261
|
this.nextBlockTimestamp += duration;
|
|
170
262
|
}
|
|
171
263
|
|
|
172
|
-
|
|
264
|
+
private deploymentNullifier(address: AztecAddress): Promise<Fr> {
|
|
265
|
+
return siloNullifier(AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async deploy(
|
|
269
|
+
contractPath: string,
|
|
270
|
+
initializer: string,
|
|
271
|
+
args: Fr[],
|
|
272
|
+
secret: Fr,
|
|
273
|
+
salt: Fr,
|
|
274
|
+
deployer: AztecAddress,
|
|
275
|
+
): Promise<Fr[]> {
|
|
276
|
+
const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
|
|
277
|
+
rootPath: this.rootPath,
|
|
278
|
+
packageName: this.packageName,
|
|
279
|
+
contractPath,
|
|
280
|
+
initializer,
|
|
281
|
+
args,
|
|
282
|
+
secret,
|
|
283
|
+
salt,
|
|
284
|
+
deployer,
|
|
285
|
+
});
|
|
286
|
+
|
|
173
287
|
// Emit deployment nullifier
|
|
174
288
|
await this.mineBlock({
|
|
175
|
-
nullifiers: [
|
|
176
|
-
await siloNullifier(
|
|
177
|
-
AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
|
|
178
|
-
instance.address.toField(),
|
|
179
|
-
),
|
|
180
|
-
],
|
|
289
|
+
nullifiers: [await this.deploymentNullifier(instance.address)],
|
|
181
290
|
});
|
|
182
291
|
|
|
183
292
|
if (!secret.equals(Fr.ZERO)) {
|
|
184
|
-
await this.
|
|
293
|
+
await this.registerContractAndAddAccount(artifact, instance, secret);
|
|
185
294
|
} else {
|
|
186
|
-
await this.
|
|
187
|
-
await this.
|
|
295
|
+
await this.contractStore.addContractInstance(instance);
|
|
296
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
188
297
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
189
298
|
}
|
|
299
|
+
|
|
300
|
+
return CONTRACT_INSTANCE.serialization!.fn(instance).flat();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
|
|
305
|
+
*/
|
|
306
|
+
async mineDeploymentNullifiers(addresses: AztecAddress[]) {
|
|
307
|
+
await this.mineBlock({
|
|
308
|
+
nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async addAccount(secret: Fr) {
|
|
313
|
+
const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
|
|
314
|
+
return this.registerContractAndAddAccount(artifact, instance, secret);
|
|
190
315
|
}
|
|
191
316
|
|
|
192
|
-
async
|
|
317
|
+
private async registerContractAndAddAccount(
|
|
318
|
+
artifact: ContractArtifact,
|
|
319
|
+
instance: ContractInstanceWithAddress,
|
|
320
|
+
secret: Fr,
|
|
321
|
+
) {
|
|
193
322
|
const partialAddress = await computePartialAddress(instance);
|
|
194
323
|
|
|
195
324
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
196
|
-
await this.
|
|
197
|
-
await this.
|
|
325
|
+
await this.contractStore.addContractInstance(instance);
|
|
326
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
198
327
|
|
|
199
|
-
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
200
|
-
await this.
|
|
201
|
-
await this.
|
|
328
|
+
const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
|
|
329
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
330
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
202
331
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
203
332
|
|
|
204
333
|
return completeAddress;
|
|
205
334
|
}
|
|
206
335
|
|
|
207
|
-
async
|
|
208
|
-
// This is a
|
|
209
|
-
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
210
|
-
await this.
|
|
211
|
-
await this.
|
|
336
|
+
async createAccount(secret: Fr) {
|
|
337
|
+
// This is a foot gun !
|
|
338
|
+
const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), secret);
|
|
339
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
340
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
212
341
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
213
342
|
|
|
214
343
|
return completeAddress;
|
|
215
344
|
}
|
|
216
345
|
|
|
217
|
-
async
|
|
218
|
-
const account = await this.
|
|
219
|
-
const
|
|
346
|
+
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
347
|
+
const account = await this.accountStore.getAccount(address);
|
|
348
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
349
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
220
350
|
|
|
221
351
|
const schnorr = new Schnorr();
|
|
222
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
352
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
223
353
|
|
|
224
|
-
const authWitness = new AuthWitness(messageHash,
|
|
354
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
225
355
|
|
|
226
356
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
227
357
|
}
|
|
228
358
|
|
|
229
|
-
|
|
230
|
-
|
|
359
|
+
setTaggingSecretStrategy(strategy: Option<TaggingSecretStrategy>): void {
|
|
360
|
+
this.taggingSecretStrategy = strategy.value;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
async sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr> {
|
|
364
|
+
// Messages are appended to the tree, so the next free slot is simply the current tree size.
|
|
365
|
+
const { size } = await this.stateMachine.synchronizer
|
|
366
|
+
.getCommitted()
|
|
367
|
+
.getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
|
|
368
|
+
const leafIndex = new Fr(size);
|
|
369
|
+
|
|
370
|
+
const message = new L1ToL2Message(
|
|
371
|
+
new L1Actor(sender, this.chainId.toNumber()),
|
|
372
|
+
new L2Actor(recipient, this.version.toNumber()),
|
|
373
|
+
content,
|
|
374
|
+
secretHash,
|
|
375
|
+
leafIndex,
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
await this.mineBlock({ l1ToL2Messages: [message.hash()] });
|
|
379
|
+
|
|
380
|
+
return leafIndex;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async mineBlock(options: { nullifiers?: Fr[]; l1ToL2Messages?: Fr[] } = {}) {
|
|
384
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
231
385
|
|
|
232
386
|
const txEffect = TxEffect.empty();
|
|
233
387
|
txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
|
|
234
388
|
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
235
389
|
|
|
236
390
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
237
|
-
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
238
|
-
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
version: this.version,
|
|
247
|
-
chainId: this.chainId,
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
250
|
-
new Body([txEffect]),
|
|
251
|
-
);
|
|
391
|
+
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
|
|
392
|
+
|
|
393
|
+
const globals = makeGlobalVariables(undefined, {
|
|
394
|
+
blockNumber,
|
|
395
|
+
timestamp: this.nextBlockTimestamp,
|
|
396
|
+
version: this.version,
|
|
397
|
+
chainId: this.chainId,
|
|
398
|
+
});
|
|
399
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
252
400
|
|
|
253
401
|
await forkedWorldTrees.close();
|
|
254
402
|
|
|
255
403
|
this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
|
|
256
404
|
|
|
257
|
-
await this.stateMachine.handleL2Block(block);
|
|
405
|
+
await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
|
|
258
406
|
}
|
|
259
407
|
|
|
260
|
-
async
|
|
261
|
-
from: AztecAddress,
|
|
408
|
+
async privateCallNewFlow(
|
|
409
|
+
from: AztecAddress | undefined,
|
|
262
410
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
263
411
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
264
412
|
args: Fr[],
|
|
265
413
|
argsHash: Fr = Fr.zero(),
|
|
266
414
|
isStaticCall: boolean = false,
|
|
415
|
+
additionalScopes: AztecAddress[] = [],
|
|
416
|
+
jobId: string,
|
|
417
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
418
|
+
gasSettings: GasSettings,
|
|
267
419
|
) {
|
|
420
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
421
|
+
const anchoredContractData = new AnchoredContractData(
|
|
422
|
+
this.contractStore,
|
|
423
|
+
this.stateMachine.contractClassService,
|
|
424
|
+
blockHeader,
|
|
425
|
+
);
|
|
426
|
+
|
|
268
427
|
this.logger.verbose(
|
|
269
|
-
`Executing external function ${await
|
|
428
|
+
`Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
270
429
|
);
|
|
271
430
|
|
|
272
|
-
const artifact = await
|
|
431
|
+
const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
273
432
|
if (!artifact) {
|
|
274
433
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
275
434
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -277,51 +436,87 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
277
436
|
throw new Error(message);
|
|
278
437
|
}
|
|
279
438
|
|
|
280
|
-
const
|
|
439
|
+
const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
|
|
281
440
|
|
|
282
|
-
|
|
441
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
442
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
|
|
443
|
+
await this.executeUtilityCall(call, { scopes: execScopes, jobId });
|
|
444
|
+
};
|
|
283
445
|
|
|
284
|
-
|
|
446
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
447
|
+
targetContractAddress,
|
|
448
|
+
functionSelector,
|
|
449
|
+
utilityExecutor,
|
|
450
|
+
blockHeader,
|
|
451
|
+
jobId,
|
|
452
|
+
scopes,
|
|
453
|
+
);
|
|
285
454
|
|
|
286
|
-
const
|
|
455
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
287
456
|
|
|
288
|
-
const
|
|
457
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
458
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
289
459
|
|
|
290
460
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
291
461
|
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
462
|
+
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
463
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
464
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
465
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
466
|
+
// marking all side effects as revertible.
|
|
467
|
+
const minRevertibleSideEffectCounter = 1;
|
|
468
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
296
469
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
297
470
|
|
|
298
471
|
const simulator = new WASMSimulator();
|
|
299
472
|
|
|
300
|
-
const
|
|
473
|
+
const transientArrayService = new TransientArrayService();
|
|
474
|
+
const taggingSecretStrategy = this.taggingSecretStrategy;
|
|
475
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
301
476
|
argsHash,
|
|
302
477
|
txContext,
|
|
478
|
+
txRequestSalt: Fr.ZERO,
|
|
303
479
|
callContext,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
[],
|
|
310
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
480
|
+
anchorBlockHeader: blockHeader,
|
|
481
|
+
utilityExecutor,
|
|
482
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
483
|
+
capsules: [],
|
|
484
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
311
485
|
noteCache,
|
|
312
486
|
taggingIndexCache,
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
487
|
+
anchoredContractData,
|
|
488
|
+
noteStore: this.noteStore,
|
|
489
|
+
keyStore: this.keyStore,
|
|
490
|
+
addressStore: this.addressStore,
|
|
491
|
+
aztecNode: this.stateMachine.node,
|
|
492
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
493
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
494
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
495
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
496
|
+
factService: new FactService(this.factStore, scopes),
|
|
497
|
+
privateEventStore: this.privateEventStore,
|
|
498
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
499
|
+
jobId,
|
|
500
|
+
totalPublicCalldataCount: 0,
|
|
501
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
502
|
+
scopes,
|
|
503
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
504
|
+
// contract would perform, including setting senderForTags.
|
|
505
|
+
senderForTags: from,
|
|
323
506
|
simulator,
|
|
324
|
-
|
|
507
|
+
txResolver: this.stateMachine.txResolver,
|
|
508
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
509
|
+
hooks: composeHooks({
|
|
510
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
|
|
511
|
+
isStaticCall ? 'private view' : 'private',
|
|
512
|
+
authorizedUtilityCallTargets,
|
|
513
|
+
),
|
|
514
|
+
// Only configure the hook when a strategy was explicitly set, so that otherwise the default tagging secret
|
|
515
|
+
// strategy is exercised.
|
|
516
|
+
resolveTaggingSecretStrategy: taggingSecretStrategy ? () => Promise.resolve(taggingSecretStrategy) : undefined,
|
|
517
|
+
}),
|
|
518
|
+
transientArrayService,
|
|
519
|
+
});
|
|
325
520
|
|
|
326
521
|
// 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
522
|
let result: PrivateExecutionResult;
|
|
@@ -343,24 +538,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
343
538
|
);
|
|
344
539
|
const publicFunctionsCalldata = await Promise.all(
|
|
345
540
|
publicCallRequests.map(async r => {
|
|
346
|
-
const calldata = await privateExecutionOracle.
|
|
541
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
347
542
|
return new HashedValues(calldata, r.calldataHash);
|
|
348
543
|
}),
|
|
349
544
|
);
|
|
350
545
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
// must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
|
|
354
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
546
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
547
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
355
548
|
} catch (err) {
|
|
356
549
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
357
550
|
}
|
|
358
551
|
|
|
359
|
-
// According to the protocol rules,
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
const
|
|
363
|
-
|
|
552
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
553
|
+
// the nonce generator for the note hashes.
|
|
554
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
555
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
556
|
+
result,
|
|
557
|
+
(addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
|
|
558
|
+
this.stateMachine.node,
|
|
559
|
+
minRevertibleSideEffectCounter,
|
|
560
|
+
);
|
|
364
561
|
|
|
365
562
|
const globals = makeGlobalVariables();
|
|
366
563
|
globals.blockNumber = blockNumber;
|
|
@@ -369,19 +566,38 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
369
566
|
globals.version = this.version;
|
|
370
567
|
globals.gasFees = GasFees.empty();
|
|
371
568
|
|
|
372
|
-
|
|
569
|
+
await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
373
570
|
|
|
374
|
-
const
|
|
571
|
+
const bindings = this.logger.getBindings();
|
|
572
|
+
const contractsDB = new PublicContractsDB(
|
|
573
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
574
|
+
bindings,
|
|
575
|
+
);
|
|
375
576
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
577
|
+
const config = PublicSimulatorConfig.from({
|
|
578
|
+
skipFeeEnforcement: true,
|
|
579
|
+
collectDebugLogs: true,
|
|
580
|
+
collectHints: false,
|
|
581
|
+
collectStatistics: false,
|
|
582
|
+
collectCallMetadata: true,
|
|
583
|
+
});
|
|
584
|
+
// The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
|
|
585
|
+
const forkId = forkedWorldTrees.getRevision().forkId;
|
|
376
586
|
const processor = new PublicProcessor(
|
|
377
587
|
globals,
|
|
378
588
|
guardedMerkleTrees,
|
|
379
589
|
contractsDB,
|
|
380
|
-
new PublicTxSimulator(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
590
|
+
new PublicTxSimulator(
|
|
591
|
+
this.stateMachine.synchronizer.avmSimulator,
|
|
592
|
+
globals,
|
|
593
|
+
contractsDB,
|
|
594
|
+
forkId,
|
|
595
|
+
config,
|
|
596
|
+
bindings,
|
|
597
|
+
),
|
|
384
598
|
new TestDateProvider(),
|
|
599
|
+
undefined,
|
|
600
|
+
createLogger('simulator:public-processor', bindings),
|
|
385
601
|
);
|
|
386
602
|
|
|
387
603
|
const tx = await Tx.create({
|
|
@@ -406,7 +622,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
406
622
|
} else if (!processedTx.revertCode.isOK()) {
|
|
407
623
|
if (processedTx.revertReason) {
|
|
408
624
|
try {
|
|
409
|
-
await enrichPublicSimulationError(
|
|
625
|
+
await enrichPublicSimulationError(
|
|
626
|
+
processedTx.revertReason,
|
|
627
|
+
this.contractStore,
|
|
628
|
+
this.stateMachine.contractClassService,
|
|
629
|
+
await this.stateMachine.anchorBlockStore.getBlockHeader(),
|
|
630
|
+
this.logger,
|
|
631
|
+
);
|
|
410
632
|
// eslint-disable-next-line no-empty
|
|
411
633
|
} catch {}
|
|
412
634
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -415,11 +637,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
415
637
|
}
|
|
416
638
|
}
|
|
417
639
|
|
|
640
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
641
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
642
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
643
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
644
|
+
const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
|
|
645
|
+
|
|
418
646
|
if (isStaticCall) {
|
|
419
647
|
await checkpoint!.revert();
|
|
420
|
-
|
|
421
|
-
await forkedWorldTrees.close();
|
|
422
|
-
return executionResult.returnValues ?? [];
|
|
648
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
423
649
|
}
|
|
424
650
|
|
|
425
651
|
const txEffect = TxEffect.empty();
|
|
@@ -435,43 +661,35 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
435
661
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
436
662
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
437
663
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
const l2Block = new L2Block(
|
|
441
|
-
makeAppendOnlyTreeSnapshot(),
|
|
442
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
443
|
-
body,
|
|
444
|
-
);
|
|
664
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
445
665
|
|
|
446
666
|
await this.stateMachine.handleL2Block(l2Block);
|
|
447
667
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return executionResult.returnValues ?? [];
|
|
668
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
451
669
|
}
|
|
452
670
|
|
|
453
|
-
async
|
|
454
|
-
from: AztecAddress,
|
|
671
|
+
async publicCallNewFlow(
|
|
672
|
+
from: AztecAddress | undefined,
|
|
455
673
|
targetContractAddress: AztecAddress,
|
|
456
674
|
calldata: Fr[],
|
|
457
675
|
isStaticCall: boolean,
|
|
676
|
+
gasSettings: GasSettings,
|
|
458
677
|
) {
|
|
459
|
-
this.
|
|
460
|
-
|
|
678
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
679
|
+
const anchoredContractData = new AnchoredContractData(
|
|
680
|
+
this.contractStore,
|
|
681
|
+
this.stateMachine.contractClassService,
|
|
682
|
+
anchorBlockHeader,
|
|
461
683
|
);
|
|
462
684
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
685
|
+
this.logger.verbose(
|
|
686
|
+
`Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
687
|
+
);
|
|
468
688
|
|
|
469
|
-
const
|
|
689
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
470
690
|
|
|
471
691
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
472
692
|
|
|
473
|
-
const anchorBlockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
|
|
474
|
-
|
|
475
693
|
const calldataHash = await computeCalldataHash(calldata);
|
|
476
694
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
477
695
|
|
|
@@ -482,30 +700,53 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
482
700
|
globals.version = this.version;
|
|
483
701
|
globals.gasFees = GasFees.empty();
|
|
484
702
|
|
|
485
|
-
|
|
703
|
+
await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
486
704
|
|
|
487
|
-
const
|
|
705
|
+
const bindings2 = this.logger.getBindings();
|
|
706
|
+
const contractsDB = new PublicContractsDB(
|
|
707
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
708
|
+
bindings2,
|
|
709
|
+
);
|
|
488
710
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
489
|
-
const
|
|
490
|
-
doMerkleOperations: true,
|
|
711
|
+
const config = PublicSimulatorConfig.from({
|
|
491
712
|
skipFeeEnforcement: true,
|
|
713
|
+
collectDebugLogs: true,
|
|
714
|
+
collectHints: false,
|
|
715
|
+
collectStatistics: false,
|
|
716
|
+
collectCallMetadata: true,
|
|
492
717
|
});
|
|
493
|
-
|
|
718
|
+
// The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
|
|
719
|
+
const forkId2 = forkedWorldTrees.getRevision().forkId;
|
|
720
|
+
const simulator = new PublicTxSimulator(
|
|
721
|
+
this.stateMachine.synchronizer.avmSimulator,
|
|
722
|
+
globals,
|
|
723
|
+
contractsDB,
|
|
724
|
+
forkId2,
|
|
725
|
+
config,
|
|
726
|
+
bindings2,
|
|
727
|
+
);
|
|
728
|
+
const processor = new PublicProcessor(
|
|
729
|
+
globals,
|
|
730
|
+
guardedMerkleTrees,
|
|
731
|
+
contractsDB,
|
|
732
|
+
simulator,
|
|
733
|
+
new TestDateProvider(),
|
|
734
|
+
undefined,
|
|
735
|
+
createLogger('simulator:public-processor', bindings2),
|
|
736
|
+
);
|
|
494
737
|
|
|
495
738
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
496
739
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
497
740
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
498
741
|
// unique.
|
|
499
742
|
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
500
|
-
|
|
501
|
-
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
502
|
-
}
|
|
743
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
503
744
|
|
|
504
745
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
505
746
|
// may require producing reverts.
|
|
506
747
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
507
748
|
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
|
|
508
|
-
from,
|
|
749
|
+
from ?? AztecAddress.NULL_MSG_SENDER,
|
|
509
750
|
targetContractAddress,
|
|
510
751
|
isStaticCall,
|
|
511
752
|
calldataHash,
|
|
@@ -523,7 +764,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
523
764
|
constantData,
|
|
524
765
|
/*gasUsed=*/ new Gas(0, 0),
|
|
525
766
|
/*feePayer=*/ AztecAddress.zero(),
|
|
526
|
-
/*
|
|
767
|
+
/*expirationTimestamp=*/ 0n,
|
|
527
768
|
inputsForPublic,
|
|
528
769
|
undefined,
|
|
529
770
|
);
|
|
@@ -550,7 +791,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
550
791
|
} else if (!processedTx.revertCode.isOK()) {
|
|
551
792
|
if (processedTx.revertReason) {
|
|
552
793
|
try {
|
|
553
|
-
await enrichPublicSimulationError(
|
|
794
|
+
await enrichPublicSimulationError(
|
|
795
|
+
processedTx.revertReason,
|
|
796
|
+
this.contractStore,
|
|
797
|
+
this.stateMachine.contractClassService,
|
|
798
|
+
anchorBlockHeader,
|
|
799
|
+
this.logger,
|
|
800
|
+
);
|
|
554
801
|
// eslint-disable-next-line no-empty
|
|
555
802
|
} catch {}
|
|
556
803
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -563,9 +810,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
563
810
|
|
|
564
811
|
if (isStaticCall) {
|
|
565
812
|
await checkpoint!.revert();
|
|
566
|
-
|
|
567
|
-
await forkedWorldTrees.close();
|
|
568
|
-
|
|
569
813
|
return returnValues ?? [];
|
|
570
814
|
}
|
|
571
815
|
|
|
@@ -582,38 +826,84 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
582
826
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
583
827
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
584
828
|
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
const l2Block = new L2Block(
|
|
588
|
-
makeAppendOnlyTreeSnapshot(),
|
|
589
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
590
|
-
body,
|
|
591
|
-
);
|
|
829
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
592
830
|
|
|
593
831
|
await this.stateMachine.handleL2Block(l2Block);
|
|
594
832
|
|
|
595
|
-
await forkedWorldTrees.close();
|
|
596
|
-
|
|
597
833
|
return returnValues ?? [];
|
|
598
834
|
}
|
|
599
835
|
|
|
600
|
-
async
|
|
836
|
+
async executeUtilityFunction(
|
|
837
|
+
from: AztecAddress | undefined,
|
|
601
838
|
targetContractAddress: AztecAddress,
|
|
602
839
|
functionSelector: FunctionSelector,
|
|
603
840
|
args: Fr[],
|
|
841
|
+
jobId: string,
|
|
842
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
604
843
|
) {
|
|
605
|
-
const
|
|
844
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
845
|
+
const anchoredContractData = new AnchoredContractData(
|
|
846
|
+
this.contractStore,
|
|
847
|
+
this.stateMachine.contractClassService,
|
|
848
|
+
blockHeader,
|
|
849
|
+
);
|
|
850
|
+
|
|
851
|
+
const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
606
852
|
if (!artifact) {
|
|
607
853
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
608
854
|
}
|
|
609
855
|
|
|
610
|
-
|
|
856
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
857
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
858
|
+
targetContractAddress,
|
|
859
|
+
functionSelector,
|
|
860
|
+
async (call, execScopes) => {
|
|
861
|
+
await this.executeUtilityCall(call, { scopes: execScopes, jobId });
|
|
862
|
+
},
|
|
863
|
+
blockHeader,
|
|
864
|
+
jobId,
|
|
865
|
+
await this.keyStore.getAccounts(),
|
|
866
|
+
);
|
|
867
|
+
|
|
868
|
+
const call = FunctionCall.from({
|
|
611
869
|
name: artifact.name,
|
|
612
|
-
selector: functionSelector,
|
|
613
870
|
to: targetContractAddress,
|
|
614
|
-
|
|
871
|
+
selector: functionSelector,
|
|
872
|
+
type: FunctionType.UTILITY,
|
|
873
|
+
hideMsgSender: false,
|
|
874
|
+
isStatic: false,
|
|
875
|
+
args,
|
|
876
|
+
returnTypes: [],
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
return this.executeUtilityCall(call, {
|
|
880
|
+
from,
|
|
881
|
+
scopes: await this.keyStore.getAccounts(),
|
|
882
|
+
jobId,
|
|
883
|
+
authorizedUtilityCallTargets,
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
private async executeUtilityCall(
|
|
888
|
+
call: FunctionCall,
|
|
889
|
+
{
|
|
890
|
+
from = AztecAddress.NULL_MSG_SENDER,
|
|
891
|
+
scopes,
|
|
892
|
+
jobId,
|
|
893
|
+
authorizedUtilityCallTargets = [],
|
|
894
|
+
}: { from?: AztecAddress; scopes: AztecAddress[]; jobId: string; authorizedUtilityCallTargets?: AztecAddress[] },
|
|
895
|
+
): Promise<Fr[]> {
|
|
896
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
897
|
+
const anchoredContractData = new AnchoredContractData(
|
|
898
|
+
this.contractStore,
|
|
899
|
+
this.stateMachine.contractClassService,
|
|
900
|
+
anchorBlockHeader,
|
|
901
|
+
);
|
|
615
902
|
|
|
616
|
-
const entryPointArtifact = await
|
|
903
|
+
const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
904
|
+
if (!entryPointArtifact) {
|
|
905
|
+
throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
|
|
906
|
+
}
|
|
617
907
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
618
908
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
619
909
|
}
|
|
@@ -624,9 +914,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
624
914
|
});
|
|
625
915
|
|
|
626
916
|
try {
|
|
627
|
-
const
|
|
628
|
-
const
|
|
629
|
-
.
|
|
917
|
+
const simulator = new WASMSimulator();
|
|
918
|
+
const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
|
|
919
|
+
await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
|
|
920
|
+
};
|
|
921
|
+
const oracle = new UtilityExecutionOracle({
|
|
922
|
+
callContext: CallContext.from({
|
|
923
|
+
msgSender: from,
|
|
924
|
+
contractAddress: call.to,
|
|
925
|
+
functionSelector: call.selector,
|
|
926
|
+
isStaticCall: true,
|
|
927
|
+
}),
|
|
928
|
+
authWitnesses: [],
|
|
929
|
+
capsules: [],
|
|
930
|
+
anchorBlockHeader,
|
|
931
|
+
anchoredContractData,
|
|
932
|
+
noteStore: this.noteStore,
|
|
933
|
+
keyStore: this.keyStore,
|
|
934
|
+
addressStore: this.addressStore,
|
|
935
|
+
aztecNode: this.stateMachine.node,
|
|
936
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
937
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
938
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
939
|
+
factService: new FactService(this.factStore, scopes),
|
|
940
|
+
privateEventStore: this.privateEventStore,
|
|
941
|
+
txResolver: this.stateMachine.txResolver,
|
|
942
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
943
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
944
|
+
jobId,
|
|
945
|
+
scopes,
|
|
946
|
+
simulator,
|
|
947
|
+
hooks: composeHooks({
|
|
948
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
|
|
949
|
+
}),
|
|
950
|
+
utilityExecutor,
|
|
951
|
+
// Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
|
|
952
|
+
transientArrayService: new TransientArrayService(),
|
|
953
|
+
});
|
|
954
|
+
const acirExecutionResult = await simulator
|
|
955
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
|
|
630
956
|
.catch((err: Error) => {
|
|
631
957
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
632
958
|
throw new ExecutionError(
|
|
@@ -640,19 +966,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
640
966
|
);
|
|
641
967
|
});
|
|
642
968
|
|
|
643
|
-
this.logger.verbose(`Utility
|
|
969
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
644
970
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
645
971
|
} catch (err) {
|
|
646
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
972
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
647
973
|
}
|
|
648
974
|
}
|
|
649
975
|
|
|
650
|
-
close(): [bigint, Map<string, AuthWitness
|
|
976
|
+
close(): [bigint, Map<string, AuthWitness>, TaggingSecretStrategy | undefined] {
|
|
651
977
|
this.logger.debug('Exiting Top Level Context');
|
|
652
|
-
return [this.nextBlockTimestamp, this.authwits];
|
|
978
|
+
return [this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategy];
|
|
653
979
|
}
|
|
654
980
|
|
|
655
|
-
private async getLastBlockNumber(): Promise<
|
|
656
|
-
|
|
981
|
+
private async getLastBlockNumber(): Promise<BlockNumber> {
|
|
982
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
983
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
private buildAuthorizeUtilityCallHook(
|
|
987
|
+
callerContext: 'private' | 'private view' | 'utility',
|
|
988
|
+
authorizedTargets: AztecAddress[],
|
|
989
|
+
): ExecutionHooks['authorizeUtilityCall'] | undefined {
|
|
990
|
+
if (authorizedTargets.length === 0) {
|
|
991
|
+
return undefined;
|
|
992
|
+
}
|
|
993
|
+
return req =>
|
|
994
|
+
Promise.resolve({
|
|
995
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
|
|
996
|
+
});
|
|
657
997
|
}
|
|
658
998
|
}
|