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