Skip to content

Commit

Permalink
feat(vm): add gateway changes to fast vm (#3236)
Browse files Browse the repository at this point in the history
## What ❔

Ports VM changes to vm_fast that are needed for gateway version. Code
changes are mostly copied from vm_latest

## Why ❔

vm_fast should support new protocol version

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted via `zkstack dev fmt` and `zkstack dev
lint`.
  • Loading branch information
perekopskiy authored Nov 12, 2024
1 parent e92b806 commit f3a2517
Show file tree
Hide file tree
Showing 35 changed files with 278 additions and 306 deletions.
16 changes: 8 additions & 8 deletions core/lib/multivm/src/glue/tracers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! Different VM versions may have distinct requirements and types for Tracers. To accommodate these differences,
//! this module defines one primary trait:
//!
//! - `MultiVMTracer<S, H>`: This trait represents a tracer that can be converted into a tracer for
//! - `MultiVmTracer<S, H>`: This trait represents a tracer that can be converted into a tracer for
//! a specific VM version.
//!
//! Specific traits for each VM version, which support Custom Tracers:
Expand All @@ -19,22 +19,22 @@
//! into a form compatible with the vm_virtual_blocks version.
//! It defines a method `vm_virtual_blocks` for obtaining a boxed tracer.
//!
//! For `MultiVMTracer` to be implemented, the Tracer must implement all N currently
//! For `MultiVmTracer` to be implemented, the Tracer must implement all N currently
//! existing sub-traits.
//!
//! ## Adding a new VM version
//!
//! To add support for one more VM version to MultiVMTracer, one needs to:
//! To add support for one more VM version to MultiVmTracer, one needs to:
//! - Create a new trait performing conversion to the specified VM tracer, e.g., `Into<VmVersion>Tracer`.
//! - Add this trait as a trait bound to the `MultiVMTracer`.
//! - Add this trait as a trait bound for `T` in `MultiVMTracer` implementation.
//! - Add this trait as a trait bound to the `MultiVmTracer`.
//! - Add this trait as a trait bound for `T` in `MultiVmTracer` implementation.
//! - Implement the trait for `T` with a bound to `VmTracer` for a specific version.
use crate::{interface::storage::WriteStorage, tracers::old::OldTracers, HistoryMode};

pub type MultiVmTracerPointer<S, H> = Box<dyn MultiVMTracer<S, H>>;
pub type MultiVmTracerPointer<S, H> = Box<dyn MultiVmTracer<S, H>>;

pub trait MultiVMTracer<S: WriteStorage, H: HistoryMode>:
pub trait MultiVmTracer<S: WriteStorage, H: HistoryMode>:
IntoLatestTracer<S, H>
+ IntoVmVirtualBlocksTracer<S, H>
+ IntoVmRefundsEnhancementTracer<S, H>
Expand Down Expand Up @@ -168,7 +168,7 @@ where
}
}

