@aztec/simulator 3.0.0-canary.a9708bd → 3.0.0-devnet.2

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 (165) hide show
  1. package/dest/private/acvm_native.d.ts +1 -2
  2. package/dest/private/acvm_native.d.ts.map +1 -1
  3. package/dest/private/circuit_recording/simulator_recorder_wrapper.d.ts +1 -1
  4. package/dest/private/circuit_recording/simulator_recorder_wrapper.d.ts.map +1 -1
  5. package/dest/public/avm/avm_execution_environment.d.ts +2 -1
  6. package/dest/public/avm/avm_execution_environment.d.ts.map +1 -1
  7. package/dest/public/avm/avm_execution_environment.js +5 -2
  8. package/dest/public/avm/avm_gas.js +2 -2
  9. package/dest/public/avm/avm_memory_types.d.ts +6 -0
  10. package/dest/public/avm/avm_memory_types.d.ts.map +1 -1
  11. package/dest/public/avm/avm_memory_types.js +9 -2
  12. package/dest/public/avm/avm_simulator.d.ts +1 -1
  13. package/dest/public/avm/avm_simulator.d.ts.map +1 -1
  14. package/dest/public/avm/avm_simulator.js +14 -21
  15. package/dest/public/avm/errors.d.ts +5 -14
  16. package/dest/public/avm/errors.d.ts.map +1 -1
  17. package/dest/public/avm/errors.js +7 -20
  18. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts +2 -1
  19. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
  20. package/dest/public/avm/fixtures/avm_simulation_tester.js +2 -3
  21. package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts +2 -0
  22. package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -1
  23. package/dest/public/avm/fixtures/base_avm_simulation_tester.js +22 -0
  24. package/dest/public/avm/fixtures/initializers.d.ts.map +1 -1
  25. package/dest/public/avm/fixtures/initializers.js +2 -2
  26. package/dest/public/avm/opcodes/accrued_substate.d.ts +2 -2
  27. package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
  28. package/dest/public/avm/opcodes/accrued_substate.js +7 -7
  29. package/dest/public/avm/opcodes/addressing_mode.d.ts.map +1 -1
  30. package/dest/public/avm/opcodes/addressing_mode.js +2 -3
  31. package/dest/public/avm/opcodes/conversion.d.ts.map +1 -1
  32. package/dest/public/avm/opcodes/conversion.js +3 -0
  33. package/dest/public/avm/opcodes/ec_add.d.ts.map +1 -1
  34. package/dest/public/avm/opcodes/ec_add.js +3 -2
  35. package/dest/public/avm/opcodes/environment_getters.d.ts.map +1 -1
  36. package/dest/public/avm/opcodes/environment_getters.js +5 -7
  37. package/dest/public/avm/opcodes/instruction.d.ts.map +1 -1
  38. package/dest/public/avm/opcodes/instruction.js +5 -6
  39. package/dest/public/avm/opcodes/misc.d.ts +2 -1
  40. package/dest/public/avm/opcodes/misc.d.ts.map +1 -1
  41. package/dest/public/avm/opcodes/misc.js +28 -8
  42. package/dest/public/avm/serialization/instruction_serialization.d.ts +8 -0
  43. package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
  44. package/dest/public/avm/serialization/instruction_serialization.js +10 -0
  45. package/dest/public/avm/test_utils.d.ts +2 -2
  46. package/dest/public/avm/test_utils.d.ts.map +1 -1
  47. package/dest/public/avm/test_utils.js +6 -9
  48. package/dest/public/fixtures/bulk_test.d.ts.map +1 -1
  49. package/dest/public/fixtures/bulk_test.js +63 -130
  50. package/dest/public/fixtures/custom_bytecode_tester.d.ts +12 -0
  51. package/dest/public/fixtures/custom_bytecode_tester.d.ts.map +1 -0
  52. package/dest/public/fixtures/custom_bytecode_tester.js +29 -0
  53. package/dest/public/fixtures/custom_bytecode_tests.d.ts +9 -0
  54. package/dest/public/fixtures/custom_bytecode_tests.d.ts.map +1 -0
  55. package/dest/public/fixtures/custom_bytecode_tests.js +109 -0
  56. package/dest/public/fixtures/index.d.ts +2 -1
  57. package/dest/public/fixtures/index.d.ts.map +1 -1
  58. package/dest/public/fixtures/index.js +2 -1
  59. package/dest/public/fixtures/minimal_public_tx.d.ts +2 -1
  60. package/dest/public/fixtures/minimal_public_tx.d.ts.map +1 -1
  61. package/dest/public/fixtures/minimal_public_tx.js +8 -22
  62. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +4 -2
  63. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  64. package/dest/public/fixtures/public_tx_simulation_tester.js +11 -6
  65. package/dest/public/fixtures/utils.js +1 -1
  66. package/dest/public/hinting_db_sources.d.ts +2 -0
  67. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  68. package/dest/public/hinting_db_sources.js +3 -0
  69. package/dest/public/index.d.ts +1 -1
  70. package/dest/public/index.d.ts.map +1 -1
  71. package/dest/public/public_db_sources.d.ts +2 -2
  72. package/dest/public/public_db_sources.d.ts.map +1 -1
  73. package/dest/public/public_db_sources.js +11 -1
  74. package/dest/public/public_errors.d.ts +12 -0
  75. package/dest/public/public_errors.d.ts.map +1 -0
  76. package/dest/public/public_errors.js +13 -0
  77. package/dest/public/public_processor/guarded_merkle_tree.d.ts +2 -0
  78. package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
  79. package/dest/public/public_processor/guarded_merkle_tree.js +3 -0
  80. package/dest/public/public_processor/public_processor.d.ts +9 -4
  81. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  82. package/dest/public/public_processor/public_processor.js +33 -16
  83. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts +41 -0
  84. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts.map +1 -0
  85. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.js +89 -0
  86. package/dest/public/public_tx_simulator/index.d.ts +1 -0
  87. package/dest/public/public_tx_simulator/index.d.ts.map +1 -1
  88. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts +5 -4
  89. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts.map +1 -1
  90. package/dest/public/public_tx_simulator/measured_public_tx_simulator.js +3 -4
  91. package/dest/public/public_tx_simulator/public_tx_context.d.ts +4 -2
  92. package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
  93. package/dest/public/public_tx_simulator/public_tx_context.js +12 -8
  94. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +24 -11
  95. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  96. package/dest/public/public_tx_simulator/public_tx_simulator.js +112 -44
  97. package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts +9 -0
  98. package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts.map +1 -0
  99. package/dest/public/public_tx_simulator/public_tx_simulator_interface.js +1 -0
  100. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts +2 -1
  101. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts.map +1 -1
  102. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.js +2 -2
  103. package/dest/public/side_effect_errors.d.ts +41 -1
  104. package/dest/public/side_effect_errors.d.ts.map +1 -1
  105. package/dest/public/side_effect_errors.js +70 -1
  106. package/dest/public/side_effect_trace.d.ts +11 -4
  107. package/dest/public/side_effect_trace.d.ts.map +1 -1
  108. package/dest/public/side_effect_trace.js +35 -20
  109. package/dest/public/side_effect_trace_interface.d.ts +6 -0
  110. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  111. package/dest/public/state_manager/nullifiers.d.ts +0 -3
  112. package/dest/public/state_manager/nullifiers.d.ts.map +1 -1
  113. package/dest/public/state_manager/nullifiers.js +1 -6
  114. package/dest/public/state_manager/state_manager.d.ts +7 -2
  115. package/dest/public/state_manager/state_manager.d.ts.map +1 -1
  116. package/dest/public/state_manager/state_manager.js +54 -15
  117. package/package.json +21 -17
  118. package/src/private/acvm_native.ts +1 -2
  119. package/src/private/circuit_recording/simulator_recorder_wrapper.ts +1 -1
  120. package/src/public/avm/avm_execution_environment.ts +4 -1
  121. package/src/public/avm/avm_gas.ts +2 -2
  122. package/src/public/avm/avm_memory_types.ts +11 -2
  123. package/src/public/avm/avm_simulator.ts +16 -27
  124. package/src/public/avm/errors.ts +7 -24
  125. package/src/public/avm/fixtures/avm_simulation_tester.ts +4 -2
  126. package/src/public/avm/fixtures/base_avm_simulation_tester.ts +32 -0
  127. package/src/public/avm/fixtures/initializers.ts +2 -1
  128. package/src/public/avm/opcodes/accrued_substate.ts +4 -4
  129. package/src/public/avm/opcodes/addressing_mode.ts +3 -3
  130. package/src/public/avm/opcodes/conversion.ts +4 -0
  131. package/src/public/avm/opcodes/ec_add.ts +3 -2
  132. package/src/public/avm/opcodes/environment_getters.ts +6 -8
  133. package/src/public/avm/opcodes/instruction.ts +8 -6
  134. package/src/public/avm/opcodes/misc.ts +41 -7
  135. package/src/public/avm/serialization/instruction_serialization.ts +12 -0
  136. package/src/public/avm/test_utils.ts +6 -14
  137. package/src/public/fixtures/bulk_test.ts +41 -23
  138. package/src/public/fixtures/custom_bytecode_tester.ts +49 -0
  139. package/src/public/fixtures/custom_bytecode_tests.ts +135 -0
  140. package/src/public/fixtures/index.ts +2 -1
  141. package/src/public/fixtures/minimal_public_tx.ts +8 -31
  142. package/src/public/fixtures/public_tx_simulation_tester.ts +16 -12
  143. package/src/public/fixtures/utils.ts +1 -1
  144. package/src/public/hinting_db_sources.ts +5 -0
  145. package/src/public/index.ts +6 -1
  146. package/src/public/public_db_sources.ts +19 -3
  147. package/src/public/public_errors.ts +14 -0
  148. package/src/public/public_processor/guarded_merkle_tree.ts +4 -0
  149. package/src/public/public_processor/public_processor.ts +46 -39
  150. package/src/public/public_tx_simulator/cpp_public_tx_simulator.ts +128 -0
  151. package/src/public/public_tx_simulator/index.ts +1 -0
  152. package/src/public/public_tx_simulator/measured_public_tx_simulator.ts +12 -9
  153. package/src/public/public_tx_simulator/public_tx_context.ts +11 -4
  154. package/src/public/public_tx_simulator/public_tx_simulator.ts +178 -60
  155. package/src/public/public_tx_simulator/public_tx_simulator_interface.ts +11 -0
  156. package/src/public/public_tx_simulator/telemetry_public_tx_simulator.ts +3 -12
  157. package/src/public/side_effect_errors.ts +91 -1
  158. package/src/public/side_effect_trace.ts +48 -23
  159. package/src/public/side_effect_trace_interface.ts +6 -0
  160. package/src/public/state_manager/nullifiers.ts +1 -7
  161. package/src/public/state_manager/state_manager.ts +73 -25
  162. package/dest/public/bytecode_errors.d.ts +0 -4
  163. package/dest/public/bytecode_errors.d.ts.map +0 -1
  164. package/dest/public/bytecode_errors.js +0 -6
  165. package/src/public/bytecode_errors.ts +0 -6
