@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.b8a057fa

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dest/AuthRegistry-HMC7WEOJ.js +3 -0
  2. package/dest/AuthRegistry-HMC7WEOJ.js.map +7 -0
  3. package/dest/ContractClassRegistry-TXCDCFNC.js +3 -0
  4. package/dest/ContractClassRegistry-TXCDCFNC.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-2TZHWOTT.js +3 -0
  6. package/dest/ContractInstanceRegistry-2TZHWOTT.js.map +7 -0
  7. package/dest/FeeJuice-FDF3J2Q5.js +3 -0
  8. package/dest/FeeJuice-FDF3J2Q5.js.map +7 -0
  9. package/dest/HandshakeRegistry-C7JF4R54.js +3 -0
  10. package/dest/HandshakeRegistry-C7JF4R54.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-IGLO227K.js +3 -0
  12. package/dest/MultiCallEntrypoint-IGLO227K.js.map +7 -0
  13. package/dest/SchnorrAccount-KCIHUCXS.js +3 -0
  14. package/dest/SchnorrAccount-KCIHUCXS.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-PVR6XUSN.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-PVR6XUSN.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  18. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  19. package/dest/bin/check_txe_oracle_version.js +61 -0
  20. package/dest/bin/index.d.ts +1 -1
  21. package/dest/bin/index.js +3 -30
  22. package/dest/bin/index.js.map +7 -0
  23. package/dest/bin/oracle_test_server.d.ts +3 -0
  24. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  25. package/dest/bin/oracle_test_server.js +41 -0
  26. package/dest/chunk-32UHX7YY.js +3 -0
  27. package/dest/chunk-32UHX7YY.js.map +7 -0
  28. package/dest/chunk-FRF5YZEO.js +304 -0
  29. package/dest/chunk-FRF5YZEO.js.map +7 -0
  30. package/dest/chunk-O57S6W5S.js +260 -0
  31. package/dest/chunk-O57S6W5S.js.map +7 -0
  32. package/dest/constants.d.ts +7 -0
  33. package/dest/constants.d.ts.map +1 -0
  34. package/dest/constants.js +10 -0
  35. package/dest/dispatcher_pool.d.ts +67 -0
  36. package/dest/dispatcher_pool.d.ts.map +1 -0
  37. package/dest/dispatcher_pool.js +286 -0
  38. package/dest/index.d.ts +51 -7
  39. package/dest/index.d.ts.map +1 -1
  40. package/dest/index.js +75 -158
  41. package/dest/metafile.json +38497 -0
  42. package/dest/msgpackr_fr_extension.d.ts +2 -0
  43. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  44. package/dest/msgpackr_fr_extension.js +21 -0
  45. package/dest/oracle/interfaces.d.ts +65 -31
  46. package/dest/oracle/interfaces.d.ts.map +1 -1
  47. package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
  48. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  49. package/dest/oracle/test-resolver/default_fixtures.js +207 -0
  50. package/dest/oracle/test-resolver/index.d.ts +9 -0
  51. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  52. package/dest/oracle/test-resolver/index.js +32 -0
  53. package/dest/oracle/test-resolver/resolver.d.ts +48 -0
  54. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  55. package/dest/oracle/test-resolver/resolver.js +181 -0
  56. package/dest/oracle/txe_oracle_public_context.d.ts +41 -17
  57. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  58. package/dest/oracle/txe_oracle_public_context.js +69 -23
  59. package/dest/oracle/txe_oracle_registry.d.ts +169 -0
  60. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  61. package/dest/oracle/txe_oracle_registry.js +745 -0
  62. package/dest/oracle/txe_oracle_top_level_context.d.ts +66 -30
  63. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  64. package/dest/oracle/txe_oracle_top_level_context.js +630 -275
  65. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  66. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  67. package/dest/oracle/txe_oracle_version.js +14 -0
  68. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  69. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  70. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  71. package/dest/rpc_server.d.ts +14 -0
  72. package/dest/rpc_server.d.ts.map +1 -0
  73. package/dest/rpc_server.js +78 -0
  74. package/dest/rpc_translator.d.ts +112 -213
  75. package/dest/rpc_translator.d.ts.map +1 -1
  76. package/dest/rpc_translator.js +877 -550
  77. package/dest/server.bundle.js +3 -0
  78. package/dest/server.bundle.js.map +7 -0
  79. package/dest/state_machine/archiver.d.ts +23 -52
  80. package/dest/state_machine/archiver.d.ts.map +1 -1
  81. package/dest/state_machine/archiver.js +76 -99
  82. package/dest/state_machine/dummy_p2p_client.d.ts +31 -15
  83. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  84. package/dest/state_machine/dummy_p2p_client.js +63 -22
  85. package/dest/state_machine/global_variable_builder.d.ts +10 -4
  86. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  87. package/dest/state_machine/global_variable_builder.js +20 -5
  88. package/dest/state_machine/index.d.ts +14 -8
  89. package/dest/state_machine/index.d.ts.map +1 -1
  90. package/dest/state_machine/index.js +84 -27
  91. package/dest/state_machine/mock_epoch_cache.d.ts +29 -12
  92. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  93. package/dest/state_machine/mock_epoch_cache.js +50 -15
  94. package/dest/state_machine/synchronizer.d.ts +15 -6
  95. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  96. package/dest/state_machine/synchronizer.js +27 -13
  97. package/dest/txe_session.d.ts +102 -21
  98. package/dest/txe_session.d.ts.map +1 -1
  99. package/dest/txe_session.js +440 -76
  100. package/dest/utils/block_creation.d.ts +22 -7
  101. package/dest/utils/block_creation.d.ts.map +1 -1
  102. package/dest/utils/block_creation.js +40 -6
  103. package/dest/utils/encoding.d.ts +192 -0
  104. package/dest/utils/encoding.d.ts.map +1 -0
  105. package/dest/{util → utils}/encoding.js +8 -3
  106. package/dest/utils/expected_failure_error.d.ts +4 -0
  107. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  108. package/dest/utils/tx_effect_creation.d.ts +3 -3
  109. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  110. package/dest/utils/tx_effect_creation.js +3 -7
  111. package/dest/utils/txe_account_store.d.ts +10 -0
  112. package/dest/utils/txe_account_store.d.ts.map +1 -0
  113. package/dest/{util/txe_account_data_provider.js → utils/txe_account_store.js} +1 -1
  114. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  115. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  116. package/dest/utils/txe_artifact_resolver.js +161 -0
  117. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  118. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  119. package/dest/utils/txe_public_contract_data_source.js +51 -0
  120. package/dest/worker.bundle.js +3 -0
  121. package/dest/worker.bundle.js.map +7 -0
  122. package/dest/worker.d.ts +2 -0
  123. package/dest/worker.d.ts.map +1 -0
  124. package/dest/worker.js +92 -0
  125. package/package.json +40 -22
  126. package/src/bin/check_txe_oracle_version.ts +70 -0
  127. package/src/bin/index.ts +11 -2
  128. package/src/bin/oracle_test_server.ts +51 -0
  129. package/src/constants.ts +13 -0
  130. package/src/dispatcher_pool.ts +317 -0
  131. package/src/index.ts +113 -201
  132. package/src/msgpackr_fr_extension.ts +23 -0
  133. package/src/oracle/interfaces.ts +68 -36
  134. package/src/oracle/test-resolver/default_fixtures.ts +282 -0
  135. package/src/oracle/test-resolver/index.ts +44 -0
  136. package/src/oracle/test-resolver/resolver.ts +245 -0
  137. package/src/oracle/txe_oracle_public_context.ts +83 -28
  138. package/src/oracle/txe_oracle_registry.ts +536 -0
  139. package/src/oracle/txe_oracle_top_level_context.ts +539 -199
  140. package/src/oracle/txe_oracle_version.ts +17 -0
  141. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  142. package/src/rpc_server.ts +87 -0
  143. package/src/rpc_translator.ts +1086 -909
  144. package/src/state_machine/archiver.ts +82 -115
  145. package/src/state_machine/dummy_p2p_client.ts +96 -33
  146. package/src/state_machine/global_variable_builder.ts +28 -9
  147. package/src/state_machine/index.ts +118 -44
  148. package/src/state_machine/mock_epoch_cache.ts +63 -23
  149. package/src/state_machine/synchronizer.ts +36 -14
  150. package/src/txe_session.ts +719 -125
  151. package/src/utils/block_creation.ts +51 -15
  152. package/src/{util → utils}/encoding.ts +9 -3
  153. package/src/utils/tx_effect_creation.ts +4 -13
  154. package/src/{util/txe_account_data_provider.ts → utils/txe_account_store.ts} +1 -1
  155. package/src/utils/txe_artifact_resolver.ts +217 -0
  156. package/src/utils/txe_public_contract_data_source.ts +60 -0
  157. package/src/worker.ts +98 -0
  158. package/dest/util/encoding.d.ts +0 -121
  159. package/dest/util/encoding.d.ts.map +0 -1
  160. package/dest/util/expected_failure_error.d.ts +0 -4
  161. package/dest/util/expected_failure_error.d.ts.map +0 -1
  162. package/dest/util/txe_account_data_provider.d.ts +0 -10
  163. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  164. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  165. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
  166. package/dest/util/txe_contract_data_provider.js +0 -22
  167. package/dest/util/txe_public_contract_data_source.d.ts +0 -20
  168. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  169. package/dest/util/txe_public_contract_data_source.js +0 -67
  170. package/src/util/txe_contract_data_provider.ts +0 -36
  171. package/src/util/txe_public_contract_data_source.ts +0 -85
  172. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  173. /package/src/{util → utils}/expected_failure_error.ts +0 -0
