@aztec/simulator 0.38.0 → 0.40.0

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 (143) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +3 -5
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +13 -32
  4. package/dest/acvm/oracle/typed_oracle.d.ts +3 -3
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +7 -7
  7. package/dest/avm/avm_execution_environment.d.ts +4 -3
  8. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  9. package/dest/avm/avm_execution_environment.js +17 -11
  10. package/dest/avm/avm_gas.d.ts.map +1 -1
  11. package/dest/avm/avm_gas.js +5 -1
  12. package/dest/avm/avm_machine_state.d.ts +5 -8
  13. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  14. package/dest/avm/avm_machine_state.js +10 -22
  15. package/dest/avm/avm_message_call_result.d.ts +5 -8
  16. package/dest/avm/avm_message_call_result.d.ts.map +1 -1
  17. package/dest/avm/avm_message_call_result.js +1 -4
  18. package/dest/avm/avm_simulator.d.ts.map +1 -1
  19. package/dest/avm/avm_simulator.js +17 -13
  20. package/dest/avm/errors.d.ts +43 -2
  21. package/dest/avm/errors.d.ts.map +1 -1
  22. package/dest/avm/errors.js +86 -4
  23. package/dest/avm/journal/journal.d.ts.map +1 -1
  24. package/dest/avm/journal/journal.js +4 -3
  25. package/dest/avm/opcodes/conversion.d.ts +16 -0
  26. package/dest/avm/opcodes/conversion.d.ts.map +1 -0
  27. package/dest/avm/opcodes/conversion.js +48 -0
  28. package/dest/avm/opcodes/environment_getters.d.ts +12 -13
  29. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  30. package/dest/avm/opcodes/environment_getters.js +13 -49
  31. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  32. package/dest/avm/opcodes/external_calls.js +11 -1
  33. package/dest/avm/opcodes/index.d.ts +2 -0
  34. package/dest/avm/opcodes/index.d.ts.map +1 -1
  35. package/dest/avm/opcodes/index.js +3 -1
  36. package/dest/avm/opcodes/misc.d.ts +17 -0
  37. package/dest/avm/opcodes/misc.d.ts.map +1 -0
  38. package/dest/avm/opcodes/misc.js +45 -0
  39. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  40. package/dest/avm/serialization/bytecode_serialization.js +6 -2
  41. package/dest/avm/serialization/instruction_serialization.d.ts +6 -4
  42. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  43. package/dest/avm/serialization/instruction_serialization.js +9 -5
  44. package/dest/client/client_execution_context.d.ts +29 -1
  45. package/dest/client/client_execution_context.d.ts.map +1 -1
  46. package/dest/client/client_execution_context.js +54 -16
  47. package/dest/client/db_oracle.d.ts +1 -8
  48. package/dest/client/db_oracle.d.ts.map +1 -1
  49. package/dest/client/execution_result.d.ts +4 -1
  50. package/dest/client/execution_result.d.ts.map +1 -1
  51. package/dest/client/execution_result.js +16 -3
  52. package/dest/client/private_execution.d.ts.map +1 -1
  53. package/dest/client/private_execution.js +3 -1
  54. package/dest/client/simulator.d.ts +1 -31
  55. package/dest/client/simulator.d.ts.map +1 -1
  56. package/dest/client/simulator.js +3 -42
  57. package/dest/client/view_data_oracle.d.ts +0 -7
  58. package/dest/client/view_data_oracle.d.ts.map +1 -1
  59. package/dest/client/view_data_oracle.js +1 -10
  60. package/dest/common/errors.d.ts +5 -0
  61. package/dest/common/errors.d.ts.map +1 -1
  62. package/dest/common/errors.js +6 -1
  63. package/dest/index.d.ts +1 -0
  64. package/dest/index.d.ts.map +1 -1
  65. package/dest/index.js +2 -1
  66. package/dest/public/abstract_phase_manager.d.ts +8 -4
  67. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  68. package/dest/public/abstract_phase_manager.js +38 -14
  69. package/dest/public/app_logic_phase_manager.d.ts +1 -0
  70. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  71. package/dest/public/app_logic_phase_manager.js +3 -3
  72. package/dest/public/executor.d.ts.map +1 -1
  73. package/dest/public/executor.js +1 -4
  74. package/dest/public/hints_builder.d.ts +3 -3
  75. package/dest/public/hints_builder.d.ts.map +1 -1
  76. package/dest/public/hints_builder.js +3 -3
  77. package/dest/public/public_execution_context.d.ts +1 -0
  78. package/dest/public/public_execution_context.d.ts.map +1 -1
  79. package/dest/public/public_execution_context.js +6 -2
  80. package/dest/public/public_processor.d.ts.map +1 -1
  81. package/dest/public/public_processor.js +5 -3
  82. package/dest/public/setup_phase_manager.d.ts +1 -0
  83. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  84. package/dest/public/setup_phase_manager.js +3 -2
  85. package/dest/public/tail_phase_manager.d.ts +1 -0
  86. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  87. package/dest/public/tail_phase_manager.js +2 -1
  88. package/dest/public/teardown_phase_manager.d.ts +1 -0
  89. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  90. package/dest/public/teardown_phase_manager.js +3 -2
  91. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  92. package/dest/public/transitional_adaptors.js +1 -1
  93. package/dest/rollup/index.d.ts +2 -0
  94. package/dest/rollup/index.d.ts.map +1 -0
  95. package/dest/rollup/index.js +2 -0
  96. package/dest/rollup/rollup.d.ts +77 -0
  97. package/dest/rollup/rollup.d.ts.map +1 -0
  98. package/dest/rollup/rollup.js +78 -0
  99. package/dest/stats/index.d.ts +2 -0
  100. package/dest/stats/index.d.ts.map +1 -0
  101. package/dest/stats/index.js +2 -0
  102. package/dest/stats/stats.d.ts +4 -0
  103. package/dest/stats/stats.d.ts.map +1 -0
  104. package/dest/stats/stats.js +11 -0
  105. package/package.json +8 -8
  106. package/src/acvm/oracle/oracle.ts +27 -35
  107. package/src/acvm/oracle/typed_oracle.ts +16 -9
  108. package/src/avm/avm_execution_environment.ts +34 -42
  109. package/src/avm/avm_gas.ts +4 -0
  110. package/src/avm/avm_machine_state.ts +14 -25
  111. package/src/avm/avm_message_call_result.ts +3 -14
  112. package/src/avm/avm_simulator.ts +22 -12
  113. package/src/avm/errors.ts +94 -4
  114. package/src/avm/journal/journal.ts +3 -2
  115. package/src/avm/opcodes/conversion.ts +59 -0
  116. package/src/avm/opcodes/environment_getters.ts +13 -66
  117. package/src/avm/opcodes/external_calls.ts +11 -0
  118. package/src/avm/opcodes/index.ts +2 -0
  119. package/src/avm/opcodes/misc.ts +63 -0
  120. package/src/avm/serialization/bytecode_serialization.ts +7 -0
  121. package/src/avm/serialization/instruction_serialization.ts +4 -0
  122. package/src/client/client_execution_context.ts +92 -16
  123. package/src/client/db_oracle.ts +1 -9
  124. package/src/client/execution_result.ts +21 -2
  125. package/src/client/private_execution.ts +2 -0
  126. package/src/client/simulator.ts +2 -80
  127. package/src/client/view_data_oracle.ts +0 -10
  128. package/src/common/errors.ts +5 -0
  129. package/src/index.ts +1 -0
  130. package/src/public/abstract_phase_manager.ts +46 -18
  131. package/src/public/app_logic_phase_manager.ts +2 -1
  132. package/src/public/executor.ts +0 -4
  133. package/src/public/hints_builder.ts +5 -5
  134. package/src/public/public_execution_context.ts +6 -1
  135. package/src/public/public_processor.ts +8 -2
  136. package/src/public/setup_phase_manager.ts +16 -8
  137. package/src/public/tail_phase_manager.ts +6 -1
  138. package/src/public/teardown_phase_manager.ts +16 -8
  139. package/src/public/transitional_adaptors.ts +1 -0
  140. package/src/rollup/index.ts +1 -0
  141. package/src/rollup/rollup.ts +160 -0
  142. package/src/stats/index.ts +1 -0
  143. package/src/stats/stats.ts +20 -0
