1use rialo_s_feature_set::{enable_secp256r1_precompile, FeatureSet};
6use rialo_s_fee_structure::FeeDetails;
7use rialo_s_svm_transaction::svm_message::SVMMessage;
8
9#[derive(Copy, Clone)]
16pub struct FeeFeatures {
17 pub enable_secp256r1_precompile: bool,
18}
19
20impl From<&FeatureSet> for FeeFeatures {
21 fn from(feature_set: &FeatureSet) -> Self {
22 Self {
23 enable_secp256r1_precompile: feature_set.is_active(&enable_secp256r1_precompile::ID),
24 }
25 }
26}
27
28pub fn calculate_fee(
30 message: &impl SVMMessage,
31 zero_fees_for_test: bool,
32 kelvins_per_signature: u64,
33 prioritization_fee: u64,
34 fee_features: FeeFeatures,
35) -> u64 {
36 calculate_fee_details(
37 message,
38 zero_fees_for_test,
39 kelvins_per_signature,
40 prioritization_fee,
41 fee_features,
42 )
43 .total_fee()
44}
45
46pub fn calculate_fee_details(
47 message: &impl SVMMessage,
48 zero_fees_for_test: bool,
49 kelvins_per_signature: u64,
50 prioritization_fee: u64,
51 fee_features: FeeFeatures,
52) -> FeeDetails {
53 if zero_fees_for_test {
54 return FeeDetails::default();
55 }
56
57 FeeDetails::new(
58 calculate_signature_fee(
59 SignatureCounts::from(message),
60 kelvins_per_signature,
61 fee_features.enable_secp256r1_precompile,
62 ),
63 prioritization_fee,
64 )
65}
66
67fn calculate_signature_fee(
69 SignatureCounts {
70 num_transaction_signatures,
71 num_ed25519_signatures,
72 num_secp256k1_signatures,
73 num_secp256r1_signatures,
74 }: SignatureCounts,
75 kelvins_per_signature: u64,
76 enable_secp256r1_precompile: bool,
77) -> u64 {
78 let signature_count = num_transaction_signatures
79 .saturating_add(num_ed25519_signatures)
80 .saturating_add(num_secp256k1_signatures)
81 .saturating_add(
82 u64::from(enable_secp256r1_precompile).wrapping_mul(num_secp256r1_signatures),
83 );
84 signature_count.saturating_mul(kelvins_per_signature)
85}
86
87struct SignatureCounts {
88 pub num_transaction_signatures: u64,
89 pub num_ed25519_signatures: u64,
90 pub num_secp256k1_signatures: u64,
91 pub num_secp256r1_signatures: u64,
92}
93
94impl<Tx: SVMMessage> From<&Tx> for SignatureCounts {
95 fn from(message: &Tx) -> Self {
96 Self {
97 num_transaction_signatures: message.num_transaction_signatures(),
98 num_ed25519_signatures: message.num_ed25519_signatures(),
99 num_secp256k1_signatures: message.num_secp256k1_signatures(),
100 num_secp256r1_signatures: message.num_secp256r1_signatures(),
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_calculate_signature_fee() {
111 const KELVINS_PER_SIGNATURE: u64 = 5_000;
112
113 assert_eq!(
115 calculate_signature_fee(
116 SignatureCounts {
117 num_transaction_signatures: 0,
118 num_ed25519_signatures: 0,
119 num_secp256k1_signatures: 0,
120 num_secp256r1_signatures: 0,
121 },
122 KELVINS_PER_SIGNATURE,
123 true,
124 ),
125 0
126 );
127
128 assert_eq!(
130 calculate_signature_fee(
131 SignatureCounts {
132 num_transaction_signatures: 1,
133 num_ed25519_signatures: 0,
134 num_secp256k1_signatures: 0,
135 num_secp256r1_signatures: 0,
136 },
137 KELVINS_PER_SIGNATURE,
138 true,
139 ),
140 KELVINS_PER_SIGNATURE
141 );
142
143 assert_eq!(
145 calculate_signature_fee(
146 SignatureCounts {
147 num_transaction_signatures: 1,
148 num_ed25519_signatures: 2,
149 num_secp256k1_signatures: 3,
150 num_secp256r1_signatures: 4,
151 },
152 KELVINS_PER_SIGNATURE,
153 true,
154 ),
155 10 * KELVINS_PER_SIGNATURE
156 );
157
158 assert_eq!(
160 calculate_signature_fee(
161 SignatureCounts {
162 num_transaction_signatures: 1,
163 num_ed25519_signatures: 2,
164 num_secp256k1_signatures: 3,
165 num_secp256r1_signatures: 4,
166 },
167 KELVINS_PER_SIGNATURE,
168 false,
169 ),
170 6 * KELVINS_PER_SIGNATURE
171 );
172 }
173}