@@ -1,155 +1,337 @@
1
- import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT, DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
- import { Schnorr } from '@aztec/foundation/crypto';
3
- import { Fr } from '@aztec/foundation/fields';
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';
67
+ import { BlockNumber } from '@aztec/foundation/branded-types';
68
+ import { Schnorr } from '@aztec/foundation/crypto/schnorr';
69
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
70
  import { LogLevels, applyStringFormatting, createLogger } from '@aztec/foundation/log';
5
71
  import { TestDateProvider } from '@aztec/foundation/timer';
6
- import { ORACLE_VERSION, enrichPublicSimulationError } from '@aztec/pxe/server';
7
- import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
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';
8
74
  import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
9
75
  import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, PublicTxSimulator } from '@aztec/simulator/server';
10
- import { FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
76
+ import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
11
77
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
78
+ import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
12
79
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
13
- import { Body, L2Block } from '@aztec/stdlib/block';
14
80
  import { computePartialAddress } from '@aztec/stdlib/contract';
15
- import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
16
- import { computeCalldataHash, siloNullifier } from '@aztec/stdlib/hash';
81
+ import { Gas, GasFees } from '@aztec/stdlib/gas';
82
+ import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
17
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';
18
86
  import { ChonkProof } from '@aztec/stdlib/proofs';
19
- import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/stdlib/testing';
87
+ import { makeGlobalVariables } from '@aztec/stdlib/testing';
20
88
  import { MerkleTreeId } from '@aztec/stdlib/trees';
21
89
  import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
22
- import { ForkCheckpoint } from '@aztec/world-state';
23
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
24
- import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlockHeader } from '../utils/block_creation.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';
92
+ import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
93
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
25
94
  export class TXEOracleTopLevelContext {
26
95
  stateMachine;
27
- contractDataProvider;
96
+ contractStore;
97
+ noteStore;
28
98
  keyStore;
29
- addressDataProvider;
30
- accountDataProvider;
31
- pxeOracleInterface;
99
+ addressStore;
100
+ accountStore;
101
+ senderTaggingStore;
102
+ recipientTaggingStore;
103
+ taggingSecretSourcesStore;
104
+ capsuleStore;
105
+ factStore;
106
+ privateEventStore;
32
107
  nextBlockTimestamp;
33
108
  version;
34
109
  chainId;
35
110
  authwits;
111
+ taggingSecretStrategy;
112
+ artifactResolver;
113
+ rootPath;
114
+ packageName;
36
115
  isMisc;
37
116
  isTxe;
38
117
  logger;
39
- constructor(stateMachine, contractDataProvider, keyStore, addressDataProvider, accountDataProvider, pxeOracleInterface, nextBlockTimestamp, version, chainId, authwits){
118
+ constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, taggingSecretSourcesStore, capsuleStore, factStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits, taggingSecretStrategy, artifactResolver, rootPath, packageName){
40
119
  this.stateMachine = stateMachine;
41
- this.contractDataProvider = contractDataProvider;
120
+ this.contractStore = contractStore;
121
+ this.noteStore = noteStore;
42
122
  this.keyStore = keyStore;
43
- this.addressDataProvider = addressDataProvider;
44
- this.accountDataProvider = accountDataProvider;
45
- this.pxeOracleInterface = pxeOracleInterface;
123
+ this.addressStore = addressStore;
124
+ this.accountStore = accountStore;
125
+ this.senderTaggingStore = senderTaggingStore;
126
+ this.recipientTaggingStore = recipientTaggingStore;
127
+ this.taggingSecretSourcesStore = taggingSecretSourcesStore;
128
+ this.capsuleStore = capsuleStore;
129
+ this.factStore = factStore;
130
+ this.privateEventStore = privateEventStore;
46
131
  this.nextBlockTimestamp = nextBlockTimestamp;
47
132
  this.version = version;
48
133
  this.chainId = chainId;
49
134
  this.authwits = authwits;
135
+ this.taggingSecretStrategy = taggingSecretStrategy;
136
+ this.artifactResolver = artifactResolver;
137
+ this.rootPath = rootPath;
138
+ this.packageName = packageName;
50
139
  this.isMisc = true;
51
140
  this.isTxe = true;
52
141
  this.logger = createLogger('txe:top_level_context');
53
142
  this.logger.debug('Entering Top Level Context');
54
143
  }
55
- utilityAssertCompatibleOracleVersion(version) {
56
- if (version !== ORACLE_VERSION) {
57
- throw new Error(`Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`);
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})`);
58
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;
59
158
  }
60
159
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
61
160
  // setup.
62
- utilityGetRandomField() {
161
+ getRandomField() {
63
162
  return Fr.random();
64
163
  }
65
164
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
66
- utilityDebugLog(level, message, fields) {
165
+ log(level, message, _fieldsSize, fields) {
67
166
  if (!LogLevels[level]) {
68
- throw new Error(`Invalid debug log level: ${level}`);
167
+ throw new Error(`Invalid log level: ${level}`);
69
168
  }
70
169
  const levelName = LogLevels[level];
71
170
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, {
72
171
  module: `${this.logger.module}:debug_log`
73
172
  });
173
+ return Promise.resolve();
74
174
  }
75
- async txeGetNextBlockNumber() {
76
- return await this.getLastBlockNumber() + 1;
175
+ getDefaultAddress() {
176
+ return DEFAULT_ADDRESS;
77
177
  }
78
- txeGetNextBlockTimestamp() {
178
+ async getNextBlockNumber() {
179
+ return BlockNumber(await this.getLastBlockNumber() + 1);
180
+ }
181
+ getNextBlockTimestamp() {
79
182
  return Promise.resolve(this.nextBlockTimestamp);
80
183
  }
81
- async txeGetLastBlockTimestamp() {
82
- return (await this.stateMachine.node.getBlockHeader('latest')).globalVariables.timestamp;
184
+ async getLastBlockTimestamp() {
185
+ return (await this.stateMachine.node.getBlockData('latest')).header.globalVariables.timestamp;
83
186
  }
84
- async txeGetLastTxEffects() {
85
- const block = await this.stateMachine.archiver.getBlock('latest');
187
+ async getLastTxEffects() {
188
+ const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
189
+ const block = await this.stateMachine.archiver.getBlock({
190
+ number: latestBlockNumber
191
+ });
86
192
  if (block.body.txEffects.length != 1) {
87
193
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
88
194
  throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
89
195
  }
90
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
+ }
91
201
  return {
92
202
  txHash: txEffects.txHash,
93
203
  noteHashes: txEffects.noteHashes,
94
- nullifiers: txEffects.nullifiers
204
+ nullifiers: txEffects.nullifiers,
205
+ privateLogs
95
206
  };
96
207
  }
97
- async txeAdvanceBlocksBy(blocks) {
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, {
225
+ contractAddress,
226
+ scopes: [
227
+ scope
228
+ ],
229
+ fromBlock: 0,
230
+ toBlock: await this.getLastBlockNumber() + 1
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;
239
+ }
240
+ async advanceBlocksBy(blocks) {
98
241
  this.logger.debug(`time traveling ${blocks} blocks`);
99
242
  for(let i = 0; i < blocks; i++){
100
243
  await this.mineBlock();
101
244
  }
102
245
  }
103
- txeAdvanceTimestampBy(duration) {
246
+ advanceTimestampBy(duration) {
104
247
  this.logger.debug(`time traveling ${duration} seconds`);
105
248
  this.nextBlockTimestamp += duration;
106
249
  }
107
- async txeDeploy(artifact, instance, secret) {
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
+ });
108
264
  // Emit deployment nullifier
109
265
  await this.mineBlock({
110
266
  nullifiers: [
111
- await siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), instance.address.toField())
267
+ await this.deploymentNullifier(instance.address)
112
268
  ]
113
269
  });
114
270
  if (!secret.equals(Fr.ZERO)) {
115
- await this.txeAddAccount(artifact, instance, secret);
271
+ await this.registerContractAndAddAccount(artifact, instance, secret);
116
272
  } else {
117
- await this.contractDataProvider.addContractInstance(instance);
118
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
273
+ await this.contractStore.addContractInstance(instance);
274
+ await this.contractStore.addContractArtifact(artifact);
119
275
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
120
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
+ });
121
285
  }
122
- async txeAddAccount(artifact, instance, secret) {
286
+ async addAccount(secret) {
287
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
288
+ return this.registerContractAndAddAccount(artifact, instance, secret);
289
+ }
290
+ async registerContractAndAddAccount(artifact, instance, secret) {
123
291
  const partialAddress = await computePartialAddress(instance);
124
292
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
125
- await this.contractDataProvider.addContractInstance(instance);
126
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
127
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
128
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
129
- await this.addressDataProvider.addCompleteAddress(completeAddress);
293
+ await this.contractStore.addContractInstance(instance);
294
+ await this.contractStore.addContractArtifact(artifact);
295
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
296
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
297
+ await this.addressStore.addCompleteAddress(completeAddress);
130
298
  this.logger.debug(`Created account ${completeAddress.address}`);
131
299
  return completeAddress;
132
300
  }
133
- async txeCreateAccount(secret) {
134
- // This is a footgun !
135
- const completeAddress = await this.keyStore.addAccount(secret, secret);
136
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
137
- await this.addressDataProvider.addCompleteAddress(completeAddress);
301
+ async createAccount(secret) {
302
+ // This is a foot gun !
303
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), secret);
304
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
305
+ await this.addressStore.addCompleteAddress(completeAddress);
138
306
  this.logger.debug(`Created account ${completeAddress.address}`);
139
307
  return completeAddress;
140
308
  }
141
- async txeAddAuthWitness(address, messageHash) {
142
- const account = await this.accountDataProvider.getAccount(address);
143
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
309
+ async addAuthWitness(address, messageHash) {
310
+ const account = await this.accountStore.getAccount(address);
311
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
312
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
144
313
  const schnorr = new Schnorr();
145
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
146
- const authWitness = new AuthWitness(messageHash, [
147
- ...signature.toBuffer()
148
- ]);
314
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
315
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
149
316
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
150
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
+ }
151
333
  async mineBlock(options = {}) {
152
- const blockNumber = await this.txeGetNextBlockNumber();
334
+ const blockNumber = await this.getNextBlockNumber();
153
335
  const txEffect = TxEffect.empty();
154
336
  txEffect.nullifiers = [
155
337
  getSingleTxBlockRequestHash(blockNumber),
@@ -157,235 +339,359 @@ export class TXEOracleTopLevelContext {
157
339
  ];
158
340
  txEffect.txHash = new TxHash(new Fr(blockNumber));
159
341
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
160
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
161
- const block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, makeGlobalVariables(undefined, {
342
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
343
+ const globals = makeGlobalVariables(undefined, {
162
344
  blockNumber,
163
345
  timestamp: this.nextBlockTimestamp,
164
346
  version: this.version,
165
347
  chainId: this.chainId
166
- })), new Body([
348
+ });
349
+ const block = await makeTXEBlock(forkedWorldTrees, globals, [
167
350
  txEffect
168
- ]));
351
+ ]);
169
352
  await forkedWorldTrees.close();
170
353
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
171
- await this.stateMachine.handleL2Block(block);
354
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
172
355
  }
173
- async txePrivateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false) {
174
- this.logger.verbose(`Executing external function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
175
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
176
- if (!artifact) {
177
- const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
178
- throw new Error(message);
179
- }
180
- const blockNumber = await this.txeGetNextBlockNumber();
181
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
182
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
183
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
184
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
185
- const txContext = new TxContext(this.chainId, this.version, gasSettings);
186
- const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
187
- const txRequestHash = getSingleTxBlockRequestHash(blockNumber);
188
- const noteCache = new ExecutionNoteCache(txRequestHash);
189
- const taggingIndexCache = new ExecutionTaggingIndexCache();
190
- const simulator = new WASMSimulator();
191
- 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, /** 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([
192
- new HashedValues(args, argsHash)
193
- ]), noteCache, taggingIndexCache, this.pxeOracleInterface, 0, 1, undefined, undefined, /**
194
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
195
- * contract would perform, including setting senderForTags.
196
- */ from, simulator);
197
- // Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
198
- let result;
199
- let executionResult;
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
361
+ };
200
362
  try {
201
- executionResult = await executePrivateFunction(simulator, privateExecutionOracle, artifact, targetContractAddress, functionSelector);
202
- const publicCallRequests = collectNested([
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([
203
518
  executionResult
204
- ], (r)=>r.publicInputs.publicCallRequests.getActiveItems().map((r)=>r.inner).concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [
205
- r.publicInputs.publicTeardownCallRequest
206
- ]));
207
- const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
208
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
209
- return new HashedValues(calldata, r.calldataHash);
210
- }));
211
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
212
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
213
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
214
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
215
- } catch (err) {
216
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
217
- }
218
- // According to the protocol rules, the nonce generator for the note hashes
219
- // can either be the first nullifier in the tx or the hash of the initial tx request
220
- // if there are none.
221
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? txRequestHash : result.firstNullifier;
222
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
223
- const globals = makeGlobalVariables();
224
- globals.blockNumber = blockNumber;
225
- globals.timestamp = this.nextBlockTimestamp;
226
- globals.chainId = this.chainId;
227
- globals.version = this.version;
228
- globals.gasFees = GasFees.empty();
229
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
230
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
231
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
232
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, {
233
- doMerkleOperations: true,
234
- skipFeeEnforcement: true
235
- }), new TestDateProvider());
236
- const tx = await Tx.create({
237
- data: publicInputs,
238
- chonkProof: ChonkProof.empty(),
239
- contractClassLogFields: [],
240
- publicFunctionCalldata: result.publicFunctionCalldata
241
- });
242
- let checkpoint;
243
- if (isStaticCall) {
244
- checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
245
- }
246
- const results = await processor.process([
247
- tx
248
- ]);
249
- const [processedTx] = results[0];
250
- const failedTxs = results[1];
251
- if (failedTxs.length !== 0) {
252
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
253
- } else if (!processedTx.revertCode.isOK()) {
254
- if (processedTx.revertReason) {
255
- try {
256
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
257
- // eslint-disable-next-line no-empty
258
- } catch {}
259
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
260
- } else {
261
- 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
+ };
262
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;
263
550
  }