@@ -1,17 +1,15 @@
1
- import { type Fr } from '@aztec/circuits.js';
2
-
3
1
  import type { AvmContext } from '../avm_context.js';
4
2
  import type { AvmExecutionEnvironment } from '../avm_execution_environment.js';
5
- import { Field, type MemoryValue } from '../avm_memory_types.js';
3
+ import { Field, type MemoryValue, Uint64 } from '../avm_memory_types.js';
6
4
  import { Opcode } from '../serialization/instruction_serialization.js';
7
5
  import { GetterInstruction } from './instruction_impl.js';
8
6
 
9
7
  abstract class EnvironmentGetterInstruction extends GetterInstruction {
10
8
  protected getValue(context: AvmContext): MemoryValue {
11
- return new Field(this.getEnvironmentValue(context.environment));
9
+ return this.getEnvironmentValue(context.environment);
12
10
  }
13
11
 
14
- protected abstract getEnvironmentValue(env: AvmExecutionEnvironment): Fr | number | bigint;
12
+ protected abstract getEnvironmentValue(env: AvmExecutionEnvironment): MemoryValue;
15
13
  }
16
14
 
17
15
  export class Address extends EnvironmentGetterInstruction {
@@ -19,7 +17,7 @@ export class Address extends EnvironmentGetterInstruction {
19
17
  static readonly opcode: Opcode = Opcode.ADDRESS;
20
18
 
21
19
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
22
- return env.address;
20
+ return new Field(env.address.toField());
23
21
  }
24
22
  }
