@aztec/txe 0.0.1-commit.4d3c002 → 0.0.1-commit.4d9804df
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-QVGDDH5X.js +3 -0
- package/dest/AuthRegistry-QVGDDH5X.js.map +7 -0
- package/dest/ContractClassRegistry-VWR3F42P.js +3 -0
- package/dest/ContractClassRegistry-VWR3F42P.js.map +7 -0
- package/dest/ContractInstanceRegistry-FHIWE33X.js +3 -0
- package/dest/ContractInstanceRegistry-FHIWE33X.js.map +7 -0
- package/dest/FeeJuice-SAOWVGG7.js +3 -0
- package/dest/FeeJuice-SAOWVGG7.js.map +7 -0
- package/dest/HandshakeRegistry-GY5CPEPS.js +3 -0
- package/dest/HandshakeRegistry-GY5CPEPS.js.map +7 -0
- package/dest/MultiCallEntrypoint-QG5H33ZZ.js +3 -0
- package/dest/MultiCallEntrypoint-QG5H33ZZ.js.map +7 -0
- package/dest/SchnorrAccount-NME3E45O.js +3 -0
- package/dest/SchnorrAccount-NME3E45O.js.map +7 -0
- package/dest/SchnorrInitializerlessAccount-WTGXU6SW.js +3 -0
- package/dest/SchnorrInitializerlessAccount-WTGXU6SW.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 +53 -0
- 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-GSUKUCKV.js +260 -0
- package/dest/chunk-GSUKUCKV.js.map +7 -0
- package/dest/chunk-UP4KKUVA.js +304 -0
- package/dest/chunk-UP4KKUVA.js.map +7 -0
- package/dest/constants.d.ts +5 -1
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +9 -1
- 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 +72 -190
- package/dest/metafile.json +38759 -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 +47 -9
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/tagging_secret_strategy.d.ts +12 -0
- package/dest/oracle/tagging_secret_strategy.d.ts.map +1 -0
- package/dest/oracle/tagging_secret_strategy.js +12 -0
- package/dest/oracle/test-resolver/default_fixtures.d.ts +16 -0
- package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/default_fixtures.js +200 -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 +26 -2
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +49 -1
- package/dest/oracle/txe_oracle_registry.d.ts +172 -0
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_registry.js +767 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +58 -18
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +555 -301
- 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 +115 -233
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +791 -647
- package/dest/server.bundle.js +3 -0
- package/dest/server.bundle.js.map +7 -0
- package/dest/state_machine/archiver.d.ts +4 -3
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +25 -16
- package/dest/state_machine/dummy_p2p_client.d.ts +14 -6
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +20 -2
- package/dest/state_machine/global_variable_builder.d.ts +10 -6
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +8 -5
- 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 +50 -14
- package/dest/state_machine/mock_epoch_cache.d.ts +1 -2
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +0 -3
- package/dest/state_machine/synchronizer.d.ts +10 -2
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +19 -6
- package/dest/txe_session.d.ts +90 -20
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +316 -63
- package/dest/utils/block_creation.d.ts +2 -2
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +2 -2
- package/dest/utils/encoding.d.ts +192 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/{util → utils}/encoding.js +7 -2
- package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
- package/dest/utils/expected_failure_error.d.ts.map +1 -0
- package/dest/utils/tx_effect_creation.d.ts +1 -1
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +0 -1
- package/dest/{util → utils}/txe_account_store.d.ts +1 -1
- package/dest/utils/txe_account_store.d.ts.map +1 -0
- 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/{util → utils}/txe_public_contract_data_source.js +7 -4
- 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 +38 -21
- package/src/bin/check_txe_oracle_version.ts +67 -0
- package/src/bin/index.ts +11 -2
- package/src/bin/oracle_test_server.ts +51 -0
- package/src/constants.ts +11 -1
- package/src/dispatcher_pool.ts +317 -0
- package/src/index.ts +99 -227
- package/src/msgpackr_fr_extension.ts +23 -0
- package/src/oracle/interfaces.ts +47 -8
- package/src/oracle/tagging_secret_strategy.ts +25 -0
- package/src/oracle/test-resolver/default_fixtures.ts +271 -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 +62 -0
- package/src/oracle/txe_oracle_registry.ts +556 -0
- package/src/oracle/txe_oracle_top_level_context.ts +356 -112
- 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 +890 -938
- package/src/state_machine/archiver.ts +37 -17
- package/src/state_machine/dummy_p2p_client.ts +38 -9
- package/src/state_machine/global_variable_builder.ts +12 -17
- package/src/state_machine/index.ts +62 -32
- package/src/state_machine/mock_epoch_cache.ts +0 -4
- package/src/state_machine/synchronizer.ts +27 -6
- package/src/txe_session.ts +548 -76
- package/src/utils/block_creation.ts +2 -1
- package/src/{util → utils}/encoding.ts +8 -2
- package/src/utils/tx_effect_creation.ts +0 -2
- package/src/utils/txe_artifact_resolver.ts +217 -0
- package/src/{util → utils}/txe_public_contract_data_source.ts +6 -4
- package/src/worker.ts +98 -0
- package/dest/util/encoding.d.ts +0 -788
- package/dest/util/encoding.d.ts.map +0 -1
- package/dest/util/expected_failure_error.d.ts.map +0 -1
- package/dest/util/txe_account_store.d.ts.map +0 -1
- 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 → utils}/expected_failure_error.js +0 -0
- /package/dest/{util → utils}/txe_account_store.js +0 -0
- /package/src/{util → utils}/expected_failure_error.ts +0 -0
- /package/src/{util → utils}/txe_account_store.ts +0 -0
|
@@ -1,29 +1,98 @@
|
|
|
1
|
-
|
|
1
|
+
function _ts_add_disposable_resource(env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() {
|
|
16
|
+
try {
|
|
17
|
+
inner.call(this);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
return Promise.reject(e);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
env.stack.push({
|
|
23
|
+
value: value,
|
|
24
|
+
dispose: dispose,
|
|
25
|
+
async: async
|
|
26
|
+
});
|
|
27
|
+
} else if (async) {
|
|
28
|
+
env.stack.push({
|
|
29
|
+
async: true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
function _ts_dispose_resources(env) {
|
|
35
|
+
var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
|
|
36
|
+
var e = new Error(message);
|
|
37
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
38
|
+
};
|
|
39
|
+
return (_ts_dispose_resources = function _ts_dispose_resources(env) {
|
|
40
|
+
function fail(e) {
|
|
41
|
+
env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
42
|
+
env.hasError = true;
|
|
43
|
+
}
|
|
44
|
+
var r, s = 0;
|
|
45
|
+
function next() {
|
|
46
|
+
while(r = env.stack.pop()){
|
|
47
|
+
try {
|
|
48
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
49
|
+
if (r.dispose) {
|
|
50
|
+
var result = r.dispose.call(r.value);
|
|
51
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
|
|
52
|
+
fail(e);
|
|
53
|
+
return next();
|
|
54
|
+
});
|
|
55
|
+
} else s |= 1;
|
|
56
|
+
} catch (e) {
|
|
57
|
+
fail(e);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
61
|
+
if (env.hasError) throw env.error;
|
|
62
|
+
}
|
|
63
|
+
return next();
|
|
64
|
+
})(env);
|
|
65
|
+
}
|
|
66
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, MAX_PRIVATE_LOGS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
67
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
68
|
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
4
69
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
70
|
import { LogLevels, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
6
71
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
7
|
-
import { CapsuleService,
|
|
8
|
-
import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache,
|
|
72
|
+
import { AnchoredContractData, CapsuleService, FactService, ORACLE_VERSION_MAJOR, composeHooks, enrichPublicSimulationError } from '@aztec/pxe/server';
|
|
73
|
+
import { CONTRACT_INSTANCE, ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, PrivateExecutionOracle, TransientArrayService, UtilityExecutionOracle, buildACIRCallback, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
|
|
9
74
|
import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
|
|
10
|
-
import {
|
|
75
|
+
import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, PublicTxSimulator } from '@aztec/simulator/server';
|
|
11
76
|
import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
12
77
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
13
78
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
14
79
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
15
80
|
import { computePartialAddress } from '@aztec/stdlib/contract';
|
|
16
|
-
import { Gas, GasFees
|
|
81
|
+
import { Gas, GasFees } from '@aztec/stdlib/gas';
|
|
17
82
|
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
18
83
|
import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
|
|
84
|
+
import { deriveKeys, hashPublicKey } from '@aztec/stdlib/keys';
|
|
85
|
+
import { AppTaggingSecretKind } from '@aztec/stdlib/logs';
|
|
86
|
+
import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/stdlib/messaging';
|
|
19
87
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
20
88
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
21
89
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
22
90
|
import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
|
|
23
|
-
import { ForkCheckpoint } from '@aztec/world-state';
|
|
24
|
-
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
25
|
-
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
91
|
+
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
92
|
+
import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
|
|
26
93
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
94
|
+
import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
|
|
95
|
+
import { makeResolveTaggingSecretStrategyHook } from './tagging_secret_strategy.js';
|
|
27
96
|
export class TXEOracleTopLevelContext {
|
|
28
97
|
stateMachine;
|
|
29
98
|
contractStore;
|
|
@@ -33,18 +102,23 @@ export class TXEOracleTopLevelContext {
|
|
|
33
102
|
accountStore;
|
|
34
103
|
senderTaggingStore;
|
|
35
104
|
recipientTaggingStore;
|
|
36
|
-
|
|
105
|
+
taggingSecretSourcesStore;
|
|
37
106
|
capsuleStore;
|
|
107
|
+
factStore;
|
|
38
108
|
privateEventStore;
|
|
39
109
|
nextBlockTimestamp;
|
|
40
110
|
version;
|
|
41
111
|
chainId;
|
|
42
112
|
authwits;
|
|
43
|
-
|
|
113
|
+
taggingSecretStrategies;
|
|
114
|
+
authorizeAllUtilityCallTargets;
|
|
115
|
+
artifactResolver;
|
|
116
|
+
rootPath;
|
|
117
|
+
packageName;
|
|
44
118
|
isMisc;
|
|
45
119
|
isTxe;
|
|
46
120
|
logger;
|
|
47
|
-
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore,
|
|
121
|
+
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, taggingSecretSourcesStore, capsuleStore, factStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits, taggingSecretStrategies, authorizeAllUtilityCallTargets, artifactResolver, rootPath, packageName){
|
|
48
122
|
this.stateMachine = stateMachine;
|
|
49
123
|
this.contractStore = contractStore;
|
|
50
124
|
this.noteStore = noteStore;
|
|
@@ -53,24 +127,38 @@ export class TXEOracleTopLevelContext {
|
|
|
53
127
|
this.accountStore = accountStore;
|
|
54
128
|
this.senderTaggingStore = senderTaggingStore;
|
|
55
129
|
this.recipientTaggingStore = recipientTaggingStore;
|
|
56
|
-
this.
|
|
130
|
+
this.taggingSecretSourcesStore = taggingSecretSourcesStore;
|
|
57
131
|
this.capsuleStore = capsuleStore;
|
|
132
|
+
this.factStore = factStore;
|
|
58
133
|
this.privateEventStore = privateEventStore;
|
|
59
134
|
this.nextBlockTimestamp = nextBlockTimestamp;
|
|
60
135
|
this.version = version;
|
|
61
136
|
this.chainId = chainId;
|
|
62
137
|
this.authwits = authwits;
|
|
63
|
-
this.
|
|
138
|
+
this.taggingSecretStrategies = taggingSecretStrategies;
|
|
139
|
+
this.authorizeAllUtilityCallTargets = authorizeAllUtilityCallTargets;
|
|
140
|
+
this.artifactResolver = artifactResolver;
|
|
141
|
+
this.rootPath = rootPath;
|
|
142
|
+
this.packageName = packageName;
|
|
64
143
|
this.isMisc = true;
|
|
65
144
|
this.isTxe = true;
|
|
66
145
|
this.logger = createLogger('txe:top_level_context');
|
|
67
146
|
this.logger.debug('Entering Top Level Context');
|
|
68
147
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
148
|
+
contractOracleVersion;
|
|
149
|
+
assertCompatibleOracleVersion(major, minor) {
|
|
150
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
151
|
+
const hint = major > ORACLE_VERSION_MAJOR ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.' : 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
152
|
+
throw new Error(`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`);
|
|
73
153
|
}
|
|
154
|
+
this.contractOracleVersion = {
|
|
155
|
+
major,
|
|
156
|
+
minor
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
160
|
+
nonOracleFunctionGetContractOracleVersion() {
|
|
161
|
+
return this.contractOracleVersion;
|
|
74
162
|
}
|
|
75
163
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
76
164
|
// setup.
|
|
@@ -78,7 +166,7 @@ export class TXEOracleTopLevelContext {
|
|
|
78
166
|
return Fr.random();
|
|
79
167
|
}
|
|
80
168
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
81
|
-
log(level, message, fields) {
|
|
169
|
+
log(level, message, _fieldsSize, fields) {
|
|
82
170
|
if (!LogLevels[level]) {
|
|
83
171
|
throw new Error(`Invalid log level: ${level}`);
|
|
84
172
|
}
|
|
@@ -98,20 +186,27 @@ export class TXEOracleTopLevelContext {
|
|
|
98
186
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
99
187
|
}
|
|
100
188
|
async getLastBlockTimestamp() {
|
|
101
|
-
return (await this.stateMachine.node.
|
|
189
|
+
return (await this.stateMachine.node.getBlockData('latest')).header.globalVariables.timestamp;
|
|
102
190
|
}
|
|
103
191
|
async getLastTxEffects() {
|
|
104
192
|
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
105
|
-
const block = await this.stateMachine.archiver.getBlock(
|
|
193
|
+
const block = await this.stateMachine.archiver.getBlock({
|
|
194
|
+
number: latestBlockNumber
|
|
195
|
+
});
|
|
106
196
|
if (block.body.txEffects.length != 1) {
|
|
107
197
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
108
198
|
throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
|
|
109
199
|
}
|
|
110
200
|
const txEffects = block.body.txEffects[0];
|
|
201
|
+
const privateLogs = txEffects.privateLogs;
|
|
202
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
203
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
204
|
+
}
|
|
111
205
|
return {
|
|
112
206
|
txHash: txEffects.txHash,
|
|
113
207
|
noteHashes: txEffects.noteHashes,
|
|
114
|
-
nullifiers: txEffects.nullifiers
|
|
208
|
+
nullifiers: txEffects.nullifiers,
|
|
209
|
+
privateLogs
|
|
115
210
|
};
|
|
116
211
|
}
|
|
117
212
|
async syncContractNonOracleMethod(contractAddress, scope, jobId) {
|
|
@@ -121,13 +216,16 @@ export class TXEOracleTopLevelContext {
|
|
|
121
216
|
}
|
|
122
217
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
123
218
|
await this.stateMachine.contractSyncService.ensureContractSynced(contractAddress, null, async (call, execScopes)=>{
|
|
124
|
-
await this.executeUtilityCall(call,
|
|
219
|
+
await this.executeUtilityCall(call, {
|
|
220
|
+
scopes: execScopes,
|
|
221
|
+
jobId
|
|
222
|
+
});
|
|
125
223
|
}, blockHeader, jobId, [
|
|
126
224
|
scope
|
|
127
225
|
]);
|
|
128
226
|
}
|
|
129
227
|
async getPrivateEvents(selector, contractAddress, scope) {
|
|
130
|
-
|
|
228
|
+
const events = (await this.privateEventStore.getPrivateEvents(selector, {
|
|
131
229
|
contractAddress,
|
|
132
230
|
scopes: [
|
|
133
231
|
scope
|
|
@@ -135,6 +233,13 @@ export class TXEOracleTopLevelContext {
|
|
|
135
233
|
fromBlock: 0,
|
|
136
234
|
toBlock: await this.getLastBlockNumber() + 1
|
|
137
235
|
})).map((e)=>e.packedEvent);
|
|
236
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
237
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
238
|
+
}
|
|
239
|
+
if (events.some((e)=>e.length > MAX_PRIVATE_EVENT_LEN)) {
|
|
240
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
|
|
241
|
+
}
|
|
242
|
+
return events;
|
|
138
243
|
}
|
|
139
244
|
async advanceBlocksBy(blocks) {
|
|
140
245
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
@@ -146,35 +251,59 @@ export class TXEOracleTopLevelContext {
|
|
|
146
251
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
147
252
|
this.nextBlockTimestamp += duration;
|
|
148
253
|
}
|
|
149
|
-
|
|
254
|
+
deploymentNullifier(address) {
|
|
255
|
+
return siloNullifier(AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
|
|
256
|
+
}
|
|
257
|
+
async deploy(contractPath, initializer, args, secret, salt, deployer) {
|
|
258
|
+
const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
|
|
259
|
+
rootPath: this.rootPath,
|
|
260
|
+
packageName: this.packageName,
|
|
261
|
+
contractPath,
|
|
262
|
+
initializer,
|
|
263
|
+
args,
|
|
264
|
+
secret,
|
|
265
|
+
salt,
|
|
266
|
+
deployer
|
|
267
|
+
});
|
|
150
268
|
// Emit deployment nullifier
|
|
151
269
|
await this.mineBlock({
|
|
152
270
|
nullifiers: [
|
|
153
|
-
await
|
|
271
|
+
await this.deploymentNullifier(instance.address)
|
|
154
272
|
]
|
|
155
273
|
});
|
|
156
274
|
if (!secret.equals(Fr.ZERO)) {
|
|
157
|
-
await this.
|
|
275
|
+
await this.registerContractAndAddAccount(artifact, instance, secret);
|
|
158
276
|
} else {
|
|
159
277
|
await this.contractStore.addContractInstance(instance);
|
|
160
278
|
await this.contractStore.addContractArtifact(artifact);
|
|
161
279
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
162
280
|
}
|
|
281
|
+
return CONTRACT_INSTANCE.serialization.fn(instance).flat();
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
|
|
285
|
+
*/ async mineDeploymentNullifiers(addresses) {
|
|
286
|
+
await this.mineBlock({
|
|
287
|
+
nullifiers: await Promise.all(addresses.map((address)=>this.deploymentNullifier(address)))
|
|
288
|
+
});
|
|
163
289
|
}
|
|
164
|
-
async addAccount(
|
|
290
|
+
async addAccount(secret) {
|
|
291
|
+
const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
|
|
292
|
+
return this.registerContractAndAddAccount(artifact, instance, secret);
|
|
293
|
+
}
|
|
294
|
+
async registerContractAndAddAccount(artifact, instance, secret) {
|
|
165
295
|
const partialAddress = await computePartialAddress(instance);
|
|
166
296
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
167
297
|
await this.contractStore.addContractInstance(instance);
|
|
168
298
|
await this.contractStore.addContractArtifact(artifact);
|
|
169
|
-
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
299
|
+
const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
|
|
170
300
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
171
301
|
await this.addressStore.addCompleteAddress(completeAddress);
|
|
172
302
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
173
303
|
return completeAddress;
|
|
174
304
|
}
|
|
175
|
-
async createAccount(secret) {
|
|
176
|
-
|
|
177
|
-
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
305
|
+
async createAccount(secret, partialAddress) {
|
|
306
|
+
const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
|
|
178
307
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
179
308
|
await this.addressStore.addCompleteAddress(completeAddress);
|
|
180
309
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
@@ -182,14 +311,39 @@ export class TXEOracleTopLevelContext {
|
|
|
182
311
|
}
|
|
183
312
|
async addAuthWitness(address, messageHash) {
|
|
184
313
|
const account = await this.accountStore.getAccount(address);
|
|
185
|
-
const
|
|
314
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
315
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
186
316
|
const schnorr = new Schnorr();
|
|
187
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
188
|
-
const authWitness = new AuthWitness(messageHash,
|
|
189
|
-
...signature.toBuffer()
|
|
190
|
-
]);
|
|
317
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
318
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
191
319
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
192
320
|
}
|
|
321
|
+
setTaggingSecretStrategies(unconstrainedStrategy, constrainedStrategy) {
|
|
322
|
+
const apply = (mode, strategy)=>{
|
|
323
|
+
if (strategy.isSome()) {
|
|
324
|
+
this.taggingSecretStrategies.set(mode, strategy.value);
|
|
325
|
+
} else {
|
|
326
|
+
this.taggingSecretStrategies.delete(mode);
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
apply(AppTaggingSecretKind.UNCONSTRAINED, unconstrainedStrategy);
|
|
330
|
+
apply(AppTaggingSecretKind.CONSTRAINED, constrainedStrategy);
|
|
331
|
+
}
|
|
332
|
+
setAuthorizeAllUtilityCallTargets(authorizeAll) {
|
|
333
|
+
this.authorizeAllUtilityCallTargets = authorizeAll;
|
|
334
|
+
}
|
|
335
|
+
async sendL1ToL2Message(content, secretHash, sender, recipient) {
|
|
336
|
+
// Messages are appended to the tree, so the next free slot is simply the current tree size.
|
|
337
|
+
const { size } = await this.stateMachine.synchronizer.getCommitted().getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
|
|
338
|
+
const leafIndex = new Fr(size);
|
|
339
|
+
const message = new L1ToL2Message(new L1Actor(sender, this.chainId.toNumber()), new L2Actor(recipient, this.version.toNumber()), content, secretHash, leafIndex);
|
|
340
|
+
await this.mineBlock({
|
|
341
|
+
l1ToL2Messages: [
|
|
342
|
+
message.hash()
|
|
343
|
+
]
|
|
344
|
+
});
|
|
345
|
+
return leafIndex;
|
|
346
|
+
}
|
|
193
347
|
async mineBlock(options = {}) {
|
|
194
348
|
const blockNumber = await this.getNextBlockNumber();
|
|
195
349
|
const txEffect = TxEffect.empty();
|
|
@@ -199,7 +353,7 @@ export class TXEOracleTopLevelContext {
|
|
|
199
353
|
];
|
|
200
354
|
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
201
355
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
202
|
-
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
356
|
+
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
|
|
203
357
|
const globals = makeGlobalVariables(undefined, {
|
|
204
358
|
blockNumber,
|
|
205
359
|
timestamp: this.nextBlockTimestamp,
|
|
@@ -211,269 +365,319 @@ export class TXEOracleTopLevelContext {
|
|
|
211
365
|
]);
|
|
212
366
|
await forkedWorldTrees.close();
|
|
213
367
|
this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
|
|
214
|
-
await this.stateMachine.handleL2Block(block);
|
|
368
|
+
await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
|
|
215
369
|
}
|
|
216
|
-
async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, jobId) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
throw new Error(message);
|
|
222
|
-
}
|
|
223
|
-
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
224
|
-
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
225
|
-
const effectiveScopes = from.isZero() ? [] : [
|
|
226
|
-
from
|
|
227
|
-
];
|
|
228
|
-
// Sync notes before executing private function to discover notes from previous transactions
|
|
229
|
-
const utilityExecutor = async (call, execScopes)=>{
|
|
230
|
-
await this.executeUtilityCall(call, execScopes, jobId);
|
|
370
|
+
async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, additionalScopes = [], jobId, authorizedUtilityCallTargets, gasSettings) {
|
|
371
|
+
const env = {
|
|
372
|
+
stack: [],
|
|
373
|
+
error: void 0,
|
|
374
|
+
hasError: false
|
|
231
375
|
};
|
|
232
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
233
|
-
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, effectiveScopes);
|
|
234
|
-
const blockNumber = await this.getNextBlockNumber();
|
|
235
|
-
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
236
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
237
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
238
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
239
|
-
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
240
|
-
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
241
|
-
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
242
|
-
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
243
|
-
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
244
|
-
// marking all side effects as revertible.
|
|
245
|
-
const minRevertibleSideEffectCounter = 1;
|
|
246
|
-
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
247
|
-
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
248
|
-
const simulator = new WASMSimulator();
|
|
249
|
-
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
250
|
-
argsHash,
|
|
251
|
-
txContext,
|
|
252
|
-
callContext,
|
|
253
|
-
anchorBlockHeader: blockHeader,
|
|
254
|
-
utilityExecutor,
|
|
255
|
-
authWitnesses: Array.from(this.authwits.values()),
|
|
256
|
-
capsules: [],
|
|
257
|
-
executionCache: HashedValuesCache.create([
|
|
258
|
-
new HashedValues(args, argsHash)
|
|
259
|
-
]),
|
|
260
|
-
noteCache,
|
|
261
|
-
taggingIndexCache,
|
|
262
|
-
contractStore: this.contractStore,
|
|
263
|
-
noteStore: this.noteStore,
|
|
264
|
-
keyStore: this.keyStore,
|
|
265
|
-
addressStore: this.addressStore,
|
|
266
|
-
aztecNode: this.stateMachine.node,
|
|
267
|
-
senderTaggingStore: this.senderTaggingStore,
|
|
268
|
-
recipientTaggingStore: this.recipientTaggingStore,
|
|
269
|
-
senderAddressBookStore: this.senderAddressBookStore,
|
|
270
|
-
capsuleService: new CapsuleService(this.capsuleStore, effectiveScopes),
|
|
271
|
-
privateEventStore: this.privateEventStore,
|
|
272
|
-
contractSyncService: this.stateMachine.contractSyncService,
|
|
273
|
-
jobId,
|
|
274
|
-
totalPublicCalldataCount: 0,
|
|
275
|
-
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
276
|
-
scopes: effectiveScopes,
|
|
277
|
-
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
278
|
-
// contract would perform, including setting senderForTags.
|
|
279
|
-
senderForTags: from,
|
|
280
|
-
simulator,
|
|
281
|
-
messageContextService: this.stateMachine.messageContextService
|
|
282
|
-
});
|
|
283
|
-
// 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.
|
|
284
|
-
let result;
|
|
285
|
-
let executionResult;
|
|
286
376
|
try {
|
|
287
|
-
|
|
288
|
-
const
|
|
377
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
378
|
+
const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, blockHeader);
|
|
379
|
+
this.logger.verbose(`Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
380
|
+
const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
381
|
+
if (!artifact) {
|
|
382
|
+
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
|
|
383
|
+
throw new Error(message);
|
|
384
|
+
}
|
|
385
|
+
const scopes = from === undefined ? additionalScopes : [
|
|
386
|
+
from,
|
|
387
|
+
...additionalScopes
|
|
388
|
+
];
|
|
389
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
390
|
+
const utilityExecutor = async (call, execScopes)=>{
|
|
391
|
+
await this.executeUtilityCall(call, {
|
|
392
|
+
scopes: execScopes,
|
|
393
|
+
jobId
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
|
|
397
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
398
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
399
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
400
|
+
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
401
|
+
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
402
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
403
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
404
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
405
|
+
// marking all side effects as revertible.
|
|
406
|
+
const minRevertibleSideEffectCounter = 1;
|
|
407
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
408
|
+
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
409
|
+
const simulator = new WASMSimulator();
|
|
410
|
+
const transientArrayService = new TransientArrayService();
|
|
411
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
412
|
+
argsHash,
|
|
413
|
+
txContext,
|
|
414
|
+
txRequestSalt: Fr.ZERO,
|
|
415
|
+
callContext,
|
|
416
|
+
anchorBlockHeader: blockHeader,
|
|
417
|
+
utilityExecutor,
|
|
418
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
419
|
+
capsules: [],
|
|
420
|
+
executionCache: HashedValuesCache.create([
|
|
421
|
+
new HashedValues(args, argsHash)
|
|
422
|
+
]),
|
|
423
|
+
noteCache,
|
|
424
|
+
taggingIndexCache,
|
|
425
|
+
anchoredContractData,
|
|
426
|
+
noteStore: this.noteStore,
|
|
427
|
+
keyStore: this.keyStore,
|
|
428
|
+
addressStore: this.addressStore,
|
|
429
|
+
aztecNode: this.stateMachine.node,
|
|
430
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
431
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
432
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
433
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
434
|
+
factService: new FactService(this.factStore, scopes),
|
|
435
|
+
privateEventStore: this.privateEventStore,
|
|
436
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
437
|
+
jobId,
|
|
438
|
+
totalPublicCalldataCount: 0,
|
|
439
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
440
|
+
scopes,
|
|
441
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
442
|
+
// contract would perform, including setting senderForTags.
|
|
443
|
+
senderForTags: from,
|
|
444
|
+
simulator,
|
|
445
|
+
txResolver: this.stateMachine.txResolver,
|
|
446
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
447
|
+
hooks: composeHooks({
|
|
448
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets),
|
|
449
|
+
resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies)
|
|
450
|
+
}),
|
|
451
|
+
transientArrayService
|
|
452
|
+
});
|
|
453
|
+
// 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.
|
|
454
|
+
let result;
|
|
455
|
+
let executionResult;
|
|
456
|
+
try {
|
|
457
|
+
executionResult = await executePrivateFunction(simulator, privateExecutionOracle, artifact, targetContractAddress, functionSelector);
|
|
458
|
+
const publicCallRequests = collectNested([
|
|
459
|
+
executionResult
|
|
460
|
+
], (r)=>r.publicInputs.publicCallRequests.getActiveItems().map((r)=>r.inner).concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [
|
|
461
|
+
r.publicInputs.publicTeardownCallRequest
|
|
462
|
+
]));
|
|
463
|
+
const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
|
|
464
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
465
|
+
return new HashedValues(calldata, r.calldataHash);
|
|
466
|
+
}));
|
|
467
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
468
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
469
|
+
} catch (err) {
|
|
470
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
471
|
+
}
|
|
472
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
473
|
+
// the nonce generator for the note hashes.
|
|
474
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
475
|
+
const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>anchoredContractData.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
|
|
476
|
+
const globals = makeGlobalVariables();
|
|
477
|
+
globals.blockNumber = blockNumber;
|
|
478
|
+
globals.timestamp = this.nextBlockTimestamp;
|
|
479
|
+
globals.chainId = this.chainId;
|
|
480
|
+
globals.version = this.version;
|
|
481
|
+
globals.gasFees = GasFees.empty();
|
|
482
|
+
const forkedWorldTrees = _ts_add_disposable_resource(env, await this.stateMachine.synchronizer.nativeWorldStateService.fork(), true);
|
|
483
|
+
const bindings = this.logger.getBindings();
|
|
484
|
+
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
|
|
485
|
+
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
486
|
+
const config = PublicSimulatorConfig.from({
|
|
487
|
+
skipFeeEnforcement: true,
|
|
488
|
+
collectDebugLogs: true,
|
|
489
|
+
collectHints: false,
|
|
490
|
+
collectStatistics: false,
|
|
491
|
+
collectCallMetadata: true
|
|
492
|
+
});
|
|
493
|
+
// The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
|
|
494
|
+
const forkId = forkedWorldTrees.getRevision().forkId;
|
|
495
|
+
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new PublicTxSimulator(this.stateMachine.synchronizer.avmSimulator, globals, contractsDB, forkId, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
|
|
496
|
+
const tx = await Tx.create({
|
|
497
|
+
data: publicInputs,
|
|
498
|
+
chonkProof: ChonkProof.empty(),
|
|
499
|
+
contractClassLogFields: [],
|
|
500
|
+
publicFunctionCalldata: result.publicFunctionCalldata
|
|
501
|
+
});
|
|
502
|
+
let checkpoint;
|
|
503
|
+
if (isStaticCall) {
|
|
504
|
+
checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
|
|
505
|
+
}
|
|
506
|
+
const results = await processor.process([
|
|
507
|
+
tx
|
|
508
|
+
]);
|
|
509
|
+
const [processedTx] = results[0];
|
|
510
|
+
const failedTxs = results[1];
|
|
511
|
+
if (failedTxs.length !== 0) {
|
|
512
|
+
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
513
|
+
} else if (!processedTx.revertCode.isOK()) {
|
|
514
|
+
if (processedTx.revertReason) {
|
|
515
|
+
try {
|
|
516
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.stateMachine.contractClassService, await this.stateMachine.anchorBlockStore.getBlockHeader(), this.logger);
|
|
517
|
+
// eslint-disable-next-line no-empty
|
|
518
|
+
} catch {}
|
|
519
|
+
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
520
|
+
} else {
|
|
521
|
+
throw new Error('Contract execution has reverted');
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
525
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
526
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
527
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
528
|
+
const offchainEffects = collectNested([
|
|
289
529
|
executionResult
|
|
290
|
-
], (r)=>r.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
noteCache.finish();
|
|
298
|
-
const nonceGenerator = noteCache.getNonceGenerator();
|
|
299
|
-
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
300
|
-
} catch (err) {
|
|
301
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
302
|
-
}
|
|
303
|
-
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
304
|
-
// the nonce generator for the note hashes.
|
|
305
|
-
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
306
|
-
const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>this.contractStore.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
|
|
307
|
-
const globals = makeGlobalVariables();
|
|
308
|
-
globals.blockNumber = blockNumber;
|
|
309
|
-
globals.timestamp = this.nextBlockTimestamp;
|
|
310
|
-
globals.chainId = this.chainId;
|
|
311
|
-
globals.version = this.version;
|
|
312
|
-
globals.gasFees = GasFees.empty();
|
|
313
|
-
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
314
|
-
const bindings = this.logger.getBindings();
|
|
315
|
-
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
|
|
316
|
-
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
317
|
-
const config = PublicSimulatorConfig.from({
|
|
318
|
-
skipFeeEnforcement: true,
|
|
319
|
-
collectDebugLogs: true,
|
|
320
|
-
collectHints: false,
|
|
321
|
-
collectStatistics: false,
|
|
322
|
-
collectCallMetadata: true
|
|
323
|
-
});
|
|
324
|
-
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
|
|
325
|
-
const tx = await Tx.create({
|
|
326
|
-
data: publicInputs,
|
|
327
|
-
chonkProof: ChonkProof.empty(),
|
|
328
|
-
contractClassLogFields: [],
|
|
329
|
-
publicFunctionCalldata: result.publicFunctionCalldata
|
|
330
|
-
});
|
|
331
|
-
let checkpoint;
|
|
332
|
-
if (isStaticCall) {
|
|
333
|
-
checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
|
|
334
|
-
}
|
|
335
|
-
const results = await processor.process([
|
|
336
|
-
tx
|
|
337
|
-
]);
|
|
338
|
-
const [processedTx] = results[0];
|
|
339
|
-
const failedTxs = results[1];
|
|
340
|
-
if (failedTxs.length !== 0) {
|
|
341
|
-
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
342
|
-
} else if (!processedTx.revertCode.isOK()) {
|
|
343
|
-
if (processedTx.revertReason) {
|
|
344
|
-
try {
|
|
345
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
346
|
-
// eslint-disable-next-line no-empty
|
|
347
|
-
} catch {}
|
|
348
|
-
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
349
|
-
} else {
|
|
350
|
-
throw new Error('Contract execution has reverted');
|
|
530
|
+
], (r)=>r.offchainEffects.map((e)=>e.data));
|
|
531
|
+
if (isStaticCall) {
|
|
532
|
+
await checkpoint.revert();
|
|
533
|
+
return {
|
|
534
|
+
returnValues: executionResult.returnValues ?? [],
|
|
535
|
+
offchainEffects
|
|
536
|
+
};
|
|
351
537
|
}
|
|
538
|
+
const txEffect = TxEffect.empty();
|
|
539
|
+
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
540
|
+
txEffect.nullifiers = processedTx.txEffect.nullifiers;
|
|
541
|
+
txEffect.privateLogs = processedTx.txEffect.privateLogs;
|
|
542
|
+
txEffect.publicLogs = processedTx.txEffect.publicLogs;
|
|
543
|
+
txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
|
|
544
|
+
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
545
|
+
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
546
|
+
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
547
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
548
|
+
txEffect
|
|
549
|
+
]);
|
|
550
|
+
await this.stateMachine.handleL2Block(l2Block);
|
|
551
|
+
return {
|
|
552
|
+
returnValues: executionResult.returnValues ?? [],
|
|
553
|
+
offchainEffects
|
|
554
|
+
};
|
|
555
|
+
} catch (e) {
|
|
556
|
+
env.error = e;
|
|
557
|
+
env.hasError = true;
|
|
558
|
+
} finally{
|
|
559
|
+
const result = _ts_dispose_resources(env);
|
|
560
|
+
if (result) await result;
|
|
352
561
|
}
|
|
353
|
-
if (isStaticCall) {
|
|
354
|
-
await checkpoint.revert();
|
|
355
|
-
await forkedWorldTrees.close();
|
|
356
|
-
return executionResult.returnValues ?? [];
|
|
357
|
-
}
|
|
358
|
-
const txEffect = TxEffect.empty();
|
|
359
|
-
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
360
|
-
txEffect.nullifiers = processedTx.txEffect.nullifiers;
|
|
361
|
-
txEffect.privateLogs = processedTx.txEffect.privateLogs;
|
|
362
|
-
txEffect.publicLogs = processedTx.txEffect.publicLogs;
|
|
363
|
-
txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
|
|
364
|
-
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
365
|
-
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
366
|
-
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
367
|
-
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
368
|
-
txEffect
|
|
369
|
-
]);
|
|
370
|
-
await this.stateMachine.handleL2Block(l2Block);
|
|
371
|
-
await forkedWorldTrees.close();
|
|
372
|
-
return executionResult.returnValues ?? [];
|
|
373
562
|
}
|
|
374
|
-
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
if (failedTxs.length !== 0) {
|
|
434
|
-
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
435
|
-
} else if (!processedTx.revertCode.isOK()) {
|
|
436
|
-
if (processedTx.revertReason) {
|
|
437
|
-
try {
|
|
438
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
439
|
-
// eslint-disable-next-line no-empty
|
|
440
|
-
} catch {}
|
|
441
|
-
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
442
|
-
} else {
|
|
443
|
-
throw new Error('Contract execution has reverted');
|
|
563
|
+
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall, gasSettings) {
|
|
564
|
+
const env = {
|
|
565
|
+
stack: [],
|
|
566
|
+
error: void 0,
|
|
567
|
+
hasError: false
|
|
568
|
+
};
|
|
569
|
+
try {
|
|
570
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
571
|
+
const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader);
|
|
572
|
+
this.logger.verbose(`Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
573
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
574
|
+
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
575
|
+
const calldataHash = await computeCalldataHash(calldata);
|
|
576
|
+
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
577
|
+
const globals = makeGlobalVariables();
|
|
578
|
+
globals.blockNumber = blockNumber;
|
|
579
|
+
globals.timestamp = this.nextBlockTimestamp;
|
|
580
|
+
globals.chainId = this.chainId;
|
|
581
|
+
globals.version = this.version;
|
|
582
|
+
globals.gasFees = GasFees.empty();
|
|
583
|
+
const forkedWorldTrees = _ts_add_disposable_resource(env, await this.stateMachine.synchronizer.nativeWorldStateService.fork(), true);
|
|
584
|
+
const bindings2 = this.logger.getBindings();
|
|
585
|
+
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings2);
|
|
586
|
+
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
587
|
+
const config = PublicSimulatorConfig.from({
|
|
588
|
+
skipFeeEnforcement: true,
|
|
589
|
+
collectDebugLogs: true,
|
|
590
|
+
collectHints: false,
|
|
591
|
+
collectStatistics: false,
|
|
592
|
+
collectCallMetadata: true
|
|
593
|
+
});
|
|
594
|
+
// The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
|
|
595
|
+
const forkId2 = forkedWorldTrees.getRevision().forkId;
|
|
596
|
+
const simulator = new PublicTxSimulator(this.stateMachine.synchronizer.avmSimulator, globals, contractsDB, forkId2, config, bindings2);
|
|
597
|
+
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings2));
|
|
598
|
+
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
599
|
+
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
600
|
+
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
601
|
+
// unique.
|
|
602
|
+
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
603
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
604
|
+
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
605
|
+
// may require producing reverts.
|
|
606
|
+
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
607
|
+
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
|
|
608
|
+
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
|
|
609
|
+
const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
|
|
610
|
+
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
|
|
611
|
+
const tx = await Tx.create({
|
|
612
|
+
data: txData,
|
|
613
|
+
chonkProof: ChonkProof.empty(),
|
|
614
|
+
contractClassLogFields: [],
|
|
615
|
+
publicFunctionCalldata: [
|
|
616
|
+
calldataHashedValues
|
|
617
|
+
]
|
|
618
|
+
});
|
|
619
|
+
let checkpoint;
|
|
620
|
+
if (isStaticCall) {
|
|
621
|
+
checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
|
|
444
622
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
623
|
+
const results = await processor.process([
|
|
624
|
+
tx
|
|
625
|
+
]);
|
|
626
|
+
const [processedTx] = results[0];
|
|
627
|
+
const failedTxs = results[1];
|
|
628
|
+
if (failedTxs.length !== 0) {
|
|
629
|
+
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
630
|
+
} else if (!processedTx.revertCode.isOK()) {
|
|
631
|
+
if (processedTx.revertReason) {
|
|
632
|
+
try {
|
|
633
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader, this.logger);
|
|
634
|
+
// eslint-disable-next-line no-empty
|
|
635
|
+
} catch {}
|
|
636
|
+
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
637
|
+
} else {
|
|
638
|
+
throw new Error('Contract execution has reverted');
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
const returnValues = results[3][0].values;
|
|
642
|
+
if (isStaticCall) {
|
|
643
|
+
await checkpoint.revert();
|
|
644
|
+
return returnValues ?? [];
|
|
645
|
+
}
|
|
646
|
+
const txEffect = TxEffect.empty();
|
|
647
|
+
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
648
|
+
txEffect.nullifiers = processedTx.txEffect.nullifiers;
|
|
649
|
+
txEffect.privateLogs = processedTx.txEffect.privateLogs;
|
|
650
|
+
txEffect.publicLogs = processedTx.txEffect.publicLogs;
|
|
651
|
+
txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
|
|
652
|
+
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
653
|
+
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
654
|
+
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
655
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
656
|
+
txEffect
|
|
657
|
+
]);
|
|
658
|
+
await this.stateMachine.handleL2Block(l2Block);
|
|
450
659
|
return returnValues ?? [];
|
|
660
|
+
} catch (e) {
|
|
661
|
+
env.error = e;
|
|
662
|
+
env.hasError = true;
|
|
663
|
+
} finally{
|
|
664
|
+
const result = _ts_dispose_resources(env);
|
|
665
|
+
if (result) await result;
|
|
451
666
|
}
|
|
452
|
-
const txEffect = TxEffect.empty();
|
|
453
|
-
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
454
|
-
txEffect.nullifiers = processedTx.txEffect.nullifiers;
|
|
455
|
-
txEffect.privateLogs = processedTx.txEffect.privateLogs;
|
|
456
|
-
txEffect.publicLogs = processedTx.txEffect.publicLogs;
|
|
457
|
-
txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
|
|
458
|
-
txEffect.txHash = new TxHash(new Fr(blockNumber));
|
|
459
|
-
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
460
|
-
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
461
|
-
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
|
|
462
|
-
txEffect
|
|
463
|
-
]);
|
|
464
|
-
await this.stateMachine.handleL2Block(l2Block);
|
|
465
|
-
await forkedWorldTrees.close();
|
|
466
|
-
return returnValues ?? [];
|
|
467
667
|
}
|
|
468
|
-
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId) {
|
|
469
|
-
const
|
|
668
|
+
async executeUtilityFunction(from, targetContractAddress, functionSelector, args, jobId, authorizedUtilityCallTargets) {
|
|
669
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
670
|
+
const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, blockHeader);
|
|
671
|
+
const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
470
672
|
if (!artifact) {
|
|
471
673
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
472
674
|
}
|
|
473
675
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
474
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
475
676
|
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, async (call, execScopes)=>{
|
|
476
|
-
await this.executeUtilityCall(call,
|
|
677
|
+
await this.executeUtilityCall(call, {
|
|
678
|
+
scopes: execScopes,
|
|
679
|
+
jobId
|
|
680
|
+
});
|
|
477
681
|
}, blockHeader, jobId, await this.keyStore.getAccounts());
|
|
478
682
|
const call = FunctionCall.from({
|
|
479
683
|
name: artifact.name,
|
|
@@ -485,10 +689,20 @@ export class TXEOracleTopLevelContext {
|
|
|
485
689
|
args,
|
|
486
690
|
returnTypes: []
|
|
487
691
|
});
|
|
488
|
-
return this.executeUtilityCall(call,
|
|
692
|
+
return this.executeUtilityCall(call, {
|
|
693
|
+
from,
|
|
694
|
+
scopes: await this.keyStore.getAccounts(),
|
|
695
|
+
jobId,
|
|
696
|
+
authorizedUtilityCallTargets
|
|
697
|
+
});
|
|
489
698
|
}
|
|
490
|
-
async executeUtilityCall(call, scopes, jobId) {
|
|
491
|
-
const
|
|
699
|
+
async executeUtilityCall(call, { from = AztecAddress.NULL_MSG_SENDER, scopes, jobId, authorizedUtilityCallTargets = [] }) {
|
|
700
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
701
|
+
const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader);
|
|
702
|
+
const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
703
|
+
if (!entryPointArtifact) {
|
|
704
|
+
throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
|
|
705
|
+
}
|
|
492
706
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
493
707
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
494
708
|
}
|
|
@@ -497,27 +711,47 @@ export class TXEOracleTopLevelContext {
|
|
|
497
711
|
selector: call.selector
|
|
498
712
|
});
|
|
499
713
|
try {
|
|
500
|
-
const
|
|
714
|
+
const simulator = new WASMSimulator();
|
|
715
|
+
const utilityExecutor = async (syncCall, execScopes)=>{
|
|
716
|
+
await this.executeUtilityCall(syncCall, {
|
|
717
|
+
scopes: execScopes,
|
|
718
|
+
jobId
|
|
719
|
+
});
|
|
720
|
+
};
|
|
501
721
|
const oracle = new UtilityExecutionOracle({
|
|
502
|
-
|
|
722
|
+
callContext: CallContext.from({
|
|
723
|
+
msgSender: from,
|
|
724
|
+
contractAddress: call.to,
|
|
725
|
+
functionSelector: call.selector,
|
|
726
|
+
isStaticCall: true
|
|
727
|
+
}),
|
|
503
728
|
authWitnesses: [],
|
|
504
729
|
capsules: [],
|
|
505
730
|
anchorBlockHeader,
|
|
506
|
-
|
|
731
|
+
anchoredContractData,
|
|
507
732
|
noteStore: this.noteStore,
|
|
508
733
|
keyStore: this.keyStore,
|
|
509
734
|
addressStore: this.addressStore,
|
|
510
735
|
aztecNode: this.stateMachine.node,
|
|
511
736
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
512
|
-
|
|
737
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
513
738
|
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
739
|
+
factService: new FactService(this.factStore, scopes),
|
|
514
740
|
privateEventStore: this.privateEventStore,
|
|
515
|
-
|
|
516
|
-
contractSyncService: this.contractSyncService,
|
|
741
|
+
txResolver: this.stateMachine.txResolver,
|
|
742
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
743
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
517
744
|
jobId,
|
|
518
|
-
scopes
|
|
745
|
+
scopes,
|
|
746
|
+
simulator,
|
|
747
|
+
hooks: composeHooks({
|
|
748
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets)
|
|
749
|
+
}),
|
|
750
|
+
utilityExecutor,
|
|
751
|
+
// Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
|
|
752
|
+
transientArrayService: new TransientArrayService()
|
|
519
753
|
});
|
|
520
|
-
const acirExecutionResult = await
|
|
754
|
+
const acirExecutionResult = await simulator.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle)).catch((err)=>{
|
|
521
755
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
522
756
|
throw new ExecutionError(err.message, {
|
|
523
757
|
contractAddress: call.to,
|
|
@@ -534,13 +768,33 @@ export class TXEOracleTopLevelContext {
|
|
|
534
768
|
}
|
|
535
769
|
close() {
|
|
536
770
|
this.logger.debug('Exiting Top Level Context');
|
|
537
|
-
return
|
|
538
|
-
this.nextBlockTimestamp,
|
|
539
|
-
this.authwits
|
|
540
|
-
|
|
771
|
+
return {
|
|
772
|
+
nextBlockTimestamp: this.nextBlockTimestamp,
|
|
773
|
+
authwits: this.authwits,
|
|
774
|
+
taggingSecretStrategies: this.taggingSecretStrategies,
|
|
775
|
+
authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets
|
|
776
|
+
};
|
|
541
777
|
}
|
|
542
778
|
async getLastBlockNumber() {
|
|
543
|
-
const
|
|
544
|
-
return
|
|
779
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
780
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
781
|
+
}
|
|
782
|
+
buildAuthorizeUtilityCallHook(callerContext, authorizedTargets) {
|
|
783
|
+
if (this.authorizeAllUtilityCallTargets) {
|
|
784
|
+
return authorizeAllUtilityCallsHook;
|
|
785
|
+
}
|
|
786
|
+
if (authorizedTargets.length === 0) {
|
|
787
|
+
return undefined;
|
|
788
|
+
}
|
|
789
|
+
return (req)=>Promise.resolve({
|
|
790
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some((t)=>t.equals(req.target))
|
|
791
|
+
});
|
|
545
792
|
}
|
|
546
793
|
}
|
|
794
|
+
/**
|
|
795
|
+
* An `authorizeUtilityCall` hook that authorizes every cross-contract utility call.
|
|
796
|
+
*
|
|
797
|
+
* Backs the `aztec_txe_setAuthorizeAllUtilityCallTargets` oracle.
|
|
798
|
+
*/ export const authorizeAllUtilityCallsHook = ()=>Promise.resolve({
|
|
799
|
+
authorized: true
|
|
800
|
+
});
|