264
- if (isStaticCall) {
265
- await checkpoint.revert();
266
- await forkedWorldTrees.close();
267
- return executionResult.returnValues ?? [];
268
- }
269
- const txEffect = TxEffect.empty();
270
- txEffect.noteHashes = processedTx.txEffect.noteHashes;
271
- txEffect.nullifiers = processedTx.txEffect.nullifiers;
272
- txEffect.privateLogs = processedTx.txEffect.privateLogs;
273
- txEffect.publicLogs = processedTx.txEffect.publicLogs;
274
- txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
275
- txEffect.txHash = new TxHash(new Fr(blockNumber));
276
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
277
- await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
278
- const body = new Body([
279
- txEffect
280
- ]);
281
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, globals), body);
282
- await this.stateMachine.handleL2Block(l2Block);
283
- await forkedWorldTrees.close();
284
- return executionResult.returnValues ?? [];
285
- }
286
- async txePublicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
287
- this.logger.verbose(`Executing public function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
288
- const blockNumber = await this.txeGetNextBlockNumber();
289
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
290
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
291
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
292
- const txContext = new TxContext(this.chainId, this.version, gasSettings);
293
- const anchorBlockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
294
- const calldataHash = await computeCalldataHash(calldata);
295
- const calldataHashedValues = new HashedValues(calldata, calldataHash);
296
- const globals = makeGlobalVariables();
297
- globals.blockNumber = blockNumber;
298
- globals.timestamp = this.nextBlockTimestamp;
299
- globals.chainId = this.chainId;
300
- globals.version = this.version;
301
- globals.gasFees = GasFees.empty();
302
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
303
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
304
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
305
- const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, {
306
- doMerkleOperations: true,
307
- skipFeeEnforcement: true
308
- });
309
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
310
- // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
311
- // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
312
- // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
313
- // unique.
314
- const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
315
- if (!isStaticCall) {
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();
316
592
  nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
317
- }
318
- // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
319
- // may require producing reverts.
320
- const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
321
- revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
322
- const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
323
- const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
324
- const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*includeByTimestamp=*/ 0n, inputsForPublic, undefined);
325
- const tx = await Tx.create({
326
- data: txData,
327
- chonkProof: ChonkProof.empty(),
328
- contractClassLogFields: [],
329
- publicFunctionCalldata: [
330
- calldataHashedValues
331
- ]
332
- });
333
- let checkpoint;
334
- if (isStaticCall) {
335
- checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
336
- }
337
- const results = await processor.process([
338
- tx
339
- ]);
340
- const [processedTx] = results[0];
341
- const failedTxs = results[1];
342
- if (failedTxs.length !== 0) {
343
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
344
- } else if (!processedTx.revertCode.isOK()) {
345
- if (processedTx.revertReason) {
346
- try {
347
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
348
- // eslint-disable-next-line no-empty
349
- } catch {}
350
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
351
- } else {
352
- throw new Error('Contract execution has reverted');
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);
353
611
  }
354
- }
355
- const returnValues = results[3][0].values;
356
- if (isStaticCall) {
357
- await checkpoint.revert();
358
- await forkedWorldTrees.close();
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);
359
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;
360
655
  }
361
- const txEffect = TxEffect.empty();
362
- txEffect.noteHashes = processedTx.txEffect.noteHashes;
363
- txEffect.nullifiers = processedTx.txEffect.nullifiers;
364
- txEffect.privateLogs = processedTx.txEffect.privateLogs;
365
- txEffect.publicLogs = processedTx.txEffect.publicLogs;
366
- txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
367
- txEffect.txHash = new TxHash(new Fr(blockNumber));
368
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
369
- await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
370
- const body = new Body([
371
- txEffect
372
- ]);
373
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, globals), body);
374
- await this.stateMachine.handleL2Block(l2Block);
375
- await forkedWorldTrees.close();
376
- return returnValues ?? [];
377
656
  }
378
- async txeSimulateUtilityFunction(targetContractAddress, functionSelector, args) {
379
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
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);
380
661
  if (!artifact) {
381
662
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
382
663
  }
383
- const call = {
664
+ // Sync notes before executing utility function to discover notes from previous transactions
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({
384
672
  name: artifact.name,
673
+ to: targetContractAddress,
385
674
  selector: functionSelector,
386
- to: targetContractAddress
387
- };
388
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
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
686
+ });
687
+ }
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
+ }
389
695
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
390
696
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
391
697
  }
@@ -394,8 +700,47 @@ export class TXEOracleTopLevelContext {
394
700
  selector: call.selector
395
701
  });
396
702
  try {
397
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface);
398
- const acirExecutionResult = await new WASMSimulator().executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
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)=>{
399
744
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
400
745
  throw new ExecutionError(err.message, {
401
746
  contractAddress: call.to,
@@ -404,20 +749,30 @@ export class TXEOracleTopLevelContext {
404
749
  cause: err
405
750
  });
406
751
  });
407
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
752
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
408
753
  return witnessMapToFields(acirExecutionResult.returnWitness);
409
754
  } catch (err) {
410
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
755
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
411
756
  }
412
757
  }
413
758
  close() {
414
759
  this.logger.debug('Exiting Top Level Context');
415
760
  return [
416
761
  this.nextBlockTimestamp,
417
- this.authwits
762
+ this.authwits,
763
+ this.taggingSecretStrategy
418
764
  ];
419
765
  }
420
766
  async getLastBlockNumber() {
421
- return (await this.stateMachine.node.getBlockHeader('latest'))?.globalVariables.blockNumber ?? 0;
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
+ });
422
777
  }
423
778
  }