impl<S, H, T> MultiVMTracer<S, H> for T
impl<S, H, T> MultiVmTracer<S, H> for T
where
S: WriteStorage,
H: HistoryMode,
Expand Down
2 changes: 1 addition & 1 deletion core/lib/multivm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use zksync_vm_interface as interface;
pub use crate::{
glue::{
history_mode::HistoryMode,
tracers::{MultiVMTracer, MultiVmTracerPointer},
tracers::{MultiVmTracer, MultiVmTracerPointer},
},
versions::{
vm_1_3_2, vm_1_4_1, vm_1_4_2, vm_boojum_integration, vm_fast, vm_latest, vm_m5, vm_m6,
Expand Down
18 changes: 9 additions & 9 deletions core/lib/multivm/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,16 +239,16 @@ pub fn get_bootloader_encoding_space(version: VmVersion) -> u32 {
VmVersion::Vm1_4_2 => crate::vm_1_4_2::constants::BOOTLOADER_TX_ENCODING_SPACE,
VmVersion::Vm1_5_0SmallBootloaderMemory => {
crate::vm_latest::constants::get_bootloader_tx_encoding_space(
crate::vm_latest::MultiVMSubversion::SmallBootloaderMemory,
crate::vm_latest::MultiVmSubversion::SmallBootloaderMemory,
)
}
VmVersion::Vm1_5_0IncreasedBootloaderMemory => {
crate::vm_latest::constants::get_bootloader_tx_encoding_space(
crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory,
crate::vm_latest::MultiVmSubversion::IncreasedBootloaderMemory,
)
}
VmVersion::VmGateway => crate::vm_latest::constants::get_bootloader_tx_encoding_space(
crate::vm_latest::MultiVMSubversion::Gateway,
crate::vm_latest::MultiVmSubversion::Gateway,
),
}
}
Expand Down Expand Up @@ -394,16 +394,16 @@ pub fn get_used_bootloader_memory_bytes(version: VmVersion) -> usize {
VmVersion::Vm1_4_2 => crate::vm_1_4_2::constants::USED_BOOTLOADER_MEMORY_BYTES,
VmVersion::Vm1_5_0SmallBootloaderMemory => {
crate::vm_latest::constants::get_used_bootloader_memory_bytes(
crate::vm_latest::MultiVMSubversion::SmallBootloaderMemory,
crate::vm_latest::MultiVmSubversion::SmallBootloaderMemory,
)
}
VmVersion::Vm1_5_0IncreasedBootloaderMemory => {
crate::vm_latest::constants::get_used_bootloader_memory_bytes(
crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory,
crate::vm_latest::MultiVmSubversion::IncreasedBootloaderMemory,
)
}
VmVersion::VmGateway => crate::vm_latest::constants::get_used_bootloader_memory_bytes(
crate::vm_latest::MultiVMSubversion::Gateway,
crate::vm_latest::MultiVmSubversion::Gateway,
),
}
}
Expand All @@ -430,16 +430,16 @@ pub fn get_used_bootloader_memory_words(version: VmVersion) -> usize {
VmVersion::Vm1_4_2 => crate::vm_1_4_2::constants::USED_BOOTLOADER_MEMORY_WORDS,
VmVersion::Vm1_5_0SmallBootloaderMemory => {
crate::vm_latest::constants::get_used_bootloader_memory_bytes(
crate::vm_latest::MultiVMSubversion::SmallBootloaderMemory,
crate::vm_latest::MultiVmSubversion::SmallBootloaderMemory,
)
}
VmVersion::Vm1_5_0IncreasedBootloaderMemory => {
crate::vm_latest::constants::get_used_bootloader_memory_bytes(
crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory,
crate::vm_latest::MultiVmSubversion::IncreasedBootloaderMemory,
)
}
VmVersion::VmGateway => crate::vm_latest::constants::get_used_bootloader_memory_bytes(
crate::vm_latest::MultiVMSubversion::Gateway,
crate::vm_latest::MultiVmSubversion::Gateway,
),
}
}
Expand Down
36 changes: 29 additions & 7 deletions core/lib/multivm/src/versions/vm_fast/bootloader_state/state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::cmp::Ordering;

use once_cell::sync::OnceCell;
use zksync_types::{L2ChainId, U256};
use zksync_types::{L2ChainId, ProtocolVersionId, U256};

