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

feat(vm): Prestate tracer implementation #1306

Merged
merged 54 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
1acf89e
prestate tracer
Feb 27, 2024
746ebfe
prestate tracer with tests first iteration
Feb 29, 2024
73905d3
`Merge branch 'main' of https://github.com/Jrigada/zksync-era into fe…
Feb 29, 2024
1579b6b
zk fmt
Feb 29, 2024
7fa2b0d
zk spell
Mar 1, 2024
f65bd70
missing docs
Mar 1, 2024
915a7d7
linter
Mar 1, 2024
669b66a
remove unused imports
Mar 1, 2024
5e26988
fmt
Mar 1, 2024
d1ede97
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 1, 2024
956a750
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 1, 2024
67ac0b3
linter
Mar 1, 2024
1903948
Merge branch 'feat-jrigada-prestate-tracer-implementation' of github.…
Mar 1, 2024
0a470b8
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 1, 2024
ab094ce
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 4, 2024
227c5ce
move to before_execution
Mar 4, 2024
7ac9f0c
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 4, 2024
55b4c4b
linter
Mar 4, 2024
2bbd935
Merge branch 'feat-jrigada-prestate-tracer-implementation' of github.…
Mar 4, 2024
618accb
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 5, 2024
4c28403
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 5, 2024
dbc5430
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 5, 2024
55b6a26
fix prestate addition of accounts
Mar 6, 2024
0fc5d60
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 6, 2024
f6e9ac7
spellcheck
Mar 6, 2024
06875cb
Merge branch 'feat-jrigada-prestate-tracer-implementation' of github.…
Mar 6, 2024
6424eeb
fix intermediate variables
Mar 7, 2024
dfb22f1
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 7, 2024
555a09d
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 7, 2024
bd8cbfd
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 8, 2024
dc7e356
previous vm integration
Mar 11, 2024
3ce1fef
previous vm integration
Mar 11, 2024
3a94ecf
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 11, 2024
f4d8cdc
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 12, 2024
0d1c382
move process storage for prestate logic to avoid repetition
Mar 12, 2024
15a6574
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 12, 2024
2360e66
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 13, 2024
d96c470
storageAccess trait
Mar 13, 2024
5a176f1
remove unused imports
Mar 13, 2024
17dd2fb
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 13, 2024
5283f64
remove unnecesary set_initial_value function
Mar 14, 2024
aaa4fcc
Merge branch 'feat-jrigada-prestate-tracer-implementation' of github.…
Mar 14, 2024
2ff7c09
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 14, 2024
801f3d5
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 14, 2024
4346de0
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 15, 2024
1094d91
remove read_keys from the versions of vm that does not need them
Mar 17, 2024
39dc18c
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 17, 2024
68ecfe4
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 18, 2024
ec4c40e
remove initial_values
Mar 19, 2024
0b3033c
remove initial_values
Mar 19, 2024
f5ce49b
remove initial_values
Mar 19, 2024
d0fee57
Merge branch 'main' into feat-jrigada-prestate-tracer-implementation
Jrigada Mar 19, 2024
ce9eb75
remove dead code annotation and collect vec
Mar 19, 2024
7d8792a
remove collect vec
Mar 19, 2024
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
Next Next commit
prestate tracer
  • Loading branch information
jrigada committed Feb 27, 2024
commit 1acf89ee01f8b6e30a1d18e9b2b978b4de391957
43 changes: 43 additions & 0 deletions core/lib/multivm/src/versions/vm_latest/tests/prestate_tracer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::borrow::Borrow;

use crate::vm_latest::ToTracerPointer;
use crate::{
interface::{TxExecutionMode, VmExecutionMode, VmInterface},
vm_latest::{
constants::BLOCK_GAS_LIMIT, tests::tester::VmTesterBuilder, tracers::PrestateTracer,
HistoryEnabled,
},
};
use zksync_test_account::TxType;
use zksync_types::{Address, Execute, U256};

#[test]
fn test_prestate_tracer() {
let mut vm = VmTesterBuilder::new(HistoryEnabled)
.with_empty_in_memory_storage()
.with_random_rich_accounts(1)
.with_deployer()
.with_gas_limit(BLOCK_GAS_LIMIT)
.with_execution_mode(TxExecutionMode::VerifyExecute)
.build();

vm.deploy_test_contract();
let account = &mut vm.rich_accounts[0];

let tx1 = account.get_test_contract_transaction(
vm.test_contract.unwrap(),
false,
Default::default(),
true,
TxType::L2,
);

println!("tx: {:?}", vm.test_contract.unwrap());
vm.vm.push_transaction(tx1);

println!("account: {:?}", account);
let prestate_tracer = PrestateTracer::new();
let tracer_ptr = prestate_tracer.into_tracer_pointer();
let res = vm.vm.inspect(tracer_ptr.into(), VmExecutionMode::Batch);
assert!(1 == 0);
}
5 changes: 4 additions & 1 deletion core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
computational_gas_price, gas_spent_on_bytecodes_and_long_messages_this_opcode,
print_debug_if_needed, VmHook,
},
CircuitsTracer, RefundsTracer, ResultTracer,
CircuitsTracer, PrestateTracer, RefundsTracer, ResultTracer,
},
types::internals::ZkSyncVmState,
VmTracer,
Expand Down Expand Up @@ -67,6 +67,7 @@ pub(crate) struct DefaultExecutionTracer<S: WriteStorage, H: HistoryMode> {
// It only takes into account circuits that are generated for actual execution. It doesn't
// take into account e.g circuits produced by the initial bootloader memory commitment.
pub(crate) circuits_tracer: CircuitsTracer<S, H>,
pub(crate) prestate_tracer: PrestateTracer,

storage: StoragePtr<S>,
_phantom: PhantomData<H>,
Expand All @@ -81,6 +82,7 @@ impl<S: WriteStorage, H: HistoryMode> DefaultExecutionTracer<S, H> {
refund_tracer: Option<RefundsTracer<S>>,
pubdata_tracer: Option<PubdataTracer<S>>,
) -> Self {
println!("NEW DefaultExecutionTracer");
Self {
tx_has_been_processed: false,
execution_mode,
Expand All @@ -95,6 +97,7 @@ impl<S: WriteStorage, H: HistoryMode> DefaultExecutionTracer<S, H> {
pubdata_tracer,
ret_from_the_bootloader: None,
circuits_tracer: CircuitsTracer::new(),
prestate_tracer: PrestateTracer::new(),
storage,
_phantom: PhantomData,
}
Expand Down
2 changes: 2 additions & 0 deletions core/lib/multivm/src/versions/vm_latest/tracers/mod.rs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
pub(crate) use circuits_tracer::CircuitsTracer;
pub(crate) use default_tracers::DefaultExecutionTracer;
pub(crate) use prestate_tracer::PrestateTracer;
pub(crate) use pubdata_tracer::PubdataTracer;
pub(crate) use refunds::RefundsTracer;
pub(crate) use result_tracer::ResultTracer;

pub(crate) mod circuits_tracer;
pub(crate) mod default_tracers;
pub(crate) mod prestate_tracer;
pub(crate) mod pubdata_tracer;
pub(crate) mod refunds;
pub(crate) mod result_tracer;
Expand Down
172 changes: 172 additions & 0 deletions core/lib/multivm/src/versions/vm_latest/tracers/prestate_tracer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
use std::fmt;
use std::{collections::HashMap, marker::PhantomData};

use crate::{
interface::{
dyn_tracers::vm_1_4_1::DynTracer,
tracer::{TracerExecutionStatus, TracerExecutionStopReason},
types::inputs::L1BatchEnv,
VmExecutionMode,
},
vm_latest::{
bootloader_state::{utils::apply_pubdata_to_memory, BootloaderState},
constants::BOOTLOADER_HEAP_PAGE,
old_vm::{history_recorder::HistoryMode, memory::SimpleMemory},
tracers::{traits::VmTracer, utils::VmHook},
types::internals::{PubdataInput, ZkSyncVmState},
utils::logs::collect_events_and_l1_system_logs_after_timestamp,
StorageOracle,
},
};
use zk_evm_1_4_1::{
aux_structures::Timestamp,
tracing::{BeforeExecutionData, VmLocalStateData},
};
use zksync_state::{StoragePtr, WriteStorage};
use zksync_types::{
get_code_key, get_nonce_key, web3::signing::keccak256, AccountTreeId, Address, Bytes,
StorageKey, StorageValue, H160, H256, L2_ETH_TOKEN_ADDRESS, U256,
};
use zksync_utils::address_to_h256;

#[derive(Debug, Clone)]
pub struct Account {
balance: Option<U256>,
code: Option<U256>,
nonce: Option<U256>,
storage: Option<HashMap<H256, H256>>,
}

impl fmt::Display for Account {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "{{")?;
if let Some(balance) = self.balance {
writeln!(f, " balance: \"0x{:x}\",", balance)?;
}
if let Some(code) = &self.code {
writeln!(f, " code: \"{}\",", code)?;
}
if let Some(nonce) = self.nonce {
writeln!(f, " nonce: {},", nonce)?;
}
if let Some(storage) = &self.storage {
writeln!(f, " storage: {{")?;
for (key, value) in storage.iter() {
writeln!(f, " {}: \"{}\",", key, value)?;
}
writeln!(f, " }}")?;
}
writeln!(f, "}}")
}
}

type State = HashMap<Address, Account>;

#[derive(Debug, Clone)]
pub(crate) struct PrestateTracer {
pub pre: State,
pub post: State,
pub config: PrestateTracerConfig,
}

impl PrestateTracer {
pub(crate) fn new() -> Self {
println!("NEW");
Self {
pre: Default::default(),
post: Default::default(),
config: PrestateTracerConfig { diff_mode: false },
}
}

pub(crate) fn get_pre(&self) -> &State {
&self.pre
}
}

#[derive(Debug, Clone)]
pub struct PrestateTracerConfig {
diff_mode: bool, // If true, this tracer will return state modifications
}

impl<S, H: HistoryMode> DynTracer<S, SimpleMemory<H>> for PrestateTracer {
fn before_execution(
&mut self,
state: VmLocalStateData<'_>,
data: BeforeExecutionData,
_memory: &SimpleMemory<H>,
_storage: StoragePtr<S>,
) {
}
}

impl<S: WriteStorage, H: HistoryMode> VmTracer<S, H> for PrestateTracer {
fn initialize_tracer(&mut self, _state: &mut ZkSyncVmState<S, H>) {}

fn finish_cycle(
&mut self,
_state: &mut ZkSyncVmState<S, H>,
_bootloader_state: &mut BootloaderState,
) -> TracerExecutionStatus {
TracerExecutionStatus::Continue
}

fn after_vm_execution(
&mut self,
state: &mut ZkSyncVmState<S, H>,
_bootloader_state: &BootloaderState,
_stop_reason: crate::interface::tracer::VmExecutionStopReason,
) {
let modified_storage_keys = {
let binding = state.storage.storage.inner().storage_ptr.borrow_mut();
// Clone the keys or derive the needed information here
binding.modified_storage_keys().clone() // Assuming `clone` is possible and inexpensive
};

let read_keys = &state.storage.read_keys;
let map = read_keys.inner().clone();
let storage_keys_read = map.iter().map(|(k, _)| k.clone()).collect::<Vec<_>>();
let pre = storage_keys_read
.iter()
.map(|k| {
let nonce_key = get_nonce_key(k.account().address());
let code_key = get_code_key(k.account().address());
let nonce = state.storage.storage.read_from_storage(&nonce_key);
let address_h256 = address_to_h256(k.account().address());
let bytes = [address_h256.as_bytes(), &[0; 32]].concat();
let balance_key: H256 = keccak256(&bytes).into();
let balance_storage_key =
StorageKey::new(AccountTreeId::new(L2_ETH_TOKEN_ADDRESS), balance_key);
let balance = state
.storage
.storage
.read_from_storage(&balance_storage_key);

let code = state.storage.storage.read_from_storage(&code_key);
let storage = get_storage_if_present(k.account(), &modified_storage_keys);
(
*(k.account().address()),
Account {
balance: Some(balance),
code: Some(code),
nonce: Some(nonce),
storage: Some(storage),
},
)
})
.collect::<State>();
self.pre = pre;
}
}

fn get_storage_if_present(
account: &AccountTreeId,
modified_storage_keys: &HashMap<StorageKey, StorageValue>,
) -> HashMap<H256, H256> {
//check if there is a StorageKey struct wioth an account field that matches the account and return the key as the key and the StorageValue as the value
modified_storage_keys
.iter()
.filter(|(k, _)| k.account() == account)
.map(|(k, v)| (k.key().clone(), v.clone()))
.collect()
}