From 36c2fdd1aa4dfa3b221d4ae245b8c2e3e3b944f9 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Wed, 15 Jan 2025 08:49:00 -0600 Subject: [PATCH 1/5] FeeFeatures --- Cargo.lock | 1 + core/src/banking_stage/consumer.rs | 4 ++-- fee/Cargo.toml | 1 + fee/src/lib.rs | 30 +++++++++++++++++++++++----- programs/sbf/Cargo.lock | 3 ++- runtime/src/bank.rs | 9 +++------ runtime/src/bank/fee_distribution.rs | 6 +++--- runtime/src/bank/tests.rs | 4 +++- svm/examples/Cargo.lock | 3 ++- svm/src/transaction_processor.rs | 8 +++----- 10 files changed, 45 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 906564f8316908..4738465511ed02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7311,6 +7311,7 @@ dependencies = [ name = "solana-fee" version = "2.2.0" dependencies = [ + "solana-feature-set", "solana-fee-structure", "solana-svm-transaction", ] diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 5a8ef5cb79b7d0..e4c671ae922301 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -13,6 +13,7 @@ use { }, itertools::Itertools, solana_feature_set as feature_set, + solana_fee::FeeFeatures, solana_ledger::token_balances::collect_token_balances, solana_measure::{measure::Measure, measure_us}, solana_poh::poh_recorder::{ @@ -767,8 +768,7 @@ impl Consumer { bank.get_lamports_per_signature() == 0, bank.fee_structure().lamports_per_signature, fee_budget_limits.prioritization_fee, - bank.feature_set - .is_active(&feature_set::remove_rounding_in_fee_calculation::id()), + FeeFeatures::from(bank.feature_set.as_ref()), ); let (mut fee_payer_account, _slot) = bank .rc diff --git a/fee/Cargo.toml b/fee/Cargo.toml index 5bb62e858f6654..d1199ec711556e 100644 --- a/fee/Cargo.toml +++ b/fee/Cargo.toml @@ -10,5 +10,6 @@ license = { workspace = true } edition = { workspace = true } [dependencies] +solana-feature-set = { workspace = true } solana-fee-structure = { workspace = true } solana-svm-transaction = { workspace = true } diff --git a/fee/src/lib.rs b/fee/src/lib.rs index 7f2f7ec072a492..91712e6062c262 100644 --- a/fee/src/lib.rs +++ b/fee/src/lib.rs @@ -1,4 +1,24 @@ -use {solana_fee_structure::FeeDetails, solana_svm_transaction::svm_message::SVMMessage}; +use { + solana_feature_set::{remove_rounding_in_fee_calculation, FeatureSet}, + solana_fee_structure::FeeDetails, + solana_svm_transaction::svm_message::SVMMessage, +}; + +/// Bools indicating the activation of features relevant +/// to the fee calculation. +#[derive(Copy, Clone)] +pub struct FeeFeatures { + pub remove_rounding_in_fee_calculation: bool, +} + +impl From<&FeatureSet> for FeeFeatures { + fn from(feature_set: &FeatureSet) -> Self { + Self { + remove_rounding_in_fee_calculation: feature_set + .is_active(&remove_rounding_in_fee_calculation::ID), + } + } +} /// Calculate fee for `SanitizedMessage` pub fn calculate_fee( @@ -6,14 +26,14 @@ pub fn calculate_fee( zero_fees_for_test: bool, lamports_per_signature: u64, prioritization_fee: u64, - remove_rounding_in_fee_calculation: bool, + fee_features: FeeFeatures, ) -> u64 { calculate_fee_details( message, zero_fees_for_test, lamports_per_signature, prioritization_fee, - remove_rounding_in_fee_calculation, + fee_features, ) .total_fee() } @@ -23,7 +43,7 @@ pub fn calculate_fee_details( zero_fees_for_test: bool, lamports_per_signature: u64, prioritization_fee: u64, - remove_rounding_in_fee_calculation: bool, + fee_features: FeeFeatures, ) -> FeeDetails { if zero_fees_for_test { return FeeDetails::default(); @@ -32,7 +52,7 @@ pub fn calculate_fee_details( FeeDetails::new( calculate_signature_fee(SignatureCounts::from(message), lamports_per_signature), prioritization_fee, - remove_rounding_in_fee_calculation, + fee_features.remove_rounding_in_fee_calculation, ) } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index de95dd72e0d5d4..3ffcaa4cedae94 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -5872,6 +5872,7 @@ dependencies = [ name = "solana-fee" version = "2.2.0" dependencies = [ + "solana-feature-set", "solana-fee-structure", "solana-svm-transaction", ] diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 11b34db594c4dd..dc6e4c0b497b68 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -95,10 +95,8 @@ use { solana_compute_budget::compute_budget::ComputeBudget, solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker}, - solana_feature_set::{ - self as feature_set, remove_rounding_in_fee_calculation, reward_full_priority_fee, - FeatureSet, - }, + solana_feature_set::{self as feature_set, reward_full_priority_fee, FeatureSet}, + solana_fee::FeeFeatures, solana_lattice_hash::lt_hash::LtHash, solana_measure::{meas_dur, measure::Measure, measure_time, measure_us}, solana_program_runtime::{ @@ -2920,8 +2918,7 @@ impl Bank { lamports_per_signature == 0, self.fee_structure().lamports_per_signature, fee_budget_limits.prioritization_fee, - self.feature_set - .is_active(&remove_rounding_in_fee_calculation::id()), + FeeFeatures::from(self.feature_set.as_ref()), ) } diff --git a/runtime/src/bank/fee_distribution.rs b/runtime/src/bank/fee_distribution.rs index e90444053df51e..22c08b66f00c2a 100644 --- a/runtime/src/bank/fee_distribution.rs +++ b/runtime/src/bank/fee_distribution.rs @@ -2,7 +2,8 @@ use { super::Bank, crate::bank::CollectorFeeDetails, log::{debug, warn}, - solana_feature_set::{remove_rounding_in_fee_calculation, reward_full_priority_fee}, + solana_feature_set::reward_full_priority_fee, + solana_fee::FeeFeatures, solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ account::{ReadableAccount, WritableAccount}, @@ -81,8 +82,7 @@ impl Bank { self.get_lamports_per_signature() == 0, self.fee_structure().lamports_per_signature, fee_budget_limits.prioritization_fee, - self.feature_set - .is_active(&remove_rounding_in_fee_calculation::id()), + FeeFeatures::from(self.feature_set.as_ref()), ); let (reward, _burn) = if self.feature_set.is_active(&reward_full_priority_fee::id()) { self.calculate_reward_and_burn_fee_details(&CollectorFeeDetails::from(fee_details)) diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 7aa0e305f4c489..96424c70c2e780 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -10388,7 +10388,9 @@ fn calculate_test_fee( lamports_per_signature == 0, fee_structure.lamports_per_signature, fee_budget_limits.prioritization_fee, - true, + FeeFeatures { + remove_rounding_in_fee_calculation: true, + }, ) } diff --git a/svm/examples/Cargo.lock b/svm/examples/Cargo.lock index 99d7d319e985cf..04f9dec10e8ffe 100644 --- a/svm/examples/Cargo.lock +++ b/svm/examples/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -5723,6 +5723,7 @@ dependencies = [ name = "solana-fee" version = "2.2.0" dependencies = [ + "solana-feature-set", "solana-fee-structure", "solana-svm-transaction", ] diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index 78a2ebef625784..def93b766a2440 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -28,9 +28,9 @@ use { solana_compute_budget::compute_budget::ComputeBudget, solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, solana_feature_set::{ - enable_transaction_loading_failure_fees, remove_accounts_executable_flag_checks, - remove_rounding_in_fee_calculation, FeatureSet, + enable_transaction_loading_failure_fees, remove_accounts_executable_flag_checks, FeatureSet, }, + solana_fee::FeeFeatures, solana_fee_structure::{FeeBudgetLimits, FeeStructure}, solana_hash::Hash, solana_instruction::TRANSACTION_LEVEL_STACK_HEIGHT, @@ -606,9 +606,7 @@ impl TransactionBatchProcessor { lamports_per_signature == 0, fee_lamports_per_signature, fee_budget_limits.prioritization_fee, - account_loader - .feature_set - .is_active(&remove_rounding_in_fee_calculation::id()), + FeeFeatures::from(account_loader.feature_set.as_ref()), ); let fee_payer_index = 0; From e59bf5af1b3fa4f50e061ecaa9e7dc4731039cc2 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Wed, 15 Jan 2025 08:53:46 -0600 Subject: [PATCH 2/5] secp256r1 signatures count towards fee - behind feature --- fee/src/lib.rs | 43 +++++++++++++++++++++++++++++++++++---- runtime/src/bank/tests.rs | 1 + 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/fee/src/lib.rs b/fee/src/lib.rs index 91712e6062c262..241c1061d86bd8 100644 --- a/fee/src/lib.rs +++ b/fee/src/lib.rs @@ -1,5 +1,7 @@ use { - solana_feature_set::{remove_rounding_in_fee_calculation, FeatureSet}, + solana_feature_set::{ + enable_secp256r1_precompile, remove_rounding_in_fee_calculation, FeatureSet, + }, solana_fee_structure::FeeDetails, solana_svm_transaction::svm_message::SVMMessage, }; @@ -9,6 +11,7 @@ use { #[derive(Copy, Clone)] pub struct FeeFeatures { pub remove_rounding_in_fee_calculation: bool, + pub enable_secp256r1_precompile: bool, } impl From<&FeatureSet> for FeeFeatures { @@ -16,6 +19,7 @@ impl From<&FeatureSet> for FeeFeatures { Self { remove_rounding_in_fee_calculation: feature_set .is_active(&remove_rounding_in_fee_calculation::ID), + enable_secp256r1_precompile: feature_set.is_active(&enable_secp256r1_precompile::ID), } } } @@ -50,7 +54,11 @@ pub fn calculate_fee_details( } FeeDetails::new( - calculate_signature_fee(SignatureCounts::from(message), lamports_per_signature), + calculate_signature_fee( + SignatureCounts::from(message), + lamports_per_signature, + fee_features.enable_secp256r1_precompile, + ), prioritization_fee, fee_features.remove_rounding_in_fee_calculation, ) @@ -62,13 +70,17 @@ fn calculate_signature_fee( num_transaction_signatures, num_ed25519_signatures, num_secp256k1_signatures, + num_secp256r1_signatures, }: SignatureCounts, lamports_per_signature: u64, + enable_secp256r1_precompile: bool, ) -> u64 { let signature_count = num_transaction_signatures .saturating_add(num_ed25519_signatures) - .saturating_add(num_secp256k1_signatures); - + .saturating_add(num_secp256k1_signatures) + .saturating_add( + u64::from(enable_secp256r1_precompile).wrapping_mul(num_secp256r1_signatures), + ); signature_count.saturating_mul(lamports_per_signature) } @@ -76,6 +88,7 @@ struct SignatureCounts { pub num_transaction_signatures: u64, pub num_ed25519_signatures: u64, pub num_secp256k1_signatures: u64, + pub num_secp256r1_signatures: u64, } impl From<&Tx> for SignatureCounts { @@ -84,6 +97,7 @@ impl From<&Tx> for SignatureCounts { num_transaction_signatures: message.num_transaction_signatures(), num_ed25519_signatures: message.num_ed25519_signatures(), num_secp256k1_signatures: message.num_secp256k1_signatures(), + num_secp256r1_signatures: message.num_secp256r1_signatures(), } } } @@ -103,8 +117,10 @@ mod tests { num_transaction_signatures: 0, num_ed25519_signatures: 0, num_secp256k1_signatures: 0, + num_secp256r1_signatures: 0, }, LAMPORTS_PER_SIGNATURE, + true, ), 0 ); @@ -116,8 +132,10 @@ mod tests { num_transaction_signatures: 1, num_ed25519_signatures: 0, num_secp256k1_signatures: 0, + num_secp256r1_signatures: 0, }, LAMPORTS_PER_SIGNATURE, + true, ), LAMPORTS_PER_SIGNATURE ); @@ -129,8 +147,25 @@ mod tests { num_transaction_signatures: 1, num_ed25519_signatures: 2, num_secp256k1_signatures: 3, + num_secp256r1_signatures: 4, + }, + LAMPORTS_PER_SIGNATURE, + true, + ), + 10 * LAMPORTS_PER_SIGNATURE + ); + + // Pre-compile signatures (no secp256r1) + assert_eq!( + calculate_signature_fee( + SignatureCounts { + num_transaction_signatures: 1, + num_ed25519_signatures: 2, + num_secp256k1_signatures: 3, + num_secp256r1_signatures: 4, }, LAMPORTS_PER_SIGNATURE, + false, ), 6 * LAMPORTS_PER_SIGNATURE ); diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 96424c70c2e780..f7ef0a1b75cc6b 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -10390,6 +10390,7 @@ fn calculate_test_fee( fee_budget_limits.prioritization_fee, FeeFeatures { remove_rounding_in_fee_calculation: true, + enable_secp256r1_precompile: true, }, ) } From 958a0121cffe7b0c4d97c4771923214c415003b3 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Thu, 16 Jan 2025 15:31:39 -0600 Subject: [PATCH 3/5] fix test_program_fees --- programs/sbf/tests/programs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 5a7877eeaa2d06..3703fae7a84deb 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -3886,7 +3886,7 @@ fn test_program_fees() { bank.set_fee_structure(&fee_structure); let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); let feature_set = bank.feature_set.clone(); - let mut bank_client = BankClient::new_shared(bank); + let mut bank_client = BankClient::new_shared(bank.clone()); let authority_keypair = Keypair::new(); let (_bank, program_id) = load_upgradeable_program_and_advance_slot( @@ -3920,7 +3920,7 @@ fn test_program_fees() { congestion_multiplier == 0, fee_structure.lamports_per_signature, fee_budget_limits.prioritization_fee, - true, + bank.feature_set.as_ref().into(), ); bank_client .send_and_confirm_message(&[&mint_keypair], message) @@ -3953,7 +3953,7 @@ fn test_program_fees() { congestion_multiplier == 0, fee_structure.lamports_per_signature, fee_budget_limits.prioritization_fee, - true, + bank.feature_set.as_ref().into(), ); assert!(expected_normal_fee < expected_prioritized_fee); From 9b75b1cbf42e4f00e3a3bc570b2783449e7254a2 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Fri, 17 Jan 2025 15:16:14 -0600 Subject: [PATCH 4/5] developer note --- fee/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fee/src/lib.rs b/fee/src/lib.rs index 241c1061d86bd8..b305e39f419b47 100644 --- a/fee/src/lib.rs +++ b/fee/src/lib.rs @@ -8,6 +8,10 @@ use { /// Bools indicating the activation of features relevant /// to the fee calculation. +// DEVELOPER NOTE: +// This struct may become empty at some point. It is preferable to keep it +// instead of removing, since fees will naturally be changed via feature-gates +// in the future. Keeping this struct will help keep things organized. #[derive(Copy, Clone)] pub struct FeeFeatures { pub remove_rounding_in_fee_calculation: bool, From d4bfcfe29c9218c351303efa675d2d59a1c0d7c2 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Tue, 21 Jan 2025 08:40:10 -0600 Subject: [PATCH 5/5] sdk::TransactionSignatureDetails::total_signatures include secp256r1 --- sdk/message/src/sanitized.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/message/src/sanitized.rs b/sdk/message/src/sanitized.rs index de804b7903a62f..16de481e99ce2c 100644 --- a/sdk/message/src/sanitized.rs +++ b/sdk/message/src/sanitized.rs @@ -455,6 +455,7 @@ impl TransactionSignatureDetails { self.num_transaction_signatures .saturating_add(self.num_secp256k1_instruction_signatures) .saturating_add(self.num_ed25519_instruction_signatures) + .saturating_add(self.num_secp256r1_instruction_signatures) } /// return the number of transaction signatures