@aztec/simulator 0.0.1-commit.e6bd8901 → 0.0.1-commit.ec5f612
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 +5 -3
- 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_context.d.ts +3 -3
- package/dest/public/avm/avm_context.d.ts.map +1 -1
- package/dest/public/avm/avm_contract_call_result.d.ts +6 -6
- package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -1
- package/dest/public/avm/avm_contract_call_result.js +3 -3
- package/dest/public/avm/avm_execution_environment.d.ts +6 -5
- package/dest/public/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/public/avm/avm_gas.js +3 -3
- package/dest/public/avm/avm_machine_state.d.ts +6 -5
- package/dest/public/avm/avm_machine_state.d.ts.map +1 -1
- package/dest/public/avm/avm_machine_state.js +3 -2
- package/dest/public/avm/avm_simulator.d.ts +3 -2
- package/dest/public/avm/avm_simulator.d.ts.map +1 -1
- package/dest/public/avm/avm_simulator.js +5 -4
- package/dest/public/avm/calldata.d.ts +51 -0
- package/dest/public/avm/calldata.d.ts.map +1 -0
- package/dest/public/avm/calldata.js +63 -0
- 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/fixtures/avm_simulation_tester.d.ts +1 -1
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/avm_simulation_tester.js +3 -2
- package/dest/public/avm/fixtures/initializers.d.ts +1 -1
- package/dest/public/avm/fixtures/initializers.d.ts.map +1 -1
- package/dest/public/avm/fixtures/initializers.js +2 -1
- package/dest/public/avm/opcodes/accrued_substate.d.ts +4 -5
- package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/public/avm/opcodes/accrued_substate.js +15 -16
- package/dest/public/avm/opcodes/external_calls.d.ts +1 -1
- package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/public/avm/opcodes/external_calls.js +7 -7
- package/dest/public/avm/opcodes/memory.js +1 -1
- 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/debug_fn_name.d.ts +4 -4
- package/dest/public/debug_fn_name.d.ts.map +1 -1
- package/dest/public/debug_fn_name.js +7 -5
- 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 +3 -4
- package/dest/public/fixtures/opcode_spammer.d.ts.map +1 -1
- package/dest/public/fixtures/opcode_spammer.js +16 -56
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +29 -2
- package/dest/public/fixtures/utils.js +4 -4
- package/dest/public/hinting_db_sources.d.ts +2 -2
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +1 -1
- package/dest/public/public_db_sources.d.ts +4 -3
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +4 -4
- package/dest/public/public_processor/guarded_merkle_tree.d.ts +2 -2
- package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
- package/dest/public/public_processor/guarded_merkle_tree.js +1 -1
- 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 +24 -11
- 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 +2 -2
- 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 +4 -3
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +8 -8
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +4 -3
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +11 -8
- 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 +10 -4
- package/dest/public/state_manager/state_manager.d.ts.map +1 -1
- package/dest/public/state_manager/state_manager.js +12 -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 +16 -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 +5 -3
- 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_context.ts +2 -2
- package/src/public/avm/avm_contract_call_result.ts +8 -6
- package/src/public/avm/avm_execution_environment.ts +9 -4
- package/src/public/avm/avm_gas.ts +2 -2
- package/src/public/avm/avm_machine_state.ts +6 -5
- package/src/public/avm/avm_simulator.ts +8 -5
- package/src/public/avm/calldata.ts +100 -0
- 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/fixtures/avm_simulation_tester.ts +8 -2
- package/src/public/avm/fixtures/initializers.ts +2 -1
- package/src/public/avm/opcodes/accrued_substate.ts +16 -19
- package/src/public/avm/opcodes/external_calls.ts +8 -7
- package/src/public/avm/opcodes/memory.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/debug_fn_name.ts +10 -8
- package/src/public/executor_metrics.ts +4 -1
- package/src/public/fixtures/amm_test.ts +2 -2
- package/src/public/fixtures/opcode_spammer.ts +18 -55
- package/src/public/fixtures/public_tx_simulation_tester.ts +34 -3
- package/src/public/fixtures/utils.ts +4 -4
- package/src/public/fuzzing/avm_fuzzer_simulator.ts +1 -1
- package/src/public/hinting_db_sources.ts +1 -1
- package/src/public/public_db_sources.ts +15 -5
- package/src/public/public_processor/guarded_merkle_tree.ts +1 -1
- package/src/public/public_processor/public_processor.ts +42 -20
- package/src/public/public_processor/public_processor_metrics.ts +10 -4
- package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +6 -3
- 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 +13 -6
- package/src/public/public_tx_simulator/public_tx_simulator.ts +17 -8
- package/src/public/side_effect_trace.ts +5 -2
- package/src/public/state_manager/state_manager.ts +27 -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);
|
|
@@ -13,6 +13,7 @@ import { SimpleContractDataSource } from '../../fixtures/simple_contract_data_so
|
|
|
13
13
|
import { PublicContractsDB, PublicTreesDB } from '../../public_db_sources.js';
|
|
14
14
|
import { PublicPersistableStateManager } from '../../state_manager/state_manager.js';
|
|
15
15
|
import { AvmSimulator } from '../avm_simulator.js';
|
|
16
|
+
import { CallDataArray } from '../calldata.js';
|
|
16
17
|
import { BaseAvmSimulationTester } from './base_avm_simulation_tester.js';
|
|
17
18
|
import { initContext, initExecutionEnvironment } from './initializers.js';
|
|
18
19
|
import {
|
|
@@ -89,7 +90,7 @@ export class AvmSimulationTester extends BaseAvmSimulationTester {
|
|
|
89
90
|
collectCallMetadata: true,
|
|
90
91
|
});
|
|
91
92
|
const environment = initExecutionEnvironment({
|
|
92
|
-
calldata,
|
|
93
|
+
calldata: new CallDataArray(calldata),
|
|
93
94
|
globals,
|
|
94
95
|
address,
|
|
95
96
|
sender,
|
|
@@ -105,7 +106,12 @@ export class AvmSimulationTester extends BaseAvmSimulationTester {
|
|
|
105
106
|
if (result.reverted) {
|
|
106
107
|
this.logger.error(`Error in ${fnName}:`);
|
|
107
108
|
this.logger.error(
|
|
108
|
-
resolveContractAssertionMessage(
|
|
109
|
+
resolveContractAssertionMessage(
|
|
110
|
+
fnName,
|
|
111
|
+
result.revertReason!,
|
|
112
|
+
result.output.bestEffortReadAll(),
|
|
113
|
+
contractArtifact,
|
|
114
|
+
)!,
|
|
109
115
|
);
|
|
110
116
|
} else {
|
|
111
117
|
this.logger.info(`Simulation of function ${fnName} succeeded!`);
|
|
@@ -19,6 +19,7 @@ import { AvmContext } from '../avm_context.js';
|
|
|
19
19
|
import { AvmExecutionEnvironment } from '../avm_execution_environment.js';
|
|
20
20
|
import { AvmMachineState } from '../avm_machine_state.js';
|
|
21
21
|
import { AvmSimulator } from '../avm_simulator.js';
|
|
22
|
+
import { CallDataArray } from '../calldata.js';
|
|
22
23
|
import { DEFAULT_TIMESTAMP } from './utils.js';
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -70,7 +71,7 @@ export function initExecutionEnvironment(overrides?: Partial<AvmExecutionEnviron
|
|
|
70
71
|
overrides?.transactionFee ?? Fr.zero(),
|
|
71
72
|
overrides?.globals ?? GlobalVariables.empty(),
|
|
72
73
|
overrides?.isStaticCall ?? false,
|
|
73
|
-
overrides?.calldata ?? [],
|
|
74
|
+
overrides?.calldata ?? new CallDataArray([]),
|
|
74
75
|
overrides?.config ?? PublicSimulatorConfig.empty(),
|
|
75
76
|
);
|
|
76
77
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { MAX_ETH_ADDRESS_VALUE } from '@aztec/constants';
|
|
2
|
+
|
|
1
3
|
import { NullifierCollisionError } from '../../side_effect_errors.js';
|
|
2
4
|
import type { AvmContext } from '../avm_context.js';
|
|
3
5
|
import { TypeTag, Uint1 } from '../avm_memory_types.js';
|
|
@@ -86,18 +88,11 @@ export class NullifierExists extends Instruction {
|
|
|
86
88
|
static type: string = 'NULLIFIEREXISTS';
|
|
87
89
|
static readonly opcode: Opcode = Opcode.NULLIFIEREXISTS;
|
|
88
90
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
89
|
-
static readonly wireFormat = [
|
|
90
|
-
OperandType.UINT8,
|
|
91
|
-
OperandType.UINT8,
|
|
92
|
-
OperandType.UINT16,
|
|
93
|
-
OperandType.UINT16,
|
|
94
|
-
OperandType.UINT16,
|
|
95
|
-
];
|
|
91
|
+
static readonly wireFormat = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT16, OperandType.UINT16];
|
|
96
92
|
|
|
97
93
|
constructor(
|
|
98
94
|
private addressingMode: number,
|
|
99
|
-
private
|
|
100
|
-
private addressOffset: number,
|
|
95
|
+
private siloedNullifierOffset: number,
|
|
101
96
|
private existsOffset: number,
|
|
102
97
|
) {
|
|
103
98
|
super();
|
|
@@ -111,13 +106,12 @@ export class NullifierExists extends Instruction {
|
|
|
111
106
|
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
112
107
|
);
|
|
113
108
|
|
|
114
|
-
const operands = [this.
|
|
115
|
-
const [
|
|
116
|
-
memory.
|
|
109
|
+
const operands = [this.siloedNullifierOffset, this.existsOffset];
|
|
110
|
+
const [siloedNullifierOffset, existsOffset] = addressing.resolve(operands, memory);
|
|
111
|
+
memory.checkTag(TypeTag.FIELD, siloedNullifierOffset);
|
|
117
112
|
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const exists = await context.persistableState.checkNullifierExists(address, nullifier);
|
|
113
|
+
const siloedNullifier = memory.get(siloedNullifierOffset).toFr();
|
|
114
|
+
const exists = await context.persistableState.checkSiloedNullifierExists(siloedNullifier);
|
|
121
115
|
|
|
122
116
|
memory.set(existsOffset, exists ? new Uint1(1) : new Uint1(0));
|
|
123
117
|
}
|
|
@@ -210,10 +204,9 @@ export class L1ToL2MessageExists extends Instruction {
|
|
|
210
204
|
}
|
|
211
205
|
}
|
|
212
206
|
|
|
213
|
-
export class
|
|
214
|
-
|
|
215
|
-
static
|
|
216
|
-
static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG;
|
|
207
|
+
export class EmitPublicLog extends Instruction {
|
|
208
|
+
static type: string = 'EMITPUBLICLOG';
|
|
209
|
+
static readonly opcode: Opcode = Opcode.EMITPUBLICLOG;
|
|
217
210
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
218
211
|
static readonly wireFormat = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT16, OperandType.UINT16];
|
|
219
212
|
|
|
@@ -282,6 +275,10 @@ export class SendL2ToL1Message extends Instruction {
|
|
|
282
275
|
memory.checkTags(TypeTag.FIELD, recipientOffset, contentOffset);
|
|
283
276
|
|
|
284
277
|
const recipient = memory.get(recipientOffset).toFr();
|
|
278
|
+
|
|
279
|
+
if (recipient.toBigInt() > MAX_ETH_ADDRESS_VALUE) {
|
|
280
|
+
throw new InstructionExecutionError(`SENDL2TOL1MSG: Recipient address is too large`);
|
|
281
|
+
}
|
|
285
282
|
const content = memory.get(contentOffset).toFr();
|
|
286
283
|
context.persistableState.writeL2ToL1Message(context.environment.address, recipient, content);
|
|
287
284
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
2
|
import type { AvmContractCallResult } from '../avm_contract_call_result.js';
|
|
3
3
|
import { type Field, TypeTag, Uint1 } from '../avm_memory_types.js';
|
|
4
|
+
import { CallDataMemory, ReturnDataMemory } from '../calldata.js';
|
|
4
5
|
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
5
6
|
import { Addressing } from './addressing_mode.js';
|
|
6
7
|
import { Instruction } from './instruction.js';
|
|
@@ -45,8 +46,8 @@ abstract class ExternalCall extends Instruction {
|
|
|
45
46
|
memory.checkTag(TypeTag.UINT32, argsSizeOffset);
|
|
46
47
|
|
|
47
48
|
const calldataSize = memory.get(argsSizeOffset).toNumber();
|
|
48
|
-
|
|
49
|
-
const calldata = memory
|
|
49
|
+
|
|
50
|
+
const calldata = new CallDataMemory(memory, argsOffset, calldataSize);
|
|
50
51
|
|
|
51
52
|
const callAddress = memory.getAs<Field>(addrOffset);
|
|
52
53
|
// If we are already in a static call, we propagate the environment.
|
|
@@ -73,8 +74,8 @@ abstract class ExternalCall extends Instruction {
|
|
|
73
74
|
const success = !nestedCallResults.reverted;
|
|
74
75
|
|
|
75
76
|
// Save return/revert data for later.
|
|
76
|
-
const
|
|
77
|
-
context.machineState.nestedReturndata =
|
|
77
|
+
const returnData = nestedCallResults.output;
|
|
78
|
+
context.machineState.nestedReturndata = returnData;
|
|
78
79
|
|
|
79
80
|
// Track the success status directly
|
|
80
81
|
context.machineState.nestedCallSuccess = success;
|
|
@@ -89,7 +90,7 @@ abstract class ExternalCall extends Instruction {
|
|
|
89
90
|
// (in Noir code).
|
|
90
91
|
if (!success) {
|
|
91
92
|
context.machineState.collectedRevertInfo = {
|
|
92
|
-
revertDataRepresentative:
|
|
93
|
+
revertDataRepresentative: returnData.bestEffortReadAll(),
|
|
93
94
|
recursiveRevertReason: nestedCallResults.revertReason!,
|
|
94
95
|
};
|
|
95
96
|
}
|
|
@@ -195,7 +196,7 @@ export class Return extends Instruction {
|
|
|
195
196
|
memory.checkTag(TypeTag.UINT32, returnSizeOffset);
|
|
196
197
|
const returnSize = memory.get(returnSizeOffset).toNumber();
|
|
197
198
|
|
|
198
|
-
const output = memory
|
|
199
|
+
const output = new ReturnDataMemory(memory, returnOffset, returnSize);
|
|
199
200
|
|
|
200
201
|
context.machineState.return(output);
|
|
201
202
|
}
|
|
@@ -243,7 +244,7 @@ export class Revert extends Instruction {
|
|
|
243
244
|
|
|
244
245
|
memory.checkTag(TypeTag.UINT32, retSizeOffset);
|
|
245
246
|
const retSize = memory.get(retSizeOffset).toNumber();
|
|
246
|
-
const output = memory
|
|
247
|
+
const output = new ReturnDataMemory(memory, returnOffset, retSize);
|
|
247
248
|
|
|
248
249
|
context.machineState.revert(output);
|
|
249
250
|
}
|
|
@@ -242,7 +242,7 @@ export class ReturndataSize extends Instruction {
|
|
|
242
242
|
const operands = [this.dstOffset];
|
|
243
243
|
const [dstOffset] = addressing.resolve(operands, memory);
|
|
244
244
|
|
|
245
|
-
memory.set(dstOffset, new Uint32(context.machineState.nestedReturndata.length));
|
|
245
|
+
memory.set(dstOffset, new Uint32(context.machineState.nestedReturndata.length()));
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
|
|
@@ -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
|
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
1
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
3
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
3
|
|
|
4
|
+
import type { CallData } from './avm/calldata.js';
|
|
5
5
|
import type { PublicContractsDBInterface } from './db_interfaces.js';
|
|
6
6
|
|
|
7
7
|
export async function getPublicFunctionDebugName(
|
|
8
8
|
db: PublicContractsDBInterface,
|
|
9
9
|
contractAddress: AztecAddress,
|
|
10
|
-
calldata:
|
|
10
|
+
calldata: CallData,
|
|
11
11
|
): Promise<string> {
|
|
12
12
|
// Public function is dispatched and therefore the target function is passed in the first argument.
|
|
13
|
-
|
|
13
|
+
const selectorField = calldata.read(0);
|
|
14
|
+
if (!selectorField) {
|
|
14
15
|
return `<calldata[0] undefined> (Contract Address: ${contractAddress})`;
|
|
15
16
|
}
|
|
16
|
-
const fallbackName = `<calldata[0]:${
|
|
17
|
-
const selector = FunctionSelector.fromFieldOrUndefined(
|
|
17
|
+
const fallbackName = `<calldata[0]:${selectorField.toString()}> (Contract Address: ${contractAddress})`;
|
|
18
|
+
const selector = FunctionSelector.fromFieldOrUndefined(selectorField);
|
|
18
19
|
if (!selector) {
|
|
19
20
|
return fallbackName;
|
|
20
21
|
}
|
|
@@ -32,13 +33,14 @@ export async function getPublicFunctionDebugName(
|
|
|
32
33
|
export async function getPublicFunctionSelectorAndName(
|
|
33
34
|
db: PublicContractsDBInterface,
|
|
34
35
|
contractAddress: AztecAddress,
|
|
35
|
-
calldata:
|
|
36
|
+
calldata: CallData,
|
|
36
37
|
): Promise<{ functionSelector?: FunctionSelector; functionName?: string }> {
|
|
37
38
|
// Public function is dispatched and therefore the target function is passed in the first argument.
|
|
38
|
-
|
|
39
|
+
const selectorField = calldata.read(0);
|
|
40
|
+
if (!selectorField) {
|
|
39
41
|
return {};
|
|
40
42
|
}
|
|
41
|
-
const selector = FunctionSelector.fromFieldOrUndefined(
|
|
43
|
+
const selector = FunctionSelector.fromFieldOrUndefined(selectorField);
|
|
42
44
|
if (!selector) {
|
|
43
45
|
return {};
|
|
44
46
|
}
|
|
@@ -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
|
*
|
|
@@ -164,7 +164,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
164
164
|
import type { Bufferable } from '@aztec/foundation/serialize';
|
|
165
165
|
import { type CallStackMetadata, PublicDataWrite, type PublicTxResult } from '@aztec/stdlib/avm';
|
|
166
166
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
167
|
-
import { computePublicDataTreeLeafSlot
|
|
167
|
+
import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
|
|
168
168
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
169
169
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
170
170
|
|
|
@@ -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,
|
|
@@ -295,9 +295,8 @@ export interface SpamConfigsForOpcode {
|
|
|
295
295
|
export const WARM_NOTE_HASH = new Fr(0xdeadbeefn);
|
|
296
296
|
export const WARM_L1_TO_L2_MSG = new Fr(0xcafebabedeadbeefn);
|
|
297
297
|
|
|
298
|
-
/** Warm nullifier
|
|
299
|
-
export const
|
|
300
|
-
export const WARM_NULLIFIER_ADDRESS = AztecAddress.fromNumber(0xbeef);
|
|
298
|
+
/** Warm nullifier constant - a pre-siloed nullifier value inserted directly into the tree */
|
|
299
|
+
export const WARM_SILOED_NULLIFIER = new Fr(0xdeadbeef0001n);
|
|
301
300
|
|
|
302
301
|
/** Warm storage constants - storage is inserted for the deployed contract's address */
|
|
303
302
|
export const WARM_STORAGE_SLOT = new Fr(0xdeadbeef0002n);
|
|
@@ -331,9 +330,8 @@ export async function insertWarmTreeEntries(
|
|
|
331
330
|
// Insert into L1 to L2 message tree
|
|
332
331
|
await merkleTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, [WARM_L1_TO_L2_MSG]);
|
|
333
332
|
|
|
334
|
-
// Insert siloed nullifier into nullifier tree
|
|
335
|
-
|
|
336
|
-
await merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [siloedNullifier.toBuffer()]);
|
|
333
|
+
// Insert siloed nullifier into nullifier tree (already siloed - used directly by NULLIFIEREXISTS)
|
|
334
|
+
await merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [WARM_SILOED_NULLIFIER.toBuffer()]);
|
|
337
335
|
|
|
338
336
|
// Insert storage value into public data tree
|
|
339
337
|
const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, WARM_STORAGE_SLOT);
|
|
@@ -1060,56 +1058,25 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
|
|
|
1060
1058
|
[Opcode.NULLIFIEREXISTS]: [
|
|
1061
1059
|
{
|
|
1062
1060
|
label: 'Non-existent nullifier',
|
|
1061
|
+
// NULLIFIEREXISTS now takes a siloed nullifier directly (no address parameter)
|
|
1063
1062
|
setup: [
|
|
1064
|
-
{ offset: 0, value: new Field(Fr.random()) }, // random nullifier
|
|
1065
|
-
{ offset: 1, value: new Field(Fr.random()) }, // random address
|
|
1063
|
+
{ offset: 0, value: new Field(Fr.random()) }, // random siloed nullifier (won't exist)
|
|
1066
1064
|
],
|
|
1067
1065
|
targetInstructions: () => [
|
|
1068
|
-
new NullifierExists(/*addressing_mode=*/ 0, /*
|
|
1066
|
+
new NullifierExists(/*addressing_mode=*/ 0, /*siloedNullifierOffset=*/ 0, /*existsOffset=*/ 1),
|
|
1069
1067
|
],
|
|
1070
1068
|
},
|
|
1071
1069
|
{
|
|
1072
1070
|
label: 'Existing nullifier (warm - from tree)',
|
|
1073
|
-
// Uses pre-inserted nullifier from insertWarmTreeEntries()
|
|
1071
|
+
// Uses pre-inserted siloed nullifier from insertWarmTreeEntries()
|
|
1072
|
+
// NULLIFIEREXISTS now takes a siloed nullifier directly
|
|
1074
1073
|
setup: [
|
|
1075
|
-
{ offset: 0, value: new Field(
|
|
1076
|
-
{ offset: 1, value: new Field(WARM_NULLIFIER_ADDRESS.toField()) }, // address it was siloed with
|
|
1074
|
+
{ offset: 0, value: new Field(WARM_SILOED_NULLIFIER) }, // pre-inserted siloed nullifier
|
|
1077
1075
|
],
|
|
1078
1076
|
targetInstructions: () => [
|
|
1079
|
-
new NullifierExists(/*addressing_mode=*/ 0, /*
|
|
1077
|
+
new NullifierExists(/*addressing_mode=*/ 0, /*siloedNullifierOffset=*/ 0, /*existsOffset=*/ 1),
|
|
1080
1078
|
],
|
|
1081
1079
|
},
|
|
1082
|
-
{
|
|
1083
|
-
label: 'Existing nullifier (warm - EMITNULLIFIER first)',
|
|
1084
|
-
// Memory layout: nullifier (incremented), constant 1, current address (from GETENVVAR), revertSize, exists result
|
|
1085
|
-
setup: [
|
|
1086
|
-
{ offset: 0, value: new Field(Fr.random()) }, // nullifier (will be incremented)
|
|
1087
|
-
{ offset: 1, value: new Field(1n) }, // constant 1 for ADD
|
|
1088
|
-
() => [
|
|
1089
|
-
// Get current contract address into offset 2
|
|
1090
|
-
new GetEnvVar(/*addressing_mode=*/ 0, /*dstOffset=*/ 2, /*varEnum=*/ 0).as(
|
|
1091
|
-
Opcode.GETENVVAR_16,
|
|
1092
|
-
GetEnvVar.wireFormat16,
|
|
1093
|
-
),
|
|
1094
|
-
],
|
|
1095
|
-
{ offset: 3, value: new Uint32(0n) }, // revertSize
|
|
1096
|
-
],
|
|
1097
|
-
targetInstructions: () => [
|
|
1098
|
-
new EmitNullifier(/*addressing_mode=*/ 0, /*nullifierOffset=*/ 0),
|
|
1099
|
-
new NullifierExists(/*addressing_mode=*/ 0, /*nullifierOffset=*/ 0, /*addressOffset=*/ 2, /*existsOffset=*/ 4),
|
|
1100
|
-
new Add(/*addressing_mode=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 0).as(
|
|
1101
|
-
Opcode.ADD_8,
|
|
1102
|
-
Add.wireFormat8,
|
|
1103
|
-
), // nullifier++
|
|
1104
|
-
],
|
|
1105
|
-
cleanupInstructions: () => [
|
|
1106
|
-
new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 3, /*returnOffset=*/ 0).as(
|
|
1107
|
-
Opcode.REVERT_8,
|
|
1108
|
-
Revert.wireFormat8,
|
|
1109
|
-
),
|
|
1110
|
-
],
|
|
1111
|
-
limit: MAX_NULLIFIERS_PER_TX - 1,
|
|
1112
|
-
},
|
|
1113
1080
|
],
|
|
1114
1081
|
|
|
1115
1082
|
[Opcode.L1TOL2MSGEXISTS]: [
|
|
@@ -1275,17 +1242,15 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
|
|
|
1275
1242
|
},
|
|
1276
1243
|
],
|
|
1277
1244
|
|
|
1278
|
-
//
|
|
1279
|
-
[Opcode.
|
|
1245
|
+
// EMITPUBLICLOG - two configs: minimal (many small logs) and max-size (one large log)
|
|
1246
|
+
[Opcode.EMITPUBLICLOG]: [
|
|
1280
1247
|
{
|
|
1281
1248
|
label: 'Many empty logs, revert, repeat',
|
|
1282
1249
|
setup: [
|
|
1283
1250
|
{ offset: 0, value: new Uint32(0n) }, // logSize = 0 fields (minimal)
|
|
1284
1251
|
{ offset: 1, value: new Uint32(0n) }, // revertSize
|
|
1285
1252
|
],
|
|
1286
|
-
targetInstructions: () => [
|
|
1287
|
-
new EmitUnencryptedLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 1),
|
|
1288
|
-
], // 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
|
|
1289
1254
|
cleanupInstructions: () => [
|
|
1290
1255
|
new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 1, /*returnOffset=*/ 0).as(
|
|
1291
1256
|
Opcode.REVERT_8,
|
|
@@ -1309,9 +1274,7 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
|
|
|
1309
1274
|
// value: new Field(0n),
|
|
1310
1275
|
//})),
|
|
1311
1276
|
],
|
|
1312
|
-
targetInstructions: () => [
|
|
1313
|
-
new EmitUnencryptedLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 2),
|
|
1314
|
-
], // uses logOffset 2 (uninitialized Field(0))
|
|
1277
|
+
targetInstructions: () => [new EmitPublicLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 2)], // uses logOffset 2 (uninitialized Field(0))
|
|
1315
1278
|
cleanupInstructions: () => [
|
|
1316
1279
|
new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 1, /*returnOffset=*/ 0).as(
|
|
1317
1280
|
Opcode.REVERT_8,
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
3
|
+
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
4
|
+
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
5
|
+
TX_DA_GAS_OVERHEAD,
|
|
6
|
+
} from '@aztec/constants';
|
|
2
7
|
import { asyncMap } from '@aztec/foundation/async-map';
|
|
3
8
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
4
9
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
@@ -131,8 +136,11 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
131
136
|
teardownCallRequest,
|
|
132
137
|
feePayer,
|
|
133
138
|
/*gasUsedByPrivate*/ teardownCall
|
|
134
|
-
? new Gas(
|
|
135
|
-
|
|
139
|
+
? new Gas(
|
|
140
|
+
DEFAULT_TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD,
|
|
141
|
+
DEFAULT_TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
142
|
+
)
|
|
143
|
+
: new Gas(TX_DA_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD),
|
|
136
144
|
defaultGlobals(),
|
|
137
145
|
);
|
|
138
146
|
}
|
|
@@ -161,6 +169,8 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
161
169
|
}
|
|
162
170
|
const avmResult = await this.simulator.simulate(tx, fullTxLabel);
|
|
163
171
|
|
|
172
|
+
await this.#recordBytecodeSizes(fullTxLabel, [...setupCalls, ...appCalls, ...(teardownCall ? [teardownCall] : [])]);
|
|
173
|
+
|
|
164
174
|
// Something like this is often useful for debugging:
|
|
165
175
|
//if (avmResult.revertReason) {
|
|
166
176
|
// // resolve / enrich revert reason
|
|
@@ -277,6 +287,27 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
277
287
|
|
|
278
288
|
return new PublicCallRequestWithCalldata(request, calldata);
|
|
279
289
|
}
|
|
290
|
+
|
|
291
|
+
// WARNING: Deduplicates by artifact name, so two different artifacts with the same name
|
|
292
|
+
// in a single tx would only record the first one's bytecode size.
|
|
293
|
+
async #recordBytecodeSizes(txLabel: string, calls: TestEnqueuedCall[]) {
|
|
294
|
+
const seenArtifactNames = new Set<string>();
|
|
295
|
+
for (const call of calls) {
|
|
296
|
+
const artifact = await this.contractDataSource.getContractArtifact(call.address);
|
|
297
|
+
if (!artifact || seenArtifactNames.has(artifact.name)) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
seenArtifactNames.add(artifact.name);
|
|
301
|
+
const instance = await this.contractDataSource.getContract(call.address);
|
|
302
|
+
if (!instance) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const contractClass = await this.contractDataSource.getContractClass(instance.currentContractClassId);
|
|
306
|
+
if (contractClass) {
|
|
307
|
+
this.metrics.recordBytecodeSize(txLabel, artifact.name, contractClass.packedBytecode.length);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
280
311
|
}
|
|
281
312
|
|
|
282
313
|
export function defaultGlobals() {
|