25
23
 
@@ -28,7 +26,7 @@ export class StorageAddress extends EnvironmentGetterInstruction {
28
26
  static readonly opcode: Opcode = Opcode.STORAGEADDRESS;
29
27
 
30
28
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
31
- return env.storageAddress;
29
+ return new Field(env.storageAddress.toField());
32
30
  }
33
31
  }
34
32
 
@@ -37,7 +35,7 @@ export class Sender extends EnvironmentGetterInstruction {
37
35
  static readonly opcode: Opcode = Opcode.SENDER;
38
36
 
39
37
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
40
- return env.sender;
38
+ return new Field(env.sender.toField());
41
39
  }
42
40
  }
43
41
 
@@ -46,7 +44,7 @@ export class FeePerL2Gas extends EnvironmentGetterInstruction {
46
44
  static readonly opcode: Opcode = Opcode.FEEPERL2GAS;
47
45
 
48
46
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
49
- return env.feePerL2Gas;
47
+ return new Field(env.feePerL2Gas);
50
48
  }
51
49
  }
52
50
 
@@ -55,7 +53,7 @@ export class FeePerDAGas extends EnvironmentGetterInstruction {
55
53
  static readonly opcode: Opcode = Opcode.FEEPERDAGAS;
56
54
 
57
55
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
58
- return env.feePerDaGas;
56
+ return new Field(env.feePerDaGas);
59
57
  }
60
58
  }
61
59
 
@@ -64,7 +62,7 @@ export class TransactionFee extends EnvironmentGetterInstruction {
64
62
  static readonly opcode: Opcode = Opcode.TRANSACTIONFEE;
65
63
 
66
64
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
67
- return env.transactionFee;
65
+ return new Field(env.transactionFee);
68
66
  }
69
67
  }
70
68
 
@@ -73,7 +71,7 @@ export class ChainId extends EnvironmentGetterInstruction {
73
71
  static readonly opcode: Opcode = Opcode.CHAINID;
74
72
 
75
73
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
76
- return env.globals.chainId;
74
+ return new Field(env.globals.chainId);
77
75
  }
78
76
  }
79
77
 
@@ -82,7 +80,7 @@ export class Version extends EnvironmentGetterInstruction {
82
80
  static readonly opcode: Opcode = Opcode.VERSION;
83
81
 
84
82
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
85
- return env.globals.version;
83
+ return new Field(env.globals.version);
86
84
  }
87
85
  }
88
86
 
@@ -91,7 +89,7 @@ export class BlockNumber extends EnvironmentGetterInstruction {
91
89
  static readonly opcode: Opcode = Opcode.BLOCKNUMBER;
92
90
 
93
91
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
94
- return env.globals.blockNumber;
92
+ return new Field(env.globals.blockNumber);
95
93
  }
96
94
  }
97
95
 
@@ -100,57 +98,6 @@ export class Timestamp extends EnvironmentGetterInstruction {
100
98
  static readonly opcode: Opcode = Opcode.TIMESTAMP;
101
99
 
102
100
  protected getEnvironmentValue(env: AvmExecutionEnvironment) {
103
- return env.globals.timestamp;
101
+ return new Uint64(env.globals.timestamp.toBigInt());
104
102
  }
105
103
  }
106
-
107
- // export class Coinbase extends EnvironmentGetterInstruction {
108
- // static type: string = 'COINBASE';
109
- // static numberOfOperands = 1;
110
-
111
- // constructor(private destOffset: number) {
112
- // super();
113
- // }
114
-
115
- // async execute(machineState: AvmMachineState, _journal: AvmJournal): Promise<void> {
116
- // const {coinbase} = machineState.executionEnvironment.globals;
117
-
118
- // machineState.memory.set(this.destOffset, coinbase);
119
-
120
- // this.incrementPc(machineState);
121
- // }
122
- // }
123
-
124
- // export class BlockL2GasLimit extends EnvironmentGetterInstruction {
125
- // static type: string = 'BLOCKL2GASLIMIT';
126
- // static numberOfOperands = 1;
127
-
128
- // constructor(private destOffset: number) {
129
- // super();
130
- // }
131
-
132
- // async execute(machineState: AvmMachineState, _journal: AvmJournal): Promise<void> {
133
- // const {blockL2GasLimit} = machineState.executionEnvironment.globals;
134
-
135
- // machineState.memory.set(this.destOffset, blockL2GasLimit);
136
-
137
- // this.incrementPc(machineState);
138
- // }
139
- // }
140
-
141
- // export class BlockDAGasLimit extends EnvironmentGetterInstruction {
142
- // static type: string = 'BLOCKDAGASLIMIT';
143
- // static numberOfOperands = 1;
144
-
145
- // constructor(private destOffset: number) {
146
- // super();
147
- // }
148
-
149
- // async execute(machineState: AvmMachineState, _journal: AvmJournal): Promise<void> {
150
- // const {blockDAGasLimit} = machineState.executionEnvironment.globals;
151
-
152
- // machineState.memory.set(this.destOffset, blockDAGasLimit);
153
-
154
- // this.incrementPc(machineState);
155
- // }
156
- // }
@@ -7,6 +7,7 @@ import { gasLeftToGas, sumGas } from '../avm_gas.js';
7
7
  import { Field, Uint8 } from '../avm_memory_types.js';
