Skip to content

Commit

Permalink
Added export of TransationTrace to JSON file.
Browse files Browse the repository at this point in the history
  • Loading branch information
Eagle941 committed Jun 12, 2024
1 parent 65eccba commit 95b6ce7
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 118 deletions.
29 changes: 15 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 14 additions & 9 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#![allow(clippy::multiple_crate_versions)] // Due to duplicate dependencies in pathfinder

use std::path::PathBuf;
use std::process;
use std::{fs, process};

use anyhow::bail;
use clap::Parser;
Expand Down Expand Up @@ -49,20 +49,25 @@ fn main() {
}
}

/// Returns an error if the file exists already and can't be overwritten,
/// Returns an error if the file exists already and can't be overwritten.
///
/// If the file exists and it can be overwritten, it is deleted.
///
/// # Arguments
///
/// - `path`: The file to write.
/// - `overwrite`: If `true`, the file can be overwritten.
fn check_file(path: &Option<PathBuf>, overwrite: bool) -> anyhow::Result<()> {
if let Some(filename) = path {
if filename.exists() && !overwrite {
let filename = filename.as_path().display();
bail!(
"The file {0:?} exists already. To ignore it, pass the flag --overwrite.",
filename
)
if filename.exists() {
if !overwrite {
let filename = filename.as_path().display();
bail!(
"The file {0:?} exists already. To ignore it, pass the flag --overwrite.",
filename
)
}
fs::remove_file(filename)?;
}
}
Ok(())
Expand Down Expand Up @@ -104,7 +109,7 @@ fn run(args: Args) -> anyhow::Result<()> {
tracing::info!(%start_block, %end_block, "Re-executing blocks");
let start_time = std::time::Instant::now();

let visited_pcs = run_replay(&replay_range, &storage.clone())?;
let visited_pcs = run_replay(&replay_range, &trace_out, &storage.clone())?;

let libfunc_stats = extract_libfuncs_weight(&visited_pcs, &storage)?;

Expand Down
8 changes: 4 additions & 4 deletions starknet-replay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ cairo-lang-sierra-generator = "2.6.0"
# `starkware-libs/blockifier`. These changes are in the branch `extract_libfunc`
# of Reilabs fork and need to be merged in main branch.
# Hardcoding the commit hash for the time being.
pathfinder-common = { git = "https:/reilabs/pathfinder.git", rev = "f802acfdc4e5842fc5f49f8e7ad60ed1379f8bf4" }
pathfinder-executor = { git = "https:/reilabs/pathfinder.git", rev = "f802acfdc4e5842fc5f49f8e7ad60ed1379f8bf4" }
pathfinder-rpc = { git = "https:/reilabs/pathfinder.git", rev = "f802acfdc4e5842fc5f49f8e7ad60ed1379f8bf4" }
pathfinder-storage = { git = "https:/reilabs/pathfinder.git", rev = "f802acfdc4e5842fc5f49f8e7ad60ed1379f8bf4" }
pathfinder-common = { git = "https:/reilabs/pathfinder.git", rev = "fdeb5b0d1747d6396e5b0774140026a3b1beae2f" }
pathfinder-executor = { git = "https:/reilabs/pathfinder.git", rev = "fdeb5b0d1747d6396e5b0774140026a3b1beae2f" }
pathfinder-rpc = { git = "https:/reilabs/pathfinder.git", rev = "fdeb5b0d1747d6396e5b0774140026a3b1beae2f" }
pathfinder-storage = { git = "https:/reilabs/pathfinder.git", rev = "fdeb5b0d1747d6396e5b0774140026a3b1beae2f" }
# `plotters` is using the latest (as of 30-May-2024) commit on the branch
# `next-release-devel` because it contains the fix for bug #551 related to
# anchoring of labels when rotated. Issue #26.
Expand Down
6 changes: 5 additions & 1 deletion starknet-replay/src/block_number/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

use std::fmt;

use serde::{Deserialize, Serialize};

pub mod pathfinder;

/// `BlockNumber` is represented as a `u64` integer.
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(
Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct BlockNumber(u64);
impl BlockNumber {
/// Creates a new `BlockNumber`.
Expand Down
105 changes: 79 additions & 26 deletions starknet-replay/src/runner/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
//! The module runner contains the code to replay transactions and extract the
//! sequence of visited program counters from each transaction replayed.

use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::mpsc::channel;

use rayon::iter::{ParallelBridge, ParallelIterator};
use pathfinder_executor::types::{TransactionSimulation, TransactionTrace};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use starknet_api::core::ClassHash as StarknetClassHash;

use self::replay_class_hash::ReplayClassHash;
use self::report::write_to_file;
use crate::block_number::BlockNumber;
use crate::runner::replay_class_hash::VisitedPcs;
use crate::runner::replay_range::ReplayRange;
Expand All @@ -15,6 +20,7 @@ use crate::{ReplayBlock, RunnerError};
pub mod replay_block;
pub mod replay_class_hash;
pub mod replay_range;
pub mod report;

/// Replays transactions as indicated by `replay_range` and extracts the list of
/// visited program counters.
Expand All @@ -31,7 +37,11 @@ pub mod replay_range;
/// - The most recent block available in the database is less than the block to
/// start the replay.
/// - There is any error during transaction replay.
pub fn run_replay<T>(replay_range: &ReplayRange, storage: &T) -> Result<VisitedPcs, RunnerError>
pub fn run_replay<T>(
replay_range: &ReplayRange,
trace_out: &Option<PathBuf>,
storage: &T,
) -> Result<VisitedPcs, RunnerError>
where
T: Storage + Sync + Send,
{
Expand All @@ -40,7 +50,7 @@ where

// Iterate through each block in `replay_work` and replay all the
// transactions
replay_blocks(storage, &replay_work)
replay_blocks(storage, trace_out, &replay_work)
}

/// Generates the list of transactions to be replayed.
Expand Down Expand Up @@ -103,6 +113,50 @@ where
Ok(replay_blocks)
}

/// Returns the hashmap of visited program counters for the input `trace`.
///
/// The result of `get_visited_program_counters` is a hashmap where the key
/// is the [`StarknetClassHash`] and the value is the Vector of visited
/// program counters for each [`StarknetClassHash`] execution in `trace`.
///
/// If `trace` is not an Invoke transaction, the function returns None
/// because no libfuncs have been called during the transaction
/// execution.
///
/// # Arguments
///
/// - `trace`: the [`pathfinder_executor::types::TransactionTrace`] to extract
/// the visited program counters from.
fn get_visited_program_counters(
trace: TransactionTrace,
) -> Option<HashMap<StarknetClassHash, Vec<Vec<usize>>>> {
match trace {
TransactionTrace::Invoke(tx) => Some(tx.visited_pcs),
_ => None,
}
}

pub fn process_transaction_traces(
transaction_simulations: Vec<TransactionSimulation>,
block_number: BlockNumber,
) -> VisitedPcs {
let mut cumulative_visited_pcs = VisitedPcs::default();
for simulation in transaction_simulations {
let Some(visited_pcs) = get_visited_program_counters(simulation.trace) else {
continue;
};

cumulative_visited_pcs.extend(visited_pcs.into_iter().map(|(class_hash, pcs)| {
let replay_class_hash = ReplayClassHash {
block_number,
class_hash,
};
(replay_class_hash, pcs)
}));
}
cumulative_visited_pcs
}

/// Re-executes the list of transactions in `replay_work` and return the
/// statistics on libfunc usage.
///
Expand All @@ -117,19 +171,32 @@ where
///
/// Returns [`Err`] if the function `execute_block` fails to replay any
/// transaction.
pub fn replay_blocks<T>(storage: &T, replay_work: &[ReplayBlock]) -> Result<VisitedPcs, RunnerError>
pub fn replay_blocks<T>(
storage: &T,
trace_out: &Option<PathBuf>,
replay_work: &[ReplayBlock],
) -> Result<VisitedPcs, RunnerError>
where
T: Storage + Sync + Send,
{
let (sender, receiver) = channel();
replay_work
.iter()
.par_bridge()
.par_iter()
.try_for_each_with(
(storage, sender),
|(storage, sender), block| -> anyhow::Result<()> {
let block_visited_pcs = storage.execute_block(block)?;
sender.send(block_visited_pcs)?;
(storage, trace_out, sender),
|(storage, trace_out, sender), block| -> anyhow::Result<()> {
let block_transaction_traces = storage.execute_block(block)?;
let block_number = block.header.number;
tracing::info!("Simulation completed block {block_number}");
if let Some(filename) = trace_out {
write_to_file(&filename, &block_transaction_traces).unwrap();
}
tracing::info!("Saved transaction trace block {block_number}");
let visited_pcs = process_transaction_traces(
block_transaction_traces,
block.header.number.into(),
);
sender.send(visited_pcs)?;
Ok(())
},
)
Expand All @@ -138,22 +205,8 @@ where
let res: Vec<_> = receiver.iter().collect();

let mut cumulative_visited_pcs = VisitedPcs::default();

for simulations in res {
for trace in &simulations {
let Some(visited_pcs) = trace.get_visited_program_counters() else {
continue;
};

cumulative_visited_pcs.extend(visited_pcs.iter().map(|(k, v)| {
let replay_class_hash = ReplayClassHash {
block_number: trace.block_number,
class_hash: *k,
};
let pcs = v.clone();
(replay_class_hash, pcs)
}));
}
for visited_pcs in res {
cumulative_visited_pcs.extend(visited_pcs.into_iter());
}

Ok(cumulative_visited_pcs)
Expand Down
Loading

0 comments on commit 95b6ce7

Please sign in to comment.