@@ -0,0 +1,49 @@
1
+ import { FunctionType, emptyContractArtifact, emptyFunctionArtifact } from '@aztec/stdlib/abi';
2
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+
4
+ import type { PublicTxResult } from '../public_tx_simulator/public_tx_simulator.js';
5
+ import { PublicTxSimulationTester } from './public_tx_simulation_tester.js';
6
+
7
+ /**
8
+ *
9
+ * Test custom bytecode (simulation or proving) with the provided bytecode.
10
+ * @param bytecode - The bytecode buffer to use
11
+ * @param tester - The tester to use (simulation or proving)
12
+ * @param txLabel - The label of the transaction
13
+ * @param contractName - The name of the contract (default: 'CustomBytecodeContract')
14
+ */
15
+ export async function testCustomBytecode(
16
+ bytecode: Buffer,
17
+ tester: PublicTxSimulationTester,
18
+ txLabel: string,
19
+ contractName: string = 'CustomBytecodeContract',
20
+ ): Promise<PublicTxResult> {
21
+ const deployer = AztecAddress.fromNumber(42);
22
+
23
+ const contractArtifact = emptyContractArtifact();
24
+ contractArtifact.name = contractName;
25
+ contractArtifact.functions = [emptyFunctionArtifact()];
26
+ contractArtifact.functions[0].name = 'public_dispatch';
27
+ contractArtifact.functions[0].functionType = FunctionType.PUBLIC;
28
+ contractArtifact.functions[0].bytecode = bytecode;
29
+
30
+ const testContract = await tester.registerAndDeployContract(
31
+ /*constructorArgs=*/ [],
32
+ deployer,
33
+ /*contractArtifact=*/ contractArtifact,
34
+ );
35
+
36
+ // EXECUTE! This means that if using AvmProvingTester subclass, it will PROVE the transaction!
37
+ return await tester.executeTxWithLabel(
38
+ /*txLabel=*/ txLabel,
39
+ /*sender=*/ deployer,
40
+ /*setupCalls=*/ [],
41
+ /*appCalls=*/ [
42
+ {
43
+ address: testContract.address,
44
+ fnName: 'public_dispatch',
45
+ args: [],
46
+ },
47
+ ],
48
+ );
49
+ }
@@ -0,0 +1,135 @@
1
+ import { strict as assert } from 'assert';
2
+
3
+ import { TypeTag } from '../avm/avm_memory_types.js';
4
+ import { Addressing, AddressingMode } from '../avm/opcodes/addressing_mode.js';
5
+ import { CalldataCopy, Jump, Return, Set } from '../avm/opcodes/index.js';
6
+ import { encodeToBytecode } from '../avm/serialization/bytecode_serialization.js';
7
+ import {
8
+ MAX_OPCODE_VALUE,
9
+ Opcode,
10
+ OperandType,
11
+ getOperandSize,
12
+ } from '../avm/serialization/instruction_serialization.js';
13
+ import { testCustomBytecode } from './custom_bytecode_tester.js';
14
+ import { PublicTxSimulationTester } from './public_tx_simulation_tester.js';
15
+
16
+ // First instruction resolved a base address (offset 0) which is uninitialized and therefore
17
+ // of invalid tag (FF). This will trigger an exceptional halt.
18
+ export async function addressingWithBaseTagIssueTest(isIndirect: boolean, tester: PublicTxSimulationTester) {
19
+ const addressingMode = Addressing.fromModes([
20
+ isIndirect ? AddressingMode.INDIRECT_RELATIVE : AddressingMode.RELATIVE,
21
+ AddressingMode.DIRECT,
22
+ AddressingMode.DIRECT,
23
+ ]);
24
+
25
+ const bytecode = encodeToBytecode([
26
+ new CalldataCopy(/*indirect=*/ addressingMode.toWire(), /*copySize=*/ 1, /*cdOffset=*/ 0, /*dstOffset=*/ 0),
27
+ new Return(/*indirect=*/ 0, /*copySizeOffset=*/ 0, /*returnOffset=*/ 0),
28
+ ]);
29
+
30
+ const txLabel = isIndirect ? 'AddressingWithBaseTagInvalidIndirect' : 'AddressingWithBaseTagInvalidDirect';
31
+ return await testCustomBytecode(bytecode, tester, txLabel);
32
+ }
33
+
34
+ export async function pcOutOfRangeTest(tester: PublicTxSimulationTester) {
35
+ const bytecode = encodeToBytecode([
36
+ new Jump(/*jumpOffset=*/ 123), // Jump to out-of-range pc offset.
37
+ new Return(/*indirect=*/ 0, /*copySizeOffset=*/ 0, /*returnOffset=*/ 0),
38
+ ]);
39
+
40
+ const txLabel = 'PcOutOfRange';
41
+ return await testCustomBytecode(bytecode, tester, txLabel);
42
+ }
43
+
44
+ export async function invalidOpcodeTest(tester: PublicTxSimulationTester) {
45
+ let bytecode = encodeToBytecode([
46
+ new Set(/*indirect=*/ 0, /*dstOffset=*/ 0, TypeTag.UINT32, /*value=*/ 0).as(Opcode.SET_8, Set.wireFormat8),
47
+ ]);
48
+
49
+ const offsetReturnOpcodeByte = bytecode.length;
50
+
51
+ bytecode = Buffer.concat([
52
+ bytecode,
53
+ encodeToBytecode([new Return(/*indirect=*/ 0, /*copySizeOffset=*/ 0, /*returnOffset=*/ 0)]),
54
+ ]);
55
+
56
+ // Manipulate the Return opcode to make the opcode invalid (out of range).
57
+ bytecode[offsetReturnOpcodeByte] = MAX_OPCODE_VALUE + 1; // opcode is invalid.
58
+
59
+ const txLabel = 'InvalidOpcode';
60
+ return await testCustomBytecode(bytecode, tester, txLabel);
61
+ }
62
+
63
+ // Single invalid byte in the bytecode.
64
+ export async function invalidByteTest(tester: PublicTxSimulationTester) {
65
+ const invalidOpcode = MAX_OPCODE_VALUE + 7;
66
+ assert(invalidOpcode < 256, 'Invalid opcode must fit in a single byte');
67
+ const bytecode = Buffer.from([invalidOpcode]);
68
+
69
+ const txLabel = 'InvalidByte';
70
+ return await testCustomBytecode(bytecode, tester, txLabel);
71
+ }
72
+
73
+ // Truncate the last instruction in the bytecode.
74
+ export async function instructionTruncatedTest(tester: PublicTxSimulationTester) {
75
+ let bytecode = encodeToBytecode([
76
+ new Set(/*indirect=*/ 0, /*dstOffset=*/ 0, TypeTag.UINT32, /*value=*/ 0).as(Opcode.SET_8, Set.wireFormat8),
77
+ ]);
78
+
79
+ // Truncate the bytecode.
80
+ bytecode = bytecode.subarray(0, -1);
81
+
82
+ const txLabel = 'InstructionTruncated';
83
+ return await testCustomBytecode(bytecode, tester, txLabel);
84
+ }
85
+
86
+ // Invalid tag value byte in an instruction.
87
+ export async function invalidTagValueTest(tester: PublicTxSimulationTester) {
88
+ const bytecode = encodeToBytecode([
89
+ new Set(/*indirect=*/ 0, /*dstOffset=*/ 0, TypeTag.UINT32, /*value=*/ 0).as(Opcode.SET_8, Set.wireFormat8),
90
+ new Return(/*indirect=*/ 0, /*copySizeOffset=*/ 0, /*returnOffset=*/ 0),
91
+ ]);
92
+
93
+ const tagOffset = getTagOffsetInInstruction(Set.wireFormat8);
94
+ assert(bytecode[tagOffset].valueOf() == TypeTag.UINT32.valueOf(), 'Set instruction tag should be UINT32 in test');
95
+ bytecode[tagOffset] = TypeTag.INVALID;
96
+
97
+ const txLabel = 'InvalidTagValue';
98
+ return await testCustomBytecode(bytecode, tester, txLabel);
99
+ }
100
+
101
+ // Combine an invalid tag in the last instruction that is truncated.
102
+ export async function invalidTagValueAndInstructionTruncatedTest(tester: PublicTxSimulationTester) {
103
+ let bytecode = encodeToBytecode([
104
+ // Important: value argument must be a bigint otherwise a type error will be thrown.
105
+ new Set(/*indirect=*/ 0, /*dstOffset=*/ 0, TypeTag.UINT128, /*value=*/ 0n).as(Opcode.SET_128, Set.wireFormat128),
106
+ ]);
107
+
108
+ // Truncate the bytecode.
109
+ bytecode = bytecode.subarray(0, -5);
110
+ const tagOffset = getTagOffsetInInstruction(Set.wireFormat128);
111
+ assert(bytecode[tagOffset].valueOf() == TypeTag.UINT128.valueOf(), 'Set instruction tag should be UINT128 in test');
112
+ bytecode[tagOffset] = 0x6f; // Invalid tag value.
113
+
114
+ const txLabel = 'InvalidTagValueAndInstructionTruncated';
115
+ return await testCustomBytecode(bytecode, tester, txLabel);
116
+ }
117
+
118
+ /**
119
+ * Returns the offset of the tag in an instruction.
120
+ * @details Loops over the wire format operand type entries until it finds the tag.
121
+ * Returns the byte offset of the tag based on each operand size that is passed.
122
+ *
123
+ * @param wireFormat array of operand types
124
+ * @returns byte offset of the tag
125
+ */
126
+ function getTagOffsetInInstruction(wireFormat: OperandType[]): number {
127
+ let offset = 0;
128
+ for (const operand of wireFormat) {
129
+ if (operand === OperandType.TAG) {
130
+ break;
131
+ }
132
+ offset += getOperandSize(operand);
133
+ }
134
+ return offset;
135
+ }
@@ -1,8 +1,9 @@
1
1
  export * from './public_tx_simulation_tester.js';
