@aztec/simulator 0.32.1 → 0.34.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 (160) hide show
  1. package/README.md +5 -3
  2. package/dest/acvm/acvm.js +2 -2
  3. package/dest/acvm/oracle/index.d.ts +0 -1
  4. package/dest/acvm/oracle/index.d.ts.map +1 -1
  5. package/dest/acvm/oracle/index.js +1 -2
  6. package/dest/acvm/oracle/oracle.d.ts +1 -1
  7. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  8. package/dest/acvm/oracle/oracle.js +4 -5
  9. package/dest/avm/avm_context.d.ts +4 -14
  10. package/dest/avm/avm_context.d.ts.map +1 -1
  11. package/dest/avm/avm_context.js +10 -22
  12. package/dest/avm/avm_execution_environment.d.ts +4 -3
  13. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  14. package/dest/avm/avm_execution_environment.js +8 -7
  15. package/dest/avm/avm_gas.d.ts +71 -0
  16. package/dest/avm/avm_gas.d.ts.map +1 -0
  17. package/dest/avm/avm_gas.js +161 -0
  18. package/dest/avm/avm_machine_state.d.ts +4 -2
  19. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  20. package/dest/avm/avm_machine_state.js +8 -2
  21. package/dest/avm/avm_memory_types.d.ts +53 -1
  22. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  23. package/dest/avm/avm_memory_types.js +99 -6
  24. package/dest/avm/avm_simulator.d.ts.map +1 -1
  25. package/dest/avm/avm_simulator.js +15 -13
  26. package/dest/avm/fixtures/index.d.ts.map +1 -1
  27. package/dest/avm/fixtures/index.js +3 -3
  28. package/dest/avm/journal/journal.d.ts +14 -13
  29. package/dest/avm/journal/journal.d.ts.map +1 -1
  30. package/dest/avm/journal/journal.js +5 -5
  31. package/dest/avm/journal/trace.d.ts +8 -19
  32. package/dest/avm/journal/trace.d.ts.map +1 -1
  33. package/dest/avm/journal/trace.js +48 -116
  34. package/dest/avm/journal/trace_types.d.ts +23 -4
  35. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  36. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  37. package/dest/avm/opcodes/accrued_substate.js +45 -17
  38. package/dest/avm/opcodes/addressing_mode.d.ts +5 -3
  39. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
  40. package/dest/avm/opcodes/addressing_mode.js +5 -1
  41. package/dest/avm/opcodes/arithmetic.d.ts +7 -3
  42. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  43. package/dest/avm/opcodes/arithmetic.js +27 -16
  44. package/dest/avm/opcodes/bitwise.d.ts +21 -20
  45. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  46. package/dest/avm/opcodes/bitwise.js +43 -65
  47. package/dest/avm/opcodes/comparators.d.ts +12 -9
  48. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  49. package/dest/avm/opcodes/comparators.js +22 -32
  50. package/dest/avm/opcodes/context_getters.d.ts +20 -0
  51. package/dest/avm/opcodes/context_getters.d.ts.map +1 -0
  52. package/dest/avm/opcodes/context_getters.js +26 -0
  53. package/dest/avm/opcodes/contract.d.ts +14 -0
  54. package/dest/avm/opcodes/contract.d.ts.map +1 -0
  55. package/dest/avm/opcodes/contract.js +49 -0
  56. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  57. package/dest/avm/opcodes/control_flow.js +12 -2
  58. package/dest/avm/opcodes/environment_getters.d.ts +30 -33
  59. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  60. package/dest/avm/opcodes/environment_getters.js +34 -43
  61. package/dest/avm/opcodes/external_calls.d.ts +13 -19
  62. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  63. package/dest/avm/opcodes/external_calls.js +69 -72
  64. package/dest/avm/opcodes/hashing.d.ts +2 -1
  65. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  66. package/dest/avm/opcodes/hashing.js +37 -18
  67. package/dest/avm/opcodes/index.d.ts +1 -0
  68. package/dest/avm/opcodes/index.d.ts.map +1 -1
  69. package/dest/avm/opcodes/index.js +2 -1
  70. package/dest/avm/opcodes/instruction.d.ts +10 -15
  71. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  72. package/dest/avm/opcodes/instruction.js +12 -22
  73. package/dest/avm/opcodes/instruction_impl.d.ts +14 -0
  74. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  75. package/dest/avm/opcodes/instruction_impl.js +37 -16
  76. package/dest/avm/opcodes/memory.d.ts +4 -3
  77. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  78. package/dest/avm/opcodes/memory.js +38 -19
  79. package/dest/avm/opcodes/storage.d.ts +5 -0
  80. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  81. package/dest/avm/opcodes/storage.js +21 -7
  82. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  83. package/dest/avm/serialization/bytecode_serialization.js +7 -5
  84. package/dest/avm/serialization/instruction_serialization.d.ts +12 -11
  85. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  86. package/dest/avm/serialization/instruction_serialization.js +13 -12
  87. package/dest/client/client_execution_context.d.ts +2 -2
  88. package/dest/client/client_execution_context.d.ts.map +1 -1
  89. package/dest/client/client_execution_context.js +6 -6
  90. package/dest/client/private_execution.d.ts +1 -1
  91. package/dest/client/private_execution.d.ts.map +1 -1
  92. package/dest/client/private_execution.js +8 -4
  93. package/dest/client/unconstrained_execution.d.ts +1 -1
  94. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  95. package/dest/client/unconstrained_execution.js +2 -2
  96. package/dest/client/view_data_oracle.d.ts +2 -2
  97. package/dest/client/view_data_oracle.d.ts.map +1 -1
  98. package/dest/client/view_data_oracle.js +2 -2
  99. package/dest/public/executor.d.ts +2 -8
  100. package/dest/public/executor.d.ts.map +1 -1
  101. package/dest/public/executor.js +101 -69
  102. package/dest/public/index.d.ts +1 -1
  103. package/dest/public/index.d.ts.map +1 -1
  104. package/dest/public/public_execution_context.d.ts +6 -6
  105. package/dest/public/public_execution_context.d.ts.map +1 -1
  106. package/dest/public/public_execution_context.js +8 -12
  107. package/dest/public/transitional_adaptors.d.ts +32 -0
  108. package/dest/public/transitional_adaptors.d.ts.map +1 -0
  109. package/dest/public/transitional_adaptors.js +161 -0
  110. package/package.json +15 -9
  111. package/src/acvm/acvm.ts +1 -1
  112. package/src/acvm/oracle/index.ts +0 -1
  113. package/src/acvm/oracle/oracle.ts +3 -4
  114. package/src/avm/avm_context.ts +11 -33
  115. package/src/avm/avm_execution_environment.ts +9 -17
  116. package/src/avm/{avm_gas_cost.ts → avm_gas.ts} +75 -21
  117. package/src/avm/avm_machine_state.ts +9 -2
  118. package/src/avm/avm_memory_types.ts +134 -6
  119. package/src/avm/avm_simulator.ts +14 -12
  120. package/src/avm/fixtures/index.ts +2 -1
  121. package/src/avm/journal/journal.ts +24 -17
  122. package/src/avm/journal/trace.ts +59 -121
  123. package/src/avm/journal/trace_types.ts +39 -39
  124. package/src/avm/opcodes/accrued_substate.ts +58 -23
  125. package/src/avm/opcodes/addressing_mode.ts +8 -3
  126. package/src/avm/opcodes/arithmetic.ts +32 -22
  127. package/src/avm/opcodes/bitwise.ts +49 -83
  128. package/src/avm/opcodes/comparators.ts +28 -43
  129. package/src/avm/opcodes/context_getters.ts +32 -0
  130. package/src/avm/opcodes/contract.ts +58 -0
  131. package/src/avm/opcodes/control_flow.ts +23 -5
  132. package/src/avm/opcodes/environment_getters.ts +35 -44
  133. package/src/avm/opcodes/external_calls.ts +90 -89
  134. package/src/avm/opcodes/hashing.ts +45 -22
  135. package/src/avm/opcodes/index.ts +1 -0
  136. package/src/avm/opcodes/instruction.ts +14 -26
  137. package/src/avm/opcodes/instruction_impl.ts +45 -15
  138. package/src/avm/opcodes/memory.ts +48 -28
  139. package/src/avm/opcodes/storage.ts +26 -12
  140. package/src/avm/serialization/bytecode_serialization.ts +6 -3
  141. package/src/avm/serialization/instruction_serialization.ts +1 -0
  142. package/src/client/client_execution_context.ts +5 -5
  143. package/src/client/private_execution.ts +10 -4
  144. package/src/client/unconstrained_execution.ts +1 -1
  145. package/src/client/view_data_oracle.ts +1 -1
  146. package/src/public/executor.ts +123 -75
  147. package/src/public/index.ts +2 -2
  148. package/src/public/public_execution_context.ts +14 -19
  149. package/src/public/transitional_adaptors.ts +240 -0
  150. package/dest/acvm/oracle/debug.d.ts +0 -19
  151. package/dest/acvm/oracle/debug.d.ts.map +0 -1
  152. package/dest/acvm/oracle/debug.js +0 -95
  153. package/dest/avm/avm_gas_cost.d.ts +0 -322
  154. package/dest/avm/avm_gas_cost.d.ts.map +0 -1
  155. package/dest/avm/avm_gas_cost.js +0 -118
  156. package/dest/avm/temporary_executor_migration.d.ts +0 -25
  157. package/dest/avm/temporary_executor_migration.d.ts.map +0 -1
  158. package/dest/avm/temporary_executor_migration.js +0 -83
  159. package/src/acvm/oracle/debug.ts +0 -109
  160. package/src/avm/temporary_executor_migration.ts +0 -122
