@aztec/simulator 0.26.6 → 0.27.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/acvm.js +2 -2
- package/dest/acvm/serialize.d.ts.map +1 -1
- package/dest/acvm/serialize.js +8 -3
- package/dest/avm/avm_context.d.ts +3 -3
- package/dest/avm/avm_context.d.ts.map +1 -1
- package/dest/avm/avm_context.js +6 -5
- package/dest/avm/avm_execution_environment.d.ts +3 -3
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +16 -17
- package/dest/avm/avm_memory_types.d.ts +9 -0
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +34 -4
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +3 -3
- package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/avm/opcodes/arithmetic.js +2 -1
- package/dest/avm/opcodes/comparators.d.ts.map +1 -1
- package/dest/avm/opcodes/comparators.js +5 -7
- package/dest/avm/opcodes/control_flow.d.ts +0 -20
- package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
- package/dest/avm/opcodes/control_flow.js +2 -46
- package/dest/avm/opcodes/external_calls.d.ts +24 -2
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +74 -17
- package/dest/avm/serialization/instruction_serialization.d.ts +1 -2
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +9 -3
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +4 -6
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +3 -3
- package/dest/public/executor.d.ts +21 -0
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +87 -1
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +1 -2
- package/package.json +5 -5
- package/src/acvm/acvm.ts +1 -1
- package/src/acvm/serialize.ts +9 -3
- package/src/avm/avm_context.ts +21 -5
- package/src/avm/avm_execution_environment.ts +27 -12
- package/src/avm/avm_memory_types.ts +36 -3
- package/src/avm/avm_simulator.ts +10 -3
- package/src/avm/opcodes/arithmetic.ts +2 -0
- package/src/avm/opcodes/comparators.ts +4 -6
- package/src/avm/opcodes/control_flow.ts +1 -47
- package/src/avm/opcodes/external_calls.ts +88 -14
- package/src/avm/serialization/instruction_serialization.ts +8 -2
- package/src/client/client_execution_context.ts +1 -13
- package/src/client/simulator.ts +1 -2
- package/src/public/executor.ts +99 -0
- package/src/public/public_execution_context.ts +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
|
+
import { TaggedMemory } from '../avm_memory_types.js';
|
|
2
3
|
import { Opcode } from '../serialization/instruction_serialization.js';
|
|
3
4
|
import { ThreeOperandInstruction } from './instruction_impl.js';
|
|
4
5
|
|
|
@@ -16,8 +17,7 @@ export class Eq extends ThreeOperandInstruction {
|
|
|
16
17
|
const a = context.machineState.memory.get(this.aOffset);
|
|
17
18
|
const b = context.machineState.memory.get(this.bOffset);
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
const dest = a.build(a.equals(b) ? 1n : 0n);
|
|
20
|
+
const dest = TaggedMemory.buildFromTagOrDie(a.equals(b) ? 1n : 0n, this.inTag);
|
|
21
21
|
context.machineState.memory.set(this.dstOffset, dest);
|
|
22
22
|
|
|
23
23
|
context.machineState.incrementPc();
|
|
@@ -38,8 +38,7 @@ export class Lt extends ThreeOperandInstruction {
|
|
|
38
38
|
const a = context.machineState.memory.get(this.aOffset);
|
|
39
39
|
const b = context.machineState.memory.get(this.bOffset);
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
const dest = a.build(a.lt(b) ? 1n : 0n);
|
|
41
|
+
const dest = TaggedMemory.buildFromTagOrDie(a.lt(b) ? 1n : 0n, this.inTag);
|
|
43
42
|
context.machineState.memory.set(this.dstOffset, dest);
|
|
44
43
|
|
|
45
44
|
context.machineState.incrementPc();
|
|
@@ -60,8 +59,7 @@ export class Lte extends ThreeOperandInstruction {
|
|
|
60
59
|
const a = context.machineState.memory.get(this.aOffset);
|
|
61
60
|
const b = context.machineState.memory.get(this.bOffset);
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
const dest = a.build(a.equals(b) || a.lt(b) ? 1n : 0n);
|
|
62
|
+
const dest = TaggedMemory.buildFromTagOrDie(a.lt(b) || a.equals(b) ? 1n : 0n, this.inTag);
|
|
65
63
|
context.machineState.memory.set(this.dstOffset, dest);
|
|
66
64
|
|
|
67
65
|
context.machineState.incrementPc();
|
|
@@ -4,52 +4,6 @@ import { InstructionExecutionError } from '../errors.js';
|
|
|
4
4
|
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
5
5
|
import { Instruction } from './instruction.js';
|
|
6
6
|
|
|
7
|
-
export class Return extends Instruction {
|
|
8
|
-
static type: string = 'RETURN';
|
|
9
|
-
static readonly opcode: Opcode = Opcode.RETURN;
|
|
10
|
-
// Informs (de)serialization. See Instruction.deserialize.
|
|
11
|
-
static readonly wireFormat: OperandType[] = [
|
|
12
|
-
OperandType.UINT8,
|
|
13
|
-
OperandType.UINT8,
|
|
14
|
-
OperandType.UINT32,
|
|
15
|
-
OperandType.UINT32,
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
constructor(private indirect: number, private returnOffset: number, private copySize: number) {
|
|
19
|
-
super();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async execute(context: AvmContext): Promise<void> {
|
|
23
|
-
const output = context.machineState.memory.getSlice(this.returnOffset, this.copySize).map(word => word.toFr());
|
|
24
|
-
|
|
25
|
-
context.machineState.return(output);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class Revert extends Instruction {
|
|
30
|
-
static type: string = 'RETURN';
|
|
31
|
-
static readonly opcode: Opcode = Opcode.REVERT;
|
|
32
|
-
// Informs (de)serialization. See Instruction.deserialize.
|
|
33
|
-
static readonly wireFormat: OperandType[] = [
|
|
34
|
-
OperandType.UINT8,
|
|
35
|
-
OperandType.UINT8,
|
|
36
|
-
OperandType.UINT32,
|
|
37
|
-
OperandType.UINT32,
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
constructor(private indirect: number, private returnOffset: number, private retSize: number) {
|
|
41
|
-
super();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async execute(context: AvmContext): Promise<void> {
|
|
45
|
-
const output = context.machineState.memory
|
|
46
|
-
.getSlice(this.returnOffset, this.returnOffset + this.retSize)
|
|
47
|
-
.map(word => word.toFr());
|
|
48
|
-
|
|
49
|
-
context.machineState.revert(output);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
7
|
export class Jump extends Instruction {
|
|
54
8
|
static type: string = 'JUMP';
|
|
55
9
|
static readonly opcode: Opcode = Opcode.JUMP;
|
|
@@ -122,7 +76,7 @@ export class InternalReturn extends Instruction {
|
|
|
122
76
|
async execute(context: AvmContext): Promise<void> {
|
|
123
77
|
const jumpOffset = context.machineState.internalCallStack.pop();
|
|
124
78
|
if (jumpOffset === undefined) {
|
|
125
|
-
throw new InstructionExecutionError('Internal call empty!');
|
|
79
|
+
throw new InstructionExecutionError('Internal call stack empty!');
|
|
126
80
|
}
|
|
127
81
|
context.machineState.pc = jumpOffset;
|
|
128
82
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FunctionSelector } from '@aztec/circuits.js';
|
|
2
2
|
|
|
3
3
|
import type { AvmContext } from '../avm_context.js';
|
|
4
|
-
import { Field } from '../avm_memory_types.js';
|
|
4
|
+
import { Field, Uint8 } from '../avm_memory_types.js';
|
|
5
5
|
import { AvmSimulator } from '../avm_simulator.js';
|
|
6
6
|
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
7
|
+
import { Addressing } from './addressing_mode.js';
|
|
7
8
|
import { Instruction } from './instruction.js';
|
|
8
9
|
|
|
9
10
|
export class Call extends Instruction {
|
|
@@ -20,6 +21,8 @@ export class Call extends Instruction {
|
|
|
20
21
|
OperandType.UINT32,
|
|
21
22
|
OperandType.UINT32,
|
|
22
23
|
OperandType.UINT32,
|
|
24
|
+
/* temporary function selector */
|
|
25
|
+
OperandType.UINT32,
|
|
23
26
|
];
|
|
24
27
|
|
|
25
28
|
constructor(
|
|
@@ -31,16 +34,30 @@ export class Call extends Instruction {
|
|
|
31
34
|
private retOffset: number,
|
|
32
35
|
private retSize: number,
|
|
33
36
|
private successOffset: number,
|
|
37
|
+
// Function selector is temporary since eventually public contract bytecode will be one blob
|
|
38
|
+
// containing all functions, and function selector will become an application-level mechanism
|
|
39
|
+
// (e.g. first few bytes of calldata + compiler-generated jump table)
|
|
40
|
+
private temporaryFunctionSelectorOffset: number,
|
|
34
41
|
) {
|
|
35
42
|
super();
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/3992): there is no concept of remaining / available gas at this moment
|
|
39
46
|
async execute(context: AvmContext): Promise<void> {
|
|
40
|
-
const
|
|
41
|
-
|
|
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,
|
|
50
|
+
);
|
|
51
|
+
|
|
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();
|
|
42
55
|
|
|
43
|
-
const nestedContext = context.createNestedContractCallContext(
|
|
56
|
+
const nestedContext = context.createNestedContractCallContext(
|
|
57
|
+
callAddress.toFr(),
|
|
58
|
+
calldata,
|
|
59
|
+
FunctionSelector.fromField(functionSelector),
|
|
60
|
+
);
|
|
44
61
|
|
|
45
62
|
const nestedCallResults = await new AvmSimulator(nestedContext).execute();
|
|
46
63
|
const success = !nestedCallResults.reverted;
|
|
@@ -50,8 +67,8 @@ export class Call extends Instruction {
|
|
|
50
67
|
const convertedReturnData = returnData.map(f => new Field(f));
|
|
51
68
|
|
|
52
69
|
// Write our return data into memory
|
|
53
|
-
context.machineState.memory.set(
|
|
54
|
-
context.machineState.memory.setSlice(
|
|
70
|
+
context.machineState.memory.set(successOffset, new Uint8(success ? 1 : 0));
|
|
71
|
+
context.machineState.memory.setSlice(retOffset, convertedReturnData);
|
|
55
72
|
|
|
56
73
|
if (success) {
|
|
57
74
|
context.persistableState.acceptNestedCallState(nestedContext.persistableState);
|
|
@@ -77,6 +94,8 @@ export class StaticCall extends Instruction {
|
|
|
77
94
|
OperandType.UINT32,
|
|
78
95
|
OperandType.UINT32,
|
|
79
96
|
OperandType.UINT32,
|
|
97
|
+
/* temporary function selector */
|
|
98
|
+
OperandType.UINT32,
|
|
80
99
|
];
|
|
81
100
|
|
|
82
101
|
constructor(
|
|
@@ -88,17 +107,26 @@ export class StaticCall extends Instruction {
|
|
|
88
107
|
private retOffset: number,
|
|
89
108
|
private retSize: number,
|
|
90
109
|
private successOffset: number,
|
|
110
|
+
private temporaryFunctionSelectorOffset: number,
|
|
91
111
|
) {
|
|
92
112
|
super();
|
|
93
113
|
}
|
|
94
114
|
|
|
95
115
|
async execute(context: AvmContext): Promise<void> {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
.
|
|
99
|
-
|
|
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
|
+
);
|
|
100
120
|
|
|
101
|
-
const
|
|
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
|
+
);
|
|
102
130
|
|
|
103
131
|
const nestedCallResults = await new AvmSimulator(nestedContext).execute();
|
|
104
132
|
const success = !nestedCallResults.reverted;
|
|
@@ -108,8 +136,8 @@ export class StaticCall extends Instruction {
|
|
|
108
136
|
const convertedReturnData = returnData.map(f => new Field(f));
|
|
109
137
|
|
|
110
138
|
// Write our return data into memory
|
|
111
|
-
context.machineState.memory.set(
|
|
112
|
-
context.machineState.memory.setSlice(
|
|
139
|
+
context.machineState.memory.set(successOffset, new Uint8(success ? 1 : 0));
|
|
140
|
+
context.machineState.memory.setSlice(retOffset, convertedReturnData);
|
|
113
141
|
|
|
114
142
|
if (success) {
|
|
115
143
|
context.persistableState.acceptNestedCallState(nestedContext.persistableState);
|
|
@@ -120,3 +148,49 @@ export class StaticCall extends Instruction {
|
|
|
120
148
|
context.machineState.incrementPc();
|
|
121
149
|
}
|
|
122
150
|
}
|
|
151
|
+
|
|
152
|
+
export class Return extends Instruction {
|
|
153
|
+
static type: string = 'RETURN';
|
|
154
|
+
static readonly opcode: Opcode = Opcode.RETURN;
|
|
155
|
+
// Informs (de)serialization. See Instruction.deserialize.
|
|
156
|
+
static readonly wireFormat: OperandType[] = [
|
|
157
|
+
OperandType.UINT8,
|
|
158
|
+
OperandType.UINT8,
|
|
159
|
+
OperandType.UINT32,
|
|
160
|
+
OperandType.UINT32,
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
constructor(private indirect: number, private returnOffset: number, private copySize: number) {
|
|
164
|
+
super();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async execute(context: AvmContext): Promise<void> {
|
|
168
|
+
const output = context.machineState.memory.getSlice(this.returnOffset, this.copySize).map(word => word.toFr());
|
|
169
|
+
|
|
170
|
+
context.machineState.return(output);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export class Revert extends Instruction {
|
|
175
|
+
static type: string = 'RETURN';
|
|
176
|
+
static readonly opcode: Opcode = Opcode.REVERT;
|
|
177
|
+
// Informs (de)serialization. See Instruction.deserialize.
|
|
178
|
+
static readonly wireFormat: OperandType[] = [
|
|
179
|
+
OperandType.UINT8,
|
|
180
|
+
OperandType.UINT8,
|
|
181
|
+
OperandType.UINT32,
|
|
182
|
+
OperandType.UINT32,
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
constructor(private indirect: number, private returnOffset: number, private retSize: number) {
|
|
186
|
+
super();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async execute(context: AvmContext): Promise<void> {
|
|
190
|
+
const output = context.machineState.memory
|
|
191
|
+
.getSlice(this.returnOffset, this.returnOffset + this.retSize)
|
|
192
|
+
.map(word => word.toFr());
|
|
193
|
+
|
|
194
|
+
context.machineState.revert(output);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -7,6 +7,7 @@ import { BufferCursor } from './buffer_cursor.js';
|
|
|
7
7
|
* Source: https://yp-aztec.netlify.app/docs/public-vm/instruction-set
|
|
8
8
|
*/
|
|
9
9
|
export enum Opcode {
|
|
10
|
+
// Compute
|
|
10
11
|
ADD,
|
|
11
12
|
SUB,
|
|
12
13
|
MUL,
|
|
@@ -21,6 +22,7 @@ export enum Opcode {
|
|
|
21
22
|
SHL,
|
|
22
23
|
SHR,
|
|
23
24
|
CAST,
|
|
25
|
+
// Execution environment
|
|
24
26
|
ADDRESS,
|
|
25
27
|
STORAGEADDRESS,
|
|
26
28
|
ORIGIN,
|
|
@@ -39,16 +41,20 @@ export enum Opcode {
|
|
|
39
41
|
BLOCKL2GASLIMIT,
|
|
40
42
|
BLOCKDAGASLIMIT,
|
|
41
43
|
CALLDATACOPY,
|
|
44
|
+
// Gas
|
|
42
45
|
L1GASLEFT,
|
|
43
46
|
L2GASLEFT,
|
|
44
47
|
DAGASLEFT,
|
|
48
|
+
// Control flow
|
|
45
49
|
JUMP,
|
|
46
50
|
JUMPI,
|
|
47
51
|
INTERNALCALL,
|
|
48
52
|
INTERNALRETURN,
|
|
53
|
+
// Memory
|
|
49
54
|
SET,
|
|
50
55
|
MOV,
|
|
51
56
|
CMOV,
|
|
57
|
+
// World state
|
|
52
58
|
SLOAD,
|
|
53
59
|
SSTORE,
|
|
54
60
|
NOTEHASHEXISTS,
|
|
@@ -59,17 +65,17 @@ export enum Opcode {
|
|
|
59
65
|
HEADERMEMBER,
|
|
60
66
|
EMITUNENCRYPTEDLOG,
|
|
61
67
|
SENDL2TOL1MSG,
|
|
68
|
+
// External calls
|
|
62
69
|
CALL,
|
|
63
70
|
STATICCALL,
|
|
64
71
|
DELEGATECALL,
|
|
65
72
|
RETURN,
|
|
66
73
|
REVERT,
|
|
74
|
+
// Gadgets
|
|
67
75
|
KECCAK,
|
|
68
76
|
POSEIDON,
|
|
69
|
-
// Add new opcodes before this
|
|
70
77
|
SHA256, // temp - may be removed, but alot of contracts rely on it
|
|
71
78
|
PEDERSEN, // temp - may be removed, but alot of contracts rely on it
|
|
72
|
-
TOTAL_OPCODES_NUMBER,
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
// Possible types for an instruction's operand in its wire format. (Keep in sync with CPP code.
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from '@aztec/circuit-types';
|
|
11
11
|
import {
|
|
12
12
|
CallContext,
|
|
13
|
-
ContractDeploymentData,
|
|
14
13
|
FunctionData,
|
|
15
14
|
FunctionSelector,
|
|
16
15
|
Header,
|
|
@@ -89,8 +88,6 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
89
88
|
* @returns The initial witness.
|
|
90
89
|
*/
|
|
91
90
|
public getInitialWitness(abi: FunctionAbi) {
|
|
92
|
-
const contractDeploymentData = this.txContext.contractDeploymentData;
|
|
93
|
-
|
|
94
91
|
const argumentsSize = countArgumentsSize(abi);
|
|
95
92
|
|
|
96
93
|
const args = this.packedArgsCache.unpack(this.argsHash);
|
|
@@ -102,7 +99,6 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
102
99
|
const fields = [
|
|
103
100
|
...this.callContext.toFields(),
|
|
104
101
|
...this.historicalHeader.toFields(),
|
|
105
|
-
...contractDeploymentData.toFields(),
|
|
106
102
|
|
|
107
103
|
this.txContext.chainId,
|
|
108
104
|
this.txContext.version,
|
|
@@ -348,14 +344,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
348
344
|
const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
349
345
|
const targetFunctionData = FunctionData.fromAbi(targetArtifact);
|
|
350
346
|
|
|
351
|
-
const derivedTxContext = new TxContext(
|
|
352
|
-
false,
|
|
353
|
-
false,
|
|
354
|
-
false,
|
|
355
|
-
ContractDeploymentData.empty(),
|
|
356
|
-
this.txContext.chainId,
|
|
357
|
-
this.txContext.version,
|
|
358
|
-
);
|
|
347
|
+
const derivedTxContext = new TxContext(false, false, this.txContext.chainId, this.txContext.version);
|
|
359
348
|
|
|
360
349
|
const derivedCallContext = await this.deriveCallContext(
|
|
361
350
|
targetContractAddress,
|
|
@@ -470,7 +459,6 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
470
459
|
FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters),
|
|
471
460
|
isDelegateCall,
|
|
472
461
|
isStaticCall,
|
|
473
|
-
false,
|
|
474
462
|
startSideEffectCounter,
|
|
475
463
|
);
|
|
476
464
|
}
|
package/src/client/simulator.ts
CHANGED
|
@@ -92,10 +92,9 @@ export class AcirSimulator {
|
|
|
92
92
|
FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters),
|
|
93
93
|
false,
|
|
94
94
|
false,
|
|
95
|
-
request.functionData.isConstructor,
|
|
96
95
|
// TODO: when contract deployment is done in-app, we should only reserve one counter for the tx hash
|
|
97
96
|
// 2 counters are reserved for tx hash and contract deployment nullifier
|
|
98
|
-
|
|
97
|
+
1,
|
|
99
98
|
);
|
|
100
99
|
const context = new ClientExecutionContext(
|
|
101
100
|
contractAddress,
|
package/src/public/executor.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { FunctionL2Logs } from '@aztec/circuit-types';
|
|
|
2
2
|
import { GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
|
|
3
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
|
|
5
9
|
import { Oracle, acvm, extractCallStack, extractReturnWitness } from '../acvm/index.js';
|
|
6
10
|
import { AvmContext } from '../avm/avm_context.js';
|
|
7
11
|
import { AvmMachineState } from '../avm/avm_machine_state.js';
|
|
@@ -220,4 +224,99 @@ export class PublicExecutor {
|
|
|
220
224
|
const newWorldState = context.persistableState.flush();
|
|
221
225
|
return temporaryConvertAvmResults(execution, newWorldState, result);
|
|
222
226
|
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* These functions are currently housed in the temporary executor as it relies on access to
|
|
230
|
+
* oracles like the contractsDB and this is the least intrusive way to achieve this.
|
|
231
|
+
* When we remove this executor(tracking issue #4792) and have an interface that is compatible with the kernel circuits,
|
|
232
|
+
* this will be moved to sequencer-client/prover.
|
|
233
|
+
*/
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Generates a proof for an associated avm execution. This is currently only used for testing purposes,
|
|
237
|
+
* as proof generation is not fully complete in the AVM yet.
|
|
238
|
+
* @param execution - The execution to run.
|
|
239
|
+
* @returns An AVM proof and the verification key.
|
|
240
|
+
*/
|
|
241
|
+
public async getAvmProof(avmExecution: PublicExecution): Promise<Buffer[]> {
|
|
242
|
+
// The paths for the barretenberg binary and the write path are hardcoded for now.
|
|
243
|
+
// We additionally need the path to a valid crs for proof generation.
|
|
244
|
+
// const bbPath = '../../barretenberg/cpp';
|
|
245
|
+
const bbPath = path.resolve('../../barretenberg/cpp');
|
|
246
|
+
const artifactsPath = path.resolve('target');
|
|
247
|
+
|
|
248
|
+
// Create the directory if it does not exist
|
|
249
|
+
await fs.mkdir(artifactsPath, { recursive: true });
|
|
250
|
+
|
|
251
|
+
const calldataPath = path.join(artifactsPath, 'calldata.bin');
|
|
252
|
+
const bytecodePath = path.join(artifactsPath, 'avm_bytecode.bin');
|
|
253
|
+
const proofPath = path.join(artifactsPath, 'proof');
|
|
254
|
+
|
|
255
|
+
const { args, functionData, contractAddress } = avmExecution;
|
|
256
|
+
const bytecode = await this.contractsDb.getBytecode(contractAddress, functionData.selector);
|
|
257
|
+
// Write call data and bytecode to files.
|
|
258
|
+
await Promise.all([
|
|
259
|
+
fs.writeFile(
|
|
260
|
+
calldataPath,
|
|
261
|
+
args.map(c => c.toBuffer()),
|
|
262
|
+
),
|
|
263
|
+
fs.writeFile(bytecodePath, bytecode!),
|
|
264
|
+
]);
|
|
265
|
+
|
|
266
|
+
const bbBinary = spawn(path.join(bbPath, 'build', 'bin', 'bb'), [
|
|
267
|
+
'avm_prove',
|
|
268
|
+
'-b',
|
|
269
|
+
bytecodePath,
|
|
270
|
+
'-d',
|
|
271
|
+
calldataPath,
|
|
272
|
+
'-c',
|
|
273
|
+
path.join(bbPath, 'srs_db', 'ignition'),
|
|
274
|
+
'-o',
|
|
275
|
+
proofPath,
|
|
276
|
+
]);
|
|
277
|
+
// The binary writes the proof and the verification key to the write path.
|
|
278
|
+
return new Promise((resolve, reject) => {
|
|
279
|
+
bbBinary.on('close', () => {
|
|
280
|
+
resolve(Promise.all([fs.readFile(proofPath), fs.readFile(path.join(artifactsPath, 'vk'))]));
|
|
281
|
+
});
|
|
282
|
+
// Catch and propagate errors from spawning
|
|
283
|
+
bbBinary.on('error', err => {
|
|
284
|
+
reject(err);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Verifies an AVM proof. This function is currently only used for testing purposes, as verification
|
|
290
|
+
* is not fully complete in the AVM yet.
|
|
291
|
+
* @param vk - The verification key to use.
|
|
292
|
+
* @param proof - The proof to verify.
|
|
293
|
+
* @returns True if the proof is valid, false otherwise.
|
|
294
|
+
*/
|
|
295
|
+
async verifyAvmProof(vk: Buffer, proof: Buffer): Promise<boolean> {
|
|
296
|
+
// The relative paths for the barretenberg binary and the write path are hardcoded for now.
|
|
297
|
+
const bbPath = path.resolve('../../barretenberg/cpp');
|
|
298
|
+
const artifactsPath = path.resolve('./target');
|
|
299
|
+
|
|
300
|
+
const vkPath = path.join(artifactsPath, 'vk');
|
|
301
|
+
const proofPath = path.join(artifactsPath, 'proof');
|
|
302
|
+
|
|
303
|
+
// Write the verification key and the proof to files.
|
|
304
|
+
await Promise.all([fs.writeFile(vkPath, vk), fs.writeFile(proofPath, proof)]);
|
|
305
|
+
|
|
306
|
+
const bbBinary = spawn(path.join(bbPath, 'build', 'bin', 'bb'), ['avm_verify', '-p', proofPath]);
|
|
307
|
+
// The binary prints to stdout 1 if the proof is valid and 0 if it is not.
|
|
308
|
+
return new Promise((resolve, reject) => {
|
|
309
|
+
let result = Buffer.alloc(0);
|
|
310
|
+
bbBinary.stdout.on('data', data => {
|
|
311
|
+
result += data;
|
|
312
|
+
});
|
|
313
|
+
bbBinary.on('close', () => {
|
|
314
|
+
resolve(result.toString() === '1');
|
|
315
|
+
});
|
|
316
|
+
// Catch and propagate errors from spawning
|
|
317
|
+
bbBinary.on('error', err => {
|
|
318
|
+
reject(err);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
}
|
|
223
322
|
}
|
|
@@ -186,7 +186,6 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
186
186
|
storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress,
|
|
187
187
|
portalContractAddress: portalAddress,
|
|
188
188
|
functionSelector,
|
|
189
|
-
isContractDeployment: false,
|
|
190
189
|
isDelegateCall,
|
|
191
190
|
isStaticCall,
|
|
192
191
|
startSideEffectCounter: 0, // TODO use counters in public execution
|