2
2
  export * from './utils.js';
3
3
  export * from './simple_contract_data_source.js';
4
- export { readAvmMinimalPublicTxInputsFromFile, createAvmMinimalPublicTx } from './minimal_public_tx.js';
4
+ export { readAvmMinimalPublicTxInputsFromFile, executeAvmMinimalPublicTx } from './minimal_public_tx.js';
5
5
  export { TestExecutorMetrics } from '../test_executor_metrics.js';
6
6
  export { ammTest } from './amm_test.js';
7
7
  export { bulkTest, megaBulkTest } from './bulk_test.js';
8
8
  export { tokenTest } from './token_test.js';
9
+ export * from './custom_bytecode_tests.js';
@@ -1,6 +1,5 @@
1
- import { FunctionType, emptyContractArtifact, emptyFunctionArtifact } from '@aztec/stdlib/abi';
2
1
  import { AvmCircuitInputs } from '@aztec/stdlib/avm';
3
- import { AztecAddress } from '@aztec/stdlib/aztec-address';
2
+ import { ProtocolContracts } from '@aztec/stdlib/tx';
4
3
 
5
4
  import avmMinimalCircuitInputsJson from '../../../artifacts/avm_minimal_inputs.json' with { type: 'json' };
6
5
  import { TypeTag } from '../avm/avm_memory_types.js';