@@ -0,0 +1,32 @@
1
+ import type { AvmContext } from '../avm_context.js';
2
+ import { Field, type MemoryValue } from '../avm_memory_types.js';
3
+ import { Opcode } from '../serialization/instruction_serialization.js';
4
+ import { GetterInstruction } from './instruction_impl.js';
5
+
6
+ export class L2GasLeft extends GetterInstruction {
7
+ static type: string = 'L2GASLEFT';
8
+ static readonly opcode: Opcode = Opcode.L2GASLEFT;
9
+
10
+ // TODO(@spalladino) Yellow paper specifies that the value should be an Uint32, not a Field.
11
+ protected getValue(context: AvmContext): MemoryValue {
12
+ return new Field(context.machineState.l2GasLeft);
13
+ }
14
+ }
15
+
16
+ export class L1GasLeft extends GetterInstruction {
17
+ static type: string = 'L1GASLEFT';
18
+ static readonly opcode: Opcode = Opcode.L1GASLEFT;
19
+
20
+ protected getValue(context: AvmContext): MemoryValue {
21
+ return new Field(context.machineState.l1GasLeft);
22
+ }
23
+ }
24
+
25
+ export class DAGasLeft extends GetterInstruction {
26
+ static type: string = 'DAGASLEFT';
27
+ static readonly opcode: Opcode = Opcode.DAGASLEFT;
28
+
29
+ protected getValue(context: AvmContext): MemoryValue {
30
+ return new Field(context.machineState.daGasLeft);
31
+ }
32
+ }
@@ -0,0 +1,58 @@
1
+ import { AztecAddress, Fr } from '@aztec/circuits.js';
2
+
3
+ import type { AvmContext } from '../avm_context.js';
4
+ import { Field } 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 GetContractInstance extends Instruction {
10
+ static readonly type: string = 'GETCONTRACTINSTANCE';
11
+ static readonly opcode: Opcode = Opcode.GETCONTRACTINSTANCE;
12
+ // Informs (de)serialization. See Instruction.deserialize.
13
+ static readonly wireFormat: OperandType[] = [
14
+ OperandType.UINT8,
15
+ OperandType.UINT8,
16
+ OperandType.UINT32,
17
+ OperandType.UINT32,
18
+ ];
19
+
20
+ constructor(private indirect: number, private addressOffset: number, private dstOffset: number) {
21
+ super();
22
+ }
23
+
24
+ async execute(context: AvmContext): Promise<void> {
25
+ const [addressOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
26
+ [this.addressOffset, this.dstOffset],
27
+ context.machineState.memory,
28
+ );
29
+
30
+ const address = AztecAddress.fromField(context.machineState.memory.get(addressOffset).toFr());
31
+ const instance = await context.persistableState.hostStorage.contractsDb.getContractInstance(address);
32
+
33
+ const data =
34
+ instance === undefined
35
+ ? [
36
+ new Field(0), // not found
37
+ new Field(0),
38
+ new Field(0),
39
+ new Field(0),
40
+ new Field(0),
41
+ new Field(0),
42
+ new Field(0),
43
+ ]
44
+ : [
45
+ new Fr(1), // found
46
+ instance.salt,
47
+ instance.deployer.toField(),
48
+ instance.contractClassId,
49
+ instance.initializationHash,
50
+ instance.portalContractAddress.toField(),
51
+ instance.publicKeysHash,
52
+ ].map(f => new Field(f));
53
+
54
+ context.machineState.memory.setSlice(dstOffset, data);
55
+
56
+ context.machineState.incrementPc();
57
+ }
58
+ }
@@ -14,8 +14,12 @@ export class Jump extends Instruction {
14
14
  super();
15
15
  }
