Skip to main content

amaru_kernel/cardano/
protocol_parameters_update.rs

1// Copyright 2025 PRAGMA
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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    // If you don’t want to expand cost models, just mark them as set.
80    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}