@aztec/simulator 0.27.1 → 0.28.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.
- package/dest/acvm/oracle/oracle.d.ts +3 -3
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +7 -7
- package/dest/acvm/oracle/typed_oracle.d.ts +3 -3
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +35 -30
- package/dest/avm/avm_memory_types.d.ts +1 -0
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +6 -1
- package/dest/avm/opcodes/arithmetic.d.ts +13 -1
- package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/avm/opcodes/arithmetic.js +31 -2
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +3 -2
- package/dest/avm/serialization/instruction_serialization.d.ts +58 -57
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +59 -58
- package/dest/avm/temporary_executor_migration.d.ts.map +1 -1
- package/dest/avm/temporary_executor_migration.js +6 -1
- package/dest/client/client_execution_context.d.ts +2 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +5 -3
- package/dest/client/execution_result.js +2 -2
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +5 -6
- package/dest/common/side_effect_counter.d.ts +1 -0
- package/dest/common/side_effect_counter.d.ts.map +1 -1
- package/dest/common/side_effect_counter.js +5 -1
- package/dest/public/db.d.ts +19 -5
- package/dest/public/db.d.ts.map +1 -1
- package/dest/public/execution.d.ts +4 -0
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor.d.ts +2 -2
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +12 -12
- package/dest/public/public_execution_context.d.ts +3 -1
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +22 -4
- package/package.json +5 -5
- package/src/acvm/oracle/oracle.ts +6 -4
- package/src/acvm/oracle/typed_oracle.ts +35 -28
- package/src/avm/avm_memory_types.ts +6 -0
- package/src/avm/opcodes/arithmetic.ts +33 -1
- package/src/avm/serialization/bytecode_serialization.ts +2 -0
- package/src/avm/serialization/instruction_serialization.ts +1 -0
- package/src/avm/temporary_executor_migration.ts +5 -0
- package/src/client/client_execution_context.ts +4 -0
- package/src/client/execution_result.ts +1 -1
- package/src/client/simulator.ts +6 -3
- package/src/common/side_effect_counter.ts +5 -0
- package/src/public/db.ts +22 -5
- package/src/public/execution.ts +4 -0
- package/src/public/executor.ts +16 -10
- package/src/public/public_execution_context.ts +23 -2
|
@@ -69,6 +69,12 @@ export class MessageLoadOracleInputs<N extends number> {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
class OracleMethodNotAvailableError extends Error {
|
|
73
|
+
constructor(methodName: string) {
|
|
74
|
+
super(`Oracle method ${methodName} is not available.`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
/**
|
|
73
79
|
* Oracle with typed parameters and typed return values.
|
|
74
80
|
* Methods that require read and/or write will have to be implemented based on the context (public, private, or view)
|
|
@@ -80,58 +86,58 @@ export abstract class TypedOracle {
|
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
packArguments(_args: Fr[]): Promise<Fr> {
|
|
83
|
-
throw new
|
|
89
|
+
throw new OracleMethodNotAvailableError('packArguments');
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
getNullifierKeyPair(_accountAddress: AztecAddress): Promise<KeyPair> {
|
|
87
|
-
throw new
|
|
93
|
+
throw new OracleMethodNotAvailableError('getNullifierKeyPair');
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
getPublicKeyAndPartialAddress(_address: AztecAddress): Promise<Fr[] | undefined> {
|
|
91
|
-
throw new
|
|
97
|
+
throw new OracleMethodNotAvailableError('getPublicKeyAndPartialAddress');
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
getContractInstance(_address: AztecAddress): Promise<ContractInstance> {
|
|
95
|
-
throw new
|
|
101
|
+
throw new OracleMethodNotAvailableError('getContractInstance');
|
|
96
102
|
}
|
|
97
103
|
|
|
98
104
|
getMembershipWitness(_blockNumber: number, _treeId: MerkleTreeId, _leafValue: Fr): Promise<Fr[] | undefined> {
|
|
99
|
-
throw new
|
|
105
|
+
throw new OracleMethodNotAvailableError('getMembershipWitness');
|
|
100
106
|
}
|
|
101
107
|
|
|
102
108
|
getSiblingPath(_blockNumber: number, _treeId: MerkleTreeId, _leafIndex: Fr): Promise<Fr[]> {
|
|
103
|
-
throw new
|
|
109
|
+
throw new OracleMethodNotAvailableError('getSiblingPath');
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
getNullifierMembershipWitness(_blockNumber: number, _nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
|
|
107
|
-
throw new
|
|
113
|
+
throw new OracleMethodNotAvailableError('getNullifierMembershipWitness');
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
getPublicDataTreeWitness(_blockNumber: number, _leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
111
|
-
throw new
|
|
117
|
+
throw new OracleMethodNotAvailableError('getPublicDataTreeWitness');
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
getLowNullifierMembershipWitness(
|
|
115
121
|
_blockNumber: number,
|
|
116
122
|
_nullifier: Fr,
|
|
117
123
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
118
|
-
throw new
|
|
124
|
+
throw new OracleMethodNotAvailableError('getLowNullifierMembershipWitness');
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
getHeader(_blockNumber: number): Promise<Header | undefined> {
|
|
122
|
-
throw new
|
|
128
|
+
throw new OracleMethodNotAvailableError('getHeader');
|
|
123
129
|
}
|
|
124
130
|
|
|
125
131
|
getCompleteAddress(_address: AztecAddress): Promise<CompleteAddress> {
|
|
126
|
-
throw new
|
|
132
|
+
throw new OracleMethodNotAvailableError('getCompleteAddress');
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
getAuthWitness(_messageHash: Fr): Promise<Fr[] | undefined> {
|
|
130
|
-
throw new
|
|
136
|
+
throw new OracleMethodNotAvailableError('getAuthWitness');
|
|
131
137
|
}
|
|
132
138
|
|
|
133
139
|
popCapsule(): Promise<Fr[]> {
|
|
134
|
-
throw new
|
|
140
|
+
throw new OracleMethodNotAvailableError('popCapsule');
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
getNotes(
|
|
@@ -146,35 +152,35 @@ export abstract class TypedOracle {
|
|
|
146
152
|
_offset: number,
|
|
147
153
|
_status: NoteStatus,
|
|
148
154
|
): Promise<NoteData[]> {
|
|
149
|
-
throw new
|
|
155
|
+
throw new OracleMethodNotAvailableError('getNotes');
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
notifyCreatedNote(_storageSlot: Fr, _noteTypeId: Fr, _note: Fr[], _innerNoteHash: Fr): void {
|
|
153
|
-
throw new
|
|
159
|
+
throw new OracleMethodNotAvailableError('notifyCreatedNote');
|
|
154
160
|
}
|
|
155
161
|
|
|
156
162
|
notifyNullifiedNote(_innerNullifier: Fr, _innerNoteHash: Fr): Promise<void> {
|
|
157
|
-
throw new
|
|
163
|
+
throw new OracleMethodNotAvailableError('notifyNullifiedNote');
|
|
158
164
|
}
|
|
159
165
|
|
|
160
166
|
checkNullifierExists(_innerNullifier: Fr): Promise<boolean> {
|
|
161
|
-
throw new
|
|
167
|
+
throw new OracleMethodNotAvailableError('checkNullifierExists');
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
getL1ToL2MembershipWitness(_entryKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
|
|
165
|
-
throw new
|
|
171
|
+
throw new OracleMethodNotAvailableError('getL1ToL2MembershipWitness');
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
getPortalContractAddress(_contractAddress: AztecAddress): Promise<EthAddress> {
|
|
169
|
-
throw new
|
|
175
|
+
throw new OracleMethodNotAvailableError('getPortalContractAddress');
|
|
170
176
|
}
|
|
171
177
|
|
|
172
178
|
storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise<Fr[]> {
|
|
173
|
-
throw new
|
|
179
|
+
throw new OracleMethodNotAvailableError('storageRead');
|
|
174
180
|
}
|
|
175
181
|
|
|
176
182
|
storageWrite(_startStorageSlot: Fr, _values: Fr[]): Promise<Fr[]> {
|
|
177
|
-
throw new
|
|
183
|
+
throw new OracleMethodNotAvailableError('storageWrite');
|
|
178
184
|
}
|
|
179
185
|
|
|
180
186
|
emitEncryptedLog(
|
|
@@ -184,42 +190,43 @@ export abstract class TypedOracle {
|
|
|
184
190
|
_publicKey: PublicKey,
|
|
185
191
|
_log: Fr[],
|
|
186
192
|
): void {
|
|
187
|
-
throw new
|
|
193
|
+
throw new OracleMethodNotAvailableError('emitEncryptedLog');
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
emitUnencryptedLog(_log: UnencryptedL2Log): void {
|
|
191
|
-
throw new
|
|
197
|
+
throw new OracleMethodNotAvailableError('emitUnencryptedLog');
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
callPrivateFunction(
|
|
195
201
|
_targetContractAddress: AztecAddress,
|
|
196
202
|
_functionSelector: FunctionSelector,
|
|
197
203
|
_argsHash: Fr,
|
|
198
|
-
|
|
204
|
+
_sideEffectCounter: number,
|
|
199
205
|
_isStaticCall: boolean,
|
|
200
206
|
_isDelegateCall: boolean,
|
|
201
207
|
): Promise<PrivateCallStackItem> {
|
|
202
|
-
throw new
|
|
208
|
+
throw new OracleMethodNotAvailableError('callPrivateFunction');
|
|
203
209
|
}
|
|
204
210
|
|
|
205
211
|
callPublicFunction(
|
|
206
212
|
_targetContractAddress: AztecAddress,
|
|
207
213
|
_functionSelector: FunctionSelector,
|
|
208
214
|
_argsHash: Fr,
|
|
215
|
+
_sideEffectCounter: number,
|
|
209
216
|
_isStaticCall: boolean,
|
|
210
217
|
_isDelegateCall: boolean,
|
|
211
218
|
): Promise<Fr[]> {
|
|
212
|
-
throw new
|
|
219
|
+
throw new OracleMethodNotAvailableError('callPublicFunction');
|
|
213
220
|
}
|
|
214
221
|
|
|
215
222
|
enqueuePublicFunctionCall(
|
|
216
223
|
_targetContractAddress: AztecAddress,
|
|
217
224
|
_functionSelector: FunctionSelector,
|
|
218
225
|
_argsHash: Fr,
|
|
219
|
-
|
|
226
|
+
_sideEffectCounter: number,
|
|
220
227
|
_isStaticCall: boolean,
|
|
221
228
|
_isDelegateCall: boolean,
|
|
222
229
|
): Promise<PublicCallRequest> {
|
|
223
|
-
throw new
|
|
230
|
+
throw new OracleMethodNotAvailableError('enqueuePublicFunctionCall');
|
|
224
231
|
}
|
|
225
232
|
}
|
|
@@ -160,7 +160,13 @@ export class Field extends MemoryValue {
|
|
|
160
160
|
return new Field(this.rep.mul(rhs.rep));
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
// Euclidean division.
|
|
163
164
|
public div(rhs: Field): Field {
|
|
165
|
+
return new Field(this.rep.ediv(rhs.rep));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Field division.
|
|
169
|
+
public fdiv(rhs: Field): Field {
|
|
164
170
|
return new Field(this.rep.div(rhs.rep));
|
|
165
171
|
}
|
|
166
172
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
|
-
import {
|
|
2
|
+
import { Field, TypeTag } from '../avm_memory_types.js';
|
|
3
|
+
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
4
|
+
import { Instruction } from './instruction.js';
|
|
3
5
|
import { ThreeOperandInstruction } from './instruction_impl.js';
|
|
4
6
|
|
|
5
7
|
export class Add extends ThreeOperandInstruction {
|
|
@@ -79,3 +81,33 @@ export class Div extends ThreeOperandInstruction {
|
|
|
79
81
|
context.machineState.incrementPc();
|
|
80
82
|
}
|
|
81
83
|
}
|
|
84
|
+
|
|
85
|
+
export class FieldDiv extends Instruction {
|
|
86
|
+
static type: string = 'FDIV';
|
|
87
|
+
static readonly opcode = Opcode.FDIV;
|
|
88
|
+
|
|
89
|
+
// Informs (de)serialization. See Instruction.deserialize.
|
|
90
|
+
static readonly wireFormat: OperandType[] = [
|
|
91
|
+
OperandType.UINT8,
|
|
92
|
+
OperandType.UINT8,
|
|
93
|
+
OperandType.UINT32,
|
|
94
|
+
OperandType.UINT32,
|
|
95
|
+
OperandType.UINT32,
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
constructor(private indirect: number, private aOffset: number, private bOffset: number, private dstOffset: number) {
|
|
99
|
+
super();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async execute(context: AvmContext): Promise<void> {
|
|
103
|
+
context.machineState.memory.checkTags(TypeTag.FIELD, this.aOffset, this.bOffset);
|
|
104
|
+
|
|
105
|
+
const a = context.machineState.memory.getAs<Field>(this.aOffset);
|
|
106
|
+
const b = context.machineState.memory.getAs<Field>(this.bOffset);
|
|
107
|
+
|
|
108
|
+
const dest = a.fdiv(b);
|
|
109
|
+
context.machineState.memory.set(this.dstOffset, dest);
|
|
110
|
+
|
|
111
|
+
context.machineState.incrementPc();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
FeePerDAGas,
|
|
18
18
|
FeePerL1Gas,
|
|
19
19
|
FeePerL2Gas,
|
|
20
|
+
FieldDiv,
|
|
20
21
|
InternalCall,
|
|
21
22
|
InternalReturn,
|
|
22
23
|
Jump,
|
|
@@ -66,6 +67,7 @@ const INSTRUCTION_SET = () =>
|
|
|
66
67
|
[Sub.opcode, Sub],
|
|
67
68
|
[Mul.opcode, Mul],
|
|
68
69
|
[Div.opcode, Div],
|
|
70
|
+
[FieldDiv.opcode, FieldDiv],
|
|
69
71
|
[Eq.opcode, Eq],
|
|
70
72
|
[Lt.opcode, Lt],
|
|
71
73
|
[Lte.opcode, Lte],
|
|
@@ -98,6 +98,9 @@ export function temporaryConvertAvmResults(
|
|
|
98
98
|
const newNullifiers: SideEffectLinkedToNoteHash[] = [];
|
|
99
99
|
const unencryptedLogs = FunctionL2Logs.empty();
|
|
100
100
|
const newL2ToL1Messages = newWorldState.newL1Messages.map(() => L2ToL1Message.empty());
|
|
101
|
+
// TODO keep track of side effect counters
|
|
102
|
+
const startSideEffectCounter = Fr.ZERO;
|
|
103
|
+
const endSideEffectCounter = Fr.ZERO;
|
|
101
104
|
|
|
102
105
|
return {
|
|
103
106
|
execution,
|
|
@@ -105,6 +108,8 @@ export function temporaryConvertAvmResults(
|
|
|
105
108
|
nullifierNonExistentReadRequests,
|
|
106
109
|
newNoteHashes,
|
|
107
110
|
newL2ToL1Messages,
|
|
111
|
+
startSideEffectCounter,
|
|
112
|
+
endSideEffectCounter,
|
|
108
113
|
newNullifiers,
|
|
109
114
|
contractStorageReads,
|
|
110
115
|
contractStorageUpdateRequests,
|
|
@@ -75,6 +75,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
75
75
|
protected readonly db: DBOracle,
|
|
76
76
|
private readonly curve: Grumpkin,
|
|
77
77
|
private node: AztecNode,
|
|
78
|
+
protected sideEffectCounter: number = 0,
|
|
78
79
|
protected log = createDebugLogger('aztec:simulator:client_execution_context'),
|
|
79
80
|
) {
|
|
80
81
|
super(contractAddress, authWitnesses, db, node, log);
|
|
@@ -103,6 +104,8 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
103
104
|
this.txContext.chainId,
|
|
104
105
|
this.txContext.version,
|
|
105
106
|
|
|
107
|
+
new Fr(this.sideEffectCounter),
|
|
108
|
+
|
|
106
109
|
...args,
|
|
107
110
|
];
|
|
108
111
|
|
|
@@ -366,6 +369,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
366
369
|
this.db,
|
|
367
370
|
this.curve,
|
|
368
371
|
this.node,
|
|
372
|
+
sideEffectCounter,
|
|
369
373
|
);
|
|
370
374
|
|
|
371
375
|
const childExecutionResult = await executePrivateFunction(
|
|
@@ -85,5 +85,5 @@ export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult):
|
|
|
85
85
|
return [
|
|
86
86
|
...execResult.enqueuedPublicFunctionCalls,
|
|
87
87
|
...[...execResult.nestedExecutions].flatMap(collectEnqueuedPublicFunctionCalls),
|
|
88
|
-
].sort((a, b) => b.callContext.
|
|
88
|
+
].sort((a, b) => b.callContext.sideEffectCounter - a.callContext.sideEffectCounter);
|
|
89
89
|
}
|
package/src/client/simulator.ts
CHANGED
|
@@ -85,6 +85,10 @@ export class AcirSimulator {
|
|
|
85
85
|
const curve = new Grumpkin();
|
|
86
86
|
|
|
87
87
|
const header = await this.db.getHeader();
|
|
88
|
+
|
|
89
|
+
// reserve the first side effect for the tx hash (inserted by the private kernel)
|
|
90
|
+
const startSideEffectCounter = 1;
|
|
91
|
+
|
|
88
92
|
const callContext = new CallContext(
|
|
89
93
|
msgSender,
|
|
90
94
|
contractAddress,
|
|
@@ -92,9 +96,7 @@ export class AcirSimulator {
|
|
|
92
96
|
FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters),
|
|
93
97
|
false,
|
|
94
98
|
false,
|
|
95
|
-
|
|
96
|
-
// 2 counters are reserved for tx hash and contract deployment nullifier
|
|
97
|
-
1,
|
|
99
|
+
startSideEffectCounter,
|
|
98
100
|
);
|
|
99
101
|
const context = new ClientExecutionContext(
|
|
100
102
|
contractAddress,
|
|
@@ -108,6 +110,7 @@ export class AcirSimulator {
|
|
|
108
110
|
this.db,
|
|
109
111
|
curve,
|
|
110
112
|
this.node,
|
|
113
|
+
startSideEffectCounter,
|
|
111
114
|
);
|
|
112
115
|
|
|
113
116
|
try {
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
export class SideEffectCounter {
|
|
5
5
|
constructor(private value = 0) {}
|
|
6
6
|
|
|
7
|
+
// TODO(alexg) remove this once public side effect counters is fully accounted for on Noir side
|
|
8
|
+
current() {
|
|
9
|
+
return this.value;
|
|
10
|
+
}
|
|
11
|
+
|
|
7
12
|
count() {
|
|
8
13
|
const value = this.value;
|
|
9
14
|
this.value++;
|
package/src/public/db.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { NullifierMembershipWitness } from '@aztec/circuit-types';
|
|
|
2
2
|
import { EthAddress, FunctionSelector, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js';
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
+
import { ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
5
6
|
|
|
6
7
|
import { MessageLoadOracleInputs } from '../acvm/index.js';
|
|
7
8
|
|
|
@@ -27,16 +28,25 @@ export interface PublicStateDB {
|
|
|
27
28
|
storageWrite(contract: AztecAddress, slot: Fr, newValue: Fr): Promise<void>;
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
|
-
*
|
|
31
|
-
|
|
31
|
+
* Mark the uncommitted changes in this TX as a checkpoint.
|
|
32
|
+
*/
|
|
33
|
+
checkpoint(): Promise<void>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Rollback to the last checkpoint.
|
|
37
|
+
*/
|
|
38
|
+
rollbackToCheckpoint(): Promise<void>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Commit the changes in this TX. Includes all changes since the last commit,
|
|
42
|
+
* even if they haven't been covered by a checkpoint.
|
|
32
43
|
*/
|
|
33
44
|
commit(): Promise<void>;
|
|
34
45
|
|
|
35
46
|
/**
|
|
36
|
-
* Rollback the
|
|
37
|
-
* @returns Nothing.
|
|
47
|
+
* Rollback to the last commit.
|
|
38
48
|
*/
|
|
39
|
-
|
|
49
|
+
rollbackToCommit(): Promise<void>;
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
/**
|
|
@@ -65,6 +75,13 @@ export interface PublicContractsDB {
|
|
|
65
75
|
* @returns The portal contract address or undefined if not found.
|
|
66
76
|
*/
|
|
67
77
|
getPortalContractAddress(address: AztecAddress): Promise<EthAddress | undefined>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Returns a publicly deployed contract instance.
|
|
81
|
+
* @param address - Address of the contract.
|
|
82
|
+
* @returns The contract instance or undefined if not found.
|
|
83
|
+
*/
|
|
84
|
+
getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined>;
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
/** Database interface for providing access to commitment tree, l1 to l2 message tree, and nullifier tree. */
|
package/src/public/execution.ts
CHANGED
|
@@ -26,6 +26,10 @@ export interface PublicExecutionResult {
|
|
|
26
26
|
newNoteHashes: SideEffect[];
|
|
27
27
|
/** The new l2 to l1 messages generated in this call. */
|
|
28
28
|
newL2ToL1Messages: L2ToL1Message[];
|
|
29
|
+
/** The side effect counter at the start of the function call. */
|
|
30
|
+
startSideEffectCounter: Fr;
|
|
31
|
+
/** The side effect counter after executing this function call */
|
|
32
|
+
endSideEffectCounter: Fr;
|
|
29
33
|
/** The new nullifiers to be inserted into the nullifier tree. */
|
|
30
34
|
newNullifiers: SideEffectLinkedToNoteHash[];
|
|
31
35
|
/** The nullifier read requests emitted in this call. */
|
package/src/public/executor.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FunctionL2Logs } from '@aztec/circuit-types';
|
|
2
|
-
import { GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
|
|
2
|
+
import { Fr, GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
|
|
3
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
5
5
|
import { spawn } from 'child_process';
|
|
@@ -83,6 +83,9 @@ export async function executePublicFunction(
|
|
|
83
83
|
returnValues: [],
|
|
84
84
|
newNoteHashes: [],
|
|
85
85
|
newL2ToL1Messages: [],
|
|
86
|
+
// TODO (side effects) get these values in the revert case from the vm
|
|
87
|
+
startSideEffectCounter: Fr.ZERO,
|
|
88
|
+
endSideEffectCounter: Fr.ZERO,
|
|
86
89
|
newNullifiers: [],
|
|
87
90
|
nullifierReadRequests: [],
|
|
88
91
|
nullifierNonExistentReadRequests: [],
|
|
@@ -107,6 +110,8 @@ export async function executePublicFunction(
|
|
|
107
110
|
newL2ToL1Msgs,
|
|
108
111
|
newNoteHashes: newNoteHashesPadded,
|
|
109
112
|
newNullifiers: newNullifiersPadded,
|
|
113
|
+
startSideEffectCounter,
|
|
114
|
+
endSideEffectCounter,
|
|
110
115
|
} = PublicCircuitPublicInputs.fromFields(returnWitness);
|
|
111
116
|
|
|
112
117
|
const nullifierReadRequests = nullifierReadRequestsPadded.filter(v => !v.isEmpty());
|
|
@@ -136,6 +141,8 @@ export async function executePublicFunction(
|
|
|
136
141
|
newNoteHashes,
|
|
137
142
|
newL2ToL1Messages,
|
|
138
143
|
newNullifiers,
|
|
144
|
+
startSideEffectCounter,
|
|
145
|
+
endSideEffectCounter,
|
|
139
146
|
nullifierReadRequests,
|
|
140
147
|
nullifierNonExistentReadRequests,
|
|
141
148
|
contractStorageReads,
|
|
@@ -165,7 +172,11 @@ export class PublicExecutor {
|
|
|
165
172
|
* @param globalVariables - The global variables to use.
|
|
166
173
|
* @returns The result of the run plus all nested runs.
|
|
167
174
|
*/
|
|
168
|
-
public async simulate(
|
|
175
|
+
public async simulate(
|
|
176
|
+
execution: PublicExecution,
|
|
177
|
+
globalVariables: GlobalVariables,
|
|
178
|
+
sideEffectCounter: number = 0,
|
|
179
|
+
): Promise<PublicExecutionResult> {
|
|
169
180
|
const selector = execution.functionData.selector;
|
|
170
181
|
const acir = await this.contractsDb.getBytecode(execution.contractAddress, selector);
|
|
171
182
|
if (!acir) {
|
|
@@ -176,14 +187,12 @@ export class PublicExecutor {
|
|
|
176
187
|
// We use this cache to hold the packed arguments.
|
|
177
188
|
const packedArgs = PackedArgsCache.create([]);
|
|
178
189
|
|
|
179
|
-
const sideEffectCounter = new SideEffectCounter();
|
|
180
|
-
|
|
181
190
|
const context = new PublicExecutionContext(
|
|
182
191
|
execution,
|
|
183
192
|
this.header,
|
|
184
193
|
globalVariables,
|
|
185
194
|
packedArgs,
|
|
186
|
-
sideEffectCounter,
|
|
195
|
+
new SideEffectCounter(sideEffectCounter),
|
|
187
196
|
this.stateDb,
|
|
188
197
|
this.contractsDb,
|
|
189
198
|
this.commitmentsDb,
|
|
@@ -213,9 +222,10 @@ export class PublicExecutor {
|
|
|
213
222
|
public async simulateAvm(
|
|
214
223
|
execution: PublicExecution,
|
|
215
224
|
globalVariables: GlobalVariables,
|
|
225
|
+
_sideEffectCounter = 0,
|
|
216
226
|
): Promise<PublicExecutionResult> {
|
|
217
227
|
// Temporary code to construct the AVM context
|
|
218
|
-
// These data structures will
|
|
228
|
+
// These data structures will permeate across the simulator when the public executor is phased out
|
|
219
229
|
const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
|
|
220
230
|
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
221
231
|
const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
|
|
@@ -244,8 +254,6 @@ export class PublicExecutor {
|
|
|
244
254
|
*/
|
|
245
255
|
public async getAvmProof(avmExecution: PublicExecution): Promise<Buffer[]> {
|
|
246
256
|
// The paths for the barretenberg binary and the write path are hardcoded for now.
|
|
247
|
-
// We additionally need the path to a valid crs for proof generation.
|
|
248
|
-
// const bbPath = '../../barretenberg/cpp';
|
|
249
257
|
const bbPath = path.resolve('../../barretenberg/cpp');
|
|
250
258
|
const artifactsPath = path.resolve('target');
|
|
251
259
|
|
|
@@ -273,8 +281,6 @@ export class PublicExecutor {
|
|
|
273
281
|
bytecodePath,
|
|
274
282
|
'-d',
|
|
275
283
|
calldataPath,
|
|
276
|
-
'-c',
|
|
277
|
-
path.join(bbPath, 'srs_db', 'ignition'),
|
|
278
284
|
'-o',
|
|
279
285
|
proofPath,
|
|
280
286
|
]);
|
|
@@ -4,6 +4,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
6
6
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
7
|
+
import { ContractInstance } from '@aztec/types/contracts';
|
|
7
8
|
|
|
8
9
|
import { TypedOracle, toACVMWitness } from '../acvm/index.js';
|
|
9
10
|
import { PackedArgsCache, SideEffectCounter } from '../common/index.js';
|
|
@@ -49,7 +50,13 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
49
50
|
*/
|
|
50
51
|
public getInitialWitness(witnessStartIndex = 0) {
|
|
51
52
|
const { callContext, args } = this.execution;
|
|
52
|
-
const fields = [
|
|
53
|
+
const fields = [
|
|
54
|
+
...callContext.toFields(),
|
|
55
|
+
...this.header.toFields(),
|
|
56
|
+
...this.globalVariables.toFields(),
|
|
57
|
+
new Fr(this.sideEffectCounter.current()),
|
|
58
|
+
...args,
|
|
59
|
+
];
|
|
53
60
|
|
|
54
61
|
return toACVMWitness(witnessStartIndex, fields);
|
|
55
62
|
}
|
|
@@ -160,6 +167,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
160
167
|
targetContractAddress: AztecAddress,
|
|
161
168
|
functionSelector: FunctionSelector,
|
|
162
169
|
argsHash: Fr,
|
|
170
|
+
sideEffectCounter: number,
|
|
163
171
|
isStaticCall: boolean,
|
|
164
172
|
isDelegateCall: boolean,
|
|
165
173
|
) {
|
|
@@ -188,7 +196,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
188
196
|
functionSelector,
|
|
189
197
|
isDelegateCall,
|
|
190
198
|
isStaticCall,
|
|
191
|
-
|
|
199
|
+
sideEffectCounter,
|
|
192
200
|
});
|
|
193
201
|
|
|
194
202
|
const nestedExecution: PublicExecution = {
|
|
@@ -237,4 +245,17 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
237
245
|
}
|
|
238
246
|
return await this.commitmentsDb.getNullifierMembershipWitnessAtLatestBlock(nullifier);
|
|
239
247
|
}
|
|
248
|
+
|
|
249
|
+
public async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
|
|
250
|
+
// Note to AVM implementor: The wrapper of the oracle call get_contract_instance in aztec-nr
|
|
251
|
+
// automatically checks that the returned instance is correct, by hashing it together back
|
|
252
|
+
// into the address. However, in the AVM, we also need to prove the negative, otherwise a malicious
|
|
253
|
+
// sequencer could just lie about not having the instance available in its local db. We can do this
|
|
254
|
+
// by using the prove_contract_non_deployment_at method if the contract is not found in the db.
|
|
255
|
+
const instance = await this.contractsDb.getContractInstance(address);
|
|
256
|
+
if (!instance) {
|
|
257
|
+
throw new Error(`Contract instance at ${address} not found`);
|
|
258
|
+
}
|
|
259
|
+
return instance;
|
|
260
|
+
}
|
|
240
261
|
}
|