16
16
 
17
- async execute(context: AvmContext): Promise<void> {
17
+ public async execute(context: AvmContext): Promise<void> {
18
+ context.machineState.consumeGas(this.gasCost());
19
+
18
20
  context.machineState.pc = this.jumpOffset;
21
+
22
+ context.machineState.memory.assert({});
19
23
  }
20
24
  }
21
25
 
@@ -35,8 +39,12 @@ export class JumpI extends Instruction {
35
39
  super();
36
40
  }
37
41
 
38
- async execute(context: AvmContext): Promise<void> {
39
- const condition = context.machineState.memory.getAs<IntegralValue>(this.condOffset);
42
+ public async execute(context: AvmContext): Promise<void> {
43
+ const memoryOperations = { reads: 1, indirect: this.indirect };
44
+ const memory = context.machineState.memory.track(this.type);
45
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
46
+
47
+ const condition = memory.getAs<IntegralValue>(this.condOffset);
40
48
 
41
49
  // TODO: reconsider this casting
42
50
  if (condition.toBigInt() == 0n) {
@@ -44,6 +52,8 @@ export class JumpI extends Instruction {
44
52
  } else {
45
53
  context.machineState.pc = this.loc;
46
54
  }
55
+
56
+ memory.assert(memoryOperations);
47
57
  }
48
58
  }
49
59
 
@@ -57,9 +67,13 @@ export class InternalCall extends Instruction {
57
67
  super();
58
68
  }
59
69
 
60
- async execute(context: AvmContext): Promise<void> {
70
+ public async execute(context: AvmContext): Promise<void> {
71
+ context.machineState.consumeGas(this.gasCost());
72
+
61
73
  context.machineState.internalCallStack.push(context.machineState.pc + 1);
62
74
  context.machineState.pc = this.loc;
75
+
76
+ context.machineState.memory.assert({});
63
77
  }
64
78
  }
65
79
 
@@ -73,11 +87,15 @@ export class InternalReturn extends Instruction {
73
87
  super();
74
88
  }
75
89
 
76
- async execute(context: AvmContext): Promise<void> {
90
+ public async execute(context: AvmContext): Promise<void> {
91
+ context.machineState.consumeGas(this.gasCost());
92
+
77
93
  const jumpOffset = context.machineState.internalCallStack.pop();
78
94
  if (jumpOffset === undefined) {
79
95
  throw new InstructionExecutionError('Internal call stack empty!');
80
96
  }
81
97
  context.machineState.pc = jumpOffset;
98
+
99
+ context.machineState.memory.assert({});
82
100
  }
83
101
  }
@@ -2,136 +2,127 @@ import { type Fr } from '@aztec/circuits.js';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
4
  import type { AvmExecutionEnvironment } from '../avm_execution_environment.js';
5
- import { Field } from '../avm_memory_types.js';
6
- import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
- import { Instruction } from './instruction.js';
5
+ import { Field, type MemoryValue } from '../avm_memory_types.js';
6
+ import { Opcode } from '../serialization/instruction_serialization.js';
7
+ import { GetterInstruction } from './instruction_impl.js';
8
8
 
9
- abstract class GetterInstruction extends Instruction {
10
- // Informs (de)serialization. See Instruction.deserialize.
11
- static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT32];
12
-
13
- constructor(protected indirect: number, protected dstOffset: number) {
14
- super();
15
- }
16
-
17
- async execute(context: AvmContext): Promise<void> {
18
- const res = new Field(this.getIt(context.environment));
19
- context.machineState.memory.set(this.dstOffset, res);
20
- context.machineState.incrementPc();
9
+ abstract class EnvironmentGetterInstruction extends GetterInstruction {
10
+ protected getValue(context: AvmContext): MemoryValue {
11
+ return new Field(this.getEnvironmentValue(context.environment));
21
12
  }
22
13
 
23
- protected abstract getIt(env: AvmExecutionEnvironment): Fr | number | bigint;
14
+ protected abstract getEnvironmentValue(env: AvmExecutionEnvironment): Fr | number | bigint;
24
15
  }
25
16
 
26
- export class Address extends GetterInstruction {
17
+ export class Address extends EnvironmentGetterInstruction {
27
18
  static type: string = 'ADDRESS';
28
19
  static readonly opcode: Opcode = Opcode.ADDRESS;
29
20
 
30
- protected getIt(env: AvmExecutionEnvironment) {
21
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
31
22
  return env.address;
32
23
  }
33
24
  }
34
25
 
35
- export class StorageAddress extends GetterInstruction {
26
+ export class StorageAddress extends EnvironmentGetterInstruction {
36
27
  static type: string = 'STORAGEADDRESS';
37
28
  static readonly opcode: Opcode = Opcode.STORAGEADDRESS;
38
29
 
39
- protected getIt(env: AvmExecutionEnvironment) {
30
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
40
31
  return env.storageAddress;
41
32
  }
42
33
  }
43
34
 
44
- export class Sender extends GetterInstruction {
35
+ export class Sender extends EnvironmentGetterInstruction {
45
36
  static type: string = 'SENDER';
46
37
  static readonly opcode: Opcode = Opcode.SENDER;
47
38
 
48
- protected getIt(env: AvmExecutionEnvironment) {
39
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
49
40
  return env.sender;
50
41
  }
51
42
  }
52
43
 
53
- export class Origin extends GetterInstruction {
44
+ export class Origin extends EnvironmentGetterInstruction {
54
45
  static type: string = 'ORIGIN';
55
46
  static readonly opcode: Opcode = Opcode.ORIGIN;
56
47
 
57
- protected getIt(env: AvmExecutionEnvironment) {
48
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
58
49
  return env.origin;
59
50
  }
60
51
  }
61
52
 
62
- export class FeePerL1Gas extends GetterInstruction {
53
+ export class FeePerL1Gas extends EnvironmentGetterInstruction {
63
54
  static type: string = 'FEEPERL1GAS';
64
55
  static readonly opcode: Opcode = Opcode.FEEPERL1GAS;
65
56
 
66
- protected getIt(env: AvmExecutionEnvironment) {
57
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
67
58
  return env.feePerL1Gas;
68
59
  }
69
60
  }
70
61
 
71
- export class FeePerL2Gas extends GetterInstruction {
62
+ export class FeePerL2Gas extends EnvironmentGetterInstruction {
72
63
  static type: string = 'FEEPERL2GAS';
73
64
  static readonly opcode: Opcode = Opcode.FEEPERL2GAS;
74
65
 
75
- protected getIt(env: AvmExecutionEnvironment) {
66
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
76
67
  return env.feePerL2Gas;
77
68
  }
78
69
  }
79
70
 
80
- export class FeePerDAGas extends GetterInstruction {
71
+ export class FeePerDAGas extends EnvironmentGetterInstruction {
81
72
  static type: string = 'FEEPERDAGAS';
82
73
  static readonly opcode: Opcode = Opcode.FEEPERDAGAS;
83
74
 
84
- protected getIt(env: AvmExecutionEnvironment) {
75
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
85
76
  return env.feePerDaGas;
86
77
  }
87
78
  }
88
79
 
89
- export class Portal extends GetterInstruction {
80
+ export class Portal extends EnvironmentGetterInstruction {
90
81
  static type: string = 'PORTAL';
91
82
  static readonly opcode: Opcode = Opcode.PORTAL;
92
83
 
93
- protected getIt(env: AvmExecutionEnvironment) {
84
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
94
85
  return env.portal.toField();
95
86
  }
96
87
  }
97
88
 
98
- export class ChainId extends GetterInstruction {
89
+ export class ChainId extends EnvironmentGetterInstruction {
99
90
  static type: string = 'CHAINID';
100
91
  static readonly opcode: Opcode = Opcode.CHAINID;
101
92
 
102
- protected getIt(env: AvmExecutionEnvironment) {
93
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
103
94
  return env.globals.chainId;
104
95
  }
105
96
  }
106
97
 
107
- export class Version extends GetterInstruction {
98
+ export class Version extends EnvironmentGetterInstruction {
108
99
  static type: string = 'VERSION';
109
100
  static readonly opcode: Opcode = Opcode.VERSION;
110
101
 
111
- protected getIt(env: AvmExecutionEnvironment) {
102
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
112
103
  return env.globals.version;
113
104
  }
114
105
  }
115
106
 
116
- export class BlockNumber extends GetterInstruction {
107
+ export class BlockNumber extends EnvironmentGetterInstruction {
117
108
  static type: string = 'BLOCKNUMBER';
118
109
  static readonly opcode: Opcode = Opcode.BLOCKNUMBER;
119
110
 
120
- protected getIt(env: AvmExecutionEnvironment) {
111
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
121
112
  return env.globals.blockNumber;
122
113
  }
123
114
  }
124
115
 
125
- export class Timestamp extends GetterInstruction {
116
+ export class Timestamp extends EnvironmentGetterInstruction {
126
117
  static type: string = 'TIMESTAMP';
127
118
  static readonly opcode: Opcode = Opcode.TIMESTAMP;
128
119
 
129
- protected getIt(env: AvmExecutionEnvironment) {
120
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
130
121
  return env.globals.timestamp;
131
122
  }
132
123
  }
133
124
 
134
- // export class Coinbase extends GetterInstruction {
125
+ // export class Coinbase extends EnvironmentGetterInstruction {
135
126
  // static type: string = 'COINBASE';
136
127
  // static numberOfOperands = 1;
137
128
 
@@ -149,7 +140,7 @@ export class Timestamp extends GetterInstruction {
149
140
  // }
150
141
 
151
142
  // // TODO: are these even needed within the block? (both block gas limit variables - why does the execution env care?)
152
- // export class BlockL1GasLimit extends GetterInstruction {
143
+ // export class BlockL1GasLimit extends EnvironmentGetterInstruction {
153
144
  // static type: string = 'BLOCKL1GASLIMIT';
154
145
  // static numberOfOperands = 1;
155
146
 
@@ -166,7 +157,7 @@ export class Timestamp extends GetterInstruction {
166
157
  // }
167
158
  // }
168
159
 
169
- // export class BlockL2GasLimit extends GetterInstruction {
160
+ // export class BlockL2GasLimit extends EnvironmentGetterInstruction {
170
161
  // static type: string = 'BLOCKL2GASLIMIT';
171
162
  // static numberOfOperands = 1;
172
163
 
@@ -183,7 +174,7 @@ export class Timestamp extends GetterInstruction {
183
174
  // }
184
175
  // }
185
176
 
186
- // export class BlockDAGasLimit extends GetterInstruction {
177
+ // export class BlockDAGasLimit extends EnvironmentGetterInstruction {
187
178
  // static type: string = 'BLOCKDAGASLIMIT';
188
179
  // static numberOfOperands = 1;
189
180
 
@@ -1,15 +1,21 @@
1
1
  import { FunctionSelector } from '@aztec/circuits.js';
2
-
2
+ import { padArrayEnd } from '@aztec/foundation/collection';
3
+
4
+ import { executePublicFunction } from '../../public/executor.js';
5
+ import {
6
+ convertPublicExecutionResult,
7
+ createPublicExecutionContext,
8
+ updateAvmContextFromPublicExecutionResult,
9
+ } from '../../public/transitional_adaptors.js';
3
10
  import type { AvmContext } from '../avm_context.js';
11
+ import { gasLeftToGas, sumGas } from '../avm_gas.js';
4
12
  import { Field, Uint8 } from '../avm_memory_types.js';
5
- import { AvmSimulator } from '../avm_simulator.js';
13
+ import { type AvmContractCallResults } from '../avm_message_call_result.js';
6
14
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
15
  import { Addressing } from './addressing_mode.js';
8
16
  import { Instruction } from './instruction.js';
9
17
 
10
- export class Call extends Instruction {
11
- static type: string = 'CALL';
12
- static readonly opcode: Opcode = Opcode.CALL;
18
+ abstract class ExternalCall extends Instruction {
13
19
  // Informs (de)serialization. See Instruction.deserialize.
14
20
  static readonly wireFormat: OperandType[] = [
15
21
  OperandType.UINT8,
@@ -27,7 +33,7 @@ export class Call extends Instruction {
27
33
 
28
34
  constructor(
29
35
  private indirect: number,
30
- private _gasOffset: number /* Unused due to no formal gas implementation at this moment */,
36
+ private gasOffset: number /* Unused due to no formal gas implementation at this moment */,
31
37
  private addrOffset: number,
32
38
  private argsOffset: number,
33
39
  private argsSize: number,
@@ -42,110 +48,95 @@ export class Call extends Instruction {
42
48
  super();
43
49
  }
44
50
 
45
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3992): there is no concept of remaining / available gas at this moment
46
- async execute(context: AvmContext): Promise<void> {
47
- const [_gasOffset, addrOffset, argsOffset, retOffset, successOffset] = Addressing.fromWire(this.indirect).resolve(
48
- [this._gasOffset, this.addrOffset, this.argsOffset, this.retOffset, this.successOffset],
49
- context.machineState.memory,
51
+ public async execute(context: AvmContext) {
52
+ const memory = context.machineState.memory.track(this.type);
53
+ const [gasOffset, addrOffset, argsOffset, retOffset, successOffset] = Addressing.fromWire(this.indirect).resolve(
54
+ [this.gasOffset, this.addrOffset, this.argsOffset, this.retOffset, this.successOffset],
55
+ memory,
50
56
  );
51
57
 
52
- const callAddress = context.machineState.memory.getAs<Field>(addrOffset);
53
- const calldata = context.machineState.memory.getSlice(argsOffset, this.argsSize).map(f => f.toFr());
54
- const functionSelector = context.machineState.memory.getAs<Field>(this.temporaryFunctionSelectorOffset).toFr();
58
+ const callAddress = memory.getAs<Field>(addrOffset);
59
+ const calldata = memory.getSlice(argsOffset, this.argsSize).map(f => f.toFr());
60
+ const l1Gas = memory.get(gasOffset).toNumber();
61
+ const l2Gas = memory.getAs<Field>(gasOffset + 1).toNumber();
62
+ const daGas = memory.getAs<Field>(gasOffset + 2).toNumber();
63
+ const functionSelector = memory.getAs<Field>(this.temporaryFunctionSelectorOffset).toFr();
55
64
 
65
+ const allocatedGas = { l1Gas, l2Gas, daGas };
66
+ const memoryOperations = { reads: this.argsSize + 5, writes: 1 + this.retSize, indirect: this.indirect };
67
+ const totalGas = sumGas(this.gasCost(memoryOperations), allocatedGas);
68
+ context.machineState.consumeGas(totalGas);
69
+
70
+ // TRANSITIONAL: This should be removed once the AVM is fully operational and the public executor is gone.
56
71
  const nestedContext = context.createNestedContractCallContext(
57
72
  callAddress.toFr(),
58
73
  calldata,
74
+ allocatedGas,
75
+ this.type,
59
76
  FunctionSelector.fromField(functionSelector),
60
77
  );
78
+ const pxContext = createPublicExecutionContext(nestedContext, calldata);
79
+ const pxResults = await executePublicFunction(pxContext, /*nested=*/ true);
80
+ const nestedCallResults: AvmContractCallResults = convertPublicExecutionResult(pxResults);
81
+ updateAvmContextFromPublicExecutionResult(nestedContext, pxResults);
82
+ const nestedPersistableState = nestedContext.persistableState;
83
+ // const nestedContext = context.createNestedContractCallContext(
84
+ // callAddress.toFr(),
85
+ // calldata,
86
+ // allocatedGas,
87
+ // this.type,
88
+ // FunctionSelector.fromField(functionSelector),
89
+ // );
90
+ // const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute();
91
+ // const nestedPersistableState = nestedContext.persistableState;
61
92
 
62
- const nestedCallResults = await new AvmSimulator(nestedContext).execute();
63
93
  const success = !nestedCallResults.reverted;
64
94
 
65
- // We only take as much data as was specified in the return size -> TODO: should we be reverting here
95
+ // We only take as much data as was specified in the return size and pad with zeroes if the return data is smaller
96
+ // than the specified size in order to prevent that memory to be left with garbage
66
97
  const returnData = nestedCallResults.output.slice(0, this.retSize);
67
- const convertedReturnData = returnData.map(f => new Field(f));
98
+ const convertedReturnData = padArrayEnd(
99
+ returnData.map(f => new Field(f)),
100
+ new Field(0),
101
+ this.retSize,
102
+ );
68
103
 
69
104
  // Write our return data into memory
70
- context.machineState.memory.set(successOffset, new Uint8(success ? 1 : 0));
71
- context.machineState.memory.setSlice(retOffset, convertedReturnData);
105
+ memory.set(successOffset, new Uint8(success ? 1 : 0));
106
+ memory.setSlice(retOffset, convertedReturnData);
72
107
 
108
+ // Refund unused gas
109
+ context.machineState.refundGas(gasLeftToGas(nestedContext.machineState));
110
+
111
+ // TODO: Should we merge the changes from a nested call in the case of a STATIC call?
73
112
  if (success) {
74
- context.persistableState.acceptNestedCallState(nestedContext.persistableState);
113
+ context.persistableState.acceptNestedCallState(nestedPersistableState);
75
114
  } else {
76
- context.persistableState.rejectNestedCallState(nestedContext.persistableState);
115
+ context.persistableState.rejectNestedCallState(nestedPersistableState);
77
116
  }
78
117
 
118
+ memory.assert(memoryOperations);
79
119
  context.machineState.incrementPc();
80
120
  }
121
+
122
+ public abstract get type(): 'CALL' | 'STATICCALL';
81
123
  }
82
124
 
83
- export class StaticCall extends Instruction {
84
- static type: string = 'STATICCALL';
85
- static readonly opcode: Opcode = Opcode.STATICCALL;
86
- // Informs (de)serialization. See Instruction.deserialize.
87
- static readonly wireFormat: OperandType[] = [
88
- OperandType.UINT8,
89
- OperandType.UINT8,
90
- OperandType.UINT32,
91
- OperandType.UINT32,
92
- OperandType.UINT32,
93
- OperandType.UINT32,
94
- OperandType.UINT32,
95
- OperandType.UINT32,
96
- OperandType.UINT32,
97
- /* temporary function selector */
98
- OperandType.UINT32,
99
- ];
125
+ export class Call extends ExternalCall {
126
+ static type = 'CALL' as const;
127
+ static readonly opcode: Opcode = Opcode.CALL;
100
128
 
101
- constructor(
102
- private indirect: number,
103
- private _gasOffset: number /* Unused due to no formal gas implementation at this moment */,
104
- private addrOffset: number,
105
- private argsOffset: number,
106
- private argsSize: number,
107
- private retOffset: number,
108
- private retSize: number,
109
- private successOffset: number,
110
- private temporaryFunctionSelectorOffset: number,
111
- ) {
112
- super();
129
+ public get type() {
130
+ return Call.type;
113
131
  }
132
+ }
114
133
 
115
- async execute(context: AvmContext): Promise<void> {
116
- const [_gasOffset, addrOffset, argsOffset, retOffset, successOffset] = Addressing.fromWire(this.indirect).resolve(
117
- [this._gasOffset, this.addrOffset, this.argsOffset, this.retOffset, this.successOffset],
118
- context.machineState.memory,
119
- );
120
-
121
- const callAddress = context.machineState.memory.get(addrOffset);
122
- const calldata = context.machineState.memory.getSlice(argsOffset, this.argsSize).map(f => f.toFr());
123
- const functionSelector = context.machineState.memory.getAs<Field>(this.temporaryFunctionSelectorOffset).toFr();
124
-
125
- const nestedContext = context.createNestedContractStaticCallContext(
126
- callAddress.toFr(),
127
- calldata,
128
- FunctionSelector.fromField(functionSelector),
129
- );
130
-
131
- const nestedCallResults = await new AvmSimulator(nestedContext).execute();
132
- const success = !nestedCallResults.reverted;
133
-
134
- // We only take as much data as was specified in the return size -> TODO: should we be reverting here
135
- const returnData = nestedCallResults.output.slice(0, this.retSize);
136
- const convertedReturnData = returnData.map(f => new Field(f));
137
-
138
- // Write our return data into memory
139
- context.machineState.memory.set(successOffset, new Uint8(success ? 1 : 0));
140
- context.machineState.memory.setSlice(retOffset, convertedReturnData);
141
-
142
- if (success) {
143
- context.persistableState.acceptNestedCallState(nestedContext.persistableState);
144
- } else {
145
- context.persistableState.rejectNestedCallState(nestedContext.persistableState);
146
- }
134
+ export class StaticCall extends ExternalCall {
135
+ static type = 'STATICCALL' as const;
136
+ static readonly opcode: Opcode = Opcode.STATICCALL;
147
137
 
148
- context.machineState.incrementPc();
138
+ public get type() {
139
+ return StaticCall.type;
149
140
  }
150
141
  }
151
142
 
@@ -164,12 +155,17 @@ export class Return extends Instruction {
164
155
  super();
165
156
  }
166
157
 
167
- async execute(context: AvmContext): Promise<void> {
168
- const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], context.machineState.memory);
158
+ public async execute(context: AvmContext): Promise<void> {
159
+ const memoryOperations = { reads: this.copySize, indirect: this.indirect };
160
+ const memory = context.machineState.memory.track(this.type);
161
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
162
+
163
+ const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], memory);
169
164
 
170
- const output = context.machineState.memory.getSlice(returnOffset, this.copySize).map(word => word.toFr());
165
+ const output = memory.getSlice(returnOffset, this.copySize).map(word => word.toFr());
171
166
 
172
167
  context.machineState.return(output);
168
+ memory.assert(memoryOperations);
173
169
  }
174
170
  }
175
171
 
@@ -188,11 +184,16 @@ export class Revert extends Instruction {
188
184
  super();
189
185
  }
190
186
 
191
- async execute(context: AvmContext): Promise<void> {
192
- const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], context.machineState.memory);
187
+ public async execute(context: AvmContext): Promise<void> {
188
+ const memoryOperations = { reads: this.retSize, indirect: this.indirect };
189
+ const memory = context.machineState.memory.track(this.type);
190
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
191
+
192
+ const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], memory);
193
193
 
194
- const output = context.machineState.memory.getSlice(returnOffset, this.retSize).map(word => word.toFr());
194
+ const output = memory.getSlice(returnOffset, this.retSize).map(word => word.toFr());
195
195
 
196
196
  context.machineState.revert(output);
197
+ memory.assert(memoryOperations);
197
198
  }
198
199
  }