oasis_core_runtime/consensus/
governance.rs1use std::collections::BTreeMap;
8
9use crate::{
10 common::{quantity::Quantity, version::ProtocolVersions},
11 consensus::beacon::EpochTime,
12};
13
14#[derive(
16 Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, cbor::Encode, cbor::Decode,
17)]
18#[repr(u8)]
19pub enum Vote {
20 #[default]
22 Invalid = 0,
23 Yes = 1,
25 No = 2,
27 Abstain = 3,
29}
30
31#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
33pub struct ProposalVote {
34 pub id: u64,
36
37 pub vote: Vote,
39}
40
41#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
43pub struct UpgradeProposal {
44 pub v: u16,
45 pub handler: String,
46 pub target: ProtocolVersions,
47 pub epoch: EpochTime,
48}
49
50#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
52pub struct CancelUpgradeProposal {
53 pub proposal_id: u64,
54}
55
56#[derive(Clone, Debug, Default, PartialEq, Eq, cbor::Encode, cbor::Decode)]
58pub struct ChangeParametersProposal {
59 pub module: String,
60 pub changes: Option<cbor::Value>,
61}
62
63#[derive(Clone, Debug, Default, PartialEq, Eq, cbor::Encode, cbor::Decode)]
65pub struct ProposalContent {
66 #[cbor(optional)]
67 pub upgrade: Option<UpgradeProposal>,
68 #[cbor(optional)]
69 pub cancel_upgrade: Option<CancelUpgradeProposal>,
70 #[cbor(optional)]
71 pub change_parameters: Option<ChangeParametersProposal>,
72}
73
74#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
76pub struct ConsensusParameterChanges {
77 #[cbor(optional)]
78 pub gas_costs: BTreeMap<String, u64>,
79 #[cbor(optional)]
80 pub min_proposal_deposit: Option<Quantity>,
81 #[cbor(optional)]
82 pub voting_period: Option<EpochTime>,
83 #[cbor(optional)]
84 pub stake_threshold: Option<u8>,
85 #[cbor(optional)]
86 pub upgrade_min_epoch_diff: Option<EpochTime>,
87 #[cbor(optional)]
88 pub upgrade_cancel_min_epoch_diff: Option<EpochTime>,
89 #[cbor(optional)]
90 pub enable_change_parameters_proposal: Option<bool>,
91}
92
93#[cfg(test)]
94mod tests {
95 use base64::prelude::*;
96
97 use super::*;
98
99 #[test]
100 fn test_consistent_proposal_vote() {
101 let tcs = vec![
103 (
104 "omJpZAtkdm90ZQE=",
105 ProposalVote {
106 id: 11,
107 vote: Vote::Yes,
108 },
109 ),
110 (
111 "omJpZAxkdm90ZQI=",
112 ProposalVote {
113 id: 12,
114 vote: Vote::No,
115 },
116 ),
117 (
118 "omJpZA1kdm90ZQM=",
119 ProposalVote {
120 id: 13,
121 vote: Vote::Abstain,
122 },
123 ),
124 ];
125 for (encoded_base64, vote) in tcs {
126 let dec: ProposalVote =
127 cbor::from_slice(&BASE64_STANDARD.decode(encoded_base64).unwrap())
128 .expect("proposal vote should deserialize correctly");
129 assert_eq!(
130 dec, vote,
131 "decoded proposal vote should match the expected value"
132 );
133
134 let ser = BASE64_STANDARD.encode(cbor::to_vec(dec));
135 assert_eq!(
136 ser, encoded_base64,
137 "proposal vote should serialize correctly"
138 );
139 }
140 }
141
142 #[test]
143 fn test_consistent_proposal_content() {
144 let tcs = vec![
146 (
147 "oW5jYW5jZWxfdXBncmFkZaFrcHJvcG9zYWxfaWQYKg==",
148 ProposalContent {
149 cancel_upgrade: Some(CancelUpgradeProposal { proposal_id: 42 }),
150 ..Default::default()
151 },
152 ),
153 (
154 "oWd1cGdyYWRlpGF2AmVlcG9jaBgqZnRhcmdldKNyY29uc2Vuc3VzX3Byb3RvY29soWVwYXRjaBh7dXJ1bnRpbWVfaG9zdF9wcm90b2NvbKFlcGF0Y2gZAch4GnJ1bnRpbWVfY29tbWl0dGVlX3Byb3RvY29soWVwYXRjaBkDFWdoYW5kbGVybHRlc3QtaGFuZGxlcg==",
155 ProposalContent {
156 upgrade: Some(UpgradeProposal {
157 v: 2,
158 handler: "test-handler".into(),
159 target: ProtocolVersions { consensus_protocol: 123.into(), runtime_host_protocol: 456.into(), runtime_committee_protocol: 789.into() } ,
160 epoch: 42,
161 }),
162 ..Default::default()
163 },
164 ),
165 (
166 "oXFjaGFuZ2VfcGFyYW1ldGVyc6JmbW9kdWxla3Rlc3QtbW9kdWxlZ2NoYW5nZXOhbXZvdGluZ19wZXJpb2QYew==",
167 ProposalContent {
168 change_parameters: Some(ChangeParametersProposal {
169 module: "test-module".into(),
170 changes: Some(cbor::to_value(ConsensusParameterChanges{
171 voting_period: Some(123),
172 ..Default::default()
173 })),
174 }),
175 ..Default::default()
176 }
177 ),
178 ];
179 for (encoded_base64, content) in tcs {
180 let dec: ProposalContent =
181 cbor::from_slice(&BASE64_STANDARD.decode(encoded_base64).unwrap())
182 .expect("proposal content should deserialize correctly");
183 assert_eq!(
184 dec, content,
185 "decoded proposal content should match the expected value"
186 );
187
188 let ser = BASE64_STANDARD.encode(cbor::to_vec(dec));
189 assert_eq!(
190 ser, encoded_base64,
191 "proposal content should serialize correctly"
192 );
193 }
194 }
195}