embedded_td/
genesis.rs

1//! Genesis type of tendermint
2
3use time::{Duration, OffsetDateTime};
4
5use crate::{
6    crypto::{AlgorithmType, PublicKey},
7    model, utils,
8};
9
10/// Genesis data
11pub struct Genesis<AppState> {
12    /// Time of genesis
13    pub genesis_time: OffsetDateTime,
14
15    /// Chain ID
16    pub chain_id: String,
17
18    /// Starting height of the blockchain
19    pub initial_height: i64,
20
21    /// Consensus parameters
22    pub consensus_params: ConsensusParams,
23
24    /// Validators
25    pub validators: Vec<ValidatorInfo>,
26
27    /// App hash
28    pub app_hash: Vec<u8>,
29
30    /// App state
31    pub app_state: Option<AppState>,
32}
33
34pub struct ConsensusParams {
35    /// Block size parameters
36    pub block: Block,
37
38    /// Evidence parameters
39    pub evidence: Evidence,
40
41    /// Validator parameters
42    pub validator: Validator,
43
44    /// Version parameters
45    pub version: Version,
46}
47
48/// Block size parameters
49pub struct Block {
50    /// Maximum number of bytes in a block
51    pub max_bytes: u64,
52
53    /// Maximum amount of gas which can be spent on a block
54    pub max_gas: i64,
55
56    /// This parameter has no value anymore in Tendermint-core
57    pub time_iota_ms: i64,
58}
59
60pub struct Evidence {
61    /// Maximum allowed age for evidence to be collected
62    pub max_age_num_blocks: u64,
63
64    /// Max age duration
65    pub max_age_duration: Duration,
66
67    /// Max bytes
68    pub max_bytes: i64,
69}
70
71pub struct Validator {
72    pub pub_key_types: Vec<AlgorithmType>,
73}
74
75pub struct Version {
76    pub app_version: Option<u64>,
77}
78
79pub struct ValidatorInfo {
80    pub address: [u8; 20],
81
82    pub public_key: PublicKey,
83
84    /// Validator voting power
85    pub power: u64,
86
87    /// Validator name
88    pub name: Option<String>,
89
90    /// Validator proposer priority
91    pub proposer_priority: i64,
92}
93
94impl ValidatorInfo {
95    pub fn generate(public_key: PublicKey) -> Self {
96        Self {
97            address: public_key.address(),
98            public_key,
99            power: 10,
100            name: None,
101            proposer_priority: 0,
102        }
103    }
104}
105
106impl<AppState> Genesis<AppState> {
107    pub fn generate(public_key: PublicKey) -> Genesis<()> {
108        let block = Block {
109            max_bytes: 22020096,
110            max_gas: -1,
111            time_iota_ms: 1000,
112        };
113
114        let evidence = Evidence {
115            max_age_num_blocks: 100000,
116            max_age_duration: Duration::days(2000),
117            max_bytes: 1048576,
118        };
119
120        let validator = Validator {
121            pub_key_types: vec![AlgorithmType::Ed25519],
122        };
123
124        let consensus_params = ConsensusParams {
125            block,
126            evidence,
127            validator,
128            version: Version { app_version: None },
129        };
130
131        let chain_id = String::from("test-chain");
132
133        let validator_info = ValidatorInfo::generate(public_key);
134
135        Genesis {
136            genesis_time: OffsetDateTime::now_utc(),
137            chain_id,
138            initial_height: 0,
139            consensus_params,
140            validators: vec![validator_info],
141            app_hash: Vec::new(),
142            app_state: None,
143        }
144    }
145
146    pub(crate) fn into_model(self) -> model::Genesis<AppState> {
147        let mut validators = Vec::with_capacity(self.validators.len());
148
149        for v in self.validators {
150            let vi = model::ValidatorInfo {
151                address: hex::encode(v.address),
152                pub_key: v.public_key.into_model(),
153                power: format!("{}", v.power),
154                name: v.name,
155                proposer_priority: format!("{}", v.proposer_priority),
156            };
157
158            validators.push(vi);
159        }
160
161        let block = model::BlockSize {
162            max_bytes: format!("{}", self.consensus_params.block.max_bytes),
163            max_gas: format!("{}", self.consensus_params.block.max_gas),
164            time_iota_ms: format!("{}", self.consensus_params.block.time_iota_ms),
165        };
166
167        let evidence = model::EvidenceParams {
168            max_bytes: format!("{}", self.consensus_params.evidence.max_bytes),
169            max_age_duration: format!(
170                "{}",
171                self.consensus_params
172                    .evidence
173                    .max_age_duration
174                    .whole_seconds()
175            ),
176            max_age_num_blocks: format!("{}", self.consensus_params.evidence.max_age_num_blocks),
177        };
178
179        let validator = model::ValidatorParams {
180            pub_key_types: self
181                .consensus_params
182                .validator
183                .pub_key_types
184                .into_iter()
185                .map(|e| e.into())
186                .collect(),
187        };
188
189        let version = model::VersionParams {
190            app_version: self
191                .consensus_params
192                .version
193                .app_version
194                .map(|e| format!("{}", e)),
195        };
196
197        let consensus_params = model::ConsensusParams {
198            block,
199            evidence,
200            validator,
201            version,
202        };
203
204        model::Genesis {
205            chain_id: self.chain_id,
206            genesis_time: utils::to_rfc3339_nanos(self.genesis_time),
207            initial_height: format!("{}", self.initial_height),
208            app_hash: hex::encode(self.app_hash),
209            validators,
210            consensus_params,
211            app_state: self.app_state,
212        }
213    }
214}