8
8
  import { type AvmContractCallResults } from '../avm_message_call_result.js';
9
9
  import { AvmSimulator } from '../avm_simulator.js';
10
+ import { RethrownError } from '../errors.js';
10
11
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
11
12
  import { Addressing } from './addressing_mode.js';
12
13
  import { Instruction } from './instruction.js';
@@ -99,6 +100,16 @@ abstract class ExternalCall extends Instruction {
99
100
 
100
101
  const success = !nestedCallResults.reverted;
101
102
 
103
+ // TRANSITIONAL: We rethrow here so that the MESSAGE gets propagated.
104
+ // This means that for now, the caller cannot recover from errors.
105
+ if (!success) {
106
+ if (!nestedCallResults.revertReason) {
107
+ throw new Error('A reverted nested call should be assigned a revert reason in the AVM execution loop');
108
+ }
109
+ // The nested call's revertReason will be used to track the stack of error causes down to the root.
110
+ throw new RethrownError(nestedCallResults.revertReason.message, nestedCallResults.revertReason);
111
+ }
112
+
102
113
  // We only take as much data as was specified in the return size and pad with zeroes if the return data is smaller
103
114
  // than the specified size in order to prevent that memory to be left with garbage
104
115
  const returnData = nestedCallResults.output.slice(0, this.retSize);
@@ -2,9 +2,11 @@ export * from './arithmetic.js';
2
2
  export * from './bitwise.js';
3
3
  export * from './control_flow.js';
4
4
  export * from './contract.js';
5
+ export * from './conversion.js';
5
6
  export * from './instruction.js';
6
7
  export * from './comparators.js';
7
8
  export * from './memory.js';
9
+ export * from './misc.js';
8
10
  export * from './storage.js';
9
11
  export * from './external_calls.js';
10
12
  export * from './environment_getters.js';
@@ -0,0 +1,63 @@
1
+ import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
2
+
3
+ import { type AvmContext } from '../avm_context.js';
4
+ import { TypeTag } from '../avm_memory_types.js';
5
+ import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
6
+ import { Addressing } from './addressing_mode.js';
7
+ import { Instruction } from './instruction.js';
8
+
9
+ export class DebugLog extends Instruction {
10
+ static type: string = 'DEBUGLOG';
11
+ static readonly opcode: Opcode = Opcode.DEBUGLOG;
12
+ static readonly logger = createDebugLogger('aztec:avm_simulator:debug_log');
13
+
14
+ // Informs (de)serialization. See Instruction.deserialize.
15
+ static readonly wireFormat: OperandType[] = [
16
+ OperandType.UINT8, // Opcode
17
+ OperandType.UINT8, // Indirect
18
+ OperandType.UINT32, // message memory address
19
+ OperandType.UINT32, // message size
20
+ OperandType.UINT32, // fields memory address
21
+ OperandType.UINT32, // fields size address
22
+ ];
23
+
24
+ constructor(
25
+ private indirect: number,
26
+ private messageOffset: number,
27
+ private messageSize: number,
28
+ private fieldsOffset: number,
29
+ private fieldsSizeOffset: number,
30
+ ) {
31
+ super();
32
+ }
33
+
34
+ public async execute(context: AvmContext): Promise<void> {
35
+ const memory = context.machineState.memory.track(this.type);
36
+ const [messageOffset, fieldsOffset, fieldsSizeOffset] = Addressing.fromWire(this.indirect).resolve(
37
+ [this.messageOffset, this.fieldsOffset, this.fieldsSizeOffset],
38
+ memory,
39
+ );
40
+
41
+ const fieldsSize = memory.get(fieldsSizeOffset).toNumber();
42
+ memory.checkTagsRange(TypeTag.UINT8, messageOffset, this.messageSize);
43
+ memory.checkTagsRange(TypeTag.FIELD, fieldsOffset, fieldsSize);
44
+
45
+ const memoryOperations = { reads: 1 + fieldsSize + this.messageSize, writes: 0, indirect: this.indirect };
46
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
47
+
48
+ const rawMessage = memory.getSlice(messageOffset, this.messageSize);
49
+ const fields = memory.getSlice(fieldsOffset, fieldsSize);
50
+
51
+ // Interpret str<N> = [u8; N] to string.
52
+ const messageAsStr = rawMessage.map(field => String.fromCharCode(field.toNumber())).join('');
53
+ const formattedStr = applyStringFormatting(
54
+ messageAsStr,
55
+ fields.map(field => field.toFr()),
56
+ );
57
+
58
+ DebugLog.logger.verbose(formattedStr);
59
+
60
+ memory.assert(memoryOperations);
61
+ context.machineState.incrementPc();
62
+ }
63
+ }
@@ -11,6 +11,7 @@ import {
11
11
  CalldataCopy,
12
12
  Cast,
13
13
  ChainId,
14
+ DebugLog,
14
15
  Div,
15
16
  EmitNoteHash,
16
17
  EmitNullifier,
@@ -46,6 +47,7 @@ import {
46
47
  StorageAddress,
47
48
  Sub,
48
49
  Timestamp,
50
+ ToRadixLE,
49
51
  TransactionFee,
50
52
  Version,
51
53
  Xor,
@@ -131,11 +133,16 @@ const INSTRUCTION_SET = () =>
131
133
  [Return.opcode, Return],
132
134
  [Revert.opcode, Revert],
133
135
 
136
+ // Misc
137
+ [DebugLog.opcode, DebugLog],
138
+
134
139
  // //// Gadgets
135
140
  [Keccak.opcode, Keccak],
136
141
  [Poseidon2.opcode, Poseidon2],
137
142
  [Sha256.opcode, Sha256],
138
143
  [Pedersen.opcode, Pedersen],
144
+ // Conversions
145
+ [ToRadixLE.opcode, ToRadixLE],
139
146
  ]);
140
147
 
141
148
  interface Serializable {
@@ -69,11 +69,15 @@ export enum Opcode {
69
69
  DELEGATECALL,
70
70
  RETURN,
71
71
  REVERT,
72
+ // Misc
73
+ DEBUGLOG,
72
74
  // Gadgets
73
75
  KECCAK,
74
76
  POSEIDON2,
75
77
  SHA256, // temp - may be removed, but alot of contracts rely on it
76
78
  PEDERSEN, // temp - may be removed, but alot of contracts rely on it
79
+ // Conversion
80
+ TORADIXLE,
77
81
  }
78
82
 
79
83
  // Possible types for an instruction's operand in its wire format. (Keep in sync with CPP code.
@@ -24,7 +24,7 @@ import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } fr
24
24
  import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi';
25
25
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
26
26
  import { Fr, type Point } from '@aztec/foundation/fields';
27
- import { createDebugLogger } from '@aztec/foundation/log';
27
+ import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
28
28
 
29
29
  import { type NoteData, toACVMWitness } from '../acvm/index.js';
30
30
  import { type PackedValuesCache } from '../common/packed_values_cache.js';
@@ -63,6 +63,7 @@ export class ClientExecutionContext extends ViewDataOracle {
63
63
  private unencryptedLogs: CountedLog<UnencryptedL2Log>[] = [];
64
64
  private nestedExecutions: ExecutionResult[] = [];
65
65
  private enqueuedPublicFunctionCalls: PublicCallRequest[] = [];
66
+ private publicTeardownFunctionCall: PublicCallRequest = PublicCallRequest.empty();
66
67
 
67
68
  constructor(
68
69
  contractAddress: AztecAddress,
@@ -173,6 +174,13 @@ export class ClientExecutionContext extends ViewDataOracle {
173
174
  return this.enqueuedPublicFunctionCalls;
174
175
  }
175
176
 
177
+ /**
178
+ * Return the public teardown function call set during this execution.
179
+ */
180
+ public getPublicTeardownFunctionCall() {
181
+ return this.publicTeardownFunctionCall;
182
+ }
183
+
176
184
  /**
177
185
  * Pack the given array of arguments.
178
186
  * @param args - Arguments to pack
@@ -262,11 +270,11 @@ export class ClientExecutionContext extends ViewDataOracle {
262
270
 
263
271
  notes.forEach(n => {
264
272
  if (n.index !== undefined) {
265
- const siloedNoteHash = siloNoteHash(n.contractAddress, n.innerNoteHash);
266
- const uniqueSiloedNoteHash = computeUniqueNoteHash(n.nonce, siloedNoteHash);
267
273
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)
268
- // Should always be uniqueSiloedNoteHash when publicly created notes include nonces.
269
- const noteHashForReadRequest = n.nonce.isZero() ? siloedNoteHash : uniqueSiloedNoteHash;
274
+ // Should always call computeUniqueNoteHash when publicly created notes include nonces.
275
+ const uniqueNoteHash = n.nonce.isZero() ? n.innerNoteHash : computeUniqueNoteHash(n.nonce, n.innerNoteHash);
276
+ const siloedNoteHash = siloNoteHash(n.contractAddress, uniqueNoteHash);
277
+ const noteHashForReadRequest = siloedNoteHash;
270
278
  this.noteHashLeafIndexMap.set(noteHashForReadRequest.toBigInt(), n.index);
271
279
  }
272
280
  });
@@ -465,9 +473,7 @@ export class ClientExecutionContext extends ViewDataOracle {
465
473
  }
466
474
 
467
475
  /**
468
- * Creates a PublicCallStackItem object representing the request to call a public function. No function
469
- * is actually called, since that must happen on the sequencer side. All the fields related to the result
470
- * of the execution are empty.
476
+ * Creates a PublicCallStackItem object representing the request to call a public function.
471
477
  * @param targetContractAddress - The address of the contract to call.
472
478
  * @param functionSelector - The function selector of the function to call.
473
479
  * @param argsHash - The packed arguments to pass to the function.
@@ -475,7 +481,8 @@ export class ClientExecutionContext extends ViewDataOracle {
475
481
  * @param isStaticCall - Whether the call is a static call.
476
482
  * @returns The public call stack item with the request information.
477
483
  */
478
- public override async enqueuePublicFunctionCall(
484
+ protected async createPublicCallRequest(
485
+ callType: 'enqueued' | 'teardown',
479
486
  targetContractAddress: AztecAddress,
480
487
  functionSelector: FunctionSelector,
481
488
  argsHash: Fr,
@@ -494,20 +501,51 @@ export class ClientExecutionContext extends ViewDataOracle {
494
501
  isStaticCall,
495
502
  );
496
503
  const args = this.packedValuesCache.unpack(argsHash);
497
- const enqueuedRequest = PublicCallRequest.from({
504
+
505
+ // TODO($846): if enqueued public calls are associated with global
506
+ // side-effect counter, that will leak info about how many other private
507
+ // side-effects occurred in the TX. Ultimately the private kernel should
508
+ // just output everything in the proper order without any counters.
509
+ this.log.verbose(
510
+ `Created PublicCallRequest of type [${callType}], side-effect counter [${sideEffectCounter}] to ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
511
+ );
512
+
513
+ return PublicCallRequest.from({
498
514
  args,
499
515
  callContext: derivedCallContext,
500
516
  parentCallContext: this.callContext,
501
517
  functionData: FunctionData.fromAbi(targetArtifact),
502
518
  contractAddress: targetContractAddress,
503
519
  });
520
+ }
504
521
 
505
- // TODO($846): if enqueued public calls are associated with global
506
- // side-effect counter, that will leak info about how many other private
507
- // side-effects occurred in the TX. Ultimately the private kernel should
508
- // just output everything in the proper order without any counters.
509
- this.log.verbose(
510
- `Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
522
+ /**
523
+ * Creates and enqueues a PublicCallStackItem object representing the request to call a public function. No function
524
+ * is actually called, since that must happen on the sequencer side. All the fields related to the result
525
+ * of the execution are empty.
526
+ * @param targetContractAddress - The address of the contract to call.
527
+ * @param functionSelector - The function selector of the function to call.
528
+ * @param argsHash - The packed arguments to pass to the function.
529
+ * @param sideEffectCounter - The side effect counter at the start of the call.
530
+ * @param isStaticCall - Whether the call is a static call.
531
+ * @returns The public call stack item with the request information.
532
+ */
533
+ public override async enqueuePublicFunctionCall(
534
+ targetContractAddress: AztecAddress,
535
+ functionSelector: FunctionSelector,
536
+ argsHash: Fr,
537
+ sideEffectCounter: number,
538
+ isStaticCall: boolean,
539
+ isDelegateCall: boolean,
540
+ ): Promise<PublicCallRequest> {
541
+ const enqueuedRequest = await this.createPublicCallRequest(
542
+ 'enqueued',
543
+ targetContractAddress,
544
+ functionSelector,
545
+ argsHash,
546
+ sideEffectCounter,
547
+ isStaticCall,
548
+ isDelegateCall,
511
549
  );
512
550
 
513
551
  this.enqueuedPublicFunctionCalls.push(enqueuedRequest);
@@ -515,6 +553,40 @@ export class ClientExecutionContext extends ViewDataOracle {
515
553
  return enqueuedRequest;
516
554
  }
517
555
 
556
+ /**
557
+ * Creates a PublicCallStackItem and sets it as the public teardown function. No function
558
+ * is actually called, since that must happen on the sequencer side. All the fields related to the result
559
+ * of the execution are empty.
560
+ * @param targetContractAddress - The address of the contract to call.
561
+ * @param functionSelector - The function selector of the function to call.
562
+ * @param argsHash - The packed arguments to pass to the function.
563
+ * @param sideEffectCounter - The side effect counter at the start of the call.
564
+ * @param isStaticCall - Whether the call is a static call.
565
+ * @returns The public call stack item with the request information.
566
+ */
567
+ public override async setPublicTeardownFunctionCall(
568
+ targetContractAddress: AztecAddress,
569
+ functionSelector: FunctionSelector,
570
+ argsHash: Fr,
571
+ sideEffectCounter: number,
572
+ isStaticCall: boolean,
573
+ isDelegateCall: boolean,
574
+ ): Promise<PublicCallRequest> {
575
+ const publicTeardownFunctionCall = await this.createPublicCallRequest(
576
+ 'teardown',
577
+ targetContractAddress,
578
+ functionSelector,
579
+ argsHash,
580
+ sideEffectCounter,
581
+ isStaticCall,
582
+ isDelegateCall,
583
+ );
584
+
585
+ this.publicTeardownFunctionCall = publicTeardownFunctionCall;
586
+
587
+ return publicTeardownFunctionCall;
588
+ }
589
+
518
590
  /**
519
591
  * Derives the call context for a nested execution.
520
592
  * @param targetContractAddress - The address of the contract being called.
@@ -570,4 +642,8 @@ export class ClientExecutionContext extends ViewDataOracle {
570
642
  const aes128 = new Aes128();
571
643
  return aes128.encryptBufferCBC(input, initializationVector, key);
572
644
  }
645
+
646
+ public override debugLog(message: string, fields: Fr[]) {
647
+ this.log.verbose(`debug_log ${applyStringFormatting(message, fields)}`);
648
+ }
573
649
  }
@@ -8,7 +8,7 @@ import {
8
8
  import { type CompleteAddress, type Header } from '@aztec/circuits.js';
9
9
  import { type FunctionArtifact, type FunctionSelector } from '@aztec/foundation/abi';
10
10
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
11
- import { type Fr, type Point } from '@aztec/foundation/fields';
11
+ import { type Fr } from '@aztec/foundation/fields';
12
12
  import { type ContractInstance } from '@aztec/types/contracts';
13
13
 
14
14
  import { type NoteData, type NullifierKeys } from '../acvm/index.js';
@@ -64,14 +64,6 @@ export interface DBOracle extends CommitmentsDB {
64
64
  */
65
65
  popCapsule(): Promise<Fr[]>;
66
66
 
67
- /**
68
- * Gets public keys for an address.
69
- * @param The address to look up
70
- * @returns The public keys for a specific address
71
- * TODO(#5834): Replace with `getCompleteAddress`.
72
- */
73
- getPublicKeysForAddress(address: AztecAddress): Promise<Point[]>;
74
-
75
67
  /**
76
68
  * Retrieve nullifier keys associated with a specific account and app/contract address.
77
69
  *
@@ -5,7 +5,7 @@ import {
5
5
  UnencryptedFunctionL2Logs,
6
6
  type UnencryptedL2Log,
7
7
  } from '@aztec/circuit-types';
8
- import { type IsEmpty, type PrivateCallStackItem, type PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
8
+ import { type IsEmpty, type PrivateCallStackItem, PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
9
9
  import { type Fr } from '@aztec/foundation/fields';
10
10
 
11
11
  import { type ACVMField } from '../acvm/index.js';
@@ -56,6 +56,8 @@ export interface ExecutionResult {
56
56
  nestedExecutions: this[];
57
57
  /** Enqueued public function execution requests to be picked up by the sequencer. */
58
58
  enqueuedPublicFunctionCalls: PublicCallRequest[];
59
+ /** Public function execution requested for teardown */
60
+ publicTeardownFunctionCall: PublicCallRequest;
59
61
  /**
60
62
  * Encrypted logs emitted during execution of this function call.
61
63
  * Note: These are preimages to `encryptedLogsHashes`.
@@ -130,6 +132,23 @@ export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult):
130
132
  // as the kernel processes it like a stack, popping items off and pushing them to output
131
133
  return [
132
134
  ...execResult.enqueuedPublicFunctionCalls,
133
- ...[...execResult.nestedExecutions].flatMap(collectEnqueuedPublicFunctionCalls),
135
+ ...execResult.nestedExecutions.flatMap(collectEnqueuedPublicFunctionCalls),
134
136
  ].sort((a, b) => b.callContext.sideEffectCounter - a.callContext.sideEffectCounter);
135
137
  }
138
+
139
+ export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): PublicCallRequest {
140
+ const teardownCalls = [
141
+ execResult.publicTeardownFunctionCall,
142
+ ...execResult.nestedExecutions.flatMap(collectPublicTeardownFunctionCall),
143
+ ].filter(call => !call.isEmpty());
144
+
145
+ if (teardownCalls.length === 1) {
146
+ return teardownCalls[0];
147
+ }
148
+
149
+ if (teardownCalls.length > 1) {
150
+ throw new Error('Multiple public teardown calls detected');
151
+ }
152
+
153
+ return PublicCallRequest.empty();
154
+ }
@@ -54,6 +54,7 @@ export async function executePrivateFunction(
54
54
  const nullifiedNoteHashCounters = context.getNullifiedNoteHashCounters();
55
55
  const nestedExecutions = context.getNestedExecutions();
56
56
  const enqueuedPublicFunctionCalls = context.getEnqueuedPublicFunctionCalls();
57
+ const publicTeardownFunctionCall = context.getPublicTeardownFunctionCall();
57
58
 
58
59
  log.debug(`Returning from call to ${contractAddress.toString()}:${functionSelector}`);
59
60
 
@@ -68,6 +69,7 @@ export async function executePrivateFunction(
68
69
  vk: Buffer.from(artifact.verificationKey!, 'hex'),
69
70
  nestedExecutions,
70
71
  enqueuedPublicFunctionCalls,
72
+ publicTeardownFunctionCall,
71
73
  encryptedLogs,
72
74
  unencryptedLogs,
73
75
  };
@@ -200,7 +200,7 @@ export class AcirSimulator {
200
200
  args: encodeArguments(artifact, [contractAddress, nonce, storageSlot, noteTypeId, extendedNoteItems]),
201
201
  };
202
202
 
203
- const [innerNoteHash, siloedNoteHash, uniqueSiloedNoteHash, innerNullifier] = (await this.runUnconstrained(
203
+ const [innerNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained(
204
204
  execRequest,
205
205
  artifact,
206
206
  contractAddress,
@@ -208,8 +208,8 @@ export class AcirSimulator {
208
208
 
209
209
  return {
210
210
  innerNoteHash: new Fr(innerNoteHash),
211
+ uniqueNoteHash: new Fr(uniqueNoteHash),
211
212
  siloedNoteHash: new Fr(siloedNoteHash),
212
- uniqueSiloedNoteHash: new Fr(uniqueSiloedNoteHash),
213
213
  innerNullifier: new Fr(innerNullifier),
214
214
  };
215
215
  }
@@ -232,82 +232,4 @@ export class AcirSimulator {
232
232
  );
233
233
  return innerNoteHash;
234
234
  }
235
-
236
- /**
237
- * Computes the unique note hash of a note.
238
- * @param contractAddress - The address of the contract.
239
- * @param nonce - The nonce of the note hash.
240
- * @param storageSlot - The storage slot.
241
- * @param noteTypeId - The note type identifier.
242
- * @param note - The note.
243
- * @returns The note hash.
244
- */
245
- public async computeUniqueSiloedNoteHash(
246
- contractAddress: AztecAddress,
247
- nonce: Fr,
248
- storageSlot: Fr,
249
- noteTypeId: Fr,
250
- note: Note,
251
- ) {
252
- const { uniqueSiloedNoteHash } = await this.computeNoteHashAndNullifier(
253
- contractAddress,
254
- nonce,
255
- storageSlot,
256
- noteTypeId,
257
- note,
258
- );
259
- return uniqueSiloedNoteHash;
260
- }
261
-
262
- /**
263
- * Computes the siloed note hash of a note.
264
- * @param contractAddress - The address of the contract.
265
- * @param nonce - The nonce of the note hash.
266
- * @param storageSlot - The storage slot.
267
- * @param noteTypeId - The note type identifier.
268
- * @param note - The note.
269
- * @returns The note hash.
270
- */
271
- public async computeSiloedNoteHash(
272
- contractAddress: AztecAddress,
273
- nonce: Fr,
274
- storageSlot: Fr,
275
- noteTypeId: Fr,
276
- note: Note,
277
- ) {
278
- const { siloedNoteHash } = await this.computeNoteHashAndNullifier(
279
- contractAddress,
280
- nonce,
281
- storageSlot,
282
- noteTypeId,
283
- note,
284
- );
285
- return siloedNoteHash;
286
- }
287
-
288
- /**
289
- * Computes the inner note hash of a note, which contains storage slot and the custom note hash.
290
- * @param contractAddress - The address of the contract.
291
- * @param nonce - The nonce of the unique note hash.
292
- * @param storageSlot - The storage slot.
293
- * @param noteTypeId - The note type identifier.
294
- * @param note - The note.
295
- * @returns The note hash.
296
- */
297
- public async computeInnerNullifier(
298
- contractAddress: AztecAddress,
299
- nonce: Fr,
300
- storageSlot: Fr,
301
- noteTypeId: Fr,
302
- note: Note,
303
- ) {
304
- const { innerNullifier } = await this.computeNoteHashAndNullifier(
305
- contractAddress,
306
- nonce,
307
- storageSlot,
308
- noteTypeId,
309
- note,
310
- );
311
- return innerNullifier;
312
- }
313
235
  }