Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(api): Refactor VM-invoking API server methods to be less VM-specific #3564

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions core/lib/dal/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,6 @@ pub(crate) fn mock_execution_result(transaction: L2Tx) -> TransactionExecutionRe
execution_info: VmExecutionMetrics::default(),
execution_status: TxExecutionStatus::Success,
refunded_gas: 0,
operator_suggested_refund: 0,
compressed_bytecodes: vec![],
call_traces: vec![],
revert_reason: None,
}
Expand Down
7 changes: 4 additions & 3 deletions core/lib/dal/src/transactions_dal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,10 @@ impl TransactionsDal<'_, '_> {
value,
&paymaster,
&paymaster_input,
exec_info.gas_used as i64,
(exec_info.initial_storage_writes + exec_info.repeated_storage_writes) as i32,
exec_info.contracts_used as i32,
exec_info.vm.gas_used as i64,
(exec_info.writes.initial_storage_writes + exec_info.writes.repeated_storage_writes)
as i32,
exec_info.vm.contracts_used as i32,
received_at,
timestamp_asserter_range_start,
timestamp_asserter_range_end,
Expand Down
30 changes: 13 additions & 17 deletions core/lib/vm_executor/src/batch/factory.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt, marker::PhantomData, rc::Rc, sync::Arc, time::Duration};
use std::{fmt, marker::PhantomData, rc::Rc, sync::Arc, time::Duration};

use anyhow::Context as _;
use once_cell::sync::OnceCell;
Expand All @@ -9,9 +9,8 @@ use zksync_multivm::{
pubdata::PubdataBuilder,
storage::{ReadStorage, StoragePtr, StorageView, StorageViewStats},
utils::{DivergenceHandler, ShadowMut},
BatchTransactionExecutionResult, BytecodeCompressionError, Call, CompressedBytecodeInfo,
ExecutionResult, FinishedL1Batch, Halt, L1BatchEnv, L2BlockEnv, SystemEnv, VmFactory,
VmInterface, VmInterfaceHistoryEnabled,
BatchTransactionExecutionResult, Call, ExecutionResult, FinishedL1Batch, Halt, L1BatchEnv,
L2BlockEnv, SystemEnv, VmFactory, VmInterface, VmInterfaceHistoryEnabled,
},
is_supported_by_fast_vm,
pubdata_builders::pubdata_params_to_builder,
Expand Down Expand Up @@ -174,8 +173,6 @@ impl<S: ReadStorage + Send + 'static, Tr: BatchTracer> BatchExecutorFactory<S>
}
}

type BytecodeResult = Result<Vec<CompressedBytecodeInfo>, BytecodeCompressionError>;

