From a1a2190c8a022ba409f15fa640fa0b2379cf6e13 Mon Sep 17 00:00:00 2001 From: Sydhds Date: Mon, 13 May 2024 14:18:59 +0200 Subject: [PATCH] Initial code for dump-block feature (#4684) * Initial code for dump-block feature * Cargo fmt pass * Display current folder * Display current folder 2 * Add denunciations to grpc block header * Cargo fmt pass * Cargo clippy pass * Try to update setup-protoc github actions * Try to update setup-protoc github actions 2 * Update serde * Update massa-sc-runtime && massa-proto-rs commit id --- .github/workflows/ci.yml | 6 +- Cargo.lock | 13 ++- Cargo.toml | 4 +- massa-api/Cargo.toml | 2 + massa-api/src/tests/public.rs | 8 ++ massa-execution-exports/Cargo.toml | 1 + massa-execution-exports/src/settings.rs | 2 + .../src/test_exports/config.rs | 11 +- massa-execution-exports/src/types.rs | 3 + massa-execution-worker/Cargo.toml | 5 + massa-execution-worker/src/context.rs | 2 + massa-execution-worker/src/execution.rs | 78 +++++++++++-- .../src/tests/scenarios_mandatories.rs | 105 ++++++++++++++++++ .../src/tests/tests_active_history.rs | 2 + massa-grpc/Cargo.toml | 1 + massa-grpc/src/tests/public.rs | 4 + massa-grpc/src/tests/stream.rs | 4 + massa-models/src/denunciation.rs | 43 +++++++ massa-models/src/mapping_grpc.rs | 35 +++++- massa-node/Cargo.toml | 1 + massa-node/base_config/config.toml | 7 +- massa-node/src/main.rs | 9 ++ massa-node/src/settings.rs | 7 ++ 23 files changed, 333 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7aa746061ed..7b1a625cff0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,9 +197,11 @@ jobs: with: shared-key: "massa" save-if: ${{ github.ref_name == 'main' }} - - uses: arduino/setup-protoc@v1 + - uses: arduino/setup-protoc@v3 with: - version: '3.x' + # version: '3.x' + version: "23.x" + include-pre-releases: false repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: diff --git a/Cargo.lock b/Cargo.lock index 35955c0f2b7..41fd5537ac8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,9 +156,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "arrayref" @@ -2566,7 +2566,7 @@ dependencies = [ [[package]] name = "massa-proto-rs" version = "0.1.0" -source = "git+https://github.com/massalabs/massa-proto-rs?rev=426fd325a55dfcc4033920bed2de075a7e7ad4b7#426fd325a55dfcc4033920bed2de075a7e7ad4b7" +source = "git+https://github.com/massalabs/massa-proto-rs?rev=38950875a7aa406fedc4f0b8336864e5ff290f2c#38950875a7aa406fedc4f0b8336864e5ff290f2c" dependencies = [ "glob", "prost", @@ -2579,7 +2579,7 @@ dependencies = [ [[package]] name = "massa-sc-runtime" version = "0.10.0" -source = "git+https://github.com/massalabs/massa-sc-runtime?rev=e95066a6d3a963ff0125616f404a84e5abb63d63#e95066a6d3a963ff0125616f404a84e5abb63d63" +source = "git+https://github.com/massalabs/massa-sc-runtime?rev=80352eb9f2a6b90a441cd64433d8874c33fb384f#80352eb9f2a6b90a441cd64433d8874c33fb384f" dependencies = [ "anyhow", "as-ffi-bindings", @@ -2913,6 +2913,7 @@ dependencies = [ "mockall", "num", "parking_lot", + "prost", "rand", "rand_xoshiro", "schnellru", @@ -4915,9 +4916,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" dependencies = [ "itoa", "ryu", diff --git a/Cargo.toml b/Cargo.toml index 79222cfb105..b20214e050e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,8 +106,8 @@ massa_versioning = { path = "./massa-versioning" } massa_wallet = { path = "./massa-wallet" } # Massa projects dependencies -massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "426fd325a55dfcc4033920bed2de075a7e7ad4b7" } -massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "e95066a6d3a963ff0125616f404a84e5abb63d63" } +massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "38950875a7aa406fedc4f0b8336864e5ff290f2c" } +massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "80352eb9f2a6b90a441cd64433d8874c33fb384f" } peernet = { git = "https://github.com/massalabs/PeerNet", "rev" = "04b05ddd320fbe76cc858115af7b5fc28bdb8310" } # Common dependencies diff --git a/massa-api/Cargo.toml b/massa-api/Cargo.toml index 469681e5ab8..0053c572ead 100644 --- a/massa-api/Cargo.toml +++ b/massa-api/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [features] test-exports = ["dep:massa_channel", "dep:massa_grpc", "massa_grpc/test-exports"] execution-trace = ["massa_execution_exports/execution-trace"] +dump-block = ["massa_execution_exports/dump-block"] + [dependencies] massa_api_exports = { workspace = true } diff --git a/massa-api/src/tests/public.rs b/massa-api/src/tests/public.rs index dcb51a904b9..035bcd22822 100644 --- a/massa-api/src/tests/public.rs +++ b/massa-api/src/tests/public.rs @@ -694,6 +694,10 @@ async fn execute_read_only_bytecode() { block_info: None, state_changes: massa_final_state::StateChanges::default(), events: massa_execution_exports::EventStore::default(), + #[cfg(feature = "execution-trace")] + slot_trace: None, + #[cfg(feature = "dump-block")] + storage: None, }, gas_cost: 100, call_result: "toto".as_bytes().to_vec(), @@ -774,6 +778,10 @@ async fn execute_read_only_call() { block_info: None, state_changes: massa_final_state::StateChanges::default(), events: massa_execution_exports::EventStore::default(), + #[cfg(feature = "execution-trace")] + slot_trace: None, + #[cfg(feature = "dump-block")] + storage: None, }, gas_cost: 100, call_result: "toto".as_bytes().to_vec(), diff --git a/massa-execution-exports/Cargo.toml b/massa-execution-exports/Cargo.toml index cb6304fe1e1..760745c5b12 100644 --- a/massa-execution-exports/Cargo.toml +++ b/massa-execution-exports/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" gas_calibration = ["tempfile"] test-exports = ["massa_models/test-exports", "tempfile", "mockall"] execution-trace = ["massa-sc-runtime/execution-trace"] +dump-block = [] [dependencies] displaydoc = {workspace = true} diff --git a/massa-execution-exports/src/settings.rs b/massa-execution-exports/src/settings.rs index 2b47694e0dc..49ae83b4559 100644 --- a/massa-execution-exports/src/settings.rs +++ b/massa-execution-exports/src/settings.rs @@ -100,4 +100,6 @@ pub struct ExecutionConfig { pub broadcast_slot_execution_traces_channel_capacity: usize, /// Max execution traces slot to keep in trace history cache pub max_execution_traces_slot_limit: usize, + /// Where to dump blocks + pub block_dump_folder_path: PathBuf, } diff --git a/massa-execution-exports/src/test_exports/config.rs b/massa-execution-exports/src/test_exports/config.rs index d5a8183c760..f42f9bd53d2 100644 --- a/massa-execution-exports/src/test_exports/config.rs +++ b/massa-execution-exports/src/test_exports/config.rs @@ -19,6 +19,14 @@ impl Default for ExecutionConfig { .expect("Overflow when creating constant ledger_entry_datastore_base_size"), }; + // Create a tmp dir then only storing the path will drop the original tmp dir object + // thus deleting the folders + // So we need to create it manually (not really safe but ok for unit testing) + let hd_cache_path = TempDir::new().unwrap().path().to_path_buf(); + std::fs::create_dir_all(hd_cache_path.clone()).unwrap(); + let block_dump_folder_path = TempDir::new().unwrap().path().to_path_buf(); + std::fs::create_dir_all(block_dump_folder_path.clone()).unwrap(); + Self { readonly_queue_length: 100, max_final_events: 1000, @@ -57,7 +65,7 @@ impl Default for ExecutionConfig { .unwrap(), base_operation_gas_cost: BASE_OPERATION_GAS_COST, last_start_period: 0, - hd_cache_path: TempDir::new().unwrap().path().to_path_buf(), + hd_cache_path, lru_cache_size: 1000, hd_cache_size: 10_000, snip_amount: 10, @@ -72,6 +80,7 @@ impl Default for ExecutionConfig { broadcast_traces_enabled: true, broadcast_slot_execution_traces_channel_capacity: 5000, max_execution_traces_slot_limit: 320, + block_dump_folder_path, } } } diff --git a/massa-execution-exports/src/types.rs b/massa-execution-exports/src/types.rs index f61781c282f..270ec83e021 100644 --- a/massa-execution-exports/src/types.rs +++ b/massa-execution-exports/src/types.rs @@ -361,6 +361,9 @@ pub struct ExecutionOutput { /// slot trace #[cfg(feature = "execution-trace")] pub slot_trace: Option<(SlotAbiCallStack, Vec)>, + /// storage + #[cfg(feature = "dump-block")] + pub storage: Option, } #[cfg(feature = "execution-trace")] diff --git a/massa-execution-worker/Cargo.toml b/massa-execution-worker/Cargo.toml index 60e5de5c9fd..2d4f0b6f972 100644 --- a/massa-execution-worker/Cargo.toml +++ b/massa-execution-worker/Cargo.toml @@ -43,6 +43,10 @@ execution-trace = [ "schnellru", "massa_execution_exports/execution-trace", ] +dump-block = [ + "prost", + "massa_execution_exports/dump-block", +] [dependencies] anyhow = { workspace = true } @@ -83,6 +87,7 @@ tempfile = { workspace = true, optional = true } massa_wallet = { workspace = true } massa-proto-rs = { workspace = true } schnellru = { workspace = true, optional = true } +prost = { version = "=0.12", optional = true } [dev-dependencies] massa_storage = { workspace = true } diff --git a/massa-execution-worker/src/context.rs b/massa-execution-worker/src/context.rs index 46292ecd933..ebca7761ddc 100644 --- a/massa-execution-worker/src/context.rs +++ b/massa-execution-worker/src/context.rs @@ -913,6 +913,8 @@ impl ExecutionContext { events: std::mem::take(&mut self.events), #[cfg(feature = "execution-trace")] slot_trace: None, + #[cfg(feature = "dump-block")] + storage: None, } } diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index 585ec12046f..db04668f1c7 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -53,10 +53,22 @@ use tracing::{debug, info, trace, warn}; use crate::trace_history::TraceHistory; #[cfg(feature = "execution-trace")] use massa_execution_exports::{AbiTrace, SlotAbiCallStack, Transfer}; +#[cfg(feature = "dump-block")] +use massa_models::block::FilledBlock; #[cfg(feature = "execution-trace")] use massa_models::config::{BASE_OPERATION_GAS_COST, MAX_GAS_PER_BLOCK, MAX_OPERATIONS_PER_BLOCK}; +#[cfg(feature = "dump-block")] +use massa_models::operation::Operation; #[cfg(feature = "execution-trace")] use massa_models::prehash::PreHashMap; +#[cfg(feature = "dump-block")] +use massa_models::secure_share::SecureShare; +#[cfg(feature = "dump-block")] +use massa_proto_rs::massa::model::v1 as grpc_model; +#[cfg(feature = "dump-block")] +use prost::Message; +#[cfg(feature = "dump-block")] +use std::io::Write; /// Used to acquire a lock on the execution context macro_rules! context_guard { @@ -325,6 +337,53 @@ impl ExecutionState { } } } + + #[cfg(feature = "dump-block")] + { + let block_folder = &self.config.block_dump_folder_path; + let block_file_path = block_folder.join(format!( + "block_slot_{}_{}.bin", + exec_out.slot.thread, exec_out.slot.period + )); + + let mut fs = std::fs::File::create(block_file_path.clone()) + .unwrap_or_else(|_| panic!("Cannot create file: {:?}", block_file_path)); + + let mut block_ser = vec![]; + if let Some(block_info) = exec_out.block_info { + let block_id = block_info.block_id; + let storage = exec_out.storage.unwrap(); + let guard = storage.read_blocks(); + let secured_block = guard + .get(&block_id) + .unwrap_or_else(|| panic!("Unable to get block for block id: {}", block_id)); + + let operations: Vec<(OperationId, Option>)> = + secured_block + .content + .operations + .iter() + .map(|operation_id| { + match storage.read_operations().get(operation_id).cloned() { + Some(verifiable_operation) => { + (*operation_id, Some(verifiable_operation)) + } + None => (*operation_id, None), + } + }) + .collect(); + + let filled_block = FilledBlock { + header: secured_block.content.header.clone(), + operations, + }; + + let grpc_filled_block = grpc_model::FilledBlock::from(filled_block); + grpc_filled_block.encode(&mut block_ser).unwrap(); + } + fs.write_all(&block_ser[..]) + .expect("Unable to write block to disk"); + } } /// Applies an execution output to the active (non-final) state @@ -1419,16 +1478,21 @@ impl ExecutionState { self.trace_history .write() .save_transfers_for_slot(*slot, transfers.clone()); - // Finish slot - #[cfg(not(feature = "execution-trace"))] - let exec_out = context_guard!(self).settle_slot(block_info); + // Finish slot + #[allow(unused_mut)] + let mut exec_out = context_guard!(self).settle_slot(block_info); #[cfg(feature = "execution-trace")] - let exec_out = { - let mut out = context_guard!(self).settle_slot(block_info); - out.slot_trace = Some((slot_trace, transfers)); - out + { + exec_out.slot_trace = Some((slot_trace, transfers)); }; + #[cfg(feature = "dump-block")] + { + exec_out.storage = match exec_target { + Some((_block_id, block_metadata)) => block_metadata.storage.clone(), + _ => None, + } + } // Broadcast a slot execution output to active channel subscribers. if self.config.broadcast_enabled { diff --git a/massa-execution-worker/src/tests/scenarios_mandatories.rs b/massa-execution-worker/src/tests/scenarios_mandatories.rs index eb5a45e0bc9..ccac3173a4b 100644 --- a/massa-execution-worker/src/tests/scenarios_mandatories.rs +++ b/massa-execution-worker/src/tests/scenarios_mandatories.rs @@ -46,6 +46,13 @@ use massa_models::operation::OperationId; #[cfg(feature = "execution-trace")] use std::thread; +#[cfg(feature = "dump-block")] +use massa_proto_rs::massa::model::v1::FilledBlock; +#[cfg(feature = "dump-block")] +use prost::Message; +#[cfg(feature = "dump-block")] +use std::io::Cursor; + const TEST_SK_1: &str = "S18r2i8oJJyhF7Kprx98zwxAc3W4szf7RKuVMX6JydZz8zSxHeC"; const TEST_SK_2: &str = "S1FpYC4ugG9ivZZbLVrTwWtF9diSRiAwwrVX5Gx1ANSRLfouUjq"; const TEST_SK_3: &str = "S1LgXhWLEgAgCX3nm6y8PVPzpybmsYpi6yg6ZySwu5Z4ERnD7Bu"; @@ -2839,3 +2846,101 @@ fn execution_trace_nested() { ] ); } + +#[cfg(feature = "dump-block")] +#[test] +fn test_dump_block() { + // setup the period duration + let exec_cfg = ExecutionConfig::default(); + let mut foreign_controllers = ExecutionForeignControllers::new_with_mocks(); + let finalized_waitpoint = WaitPoint::new(); + let finalized_waitpoint_trigger_handle = finalized_waitpoint.get_trigger_handle(); + let recipient_address = + Address::from_public_key(&KeyPair::generate(0).unwrap().get_public_key()); + selector_boilerplate(&mut foreign_controllers.selector_controller); + final_state_boilerplate( + &mut foreign_controllers.final_state, + foreign_controllers.db.clone(), + &foreign_controllers.selector_controller, + &mut foreign_controllers.ledger_controller, + None, + None, + None, + ); + foreign_controllers + .final_state + .write() + .expect_finalize() + .times(1) + .with(predicate::eq(Slot::new(1, 0)), predicate::always()) + .returning(move |_, changes| { + // 190 because 100 in the get_balance in the `final_state_boilerplate` and 90 from the transfer. + assert_eq!( + changes + .ledger_changes + .get_balance_or_else(&recipient_address, || None), + Some(Amount::from_str("190").unwrap()) + ); + // 1.02 for the block rewards + assert_eq!( + changes.ledger_changes.get_balance_or_else( + &Address::from_public_key( + &KeyPair::from_str(TEST_SK_1).unwrap().get_public_key() + ), + || None + ), + Some( + exec_cfg + .block_reward + .saturating_add(Amount::from_str("10").unwrap()) // add 10 fee + ) + ); + finalized_waitpoint_trigger_handle.trigger(); + }); + let mut universe = ExecutionTestUniverse::new(foreign_controllers, exec_cfg.clone()); + // create the operation + let operation = Operation::new_verifiable( + Operation { + fee: Amount::from_str("10").unwrap(), + expire_period: 10, + op: OperationType::Transaction { + recipient_address, + amount: Amount::from_str("90").unwrap(), + }, + }, + OperationSerializer::new(), + &KeyPair::from_str(TEST_SK_1).unwrap(), + *CHAINID, + ) + .unwrap(); + // create the block containing the transaction operation + universe.storage.store_operations(vec![operation.clone()]); + let block_slot = Slot::new(1, 0); + let block = ExecutionTestUniverse::create_block( + &KeyPair::from_str(TEST_SK_1).unwrap(), + block_slot.clone(), + vec![operation], + vec![], + vec![], + ); + // store the block in storage + universe.send_and_finalize(&KeyPair::from_str(TEST_SK_1).unwrap(), block); + finalized_waitpoint.wait(); + + std::thread::sleep(Duration::from_secs(1)); + + let block_folder = &exec_cfg.block_dump_folder_path; + let block_file_path = block_folder.join(format!( + "block_slot_{}_{}.bin", + block_slot.thread, block_slot.period + )); + + let block_content = std::fs::read(block_file_path).expect("Unable to read block dump"); + let filled_block = FilledBlock::decode(&mut Cursor::new(block_content)).unwrap(); + let header_content = filled_block.header.unwrap().content.unwrap(); + let header_slot = header_content.slot.unwrap(); + assert_eq!(header_slot.thread, u32::from(block_slot.thread)); + assert_eq!(header_slot.period, block_slot.period); + assert_eq!(header_content.endorsements.len(), 0); + assert_eq!(filled_block.operations.len(), 1); +} diff --git a/massa-execution-worker/src/tests/tests_active_history.rs b/massa-execution-worker/src/tests/tests_active_history.rs index 7e4d9c926e1..5088584d687 100644 --- a/massa-execution-worker/src/tests/tests_active_history.rs +++ b/massa-execution-worker/src/tests/tests_active_history.rs @@ -56,6 +56,8 @@ fn test_active_history_deferred_credits() { events: Default::default(), #[cfg(feature = "execution-trace")] slot_trace: Default::default(), + #[cfg(feature = "dump-block")] + storage: None, }; let active_history = ActiveHistory(VecDeque::from([exec_output_1])); diff --git a/massa-grpc/Cargo.toml b/massa-grpc/Cargo.toml index 07d0cc759de..201c80ed1f5 100644 --- a/massa-grpc/Cargo.toml +++ b/massa-grpc/Cargo.toml @@ -9,6 +9,7 @@ documentation = "https://docs.massa.net/" [features] execution-trace = ["serde_json"] +dump-block = [] test-exports = [] [dependencies] diff --git a/massa-grpc/src/tests/public.rs b/massa-grpc/src/tests/public.rs index 58f9dc78c74..abbf5b37765 100644 --- a/massa-grpc/src/tests/public.rs +++ b/massa-grpc/src/tests/public.rs @@ -355,6 +355,10 @@ async fn execute_read_only_call() { block_info: None, state_changes: massa_final_state::StateChanges::default(), events: EventStore::default(), + #[cfg(feature = "execution-trace")] + slot_trace: None, + #[cfg(feature = "dump-block")] + storage: None, }, gas_cost: 100, call_result: "toto".as_bytes().to_vec(), diff --git a/massa-grpc/src/tests/stream.rs b/massa-grpc/src/tests/stream.rs index 2bba9d10ac8..ae535a61637 100644 --- a/massa-grpc/src/tests/stream.rs +++ b/massa-grpc/src/tests/stream.rs @@ -1068,6 +1068,10 @@ async fn new_slot_execution_outputs() { block_info: None, state_changes: massa_final_state::StateChanges::default(), events: Default::default(), + #[cfg(feature = "execution-trace")] + slot_trace: None, + #[cfg(feature = "dump-block")] + storage: None, }; let (tx_request, rx) = tokio::sync::mpsc::channel(10); diff --git a/massa-models/src/denunciation.rs b/massa-models/src/denunciation.rs index 57da1e70339..21daf69a0ed 100644 --- a/massa-models/src/denunciation.rs +++ b/massa-models/src/denunciation.rs @@ -89,6 +89,29 @@ impl EndorsementDenunciation { hash_data.extend(content_hash.to_bytes()); Hash::compute_from(&hash_data) } + + // Getters (for GRPC From) + pub fn get_public_key(&self) -> &PublicKey { + &self.public_key + } + pub fn get_slot(&self) -> &Slot { + &self.slot + } + pub fn get_index(&self) -> &u32 { + &self.index + } + pub fn get_hash_1(&self) -> &Hash { + &self.hash_1 + } + pub fn get_hash_2(&self) -> &Hash { + &self.hash_2 + } + pub fn get_signature_1(&self) -> &Signature { + &self.signature_1 + } + pub fn get_signature_2(&self) -> &Signature { + &self.signature_2 + } } /// A Variant of Denunciation enum for block header @@ -120,6 +143,26 @@ impl BlockHeaderDenunciation { hash_data.extend(content_hash.to_bytes()); Hash::compute_from(&hash_data) } + + // Getters (for GRPC From) + pub fn get_public_key(&self) -> &PublicKey { + &self.public_key + } + pub fn get_slot(&self) -> &Slot { + &self.slot + } + pub fn get_hash_1(&self) -> &Hash { + &self.hash_1 + } + pub fn get_hash_2(&self) -> &Hash { + &self.hash_2 + } + pub fn get_signature_1(&self) -> &Signature { + &self.signature_1 + } + pub fn get_signature_2(&self) -> &Signature { + &self.signature_2 + } } /// A denunciation enum diff --git a/massa-models/src/mapping_grpc.rs b/massa-models/src/mapping_grpc.rs index aed3ef93dca..3c611304181 100644 --- a/massa-models/src/mapping_grpc.rs +++ b/massa-models/src/mapping_grpc.rs @@ -4,7 +4,7 @@ use crate::amount::Amount; use crate::block::{Block, BlockGraphStatus, FilledBlock, SecureShareBlock}; use crate::block_header::{BlockHeader, SecuredHeader}; use crate::config::CompactConfig; -use crate::denunciation::DenunciationIndex; +use crate::denunciation::{Denunciation, DenunciationIndex}; use crate::endorsement::{Endorsement, SecureShareEndorsement}; use crate::error::ModelsError; use crate::operation::{Operation, OperationType, SecureShareOperation}; @@ -90,6 +90,7 @@ impl From for grpc_model::BlockHeader { .map(|parent| parent.to_string()) .collect(), endorsements: res, + denunciations: value.denunciations.into_iter().map(|d| d.into()).collect(), current_version: value.current_version, announced_version: value.announced_version, //TODO to be updated in Massa models @@ -402,3 +403,35 @@ impl From for grpc_model::NetworkStats { } } } + +impl From for grpc_model::Denunciation { + fn from(value: Denunciation) -> Self { + match value { + Denunciation::Endorsement(de) => grpc_model::Denunciation { + entry: Some(grpc_model::denunciation::Entry::Endorsement( + grpc_model::EndorsementDenunciation { + public_key: de.get_public_key().to_string(), + slot: Some((*de.get_slot()).into()), + index: *de.get_index(), + hash_1: de.get_hash_1().to_string(), + hash_2: de.get_hash_2().to_string(), + signature_1: de.get_signature_1().to_string(), + signature_2: de.get_signature_2().to_string(), + }, + )), + }, + Denunciation::BlockHeader(db) => grpc_model::Denunciation { + entry: Some(grpc_model::denunciation::Entry::BlockHeader( + grpc_model::BlockHeaderDenunciation { + public_key: db.get_public_key().to_string(), + slot: Some((*db.get_slot()).into()), + hash_1: db.get_hash_1().to_string(), + hash_2: db.get_hash_2().to_string(), + signature_1: db.get_signature_1().to_string(), + signature_2: db.get_signature_2().to_string(), + }, + )), + }, + } + } +} diff --git a/massa-node/Cargo.toml b/massa-node/Cargo.toml index 87a065f9ad5..c9fabd525f6 100644 --- a/massa-node/Cargo.toml +++ b/massa-node/Cargo.toml @@ -23,6 +23,7 @@ sandbox = [ "massa_metrics/sandbox", ] execution-trace = ["massa_grpc/execution-trace", "massa_api/execution-trace", "massa_execution_worker/execution-trace", "massa_execution_exports/execution-trace"] +dump-block = ["massa_execution_worker/dump-block", "massa_execution_exports/dump-block"] [dependencies] crossbeam-channel = { workspace = true } # BOM UPGRADE Revert to "0.5.6" if problem diff --git a/massa-node/base_config/config.toml b/massa-node/base_config/config.toml index a67a067edff..b371cb6a690 100644 --- a/massa-node/base_config/config.toml +++ b/massa-node/base_config/config.toml @@ -213,6 +213,7 @@ snip_amount = 10 # slot execution outputs channel capacity broadcast_slot_execution_output_channel_capacity = 5000 + # Enable execution-traces (detailed execution info like SC abi calls) with: --features execution-trace # slot execution traces channel capacity broadcast_slot_execution_traces_channel_capacity = 5000 # Max slots execution traces to keep in cache @@ -422,4 +423,8 @@ [versioning] # Warn user to update its node if we reach this percentage for announced network versions - mip_stats_warn_announced_version = 30 \ No newline at end of file + mip_stats_warn_announced_version = 30 + +# Dump final blocks (in grpc binary format) by activating the feature: --features dump-block +[block_dump] + block_dump_folder_path = "dump/blocks" \ No newline at end of file diff --git a/massa-node/src/main.rs b/massa-node/src/main.rs index 2571ca33c71..b4e6dfb1a82 100644 --- a/massa-node/src/main.rs +++ b/massa-node/src/main.rs @@ -449,6 +449,14 @@ async fn launch( ) .expect("Failed to load gas costs"); + let block_dump_folder_path = SETTINGS.block_dump.block_dump_folder_path.clone(); + if !block_dump_folder_path.exists() { + info!("Current folder: {:?}", std::env::current_dir().unwrap()); + info!("Creating dump folder: {:?}", block_dump_folder_path); + std::fs::create_dir_all(block_dump_folder_path.clone()) + .expect("Cannot create dump block folder"); + } + // launch execution module let execution_config = ExecutionConfig { max_final_events: SETTINGS.execution.max_final_events, @@ -497,6 +505,7 @@ async fn launch( .execution .broadcast_slot_execution_traces_channel_capacity, max_execution_traces_slot_limit: SETTINGS.execution.execution_traces_limit, + block_dump_folder_path, }; let execution_channels = ExecutionChannels { diff --git a/massa-node/src/settings.rs b/massa-node/src/settings.rs index 8c288907bae..c212d02426f 100644 --- a/massa-node/src/settings.rs +++ b/massa-node/src/settings.rs @@ -144,6 +144,7 @@ pub struct Settings { pub grpc: GrpcApiSettings, pub metrics: MetricsSettings, pub versioning: VersioningSettings, + pub block_dump: BlockDumpSettings, } /// Consensus configuration @@ -381,6 +382,12 @@ pub struct VersioningSettings { pub(crate) mip_stats_warn_announced_version: u32, } +#[derive(Debug, Deserialize, Clone)] +pub struct BlockDumpSettings { + /// Where to dump blocks + pub(crate) block_dump_folder_path: PathBuf, +} + #[cfg(test)] #[test] fn test_load_node_config() {