use super::{
l2_block::BootloaderL2Block,
Expand All @@ -10,8 +10,11 @@ use super::{
BootloaderStateSnapshot,
};
use crate::{
interface::{BootloaderMemory, CompressedBytecodeInfo, L2BlockEnv, TxExecutionMode},
versions::vm_fast::{pubdata::PubdataInput, transaction_data::TransactionData},
interface::{
pubdata::{PubdataBuilder, PubdataInput},
BootloaderMemory, CompressedBytecodeInfo, L2BlockEnv, TxExecutionMode,
},
versions::vm_fast::transaction_data::TransactionData,
vm_latest::{constants::TX_DESCRIPTION_OFFSET, utils::l2_blocks::assert_next_block},
};

Expand Down Expand Up @@ -42,13 +45,16 @@ pub struct BootloaderState {
free_tx_offset: usize,
/// Information about the pubdata that will be needed to supply to the L1Messenger
pubdata_information: OnceCell<PubdataInput>,
/// Protocol version.
protocol_version: ProtocolVersionId,
}

impl BootloaderState {
pub(crate) fn new(
execution_mode: TxExecutionMode,
initial_memory: BootloaderMemory,
first_l2_block: L2BlockEnv,
protocol_version: ProtocolVersionId,
) -> Self {
let l2_block = BootloaderL2Block::new(first_l2_block, 0);
Self {
Expand All @@ -59,6 +65,7 @@ impl BootloaderState {
execution_mode,
free_tx_offset: 0,
pubdata_information: Default::default(),
protocol_version,
}
}

Expand Down Expand Up @@ -139,12 +146,23 @@ impl BootloaderState {
.expect("Pubdata information is not set")
}

pub(crate) fn settlement_layer_pubdata(&self, pubdata_builder: &dyn PubdataBuilder) -> Vec<u8> {
let pubdata_information = self
.pubdata_information
.get()
.expect("Pubdata information is not set");
pubdata_builder.settlement_layer_pubdata(pubdata_information, self.protocol_version)
}

fn last_mut_l2_block(&mut self) -> &mut BootloaderL2Block {
self.l2_blocks.last_mut().unwrap()
}

/// Apply all bootloader transaction to the initial memory
pub(crate) fn bootloader_memory(&self) -> BootloaderMemory {
pub(crate) fn bootloader_memory(
&self,
pubdata_builder: &dyn PubdataBuilder,
) -> BootloaderMemory {
let mut initial_memory = self.initial_memory.clone();
let mut offset = 0;
let mut compressed_bytecodes_offset = 0;
Expand Down Expand Up @@ -172,11 +190,15 @@ impl BootloaderState {

let pubdata_information = self
.pubdata_information
.clone()
.into_inner()
.get()
.expect("Empty pubdata information");

apply_pubdata_to_memory(&mut initial_memory, pubdata_information);
apply_pubdata_to_memory(
&mut initial_memory,
pubdata_builder,
pubdata_information,
self.protocol_version,
);
initial_memory
}

Expand Down
70 changes: 50 additions & 20 deletions core/lib/multivm/src/versions/vm_fast/bootloader_state/utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use zksync_types::{ethabi, h256_to_u256, U256};
use zksync_types::{ethabi, h256_to_u256, ProtocolVersionId, U256};

use super::{l2_block::BootloaderL2Block, tx::BootloaderTx};
use crate::{
interface::{BootloaderMemory, CompressedBytecodeInfo, TxExecutionMode},
interface::{
pubdata::{PubdataBuilder, PubdataInput},
BootloaderMemory, CompressedBytecodeInfo, TxExecutionMode,
},
utils::bytecode,
versions::vm_fast::pubdata::PubdataInput,
vm_latest::constants::{
BOOTLOADER_TX_DESCRIPTION_OFFSET, BOOTLOADER_TX_DESCRIPTION_SIZE,
COMPRESSED_BYTECODES_OFFSET, OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET,
Expand Down Expand Up @@ -118,26 +120,54 @@ fn apply_l2_block_inner(
])
}

fn bootloader_memory_input(
pubdata_builder: &dyn PubdataBuilder,
input: &PubdataInput,
protocol_version: ProtocolVersionId,
) -> Vec<u8> {
let l2_da_validator_address = pubdata_builder.l2_da_validator();
let operator_input = pubdata_builder.l1_messenger_operator_input(input, protocol_version);
ethabi::encode(&[
ethabi::Token::Address(l2_da_validator_address),
ethabi::Token::Bytes(operator_input),
])
}

pub(crate) fn apply_pubdata_to_memory(
memory: &mut BootloaderMemory,
pubdata_information: PubdataInput,
pubdata_builder: &dyn PubdataBuilder,
pubdata_information: &PubdataInput,
protocol_version: ProtocolVersionId,
) {
// Skipping two slots as they will be filled by the bootloader itself:
// - One slot is for the selector of the call to the L1Messenger.
// - The other slot is for the 0x20 offset for the calldata.
let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 2;

// Need to skip first word as it represents array offset
// while bootloader expects only [len || data]
let pubdata = ethabi::encode(&[ethabi::Token::Bytes(
pubdata_information.build_pubdata(true),
)])[32..]
.to_vec();

assert!(
pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2,
"The encoded pubdata is too big"
);
let (l1_messenger_pubdata_start_slot, pubdata) = if protocol_version.is_pre_gateway() {
// Skipping two slots as they will be filled by the bootloader itself:
// - One slot is for the selector of the call to the L1Messenger.
// - The other slot is for the 0x20 offset for the calldata.
let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 2;
// Need to skip first word as it represents array offset
// while bootloader expects only [len || data]
let pubdata = ethabi::encode(&[ethabi::Token::Bytes(
pubdata_builder.l1_messenger_operator_input(pubdata_information, protocol_version),
)])[32..]
.to_vec();
assert!(
pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2,
"The encoded pubdata is too big"
);
(l1_messenger_pubdata_start_slot, pubdata)
} else {
// Skipping the first slot as it will be filled by the bootloader itself:
// It is for the selector of the call to the L1Messenger.
let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 1;
let pubdata =
bootloader_memory_input(pubdata_builder, pubdata_information, protocol_version);
assert!(
// Note that unlike the previous version, the difference is `1`, since now it also includes the offset
pubdata.len() / 32 < OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS,
"The encoded pubdata is too big"
);
(l1_messenger_pubdata_start_slot, pubdata)
};

pubdata
.chunks(32)
Expand Down
3 changes: 2 additions & 1 deletion core/lib/multivm/src/versions/vm_fast/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub use zksync_vm2::interface;

pub(crate) use self::version::FastVmVersion;
pub use self::vm::Vm;

mod bootloader_state;
Expand All @@ -10,10 +11,10 @@ mod evm_deploy_tracer;
mod glue;
mod hook;
mod initial_bootloader_memory;
mod pubdata;
mod refund;
#[cfg(test)]
mod tests;
mod transaction_data;
mod utils;
mod version;
mod vm;
Loading

0 comments on commit f3a2517

Please sign in to comment.