#[derive(Debug)]
enum BatchVm<S: ReadStorage, Tr: BatchTracer> {
Legacy(LegacyVmInstance<S, HistoryEnabled>),
Expand Down Expand Up @@ -241,7 +238,7 @@ impl<S: ReadStorage, Tr: BatchTracer> BatchVm<S, Tr> {
&mut self,
tx: Transaction,
with_compression: bool,
) -> BatchTransactionExecutionResult<BytecodeResult> {
) -> BatchTransactionExecutionResult {
let legacy_tracer_result = Arc::new(OnceCell::default());
let legacy_tracer = if Tr::TRACE_CALLS {
vec![CallTracer::new(legacy_tracer_result.clone()).into_tracer_pointer()]
Expand Down Expand Up @@ -270,7 +267,7 @@ impl<S: ReadStorage, Tr: BatchTracer> BatchVm<S, Tr> {
}
};

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

BatchTransactionExecutionResult {
tx_result: Box::new(tx_result),
compressed_bytecodes,
compression_result: compressed_bytecodes,
call_traces,
}
}
Expand Down Expand Up @@ -466,10 +463,10 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
// and so we re-execute the transaction, but without compression.

let res = vm.inspect_transaction(tx.clone(), true);
if let Ok(compressed_bytecodes) = res.compressed_bytecodes {
if res.compression_result.is_ok() {
return Ok(BatchTransactionExecutionResult {
tx_result: res.tx_result,
compressed_bytecodes,
compression_result: Ok(()),
call_traces: res.call_traces,
});
}
Expand All @@ -480,12 +477,11 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
vm.make_snapshot();

let res = vm.inspect_transaction(tx.clone(), false);
let compressed_bytecodes = res
.compressed_bytecodes
res.compression_result
.context("compression failed when it wasn't applied")?;
Ok(BatchTransactionExecutionResult {
tx_result: res.tx_result,
compressed_bytecodes,
compression_result: Ok(()),
call_traces: res.call_traces,
})
}
Expand All @@ -498,10 +494,10 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
vm: &mut BatchVm<S, Tr>,
) -> anyhow::Result<BatchTransactionExecutionResult> {
let res = vm.inspect_transaction(tx.clone(), true);
if let Ok(compressed_bytecodes) = res.compressed_bytecodes {
if res.compression_result.is_ok() {
Ok(BatchTransactionExecutionResult {
tx_result: res.tx_result,
compressed_bytecodes,
compression_result: Ok(()),
call_traces: res.call_traces,
})
} else {
Expand All @@ -512,7 +508,7 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
};
Ok(BatchTransactionExecutionResult {
tx_result,
compressed_bytecodes: vec![],
compression_result: Ok(()),
call_traces: vec![],
})
}
Expand Down
2 changes: 1 addition & 1 deletion core/lib/vm_interface/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub trait OneshotExecutor<S: ReadStorage> {

/// VM executor capable of validating transactions.
#[async_trait]
pub trait TransactionValidator<S: ReadStorage>: OneshotExecutor<S> {
pub trait TransactionValidator<S: ReadStorage> {
/// Validates the provided transaction.
async fn validate_transaction(
&self,
Expand Down
39 changes: 14 additions & 25 deletions core/lib/vm_interface/src/types/outputs/execution_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,9 @@ use zksync_types::{
};

use crate::{
BytecodeCompressionError, CompressedBytecodeInfo, Halt, VmExecutionMetrics,
VmExecutionStatistics, VmRevertReason,
BytecodeCompressionError, Halt, VmExecutionMetrics, VmExecutionStatistics, VmRevertReason,
};

const L1_MESSAGE_EVENT_SIGNATURE: H256 = H256([
58, 54, 228, 114, 145, 244, 32, 31, 175, 19, 127, 171, 8, 29, 146, 41, 91, 206, 45, 83, 190,
44, 108, 166, 139, 168, 44, 127, 170, 156, 226, 65,
]);

pub fn bytecode_len_in_bytes(bytecodehash: H256) -> usize {
usize::from(u16::from_be_bytes([bytecodehash[2], bytecodehash[3]])) * 32
}
Expand Down Expand Up @@ -51,6 +45,11 @@ impl VmEvent {
201, 71, 34, 255, 19, 234, 207, 83, 84, 124, 71, 65, 218, 181, 34, 131, 83, 160, 89, 56,
255, 205, 213, 212, 162, 213, 51, 174, 14, 97, 130, 135,
]);
/// Long signature of the L1 messenger publication event (`L1MessageSent`).
pub const L1_MESSAGE_EVENT_SIGNATURE: H256 = H256([
58, 54, 228, 114, 145, 244, 32, 31, 175, 19, 127, 171, 8, 29, 146, 41, 91, 206, 45, 83,
190, 44, 108, 166, 139, 168, 44, 127, 170, 156, 226, 65,
]);

/// Extracts all the "long" L2->L1 messages that were submitted by the L1Messenger contract.
pub fn extract_long_l2_to_l1_messages(events: &[Self]) -> Vec<Vec<u8>> {
Expand All @@ -60,7 +59,7 @@ impl VmEvent {
// Filter events from the l1 messenger contract that match the expected signature.
event.address == L1_MESSENGER_ADDRESS
&& event.indexed_topics.len() == 3
&& event.indexed_topics[0] == L1_MESSAGE_EVENT_SIGNATURE
&& event.indexed_topics[0] == Self::L1_MESSAGE_EVENT_SIGNATURE
})
.map(|event| {
let decoded_tokens = ethabi::decode(&[ethabi::ParamType::Bytes], &event.value)
Expand Down Expand Up @@ -336,43 +335,33 @@ impl Call {
}

/// Mid-level transaction execution output returned by a [batch executor](crate::executor::BatchExecutor).
#[derive(Debug, Clone)]
pub struct BatchTransactionExecutionResult<C = Vec<CompressedBytecodeInfo>> {
#[derive(Debug)]
pub struct BatchTransactionExecutionResult {
/// VM result.
pub tx_result: Box<VmExecutionResultAndLogs>,
/// Compressed bytecodes used by the transaction.
pub compressed_bytecodes: C,
pub compression_result: Result<(), BytecodeCompressionError>,
/// Call traces (if requested; otherwise, empty).
pub call_traces: Vec<Call>,
}

impl<C> BatchTransactionExecutionResult<C> {
impl BatchTransactionExecutionResult {
pub fn was_halted(&self) -> bool {
matches!(self.tx_result.result, ExecutionResult::Halt { .. })
}
}

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

/// High-level transaction execution result used by the API server sandbox etc.
/// High-level transaction execution result used by the state keeper etc.
#[derive(Debug, Clone, PartialEq)]
pub struct TransactionExecutionResult {
pub transaction: Transaction,
pub hash: H256,
pub execution_info: VmExecutionMetrics,
pub execution_status: TxExecutionStatus,
pub refunded_gas: u64,
pub operator_suggested_refund: u64,
pub compressed_bytecodes: Vec<CompressedBytecodeInfo>,
pub call_traces: Vec<Call>,
pub revert_reason: Option<String>,
}
Expand Down Expand Up @@ -436,7 +425,7 @@ mod tests {
ethabi::ParamType::Bytes,
],
);
assert_eq!(L1_MESSAGE_EVENT_SIGNATURE, expected_signature);
assert_eq!(VmEvent::L1_MESSAGE_EVENT_SIGNATURE, expected_signature);
}

#[test]
Expand Down
76 changes: 11 additions & 65 deletions core/lib/vm_interface/src/types/outputs/statistic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,6 @@ pub struct DeduplicatedWritesMetrics {
}

impl DeduplicatedWritesMetrics {
pub fn from_tx_metrics(tx_metrics: &TransactionExecutionMetrics) -> Self {
Self {
initial_storage_writes: tx_metrics.initial_storage_writes,
repeated_storage_writes: tx_metrics.repeated_storage_writes,
total_updated_values_size: tx_metrics.total_updated_values_size,
}
}

pub fn size(&self, protocol_version: ProtocolVersionId) -> usize {
if protocol_version.is_pre_boojum() {
self.initial_storage_writes * InitialStorageWrite::SERIALIZED_SIZE
Expand All @@ -167,67 +159,40 @@ impl DeduplicatedWritesMetrics {
}
}

/// [`VmExecutionMetrics`] + some other metrics specific for executing a single transaction (e.g.,
/// gas remaining after execution and gas refunded by the bootloader).
#[derive(Debug, Clone, Copy)]
pub struct TransactionExecutionMetrics {
pub initial_storage_writes: usize,
pub repeated_storage_writes: usize,
pub gas_used: usize,
pub writes: DeduplicatedWritesMetrics,
pub vm: VmExecutionMetrics,
pub gas_remaining: u32,
pub event_topics: u16,
pub published_bytecode_bytes: usize,
pub l2_l1_long_messages: usize,
pub l2_l1_logs: usize,
pub user_l2_l1_logs: usize,
pub contracts_used: usize,
pub contracts_deployed: u16,
pub vm_events: usize,
pub storage_logs: usize,
/// Sum of storage logs, vm events, l2->l1 logs, and the number of precompile calls.
pub total_log_queries: usize,
pub cycles_used: u32,
pub computational_gas_used: u32,
pub total_updated_values_size: usize,
pub pubdata_published: u32,
pub circuit_statistic: CircuitStatistic,
pub gas_refunded: u64,
}

impl Default for TransactionExecutionMetrics {
fn default() -> Self {
Self {
initial_storage_writes: 0,
repeated_storage_writes: 0,
gas_used: 0,
writes: DeduplicatedWritesMetrics::default(),
vm: VmExecutionMetrics::default(),
gas_remaining: u32::MAX,
event_topics: 0,
published_bytecode_bytes: 0,
l2_l1_long_messages: 0,
l2_l1_logs: 0,
user_l2_l1_logs: 0,
contracts_used: 0,
contracts_deployed: 0,
vm_events: 0,
storage_logs: 0,
total_log_queries: 0,
cycles_used: 0,
computational_gas_used: 0,
total_updated_values_size: 0,
pubdata_published: 0,
circuit_statistic: Default::default(),
gas_refunded: 0,
}
}
}

/// Metrics for a (part of) VM execution.
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize)]
pub struct VmExecutionMetrics {
pub gas_used: usize,
pub published_bytecode_bytes: usize,
pub l2_l1_long_messages: usize,
pub l2_to_l1_logs: usize,
pub user_l2_to_l1_logs: usize,
pub contracts_used: usize,
pub contracts_used: usize, // FIXME: incorrectly defined?
pub contracts_deployed: u16,
pub vm_events: usize,
pub storage_logs: usize,
/// Sum of storage logs, vm events, l2->l1 logs, and the number of precompile calls.
pub total_log_queries: usize,
pub cycles_used: u32,
pub computational_gas_used: u32,
Expand All @@ -236,25 +201,6 @@ pub struct VmExecutionMetrics {
}

impl VmExecutionMetrics {
pub fn from_tx_metrics(tx_metrics: &TransactionExecutionMetrics) -> Self {
Self {
published_bytecode_bytes: tx_metrics.published_bytecode_bytes,
l2_l1_long_messages: tx_metrics.l2_l1_long_messages,
l2_to_l1_logs: tx_metrics.l2_l1_logs,
user_l2_to_l1_logs: tx_metrics.user_l2_l1_logs,
contracts_deployed: tx_metrics.contracts_deployed,
contracts_used: tx_metrics.contracts_used,
gas_used: tx_metrics.gas_used,
storage_logs: tx_metrics.storage_logs,
vm_events: tx_metrics.vm_events,
total_log_queries: tx_metrics.total_log_queries,
cycles_used: tx_metrics.cycles_used,
computational_gas_used: tx_metrics.computational_gas_used,
pubdata_published: tx_metrics.pubdata_published,
circuit_statistic: tx_metrics.circuit_statistic,
}
}

pub fn size(&self) -> usize {
self.l2_to_l1_logs * L2ToL1Log::SERIALIZED_SIZE
+ self.l2_l1_long_messages
Expand Down
Loading
Loading