@@ -8,13 +7,10 @@ import { Add, Return, Set } from '../avm/opcodes/index.js';
8
7
  import { encodeToBytecode } from '../avm/serialization/bytecode_serialization.js';
9
8
  import { Opcode } from '../avm/serialization/instruction_serialization.js';
10
9
  import type { PublicTxResult } from '../public_tx_simulator/public_tx_simulator.js';
10
+ import { testCustomBytecode } from './custom_bytecode_tester.js';
11
11
  import { PublicTxSimulationTester } from './public_tx_simulation_tester.js';
12
12
 
13
- export async function createAvmMinimalPublicTx(): Promise<PublicTxResult> {
14
- const deployer = AztecAddress.fromNumber(42);
15
-
16
- const simTester = await PublicTxSimulationTester.create();
17
-
13
+ export async function executeAvmMinimalPublicTx(tester: PublicTxSimulationTester): Promise<PublicTxResult> {
18
14
  const minimalBytecode = encodeToBytecode([
19
15
  new Set(/*indirect*/ 0, /*dstOffset*/ 0, TypeTag.UINT32, /*value*/ 1).as(Opcode.SET_8, Set.wireFormat8),
20
16
  new Set(/*indirect*/ 0, /*dstOffset*/ 1, TypeTag.UINT32, /*value*/ 2).as(Opcode.SET_8, Set.wireFormat8),
@@ -22,32 +18,13 @@ export async function createAvmMinimalPublicTx(): Promise<PublicTxResult> {
22
18
  new Return(/*indirect=*/ 0, /*copySizeOffset=*/ 0, /*returnOffset=*/ 2),
23
19
  ]);
24
20
 
25
- const minimalContractArtifact = emptyContractArtifact();
26
- minimalContractArtifact.name = 'MinimalContract';
27
- minimalContractArtifact.functions = [emptyFunctionArtifact()];
28
- minimalContractArtifact.functions[0].name = 'public_dispatch';
29
- minimalContractArtifact.functions[0].functionType = FunctionType.PUBLIC;
30
- minimalContractArtifact.functions[0].bytecode = minimalBytecode;
21
+ const result = await testCustomBytecode(minimalBytecode, tester, 'MinimalTx', 'AvmMinimalContract');
31
22
 
32
- const minimalTestContract = await simTester.registerAndDeployContract(
33
- /*constructorArgs=*/ [],
34
- deployer,
35
- /*contractArtifact=*/ minimalContractArtifact,
36
- );
23
+ // Modify the protocol contracts to be all zeros
24
+ result.avmProvingRequest.inputs.hints.protocolContracts = ProtocolContracts.empty();
25
+ result.avmProvingRequest.inputs.publicInputs.protocolContracts = ProtocolContracts.empty();
37
26
 
38
- return await simTester.simulateTx(
39
- /*sender=*/ deployer,
40
- /*setupCalls=*/ [],
41
- /*appCalls=*/ [
42
- {
43
- address: minimalTestContract.address,
44
- fnName: 'public_dispatch',
45
- args: [],
46
- },
47
- ],
48
- /*teardownCall=*/ undefined,
49
- /*feePayer=*/ deployer,
50
- );
27
+ return result;
51
28
  }
52
29
 
53
30
  /**
@@ -16,8 +16,10 @@ import {
16
16
  getFunctionSelector,
17
17
  } from '../avm/fixtures/utils.js';
18
18
  import { PublicContractsDB } from '../public_db_sources.js';
19
+ import { MeasuredCppPublicTxSimulatorHintedDbs } from '../public_tx_simulator/cpp_public_tx_simulator.js';
19
20
  import { MeasuredPublicTxSimulator } from '../public_tx_simulator/measured_public_tx_simulator.js';
20
21
  import type { PublicTxResult } from '../public_tx_simulator/public_tx_simulator.js';
22
+ import type { MeasuredPublicTxSimulatorInterface } from '../public_tx_simulator/public_tx_simulator_interface.js';
21
23
  import { TestExecutorMetrics } from '../test_executor_metrics.js';
22
24
  import { SimpleContractDataSource } from './simple_contract_data_source.js';
23
25
  import { type TestPrivateInsertions, createTxForPublicCalls } from './utils.js';
@@ -40,7 +42,7 @@ export type TestEnqueuedCall = {
40
42
  */
41
43
  export class PublicTxSimulationTester extends BaseAvmSimulationTester {
42
44
  protected txCount: number = 0;
43
- private simulator: MeasuredPublicTxSimulator;
45
+ private simulator: MeasuredPublicTxSimulatorInterface;
44
46
  private metricsPrefix?: string;
45
47
 
46
48
  constructor(
@@ -48,28 +50,30 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
48
50
  contractDataSource: SimpleContractDataSource,
49
51
  globals: GlobalVariables = defaultGlobals(),
50
52
  private metrics: TestExecutorMetrics = new TestExecutorMetrics(),
53
+ useCppSimulator: boolean = false,
51
54
  ) {
52
55
  super(contractDataSource, merkleTree);
53
56
 
54
57
  const contractsDB = new PublicContractsDB(contractDataSource);
55
- this.simulator = new MeasuredPublicTxSimulator(
56
- merkleTree,
57
- contractsDB,
58
- globals,
59
- /*doMerkleOperations=*/ true,
60
- /*skipFeeEnforcement=*/ false,
61
- /*clientInitiatedSimulation=*/ true,
62
- this.metrics,
63
- );
58
+ const config = {
59
+ doMerkleOperations: true,
60
+ skipFeeEnforcement: false,
61
+ clientInitiatedSimulation: true,
62
+ };
63
+ this.simulator = useCppSimulator
64
+ ? new MeasuredCppPublicTxSimulatorHintedDbs(merkleTree, contractsDB, globals, this.metrics, config)
65
+ : new MeasuredPublicTxSimulator(merkleTree, contractsDB, globals, this.metrics, config);
64
66
  }
65
67
 
66
68
  public static async create(
69
+ worldStateService: NativeWorldStateService, // make sure to close this later
67
70
  globals: GlobalVariables = defaultGlobals(),
68
71
  metrics: TestExecutorMetrics = new TestExecutorMetrics(),
72
+ useCppSimulator = false,
69
73
  ): Promise<PublicTxSimulationTester> {
70
74
  const contractDataSource = new SimpleContractDataSource();
71
- const merkleTree = await (await NativeWorldStateService.tmp()).fork();
72
- return new PublicTxSimulationTester(merkleTree, contractDataSource, globals, metrics);
75
+ const merkleTree = await worldStateService.fork();
76
+ return new PublicTxSimulationTester(merkleTree, contractDataSource, globals, metrics, useCppSimulator);
73
77
  }
74
78
 
75
79
  public setMetricsPrefix(prefix: string) {
@@ -153,7 +153,7 @@ export async function createTxForPublicCalls(
153
153
 
154
154
  return await Tx.create({
155
155
  data: txData,
156
- clientIvcProof: ClientIvcProof.empty(),
156
+ clientIvcProof: ClientIvcProof.random(),
157
157
  contractClassLogFields: [],
158
158
  publicFunctionCalldata: calldata,
159
159
  });
@@ -40,6 +40,7 @@ import {
40
40
  } from '@aztec/stdlib/trees';
41
41
  import { TreeSnapshots } from '@aztec/stdlib/tx';
42
42
  import type { UInt64 } from '@aztec/stdlib/types';
43
+ import type { WorldStateRevision } from '@aztec/stdlib/world-state';
43
44
 
44
45
  import { strict as assert } from 'assert';
45
46
 
@@ -449,6 +450,10 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
449
450
  return this.db.getInitialHeader();
450
451
  }
451
452
 
453
+ public getRevision(): WorldStateRevision {
454
+ return this.db.getRevision();
455
+ }
456
+
452
457
  public async updateArchive(header: any): Promise<void> {
453
458
  return await this.db.updateArchive(header);
454
459
  }
@@ -1,5 +1,10 @@
1
1
  export { PublicContractsDB } from './public_db_sources.js';
2
2
  export { GuardedMerkleTreeOperations } from './public_processor/guarded_merkle_tree.js';
3
3
  export { PublicProcessor, PublicProcessorFactory } from './public_processor/public_processor.js';
4
- export { PublicTxSimulator, TelemetryPublicTxSimulator, type PublicTxResult } from './public_tx_simulator/index.js';
4
+ export {
5
+ PublicTxSimulator,
6
+ type PublicTxSimulatorConfig,
7
+ TelemetryPublicTxSimulator,
8
+ type PublicTxResult,
9
+ } from './public_tx_simulator/index.js';
5
10
  export { getCallRequestsWithCalldataByPhase } from './utils.js';
@@ -1,4 +1,9 @@
1
- import { NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT } from '@aztec/constants';
1
+ import {
2
+ L1_TO_L2_MSG_TREE_LEAF_COUNT,
3
+ NOTE_HASH_TREE_LEAF_COUNT,
4
+ NULLIFIER_SUBTREE_HEIGHT,
5
+ PUBLIC_DATA_SUBTREE_HEIGHT,
6
+ } from '@aztec/constants';
2
7
  import { Fr } from '@aztec/foundation/fields';
3
8
  import { createLogger } from '@aztec/foundation/log';
4
9
  import { Timer } from '@aztec/foundation/timer';
@@ -27,7 +32,10 @@ import {
27
32
  import { TreeSnapshots, type Tx } from '@aztec/stdlib/tx';
28
33
  import type { UInt64 } from '@aztec/stdlib/types';
29
34
 
35
+ import { strict as assert } from 'assert';
36
+
30
37
  import type { PublicContractsDBInterface, PublicStateDBInterface } from './db_interfaces.js';
38
+ import { L1ToL2MessageIndexOutOfRangeError, NoteHashIndexOutOfRangeError } from './side_effect_errors.js';
31
39
  import { TxContractCache } from './tx_contract_cache.js';
32
40
 
33
41
  /**
@@ -323,9 +331,13 @@ export class PublicTreesDB implements PublicStateDBInterface {
323
331
  } satisfies PublicDBAccessStats);
324
332
  }
325
333
 
326
- public async getL1ToL2LeafValue(leafIndex: bigint): Promise<Fr | undefined> {
334
+ public async getL1ToL2LeafValue(leafIndex: bigint): Promise<Fr> {
327
335
  const timer = new Timer();
336
+ if (leafIndex > L1_TO_L2_MSG_TREE_LEAF_COUNT) {
337
+ throw new L1ToL2MessageIndexOutOfRangeError(Number(leafIndex));
338
+ }
328
339
  const leafValue = await this.db.getLeafValue(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex);
340
+ assert(leafValue !== undefined, 'Unexpected null response from l1 to l2 message tree');
329
341
  // TODO: We need this for the hints. See class comment for more details.
330
342
  await this.db.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex);
331
343
 
@@ -337,9 +349,13 @@ export class PublicTreesDB implements PublicStateDBInterface {
337
349
  return leafValue;
338
350
  }
339
351
 
340
- public async getNoteHash(leafIndex: bigint): Promise<Fr | undefined> {
352
+ public async getNoteHash(leafIndex: bigint): Promise<Fr> {
341
353
  const timer = new Timer();
354
+ if (leafIndex > NOTE_HASH_TREE_LEAF_COUNT) {
355
+ throw new NoteHashIndexOutOfRangeError(Number(leafIndex));
356
+ }
342
357
  const leafValue = await this.db.getLeafValue(MerkleTreeId.NOTE_HASH_TREE, leafIndex);
358
+ assert(leafValue !== undefined, 'Unexpected null response from note hash tree');
343
359
  // TODO: We need this for the hints. See class comment for more details.
344
360
  await this.db.getSiblingPath(MerkleTreeId.NOTE_HASH_TREE, leafIndex);
345
361
 
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Any known (and checked) error that can be thrown during public execution.
3
+ * Includes AvmExecutionErrors and SideEffectErrors.
4
+ *
5
+ * AvmSimulator catches any checked errors before returning a boolean "reverted".
6
+ * Unchecked errors are generally the result of a bug. They are propagated and
7
+ * ultimately will be the resonsibility of PublicProcessor to handle.
8
+ */
9
+ export abstract class CheckedPublicExecutionError extends Error {
10
+ constructor(message: string) {
11
+ super(message);
12
+ this.name = 'CheckedPublicExecutionError';
13
+ }
14
+ }
@@ -11,6 +11,7 @@ import type {
11
11
  TreeInfo,
12
12
  } from '@aztec/stdlib/trees';
13
13
  import type { BlockHeader, StateReference } from '@aztec/stdlib/tx';
14
+ import type { WorldStateRevision } from '@aztec/stdlib/world-state';
14
15
 
15
16
  /**
16
17
  * Wraps an instance of `MerkleTreeWriteOperations` to allow the sequencer to gate access.
@@ -88,6 +89,9 @@ export class GuardedMerkleTreeOperations implements MerkleTreeWriteOperations {
88
89
  getInitialHeader(): BlockHeader {
89
90
  return this.target.getInitialHeader();
90
91
  }
92
+ public getRevision(): WorldStateRevision {
93
+ return this.target.getRevision();
94
+ }
91
95
  getSiblingPath<ID extends MerkleTreeId>(treeId: ID, index: bigint): Promise<SiblingPath<TreeHeights[ID]>> {
92
96
  return this.guardAndPush(() => this.target.getSiblingPath(treeId, index));
93
97
  }
@@ -27,7 +27,6 @@ import {
27
27
  StateReference,
28
28
  Tx,
29
29
  TxExecutionPhase,
30
- type TxValidator,
31
30
  makeProcessedTxFromPrivateOnlyTx,
32
31
  makeProcessedTxFromTxWithPublicCalls,
33
32
  } from '@aztec/stdlib/tx';
@@ -41,8 +40,14 @@ import {
41
40
  } from '@aztec/telemetry-client';
42
41
  import { ForkCheckpoint } from '@aztec/world-state/native';
43
42
 
43
+ import { AssertionError } from 'assert';
44
+
44
45
  import { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
45
- import { type PublicTxSimulator, TelemetryPublicTxSimulator } from '../public_tx_simulator/index.js';
46
+ import {
47
+ type PublicTxSimulator,
48
+ type PublicTxSimulatorConfig,
49
+ TelemetryPublicTxSimulator,
50
+ } from '../public_tx_simulator/index.js';
46
51
  import { GuardedMerkleTreeOperations } from './guarded_merkle_tree.js';
47
52
  import { PublicProcessorMetrics } from './public_processor_metrics.js';
48
53
 
@@ -58,7 +63,6 @@ export class PublicProcessorFactory {
58
63
 
59
64
  /**
60
65
  * Creates a new instance of a PublicProcessor.
61
- * @param historicalHeader - The header of a block previous to the one in which the tx is included.
62
66
  * @param globalVariables - The global variables for the block being processed.
63
67
  * @param skipFeeEnforcement - Allows disabling balance checks for fee estimations.
64
68
  * @returns A new instance of a PublicProcessor.
@@ -66,20 +70,23 @@ export class PublicProcessorFactory {
66
70
  public create(
67
71
  merkleTree: MerkleTreeWriteOperations,
68
72
  globalVariables: GlobalVariables,
69
- skipFeeEnforcement: boolean,
70
- clientInitiatedSimulation: boolean = false,
73
+ config: {
74
+ skipFeeEnforcement: boolean;
75
+ clientInitiatedSimulation: boolean;
76
+ proverId?: Fr;
77
+ maxDebugLogMemoryReads?: number;
78
+ },
71
79
  ): PublicProcessor {
72
80
  const contractsDB = new PublicContractsDB(this.contractDataSource);
73
81
 
74
82
  const guardedFork = new GuardedMerkleTreeOperations(merkleTree);
75
- const publicTxSimulator = this.createPublicTxSimulator(
76
- guardedFork,
77
- contractsDB,
78
- globalVariables,
79
- /*doMerkleOperations=*/ true,
80
- skipFeeEnforcement,
81
- clientInitiatedSimulation,
82
- );
83
+ const publicTxSimulator = this.createPublicTxSimulator(guardedFork, contractsDB, globalVariables, {
84
+ proverId: config.proverId,
85
+ doMerkleOperations: true,
86
+ skipFeeEnforcement: config.skipFeeEnforcement,
87
+ clientInitiatedSimulation: config.clientInitiatedSimulation,
88
+ maxDebugLogMemoryReads: config.maxDebugLogMemoryReads,
89
+ });
83
90
 
84
91
  return new PublicProcessor(
85
92
  globalVariables,
@@ -95,19 +102,9 @@ export class PublicProcessorFactory {
95
102
  merkleTree: MerkleTreeWriteOperations,
96
103
  contractsDB: PublicContractsDB,
97
104
  globalVariables: GlobalVariables,
98
- doMerkleOperations: boolean,
99
- skipFeeEnforcement: boolean,
100
- clientInitiatedSimulation: boolean,
105
+ config?: Partial<PublicTxSimulatorConfig>,
101
106
  ): PublicTxSimulator {
102
- return new TelemetryPublicTxSimulator(
103
- merkleTree,
104
- contractsDB,
105
- globalVariables,
106
- doMerkleOperations,
107
- skipFeeEnforcement,
108
- clientInitiatedSimulation,
109
- this.telemetryClient,
110
- );
107
+ return new TelemetryPublicTxSimulator(merkleTree, contractsDB, globalVariables, this.telemetryClient, config);
111
108
  }
112
109
  }
113
110
 
@@ -154,7 +151,7 @@ export class PublicProcessor implements Traceable {
154
151
  limits: PublicProcessorLimits = {},
155
152
  validator: PublicProcessorValidator = {},
156
153
  ): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[]]> {
157
- const { maxTransactions, maxBlockSize, deadline, maxBlockGas } = limits;
154
+ const { maxTransactions, maxBlockSize, deadline, maxBlockGas, maxBlobFields } = limits;
158
155
  const { preprocessValidator, nullifierCache } = validator;
159
156
  const result: ProcessedTx[] = [];
160
157
  const usedTxs: Tx[] = [];
@@ -165,6 +162,7 @@ export class PublicProcessor implements Traceable {
165
162
  let returns: NestedProcessReturnValues[] = [];
166
163
  let totalPublicGas = new Gas(0, 0);
167
164
  let totalBlockGas = new Gas(0, 0);
165
+ let totalBlobFields = 0;
168
166
 
169
167
  for await (const origTx of txs) {
170
168
  // Only process up to the max tx limit
@@ -252,6 +250,23 @@ export class PublicProcessor implements Traceable {
252
250
  continue;
253
251
  }
254
252
 
253
+ // If the actual blob fields of this tx would exceed the limit, skip it
254
+ const txBlobFields = processedTx.txEffect.toBlobFields().length;
255
+ if (maxBlobFields !== undefined && totalBlobFields + txBlobFields > maxBlobFields) {
256
+ this.log.debug(
257
+ `Skipping processed tx ${txHash} with ${txBlobFields} blob fields due to max blob fields limit.`,
258
+ {
259
+ txHash,
260
+ txBlobFields,
261
+ totalBlobFields,
262
+ maxBlobFields,
263
+ },
264
+ );
265
+ // Need to revert the checkpoint here and don't go any further
266
+ await checkpoint.revert();
267
+ continue;
268
+ }
269
+
255
270
  // FIXME(fcarreiro): it's ugly to have to notify the validator of nullifiers.
256
271
  // I'd rather pass the validators the processedTx as well and let them deal with it.
257
272
  nullifierCache?.addNullifiers(processedTx.txEffect.nullifiers.map(n => n.toBuffer()));
@@ -262,6 +277,7 @@ export class PublicProcessor implements Traceable {
262
277
  totalPublicGas = totalPublicGas.add(processedTx.gasUsed.publicGas);
263
278
  totalBlockGas = totalBlockGas.add(processedTx.gasUsed.totalGas);
264
279
  totalSizeInBytes += txSize;
280
+ totalBlobFields += txBlobFields;
265
281
  } catch (err: any) {
266
282
  if (err?.name === 'PublicProcessorTimeoutError') {
267
283
  this.log.warn(`Stopping tx processing due to timeout.`);
@@ -292,7 +308,7 @@ export class PublicProcessor implements Traceable {
292
308
  // Roll back state to start of TX before proceeding to next TX
293
309
  await checkpoint.revert();
294
310
  await this.guardedMerkleTree.getUnderlyingFork().revertAllCheckpoints();
295
- const errorMessage = err instanceof Error ? err.message : 'Unknown error';
311
+ const errorMessage = err instanceof Error || err instanceof AssertionError ? err.message : 'Unknown error';
296
312
  this.log.warn(`Failed to process tx ${txHash.toString()}: ${errorMessage} ${err?.stack}`);
297
313
  failed.push({ tx, error: err instanceof Error ? err : new Error(errorMessage) });
298
314
  returns.push(new NestedProcessReturnValues([]));
@@ -366,10 +382,7 @@ export class PublicProcessor implements Traceable {
366
382
  return [processedTx, returnValues ?? []];
367
383
  }
368
384
 
369
- private async doTreeInsertionsForPrivateOnlyTx(
370
- processedTx: ProcessedTx,
371
- txValidator?: TxValidator<ProcessedTx>,
372
- ): Promise<void> {
385
+ private async doTreeInsertionsForPrivateOnlyTx(processedTx: ProcessedTx): Promise<void> {
373
386
  const treeInsertionStart = process.hrtime.bigint();
374
387
 
375
388
  // Update the state so that the next tx in the loop has the correct .startState
@@ -388,14 +401,8 @@ export class PublicProcessor implements Traceable {
388
401
  padArrayEnd(processedTx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
389
402
  NULLIFIER_SUBTREE_HEIGHT,
390
403
  );
391
- } catch {
392
- if (txValidator) {
393
- // Ideally the validator has already caught this above, but just in case:
394
- throw new Error(`Transaction ${processedTx.hash} invalid after processing public functions`);
395
- } else {
396
- // We have no validator and assume this call should blindly process txs with duplicates being caught later
397
- this.log.warn(`Detected duplicate nullifier after public processing for: ${processedTx.hash}.`);
398
- }
404
+ } catch (cause) {
405
+ throw new Error(`Transaction ${processedTx.hash} failed with duplicate nullifiers`, { cause });
399
406
  }
400
407
 
401
408
  const treeInsertionEnd = process.hrtime.bigint();