tendermint/consensus/
params.rs

1//! Tendermint consensus parameters
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    block, evidence, prelude::*, public_key, serializers::allow_empty_object::allow_empty_object,
7};
8
9/// All consensus-relevant parameters that can be adjusted by the ABCI app.
10///
11/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#consensusparams)
12#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
13pub struct Params {
14    /// Parameters limiting the size of a block and time between consecutive blocks.
15    pub block: block::Size,
16    /// Parameters limiting the validity of evidence of byzantine behaviour.
17    pub evidence: evidence::Params,
18    /// Parameters limiting the types of public keys validators can use.
19    pub validator: ValidatorParams,
20    /// The ABCI application version. Will default to None if not present.
21    #[serde(default, deserialize_with = "allow_empty_object")]
22    //#[serde(skip)]
23    pub version: Option<VersionParams>,
24    /// Parameters specific to the Application Blockchain Interface.
25    ///
26    /// This field has been added in CometBFT 0.38 and will be ignored when
27    /// encoding into earlier protocol versions.
28    #[serde(default)]
29    pub abci: AbciParams,
30}
31
32/// ValidatorParams restrict the public key types validators can use.
33///
34/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#validatorparams)
35#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
36pub struct ValidatorParams {
37    /// List of accepted public key types.
38    pub pub_key_types: Vec<public_key::Algorithm>,
39}
40
41/// Version Parameters
42///
43/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#versionparams)
44#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq, Default)]
45pub struct VersionParams {
46    /// The ABCI application version.
47    #[serde(with = "crate::serializers::from_str", alias = "app_version")]
48    pub app: u64,
49}
50
51/// Parameters specific to the Application Blockchain Interface.
52#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq, Default)]
53pub struct AbciParams {
54    /// Configures the first height during which
55    /// vote extensions will be enabled. During this specified height, and for all
56    /// subsequent heights, precommit messages that do not contain valid extension data
57    /// will be considered invalid. Prior to this height, vote extensions will not
58    /// be used or accepted by validators on the network.
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub vote_extensions_enable_height: Option<block::Height>,
61}
62
63// =============================================================================
64// Protobuf conversions
65// =============================================================================
66
67// Todo: How are these key types created?
68fn key_type(s: &str) -> public_key::Algorithm {
69    if s == "Ed25519" || s == "ed25519" {
70        return public_key::Algorithm::Ed25519;
71    }
72    if s == "Secp256k1" || s == "secp256k1" {
73        return public_key::Algorithm::Secp256k1;
74    }
75    public_key::Algorithm::Ed25519 // Todo: Shall we error out for invalid key types?
76}
77
78mod v0_34 {
79    use tendermint_proto::v0_34::{
80        abci::ConsensusParams as RawAbciConsensusParams,
81        types::{
82            ConsensusParams as RawParams, ValidatorParams as RawValidatorParams,
83            VersionParams as RawVersionParams,
84        },
85    };
86    use tendermint_proto::Protobuf;
87
88    use super::{key_type, Params, ValidatorParams, VersionParams};
89    use crate::{error::Error, prelude::*, public_key};
90
91    impl Protobuf<RawParams> for Params {}
92
93    impl TryFrom<RawParams> for Params {
94        type Error = Error;
95
96        fn try_from(value: RawParams) -> Result<Self, Self::Error> {
97            Ok(Self {
98                block: value
99                    .block
100                    .ok_or_else(|| Error::invalid_block("missing block".to_string()))?
101                    .try_into()?,
102                evidence: value
103                    .evidence
104                    .ok_or_else(Error::invalid_evidence)?
105                    .try_into()?,
106                validator: value
107                    .validator
108                    .ok_or_else(Error::invalid_validator_params)?
109                    .try_into()?,
110                version: value.version.map(TryFrom::try_from).transpose()?,
111                abci: Default::default(),
112            })
113        }
114    }
115
116    impl From<Params> for RawParams {
117        fn from(value: Params) -> Self {
118            RawParams {
119                block: Some(value.block.into()),
120                evidence: Some(value.evidence.into()),
121                validator: Some(value.validator.into()),
122                version: value.version.map(From::from),
123            }
124        }
125    }
126
127    impl Protobuf<RawAbciConsensusParams> for Params {}
128
129    impl TryFrom<RawAbciConsensusParams> for Params {
130        type Error = Error;
131
132        fn try_from(value: RawAbciConsensusParams) -> Result<Self, Self::Error> {
133            Ok(Self {
134                block: value
135                    .block
136                    .ok_or_else(|| Error::invalid_block("missing block".to_string()))?
137                    .try_into()?,
138                evidence: value
139                    .evidence
140                    .ok_or_else(Error::invalid_evidence)?
141                    .try_into()?,
142                validator: value
143                    .validator
144                    .ok_or_else(Error::invalid_validator_params)?
145                    .try_into()?,
146                version: value.version.map(TryFrom::try_from).transpose()?,
147                abci: Default::default(),
148            })
149        }
150    }
151
152    impl From<Params> for RawAbciConsensusParams {
153        fn from(value: Params) -> Self {
154            RawAbciConsensusParams {
155                block: Some(value.block.into()),
156                evidence: Some(value.evidence.into()),
157                validator: Some(value.validator.into()),
158                version: value.version.map(From::from),
159            }
160        }
161    }
162
163    impl Protobuf<RawValidatorParams> for ValidatorParams {}
164
165    impl TryFrom<RawValidatorParams> for ValidatorParams {
166        type Error = Error;
167
168        fn try_from(value: RawValidatorParams) -> Result<Self, Self::Error> {
169            Ok(Self {
170                pub_key_types: value.pub_key_types.iter().map(|f| key_type(f)).collect(),
171            })
172        }
173    }
174
175    impl From<ValidatorParams> for RawValidatorParams {
176        fn from(value: ValidatorParams) -> Self {
177            RawValidatorParams {
178                pub_key_types: value
179                    .pub_key_types
180                    .into_iter()
181                    .map(|k| match k {
182                        public_key::Algorithm::Ed25519 => "ed25519".to_string(),
183                        public_key::Algorithm::Secp256k1 => "secp256k1".to_string(),
184                    })
185                    .collect(),
186            }
187        }
188    }
189
190    impl Protobuf<RawVersionParams> for VersionParams {}
191
192    impl TryFrom<RawVersionParams> for VersionParams {
193        type Error = Error;
194
195        fn try_from(value: RawVersionParams) -> Result<Self, Self::Error> {
196            Ok(Self {
197                app: value.app_version,
198            })
199        }
200    }
201
202    impl From<VersionParams> for RawVersionParams {
203        fn from(value: VersionParams) -> Self {
204            RawVersionParams {
205                app_version: value.app,
206            }
207        }
208    }
209}
210
211mod v0_37 {
212    use tendermint_proto::v0_37::types::{
213        ConsensusParams as RawParams, ValidatorParams as RawValidatorParams,
214        VersionParams as RawVersionParams,
215    };
216    use tendermint_proto::Protobuf;
217
218    use super::{key_type, Params, ValidatorParams, VersionParams};
219    use crate::{error::Error, prelude::*, public_key};
220
221    impl Protobuf<RawParams> for Params {}
222
223    impl TryFrom<RawParams> for Params {
224        type Error = Error;
225
226        fn try_from(value: RawParams) -> Result<Self, Self::Error> {
227            Ok(Self {
228                block: value
229                    .block
230                    .ok_or_else(|| Error::invalid_block("missing block".to_string()))?
231                    .try_into()?,
232                evidence: value
233                    .evidence
234                    .ok_or_else(Error::invalid_evidence)?
235                    .try_into()?,
236                validator: value
237                    .validator
238                    .ok_or_else(Error::invalid_validator_params)?
239                    .try_into()?,
240                version: value.version.map(TryFrom::try_from).transpose()?,
241                abci: Default::default(),
242            })
243        }
244    }
245
246    impl From<Params> for RawParams {
247        fn from(value: Params) -> Self {
248            RawParams {
249                block: Some(value.block.into()),
250                evidence: Some(value.evidence.into()),
251                validator: Some(value.validator.into()),
252                version: value.version.map(From::from),
253            }
254        }
255    }
256
257    impl Protobuf<RawValidatorParams> for ValidatorParams {}
258
259    impl TryFrom<RawValidatorParams> for ValidatorParams {
260        type Error = Error;
261
262        fn try_from(value: RawValidatorParams) -> Result<Self, Self::Error> {
263            Ok(Self {
264                pub_key_types: value.pub_key_types.iter().map(|f| key_type(f)).collect(),
265            })
266        }
267    }
268
269    impl From<ValidatorParams> for RawValidatorParams {
270        fn from(value: ValidatorParams) -> Self {
271            RawValidatorParams {
272                pub_key_types: value
273                    .pub_key_types
274                    .into_iter()
275                    .map(|k| match k {
276                        public_key::Algorithm::Ed25519 => "ed25519".to_string(),
277                        public_key::Algorithm::Secp256k1 => "secp256k1".to_string(),
278                    })
279                    .collect(),
280            }
281        }
282    }
283
284    impl Protobuf<RawVersionParams> for VersionParams {}
285
286    impl TryFrom<RawVersionParams> for VersionParams {
287        type Error = Error;
288
289        fn try_from(value: RawVersionParams) -> Result<Self, Self::Error> {
290            Ok(Self { app: value.app })
291        }
292    }
293
294    impl From<VersionParams> for RawVersionParams {
295        fn from(value: VersionParams) -> Self {
296            RawVersionParams { app: value.app }
297        }
298    }
299}
300
301mod v0_38 {
302    use tendermint_proto::v0_38::types::{
303        AbciParams as RawAbciParams, ConsensusParams as RawParams,
304        ValidatorParams as RawValidatorParams, VersionParams as RawVersionParams,
305    };
306    use tendermint_proto::Protobuf;
307
308    use super::{key_type, AbciParams, Params, ValidatorParams, VersionParams};
309    use crate::{error::Error, prelude::*, public_key};
310
311    impl Protobuf<RawParams> for Params {}
312
313    impl TryFrom<RawParams> for Params {
314        type Error = Error;
315
316        fn try_from(value: RawParams) -> Result<Self, Self::Error> {
317            Ok(Self {
318                block: value
319                    .block
320                    .ok_or_else(|| Error::invalid_block("missing block".to_string()))?
321                    .try_into()?,
322                evidence: value
323                    .evidence
324                    .ok_or_else(Error::invalid_evidence)?
325                    .try_into()?,
326                validator: value
327                    .validator
328                    .ok_or_else(Error::invalid_validator_params)?
329                    .try_into()?,
330                version: value.version.map(TryFrom::try_from).transpose()?,
331                abci: value
332                    .abci
333                    .map(TryFrom::try_from)
334                    .transpose()?
335                    .unwrap_or_default(),
336            })
337        }
338    }
339
340    impl From<Params> for RawParams {
341        fn from(value: Params) -> Self {
342            RawParams {
343                block: Some(value.block.into()),
344                evidence: Some(value.evidence.into()),
345                validator: Some(value.validator.into()),
346                version: value.version.map(From::from),
347                abci: Some(value.abci.into()),
348            }
349        }
350    }
351
352    impl Protobuf<RawValidatorParams> for ValidatorParams {}
353
354    impl TryFrom<RawValidatorParams> for ValidatorParams {
355        type Error = Error;
356
357        fn try_from(value: RawValidatorParams) -> Result<Self, Self::Error> {
358            Ok(Self {
359                pub_key_types: value.pub_key_types.iter().map(|f| key_type(f)).collect(),
360            })
361        }
362    }
363
364    impl From<ValidatorParams> for RawValidatorParams {
365        fn from(value: ValidatorParams) -> Self {
366            RawValidatorParams {
367                pub_key_types: value
368                    .pub_key_types
369                    .into_iter()
370                    .map(|k| match k {
371                        public_key::Algorithm::Ed25519 => "ed25519".to_string(),
372                        public_key::Algorithm::Secp256k1 => "secp256k1".to_string(),
373                    })
374                    .collect(),
375            }
376        }
377    }
378
379    impl Protobuf<RawVersionParams> for VersionParams {}
380
381    impl TryFrom<RawVersionParams> for VersionParams {
382        type Error = Error;
383
384        fn try_from(value: RawVersionParams) -> Result<Self, Self::Error> {
385            Ok(Self { app: value.app })
386        }
387    }
388
389    impl From<VersionParams> for RawVersionParams {
390        fn from(value: VersionParams) -> Self {
391            RawVersionParams { app: value.app }
392        }
393    }
394
395    impl Protobuf<RawAbciParams> for AbciParams {}
396
397    impl TryFrom<RawAbciParams> for AbciParams {
398        type Error = Error;
399
400        fn try_from(message: RawAbciParams) -> Result<Self, Self::Error> {
401            let vote_extensions_enable_height = match message.vote_extensions_enable_height {
402                0 => None,
403                h => Some(h.try_into()?),
404            };
405            Ok(Self {
406                vote_extensions_enable_height,
407            })
408        }
409    }
410
411    impl From<AbciParams> for RawAbciParams {
412        fn from(value: AbciParams) -> Self {
413            Self {
414                vote_extensions_enable_height: value
415                    .vote_extensions_enable_height
416                    .map_or(0, Into::into),
417            }
418        }
419    }
420}