diff --git a/pallas-applying/src/shelley_ma.rs b/pallas-applying/src/shelley_ma.rs index 098ef063..036ef178 100644 --- a/pallas-applying/src/shelley_ma.rs +++ b/pallas-applying/src/shelley_ma.rs @@ -408,7 +408,8 @@ fn compute_script_hash(script: &NativeScript) -> PolicyId { pallas_crypto::hash::Hasher::<224>::hash(&payload) } -// Checks all certificates in order, and counts the relevant ones for computing deposits. +// Checks all certificates in order, and counts the relevant ones for computing +// deposits. #[allow(clippy::too_many_arguments)] fn check_certificates( cert_opt: &Option>, @@ -585,13 +586,13 @@ fn check_pool_retirement( pool_hash: &PoolKeyhash, repoch: &Epoch, cepoch: &Epoch, - emax: &u32, + emax: &Epoch, ps: &mut PState, ) -> ValidationResult { if !ps.pool_params.contains_key(pool_hash) { return Err(ShelleyMA(PoolNotRegistered)); } - if (*cepoch < *repoch) & (*repoch <= *cepoch + *emax as u64) { + if (*cepoch < *repoch) & (*repoch <= *cepoch + *emax) { ps.retiring.insert(*pool_hash, *repoch); Ok(()) } else { diff --git a/pallas-applying/src/utils/environment.rs b/pallas-applying/src/utils/environment.rs index 84b49cbf..b9a04dda 100644 --- a/pallas-applying/src/utils/environment.rs +++ b/pallas-applying/src/utils/environment.rs @@ -5,7 +5,7 @@ use pallas_primitives::{ Coin, CostMdls, ExUnitPrices, ExUnits, Nonce, ProtocolVersion, RationalNumber, UnitInterval, }, babbage::CostMdls as BabbageCostMdls, - conway::CostMdls as ConwayCostMdls, + conway::{CostMdls as ConwayCostMdls, Epoch}, }; #[allow(clippy::large_enum_variant)] @@ -81,7 +81,7 @@ pub struct ShelleyProtParams { pub min_pool_cost: Coin, pub expansion_rate: UnitInterval, pub treasury_growth_rate: UnitInterval, - pub maximum_epoch: u32, + pub maximum_epoch: Epoch, pub pool_pledge_influence: RationalNumber, pub decentralization_constant: UnitInterval, pub extra_entropy: Nonce, @@ -109,7 +109,7 @@ pub struct AlonzoProtParams { pub max_collateral_inputs: u32, pub expansion_rate: UnitInterval, pub treasury_growth_rate: UnitInterval, - pub maximum_epoch: u32, + pub maximum_epoch: Epoch, pub pool_pledge_influence: RationalNumber, pub decentralization_constant: UnitInterval, pub extra_entropy: Nonce, @@ -137,7 +137,7 @@ pub struct BabbageProtParams { pub max_collateral_inputs: u32, pub expansion_rate: UnitInterval, pub treasury_growth_rate: UnitInterval, - pub maximum_epoch: u32, + pub maximum_epoch: Epoch, pub pool_pledge_influence: RationalNumber, pub decentralization_constant: UnitInterval, pub extra_entropy: Nonce, @@ -165,16 +165,16 @@ pub struct ConwayProtParams { pub max_collateral_inputs: u32, pub expansion_rate: UnitInterval, pub treasury_growth_rate: UnitInterval, - pub maximum_epoch: u32, + pub maximum_epoch: Epoch, pub pool_pledge_influence: RationalNumber, pub pool_voting_thresholds: pallas_primitives::conway::PoolVotingThresholds, pub drep_voting_thresholds: pallas_primitives::conway::DRepVotingThresholds, pub min_committee_size: u64, - pub committee_term_limit: u32, - pub governance_action_validity_period: u32, + pub committee_term_limit: Epoch, + pub governance_action_validity_period: Epoch, pub governance_action_deposit: Coin, pub drep_deposit: Coin, - pub drep_inactivity_period: u32, + pub drep_inactivity_period: Epoch, pub minfee_refscript_cost_per_byte: UnitInterval, } diff --git a/pallas-configs/src/conway.rs b/pallas-configs/src/conway.rs new file mode 100644 index 00000000..924cd562 --- /dev/null +++ b/pallas-configs/src/conway.rs @@ -0,0 +1,110 @@ +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GenesisFile { + pub pool_voting_thresholds: PoolVotingThresholds, + pub d_rep_voting_thresholds: DRepVotingThresholds, + pub committee_min_size: u64, + pub committee_max_term_length: u32, + pub gov_action_lifetime: u32, + pub gov_action_deposit: u64, + pub d_rep_deposit: u64, + pub d_rep_activity: u32, + pub min_fee_ref_script_cost_per_byte: u64, + pub plutus_v3_cost_model: Vec, + pub constitution: Constitution, + pub committee: Committee, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct PoolVotingThresholds { + pub committee_normal: f32, + pub committee_no_confidence: f32, + pub hard_fork_initiation: f32, + pub motion_no_confidence: f32, + pub pp_security_group: f32, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct DRepVotingThresholds { + pub motion_no_confidence: f32, + pub committee_normal: f32, + pub committee_no_confidence: f32, + pub update_to_constitution: f32, + pub hard_fork_initiation: f32, + pub pp_network_group: f32, + pub pp_economic_group: f32, + pub pp_technical_group: f32, + pub pp_gov_group: f32, + pub treasury_withdrawal: f32, +} + +#[derive(Debug, Deserialize)] +pub struct Constitution { + pub anchor: Anchor, + pub script: String, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Anchor { + pub data_hash: String, + pub url: String, +} + +#[derive(Debug, Deserialize)] +pub struct Committee { + pub members: HashMap, + pub threshold: Fraction, +} + +#[derive(Deserialize, Clone, Debug)] +pub struct Fraction { + pub numerator: u64, + pub denominator: u64, +} + +impl From for pallas_primitives::conway::RationalNumber { + fn from(value: Fraction) -> Self { + Self { + numerator: value.numerator, + denominator: value.denominator, + } + } +} + +pub fn from_file(path: &std::path::Path) -> Result { + let file = std::fs::File::open(path)?; + let reader = std::io::BufReader::new(file); + let parsed: GenesisFile = serde_json::from_reader(reader)?; + + Ok(parsed) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn load_test_data_config(network: &str) -> GenesisFile { + let path = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("..") + .join("test_data") + .join(format!("{network}-conway-genesis.json")); + + from_file(&path).unwrap() + } + + #[test] + fn test_preview_json_loads() { + load_test_data_config("preview"); + } + + #[test] + fn test_mainnet_json_loads() { + load_test_data_config("mainnet"); + } +} diff --git a/pallas-configs/src/lib.rs b/pallas-configs/src/lib.rs index 61ddc9b7..28e72446 100644 --- a/pallas-configs/src/lib.rs +++ b/pallas-configs/src/lib.rs @@ -2,4 +2,5 @@ pub mod alonzo; pub mod byron; +pub mod conway; pub mod shelley; diff --git a/pallas-configs/src/shelley.rs b/pallas-configs/src/shelley.rs index 8609d930..e10e6d84 100644 --- a/pallas-configs/src/shelley.rs +++ b/pallas-configs/src/shelley.rs @@ -1,6 +1,6 @@ use num_rational::BigRational; use pallas_crypto::hash::Hash; -use pallas_primitives::conway::RationalNumber; +use pallas_primitives::conway::{Epoch, RationalNumber}; use serde::{Deserialize, Deserializer}; use std::{collections::HashMap, str::FromStr}; @@ -90,7 +90,7 @@ pub struct ProtocolParams { pub pool_deposit: u64, pub n_opt: u32, pub min_pool_cost: u64, - pub e_max: u32, + pub e_max: Epoch, pub extra_entropy: ExtraEntropy, #[serde(deserialize_with = "deserialize_rational")] diff --git a/pallas-primitives/src/conway/model.rs b/pallas-primitives/src/conway/model.rs index 53f978bf..26f739ea 100644 --- a/pallas-primitives/src/conway/model.rs +++ b/pallas-primitives/src/conway/model.rs @@ -604,6 +604,15 @@ pub struct ProtocolParamUpdate { pub minfee_refscript_cost_per_byte: Option, } +#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub struct Update { + #[n(0)] + pub proposed_protocol_parameter_updates: KeyValuePairs, + + #[n(1)] + pub epoch: Epoch, +} + #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct PoolVotingThresholds { pub motion_no_confidence: UnitInterval, diff --git a/pallas-traverse/src/lib.rs b/pallas-traverse/src/lib.rs index 7a9c3ca2..8c68b791 100644 --- a/pallas-traverse/src/lib.rs +++ b/pallas-traverse/src/lib.rs @@ -186,6 +186,7 @@ pub enum MultiEraUpdate<'b> { Byron(u64, Box>), AlonzoCompatible(Box>), Babbage(Box>), + Conway(Box>), } #[derive(Debug, Clone)] diff --git a/pallas-traverse/src/update.rs b/pallas-traverse/src/update.rs index 90c25ef8..b135499d 100644 --- a/pallas-traverse/src/update.rs +++ b/pallas-traverse/src/update.rs @@ -2,7 +2,7 @@ use pallas_codec::minicbor; use paste::paste; use std::{borrow::Cow, ops::Deref}; -use pallas_primitives::{alonzo, babbage, byron}; +use pallas_primitives::{alonzo, babbage, byron, conway}; macro_rules! param_boilerplate { ($name:ident: $type_:ty, [$($variant:tt)*]) => { @@ -47,8 +47,12 @@ pub type UnitInterval = alonzo::UnitInterval; pub type Nonce = alonzo::Nonce; pub type ExUnitPrices = alonzo::ExUnitPrices; pub type ExUnits = alonzo::ExUnits; -pub type CostMdls = alonzo::CostMdls; +pub type AlonzoCostMdls = alonzo::CostMdls; +pub type BabbageCostMdls = babbage::CostMdls; +pub type ConwayCostMdls = conway::CostMdls; pub type ProtocolVersion = alonzo::ProtocolVersion; +pub type PoolVotingThresholds = conway::PoolVotingThresholds; +pub type DRepVotingThresholds = conway::DRepVotingThresholds; use crate::{Era, MultiEraUpdate}; @@ -70,13 +74,18 @@ impl<'b> MultiEraUpdate<'b> { let up = Box::new(Cow::Owned(up)); Ok(MultiEraUpdate::Babbage(up)) } - _ => unimplemented!("unimplemented era"), + Era::Conway => { + let up = minicbor::decode(cbor)?; + let up = Box::new(Cow::Owned(up)); + Ok(MultiEraUpdate::Conway(up)) + } } } pub fn encode(&self) -> Vec { // to_vec is infallible match self { + MultiEraUpdate::Conway(x) => minicbor::to_vec(x).unwrap(), MultiEraUpdate::AlonzoCompatible(x) => minicbor::to_vec(x).unwrap(), MultiEraUpdate::Babbage(x) => minicbor::to_vec(x).unwrap(), MultiEraUpdate::Byron(a, b) => minicbor::to_vec((a, b)).unwrap(), @@ -121,6 +130,7 @@ impl<'b> MultiEraUpdate<'b> { MultiEraUpdate::Byron(x, _) => *x, MultiEraUpdate::AlonzoCompatible(x) => x.epoch, MultiEraUpdate::Babbage(x) => x.epoch, + MultiEraUpdate::Conway(x) => x.epoch, } } @@ -147,6 +157,40 @@ impl<'b> MultiEraUpdate<'b> { } } + pub fn alonzo_first_proposed_cost_models_for_script_languages(&self) -> Option { + match self { + MultiEraUpdate::AlonzoCompatible(x) => x + .proposed_protocol_parameter_updates + .first() + .and_then(|x| x.1.cost_models_for_script_languages.clone()), + _ => None, + } + } + + pub fn babbage_first_proposed_cost_models_for_script_languages( + &self, + ) -> Option { + match self { + MultiEraUpdate::Babbage(x) => x + .proposed_protocol_parameter_updates + .first() + .and_then(|x| x.1.cost_models_for_script_languages.clone()), + _ => None, + } + } + + pub fn conway_first_proposed_cost_models_for_script_languages(&self) -> Option { + match self { + MultiEraUpdate::Conway(x) => x + .proposed_protocol_parameter_updates + .first() + .and_then(|x| x.1.cost_models_for_script_languages.clone()), + _ => None, + } + } + + // remaining params are mostly boilerplate code, so we can just generate them + param_boilerplate!(minfee_a: u32, [AlonzoCompatible Babbage]); param_boilerplate!(minfee_b: u32, [AlonzoCompatible Babbage]); @@ -181,9 +225,6 @@ impl<'b> MultiEraUpdate<'b> { param_boilerplate!(ada_per_utxo_byte: u64, [AlonzoCompatible Babbage]); - //param_boilerplate!(cost_models_for_script_languages: CostMdls, - // [AlonzoCompatible Babbage]); - param_boilerplate!(execution_costs: ExUnitPrices, [AlonzoCompatible Babbage]); param_boilerplate!(max_tx_ex_units: ExUnits, [AlonzoCompatible Babbage]); @@ -195,4 +236,22 @@ impl<'b> MultiEraUpdate<'b> { param_boilerplate!(collateral_percentage: u32, [AlonzoCompatible Babbage]); param_boilerplate!(max_collateral_inputs: u32, [AlonzoCompatible Babbage]); + + param_boilerplate!(pool_voting_thresholds: PoolVotingThresholds, [Conway]); + + param_boilerplate!(drep_voting_thresholds: DRepVotingThresholds, [Conway]); + + param_boilerplate!(min_committee_size: u64, [Conway]); + + param_boilerplate!(committee_term_limit: u64, [Conway]); + + param_boilerplate!(governance_action_validity_period: u64, [Conway]); + + param_boilerplate!(governance_action_deposit: u64, [Conway]); + + param_boilerplate!(drep_deposit: u64, [Conway]); + + param_boilerplate!(drep_inactivity_period: u64, [Conway]); + + param_boilerplate!(minfee_refscript_cost_per_byte: UnitInterval, [Conway]); } diff --git a/test_data/mainnet-conway-genesis.json b/test_data/mainnet-conway-genesis.json new file mode 100644 index 00000000..e282b8b5 --- /dev/null +++ b/test_data/mainnet-conway-genesis.json @@ -0,0 +1,303 @@ +{ + "poolVotingThresholds": { + "committeeNormal": 0.51, + "committeeNoConfidence": 0.51, + "hardForkInitiation": 0.51, + "motionNoConfidence": 0.51, + "ppSecurityGroup": 0.51 + }, + "dRepVotingThresholds": { + "motionNoConfidence": 0.67, + "committeeNormal": 0.67, + "committeeNoConfidence": 0.6, + "updateToConstitution": 0.75, + "hardForkInitiation": 0.6, + "ppNetworkGroup": 0.67, + "ppEconomicGroup": 0.67, + "ppTechnicalGroup": 0.67, + "ppGovGroup": 0.75, + "treasuryWithdrawal": 0.67 + }, + "committeeMinSize": 7, + "committeeMaxTermLength": 146, + "govActionLifetime": 6, + "govActionDeposit": 100000000000, + "dRepDeposit": 500000000, + "dRepActivity": 20, + "minFeeRefScriptCostPerByte": 15, + "plutusV3CostModel": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 24548, + 29498, + 38, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1 + ], + "constitution": { + "anchor": { + "dataHash": "ca41a91f399259bcefe57f9858e91f6d00e1a38d6d9c63d4052914ea7bd70cb2", + "url": "ipfs://bafkreifnwj6zpu3ixa4siz2lndqybyc5wnnt3jkwyutci4e2tmbnj3xrdm" + }, + "script": "fa24fb305126805cf2164c161d852a0e7330cf988f1fe558cf7d4a64" + }, + "committee": { + "members": { + "scriptHash-df0e83bde65416dade5b1f97e7f115cc1ff999550ad968850783fe50": 580, + "scriptHash-b6012034ba0a7e4afbbf2c7a1432f8824aee5299a48e38e41a952686": 580, + "scriptHash-ce8b37a72b178a37bbd3236daa7b2c158c9d3604e7aa667e6c6004b7": 580, + "scriptHash-f0dc2c00d92a45521267be2d5de1c485f6f9d14466d7e16062897cf7": 580, + "scriptHash-349e55f83e9af24813e6cb368df6a80d38951b2a334dfcdf26815558": 580, + "scriptHash-84aebcfd3e00d0f87af918fc4b5e00135f407e379893df7e7d392c6a": 580, + "scriptHash-e8165b3328027ee0d74b1f07298cb092fd99aa7697a1436f5997f625": 580 + }, + "threshold": { + "numerator": 2, + "denominator": 3 + } + } +} \ No newline at end of file diff --git a/test_data/preview-conway-genesis.json b/test_data/preview-conway-genesis.json new file mode 100644 index 00000000..cad84abd --- /dev/null +++ b/test_data/preview-conway-genesis.json @@ -0,0 +1,297 @@ +{ + "poolVotingThresholds": { + "committeeNormal": 0.51, + "committeeNoConfidence": 0.51, + "hardForkInitiation": 0.51, + "motionNoConfidence": 0.51, + "ppSecurityGroup": 0.51 + }, + "dRepVotingThresholds": { + "motionNoConfidence": 0.67, + "committeeNormal": 0.67, + "committeeNoConfidence": 0.6, + "updateToConstitution": 0.75, + "hardForkInitiation": 0.6, + "ppNetworkGroup": 0.67, + "ppEconomicGroup": 0.67, + "ppTechnicalGroup": 0.67, + "ppGovGroup": 0.75, + "treasuryWithdrawal": 0.67 + }, + "committeeMinSize": 0, + "committeeMaxTermLength": 365, + "govActionLifetime": 30, + "govActionDeposit": 100000000000, + "dRepDeposit": 500000000, + "dRepActivity": 20, + "minFeeRefScriptCostPerByte": 15, + "plutusV3CostModel": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 24548, + 29498, + 38, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1 + ], + "constitution": { + "anchor": { + "dataHash": "ca41a91f399259bcefe57f9858e91f6d00e1a38d6d9c63d4052914ea7bd70cb2", + "url": "ipfs://bafkreifnwj6zpu3ixa4siz2lndqybyc5wnnt3jkwyutci4e2tmbnj3xrdm" + }, + "script": "fa24fb305126805cf2164c161d852a0e7330cf988f1fe558cf7d4a64" + }, + "committee": { + "members": { + "scriptHash-ff9babf23fef3f54ec29132c07a8e23807d7b395b143ecd8ff79f4c7": 1000 + }, + "threshold": { + "numerator": 2, + "denominator": 3 + } + } +} \ No newline at end of file