From 8b23f0a0bc82c99a6db0f223ffe9de6b84cb3e57 Mon Sep 17 00:00:00 2001 From: Modship Date: Thu, 4 Apr 2024 16:40:05 +0200 Subject: [PATCH] minimal fees (#4664) * add minimal fees to config * parse config * update operation pool to not include op with fee < config.fee * return minimal_fees in node get_status (rpc api) * update massa-client to reject op with fee < minimal_fees * update proto-rs sc-runtime rev * update massa-api * grpc get_status * update massa grpc * clippy * massa-api unit test * fix test * PR comment * fix config.toml * massa-sc-runtime target main --- Cargo.lock | 4 +- Cargo.toml | 10 +-- massa-api-exports/src/config.rs | 3 + massa-api-exports/src/node.rs | 3 + massa-api/src/public.rs | 56 ++++++++++++ massa-api/src/tests/mock.rs | 3 + massa-api/src/tests/public.rs | 63 +++++++++++++ massa-client/src/cmds.rs | 23 +++-- massa-grpc/src/config.rs | 3 + massa-grpc/src/public.rs | 14 +++ massa-grpc/src/stream/send_operations.rs | 6 ++ massa-grpc/src/tests/mock.rs | 2 + massa-grpc/src/tests/stream.rs | 90 ++++++++++++++++++- massa-node/base_config/config.toml | 4 +- massa-node/src/main.rs | 7 ++ massa-node/src/settings.rs | 4 +- massa-pool-exports/src/config.rs | 2 + massa-pool-exports/src/test_exports/config.rs | 12 ++- massa-pool-worker/src/operation_pool.rs | 5 ++ 19 files changed, 291 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15cbe2e90e2..540b62c9a2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2566,7 +2566,7 @@ dependencies = [ [[package]] name = "massa-proto-rs" version = "0.1.0" -source = "git+https://github.com/massalabs/massa-proto-rs?rev=25638b3b7d387afbca81afcb02bae1af03697f18#25638b3b7d387afbca81afcb02bae1af03697f18" +source = "git+https://github.com/massalabs/massa-proto-rs?rev=426fd325a55dfcc4033920bed2de075a7e7ad4b7#426fd325a55dfcc4033920bed2de075a7e7ad4b7" 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=32102813c05559c17d8ac1e1ee673802c2ba2ea8#32102813c05559c17d8ac1e1ee673802c2ba2ea8" +source = "git+https://github.com/massalabs/massa-sc-runtime?rev=e95066a6d3a963ff0125616f404a84e5abb63d63#e95066a6d3a963ff0125616f404a84e5abb63d63" dependencies = [ "anyhow", "as-ffi-bindings", diff --git a/Cargo.toml b/Cargo.toml index 432564d2eb4..79222cfb105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,8 +53,8 @@ opt-level = 3 # Speed-up the CI # This profile is used for prebuilt binaries. [profile.release_prebuilt] inherits = "release" -codegen-units = 1 # Do not split into multiple codegen units, improve performance, may compile slower -lto = true # Enables Link Time Optimization, enabling more aggressive optimizations across the entire codebase +codegen-units = 1 # Do not split into multiple codegen units, improve performance, may compile slower +lto = true # Enables Link Time Optimization, enabling more aggressive optimizations across the entire codebase # # Features # @@ -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" = "25638b3b7d387afbca81afcb02bae1af03697f18" } -massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "32102813c05559c17d8ac1e1ee673802c2ba2ea8" } +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" } peernet = { git = "https://github.com/massalabs/PeerNet", "rev" = "04b05ddd320fbe76cc858115af7b5fc28bdb8310" } # Common dependencies @@ -201,4 +201,4 @@ tracing-subscriber = "0.3" unsigned-varint = "0.8" variant_count = "1.1" walkdir = "2.3" -zeroize = { version = "1.7", features = ["derive"] } \ No newline at end of file +zeroize = { version = "1.7", features = ["derive"] } diff --git a/massa-api-exports/src/config.rs b/massa-api-exports/src/config.rs index 1073302e9db..6ec7e31abc3 100644 --- a/massa-api-exports/src/config.rs +++ b/massa-api-exports/src/config.rs @@ -1,5 +1,6 @@ // Copyright (c) 2022 MASSA LABS +use massa_models::amount::Amount; use massa_signature::KeyPair; use massa_time::MassaTime; use std::net::SocketAddr; @@ -81,4 +82,6 @@ pub struct APIConfig { pub chain_id: u64, /// Delta to compute upper bounds when fetching deferred credits pub deferred_credits_delta: MassaTime, + /// minimal fees to include an operation in a block + pub minimal_fees: Amount, } diff --git a/massa-api-exports/src/node.rs b/massa-api-exports/src/node.rs index b39888bb51e..9676aab2dd7 100644 --- a/massa-api-exports/src/node.rs +++ b/massa-api-exports/src/node.rs @@ -1,5 +1,6 @@ // Copyright (c) 2022 MASSA LABS +use massa_models::amount::Amount; use massa_models::node::NodeId; use massa_models::stats::{ConsensusStats, ExecutionStats, NetworkStats}; use massa_models::{config::CompactConfig, slot::Slot, version::Version}; @@ -43,6 +44,8 @@ pub struct NodeStatus { pub config: CompactConfig, /// chain id pub chain_id: u64, + /// minimal fees to include an operation in a block + pub minimal_fees: Amount, } impl std::fmt::Display for NodeStatus { diff --git a/massa-api/src/public.rs b/massa-api/src/public.rs index a096af53fd3..0fab4fac3e8 100644 --- a/massa-api/src/public.rs +++ b/massa-api/src/public.rs @@ -281,6 +281,27 @@ impl MassaRpcServer for API { fee, }; + // check if fee is enough + if fee + .unwrap_or_default() + .checked_sub(self.0.api_settings.minimal_fees) + .is_none() + { + let result = ExecuteReadOnlyResponse { + executed_at: Slot::new(0, 0), + result: ReadOnlyResult::Error(format!( + "fee is too low provided: {} , minimal_fees required: {}", + fee.unwrap_or_default(), + self.0.api_settings.minimal_fees + )), + gas_cost: 0, + output_events: Default::default(), + state_changes: Default::default(), + }; + res.push(result); + continue; + } + // run let result = self.0.execution_controller.execute_readonly_request(req); @@ -365,6 +386,26 @@ impl MassaRpcServer for API { fee, }; + if fee + .unwrap_or_default() + .checked_sub(self.0.api_settings.minimal_fees) + .is_none() + { + let result = ExecuteReadOnlyResponse { + executed_at: Slot::new(0, 0), + result: ReadOnlyResult::Error(format!( + "fee is too low provided: {} , minimal_fees required: {}", + fee.unwrap_or_default(), + self.0.api_settings.minimal_fees + )), + gas_cost: 0, + output_events: Default::default(), + state_changes: Default::default(), + }; + res.push(result); + continue; + } + // run let result = self.0.execution_controller.execute_readonly_request(req); @@ -520,6 +561,7 @@ impl MassaRpcServer for API { config, current_cycle, chain_id: self.0.api_settings.chain_id, + minimal_fees: self.0.api_settings.minimal_fees, }) } @@ -1145,6 +1187,19 @@ impl MassaRpcServer for API { .map(|op_input| check_input_operation(op_input, api_cfg, last_slot)) .map(|op| match op { Ok(operation) => { + if operation + .content + .fee + .checked_sub(api_cfg.minimal_fees) + .is_none() + { + return Err(ApiError::BadRequest(format!( + "fee is too low provided: {} , minimal_fees required: {}", + operation.content.fee, self.0.api_settings.minimal_fees + )) + .into()); + } + let _verify_signature = match operation.verify_signature() { Ok(()) => (), Err(e) => return Err(ApiError::ModelsError(e).into()), @@ -1154,6 +1209,7 @@ impl MassaRpcServer for API { Err(e) => Err(e), }) .collect::>>()?; + to_send.store_operations(verified_ops.clone()); let ids: Vec = verified_ops.iter().map(|op| op.id).collect(); cmd_sender.add_operations(to_send.clone()); diff --git a/massa-api/src/tests/mock.rs b/massa-api/src/tests/mock.rs index efcb538ff55..735da5266b9 100644 --- a/massa-api/src/tests/mock.rs +++ b/massa-api/src/tests/mock.rs @@ -7,6 +7,7 @@ use std::{collections::HashMap, net::SocketAddr}; use massa_api_exports::config::APIConfig; use massa_consensus_exports::{ConsensusBroadcasts, MockConsensusController}; use massa_execution_exports::{GasCosts, MockExecutionController}; +use massa_models::amount::Amount; use massa_models::config::CHAINID; use massa_models::{ config::{ @@ -68,6 +69,7 @@ pub(crate) fn get_apiv2_server(addr: &SocketAddr) -> (API, APIConfig) { last_start_period: 0, chain_id: *CHAINID, deferred_credits_delta: MassaTime::from_millis(24 * 3600 * 2), + minimal_fees: Amount::zero(), }; // let shared_storage: massa_storage::Storage = massa_storage::Storage::create_root(); @@ -143,6 +145,7 @@ pub(crate) fn start_public_api(addr: SocketAddr) -> (API, APIConfig) { last_start_period: 0, chain_id: *CHAINID, deferred_credits_delta: MassaTime::from_millis(24 * 3600 * 2), + minimal_fees: Amount::zero(), }; let shared_storage: massa_storage::Storage = massa_storage::Storage::create_root(); diff --git a/massa-api/src/tests/public.rs b/massa-api/src/tests/public.rs index ae4bbfb3267..e3ace78e249 100644 --- a/massa-api/src/tests/public.rs +++ b/massa-api/src/tests/public.rs @@ -449,6 +449,69 @@ async fn get_graph_interval() { api_public_handle.stop().await; } +#[tokio::test] +async fn send_operations_low_fee() { + let addr: SocketAddr = "[::]:5049".parse().unwrap(); + let (mut api_public, mut config) = start_public_api(addr); + + config.minimal_fees = Amount::from_str("0.01").unwrap(); + api_public.0.api_settings.minimal_fees = Amount::from_str("0.01").unwrap(); + + let mut pool_ctrl = MockPoolController::new(); + pool_ctrl.expect_clone_box().returning(|| { + let mut pool_ctrl = MockPoolController::new(); + pool_ctrl.expect_add_operations().returning(|_a| ()); + Box::new(pool_ctrl) + }); + + let mut protocol_ctrl = MockProtocolController::new(); + protocol_ctrl.expect_clone_box().returning(|| { + let mut protocol_ctrl = MockProtocolController::new(); + protocol_ctrl + .expect_propagate_operations() + .returning(|_a| Ok(())); + Box::new(protocol_ctrl) + }); + + api_public.0.protocol_controller = Box::new(protocol_ctrl); + api_public.0.pool_command_sender = Box::new(pool_ctrl); + + let api_public_handle = api_public + .serve(&addr, &config) + .await + .expect("failed to start PUBLIC API"); + + let client = HttpClientBuilder::default() + .build(format!( + "http://localhost:{}", + addr.to_string().split(':').last().unwrap() + )) + .unwrap(); + let keypair = KeyPair::generate(0).unwrap(); + + // send transaction + let operation = create_operation_with_expire_period(&keypair, 500000); + + let input: OperationInput = OperationInput { + creator_public_key: keypair.get_public_key(), + signature: operation.signature, + serialized_content: operation.serialized_data, + }; + + let response: Result, Error> = client + .request("send_operations", rpc_params![vec![input]]) + .await; + + let err = response.unwrap_err(); + + // op has low fee and should not be executed + assert!(err + .to_string() + .contains("Bad request: fee is too low provided: 0")); + + api_public_handle.stop().await; +} + #[tokio::test] async fn send_operations() { let addr: SocketAddr = "[::]:5014".parse().unwrap(); diff --git a/massa-client/src/cmds.rs b/massa-client/src/cmds.rs index 03914347464..0d5805d3b80 100644 --- a/massa-client/src/cmds.rs +++ b/massa-client/src/cmds.rs @@ -1360,16 +1360,27 @@ async fn send_operation( addr: Address, json: bool, ) -> Result> { - let cfg = match client.public.get_status().await { + let status = match client.public.get_status().await { Ok(node_status) => node_status, Err(e) => rpc_error!(e), + }; + + // check if the fee is higher than the minimal fees of the node + if fee.checked_sub(status.minimal_fees).is_none() { + bail!(format!( + "fee is too low provided: {} , minimal_fees required: {}", + fee, status.minimal_fees + )); } - .config; - let slot = get_current_latest_block_slot(cfg.thread_count, cfg.t0, cfg.genesis_timestamp)? - .unwrap_or_else(|| Slot::new(0, 0)); - let mut expire_period = slot.period + cfg.operation_validity_periods; - if slot.thread >= addr.get_thread(cfg.thread_count) { + let slot = get_current_latest_block_slot( + status.config.thread_count, + status.config.t0, + status.config.genesis_timestamp, + )? + .unwrap_or_else(|| Slot::new(0, 0)); + let mut expire_period = slot.period + status.config.operation_validity_periods; + if slot.thread >= addr.get_thread(status.config.thread_count) { expire_period += 1; }; diff --git a/massa-grpc/src/config.rs b/massa-grpc/src/config.rs index 313ee10a412..172255200cc 100644 --- a/massa-grpc/src/config.rs +++ b/massa-grpc/src/config.rs @@ -1,5 +1,6 @@ // Copyright (c) 2023 MASSA LABS +use massa_models::amount::Amount; use massa_signature::KeyPair; use massa_time::MassaTime; use serde::Deserialize; @@ -133,6 +134,8 @@ pub struct GrpcConfig { pub client_private_key_path: PathBuf, /// chain id pub chain_id: u64, + /// minimal fees + pub minimal_fees: Amount, } /// gRPC API configuration. diff --git a/massa-grpc/src/public.rs b/massa-grpc/src/public.rs index 09eff717b8a..f280e6daa11 100644 --- a/massa-grpc/src/public.rs +++ b/massa-grpc/src/public.rs @@ -143,6 +143,19 @@ pub(crate) fn execute_read_only_call( .transpose()?, }; + if read_only_call + .fee + .unwrap_or_default() + .checked_sub(grpc.grpc_config.minimal_fees) + .is_none() + { + return Err(GrpcError::InvalidArgument(format!( + "fee is too low provided: {} , minimal_fees required: {}", + read_only_call.fee.unwrap_or_default(), + grpc.grpc_config.minimal_fees + ))); + } + let output = grpc .execution_controller .execute_readonly_request(read_only_call)?; @@ -945,6 +958,7 @@ pub(crate) fn get_status( final_state_fingerprint: state.final_state_fingerprint.to_string(), config: Some(config.into()), chain_id: grpc.grpc_config.chain_id, + minimal_fees: Some(grpc.grpc_config.minimal_fees.into()), }; Ok(grpc_api::GetStatusResponse { diff --git a/massa-grpc/src/stream/send_operations.rs b/massa-grpc/src/stream/send_operations.rs index e18fb7b3005..79b61a48856 100644 --- a/massa-grpc/src/stream/send_operations.rs +++ b/massa-grpc/src/stream/send_operations.rs @@ -111,6 +111,12 @@ pub(crate) async fn send_operations( return Err(GrpcError::InvalidArgument("Operation expire_period is lower than the current period of this node. Your operation will never be included in a block.".into())); } } + + + if res_operation.content.fee.checked_sub(config.minimal_fees).is_none() { + return Err(GrpcError::InvalidArgument("Operation fee is lower than the minimal fee. Your operation will never be included in a block.".into())); + } + if rest.is_empty() { res_operation.verify_signature() .map(|_| (res_operation.id.to_string(), res_operation)) diff --git a/massa-grpc/src/tests/mock.rs b/massa-grpc/src/tests/mock.rs index eb0d95d6307..2f9a8c2a886 100644 --- a/massa-grpc/src/tests/mock.rs +++ b/massa-grpc/src/tests/mock.rs @@ -5,6 +5,7 @@ use crate::config::{GrpcConfig, ServiceName}; use crate::server::MassaPublicGrpc; use massa_consensus_exports::{ConsensusBroadcasts, MockConsensusController}; use massa_execution_exports::{ExecutionChannels, MockExecutionController}; +use massa_models::amount::Amount; use massa_models::{ config::{ ENDORSEMENT_COUNT, MAX_DATASTORE_VALUE_LENGTH, MAX_DENUNCIATIONS_PER_BLOCK_HEADER, @@ -109,6 +110,7 @@ pub(crate) fn grpc_public_service(addr: &SocketAddr) -> MassaPublicGrpc { client_private_key_path: PathBuf::default(), max_query_items_per_request: 50, chain_id: *CHAINID, + minimal_fees: Amount::zero(), }; let mip_stats_config = MipStatsConfig { diff --git a/massa-grpc/src/tests/stream.rs b/massa-grpc/src/tests/stream.rs index 52bf30fd5cf..2bba9d10ac8 100644 --- a/massa-grpc/src/tests/stream.rs +++ b/massa-grpc/src/tests/stream.rs @@ -1,11 +1,12 @@ // Copyright (c) 2023 MASSA LABS use crate::tests::mock::grpc_public_service; +use core::panic; use massa_consensus_exports::MockConsensusController; use massa_execution_exports::{ExecutionOutput, MockExecutionController, SlotExecutionOutput}; use massa_models::{ - address::Address, block::FilledBlock, secure_share::SecureShareSerializer, slot::Slot, - stats::ExecutionStats, + address::Address, amount::Amount, block::FilledBlock, secure_share::SecureShareSerializer, + slot::Slot, stats::ExecutionStats, }; use massa_pool_exports::MockPoolController; use massa_proto_rs::massa::{ @@ -26,7 +27,7 @@ use massa_protocol_exports::{ use massa_serialization::Serializer; use massa_signature::KeyPair; use massa_time::MassaTime; -use std::{net::SocketAddr, ops::Add, time::Duration}; +use std::{net::SocketAddr, ops::Add, str::FromStr, time::Duration}; use tokio_stream::StreamExt; #[tokio::test] @@ -1223,9 +1224,90 @@ async fn new_slot_execution_outputs() { stop_handle.stop(); } +#[tokio::test] +async fn send_operations_low_fee() { + let addr: SocketAddr = "[::]:4000".parse().unwrap(); + let mut public_server = grpc_public_service(&addr); + public_server.grpc_config.minimal_fees = Amount::from_str("0.01").unwrap(); + + let mut pool_ctrl = Box::new(MockPoolController::new()); + pool_ctrl.expect_clone_box().returning(|| { + let mut pool_ctrl = Box::new(MockPoolController::new()); + + pool_ctrl.expect_add_operations().returning(|_| ()); + + pool_ctrl + }); + + let mut protocol_ctrl = Box::new(MockProtocolController::new()); + protocol_ctrl.expect_clone_box().returning(|| { + let mut ctrl = Box::new(MockProtocolController::new()); + + ctrl.expect_propagate_operations().returning(|_| Ok(())); + + ctrl + }); + + public_server.pool_controller = pool_ctrl; + public_server.protocol_controller = protocol_ctrl; + + let config = public_server.grpc_config.clone(); + let stop_handle = public_server.serve(&config).await.unwrap(); + + let (tx, rx) = tokio::sync::mpsc::channel(10); + let request_stream = tokio_stream::wrappers::ReceiverStream::new(rx); + + let mut public_client = PublicServiceClient::connect(format!( + "grpc://localhost:{}", + addr.to_string().split(':').last().unwrap() + )) + .await + .unwrap(); + + let mut resp_stream = public_client + .send_operations(request_stream) + .await + .unwrap() + .into_inner(); + + let keypair = KeyPair::generate(0).unwrap(); + // Note: expire_period is set to be higher than current slot (which is computed from config genesis timestamp) + // CHeck send_operation.rs where last_slot value is computed + let op2 = create_operation_with_expire_period(&keypair, 1950000); + let mut buffer: Vec = Vec::new(); + SecureShareSerializer::new() + .serialize(&op2, &mut buffer) + .unwrap(); + + tx.send(SendOperationsRequest { + operations: vec![buffer.clone()], + }) + .await + .unwrap(); + + let result = tokio::time::timeout(Duration::from_secs(5), resp_stream.next()) + .await + .unwrap() + .unwrap() + .unwrap() + .result + .unwrap(); + + match result { + massa_proto_rs::massa::api::v1::send_operations_response::Result::OperationIds(_ope_id) => { + panic!("should be error"); + } + massa_proto_rs::massa::api::v1::send_operations_response::Result::Error(e) => { + assert_eq!(e.message, "invalid operation(s): Invalid argument error: Operation fee is lower than the minimal fee. Your operation will never be included in a block."); + } + } + + stop_handle.stop(); +} + #[tokio::test] async fn send_operations() { - let addr: SocketAddr = "[::]:4023".parse().unwrap(); + let addr: SocketAddr = "[::]:4033".parse().unwrap(); let mut public_server = grpc_public_service(&addr); let mut pool_ctrl = Box::new(MockPoolController::new()); diff --git a/massa-node/base_config/config.toml b/massa-node/base_config/config.toml index 6b2fb0f3b05..d3169c6f90b 100644 --- a/massa-node/base_config/config.toml +++ b/massa-node/base_config/config.toml @@ -411,6 +411,8 @@ broadcast_endorsements_channel_capacity = 2000 # operations channel capacity broadcast_operations_channel_capacity = 5000 + # minimal fee to include operation in the pool 0.01MAS + minimal_fees = 0.01 [selector] @@ -427,4 +429,4 @@ [versioning] # Warn user to update its node if we reach this percentage for announced network versions - mip_stats_warn_announced_version = 30 + mip_stats_warn_announced_version = 30 \ No newline at end of file diff --git a/massa-node/src/main.rs b/massa-node/src/main.rs index 941c6ab87db..34eb43f1c48 100644 --- a/massa-node/src/main.rs +++ b/massa-node/src/main.rs @@ -45,6 +45,7 @@ use massa_ledger_worker::FinalLedger; use massa_logging::massa_trace; use massa_metrics::{MassaMetrics, MetricsStopper}; use massa_models::address::Address; +use massa_models::amount::Amount; use massa_models::config::constants::{ ASYNC_MSG_CST_GAS_COST, BLOCK_REWARD, BOOTSTRAP_RANDOMNESS_SIZE_BYTES, CHANNEL_SIZE, CONSENSUS_BOOTSTRAP_PART_SIZE, DELTA_F0, DENUNCIATION_EXPIRE_PERIODS, ENDORSEMENT_COUNT, @@ -549,6 +550,7 @@ async fn launch( periods_per_cycle: PERIODS_PER_CYCLE, denunciation_expire_periods: DENUNCIATION_EXPIRE_PERIODS, max_denunciations_per_block_header: MAX_DENUNCIATIONS_PER_BLOCK_HEADER, + minimal_fees: SETTINGS.pool.minimal_fees, last_start_period: final_state.read().get_last_start_period(), }; @@ -837,6 +839,7 @@ async fn launch( last_start_period: final_state.read().get_last_start_period(), chain_id: *CHAINID, deferred_credits_delta: SETTINGS.api.deferred_credits_delta, + minimal_fees: SETTINGS.pool.minimal_fees, }; // spawn Massa API @@ -869,6 +872,7 @@ async fn launch( &SETTINGS.grpc.public, keypair.clone(), &final_state, + SETTINGS.pool.minimal_fees, ); let grpc_public_api = MassaPublicGrpc { @@ -909,6 +913,7 @@ async fn launch( &SETTINGS.grpc.private, keypair.clone(), &final_state, + SETTINGS.pool.minimal_fees, ); let bs_white_black_list = bootstrap_manager @@ -1063,6 +1068,7 @@ fn configure_grpc( settings: &GrpcSettings, keypair: KeyPair, final_state: &Arc>, + minimal_fees: Amount, ) -> GrpcConfig { GrpcConfig { name, @@ -1129,6 +1135,7 @@ fn configure_grpc( client_certificate_path: settings.client_certificate_path.clone(), client_private_key_path: settings.client_private_key_path.clone(), chain_id: *CHAINID, + minimal_fees, } } diff --git a/massa-node/src/settings.rs b/massa-node/src/settings.rs index acf5f937b0f..bdff3e641f4 100644 --- a/massa-node/src/settings.rs +++ b/massa-node/src/settings.rs @@ -4,7 +4,7 @@ use std::{collections::HashMap, path::PathBuf}; use massa_bootstrap::IpType; -use massa_models::{config::build_massa_settings, node::NodeId}; +use massa_models::{amount::Amount, config::build_massa_settings, node::NodeId}; use massa_protocol_exports::PeerCategoryInfo; use massa_time::MassaTime; use serde::Deserialize; @@ -101,6 +101,8 @@ pub struct PoolSettings { pub broadcast_endorsements_channel_capacity: usize, /// operations channel capacity pub broadcast_operations_channel_capacity: usize, + /// operations minimum fees for block creator + pub minimal_fees: Amount, } /// API and server configuration, read from a file configuration. diff --git a/massa-pool-exports/src/config.rs b/massa-pool-exports/src/config.rs index 48d1e794460..965104de8dc 100644 --- a/massa-pool-exports/src/config.rs +++ b/massa-pool-exports/src/config.rs @@ -57,6 +57,8 @@ pub struct PoolConfig { pub denunciation_expire_periods: u64, /// max number of denunciations that can be included in a block header pub max_denunciations_per_block_header: u32, + /// Minimum acceptable fees to include an operation in a block + pub minimal_fees: Amount, /// last_start_period /// * If start all new network: set to 0 /// * If from snapshot: retrieve from args diff --git a/massa-pool-exports/src/test_exports/config.rs b/massa-pool-exports/src/test_exports/config.rs index fb572fdf771..b33cebd014f 100644 --- a/massa-pool-exports/src/test_exports/config.rs +++ b/massa-pool-exports/src/test_exports/config.rs @@ -1,9 +1,12 @@ // Copyright (c) 2022 MASSA LABS -use massa_models::config::{ - BASE_OPERATION_GAS_COST, DENUNCIATION_EXPIRE_PERIODS, ENDORSEMENT_COUNT, MAX_BLOCK_SIZE, - MAX_DENUNCIATIONS_PER_BLOCK_HEADER, MAX_GAS_PER_BLOCK, MAX_OPERATIONS_PER_BLOCK, - OPERATION_VALIDITY_PERIODS, PERIODS_PER_CYCLE, ROLL_PRICE, T0, THREAD_COUNT, +use massa_models::{ + amount::Amount, + config::{ + BASE_OPERATION_GAS_COST, DENUNCIATION_EXPIRE_PERIODS, ENDORSEMENT_COUNT, MAX_BLOCK_SIZE, + MAX_DENUNCIATIONS_PER_BLOCK_HEADER, MAX_GAS_PER_BLOCK, MAX_OPERATIONS_PER_BLOCK, + OPERATION_VALIDITY_PERIODS, PERIODS_PER_CYCLE, ROLL_PRICE, T0, THREAD_COUNT, + }, }; use massa_time::MassaTime; @@ -38,6 +41,7 @@ impl Default for PoolConfig { last_start_period: 0, operation_pool_refresh_interval: MassaTime::from_millis(2000), operation_max_future_start_delay: T0.saturating_mul(5), + minimal_fees: Amount::zero(), } } } diff --git a/massa-pool-worker/src/operation_pool.rs b/massa-pool-worker/src/operation_pool.rs index 2af01f60e96..e7108032bdc 100644 --- a/massa-pool-worker/src/operation_pool.rs +++ b/massa-pool-worker/src/operation_pool.rs @@ -165,6 +165,11 @@ impl OperationPool { }); } + if retain { + // filter ops which doesn't have minimal fees + retain = op_info.fee.checked_sub(self.config.minimal_fees).is_some(); + } + // filter out ops that have been executed in final or candidate slots // TODO: in the re-execution followup, we should only filter out final-executed ops here (exec_status == Some(true)) if retain {