casper_node/utils/chain_specification/
parse_toml.rs1use std::{convert::TryFrom, path::Path};
31
32use serde::{Deserialize, Serialize};
33
34use casper_types::{
35 bytesrepr::Bytes, file_utils, AccountsConfig, ActivationPoint, Chainspec, ChainspecRawBytes,
36 CoreConfig, GlobalStateUpdate, GlobalStateUpdateConfig, HighwayConfig, NetworkConfig,
37 ProtocolConfig, ProtocolVersion, StorageCosts, SystemConfig, TransactionConfig, VacancyConfig,
38 WasmConfig,
39};
40
41use crate::utils::{
42 chain_specification::error::{ChainspecAccountsLoadError, Error, GlobalStateUpdateLoadError},
43 Loadable,
44};
45
46pub const CHAINSPEC_FILENAME: &str = "chainspec.toml";
49pub const CHAINSPEC_ACCOUNTS_FILENAME: &str = "accounts.toml";
51pub const CHAINSPEC_GLOBAL_STATE_FILENAME: &str = "global_state.toml";
53
54#[derive(PartialEq, Eq, Serialize, Deserialize, Debug)]
55#[serde(deny_unknown_fields)]
57struct TomlNetwork {
58 name: String,
59 maximum_net_message_size: u32,
60}
61
62#[derive(PartialEq, Eq, Serialize, Deserialize, Debug)]
63#[serde(deny_unknown_fields)]
65struct TomlProtocol {
66 version: ProtocolVersion,
67 hard_reset: bool,
68 activation_point: ActivationPoint,
69}
70
71#[derive(PartialEq, Eq, Serialize, Deserialize, Debug)]
73#[serde(deny_unknown_fields)]
75pub(super) struct TomlChainspec {
76 protocol: TomlProtocol,
77 network: TomlNetwork,
78 core: CoreConfig,
79 transactions: TransactionConfig,
80 highway: HighwayConfig,
81 wasm: WasmConfig,
82 system_costs: SystemConfig,
83 vacancy: VacancyConfig,
84 storage_costs: StorageCosts,
85}
86
87impl From<&Chainspec> for TomlChainspec {
88 fn from(chainspec: &Chainspec) -> Self {
89 let protocol = TomlProtocol {
90 version: chainspec.protocol_config.version,
91 hard_reset: chainspec.protocol_config.hard_reset,
92 activation_point: chainspec.protocol_config.activation_point,
93 };
94 let network = TomlNetwork {
95 name: chainspec.network_config.name.clone(),
96 maximum_net_message_size: chainspec.network_config.maximum_net_message_size,
97 };
98 let core = chainspec.core_config.clone();
99 let transactions = chainspec.transaction_config.clone();
100 let highway = chainspec.highway_config;
101 let wasm = chainspec.wasm_config;
102 let system_costs = chainspec.system_costs_config;
103 let vacancy = chainspec.vacancy_config;
104 let storage_costs = chainspec.storage_costs;
105
106 TomlChainspec {
107 protocol,
108 network,
109 core,
110 transactions,
111 highway,
112 wasm,
113 system_costs,
114 vacancy,
115 storage_costs,
116 }
117 }
118}
119
120pub(super) fn parse_toml<P: AsRef<Path>>(
121 chainspec_path: P,
122) -> Result<(Chainspec, ChainspecRawBytes), Error> {
123 let chainspec_bytes =
124 file_utils::read_file(chainspec_path.as_ref()).map_err(Error::LoadChainspec)?;
125 let toml_chainspec: TomlChainspec =
126 toml::from_str(std::str::from_utf8(&chainspec_bytes).unwrap())?;
127
128 let root = chainspec_path
129 .as_ref()
130 .parent()
131 .unwrap_or_else(|| Path::new(""));
132
133 let (accounts_config, maybe_genesis_accounts_bytes) = parse_toml_accounts(root)?;
135
136 let network_config = NetworkConfig {
137 name: toml_chainspec.network.name,
138 accounts_config,
139 maximum_net_message_size: toml_chainspec.network.maximum_net_message_size,
140 };
141
142 let (global_state_update, maybe_global_state_bytes) = match parse_toml_global_state(root)? {
144 Some((config, bytes)) => (
145 Some(
146 GlobalStateUpdate::try_from(config)
147 .map_err(GlobalStateUpdateLoadError::DecodingKeyValuePairs)?,
148 ),
149 Some(bytes),
150 ),
151 None => (None, None),
152 };
153
154 let protocol_config = ProtocolConfig {
155 version: toml_chainspec.protocol.version,
156 hard_reset: toml_chainspec.protocol.hard_reset,
157 activation_point: toml_chainspec.protocol.activation_point,
158 global_state_update,
159 };
160
161 let chainspec = Chainspec {
162 protocol_config,
163 network_config,
164 core_config: toml_chainspec.core,
165 transaction_config: toml_chainspec.transactions,
166 highway_config: toml_chainspec.highway,
167 wasm_config: toml_chainspec.wasm,
168 system_costs_config: toml_chainspec.system_costs,
169 vacancy_config: toml_chainspec.vacancy,
170 storage_costs: toml_chainspec.storage_costs,
171 };
172 let chainspec_raw_bytes = ChainspecRawBytes::new(
173 Bytes::from(chainspec_bytes),
174 maybe_genesis_accounts_bytes,
175 maybe_global_state_bytes,
176 );
177
178 Ok((chainspec, chainspec_raw_bytes))
179}
180
181impl Loadable for (Chainspec, ChainspecRawBytes) {
182 type Error = Error;
183
184 fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, Self::Error> {
185 parse_toml(path.as_ref().join(CHAINSPEC_FILENAME))
186 }
187}
188
189pub(super) fn parse_toml_accounts<P: AsRef<Path>>(
193 dir_path: P,
194) -> Result<(AccountsConfig, Option<Bytes>), ChainspecAccountsLoadError> {
195 let accounts_path = dir_path.as_ref().join(CHAINSPEC_ACCOUNTS_FILENAME);
196 if !accounts_path.is_file() {
197 let config = AccountsConfig::new(vec![], vec![], vec![]);
198 let maybe_bytes = None;
199 return Ok((config, maybe_bytes));
200 }
201 let bytes = file_utils::read_file(accounts_path)?;
202 let config: AccountsConfig = toml::from_str(std::str::from_utf8(&bytes).unwrap())?;
203 Ok((config, Some(Bytes::from(bytes))))
204}
205
206pub(super) fn parse_toml_global_state<P: AsRef<Path>>(
207 path: P,
208) -> Result<Option<(GlobalStateUpdateConfig, Bytes)>, GlobalStateUpdateLoadError> {
209 let update_path = path.as_ref().join(CHAINSPEC_GLOBAL_STATE_FILENAME);
210 if !update_path.is_file() {
211 return Ok(None);
212 }
213 let bytes = file_utils::read_file(update_path)?;
214 let config = toml::from_str(std::str::from_utf8(&bytes).unwrap())?;
215 Ok(Some((config, Bytes::from(bytes))))
216}