Skip to content

Commit 9a5147a

Browse files
authored
refactor(api): Refactor VM-invoking API server methods to be less VM-specific (#3564)
## What ❔ - Refactors VM-invoking methods in the API server (e.g., gas estimation) to use less VM-specific logic. - Simplifies some VM interfaces along the way. E.g., unifies batch and oneshot VM executor results. ## Why ❔ Should somewhat simplify ZK OS integration into the API server. ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [x] Tests for the changes have been added / updated. - [x] Documentation comments have been added / updated. - [x] Code has been formatted via `zkstack dev fmt` and `zkstack dev lint`.
1 parent 298abd2 commit 9a5147a

File tree

36 files changed

+311
-490
lines changed

36 files changed

+311
-490
lines changed

core/bin/system-constants-generator/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ pub(super) fn execute_user_txs_in_test_gas_vm(
340340
}
341341

342342
let result = vm.execute(InspectExecutionMode::Bootloader);
343-
let metrics = result.get_execution_metrics(None);
343+
let metrics = result.get_execution_metrics();
344344

345345
VmSpentResourcesResult {
346346
// It is assumed that the entire `gas_used` was spent on computation and so it safe to convert to u32

core/lib/dal/src/tests/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,6 @@ pub(crate) fn mock_execution_result(transaction: L2Tx) -> TransactionExecutionRe
162162
execution_info: VmExecutionMetrics::default(),
163163
execution_status: TxExecutionStatus::Success,
164164
refunded_gas: 0,
165-
operator_suggested_refund: 0,
166-
compressed_bytecodes: vec![],
167165
call_traces: vec![],
168166
revert_reason: None,
169167
}

core/lib/dal/src/transactions_dal.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,10 @@ impl TransactionsDal<'_, '_> {
482482
value,
483483
&paymaster,
484484
&paymaster_input,
485-
exec_info.gas_used as i64,
486-
(exec_info.initial_storage_writes + exec_info.repeated_storage_writes) as i32,
487-
exec_info.contracts_used as i32,
485+
exec_info.vm.gas_used as i64,
486+
(exec_info.writes.initial_storage_writes + exec_info.writes.repeated_storage_writes)
487+
as i32,
488+
exec_info.vm.contracts_used as i32,
488489
received_at,
489490
timestamp_asserter_range_start,
490491
timestamp_asserter_range_end,

core/lib/multivm/src/versions/testonly/block_tip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ fn execute_test<VM: TestedVm>(test_data: L1MessengerTestData) -> TestStatistics
185185
TestStatistics {
186186
max_used_gas: gas_before - gas_after,
187187
circuit_statistics: result.statistics.circuit_statistic.total() as u64,
188-
execution_metrics_size: result.get_execution_metrics(None).size() as u64,
188+
execution_metrics_size: result.get_execution_metrics().size() as u64,
189189
}
190190
}
191191

core/lib/vm_executor/src/batch/factory.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{borrow::Cow, fmt, marker::PhantomData, rc::Rc, sync::Arc, time::Duration};
1+
use std::{fmt, marker::PhantomData, rc::Rc, sync::Arc, time::Duration};
22

33
use anyhow::Context as _;
44
use once_cell::sync::OnceCell;
@@ -9,9 +9,8 @@ use zksync_multivm::{
99
pubdata::PubdataBuilder,
1010
storage::{ReadStorage, StoragePtr, StorageView, StorageViewStats},
1111
utils::{DivergenceHandler, ShadowMut},
12-
BatchTransactionExecutionResult, BytecodeCompressionError, Call, CompressedBytecodeInfo,
13-
ExecutionResult, FinishedL1Batch, Halt, L1BatchEnv, L2BlockEnv, SystemEnv, VmFactory,
14-
VmInterface, VmInterfaceHistoryEnabled,
12+
BatchTransactionExecutionResult, Call, ExecutionResult, FinishedL1Batch, Halt, L1BatchEnv,
13+
L2BlockEnv, SystemEnv, VmFactory, VmInterface, VmInterfaceHistoryEnabled,
1514
},
1615
is_supported_by_fast_vm,
1716
pubdata_builders::pubdata_params_to_builder,
@@ -174,8 +173,6 @@ impl<S: ReadStorage + Send + 'static, Tr: BatchTracer> BatchExecutorFactory<S>
174173
}
175174
}
176175

