@aztec/simulator 0.0.1-commit.29c6b1a3 → 0.0.1-commit.2b2662070
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/README.md +4 -4
- package/dest/private/acvm/acvm.d.ts +4 -2
- package/dest/private/acvm/acvm.d.ts.map +1 -1
- package/dest/private/acvm/acvm.js +4 -3
- package/dest/private/acvm_native.d.ts +5 -3
- package/dest/private/acvm_native.d.ts.map +1 -1
- package/dest/private/acvm_native.js +8 -6
- package/dest/private/acvm_wasm.d.ts +4 -3
- package/dest/private/acvm_wasm.d.ts.map +1 -1
- package/dest/private/acvm_wasm.js +4 -4
- package/dest/private/circuit_recording/circuit_recorder.d.ts +4 -3
- package/dest/private/circuit_recording/circuit_recorder.d.ts.map +1 -1
- package/dest/private/circuit_recording/circuit_recorder.js +7 -5
- package/dest/private/circuit_recording/file_circuit_recorder.d.ts +3 -2
- package/dest/private/circuit_recording/file_circuit_recorder.d.ts.map +1 -1
- package/dest/private/circuit_recording/file_circuit_recorder.js +2 -2
- package/dest/private/circuit_recording/memory_circuit_recorder.d.ts +7 -2
- package/dest/private/circuit_recording/memory_circuit_recorder.d.ts.map +1 -1
- package/dest/private/circuit_recording/memory_circuit_recorder.js +4 -4
- package/dest/private/factory.d.ts +3 -3
- package/dest/private/factory.d.ts.map +1 -1
- package/dest/private/factory.js +7 -4
- package/dest/public/avm/avm_gas.js +3 -3
- package/dest/public/avm/avm_simulator.js +1 -1
- package/dest/public/avm/calldata.d.ts +1 -1
- package/dest/public/avm/calldata.d.ts.map +1 -1
- package/dest/public/avm/calldata.js +3 -2
- package/dest/public/avm/fixtures/account_proof_fetcher.d.ts +2 -0
- package/dest/public/avm/fixtures/account_proof_fetcher.d.ts.map +1 -0
- package/dest/public/avm/fixtures/account_proof_fetcher.js +152 -0
- package/dest/public/avm/opcodes/accrued_substate.d.ts +2 -2
- package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/public/avm/opcodes/accrued_substate.js +3 -4
- package/dest/public/avm/serialization/bytecode_serialization.js +3 -3
- package/dest/public/avm/serialization/instruction_serialization.d.ts +2 -2
- package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/public/avm/serialization/instruction_serialization.js +1 -1
- package/dest/public/contracts_db_checkpoint.d.ts +2 -2
- package/dest/public/contracts_db_checkpoint.d.ts.map +1 -1
- package/dest/public/contracts_db_checkpoint.js +1 -1
- package/dest/public/executor_metrics.d.ts +1 -1
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +7 -2
- package/dest/public/fixtures/amm_test.js +2 -2
- package/dest/public/fixtures/opcode_spammer.d.ts +1 -1
- package/dest/public/fixtures/opcode_spammer.d.ts.map +1 -1
- package/dest/public/fixtures/opcode_spammer.js +6 -6
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +6 -5
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +37 -10
- package/dest/public/fixtures/utils.d.ts +2 -2
- package/dest/public/fixtures/utils.d.ts.map +1 -1
- package/dest/public/fixtures/utils.js +10 -10
- package/dest/public/hinting_db_sources.d.ts +5 -5
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +7 -6
- package/dest/public/public_db_sources.d.ts +6 -5
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +14 -14
- package/dest/public/public_processor/guarded_merkle_tree.d.ts +5 -5
- package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
- package/dest/public/public_processor/guarded_merkle_tree.js +5 -5
- package/dest/public/public_processor/public_processor.d.ts +8 -4
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +60 -47
- package/dest/public/public_processor/public_processor_metrics.d.ts +2 -2
- package/dest/public/public_processor/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor_metrics.js +20 -4
- package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts +3 -2
- package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/contract_provider_for_cpp.js +4 -3
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts +5 -5
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator.js +10 -11
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.d.ts +4 -4
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.js +7 -7
- package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.d.ts +4 -4
- package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.js +6 -6
- package/dest/public/public_tx_simulator/dumping_cpp_public_tx_simulator.d.ts +3 -2
- package/dest/public/public_tx_simulator/dumping_cpp_public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/dumping_cpp_public_tx_simulator.js +2 -2
- package/dest/public/public_tx_simulator/factories.d.ts +3 -2
- package/dest/public/public_tx_simulator/factories.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/factories.js +4 -4
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +10 -5
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +16 -18
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +9 -4
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +19 -12
- package/dest/public/side_effect_trace.d.ts +4 -4
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +3 -3
- package/dest/public/state_manager/state_manager.d.ts +4 -4
- package/dest/public/state_manager/state_manager.d.ts.map +1 -1
- package/dest/public/state_manager/state_manager.js +5 -5
- package/dest/public/test_executor_metrics.d.ts +8 -2
- package/dest/public/test_executor_metrics.d.ts.map +1 -1
- package/dest/public/test_executor_metrics.js +24 -2
- package/package.json +15 -16
- package/src/private/acvm/acvm.ts +4 -3
- package/src/private/acvm_native.ts +11 -5
- package/src/private/acvm_wasm.ts +7 -3
- package/src/private/circuit_recording/circuit_recorder.ts +7 -5
- package/src/private/circuit_recording/file_circuit_recorder.ts +7 -2
- package/src/private/circuit_recording/memory_circuit_recorder.ts +6 -4
- package/src/private/factory.ts +7 -4
- package/src/public/avm/avm_gas.ts +2 -2
- package/src/public/avm/avm_simulator.ts +1 -1
- package/src/public/avm/calldata.ts +3 -2
- package/src/public/avm/fixtures/account_proof.json +553 -0
- package/src/public/avm/fixtures/account_proof_fetcher.ts +166 -0
- package/src/public/avm/opcodes/accrued_substate.ts +3 -4
- package/src/public/avm/opcodes/external_calls.ts +1 -1
- package/src/public/avm/serialization/bytecode_serialization.ts +2 -2
- package/src/public/avm/serialization/instruction_serialization.ts +1 -1
- package/src/public/contracts_db_checkpoint.ts +1 -1
- package/src/public/executor_metrics.ts +4 -1
- package/src/public/fixtures/amm_test.ts +2 -2
- package/src/public/fixtures/opcode_spammer.ts +6 -10
- package/src/public/fixtures/public_tx_simulation_tester.ts +47 -6
- package/src/public/fixtures/utils.ts +17 -12
- package/src/public/fuzzing/avm_fuzzer_simulator.ts +1 -1
- package/src/public/hinting_db_sources.ts +9 -7
- package/src/public/public_db_sources.ts +27 -19
- package/src/public/public_processor/guarded_merkle_tree.ts +6 -6
- package/src/public/public_processor/public_processor.ts +86 -60
- package/src/public/public_processor/public_processor_metrics.ts +10 -4
- package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +8 -4
- package/src/public/public_tx_simulator/cpp_public_tx_simulator.ts +10 -8
- package/src/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.ts +7 -5
- package/src/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.ts +7 -5
- package/src/public/public_tx_simulator/dumping_cpp_public_tx_simulator.ts +3 -1
- package/src/public/public_tx_simulator/factories.ts +6 -3
- package/src/public/public_tx_simulator/public_tx_context.ts +21 -16
- package/src/public/public_tx_simulator/public_tx_simulator.ts +20 -12
- package/src/public/side_effect_trace.ts +5 -2
- package/src/public/state_manager/state_manager.ts +19 -4
- package/src/public/test_executor_metrics.ts +27 -3
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches an account proof from the Ethereum mainnet and saves it as account_proof.json.
|
|
3
|
+
* This script is not using any Aztec library code, so it's easily portable.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { createPublicClient, fromRlp, hexToBytes, http } from 'viem';
|
|
9
|
+
import { mainnet } from 'viem/chains';
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
const RPC_URL = process.env.RPC_URL;
|
|
14
|
+
const ADDRESS = (process.env.ADDRESS || '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') as `0x${string}`;
|
|
15
|
+
const BLOCK_TAG = process.env.BLOCK_NUMBER ? BigInt(process.env.BLOCK_NUMBER) : 'latest';
|
|
16
|
+
const MAX_ACCOUNT_PATH = 15;
|
|
17
|
+
|
|
18
|
+
function padTo(arr: number[], len: number) {
|
|
19
|
+
return [...arr, ...Array(len - arr.length).fill(0)].slice(0, len);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function toBytes(hex: `0x${string}`) {
|
|
23
|
+
return Array.from(hexToBytes(hex));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function bytesToU64s(bytes: number[]) {
|
|
27
|
+
const paddedBytes = padTo(bytes, 32);
|
|
28
|
+
return Array.from({ length: 4 }, (_, i) => {
|
|
29
|
+
let val = 0n;
|
|
30
|
+
for (let j = 0; j < 8; j++) {
|
|
31
|
+
val += BigInt(paddedBytes[i * 8 + j]) << BigInt(j * 8);
|
|
32
|
+
}
|
|
33
|
+
return val.toString();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toBytesAndLen(val: bigint | number) {
|
|
38
|
+
if (val === 0n || val === 0) {
|
|
39
|
+
return { bytes: [0], length: 0 };
|
|
40
|
+
}
|
|
41
|
+
let hex = val.toString(16);
|
|
42
|
+
if (hex.length % 2) {
|
|
43
|
+
hex = '0' + hex;
|
|
44
|
+
}
|
|
45
|
+
const bytes = toBytes(`0x${hex}`);
|
|
46
|
+
return { bytes, length: bytes.length };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function parseNode(rlp: `0x${string}`) {
|
|
50
|
+
// Should be safe when working with branches and extensions without embedded children.
|
|
51
|
+
const decoded = fromRlp(rlp) as `0x${string}`[];
|
|
52
|
+
const node = {
|
|
53
|
+
rows: Array(16)
|
|
54
|
+
.fill(0)
|
|
55
|
+
.map(() => Array(32).fill(0)),
|
|
56
|
+
row_exist: Array(16).fill(false),
|
|
57
|
+
node_type: 0,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (decoded.length === 17) {
|
|
61
|
+
for (let i = 0; i < 16; i++) {
|
|
62
|
+
if (decoded[i] !== '0x') {
|
|
63
|
+
node.row_exist[i] = true;
|
|
64
|
+
node.rows[i] = padTo(toBytes(decoded[i]), 32);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} else if (decoded.length === 2) {
|
|
68
|
+
const keyBytes = toBytes(decoded[0]);
|
|
69
|
+
const prefix = keyBytes[0];
|
|
70
|
+
if (prefix >> 4 >= 2) {
|
|
71
|
+
throw new Error('Unsupported: leaf node in proof path');
|
|
72
|
+
}
|
|
73
|
+
node.node_type = 1;
|
|
74
|
+
// Extension header format expected by the noir code: check out storage_proof types.nr.
|
|
75
|
+
node.rows[0][0] = prefix >> 4;
|
|
76
|
+
node.rows[0][8] = prefix & 0x0f;
|
|
77
|
+
node.rows[0][16] = keyBytes.length - 1;
|
|
78
|
+
|
|
79
|
+
for (let i = 1; i < keyBytes.length && i < 32; i++) {
|
|
80
|
+
node.rows[1][i - 1] = keyBytes[i];
|
|
81
|
+
}
|
|
82
|
+
node.rows[2] = padTo(toBytes(decoded[1]), 32);
|
|
83
|
+
node.row_exist[0] = node.row_exist[1] = node.row_exist[2] = true;
|
|
84
|
+
}
|
|
85
|
+
return node;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parseProof(proof: `0x${string}`[], maxLen: number) {
|
|
89
|
+
const nodes = proof.slice(0, -1).slice(0, maxLen).map(parseNode);
|
|
90
|
+
while (nodes.length < maxLen) {
|
|
91
|
+
nodes.push({
|
|
92
|
+
rows: Array(16)
|
|
93
|
+
.fill(0)
|
|
94
|
+
.map(() => Array(32).fill(0)),
|
|
95
|
+
row_exist: Array(16).fill(false),
|
|
96
|
+
node_type: 0,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return nodes;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function nodeToLibFormat(node: { rows: number[][]; row_exist: boolean[]; node_type: number }) {
|
|
103
|
+
return {
|
|
104
|
+
rows: node.rows.map(bytesToU64s),
|
|
105
|
+
row_exist: node.row_exist,
|
|
106
|
+
node_type: String(node.node_type),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function main() {
|
|
111
|
+
if (!RPC_URL) {
|
|
112
|
+
throw new Error('RPC_URL is not set');
|
|
113
|
+
}
|
|
114
|
+
console.log(`Fetching account proof for ${ADDRESS}`);
|
|
115
|
+
|
|
116
|
+
const client = createPublicClient({
|
|
117
|
+
chain: mainnet,
|
|
118
|
+
transport: http(RPC_URL),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const [blockNumber, proof, block] = await Promise.all([
|
|
122
|
+
client.getBlockNumber(),
|
|
123
|
+
client.getProof({
|
|
124
|
+
address: ADDRESS,
|
|
125
|
+
storageKeys: [],
|
|
126
|
+
blockNumber: BLOCK_TAG === 'latest' ? undefined : BLOCK_TAG,
|
|
127
|
+
}),
|
|
128
|
+
client.getBlock({
|
|
129
|
+
blockNumber: BLOCK_TAG === 'latest' ? undefined : BLOCK_TAG,
|
|
130
|
+
}),
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
console.log(`Block: ${blockNumber}, Account nodes: ${proof.accountProof.length}`);
|
|
134
|
+
|
|
135
|
+
// The -1 is because the last node in the proof is the leaf, which is excluded from path verification.
|
|
136
|
+
const accountPathLen = proof.accountProof.length - 1;
|
|
137
|
+
if (accountPathLen > MAX_ACCOUNT_PATH) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
`Account proof path length ${accountPathLen} exceeds MAX_ACCOUNT_PATH ${MAX_ACCOUNT_PATH}. Increase the limit.`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const nonce = toBytesAndLen(proof.nonce);
|
|
144
|
+
const balance = toBytesAndLen(proof.balance);
|
|
145
|
+
|
|
146
|
+
const data = {
|
|
147
|
+
block_number: String(blockNumber),
|
|
148
|
+
node_length: String(accountPathLen),
|
|
149
|
+
root: bytesToU64s(toBytes(block.stateRoot)),
|
|
150
|
+
nodes: parseProof(proof.accountProof, MAX_ACCOUNT_PATH).map(nodeToLibFormat),
|
|
151
|
+
account: {
|
|
152
|
+
address: toBytes(ADDRESS).map(String),
|
|
153
|
+
balance: padTo(balance.bytes, 32).map(String),
|
|
154
|
+
balance_length: String(balance.length),
|
|
155
|
+
code_hash: bytesToU64s(toBytes(proof.codeHash)),
|
|
156
|
+
nonce: padTo(nonce.bytes, 8).map(String),
|
|
157
|
+
nonce_length: String(nonce.length),
|
|
158
|
+
storage_hash: bytesToU64s(toBytes(proof.storageHash)),
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
fs.writeFileSync(join(__dirname, 'account_proof.json'), JSON.stringify(data, null, 2));
|
|
163
|
+
console.log('account_proof.json generated');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
main().catch(console.error);
|
|
@@ -204,10 +204,9 @@ export class L1ToL2MessageExists extends Instruction {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
export class
|
|
208
|
-
|
|
209
|
-
static
|
|
210
|
-
static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG;
|
|
207
|
+
export class EmitPublicLog extends Instruction {
|
|
208
|
+
static type: string = 'EMITPUBLICLOG';
|
|
209
|
+
static readonly opcode: Opcode = Opcode.EMITPUBLICLOG;
|
|
211
210
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
212
211
|
static readonly wireFormat = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT16, OperandType.UINT16];
|
|
213
212
|
|
|
@@ -14,8 +14,8 @@ abstract class ExternalCall extends Instruction {
|
|
|
14
14
|
OperandType.UINT16, // L2 gas offset
|
|
15
15
|
OperandType.UINT16, // DA gas offset
|
|
16
16
|
OperandType.UINT16, // Address offset
|
|
17
|
-
OperandType.UINT16, // Args offset
|
|
18
17
|
OperandType.UINT16, // Args size offset
|
|
18
|
+
OperandType.UINT16, // Args offset
|
|
19
19
|
];
|
|
20
20
|
|
|
21
21
|
constructor(
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
EcAdd,
|
|
20
20
|
EmitNoteHash,
|
|
21
21
|
EmitNullifier,
|
|
22
|
-
|
|
22
|
+
EmitPublicLog,
|
|
23
23
|
Eq,
|
|
24
24
|
FieldDiv,
|
|
25
25
|
GetContractInstance,
|
|
@@ -129,7 +129,7 @@ export const INSTRUCTION_SET = new Map<Opcode, InstructionDeserializer>([
|
|
|
129
129
|
[L1ToL2MessageExists.opcode, Instruction.fromBuffer.bind(L1ToL2MessageExists)], // Messages
|
|
130
130
|
|
|
131
131
|
// Accrued Substate
|
|
132
|
-
[
|
|
132
|
+
[EmitPublicLog.opcode, Instruction.fromBuffer.bind(EmitPublicLog)],
|
|
133
133
|
[SendL2ToL1Message.opcode, Instruction.fromBuffer.bind(SendL2ToL1Message)],
|
|
134
134
|
[GetContractInstance.opcode, Instruction.fromBuffer.bind(GetContractInstance)],
|
|
135
135
|
|
|
@@ -31,7 +31,7 @@ export class ContractsDbCheckpoint {
|
|
|
31
31
|
return this.bytecodeCommitments.get(classId.toString());
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
public
|
|
34
|
+
public fork(): ContractsDbCheckpoint {
|
|
35
35
|
const copy = new ContractsDbCheckpoint();
|
|
36
36
|
this.instances.forEach((value, key) => copy.instances.set(key, value));
|
|
37
37
|
this.classes.forEach((value, key) => copy.classes.set(key, value));
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type TelemetryClient,
|
|
8
8
|
type Tracer,
|
|
9
9
|
type UpDownCounter,
|
|
10
|
+
createUpDownCounterWithDefault,
|
|
10
11
|
} from '@aztec/telemetry-client';
|
|
11
12
|
|
|
12
13
|
import type { ExecutorMetricsInterface } from './executor_metrics_interface.js';
|
|
@@ -25,7 +26,9 @@ export class ExecutorMetrics implements ExecutorMetricsInterface {
|
|
|
25
26
|
this.tracer = client.getTracer(name);
|
|
26
27
|
const meter = client.getMeter(name);
|
|
27
28
|
|
|
28
|
-
this.fnCount = meter
|
|
29
|
+
this.fnCount = createUpDownCounterWithDefault(meter, Metrics.PUBLIC_EXECUTOR_SIMULATION_COUNT, {
|
|
30
|
+
[Attributes.OK]: [true, false],
|
|
31
|
+
});
|
|
29
32
|
|
|
30
33
|
this.fnDuration = meter.createHistogram(Metrics.PUBLIC_EXECUTOR_SIMULATION_DURATION);
|
|
31
34
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DomainSeparator } from '@aztec/constants';
|
|
2
2
|
import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon';
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import type { Logger } from '@aztec/foundation/log';
|
|
@@ -326,6 +326,6 @@ async function removeLiquidity(
|
|
|
326
326
|
async function computePartialNoteValidityCommitment(partialNote: { commitment: Fr }, completer: AztecAddress) {
|
|
327
327
|
return await poseidon2HashWithSeparator(
|
|
328
328
|
[partialNote.commitment, completer],
|
|
329
|
-
|
|
329
|
+
DomainSeparator.PARTIAL_NOTE_VALIDITY_COMMITMENT,
|
|
330
330
|
);
|
|
331
331
|
}
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
* - `EMITNOTEHASH`: max 64 per TX
|
|
144
144
|
* - `EMITNULLIFIER`: max 63 per TX (one reserved for TX nullifier)
|
|
145
145
|
* - `SENDL2TOL1MSG`: max 8 per TX
|
|
146
|
-
* - `
|
|
146
|
+
* - `EMITPUBLICLOG`: limited by total log payload size
|
|
147
147
|
*
|
|
148
148
|
* By having the inner contract REVERT after emitting side effects, those effects are discarded, allowing the outer contract to call it again. This enables thousands of opcode executions per TX instead of just the limit.
|
|
149
149
|
*
|
|
@@ -182,7 +182,7 @@ import {
|
|
|
182
182
|
EcAdd,
|
|
183
183
|
EmitNoteHash,
|
|
184
184
|
EmitNullifier,
|
|
185
|
-
|
|
185
|
+
EmitPublicLog,
|
|
186
186
|
Eq,
|
|
187
187
|
FieldDiv,
|
|
188
188
|
GetContractInstance,
|
|
@@ -1242,17 +1242,15 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
|
|
|
1242
1242
|
},
|
|
1243
1243
|
],
|
|
1244
1244
|
|
|
1245
|
-
//
|
|
1246
|
-
[Opcode.
|
|
1245
|
+
// EMITPUBLICLOG - two configs: minimal (many small logs) and max-size (one large log)
|
|
1246
|
+
[Opcode.EMITPUBLICLOG]: [
|
|
1247
1247
|
{
|
|
1248
1248
|
label: 'Many empty logs, revert, repeat',
|
|
1249
1249
|
setup: [
|
|
1250
1250
|
{ offset: 0, value: new Uint32(0n) }, // logSize = 0 fields (minimal)
|
|
1251
1251
|
{ offset: 1, value: new Uint32(0n) }, // revertSize
|
|
1252
1252
|
],
|
|
1253
|
-
targetInstructions: () => [
|
|
1254
|
-
new EmitUnencryptedLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 1),
|
|
1255
|
-
], // logOffset doesn't matter when size is 0
|
|
1253
|
+
targetInstructions: () => [new EmitPublicLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 1)], // logOffset doesn't matter when size is 0
|
|
1256
1254
|
cleanupInstructions: () => [
|
|
1257
1255
|
new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 1, /*returnOffset=*/ 0).as(
|
|
1258
1256
|
Opcode.REVERT_8,
|
|
@@ -1276,9 +1274,7 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
|
|
|
1276
1274
|
// value: new Field(0n),
|
|
1277
1275
|
//})),
|
|
1278
1276
|
],
|
|
1279
|
-
targetInstructions: () => [
|
|
1280
|
-
new EmitUnencryptedLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 2),
|
|
1281
|
-
], // uses logOffset 2 (uninitialized Field(0))
|
|
1277
|
+
targetInstructions: () => [new EmitPublicLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 2)], // uses logOffset 2 (uninitialized Field(0))
|
|
1282
1278
|
cleanupInstructions: () => [
|
|
1283
1279
|
new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 1, /*returnOffset=*/ 0).as(
|
|
1284
1280
|
Opcode.REVERT_8,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PUBLIC_TX_L2_GAS_OVERHEAD, TX_DA_GAS_OVERHEAD } from '@aztec/constants';
|
|
2
2
|
import { asyncMap } from '@aztec/foundation/async-map';
|
|
3
3
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { type ContractArtifact, encodeArguments } from '@aztec/stdlib/abi';
|
|
6
6
|
import { PublicSimulatorConfig, type PublicTxResult } from '@aztec/stdlib/avm';
|
|
7
7
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
|
-
import { Gas, GasFees } from '@aztec/stdlib/gas';
|
|
8
|
+
import { FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT, Gas, GasFees } from '@aztec/stdlib/gas';
|
|
9
9
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
10
10
|
import { PublicCallRequest } from '@aztec/stdlib/kernel';
|
|
11
11
|
import { GlobalVariables, PublicCallRequestWithCalldata, type Tx } from '@aztec/stdlib/tx';
|
|
@@ -112,6 +112,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
112
112
|
feePayer: AztecAddress = sender,
|
|
113
113
|
/* need some unique first nullifier for note-nonce computations */
|
|
114
114
|
privateInsertions: TestPrivateInsertions = { nonRevertible: { nullifiers: [new Fr(420000 + this.txCount)] } },
|
|
115
|
+
gasLimits?: Gas,
|
|
115
116
|
): Promise<Tx> {
|
|
116
117
|
const setupCallRequests = await asyncMap(setupCalls, call =>
|
|
117
118
|
this.#createPubicCallRequestForCall(call, call.sender ?? sender),
|
|
@@ -131,9 +132,13 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
131
132
|
teardownCallRequest,
|
|
132
133
|
feePayer,
|
|
133
134
|
/*gasUsedByPrivate*/ teardownCall
|
|
134
|
-
? new Gas(
|
|
135
|
-
|
|
135
|
+
? new Gas(
|
|
136
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD,
|
|
137
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
138
|
+
)
|
|
139
|
+
: new Gas(TX_DA_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD),
|
|
136
140
|
defaultGlobals(),
|
|
141
|
+
gasLimits,
|
|
137
142
|
);
|
|
138
143
|
}
|
|
139
144
|
|
|
@@ -146,8 +151,9 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
146
151
|
/* need some unique first nullifier for note-nonce computations */
|
|
147
152
|
privateInsertions?: TestPrivateInsertions,
|
|
148
153
|
txLabel: string = 'unlabeledTx',
|
|
154
|
+
gasLimits?: Gas,
|
|
149
155
|
): Promise<PublicTxResult> {
|
|
150
|
-
const tx = await this.createTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions);
|
|
156
|
+
const tx = await this.createTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions, gasLimits);
|
|
151
157
|
|
|
152
158
|
await this.setFeePayerBalance(feePayer);
|
|
153
159
|
|
|
@@ -161,6 +167,8 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
161
167
|
}
|
|
162
168
|
const avmResult = await this.simulator.simulate(tx, fullTxLabel);
|
|
163
169
|
|
|
170
|
+
await this.#recordBytecodeSizes(fullTxLabel, [...setupCalls, ...appCalls, ...(teardownCall ? [teardownCall] : [])]);
|
|
171
|
+
|
|
164
172
|
// Something like this is often useful for debugging:
|
|
165
173
|
//if (avmResult.revertReason) {
|
|
166
174
|
// // resolve / enrich revert reason
|
|
@@ -190,8 +198,18 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
190
198
|
teardownCall?: TestEnqueuedCall,
|
|
191
199
|
feePayer?: AztecAddress,
|
|
192
200
|
privateInsertions?: TestPrivateInsertions,
|
|
201
|
+
gasLimits?: Gas,
|
|
193
202
|
): Promise<PublicTxResult> {
|
|
194
|
-
return await this.simulateTx(
|
|
203
|
+
return await this.simulateTx(
|
|
204
|
+
sender,
|
|
205
|
+
setupCalls,
|
|
206
|
+
appCalls,
|
|
207
|
+
teardownCall,
|
|
208
|
+
feePayer,
|
|
209
|
+
privateInsertions,
|
|
210
|
+
txLabel,
|
|
211
|
+
gasLimits,
|
|
212
|
+
);
|
|
195
213
|
}
|
|
196
214
|
|
|
197
215
|
/**
|
|
@@ -209,6 +227,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
209
227
|
teardownCall?: TestEnqueuedCall,
|
|
210
228
|
feePayer?: AztecAddress,
|
|
211
229
|
privateInsertions?: TestPrivateInsertions,
|
|
230
|
+
gasLimits?: Gas,
|
|
212
231
|
): Promise<PublicTxResult> {
|
|
213
232
|
return await this.simulateTxWithLabel(
|
|
214
233
|
txLabel,
|
|
@@ -218,6 +237,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
218
237
|
teardownCall,
|
|
219
238
|
feePayer,
|
|
220
239
|
privateInsertions,
|
|
240
|
+
gasLimits,
|
|
221
241
|
);
|
|
222
242
|
}
|
|
223
243
|
|
|
@@ -277,6 +297,27 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
277
297
|
|
|
278
298
|
return new PublicCallRequestWithCalldata(request, calldata);
|
|
279
299
|
}
|
|
300
|
+
|
|
301
|
+
// WARNING: Deduplicates by artifact name, so two different artifacts with the same name
|
|
302
|
+
// in a single tx would only record the first one's bytecode size.
|
|
303
|
+
async #recordBytecodeSizes(txLabel: string, calls: TestEnqueuedCall[]) {
|
|
304
|
+
const seenArtifactNames = new Set<string>();
|
|
305
|
+
for (const call of calls) {
|
|
306
|
+
const artifact = await this.contractDataSource.getContractArtifact(call.address);
|
|
307
|
+
if (!artifact || seenArtifactNames.has(artifact.name)) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
seenArtifactNames.add(artifact.name);
|
|
311
|
+
const instance = await this.contractDataSource.getContract(call.address);
|
|
312
|
+
if (!instance) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const contractClass = await this.contractDataSource.getContractClass(instance.currentContractClassId);
|
|
316
|
+
if (contractClass) {
|
|
317
|
+
this.metrics.recordBytecodeSize(txLabel, artifact.name, contractClass.packedBytecode.length);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
280
321
|
}
|
|
281
322
|
|
|
282
323
|
export function defaultGlobals() {
|
|
@@ -2,10 +2,8 @@ import {
|
|
|
2
2
|
CONTRACT_CLASS_PUBLISHED_MAGIC_VALUE,
|
|
3
3
|
CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS,
|
|
4
4
|
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
8
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
5
|
+
MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
|
|
6
|
+
MAX_PROCESSABLE_L2_GAS,
|
|
9
7
|
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
10
8
|
} from '@aztec/constants';
|
|
11
9
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
@@ -14,7 +12,13 @@ import { CONTRACT_INSTANCE_PUBLISHED_EVENT_TAG } from '@aztec/protocol-contracts
|
|
|
14
12
|
import { bufferAsFields } from '@aztec/stdlib/abi';
|
|
15
13
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
16
14
|
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
17
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT,
|
|
17
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT,
|
|
18
|
+
Gas,
|
|
19
|
+
GasFees,
|
|
20
|
+
GasSettings,
|
|
21
|
+
} from '@aztec/stdlib/gas';
|
|
18
22
|
import { siloNullifier } from '@aztec/stdlib/hash';
|
|
19
23
|
import {
|
|
20
24
|
LogHash,
|
|
@@ -62,13 +66,14 @@ export async function createTxForPublicCalls(
|
|
|
62
66
|
feePayer = AztecAddress.zero(),
|
|
63
67
|
gasUsedByPrivate: Gas = Gas.empty(),
|
|
64
68
|
globals: GlobalVariables = GlobalVariables.empty(),
|
|
69
|
+
gasLimits?: Gas,
|
|
65
70
|
): Promise<Tx> {
|
|
66
71
|
assert(
|
|
67
72
|
setupCallRequests.length > 0 || appCallRequests.length > 0 || teardownCallRequest !== undefined,
|
|
68
73
|
"Can't create public tx with no enqueued calls",
|
|
69
74
|
);
|
|
70
75
|
// use max limits
|
|
71
|
-
|
|
76
|
+
gasLimits = gasLimits ?? new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
72
77
|
|
|
73
78
|
const forPublic = PartialPrivateTailPublicInputsForPublic.empty();
|
|
74
79
|
|
|
@@ -128,19 +133,19 @@ export async function createTxForPublicCalls(
|
|
|
128
133
|
|
|
129
134
|
const maxFeesPerGas = feePayer.isZero() ? GasFees.empty() : new GasFees(10, 10);
|
|
130
135
|
const teardownGasLimits = teardownCallRequest
|
|
131
|
-
? new Gas(
|
|
136
|
+
? new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT)
|
|
132
137
|
: Gas.empty();
|
|
133
138
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, maxFeesPerGas, GasFees.empty());
|
|
134
139
|
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
135
140
|
const header = BlockHeader.empty({ globalVariables: globals });
|
|
136
141
|
const constantData = new TxConstantData(header, txContext, Fr.zero(), Fr.zero());
|
|
137
|
-
const
|
|
142
|
+
const expirationTimestamp = 0n; // Not used in the simulator.
|
|
138
143
|
|
|
139
144
|
const txData = new PrivateKernelTailCircuitPublicInputs(
|
|
140
145
|
constantData,
|
|
141
146
|
/*gasUsed=*/ gasUsedByPrivate,
|
|
142
147
|
feePayer,
|
|
143
|
-
|
|
148
|
+
expirationTimestamp,
|
|
144
149
|
forPublic,
|
|
145
150
|
);
|
|
146
151
|
|
|
@@ -163,7 +168,7 @@ export async function createTxForPrivateOnly(
|
|
|
163
168
|
gasUsedByPrivate: Gas = new Gas(10, 10),
|
|
164
169
|
): Promise<Tx> {
|
|
165
170
|
// use max limits
|
|
166
|
-
const gasLimits = new Gas(
|
|
171
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
167
172
|
|
|
168
173
|
const forRollup = PartialPrivateTailPublicInputsForRollup.empty();
|
|
169
174
|
|
|
@@ -171,13 +176,13 @@ export async function createTxForPrivateOnly(
|
|
|
171
176
|
const gasSettings = new GasSettings(gasLimits, Gas.empty(), maxFeesPerGas, GasFees.empty());
|
|
172
177
|
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
173
178
|
const constantData = new TxConstantData(BlockHeader.empty(), txContext, Fr.zero(), Fr.zero());
|
|
174
|
-
const
|
|
179
|
+
const expirationTimestamp = 0n; // Not used in the simulator.
|
|
175
180
|
|
|
176
181
|
const txData = new PrivateKernelTailCircuitPublicInputs(
|
|
177
182
|
constantData,
|
|
178
183
|
/*gasUsed=*/ gasUsedByPrivate,
|
|
179
184
|
feePayer,
|
|
180
|
-
|
|
185
|
+
expirationTimestamp,
|
|
181
186
|
/*forPublic=*/ undefined,
|
|
182
187
|
forRollup,
|
|
183
188
|
);
|
|
@@ -146,7 +146,7 @@ async function createTxFromHint(cppTx: AvmTxHint): Promise<Tx> {
|
|
|
146
146
|
constants,
|
|
147
147
|
cppTx.gasUsedByPrivate,
|
|
148
148
|
cppTx.feePayer,
|
|
149
|
-
0n, //
|
|
149
|
+
0n, // expirationTimestamp
|
|
150
150
|
forPublic,
|
|
151
151
|
undefined, // forRollup - not needed for public simulation
|
|
152
152
|
);
|
|
@@ -410,12 +410,12 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
|
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
public async createCheckpoint(): Promise<
|
|
413
|
+
public async createCheckpoint(): Promise<number> {
|
|
414
414
|
const actionCounter = this.checkpointActionCounter++;
|
|
415
415
|
const oldCheckpointId = this.getCurrentCheckpointId();
|
|
416
416
|
const treesStateHash = await this.getTreesStateHash();
|
|
417
417
|
|
|
418
|
-
await this.db.createCheckpoint();
|
|
418
|
+
const depth = await this.db.createCheckpoint();
|
|
419
419
|
this.checkpointStack.push(this.nextCheckpointId++);
|
|
420
420
|
const newCheckpointId = this.getCurrentCheckpointId();
|
|
421
421
|
|
|
@@ -424,14 +424,16 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
|
|
|
424
424
|
HintingMerkleWriteOperations.log.trace(
|
|
425
425
|
`[createCheckpoint:${actionCounter}] Checkpoint evolved ${oldCheckpointId} -> ${newCheckpointId} at trees state ${treesStateHash}.`,
|
|
426
426
|
);
|
|
427
|
+
|
|
428
|
+
return depth;
|
|
427
429
|
}
|
|
428
430
|
|
|
429
|
-
public
|
|
430
|
-
throw new Error('
|
|
431
|
+
public commitAllCheckpointsTo(_depth: number): Promise<void> {
|
|
432
|
+
throw new Error('commitAllCheckpointsTo is not supported in HintingMerkleWriteOperations.');
|
|
431
433
|
}
|
|
432
434
|
|
|
433
|
-
public
|
|
434
|
-
throw new Error('
|
|
435
|
+
public revertAllCheckpointsTo(_depth: number): Promise<void> {
|
|
436
|
+
throw new Error('revertAllCheckpointsTo is not supported in HintingMerkleWriteOperations.');
|
|
435
437
|
}
|
|
436
438
|
|
|
437
439
|
public async commitCheckpoint(): Promise<void> {
|
|
@@ -572,7 +574,7 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
|
|
|
572
574
|
return await this.db.close();
|
|
573
575
|
}
|
|
574
576
|
|
|
575
|
-
async [Symbol.
|
|
577
|
+
async [Symbol.asyncDispose](): Promise<void> {
|
|
576
578
|
await this.close();
|
|
577
579
|
}
|
|
578
580
|
|