diff --git a/Cargo.lock b/Cargo.lock index 3049526b5ad..557f0f9679b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2873,6 +2873,7 @@ dependencies = [ "massa_versioning", "mockall", "num", + "serde", "tempfile", "thiserror", "tokio", diff --git a/massa-execution-exports/Cargo.toml b/massa-execution-exports/Cargo.toml index fc84b6e6c0d..30374f56e1a 100644 --- a/massa-execution-exports/Cargo.toml +++ b/massa-execution-exports/Cargo.toml @@ -28,6 +28,7 @@ massa_pos_exports = {workspace = true} massa_module_cache = {workspace = true} massa_versioning = {workspace = true} massa-sc-runtime = {workspace = true} +serde = {workspace = true, "features" = ["derive"]} [dev-dependencies] mockall = {workspace = true} diff --git a/massa-execution-exports/src/event_store.rs b/massa-execution-exports/src/event_store.rs index 535a04daf1c..a01de21306a 100644 --- a/massa-execution-exports/src/event_store.rs +++ b/massa-execution-exports/src/event_store.rs @@ -5,10 +5,11 @@ use massa_models::execution::EventFilter; use massa_models::output_event::SCOutputEvent; +use serde::Serialize; use std::collections::VecDeque; /// Store for events emitted by smart contracts -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, Serialize)] pub struct EventStore(pub VecDeque); impl EventStore { diff --git a/massa-execution-exports/src/types.rs b/massa-execution-exports/src/types.rs index 4c8afbb1a99..a05f38efdf7 100644 --- a/massa-execution-exports/src/types.rs +++ b/massa-execution-exports/src/types.rs @@ -19,6 +19,7 @@ use massa_models::{ }; use massa_pos_exports::ProductionStats; use massa_storage::Storage; +use serde::Serialize; use std::collections::{BTreeMap, BTreeSet}; #[cfg(feature = "execution-trace")] @@ -217,7 +218,7 @@ pub enum SlotExecutionOutput { } /// structure storing a block id + network versions (from a block header) -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] pub struct ExecutedBlockInfo { /// Block id pub block_id: BlockId, @@ -228,7 +229,7 @@ pub struct ExecutedBlockInfo { } /// structure describing the output of a single execution -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] pub struct ExecutionOutput { /// slot pub slot: Slot, diff --git a/massa-execution-exports/src/types_trace_info.rs b/massa-execution-exports/src/types_trace_info.rs index 4f93c4ca63f..9655e473513 100644 --- a/massa-execution-exports/src/types_trace_info.rs +++ b/massa-execution-exports/src/types_trace_info.rs @@ -13,7 +13,10 @@ pub use massa_sc_runtime::{ }; #[cfg(feature = "execution-trace")] -#[derive(Debug, Clone)] +use serde::Serialize; + +#[cfg(feature = "execution-trace")] +#[derive(Debug, Clone, Serialize)] /// Structure for all abi calls in a slot pub struct SlotAbiCallStack { /// Slot @@ -25,7 +28,7 @@ pub struct SlotAbiCallStack { } #[cfg(feature = "execution-trace")] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] /// structure describing a transfer pub struct Transfer { /// From @@ -46,7 +49,7 @@ pub struct Transfer { #[cfg(feature = "execution-trace")] /// A trace of an abi call + its parameters + the result -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] pub struct AbiTrace { /// Abi name pub name: String, diff --git a/massa-execution-worker/Cargo.toml b/massa-execution-worker/Cargo.toml index 31c12c4ee35..26f2a1e6faf 100644 --- a/massa-execution-worker/Cargo.toml +++ b/massa-execution-worker/Cargo.toml @@ -47,8 +47,8 @@ dump-block = [ ] db_storage_backend = [] file_storage_backend = [] - execution-info = ["execution-trace"] +slot-replayer = [] [dependencies] anyhow = { workspace = true } diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index 9ee1079fc84..6fd36473f15 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -272,6 +272,12 @@ impl ExecutionState { self.update_versioning_stats(&exec_out.block_info, &exec_out.slot); let exec_out_2 = exec_out.clone(); + #[cfg(feature = "slot-replayer")] + { + println!(">>> Execution changes"); + println!("{:#?}", serde_json::to_string_pretty(&exec_out)); + println!("<<<"); + } // apply state changes to the final ledger self.final_state .write() diff --git a/massa-execution-worker/src/slot_sequencer.rs b/massa-execution-worker/src/slot_sequencer.rs index 2908e6266b3..c2b4a4d6e1d 100644 --- a/massa-execution-worker/src/slot_sequencer.rs +++ b/massa-execution-worker/src/slot_sequencer.rs @@ -115,21 +115,24 @@ impl SlotSequencer { // This is the max between the latest CSS-final slot, the latest blockclique slot, // and the latest slot to be executed in time. let max_slot = std::cmp::max( - std::cmp::max( - *self - .latest_consensus_final_slots - .iter() - .max() - .expect("latest_consensus_final_slots is empty"), - initial_blockclique - .keys() - .max() - .copied() - .unwrap_or_else(|| Slot::new(self.config.last_start_period, 0)), - ), - self.get_time_cursor(), + *self + .latest_consensus_final_slots + .iter() + .max() + .expect("latest_consensus_final_slots is empty"), + initial_blockclique + .keys() + .max() + .copied() + .unwrap_or_else(|| Slot::new(self.config.last_start_period, 0)), ); + // slot-replayer doesn't need the "latest slot to be executed in time" + // as it replays blocks in known period of time. Moreover this may + // introduce huge performance loss. + #[cfg(not(feature = "slot-replayer"))] + let max_slot = std::cmp::max(max_slot, self.get_time_cursor()); + // Iterate from the starting slot to the `max_slot` to build the slot sequence. while slot <= max_slot { // If the slot is rearlier than (or equal to) the latest CSS-final slot in that thread => mark the slot as CSS-final @@ -209,9 +212,17 @@ impl SlotSequencer { pub fn update( &mut self, mut new_consensus_final_blocks: HashMap, + #[cfg_attr(feature = "slot-replayer", allow(unused_assignments))] mut new_blockclique: Option>, mut new_blocks_metadata: PreHashMap, ) { + // The slot-replay don't care about speculative execution. We clear + // them. + #[cfg(feature = "slot-replayer")] + { + new_blockclique = None; + } + // If the slot sequence is empty, initialize it by calling `Self::init` and quit. // This happens on the first call to `Self::update` (see the doc of `Self::update`). if self.sequence.is_empty() { @@ -589,6 +600,8 @@ impl SlotSequencer { } // Check if the next candidate slot is available for execution. + #[cfg(not(feature = "slot-replayer"))] + // slot-replayer only replay final slot { // Get the slot just after the last executed candidate slot. let next_candidate_slot = self @@ -706,6 +719,8 @@ impl SlotSequencer { // Here we know that there are no SCE-final slots to execute. // Low priority: execute the next candidate slot that is available for execution, if any. + #[cfg(not(feature = "slot-replayer"))] + // slot-replayer does not care about spectulative execution { // Get the slot just after the latest executed speculative slot. let slot = self diff --git a/massa-final-state/src/final_state.rs b/massa-final-state/src/final_state.rs index f8bb4ecae6b..97930b4f9fa 100644 --- a/massa-final-state/src/final_state.rs +++ b/massa-final-state/src/final_state.rs @@ -619,7 +619,7 @@ impl FinalState { { warn!("Wrong key/value for EXECUTED_DENUNCIATIONS PREFIX serialized_key: {:?}, serialized_value: {:?}", serialized_key, serialized_value); return Err(anyhow!( - "Wrong key/value for EXECUTED_DENUNCIATIONS PREFIX serialized_key: {:?}, serialized_value: {:?}", + "Wrong key/value for EXECUTED_DENUNCIATIONS PREFIX serialized_key: {:?}, serialized_value: {:?}", serialized_key, serialized_value )); } @@ -630,7 +630,7 @@ impl FinalState { { warn!("Wrong key/value for LEDGER PREFIX serialized_key: {:?}, serialized_value: {:?}", serialized_key, serialized_value); return Err(anyhow!( - "Wrong key/value for LEDGER PREFIX serialized_key: {:?}, serialized_value: {:?}", + "Wrong key/value for LEDGER PREFIX serialized_key: {:?}, serialized_value: {:?}", serialized_key, serialized_value )); } @@ -641,7 +641,7 @@ impl FinalState { { warn!("Wrong key/value for MIP Store"); return Err(anyhow!( - "Wrong key/value for MIP Store serialized_key: {:?}, serialized_value: {:?}", + "Wrong key/value for MIP Store serialized_key: {:?}, serialized_value: {:?}", serialized_key, serialized_value )); }