soroban_simulation/
network_config.rs1use anyhow::{anyhow, bail, Context, Result};
2use soroban_env_host::budget::Budget;
3use soroban_env_host::fees::{
4 compute_rent_write_fee_per_1kb, FeeConfiguration, RentFeeConfiguration,
5 RentWriteFeeConfiguration,
6};
7use soroban_env_host::storage::SnapshotSource;
8use soroban_env_host::xdr::{
9 ConfigSettingEntry, ConfigSettingId, ContractCostParams, LedgerEntry, LedgerEntryData,
10 LedgerKey, LedgerKeyConfigSetting,
11};
12use soroban_env_host::LedgerInfo;
13use std::rc::Rc;
14
15const CPU_SHADOW_LIMIT_FACTOR: u64 = 10;
16const MEMORY_SHADOW_LIMIT_FACTOR: u64 = 2;
17
18#[derive(Debug, Default, PartialEq, Eq)]
22pub struct NetworkConfig {
23 pub fee_configuration: FeeConfiguration,
24 pub rent_fee_configuration: RentFeeConfiguration,
25 pub tx_max_instructions: i64,
26 pub tx_memory_limit: u32,
27 pub cpu_cost_params: ContractCostParams,
28 pub memory_cost_params: ContractCostParams,
29 pub min_temp_entry_ttl: u32,
31 pub min_persistent_entry_ttl: u32,
32 pub max_entry_ttl: u32,
33}
34
35fn load_configuration_setting(
36 snapshot: &impl SnapshotSource,
37 setting_id: ConfigSettingId,
38) -> Result<ConfigSettingEntry> {
39 let key = Rc::new(LedgerKey::ConfigSetting(LedgerKeyConfigSetting {
40 config_setting_id: setting_id,
41 }));
42 let (entry, _) = snapshot
43 .get(&key)?
44 .ok_or_else(|| anyhow!("setting {setting_id:?} is not present in the snapshot"))?;
45 if let LedgerEntry {
46 data: LedgerEntryData::ConfigSetting(cs),
47 ..
48 } = &*entry
49 {
50 Ok(cs.clone())
51 } else {
52 bail!("encountered unexpected config setting ledger entry {entry:#?}");
53 }
54}
55
56macro_rules! load_setting {
57 ($snapshot:ident, $enum_variant:ident) => {
58 match load_configuration_setting($snapshot, ConfigSettingId::$enum_variant)? {
59 ConfigSettingEntry::$enum_variant(setting) => setting,
60 _ => bail!(
61 "loaded unexpected config setting entry for {:?} key",
62 stringify!($enum_variant)
63 ),
64 }
65 };
66}
67
68impl NetworkConfig {
69 pub fn load_from_snapshot(
74 snapshot: &impl SnapshotSource,
75 bucket_list_size: u64,
76 ) -> Result<Self> {
77 let compute = load_setting!(snapshot, ContractComputeV0);
78 let ledger_cost = load_setting!(snapshot, ContractLedgerCostV0);
79 let ledger_cost_ext = load_setting!(snapshot, ContractLedgerCostExtV0);
80 let historical_data = load_setting!(snapshot, ContractHistoricalDataV0);
81 let events = load_setting!(snapshot, ContractEventsV0);
82 let bandwidth = load_setting!(snapshot, ContractBandwidthV0);
83 let state_archival = load_setting!(snapshot, StateArchival);
84 let cpu_cost_params = load_setting!(snapshot, ContractCostParamsCpuInstructions);
85 let memory_cost_params = load_setting!(snapshot, ContractCostParamsMemoryBytes);
86
87 let write_fee_configuration = RentWriteFeeConfiguration {
88 state_target_size_bytes: ledger_cost.soroban_state_target_size_bytes,
89 rent_fee_1kb_state_size_low: ledger_cost.rent_fee1_kb_soroban_state_size_low,
90 rent_fee_1kb_state_size_high: ledger_cost.rent_fee1_kb_soroban_state_size_high,
91 state_size_rent_fee_growth_factor: ledger_cost.soroban_state_rent_fee_growth_factor,
92 };
93 let bucket_list_size: i64 = bucket_list_size
94 .try_into()
95 .context("bucket list size exceeds i64::MAX")?;
96 let rent_fee_per_1kb =
97 compute_rent_write_fee_per_1kb(bucket_list_size, &write_fee_configuration);
98
99 let fee_configuration = FeeConfiguration {
100 fee_per_instruction_increment: compute.fee_rate_per_instructions_increment,
101 fee_per_disk_read_entry: ledger_cost.fee_disk_read_ledger_entry,
102 fee_per_write_entry: ledger_cost.fee_write_ledger_entry,
103 fee_per_disk_read_1kb: ledger_cost.fee_disk_read1_kb,
104 fee_per_write_1kb: ledger_cost_ext.fee_write1_kb,
105 fee_per_historical_1kb: historical_data.fee_historical1_kb,
106 fee_per_contract_event_1kb: events.fee_contract_events1_kb,
107 fee_per_transaction_size_1kb: bandwidth.fee_tx_size1_kb,
108 };
109 let rent_fee_configuration = RentFeeConfiguration {
110 fee_per_rent_1kb: rent_fee_per_1kb,
111 fee_per_write_1kb: ledger_cost_ext.fee_write1_kb,
112 fee_per_write_entry: ledger_cost.fee_write_ledger_entry,
113 persistent_rent_rate_denominator: state_archival.persistent_rent_rate_denominator,
114 temporary_rent_rate_denominator: state_archival.temp_rent_rate_denominator,
115 };
116
117 Ok(Self {
118 fee_configuration,
119 rent_fee_configuration,
120 cpu_cost_params,
121 memory_cost_params,
122 min_temp_entry_ttl: state_archival.min_temporary_ttl,
123 min_persistent_entry_ttl: state_archival.min_persistent_ttl,
124 tx_max_instructions: compute.tx_max_instructions,
125 tx_memory_limit: compute.tx_memory_limit,
126 max_entry_ttl: state_archival.max_entry_ttl,
127 })
128 }
129
130 pub fn fill_config_fields_in_ledger_info(&self, ledger_info: &mut LedgerInfo) {
136 ledger_info.min_persistent_entry_ttl = self.min_persistent_entry_ttl;
137 ledger_info.min_temp_entry_ttl = self.min_temp_entry_ttl;
138 ledger_info.max_entry_ttl = self.max_entry_ttl;
139 }
140
141 pub(crate) fn create_budget(&self) -> Result<Budget> {
142 let cpu_shadow_limit =
143 (self.tx_max_instructions as u64).saturating_mul(CPU_SHADOW_LIMIT_FACTOR);
144 let mem_shadow_limit =
145 (self.tx_memory_limit as u64).saturating_mul(MEMORY_SHADOW_LIMIT_FACTOR);
146 Budget::try_from_configs_with_shadow_limits(
147 self.tx_max_instructions as u64,
148 self.tx_memory_limit as u64,
149 cpu_shadow_limit,
150 mem_shadow_limit,
151 self.cpu_cost_params.clone(),
152 self.memory_cost_params.clone(),
153 )
154 .context("cannot create budget from network configuration")
155 }
156}