Skip to main content

solana_fee/
lib.rs

1#![cfg(feature = "agave-unstable-api")]
2use {
3    agave_feature_set::FeatureSet, solana_fee_structure::FeeDetails,
4    solana_svm_transaction::svm_message::SVMStaticMessage,
5};
6
7/// Bools indicating the activation of features relevant
8/// to the fee calculation.
9// DEVELOPER NOTE:
10// This struct may become empty at some point. It is preferable to keep it
11// instead of removing, since fees will naturally be changed via feature-gates
12// in the future. Keeping this struct will help keep things organized.
13#[derive(Copy, Clone)]
14pub struct FeeFeatures {}
15
16impl From<&FeatureSet> for FeeFeatures {
17    fn from(_feature_set: &FeatureSet) -> Self {
18        Self {}
19    }
20}
21
22/// Calculate fee for `SanitizedMessage`
23pub fn calculate_fee(
24    message: &impl SVMStaticMessage,
25    lamports_per_signature: u64,
26    prioritization_fee: u64,
27    fee_features: FeeFeatures,
28) -> u64 {
29    calculate_fee_details(
30        message,
31        lamports_per_signature,
32        prioritization_fee,
33        fee_features,
34    )
35    .total_fee()
36}
37
38pub fn calculate_fee_details(
39    message: &impl SVMStaticMessage,
40    lamports_per_signature: u64,
41    prioritization_fee: u64,
42    _fee_features: FeeFeatures,
43) -> FeeDetails {
44    FeeDetails::new(
45        calculate_signature_fee(SignatureCounts::from(message), lamports_per_signature),
46        prioritization_fee,
47    )
48}
49
50/// Calculate fees from signatures.
51pub fn calculate_signature_fee(
52    SignatureCounts {
53        num_transaction_signatures,
54        num_ed25519_signatures,
55        num_secp256k1_signatures,
56        num_secp256r1_signatures,
57    }: SignatureCounts,
58    lamports_per_signature: u64,
59) -> u64 {
60    let signature_count = num_transaction_signatures
61        .saturating_add(num_ed25519_signatures)
62        .saturating_add(num_secp256k1_signatures)
63        .saturating_add(num_secp256r1_signatures);
64    signature_count.saturating_mul(lamports_per_signature)
65}
66
67pub struct SignatureCounts {
68    pub num_transaction_signatures: u64,
69    pub num_ed25519_signatures: u64,
70    pub num_secp256k1_signatures: u64,
71    pub num_secp256r1_signatures: u64,
72}
73
74impl<Tx: SVMStaticMessage> From<&Tx> for SignatureCounts {
75    fn from(message: &Tx) -> Self {
76        Self {
77            num_transaction_signatures: message.num_transaction_signatures(),
78            num_ed25519_signatures: message.num_ed25519_signatures(),
79            num_secp256k1_signatures: message.num_secp256k1_signatures(),
80            num_secp256r1_signatures: message.num_secp256r1_signatures(),
81        }
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_calculate_signature_fee() {
91        const LAMPORTS_PER_SIGNATURE: u64 = 5_000;
92
93        // Impossible case - 0 signatures.
94        assert_eq!(
95            calculate_signature_fee(
96                SignatureCounts {
97                    num_transaction_signatures: 0,
98                    num_ed25519_signatures: 0,
99                    num_secp256k1_signatures: 0,
100                    num_secp256r1_signatures: 0,
101                },
102                LAMPORTS_PER_SIGNATURE,
103            ),
104            0
105        );
106
107        // Simple signature
108        assert_eq!(
109            calculate_signature_fee(
110                SignatureCounts {
111                    num_transaction_signatures: 1,
112                    num_ed25519_signatures: 0,
113                    num_secp256k1_signatures: 0,
114                    num_secp256r1_signatures: 0,
115                },
116                LAMPORTS_PER_SIGNATURE,
117            ),
118            LAMPORTS_PER_SIGNATURE
119        );
120
121        // Pre-compile signatures.
122        assert_eq!(
123            calculate_signature_fee(
124                SignatureCounts {
125                    num_transaction_signatures: 1,
126                    num_ed25519_signatures: 2,
127                    num_secp256k1_signatures: 3,
128                    num_secp256r1_signatures: 4,
129                },
130                LAMPORTS_PER_SIGNATURE,
131            ),
132            10 * LAMPORTS_PER_SIGNATURE
133        );
134    }
135}