177-
type BytecodeResult = Result<Vec<CompressedBytecodeInfo>, BytecodeCompressionError>;
178-
179176
#[derive(Debug)]
180177
enum BatchVm<S: ReadStorage, Tr: BatchTracer> {
181178
Legacy(LegacyVmInstance<S, HistoryEnabled>),
@@ -241,7 +238,7 @@ impl<S: ReadStorage, Tr: BatchTracer> BatchVm<S, Tr> {
241238
&mut self,
242239
tx: Transaction,
243240
with_compression: bool,
244-
) -> BatchTransactionExecutionResult<BytecodeResult> {
241+
) -> BatchTransactionExecutionResult {
245242
let legacy_tracer_result = Arc::new(OnceCell::default());
246243
let legacy_tracer = if Tr::TRACE_CALLS {
247244
vec![CallTracer::new(legacy_tracer_result.clone()).into_tracer_pointer()]
@@ -270,7 +267,7 @@ impl<S: ReadStorage, Tr: BatchTracer> BatchVm<S, Tr> {
270267
}
271268
};
272269

273-
let compressed_bytecodes = compression_result.map(Cow::into_owned);
270+
let compressed_bytecodes = compression_result.map(drop);
274271
let legacy_traces = Arc::try_unwrap(legacy_tracer_result)
275272
.expect("failed extracting call traces")
276273
.take()
@@ -289,7 +286,7 @@ impl<S: ReadStorage, Tr: BatchTracer> BatchVm<S, Tr> {
289286

290287
BatchTransactionExecutionResult {
291288
tx_result: Box::new(tx_result),
292-
compressed_bytecodes,
289+
compression_result: compressed_bytecodes,
293290
call_traces,
294291
}
295292
}
@@ -466,10 +463,10 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
466463
// and so we re-execute the transaction, but without compression.
467464

468465
let res = vm.inspect_transaction(tx.clone(), true);
469-
if let Ok(compressed_bytecodes) = res.compressed_bytecodes {
466+
if res.compression_result.is_ok() {
470467
return Ok(BatchTransactionExecutionResult {
471468
tx_result: res.tx_result,
472-
compressed_bytecodes,
469+
compression_result: Ok(()),
473470
call_traces: res.call_traces,
474471
});
475472
}
@@ -480,12 +477,11 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
480477
vm.make_snapshot();
481478

482479
let res = vm.inspect_transaction(tx.clone(), false);
483-
let compressed_bytecodes = res
484-
.compressed_bytecodes
480+
res.compression_result
485481
.context("compression failed when it wasn't applied")?;
486482
Ok(BatchTransactionExecutionResult {
487483
tx_result: res.tx_result,
488-
compressed_bytecodes,
484+
compression_result: Ok(()),
489485
call_traces: res.call_traces,
490486
})
491487
}
@@ -498,10 +494,10 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
498494
vm: &mut BatchVm<S, Tr>,
499495
) -> anyhow::Result<BatchTransactionExecutionResult> {
500496
let res = vm.inspect_transaction(tx.clone(), true);
501-
if let Ok(compressed_bytecodes) = res.compressed_bytecodes {
497+
if res.compression_result.is_ok() {
502498
Ok(BatchTransactionExecutionResult {
503499
tx_result: res.tx_result,
504-
compressed_bytecodes,
500+
compression_result: Ok(()),
505501
call_traces: res.call_traces,
506502
})
507503
} else {
@@ -512,7 +508,7 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
512508
};
513509
Ok(BatchTransactionExecutionResult {
514510
tx_result,
515-
compressed_bytecodes: vec![],
511+
compression_result: Ok(()),
516512
call_traces: vec![],
517513
})
518514
}

core/lib/vm_executor/src/batch/metrics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl BatchTipMetrics {
9292
self.circuit_statistic
9393
.observe(execution_result.statistics.circuit_statistic.total());
9494
self.execution_metrics_size
95-
.observe(execution_result.get_execution_metrics(None).size());
95+
.observe(execution_result.get_execution_metrics().size());
9696
}
9797
}
9898

core/lib/vm_interface/src/executor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub trait OneshotExecutor<S: ReadStorage> {
6161

6262
/// VM executor capable of validating transactions.
6363
#[async_trait]
64-
pub trait TransactionValidator<S: ReadStorage>: OneshotExecutor<S> {
64+
pub trait TransactionValidator<S: ReadStorage> {
6565
/// Validates the provided transaction.
6666
async fn validate_transaction(
6767
&self,

core/lib/vm_interface/src/types/outputs/execution_result.rs

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,17 @@ use zksync_system_constants::{
66
PUBLISH_BYTECODE_OVERHEAD,
77
};
88
use zksync_types::{
9+
bytecode::BytecodeHash,
910
ethabi,
1011
l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log},
1112
zk_evm_types::FarCallOpcode,
1213
Address, L1BatchNumber, StorageLogWithPreviousValue, Transaction, H256, U256,
1314
};
1415

1516
use crate::{
16-
BytecodeCompressionError, CompressedBytecodeInfo, Halt, VmExecutionMetrics,
17-
VmExecutionStatistics, VmRevertReason,
17+
BytecodeCompressionError, Halt, VmExecutionMetrics, VmExecutionStatistics, VmRevertReason,
1818
};
1919

20-
const L1_MESSAGE_EVENT_SIGNATURE: H256 = H256([
21-
58, 54, 228, 114, 145, 244, 32, 31, 175, 19, 127, 171, 8, 29, 146, 41, 91, 206, 45, 83, 190,
22-
44, 108, 166, 139, 168, 44, 127, 170, 156, 226, 65,
23-
]);
24-
25-
pub fn bytecode_len_in_bytes(bytecodehash: H256) -> usize {
26-
usize::from(u16::from_be_bytes([bytecodehash[2], bytecodehash[3]])) * 32
27-
}
28-
2920
/// Event generated by the VM.
3021
#[derive(Default, Debug, Clone, PartialEq)]
3122
pub struct VmEvent {
@@ -51,6 +42,11 @@ impl VmEvent {
5142
201, 71, 34, 255, 19, 234, 207, 83, 84, 124, 71, 65, 218, 181, 34, 131, 83, 160, 89, 56,
5243
255, 205, 213, 212, 162, 213, 51, 174, 14, 97, 130, 135,
5344
]);
45+
/// Long signature of the L1 messenger publication event (`L1MessageSent`).
46+
pub const L1_MESSAGE_EVENT_SIGNATURE: H256 = H256([
47+
58, 54, 228, 114, 145, 244, 32, 31, 175, 19, 127, 171, 8, 29, 146, 41, 91, 206, 45, 83,
48+
190, 44, 108, 166, 139, 168, 44, 127, 170, 156, 226, 65,
49+
]);
5450

5551
/// Extracts all the "long" L2->L1 messages that were submitted by the L1Messenger contract.
5652
pub fn extract_long_l2_to_l1_messages(events: &[Self]) -> Vec<Vec<u8>> {
@@ -60,7 +56,7 @@ impl VmEvent {
6056
// Filter events from the l1 messenger contract that match the expected signature.
6157
event.address == L1_MESSENGER_ADDRESS
6258
&& event.indexed_topics.len() == 3
63-
&& event.indexed_topics[0] == L1_MESSAGE_EVENT_SIGNATURE
59+
&& event.indexed_topics[0] == Self::L1_MESSAGE_EVENT_SIGNATURE
6460
})
6561
.map(|event| {
6662
let decoded_tokens = ethabi::decode(&[ethabi::ParamType::Bytes], &event.value)
@@ -174,11 +170,7 @@ impl VmExecutionResultAndLogs {
174170
Self::mock(ExecutionResult::Success { output: vec![] })
175171
}
176172

177-
pub fn get_execution_metrics(&self, tx: Option<&Transaction>) -> VmExecutionMetrics {
178-
let contracts_deployed = tx
179-
.map(|tx| tx.execute.factory_deps.len() as u16)
180-
.unwrap_or(0);
181-
173+
pub fn get_execution_metrics(&self) -> VmExecutionMetrics {
182174
// We published the data as ABI-encoded `bytes`, so the total length is:
183175
// - message length in bytes, rounded up to a multiple of 32
184176
// - 32 bytes of encoded offset
@@ -190,8 +182,11 @@ impl VmExecutionResultAndLogs {
190182

191183
let published_bytecode_bytes = VmEvent::extract_published_bytecodes(&self.logs.events)
192184
.iter()
193-
.map(|bytecodehash| {
194-
bytecode_len_in_bytes(*bytecodehash) + PUBLISH_BYTECODE_OVERHEAD as usize
185+
.map(|&bytecode_hash| {
186+
let len_in_bytes = BytecodeHash::try_from(bytecode_hash)
187+
.expect("published unparseable bytecode hash")
188+
.len_in_bytes();
189+
len_in_bytes + PUBLISH_BYTECODE_OVERHEAD as usize
195190
})
196191
.sum();
197192

@@ -202,7 +197,6 @@ impl VmExecutionResultAndLogs {
202197
l2_to_l1_logs: self.logs.total_l2_to_l1_logs_count(),
203198
user_l2_to_l1_logs: self.logs.user_l2_to_l1_logs.len(),
204199
contracts_used: self.statistics.contracts_used,
205-
contracts_deployed,
206200
vm_events: self.logs.events.len(),
207201
storage_logs: self.logs.storage_logs.len(),
208202
total_log_queries: self.statistics.total_log_queries,
@@ -336,43 +330,33 @@ impl Call {
336330
}
337331

338332
/// Mid-level transaction execution output returned by a [batch executor](crate::executor::BatchExecutor).
339-
#[derive(Debug, Clone)]
340-
pub struct BatchTransactionExecutionResult<C = Vec<CompressedBytecodeInfo>> {
333+
#[derive(Debug)]
334+
pub struct BatchTransactionExecutionResult {
341335
/// VM result.
342336
pub tx_result: Box<VmExecutionResultAndLogs>,
343337
/// Compressed bytecodes used by the transaction.
344-
pub compressed_bytecodes: C,
338+
pub compression_result: Result<(), BytecodeCompressionError>,
345339
/// Call traces (if requested; otherwise, empty).
346340
pub call_traces: Vec<Call>,
347341
}
348342

349-
impl<C> BatchTransactionExecutionResult<C> {
343+
impl BatchTransactionExecutionResult {
350344
pub fn was_halted(&self) -> bool {
351345
matches!(self.tx_result.result, ExecutionResult::Halt { .. })
352346
}
353347
}
354348

355349
/// Mid-level transaction execution output returned by a [oneshot executor](crate::executor::OneshotExecutor).
356-
#[derive(Debug)]
357-
pub struct OneshotTransactionExecutionResult {
358-
/// VM result.
359-
pub tx_result: Box<VmExecutionResultAndLogs>,
360-
/// Result of compressing bytecodes used by the transaction.
361-
pub compression_result: Result<(), BytecodeCompressionError>,
362-
/// Call traces (if requested; otherwise, empty).
363-
pub call_traces: Vec<Call>,
364-
}
350+
pub type OneshotTransactionExecutionResult = BatchTransactionExecutionResult;
365351

366-
/// High-level transaction execution result used by the API server sandbox etc.
352+
/// High-level transaction execution result used by the state keeper etc.
367353
#[derive(Debug, Clone, PartialEq)]
368354
pub struct TransactionExecutionResult {
369355
pub transaction: Transaction,
370356
pub hash: H256,
371357
pub execution_info: VmExecutionMetrics,
372358
pub execution_status: TxExecutionStatus,
373359
pub refunded_gas: u64,
374-
pub operator_suggested_refund: u64,
375-
pub compressed_bytecodes: Vec<CompressedBytecodeInfo>,
376360
pub call_traces: Vec<Call>,
377361
pub revert_reason: Option<String>,
378362
}
@@ -436,7 +420,7 @@ mod tests {
436420
ethabi::ParamType::Bytes,
437421
],
438422
);
439-
assert_eq!(L1_MESSAGE_EVENT_SIGNATURE, expected_signature);
423+
assert_eq!(VmEvent::L1_MESSAGE_EVENT_SIGNATURE, expected_signature);
440424
}
441425

442426
#[test]

0 commit comments

Comments
 (0)