1use std::fmt::{self, Write};
16
17pub use pallas_primitives::conway::ProtocolParamUpdate;
18
19use crate::RationalNumber;
20
21pub fn display_protocol_parameters_update(update: &ProtocolParamUpdate, prefix: &str) -> Result<String, fmt::Error> {
22 let mut s = String::new();
23
24 fn display_rational(r: &RationalNumber) -> String {
25 format!("{}/{}", r.numerator, r.denominator)
26 }
27
28 fn push_opt<T: fmt::Display>(
29 out: &mut String,
30 is_first: &mut bool,
31 prefix: &str,
32 name: &str,
33 v: &Option<T>,
34 ) -> fmt::Result {
35 if let Some(x) = v {
36 if *is_first {
37 *is_first = false;
38 } else {
39 writeln!(out)?;
40 }
41 write!(out, "{prefix}{name}={x}")?;
42 }
43 Ok(())
44 }
45
46 let mut is_first = true;
47
48 push_opt(&mut s, &mut is_first, prefix, "minfee_a", &update.minfee_a)?;
49
50 push_opt(&mut s, &mut is_first, prefix, "minfee_b", &update.minfee_b)?;
51
52 push_opt(&mut s, &mut is_first, prefix, "max_block_body_size", &update.max_block_body_size)?;
53
54 push_opt(&mut s, &mut is_first, prefix, "max_transaction_size", &update.max_transaction_size)?;
55
56 push_opt(&mut s, &mut is_first, prefix, "max_block_header_size", &update.max_block_header_size)?;
57
58 push_opt(&mut s, &mut is_first, prefix, "key_deposit", &update.key_deposit)?;
59
60 push_opt(&mut s, &mut is_first, prefix, "pool_deposit", &update.pool_deposit)?;
61
62 push_opt(&mut s, &mut is_first, prefix, "maximum_epoch", &update.maximum_epoch)?;
63
64 push_opt(&mut s, &mut is_first, prefix, "desired_number_of_stake_pools", &update.desired_number_of_stake_pools)?;
65
66 let pool_pledge_influence = update.pool_pledge_influence.as_ref().map(display_rational);
67 push_opt(&mut s, &mut is_first, prefix, "pool_pledge_influence", &pool_pledge_influence)?;
68
69 let expansion_rate = update.expansion_rate.as_ref().map(display_rational);
70 push_opt(&mut s, &mut is_first, prefix, "expansion_rate", &expansion_rate)?;
71
72 let treasury_growth_rate = update.treasury_growth_rate.as_ref().map(display_rational);
73 push_opt(&mut s, &mut is_first, prefix, "treasury_growth_rate", &treasury_growth_rate)?;
74
75 push_opt(&mut s, &mut is_first, prefix, "min_pool_cost", &update.min_pool_cost)?;
76
77 push_opt(&mut s, &mut is_first, prefix, "lovelace_per_utxo_byte", &update.ada_per_utxo_byte)?;
78
79 let cost_models = update.cost_models_for_script_languages.as_ref().map(|cost_models| {
81 let mut languages = vec![];
82 if cost_models.plutus_v1.is_some() {
83 languages.push("v1");
84 }
85 if cost_models.plutus_v2.is_some() {
86 languages.push("v2");
87 }
88 if cost_models.plutus_v3.is_some() {
89 languages.push("v3");
90 }
91 languages.join(", ")
92 });
93 push_opt(&mut s, &mut is_first, prefix, "cost_models", &cost_models)?;
94
95 let execution_costs = update
96 .execution_costs
97 .as_ref()
98 .map(|p| format!("{{mem={}, cpu={}}}", display_rational(&p.mem_price), display_rational(&p.step_price)));
99 push_opt(&mut s, &mut is_first, prefix, "execution_costs", &execution_costs)?;
100
101 let max_tx_ex_units = update.max_tx_ex_units.as_ref().map(|u| format!("{{mem={}, cpu={}}}", u.mem, u.steps));
102 push_opt(&mut s, &mut is_first, prefix, "max_tx_ex_units", &max_tx_ex_units)?;
103
104 let max_block_ex_units = update.max_block_ex_units.as_ref().map(|u| format!("{{mem={}, cpu={}}}", u.mem, u.steps));
105 push_opt(&mut s, &mut is_first, prefix, "max_block_ex_units", &max_block_ex_units)?;
106
107 push_opt(&mut s, &mut is_first, prefix, "max_value_size", &update.max_value_size)?;
108
109 push_opt(&mut s, &mut is_first, prefix, "collateral_percentage", &update.collateral_percentage)?;
110
111 push_opt(&mut s, &mut is_first, prefix, "max_collateral_inputs", &update.max_collateral_inputs)?;
112
113 let pool_voting = update.pool_voting_thresholds.as_ref().map(|v| {
114 format!(
115 "\n{p} ├─ committee (normal) {cn}\
116 \n{p} ├─ committee (no confidence) {cc}\
117 \n{p} ├─ motion of no confidence {mnc}\
118 \n{p} ├─ hard fork {hfi}\
119 \n{p} └─ protocol params (security) {svt}",
120 p = prefix,
121 cn = display_rational(&v.committee_normal),
122 cc = display_rational(&v.committee_no_confidence),
123 mnc = display_rational(&v.motion_no_confidence),
124 hfi = display_rational(&v.hard_fork_initiation),
125 svt = display_rational(&v.security_voting_threshold),
126 )
127 });
128 push_opt(&mut s, &mut is_first, prefix, "pool_voting_thresholds", &pool_voting)?;
129
130 let drep_voting = update.drep_voting_thresholds.as_ref().map(|v| {
131 format!(
132 "\n{p} ├─ committee (normal) {cn}\
133 \n{p} ├─ committee (no confidence) {cc}\
134 \n{p} ├─ motion of no confidence {mnc}\
135 \n{p} ├─ treasury withdrawal {tw}\
136 \n{p} ├─ constitution {uc}\
137 \n{p} ├─ protocol params (network) {ppn}\
138 \n{p} ├─ protocol params (economic) {ppe}\
139 \n{p} ├─ protocol params (technical) {ppt}\
140 \n{p} ├─ protocol params (governance) {ppg}\
141 \n{p} └─ hard fork {hfi}",
142 p = prefix,
143 cn = display_rational(&v.committee_normal),
144 cc = display_rational(&v.committee_no_confidence),
145 mnc = display_rational(&v.motion_no_confidence),
146 tw = display_rational(&v.treasury_withdrawal),
147 uc = display_rational(&v.update_constitution),
148 ppn = display_rational(&v.pp_network_group),
149 ppe = display_rational(&v.pp_economic_group),
150 ppt = display_rational(&v.pp_technical_group),
151 ppg = display_rational(&v.pp_governance_group),
152 hfi = display_rational(&v.hard_fork_initiation),
153 )
154 });
155
156 push_opt(&mut s, &mut is_first, prefix, "drep_voting_thresholds", &drep_voting)?;
157
158 push_opt(&mut s, &mut is_first, prefix, "min_committee_size", &update.min_committee_size)?;
159
160 push_opt(&mut s, &mut is_first, prefix, "committee_term_limit", &update.committee_term_limit)?;
161
162 push_opt(
163 &mut s,
164 &mut is_first,
165 prefix,
166 "governance_action_validity_period",
167 &update.governance_action_validity_period,
168 )?;
169
170 push_opt(&mut s, &mut is_first, prefix, "governance_action_deposit", &update.governance_action_deposit)?;
171
172 push_opt(&mut s, &mut is_first, prefix, "drep_deposit", &update.drep_deposit)?;
173
174 push_opt(&mut s, &mut is_first, prefix, "drep_inactivity_period", &update.drep_inactivity_period)?;
175
176 let minfee_refscript_cost_per_byte = update.minfee_refscript_cost_per_byte.as_ref().map(display_rational);
177 push_opt(&mut s, &mut is_first, prefix, "minfee_refscript_cost_per_byte", &minfee_refscript_cost_per_byte)?;
178
179 Ok(s)
180}