1use std::collections::BTreeMap;
16
17use pallas_math::math::{FixedDecimal, FixedPrecision};
18use serde::{Deserialize, Deserializer, Serialize, Serializer};
19
20use crate::{
21 CostModel, CostModels, DRepVotingThresholds, EraHistory, ExUnitPrices, ExUnits, Language, Lovelace, PoolId,
22 PoolVotingThresholds, ProtocolParamUpdate, ProtocolVersion, RationalNumber, Slot, cbor,
23};
24
25mod default;
26pub use default::*;
27
28#[derive(Clone, Debug, PartialEq, Eq)]
32pub struct ProtocolParameters {
33 pub protocol_version: ProtocolVersion,
35
36 pub max_block_body_size: u64,
38 pub max_transaction_size: u64,
39 pub max_block_header_size: u16,
40 pub max_tx_ex_units: ExUnits,
41 pub max_block_ex_units: ExUnits,
42 pub max_value_size: u64,
43 pub max_collateral_inputs: u16,
44
45 pub min_fee_a: Lovelace,
47 pub min_fee_b: u64,
48 pub stake_credential_deposit: Lovelace,
49 pub stake_pool_deposit: Lovelace,
50 pub monetary_expansion_rate: RationalNumber,
51 pub treasury_expansion_rate: RationalNumber,
52 pub min_pool_cost: u64,
53 pub lovelace_per_utxo_byte: Lovelace,
54 pub prices: ExUnitPrices,
55 pub min_fee_ref_script_lovelace_per_byte: RationalNumber,
56 pub max_ref_script_size_per_tx: u32,
57 pub max_ref_script_size_per_block: u32,
58 pub ref_script_cost_stride: u32,
59 pub ref_script_cost_multiplier: RationalNumber,
60
61 pub stake_pool_max_retirement_epoch: u64,
63 pub optimal_stake_pools_count: u16,
64 pub pledge_influence: RationalNumber,
65 pub collateral_percentage: u16,
66 pub cost_models: CostModels,
67
68 pub pool_voting_thresholds: PoolVotingThresholds,
70 pub drep_voting_thresholds: DRepVotingThresholds,
71 pub min_committee_size: u16,
72 pub max_committee_term_length: u64,
73 pub gov_action_lifetime: u64,
74 pub gov_action_deposit: Lovelace,
75 pub drep_deposit: Lovelace,
76 pub drep_expiry: u64,
77}
78
79impl ProtocolParameters {
80 pub fn update(&mut self, u: ProtocolParamUpdate) {
81 #[inline]
82 fn set<T>(field: &mut T, opt: Option<T>) {
83 if let Some(val) = opt {
84 *field = val
85 }
86 }
87 set(&mut self.min_fee_a, u.minfee_a);
88 set(&mut self.min_fee_b, u.minfee_b);
89 set(&mut self.max_block_body_size, u.max_block_body_size);
90 set(&mut self.max_transaction_size, u.max_transaction_size);
91 set(
92 &mut self.max_block_header_size,
93 u.max_block_header_size.map(|x| x as u16),
95 );
96 set(&mut self.stake_credential_deposit, u.key_deposit);
97 set(&mut self.stake_pool_deposit, u.pool_deposit);
98 set(&mut self.stake_pool_max_retirement_epoch, u.maximum_epoch);
99 set(
100 &mut self.optimal_stake_pools_count,
101 u.desired_number_of_stake_pools.map(|x| x as u16),
103 );
104 set(&mut self.pledge_influence, u.pool_pledge_influence);
105 set(&mut self.treasury_expansion_rate, u.expansion_rate);
106 set(&mut self.monetary_expansion_rate, u.treasury_growth_rate);
107 set(&mut self.min_pool_cost, u.min_pool_cost);
108 set(&mut self.lovelace_per_utxo_byte, u.ada_per_utxo_byte);
109 if let Some(cost_models) = u.cost_models_for_script_languages {
110 match Language::PlutusV1 {
117 Language::PlutusV1 => {
118 if let Some(plutus_v1) = cost_models.plutus_v1 {
119 self.cost_models.plutus_v1 = Some(plutus_v1);
120 }
121 }
122 Language::PlutusV2 | Language::PlutusV3 => (),
123 }
124 if let Some(plutus_v2) = cost_models.plutus_v2 {
125 self.cost_models.plutus_v2 = Some(plutus_v2);
126 }
127 if let Some(plutus_v3) = cost_models.plutus_v3 {
128 self.cost_models.plutus_v3 = Some(plutus_v3);
129 }
130 }
131 set(&mut self.prices, u.execution_costs);
132 set(&mut self.max_tx_ex_units, u.max_tx_ex_units);
133 set(&mut self.max_block_ex_units, u.max_block_ex_units);
134 set(&mut self.max_value_size, u.max_value_size);
135 set(
136 &mut self.collateral_percentage,
137 u.collateral_percentage.map(|x| x as u16),
139 );
140 set(
141 &mut self.max_collateral_inputs,
142 u.max_collateral_inputs.map(|x| x as u16),
144 );
145 set(&mut self.pool_voting_thresholds, u.pool_voting_thresholds);
146 set(&mut self.drep_voting_thresholds, u.drep_voting_thresholds);
147 set(
148 &mut self.min_committee_size,
149 u.min_committee_size.map(|x| x as u16),
151 );
152 set(&mut self.max_committee_term_length, u.committee_term_limit);
153 set(&mut self.gov_action_lifetime, u.governance_action_validity_period);
154 set(&mut self.gov_action_deposit, u.governance_action_deposit);
155 set(&mut self.drep_deposit, u.drep_deposit);
156 set(&mut self.drep_expiry, u.drep_inactivity_period);
157 set(&mut self.min_fee_ref_script_lovelace_per_byte, u.minfee_refscript_cost_per_byte);
158 }
159}
160
161fn decode_rationale(d: &mut cbor::Decoder<'_>) -> Result<RationalNumber, cbor::decode::Error> {
162 cbor::allow_tag(d, cbor::Tag::new(30))?;
163 cbor::heterogeneous_array(d, |d, assert_len| {
164 assert_len(2)?;
165 let numerator = d.u64()?;
166 let denominator = d.u64()?;
167 Ok(RationalNumber { numerator, denominator })
168 })
169}
170
171fn decode_protocol_version(d: &mut cbor::Decoder<'_>) -> Result<ProtocolVersion, cbor::decode::Error> {
172 cbor::heterogeneous_array(d, |d, assert_len| {
173 assert_len(2)?;
174 let major = d.u8()?;
175
176 if major > 12 {
178 return Err(cbor::decode::Error::message("invalid protocol version's major: too high"));
179 }
180 Ok((major as u64, d.u64()?))
181 })
182}
183
184impl<'b, C> cbor::decode::Decode<'b, C> for ProtocolParameters {
185 fn decode(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
186 d.array()?;
187 let min_fee_a = d.u64()?;
188 let min_fee_b = d.u64()?;
189 let max_block_body_size = d.u64()?;
190 let max_transaction_size = d.u64()?;
191 let max_block_header_size = d.u16()?;
192 let stake_credential_deposit = d.u64()?;
193 let stake_pool_deposit = d.u64()?;
194 let stake_pool_max_retirement_epoch = d.u64()?;
195 let optimal_stake_pools_count = d.u16()?;
196 let pledge_influence = decode_rationale(d)?;
197 let monetary_expansion_rate = decode_rationale(d)?;
198 let treasury_expansion_rate = decode_rationale(d)?;
199 let protocol_version = decode_protocol_version(d)?;
200 let min_pool_cost = d.u64()?;
201 let lovelace_per_utxo_byte = d.u64()?;
202
203 let mut plutus_v1 = None;
204 let mut plutus_v2 = None;
205 let mut plutus_v3 = None;
206 let i = d.map_iter_with::<C, u8, CostModel>(ctx)?;
207 for item in i {
208 let (k, v) = item?;
209 match k {
210 0 => {
211 plutus_v1 = Some(v);
212 }
213 1 => {
214 plutus_v2 = Some(v);
215 }
216 2 => {
217 plutus_v3 = Some(v);
218 }
219 _ => unreachable!("unexpected language version: {k}"),
220 }
221 }
222 let prices = d.decode_with(ctx)?;
223 let max_tx_ex_units = d.decode_with(ctx)?;
224 let max_block_ex_units = d.decode_with(ctx)?;
225 let max_value_size = d.u64()?;
226 let collateral_percentage = d.u16()?;
227 let max_collateral_inputs = d.u16()?;
228 let pool_voting_thresholds = d.decode_with(ctx)?;
229 let drep_voting_thresholds = d.decode_with(ctx)?;
230 let min_committee_size = d.u16()?;
231 let max_committee_term_length = d.u64()?;
232 let gov_action_lifetime = d.u64()?;
233 let gov_action_deposit = d.u64()?;
234 let drep_deposit = d.u64()?;
235 let drep_expiry = d.decode_with(ctx)?;
236 let min_fee_ref_script_lovelace_per_byte = decode_rationale(d)?;
237
238 Ok(ProtocolParameters {
239 protocol_version,
240 min_fee_a,
241 min_fee_b,
242 max_block_body_size,
243 max_transaction_size,
244 max_block_header_size,
245 stake_credential_deposit,
246 stake_pool_deposit,
247 stake_pool_max_retirement_epoch,
248 optimal_stake_pools_count,
249 pledge_influence,
250 monetary_expansion_rate,
251 treasury_expansion_rate,
252 min_pool_cost,
253 lovelace_per_utxo_byte,
254 cost_models: CostModels { plutus_v1, plutus_v2, plutus_v3 },
255 prices,
256 max_tx_ex_units,
257 max_block_ex_units,
258 max_value_size,
259 collateral_percentage,
260 max_collateral_inputs,
261 pool_voting_thresholds,
262 drep_voting_thresholds,
263 min_committee_size,
264 max_committee_term_length,
265 gov_action_lifetime,
266 gov_action_deposit,
267 drep_deposit,
268 drep_expiry,
269 min_fee_ref_script_lovelace_per_byte,
270 max_ref_script_size_per_tx: 200 * 1024, max_ref_script_size_per_block: 1024 * 1024, ref_script_cost_stride: 25600, ref_script_cost_multiplier: RationalNumber { numerator: 12, denominator: 10 }, })
275 }
276}
277
278fn encode_rationale<W: cbor::encode::Write>(
279 e: &mut cbor::Encoder<W>,
280 rat: &RationalNumber,
281) -> Result<(), cbor::encode::Error<W::Error>> {
282 e.tag(cbor::Tag::new(30))?;
283 e.array(2)?;
284
285 e.u64(rat.numerator)?;
286 e.u64(rat.denominator)?;
287 Ok(())
288}
289
290fn encode_protocol_version<W: cbor::encode::Write>(
291 e: &mut cbor::Encoder<W>,
292 v: &ProtocolVersion,
293) -> Result<(), cbor::encode::Error<W::Error>> {
294 e.array(2)?;
295 e.u64(v.0)?;
296 e.u64(v.1)?;
297 Ok(())
298}
299
300impl<C> cbor::encode::Encode<C> for ProtocolParameters {
301 fn encode<W: cbor::encode::Write>(
302 &self,
303 e: &mut cbor::Encoder<W>,
304 ctx: &mut C,
305 ) -> Result<(), cbor::encode::Error<W::Error>> {
306 e.array(31)?;
307 e.u64(self.min_fee_a)?;
308 e.u64(self.min_fee_b)?;
309 e.u64(self.max_block_body_size)?;
310 e.u64(self.max_transaction_size)?;
311 e.u16(self.max_block_header_size)?;
312 e.u64(self.stake_credential_deposit)?;
313 e.u64(self.stake_pool_deposit)?;
314 e.u64(self.stake_pool_max_retirement_epoch)?;
315 e.u16(self.optimal_stake_pools_count)?;
316 encode_rationale(e, &self.pledge_influence)?;
317 encode_rationale(e, &self.monetary_expansion_rate)?;
318 encode_rationale(e, &self.treasury_expansion_rate)?;
319 encode_protocol_version(e, &self.protocol_version)?;
320 e.u64(self.min_pool_cost)?;
321 e.u64(self.lovelace_per_utxo_byte)?;
322
323 let mut count = 0;
324 if self.cost_models.plutus_v1.is_some() {
325 count += 1;
326 }
327 if self.cost_models.plutus_v2.is_some() {
328 count += 1;
329 }
330 if self.cost_models.plutus_v3.is_some() {
331 count += 1;
332 }
333 e.map(count)?;
334 if let Some(v) = self.cost_models.plutus_v1.as_ref() {
335 e.u8(0)?;
336 e.encode_with(v, ctx)?;
337 }
338 if let Some(v) = self.cost_models.plutus_v2.as_ref() {
339 e.u8(1)?;
340 e.encode_with(v, ctx)?;
341 }
342 if let Some(v) = self.cost_models.plutus_v3.as_ref() {
343 e.u8(2)?;
344 e.encode_with(v, ctx)?;
345 }
346
347 e.encode_with(&self.prices, ctx)?;
348 e.encode_with(self.max_tx_ex_units, ctx)?;
349 e.encode_with(self.max_block_ex_units, ctx)?;
350
351 e.u64(self.max_value_size)?;
352 e.u16(self.collateral_percentage)?;
353 e.u16(self.max_collateral_inputs)?;
354
355 e.encode_with(&self.pool_voting_thresholds, ctx)?;
356 e.encode_with(&self.drep_voting_thresholds, ctx)?;
357
358 e.u16(self.min_committee_size)?;
359 e.u64(self.max_committee_term_length)?;
360 e.u64(self.gov_action_lifetime)?;
361 e.u64(self.gov_action_deposit)?;
362 e.u64(self.drep_deposit)?;
363 e.encode_with(self.drep_expiry, ctx)?;
364 encode_rationale(e, &self.min_fee_ref_script_lovelace_per_byte)?;
365
366 Ok(())
367 }
368}
369
370#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
371pub struct GlobalParameters {
372 pub consensus_security_param: usize,
376
377 pub epoch_length_scale_factor: usize,
379
380 pub active_slot_coeff_inverse: usize,
382
383 pub max_lovelace_supply: Lovelace,
385
386 pub slots_per_kes_period: u64,
388
389 pub max_kes_evolution: u8,
392
393 pub epoch_length: usize,
395
396 pub stability_window: Slot,
398
399 pub randomness_stabilization_window: u64,
402
403 pub system_start: u64,
405}
406
407#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
409pub struct ConsensusParameters {
410 randomness_stabilization_window: u64,
411 slots_per_kes_period: u64,
412 max_kes_evolution: u64,
413 active_slot_coeff: SerializedFixedDecimal,
414 era_history: EraHistory,
415 ocert_counters: BTreeMap<PoolId, u64>,
416}
417
418#[derive(Clone, Debug, PartialEq)]
419struct SerializedFixedDecimal(FixedDecimal);
420
421impl Serialize for SerializedFixedDecimal {
422 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
423 where
424 S: Serializer,
425 {
426 serializer.serialize_str(&self.0.to_string())
427 }
428}
429
430impl<'a> Deserialize<'a> for SerializedFixedDecimal {
431 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
432 where
433 D: Deserializer<'a>,
434 {
435 let s = String::deserialize(deserializer)?;
436 FixedDecimal::from_str(&s, s.len() as u64).map(SerializedFixedDecimal).map_err(serde::de::Error::custom)
437 }
438}
439
440impl ConsensusParameters {
441 pub fn new(
443 global_parameters: GlobalParameters,
444 era_history: &EraHistory,
445 ocert_counters: BTreeMap<PoolId, u64>,
446 ) -> Self {
447 Self::create(
448 global_parameters.randomness_stabilization_window,
449 global_parameters.slots_per_kes_period,
450 global_parameters.max_kes_evolution as u64,
451 1f64 / global_parameters.active_slot_coeff_inverse as f64,
452 era_history,
453 ocert_counters,
454 )
455 }
456
457 pub fn create(
459 randomness_stabilization_window: u64,
460 slots_per_kes_period: u64,
461 max_kes_evolution: u64,
462 active_slot_coeff: f64,
463 era_history: &EraHistory,
464 ocert_counters: BTreeMap<PoolId, u64>,
465 ) -> ConsensusParameters {
466 let active_slot_coeff = FixedDecimal::from((active_slot_coeff * 100.0) as u64) / FixedDecimal::from(100u64);
467 Self {
468 randomness_stabilization_window,
469 slots_per_kes_period,
470 max_kes_evolution,
471 active_slot_coeff: SerializedFixedDecimal(active_slot_coeff),
472 era_history: era_history.clone(),
473 ocert_counters,
474 }
475 }
476
477 pub fn era_history(&self) -> &EraHistory {
478 &self.era_history
479 }
480
481 pub fn randomness_stabilization_window(&self) -> u64 {
482 self.randomness_stabilization_window
483 }
484
485 pub fn slot_to_kes_period(&self, slot: Slot) -> u64 {
486 u64::from(slot) / self.slots_per_kes_period
487 }
488
489 pub fn max_kes_evolutions(&self) -> u64 {
490 self.max_kes_evolution
491 }
492
493 pub fn latest_opcert_sequence_number(&self, pool_id: &PoolId) -> Option<u64> {
494 self.ocert_counters.get(pool_id).copied()
495 }
496
497 pub fn active_slot_coeff(&self) -> FixedDecimal {
498 self.active_slot_coeff.0.clone()
499 }
500}
501
502#[cfg(any(test, feature = "test-utils"))]
503pub use tests::*;
504
505#[cfg(any(test, feature = "test-utils"))]
506mod tests {
507 use proptest::{collection, option, prelude::*};
508
509 use super::PREPROD_INITIAL_PROTOCOL_PARAMETERS;
510 #[cfg(not(target_os = "windows"))]
511 use crate::prop_cbor_roundtrip;
512 use crate::{
513 CostModel, CostModels, DRepVotingThresholds, ExUnitPrices, ExUnits, GovernanceAction, Hash, KeyValuePairs,
514 Lovelace, Nullable, PoolVotingThresholds, ProposalId, ProtocolParamUpdate, ProtocolParameters, ProtocolVersion,
515 RewardAccount, Set, StakeCredential, any_constitution, any_hash28, any_nullable, any_proposal_id,
516 any_rational_number, any_reward_account, any_stake_credential, size::SCRIPT,
517 };
518
519 #[cfg(not(target_os = "windows"))]
520 prop_cbor_roundtrip!(ProtocolParameters, any_protocol_parameter());
521
522 prop_compose! {
523 pub fn any_ex_units()(
524 mem in any::<u64>(),
525 steps in any::<u64>(),
526 ) -> ExUnits {
527 ExUnits {
528 mem,
529 steps,
530 }
531 }
532 }
533
534 prop_compose! {
535 pub fn any_ex_units_prices()(
536 mem_price in any_rational_number(),
537 step_price in any_rational_number(),
538 ) -> ExUnitPrices {
539 ExUnitPrices {
540 mem_price,
541 step_price,
542 }
543 }
544 }
545
546 prop_compose! {
547 pub fn any_protocol_version()(
548 major in any::<u8>(),
549 minor in any::<u64>(),
550 ) -> ProtocolVersion {
551 ((major % 13) as u64, minor)
552 }
553 }
554
555 prop_compose! {
556 pub fn any_drep_voting_thresholds()(
557 motion_no_confidence in any_rational_number(),
558 committee_normal in any_rational_number(),
559 committee_no_confidence in any_rational_number(),
560 update_constitution in any_rational_number(),
561 hard_fork_initiation in any_rational_number(),
562 pp_network_group in any_rational_number(),
563 pp_economic_group in any_rational_number(),
564 pp_technical_group in any_rational_number(),
565 pp_governance_group in any_rational_number(),
566 treasury_withdrawal in any_rational_number(),
567 ) -> DRepVotingThresholds {
568 DRepVotingThresholds {
569 motion_no_confidence,
570 committee_normal,
571 committee_no_confidence,
572 update_constitution,
573 hard_fork_initiation,
574 pp_network_group,
575 pp_economic_group,
576 pp_technical_group,
577 pp_governance_group,
578 treasury_withdrawal,
579 }
580 }
581 }
582
583 prop_compose! {
584 pub fn any_pool_voting_thresholds()(
585 motion_no_confidence in any_rational_number(),
586 committee_normal in any_rational_number(),
587 committee_no_confidence in any_rational_number(),
588 hard_fork_initiation in any_rational_number(),
589 security_voting_threshold in any_rational_number(),
590 ) -> PoolVotingThresholds {
591 PoolVotingThresholds {
592 motion_no_confidence,
593 committee_normal,
594 committee_no_confidence,
595 hard_fork_initiation,
596 security_voting_threshold,
597 }
598 }
599 }
600
601 prop_compose! {
602 pub fn any_cost_model()(
603 machine_cost in option::of(any::<i64>()),
604 some_builtin in option::of(any::<i64>()),
605 some_other_builtin in option::of(any::<i64>()),
606 ) -> CostModel {
607 vec![
608 machine_cost,
609 some_builtin,
610 some_other_builtin,
611 ]
612 .into_iter()
613 .flatten()
614 .collect()
615 }
616 }
617
618 prop_compose! {
619 pub fn any_cost_models()(
620 plutus_v1 in option::of(any_cost_model()),
621 plutus_v2 in option::of(any_cost_model()),
622 plutus_v3 in option::of(any_cost_model()),
623 ) -> CostModels {
624 CostModels {
625 plutus_v1,
626 plutus_v2,
627 plutus_v3,
628 }
629 }
630 }
631
632 prop_compose! {
633 pub fn any_ex_unit_prices()(
634 mem_price in any_rational_number(),
635 step_price in any_rational_number(),
636 ) -> ExUnitPrices {
637 ExUnitPrices {
638 mem_price,
639 step_price,
640 }
641 }
642 }
643
644 prop_compose! {
645 pub fn any_protocol_params_update()(
646 minfee_a in option::of(any::<u64>()),
647 minfee_b in option::of(any::<u64>()),
648 max_block_body_size in option::of(any::<u64>()),
649 max_transaction_size in option::of(any::<u64>()),
650 max_block_header_size in option::of(any::<u64>()),
651 key_deposit in option::of(any::<Lovelace>()),
652 pool_deposit in option::of(any::<Lovelace>()),
653 maximum_epoch in option::of(any::<u64>()),
654 desired_number_of_stake_pools in option::of(any::<u64>()),
655 pool_pledge_influence in option::of(any_rational_number()),
656 expansion_rate in option::of(any_rational_number()),
657 treasury_growth_rate in option::of(any_rational_number()),
658 min_pool_cost in option::of(any::<Lovelace>()),
659 ada_per_utxo_byte in option::of(any::<Lovelace>()),
660 cost_models_for_script_languages in option::of(any_cost_models()),
661 execution_costs in option::of(any_ex_unit_prices()),
662 max_tx_ex_units in option::of(any_ex_units()),
663 max_block_ex_units in option::of(any_ex_units()),
664 max_value_size in option::of(any::<u64>()),
665 collateral_percentage in option::of(any::<u64>()),
666 max_collateral_inputs in option::of(any::<u64>()),
667 pool_voting_thresholds in option::of(any_pool_voting_thresholds()),
668 drep_voting_thresholds in option::of(any_drep_voting_thresholds()),
669 min_committee_size in option::of(any::<u64>()),
670 committee_term_limit in option::of(any::<u64>()),
671 governance_action_validity_period in option::of(any::<u64>()),
672 governance_action_deposit in option::of(any::<Lovelace>()),
673 drep_deposit in option::of(any::<Lovelace>()),
674 drep_inactivity_period in option::of(any::<u64>()),
675 minfee_refscript_cost_per_byte in option::of(any_rational_number()),
676 ) -> ProtocolParamUpdate {
677 ProtocolParamUpdate {
678 minfee_a,
679 minfee_b,
680 max_block_body_size,
681 max_transaction_size,
682 max_block_header_size,
683 key_deposit,
684 pool_deposit,
685 maximum_epoch,
686 desired_number_of_stake_pools,
687 pool_pledge_influence,
688 expansion_rate,
689 treasury_growth_rate,
690 min_pool_cost,
691 ada_per_utxo_byte,
692 cost_models_for_script_languages,
693 execution_costs,
694 max_tx_ex_units,
695 max_block_ex_units,
696 max_value_size,
697 collateral_percentage,
698 max_collateral_inputs,
699 pool_voting_thresholds,
700 drep_voting_thresholds,
701 min_committee_size,
702 committee_term_limit,
703 governance_action_validity_period,
704 governance_action_deposit,
705 drep_deposit,
706 drep_inactivity_period,
707 minfee_refscript_cost_per_byte,
708 }
709 }
710 }
711
712 pub fn any_gov_action() -> impl Strategy<Value = GovernanceAction> {
713 prop_compose! {
714 fn any_parent_proposal_id()(
715 proposal_id in option::of(any_proposal_id()),
716 ) -> Nullable<ProposalId> {
717 Nullable::from(proposal_id)
718 }
719 }
720
721 prop_compose! {
722 fn any_action_parameter_change()(
723 parent_proposal_id in any_parent_proposal_id(),
724 pparams in any_protocol_params_update(),
725 guardrails in any_guardrails_script(),
726 ) -> GovernanceAction {
727 GovernanceAction::ParameterChange(parent_proposal_id, Box::new(pparams), guardrails)
728 }
729 }
730
731 prop_compose! {
732 fn any_hardfork_initiation()(
733 parent_proposal_id in any_parent_proposal_id(),
734 protocol_version in any_protocol_version(),
735 ) -> GovernanceAction {
736 GovernanceAction::HardForkInitiation(parent_proposal_id, protocol_version)
737 }
738 }
739
740 prop_compose! {
741 #[allow(clippy::unwrap_used)]
742 fn any_treasury_withdrawals()(
743 withdrawals in collection::vec(any_withdrawal(), 0..3),
744 guardrails in any_guardrails_script(),
745 ) -> GovernanceAction {
746 GovernanceAction::TreasuryWithdrawals(
747 KeyValuePairs::try_from(withdrawals).unwrap().as_pallas(),
748 guardrails
749 )
750 }
751 }
752
753 prop_compose! {
754 fn any_no_confidence()(
755 parent_proposal_id in any_parent_proposal_id(),
756 ) -> GovernanceAction {
757 GovernanceAction::NoConfidence(parent_proposal_id)
758 }
759 }
760
761 prop_compose! {
762 fn any_committee_registration()(
763 credential in any_stake_credential(),
764 epoch in any::<u64>(),
765 ) -> (StakeCredential, u64) {
766 (credential, epoch)
767 }
768 }
769
770 prop_compose! {
771 #[allow(clippy::unwrap_used)]
772 fn any_committee_update()(
773 parent_proposal_id in any_parent_proposal_id(),
774 to_remove in collection::btree_set(any_stake_credential(), 0..3),
775 to_add in collection::vec(any_committee_registration(), 0..3),
776 quorum in any_rational_number(),
777 ) -> GovernanceAction {
778 GovernanceAction::UpdateCommittee(
779 parent_proposal_id,
780 Set::from(to_remove.into_iter().collect::<Vec<_>>()),
781 KeyValuePairs::try_from(to_add).unwrap().as_pallas(),
782 quorum
783 )
784 }
785 }
786
787 prop_compose! {
788 fn any_new_constitution()(
789 parent_proposal_id in any_parent_proposal_id(),
790 constitution in any_constitution(),
791 ) -> GovernanceAction {
792 GovernanceAction::NewConstitution(parent_proposal_id, constitution)
793 }
794 }
795
796 fn any_nice_poll() -> impl Strategy<Value = GovernanceAction> {
797 prop::strategy::Just(GovernanceAction::Information)
798 }
799
800 prop_oneof![
801 any_action_parameter_change(),
802 any_hardfork_initiation(),
803 any_treasury_withdrawals(),
804 any_no_confidence(),
805 any_committee_update(),
806 any_new_constitution(),
807 any_nice_poll(),
808 ]
809 }
810
811 prop_compose! {
812 pub fn any_withdrawal()(
813 reward_account in any_reward_account(),
814 amount in any::<Lovelace>(),
815 ) -> (RewardAccount, Lovelace) {
816 (reward_account, amount)
817 }
818 }
819
820 pub fn any_guardrails_script() -> impl Strategy<Value = Nullable<Hash<SCRIPT>>> {
821 any_nullable(any_hash28())
822 }
823
824 prop_compose! {
825 pub fn any_protocol_parameter()(
826 protocol_version in any_protocol_version(),
827 max_block_body_size in any::<u64>(),
828 max_transaction_size in any::<u64>(),
829 max_block_header_size in any::<u16>(),
830 max_tx_ex_units in any_ex_units(),
831 max_block_ex_units in any_ex_units(),
832 max_value_size in any::<u64>(),
833 max_collateral_inputs in any::<u16>(),
834 min_fee_a in any::<Lovelace>(),
835 min_fee_b in any::<Lovelace>(),
836 stake_credential_deposit in any::<Lovelace>(),
837 stake_pool_deposit in any::<Lovelace>(),
838 monetary_expansion_rate in any_rational_number(),
839 treasury_expansion_rate in any_rational_number(),
840 min_pool_cost in any::<Lovelace>(),
841 lovelace_per_utxo_byte in any::<Lovelace>(),
842 prices in any_ex_units_prices(),
843 min_fee_ref_script_lovelace_per_byte in any_rational_number(),
844 stake_pool_max_retirement_epoch in any::<u64>(),
845 optimal_stake_pools_count in any::<u16>(),
846 pledge_influence in any_rational_number(),
847 collateral_percentage in any::<u16>(),
848 cost_models in any_cost_models(),
849 pool_voting_thresholds in any_pool_voting_thresholds(),
850 drep_voting_thresholds in any_drep_voting_thresholds(),
851 min_committee_size in any::<u16>(),
852 max_committee_term_length in any::<u64>(),
853 gov_action_lifetime in any::<u64>(),
854 gov_action_deposit in any::<Lovelace>(),
855 drep_deposit in any::<Lovelace>(),
856 drep_expiry in any::<u64>(),
857 ) -> ProtocolParameters {
858 let default = &*PREPROD_INITIAL_PROTOCOL_PARAMETERS;
859 ProtocolParameters {
860 protocol_version,
861 max_block_body_size,
862 max_transaction_size,
863 max_block_header_size,
864 max_tx_ex_units,
865 max_block_ex_units,
866 max_value_size,
867 max_collateral_inputs,
868 min_fee_a,
869 min_fee_b,
870 stake_credential_deposit,
871 stake_pool_deposit,
872 monetary_expansion_rate,
873 treasury_expansion_rate,
874 min_pool_cost,
875 lovelace_per_utxo_byte,
876 prices,
877 min_fee_ref_script_lovelace_per_byte,
878 max_ref_script_size_per_tx: default.max_ref_script_size_per_tx,
879 max_ref_script_size_per_block: default.max_ref_script_size_per_block,
880 ref_script_cost_stride: default.ref_script_cost_stride,
881 ref_script_cost_multiplier: default.ref_script_cost_multiplier.clone(),
882 stake_pool_max_retirement_epoch,
883 optimal_stake_pools_count,
884 pledge_influence,
885 collateral_percentage,
886 cost_models,
887 pool_voting_thresholds,
888 drep_voting_thresholds,
889 min_committee_size,
890 max_committee_term_length,
891 gov_action_lifetime,
892 gov_action_deposit,
893 drep_deposit,
894 drep_expiry,
895 }
896 }
897 }
898}