dpp/fee/default_costs/
mod.rs

1//! Fee costs
2//!
3//! Fee costs for Known Platform operations
4//!
5
6use crate::block::epoch::{Epoch, EpochIndex};
7use crate::fee::Credits;
8use platform_version::version::fee::{
9    FeeVersion, FeeVersionFieldsBeforeVersion4, FeeVersionNumber,
10};
11use std::collections::BTreeMap;
12
13pub mod constants;
14
15pub type CachedEpochIndexFeeVersions = BTreeMap<EpochIndex, &'static FeeVersion>;
16pub type EpochIndexFeeVersionsForStorage = BTreeMap<EpochIndex, FeeVersionNumber>;
17
18// This is type only meant for deserialization because of an issue
19// The issue was that the platform state was stored with FeeVersions in it before version 1.4
20// When we would add new fields we would be unable to deserialize
21// This FeeProcessingVersionFieldsBeforeVersion4 is how things were before version 1.4 was released
22pub type CachedEpochIndexFeeVersionsFieldsBeforeVersion4 =
23    BTreeMap<EpochIndex, FeeVersionFieldsBeforeVersion4>;
24
25/// A Known Cost Item is an item that changes costs depending on the Epoch
26#[derive(Eq, PartialEq, Copy, Clone, Hash)]
27pub enum KnownCostItem {
28    /// The storage cost used when writing bytes
29    StorageDiskUsageCreditPerByte,
30    /// The processing cost used when writing bytes
31    StorageProcessingCreditPerByte,
32    /// The processing cost used when loading bytes from storage
33    StorageLoadCreditPerByte,
34    /// The processing cost used when loading bytes not from storage
35    NonStorageLoadCreditPerByte,
36    /// The cost used when performing a disk seek
37    StorageSeekCost,
38    // The following are set costs of routine operations
39    /// The cost for fetching an identity balance
40    FetchIdentityBalanceProcessingCost,
41    /// The cost for fetching an identity key
42    FetchSingleIdentityKeyProcessingCost,
43    /// The cost for a Single SHA256 operation, with a specific size
44    SingleSHA256(usize),
45    /// The cost for a Blake3 operation, with a specific size
46    Blake3(usize),
47    /// The cost for a EcdsaSecp256k1 signature verification
48    VerifySignatureEcdsaSecp256k1,
49    /// The cost for a BLS12_381 signature verification
50    VerifySignatureBLS12_381,
51    /// The cost for a EcdsaHash160 signature verification
52    VerifySignatureEcdsaHash160,
53    /// The cost for a Bip13ScriptHash signature verification
54    VerifySignatureBip13ScriptHash,
55    /// The cost for a Eddsa25519Hash160 signature verification
56    VerifySignatureEddsa25519Hash160,
57}
58
59impl KnownCostItem {
60    #[inline]
61    pub fn lookup_cost(&self, fee_version: &FeeVersion) -> Credits {
62        match self {
63            KnownCostItem::StorageDiskUsageCreditPerByte => {
64                fee_version.storage.storage_disk_usage_credit_per_byte
65            }
66            KnownCostItem::StorageProcessingCreditPerByte => {
67                fee_version.storage.storage_processing_credit_per_byte
68            }
69            KnownCostItem::StorageLoadCreditPerByte => {
70                fee_version.storage.storage_load_credit_per_byte
71            }
72            KnownCostItem::NonStorageLoadCreditPerByte => {
73                fee_version.storage.non_storage_load_credit_per_byte
74            }
75            KnownCostItem::StorageSeekCost => fee_version.storage.storage_seek_cost,
76            KnownCostItem::FetchIdentityBalanceProcessingCost => {
77                fee_version
78                    .processing
79                    .fetch_identity_balance_processing_cost
80            }
81            KnownCostItem::FetchSingleIdentityKeyProcessingCost => {
82                fee_version
83                    .processing
84                    .fetch_single_identity_key_processing_cost
85            }
86            KnownCostItem::Blake3(size) => {
87                fee_version.hashing.blake3_base
88                    + fee_version.hashing.blake3_per_block * *size as u64
89            }
90            KnownCostItem::SingleSHA256(size) => {
91                fee_version.hashing.single_sha256_base
92                    + fee_version.hashing.sha256_per_block * *size as u64
93            }
94            KnownCostItem::VerifySignatureEcdsaSecp256k1 => {
95                fee_version.signature.verify_signature_ecdsa_secp256k1
96            }
97            KnownCostItem::VerifySignatureBLS12_381 => {
98                fee_version.signature.verify_signature_bls12_381
99            }
100            KnownCostItem::VerifySignatureEcdsaHash160 => {
101                fee_version.signature.verify_signature_ecdsa_hash160
102            }
103            KnownCostItem::VerifySignatureBip13ScriptHash => {
104                fee_version.signature.verify_signature_bip13_script_hash
105            }
106            KnownCostItem::VerifySignatureEddsa25519Hash160 => {
107                fee_version.signature.verify_signature_eddsa25519_hash160
108            }
109        }
110    }
111
112    pub fn lookup_cost_on_epoch<T: EpochCosts>(
113        &self,
114        epoch: &T,
115        cached_fee_version: &CachedEpochIndexFeeVersions,
116    ) -> Credits {
117        let version = epoch.active_fee_version(cached_fee_version);
118        self.lookup_cost(version)
119    }
120}
121
122/// Costs for Epochs
123pub trait EpochCosts {
124    /// Get the closest epoch in the past that has a cost table
125    /// This is where the base costs last changed
126    fn active_fee_version(
127        &self,
128        cached_fee_version: &CachedEpochIndexFeeVersions,
129    ) -> &'static FeeVersion;
130    /// Get the cost for the known cost item
131    fn cost_for_known_cost_item(
132        &self,
133        cached_fee_version: &CachedEpochIndexFeeVersions,
134        cost_item: KnownCostItem,
135    ) -> Credits;
136}
137
138impl EpochCosts for Epoch {
139    /// Get the active fee version for an epoch
140    fn active_fee_version(
141        &self,
142        cached_fee_version: &CachedEpochIndexFeeVersions,
143    ) -> &'static FeeVersion {
144        // If the exact EpochIndex is matching to a FeeVersion update
145        if let Some(fee_version) = cached_fee_version.get(&self.index) {
146            return fee_version;
147        }
148        // else return the FeeVersion at  lower adjacent EpochIndex (if available, else the FeeVersion of first PlatformVersion)
149        cached_fee_version
150            .range(..=self.index)
151            .next_back()
152            .map(|(_, fee_version)| *fee_version)
153            .unwrap_or_else(|| FeeVersion::first())
154    }
155
156    /// Get the cost for the known cost item
157    fn cost_for_known_cost_item(
158        &self,
159        cached_fee_version: &CachedEpochIndexFeeVersions,
160        cost_item: KnownCostItem,
161    ) -> Credits {
162        cost_item.lookup_cost_on_epoch(self, cached_fee_version)
163    }
164}