tycho_types/models/config/
mod.rs

1//! Blockchain config and params.
2
3pub use self::params::*;
4use crate::cell::*;
5use crate::dict::{Dict, DictKey};
6use crate::error::Error;
7use crate::models::currency::ExtraCurrencyCollection;
8use crate::models::global_version::GlobalVersion;
9use crate::num::Tokens;
10
11mod params;
12
13#[cfg(test)]
14mod tests;
15
16/// Blockchain config.
17#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct BlockchainConfig {
20    /// Configuration contract address.
21    pub address: HashBytes,
22    /// Configuration parameters.
23    pub params: BlockchainConfigParams,
24}
25
26impl BlockchainConfig {
27    /// Creates a new blockchain config with only the address set.
28    pub fn new_empty(address: HashBytes) -> Self {
29        let mut params = BlockchainConfigParams(Dict::new());
30        params
31            .set_raw(ConfigParam0::ID, CellBuilder::build_from(address).unwrap())
32            .unwrap();
33
34        Self { address, params }
35    }
36}
37
38impl std::ops::Deref for BlockchainConfig {
39    type Target = BlockchainConfigParams;
40
41    #[inline]
42    fn deref(&self) -> &Self::Target {
43        &self.params
44    }
45}
46
47impl std::ops::DerefMut for BlockchainConfig {
48    #[inline]
49    fn deref_mut(&mut self) -> &mut Self::Target {
50        &mut self.params
51    }
52}
53
54/// A non-empty dictionary with blockchain config params.
55#[derive(Debug, Clone, Eq, PartialEq)]
56#[repr(transparent)]
57pub struct BlockchainConfigParams(Dict<u32, Cell>);
58
59impl BlockchainConfigParams {
60    /// Creates a dictionary from a raw cell.
61    ///
62    /// NOTE: Root is mandatory since the configs dictionary can't be empty.
63    pub fn from_raw(dict_root: Cell) -> Self {
64        Self(Dict::from_raw(Some(dict_root)))
65    }
66
67    /// Returns the elector account address (in masterchain).
68    ///
69    /// Uses [`ConfigParam1`].
70    pub fn get_elector_address(&self) -> Result<HashBytes, Error> {
71        ok!(self.get::<ConfigParam1>()).ok_or(Error::CellUnderflow)
72    }
73
74    /// Updates the elector account address (in masterchain).
75    ///
76    /// Uses [`ConfigParam1`].
77    pub fn set_elector_address(&mut self, address: &HashBytes) -> Result<bool, Error> {
78        self.set_raw(ConfigParam1::ID, ok!(CellBuilder::build_from(address)))
79    }
80
81    /// Returns the minter account address (in masterchain).
82    ///
83    /// Uses [`ConfigParam2`] with a fallback to [`ConfigParam0`] (config).
84    pub fn get_minter_address(&self) -> Result<HashBytes, Error> {
85        match ok!(self.get::<ConfigParam2>()) {
86            Some(address) => Ok(address),
87            None => ok!(self.get::<ConfigParam0>()).ok_or(Error::CellUnderflow),
88        }
89    }
90
91    /// Updates the minter account address (in masterchain).
92    ///
93    /// Uses [`ConfigParam2`].
94    pub fn set_minter_address(&mut self, address: &HashBytes) -> Result<bool, Error> {
95        self.set_raw(ConfigParam2::ID, ok!(CellBuilder::build_from(address)))
96    }
97
98    /// Returns the burning config.
99    ///
100    /// Uses [`ConfigParam5`].
101    pub fn get_burning_config(&self) -> Result<BurningConfig, Error> {
102        ok!(self.get::<ConfigParam5>()).ok_or(Error::CellUnderflow)
103    }
104
105    /// Updates the burning config.
106    ///
107    /// Uses [`ConfigParam5`].
108    pub fn set_burning_config(&mut self, config: &BurningConfig) -> Result<bool, Error> {
109        self.set_raw(ConfigParam5::ID, ok!(CellBuilder::build_from(config)))
110    }
111
112    /// Returns the fee collector account address (in masterchain).
113    ///
114    /// Uses [`ConfigParam3`] with a fallback to [`ConfigParam1`] (elector).
115    pub fn get_fee_collector_address(&self) -> Result<HashBytes, Error> {
116        match ok!(self.get::<ConfigParam3>()) {
117            Some(address) => Ok(address),
118            None => ok!(self.get::<ConfigParam1>()).ok_or(Error::CellUnderflow),
119        }
120    }
121
122    /// Updates the fee collector address (in masterchain).
123    ///
124    /// Uses [`ConfigParam3`].
125    pub fn set_fee_collector_address(&mut self, address: &HashBytes) -> Result<bool, Error> {
126        self.set_raw(ConfigParam3::ID, ok!(CellBuilder::build_from(address)))
127    }
128
129    /// Returns the lowest supported block version and required capabilities.
130    ///
131    /// Uses [`ConfigParam8`].
132    pub fn get_global_version(&self) -> Result<GlobalVersion, Error> {
133        ok!(self.get::<ConfigParam8>()).ok_or(Error::CellUnderflow)
134    }
135
136    /// Updates the global version.
137    ///
138    /// Uses [`ConfigParam8`].
139    pub fn set_global_version(&mut self, version: &GlobalVersion) -> Result<bool, Error> {
140        self.set_raw(ConfigParam8::ID, ok!(CellBuilder::build_from(version)))
141    }
142
143    /// Returns a list of params that must be present in config.
144    ///
145    /// Uses [`ConfigParam9`].
146    pub fn get_mandatory_params(&self) -> Result<Dict<u32, ()>, Error> {
147        ok!(self.get::<ConfigParam9>()).ok_or(Error::CellUnderflow)
148    }
149
150    /// Updates a list of params that must be present in config.
151    ///
152    /// Uses [`ConfigParam9`].
153    pub fn set_mandatory_params(&mut self, params: &[u32]) -> Result<bool, Error> {
154        let mut dict = Dict::new();
155        for id in params {
156            ok!(dict.set(*id, ()));
157        }
158        self.set_raw(
159            ConfigParam9::ID,
160            ok!(CellBuilder::build_from(NonEmptyDict(dict))),
161        )
162    }
163
164    /// Returns a list of params that have a different set of update requirements.
165    ///
166    /// Uses [`ConfigParam10`].
167    pub fn get_critical_params(&self) -> Result<Dict<u32, ()>, Error> {
168        ok!(self.get::<ConfigParam10>()).ok_or(Error::CellUnderflow)
169    }
170
171    /// Updates a list of params that have a different set of update requirements.
172    ///
173    /// Uses [`ConfigParam10`].
174    pub fn set_critical_params(&mut self, params: &[u32]) -> Result<bool, Error> {
175        let mut dict = Dict::new();
176        for id in params {
177            ok!(dict.set(*id, ()));
178        }
179        self.set_raw(
180            ConfigParam10::ID,
181            ok!(CellBuilder::build_from(NonEmptyDict(dict))),
182        )
183    }
184
185    /// Returns a dictionary with workchain descriptions.
186    ///
187    /// Uses [`ConfigParam12`].
188    pub fn get_workchains(&self) -> Result<Dict<i32, WorkchainDescription>, Error> {
189        ok!(self.get::<ConfigParam12>()).ok_or(Error::CellUnderflow)
190    }
191
192    /// Updates a list of workchain descriptions.
193    ///
194    /// Uses [`ConfigParam12`].
195    pub fn set_workchains(
196        &mut self,
197        workchains: &Dict<i32, WorkchainDescription>,
198    ) -> Result<bool, Error> {
199        self.set_raw(ConfigParam12::ID, ok!(CellBuilder::build_from(workchains)))
200    }
201
202    /// Returns a block creation reward for the specified workchain in tokens.
203    ///
204    /// Uses [`ConfigParam14`].
205    pub fn get_block_creation_reward(&self, masterchain: bool) -> Result<Tokens, Error> {
206        let rewards = ok!(self.get_block_creation_rewards());
207        Ok(if masterchain {
208            rewards.masterchain_block_fee
209        } else {
210            rewards.basechain_block_fee
211        })
212    }
213
214    /// Returns a block creation rewards in tokens.
215    ///
216    /// Uses [`ConfigParam14`].
217    pub fn get_block_creation_rewards(&self) -> Result<BlockCreationRewards, Error> {
218        ok!(self.get::<ConfigParam14>()).ok_or(Error::CellUnderflow)
219    }
220
221    /// Updates a block creation rewards in tokens.
222    ///
223    /// Uses [`ConfigParam14`].
224    pub fn set_block_creation_rewards(
225        &mut self,
226        rewards: &BlockCreationRewards,
227    ) -> Result<bool, Error> {
228        self.set_raw(ConfigParam14::ID, ok!(CellBuilder::build_from(rewards)))
229    }
230
231    /// Returns election timings.
232    ///
233    /// Uses [`ConfigParam15`].
234    pub fn get_election_timings(&self) -> Result<ElectionTimings, Error> {
235        ok!(self.get::<ConfigParam15>()).ok_or(Error::CellUnderflow)
236    }
237
238    /// Updates election timings.
239    ///
240    /// Uses [`ConfigParam15`].
241    pub fn set_election_timings(&mut self, timings: &ElectionTimings) -> Result<bool, Error> {
242        self.set_raw(ConfigParam15::ID, ok!(CellBuilder::build_from(timings)))
243    }
244
245    /// Returns possible validator count.
246    ///
247    /// Uses [`ConfigParam16`].
248    pub fn get_validator_count_params(&self) -> Result<ValidatorCountParams, Error> {
249        ok!(self.get::<ConfigParam16>()).ok_or(Error::CellUnderflow)
250    }
251
252    /// Updates possible validator count.
253    ///
254    /// Uses [`ConfigParam16`].
255    pub fn set_validator_count_params(
256        &mut self,
257        params: &ValidatorCountParams,
258    ) -> Result<bool, Error> {
259        self.set_raw(ConfigParam16::ID, ok!(CellBuilder::build_from(params)))
260    }
261
262    /// Returns validator stake range and factor.
263    ///
264    /// Uses [`ConfigParam17`].
265    pub fn get_validator_stake_params(&self) -> Result<ValidatorStakeParams, Error> {
266        ok!(self.get::<ConfigParam17>()).ok_or(Error::CellUnderflow)
267    }
268
269    /// Updates validator stake range and factor.
270    ///
271    /// Uses [`ConfigParam17`].
272    pub fn set_validator_stake_params(
273        &mut self,
274        params: &ValidatorStakeParams,
275    ) -> Result<bool, Error> {
276        self.set_raw(ConfigParam17::ID, ok!(CellBuilder::build_from(params)))
277    }
278
279    /// Returns a list with a history of all storage prices.
280    ///
281    /// Uses [`ConfigParam18`].
282    pub fn get_storage_prices(&self) -> Result<Dict<u32, StoragePrices>, Error> {
283        ok!(self.get::<ConfigParam18>()).ok_or(Error::CellUnderflow)
284    }
285
286    /// Updates a list with a history of all storage prices.
287    ///
288    /// Uses [`ConfigParam18`].
289    pub fn set_storage_prices(&mut self, prices: &[StoragePrices]) -> Result<bool, Error> {
290        let mut dict = Dict::<u32, StoragePrices>::new();
291        for (i, prices) in prices.iter().enumerate() {
292            ok!(dict.set(i as u32, *prices));
293        }
294        self.set_raw(
295            ConfigParam18::ID,
296            ok!(CellBuilder::build_from(NonEmptyDict(dict))),
297        )
298    }
299
300    /// Returns a global id.
301    pub fn get_global_id(&self) -> Result<i32, Error> {
302        ok!(self.get::<ConfigParam19>()).ok_or(Error::CellUnderflow)
303    }
304
305    /// Updates a global id.
306    pub fn set_global_id(&mut self, global_id: i32) -> Result<bool, Error> {
307        self.set_raw(
308            ConfigParam19::ID,
309            ok!(CellBuilder::build_from(global_id as u32)),
310        )
311    }
312
313    /// Returns gas limits and prices.
314    ///
315    /// Uses [`ConfigParam20`] (for masterchain) or [`ConfigParam21`] (for other workchains).
316    pub fn get_gas_prices(&self, masterchain: bool) -> Result<GasLimitsPrices, Error> {
317        ok!(if masterchain {
318            self.get::<ConfigParam20>()
319        } else {
320            self.get::<ConfigParam21>()
321        })
322        .ok_or(Error::CellUnderflow)
323    }
324
325    /// Updates gas limits and prices.
326    ///
327    /// Uses [`ConfigParam20`] (for masterchain) or [`ConfigParam21`] (for other workchains).
328    pub fn set_gas_prices(
329        &mut self,
330        masterchain: bool,
331        prices: &GasLimitsPrices,
332    ) -> Result<bool, Error> {
333        let id = if masterchain {
334            ConfigParam20::ID
335        } else {
336            ConfigParam21::ID
337        };
338        self.set_raw(id, ok!(CellBuilder::build_from(prices)))
339    }
340
341    /// Returns block limits.
342    ///
343    /// Uses [`ConfigParam22`] (for masterchain) or [`ConfigParam23`] (for other workchains).
344    pub fn get_block_limits(&self, masterchain: bool) -> Result<BlockLimits, Error> {
345        ok!(if masterchain {
346            self.get::<ConfigParam22>()
347        } else {
348            self.get::<ConfigParam23>()
349        })
350        .ok_or(Error::CellUnderflow)
351    }
352
353    /// Updates block limits.
354    ///
355    /// Uses [`ConfigParam22`] (for masterchain) or [`ConfigParam23`] (for other workchains).
356    pub fn set_block_limits(
357        &mut self,
358        masterchain: bool,
359        limits: &BlockLimits,
360    ) -> Result<bool, Error> {
361        let id = if masterchain {
362            ConfigParam22::ID
363        } else {
364            ConfigParam23::ID
365        };
366        self.set_raw(id, ok!(CellBuilder::build_from(limits)))
367    }
368
369    /// Returns message forwarding prices.
370    ///
371    /// Uses [`ConfigParam24`] (for masterchain) or [`ConfigParam25`] (for other workchains).
372    pub fn get_msg_forward_prices(&self, masterchain: bool) -> Result<MsgForwardPrices, Error> {
373        ok!(if masterchain {
374            self.get::<ConfigParam24>()
375        } else {
376            self.get::<ConfigParam25>()
377        })
378        .ok_or(Error::CellUnderflow)
379    }
380
381    /// Updates message forwarding prices.
382    ///
383    /// Uses [`ConfigParam24`] (for masterchain) or [`ConfigParam25`] (for other workchains).
384    pub fn set_msg_forward_prices(
385        &mut self,
386        masterchain: bool,
387        prices: &MsgForwardPrices,
388    ) -> Result<bool, Error> {
389        let id = if masterchain {
390            ConfigParam24::ID
391        } else {
392            ConfigParam25::ID
393        };
394        self.set_raw(id, ok!(CellBuilder::build_from(prices)))
395    }
396
397    /// Returns a catchain config.
398    ///
399    /// Uses [`ConfigParam28`].
400    #[cfg(not(feature = "tycho"))]
401    pub fn get_catchain_config(&self) -> Result<CatchainConfig, Error> {
402        ok!(self.get::<ConfigParam28>()).ok_or(Error::CellUnderflow)
403    }
404
405    /// Updates a catchain config.
406    ///
407    /// Uses [`ConfigParam28`].
408    #[cfg(not(feature = "tycho"))]
409    pub fn set_catchain_config(&mut self, config: &CatchainConfig) -> Result<bool, Error> {
410        self.set_raw(ConfigParam28::ID, ok!(CellBuilder::build_from(config)))
411    }
412
413    /// Returns a collation config.
414    ///
415    /// Uses [`ConfigParam28`].
416    #[cfg(feature = "tycho")]
417    pub fn get_collation_config(&self) -> Result<CollationConfig, Error> {
418        ok!(self.get::<ConfigParam28>()).ok_or(Error::CellUnderflow)
419    }
420
421    /// Updates a collation config.
422    ///
423    /// Uses [`ConfigParam28`].
424    #[cfg(feature = "tycho")]
425    pub fn set_collation_config(&mut self, config: &CollationConfig) -> Result<bool, Error> {
426        self.set_raw(ConfigParam28::ID, ok!(CellBuilder::build_from(config)))
427    }
428
429    /// Returns a consensus config.
430    ///
431    /// Uses [`ConfigParam29`].
432    pub fn get_consensus_config(&self) -> Result<ConsensusConfig, Error> {
433        ok!(self.get::<ConfigParam29>()).ok_or(Error::CellUnderflow)
434    }
435
436    /// Updates a consensus config.
437    ///
438    /// Uses [`ConfigParam29`].
439    pub fn set_consensus_config(&mut self, config: &ConsensusConfig) -> Result<bool, Error> {
440        self.set_raw(ConfigParam29::ID, ok!(CellBuilder::build_from(config)))
441    }
442
443    /// Returns a list of fundamental account addresses (in masterchain).
444    ///
445    /// Uses [`ConfigParam31`].
446    pub fn get_fundamental_addresses(&self) -> Result<Dict<HashBytes, ()>, Error> {
447        ok!(self.get::<ConfigParam31>()).ok_or(Error::CellUnderflow)
448    }
449
450    /// Updates a list of fundamental account addresses (in masterchain).
451    ///
452    /// Uses [`ConfigParam31`].
453    pub fn set_fundamental_addresses(&mut self, addresses: &[HashBytes]) -> Result<bool, Error> {
454        let mut dict = Dict::<HashBytes, ()>::new();
455        for address in addresses {
456            ok!(dict.set(*address, ()));
457        }
458        self.set_raw(ConfigParam31::ID, ok!(CellBuilder::build_from(dict)))
459    }
460
461    /// Returns `true` if the config contains info about the previous validator set.
462    ///
463    /// Uses [`ConfigParam32`] or [`ConfigParam33`].
464    pub fn contains_prev_validator_set(&self) -> Result<bool, Error> {
465        Ok(ok!(self.contains::<ConfigParam32>()) || ok!(self.contains::<ConfigParam33>()))
466    }
467
468    /// Returns `true` if the config contains info about the next validator set.
469    ///
470    /// Uses [`ConfigParam36`] or [`ConfigParam37`].
471    pub fn contains_next_validator_set(&self) -> Result<bool, Error> {
472        Ok(ok!(self.contains::<ConfigParam36>()) || ok!(self.contains::<ConfigParam37>()))
473    }
474
475    /// Returns the previous validator set.
476    ///
477    /// Uses [`ConfigParam33`] (temp prev validators) or [`ConfigParam32`] (prev validators).
478    pub fn get_previous_validator_set(&self) -> Result<Option<ValidatorSet>, Error> {
479        match ok!(self.get::<ConfigParam33>()) {
480            None => self.get::<ConfigParam32>(),
481            set => Ok(set),
482        }
483    }
484
485    /// Returns the current validator set.
486    ///
487    /// Uses [`ConfigParam35`] (temp validators) or [`ConfigParam34`] (current validators).
488    pub fn get_current_validator_set(&self) -> Result<ValidatorSet, Error> {
489        match ok!(self.get::<ConfigParam35>()) {
490            Some(set) => Ok(set),
491            None => ok!(self.get::<ConfigParam34>()).ok_or(Error::CellUnderflow),
492        }
493    }
494
495    /// Returns the next validator set.
496    ///
497    /// Uses [`ConfigParam37`] (temp next validators) or [`ConfigParam36`] (next validators).
498    pub fn get_next_validator_set(&self) -> Result<Option<ValidatorSet>, Error> {
499        match ok!(self.get::<ConfigParam37>()) {
500            None => self.get::<ConfigParam36>(),
501            set => Ok(set),
502        }
503    }
504
505    /// Returns size limits.
506    pub fn get_size_limits(&self) -> Result<SizeLimitsConfig, Error> {
507        ok!(self.get::<ConfigParam43>()).ok_or(Error::CellUnderflow)
508    }
509
510    /// Updates a global id.
511    pub fn set_size_limits(&mut self, size_limits: &SizeLimitsConfig) -> Result<bool, Error> {
512        self.set_raw(ConfigParam43::ID, ok!(CellBuilder::build_from(size_limits)))
513    }
514
515    /// Returns `true` if the config contains a param for the specified id.
516    pub fn contains<'a, T: KnownConfigParam<'a>>(&'a self) -> Result<bool, Error> {
517        self.0.contains_key(T::ID)
518    }
519
520    /// Returns `true` if the config contains a param for the specified id.
521    pub fn contains_raw(&self, id: u32) -> Result<bool, Error> {
522        self.0.contains_key(id)
523    }
524
525    /// Tries to get a parameter from the blockchain config.
526    pub fn get<'a, T: KnownConfigParam<'a>>(&'a self) -> Result<Option<T::Value>, Error> {
527        let Some(mut slice) = ok!(self.get_raw(T::ID)) else {
528            return Ok(None);
529        };
530        match <T::Wrapper as Load<'a>>::load_from(&mut slice) {
531            Ok(wrapped) => Ok(Some(wrapped.into_inner())),
532            Err(e) => Err(e),
533        }
534    }
535
536    /// Tries to update a parameter in the blockchain config.
537    pub fn set<'a, T: KnownConfigParam<'a>>(&'a mut self, value: &T::Value) -> Result<bool, Error> {
538        let value = ok!(CellBuilder::build_from(T::Wrapper::wrap_inner(value)));
539        self.set_raw(T::ID, value)
540    }
541
542    /// Tries to get a raw parameter from the blockchain config (as slice).
543    pub fn get_raw(&self, id: u32) -> Result<Option<CellSlice<'_>>, Error> {
544        match ok!(self.get_raw_cell_ref(id)) {
545            Some(cell) => cell.as_slice().map(Some),
546            None => Ok(None),
547        }
548    }
549
550    /// Tries to get a raw parameter from the blockchain config (as cell).
551    pub fn get_raw_cell(&self, id: u32) -> Result<Option<Cell>, Error> {
552        match ok!(self.0.get_raw(id)) {
553            Some(slice) => match slice.get_reference_cloned(0) {
554                Ok(cell) => Ok(Some(cell)),
555                Err(e) => Err(e),
556            },
557            None => Ok(None),
558        }
559    }
560
561    /// Tries to get a raw parameter from the blockchain config (as cell ref).
562    pub fn get_raw_cell_ref(&self, id: u32) -> Result<Option<&'_ DynCell>, Error> {
563        match ok!(self.0.get_raw(id)) {
564            Some(slice) => match slice.get_reference(0) {
565                Ok(cell) => Ok(Some(cell)),
566                Err(e) => Err(e),
567            },
568            None => Ok(None),
569        }
570    }
571
572    /// Tries to set a parameter in the blockchain config.
573    ///
574    /// NOTE: Use with caution, as it doesn't check the value structure.
575    pub fn set_raw(&mut self, id: u32, value: Cell) -> Result<bool, Error> {
576        self.0.set(id, value)
577    }
578
579    /// Removes a parameter from the blockchain config.
580    ///
581    /// NOTE: Removing a zero parameter successfully does nothing
582    /// and returns `None` as it is required and externaly managed.
583    pub fn remove(&mut self, id: u32) -> Result<Option<Cell>, Error> {
584        if id == 0 {
585            return Ok(None);
586        }
587        self.0.remove(id)
588    }
589
590    /// Returns a reference to the underlying dictionary.
591    pub fn as_dict(&self) -> &Dict<u32, Cell> {
592        &self.0
593    }
594}
595
596impl Store for BlockchainConfigParams {
597    fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
598        match self.0.root() {
599            Some(root) => builder.store_reference(root.clone()),
600            None => Err(Error::InvalidData),
601        }
602    }
603}
604
605impl<'a> Load<'a> for BlockchainConfigParams {
606    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
607        let root = ok!(slice.load_reference_cloned());
608        Ok(Self(Dict::from(Some(root))))
609    }
610}
611
612/// Marker trait which is implemented for known config params.
613pub trait KnownConfigParam<'a> {
614    /// Parameter index in a configuration dictionary.
615    const ID: u32;
616
617    /// Associated value type.
618    type Value;
619
620    /// Value wrapper.
621    type Wrapper: ConfigParamWrapper<Self::Value> + Store + Load<'a>;
622}
623
624/// Trait to customize config param representation.
625pub trait ConfigParamWrapper<T> {
626    /// Converts this wrapper into an underlying type.
627    fn into_inner(self) -> T;
628
629    /// Converts an inner type into a wrapper.
630    fn wrap_inner(inner: &T) -> &Self;
631}
632
633/// Identity wrapper for [`ConfigParamWrapper`].
634#[repr(transparent)]
635pub struct ParamIdentity<T>(T);
636
637impl<T> ConfigParamWrapper<T> for ParamIdentity<T> {
638    #[inline]
639    fn into_inner(self) -> T {
640        self.0
641    }
642
643    #[inline]
644    fn wrap_inner(inner: &T) -> &Self {
645        // SAFETY: `ParamIdentity` is a transparent wrapper.
646        unsafe { &*(inner as *const T).cast() }
647    }
648}
649
650impl<'a, T: Load<'a>> Load<'a> for ParamIdentity<T> {
651    #[inline]
652    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
653        match T::load_from(slice) {
654            Ok(value) => Ok(Self(value)),
655            Err(e) => Err(e),
656        }
657    }
658}
659
660impl<T: Store> Store for ParamIdentity<T> {
661    #[inline]
662    fn store_into(&self, builder: &mut CellBuilder, cx: &dyn CellContext) -> Result<(), Error> {
663        self.0.store_into(builder, cx)
664    }
665}
666
667#[cfg(feature = "serde")]
668impl<T: serde::Serialize> serde::Serialize for ParamIdentity<T> {
669    #[inline]
670    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
671        self.0.serialize(serializer)
672    }
673}
674
675#[cfg(feature = "serde")]
676impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for ParamIdentity<T> {
677    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
678    where
679        D: serde::Deserializer<'de>,
680    {
681        T::deserialize(deserializer).map(Self)
682    }
683}
684
685/// Dict wrapper for [`ConfigParamWrapper`] for parsing non-empty dictionaries.
686#[repr(transparent)]
687pub struct NonEmptyDict<T>(T);
688
689impl<T> ConfigParamWrapper<T> for NonEmptyDict<T> {
690    fn into_inner(self) -> T {
691        self.0
692    }
693
694    #[inline]
695    fn wrap_inner(inner: &T) -> &Self {
696        // SAFETY: `NonEmptyDict` is a transparent wrapper.
697        unsafe { &*(inner as *const T).cast() }
698    }
699}
700
701impl<'a, K, V> Load<'a> for NonEmptyDict<Dict<K, V>>
702where
703    K: DictKey,
704{
705    #[inline]
706    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
707        match Dict::load_from_root_ext(slice, Cell::empty_context()) {
708            Ok(value) => Ok(Self(value)),
709            Err(e) => Err(e),
710        }
711    }
712}
713
714impl<K, V> Store for NonEmptyDict<Dict<K, V>> {
715    fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
716        match self.0.root() {
717            Some(root) => builder.store_slice(ok!(root.as_slice())),
718            None => Err(Error::InvalidData),
719        }
720    }
721}
722
723#[cfg(feature = "serde")]
724impl serde::Serialize for NonEmptyDict<Dict<u32, ()>> {
725    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
726        use serde::ser::SerializeSeq;
727
728        let mut seq = serializer.serialize_seq(None)?;
729        for entry in self.0.iter() {
730            match entry {
731                Ok((key, _)) => ok!(seq.serialize_element(&key)),
732                Err(e) => return Err(serde::ser::Error::custom(e)),
733            }
734        }
735        seq.end()
736    }
737}
738
739#[cfg(feature = "serde")]
740impl<'de> serde::Deserialize<'de> for NonEmptyDict<Dict<u32, ()>> {
741    #[inline]
742    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
743        use serde::de::Error;
744
745        let parsed = ok!(Vec::<u32>::deserialize(deserializer));
746        if parsed.is_empty() {
747            return Err(Error::custom("dictionary is empty"));
748        }
749
750        let mut res = Dict::new();
751        for item in parsed {
752            ok!(res.set(item, ()).map_err(Error::custom));
753        }
754
755        Ok(Self(res))
756    }
757}
758
759#[cfg(feature = "serde")]
760impl serde::Serialize for NonEmptyDict<Dict<u32, StoragePrices>> {
761    #[inline]
762    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
763        self.0.serialize(serializer)
764    }
765}
766
767#[cfg(feature = "serde")]
768impl<'de> serde::Deserialize<'de> for NonEmptyDict<Dict<u32, StoragePrices>> {
769    #[inline]
770    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
771        let res = ok!(Dict::deserialize(deserializer));
772        if res.is_empty() {
773            return Err(serde::de::Error::custom("dictionary is empty"));
774        }
775        Ok(Self(res))
776    }
777}
778
779macro_rules! define_config_params {
780    ($(
781        $(#[doc = $doc:expr])*
782        $(#[cfg($($cfg_attrs:tt)*)])?
783        $(#[serde($($serde_attrs:tt)*)])?
784        $id:literal => $ident:ident($($ty:tt)*)
785    ),*$(,)?) => {
786        $(
787            $(#[cfg($($cfg_attrs)*)])?
788            $(#[doc = $doc])*
789            pub struct $ident;
790
791            $(#[cfg($($cfg_attrs)*)])?
792            impl<'a> KnownConfigParam<'a> for $ident {
793                const ID: u32 = $id;
794
795                define_config_params!(@wrapper $($ty)*);
796            }
797        )*
798
799        #[cfg(feature = "serde")]
800        impl serde::Serialize for BlockchainConfigParams {
801            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
802            where
803                S: serde::Serializer,
804            {
805                use serde::ser::{Error, SerializeMap};
806
807                let dict = &self.0;
808                if !serializer.is_human_readable() {
809                    return crate::boc::BocRepr::serialize(dict, serializer);
810                }
811
812                let mut map = serializer.serialize_map(None)?;
813
814                for entry in dict.iter() {
815                    let (key, value) = match entry {
816                        Ok(entry) => entry,
817                        Err(e) => return Err(Error::custom(e)),
818                    };
819
820                    {
821                        match key {
822                            $(
823                                $(#[cfg($($cfg_attrs)*)])?
824                                $($id => {
825                                    let value = define_config_params!(
826                                        @ser
827                                        $ident,
828                                        value,
829                                        $($serde_attrs)*
830                                    );
831                                    ok!(map.serialize_entry(&key, &value));
832                                },)?
833                            )*
834                            _ => ok!(map.serialize_entry(&key, value.as_ref())),
835                        }
836                    }
837                }
838
839                map.end()
840            }
841        }
842
843        #[cfg(feature = "serde")]
844        impl<'de> serde::Deserialize<'de> for BlockchainConfigParams {
845            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
846            where
847                D: serde::Deserializer<'de>,
848            {
849                use serde::de::{Error, Visitor, MapAccess};
850
851                #[derive(serde::Deserialize)]
852                struct RawValue(#[serde(with = "crate::boc::Boc")] Cell);
853
854                struct MapVisitor;
855
856                impl<'de> Visitor<'de> for MapVisitor {
857                    type Value = BlockchainConfigParams;
858
859                    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
860                        f.write_str("a config params map")
861                    }
862
863                    fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
864                    where
865                        M: MapAccess<'de>,
866                    {
867                        let mut dict = Dict::new();
868
869                        while let Some(key) = access.next_key::<u32>()? {
870                            let value = match key {
871                                $(
872                                    $(#[cfg($($cfg_attrs)*)])?
873                                    $($id => define_config_params!(
874                                        @de
875                                        $ident,
876                                        access,
877                                        $($serde_attrs)*
878                                    ),)?
879                                )*
880                                _ => {
881                                    let RawValue(cell) = ok!(access.next_value());
882                                    cell
883                                }
884                            };
885                            ok!(dict.set(key, value).map_err(Error::custom));
886                        }
887
888                        Ok(BlockchainConfigParams(dict))
889                    }
890                }
891
892                if deserializer.is_human_readable() {
893                    deserializer.deserialize_map(MapVisitor)
894                } else {
895                    crate::boc::BocRepr::deserialize(deserializer)
896                }
897            }
898        }
899    };
900
901    (@wrapper $wrapper:ident => $($ty:tt)*) => {
902        type Value = $($ty)*;
903        type Wrapper = $wrapper<Self::Value>;
904    };
905    (@wrapper $($ty:tt)*) => {
906        type Value = $($ty)*;
907        type Wrapper = ParamIdentity<Self::Value>;
908    };
909
910    (@ser $ident:ident, $value:ident, transparent) => {{
911        ok!($value.parse::<<$ident as KnownConfigParam>::Wrapper>().map_err(Error::custom))
912    }};
913    (@ser $ident:ident, $value:ident, remote = $remote:ident) => {{
914        let value = ok!($value.parse::<<$ident as KnownConfigParam>::Wrapper>().map_err(Error::custom));
915        $remote(<<$ident as KnownConfigParam>::Wrapper>::into_inner(value))
916    }};
917
918    (@de $ident:ident, $access:ident, transparent) => {{
919        let parsed = ok!($access.next_value::<<$ident as KnownConfigParam>::Wrapper>());
920        ok!(CellBuilder::build_from(&parsed).map_err(Error::custom))
921    }};
922    (@de $ident:ident, $access:ident, remote = $remote:ident) => {{
923        let parsed = ok!($access.next_value::<$remote>());
924        ok!(CellBuilder::build_from(&parsed.0).map_err(Error::custom))
925    }};
926}
927
928define_config_params! {
929    /// Configuration account address (in masterchain).
930    #[serde(transparent)]
931    0 => ConfigParam0(HashBytes),
932
933    /// Elector account address (in masterchain).
934    #[serde(transparent)]
935    1 => ConfigParam1(HashBytes),
936
937    /// Minter account address (in masterchain).
938    #[serde(transparent)]
939    2 => ConfigParam2(HashBytes),
940
941    /// Fee collector account address (in masterchain).
942    #[serde(transparent)]
943    3 => ConfigParam3(HashBytes),
944
945    /// DNS root account address (in masterchain).
946    #[serde(transparent)]
947    4 => ConfigParam4(HashBytes),
948
949    /// Burning config.
950    #[serde(transparent)]
951    5 => ConfigParam5(BurningConfig),
952
953    /// Mint new price and mint add price (unused).
954    6 => ConfigParam6(CellSlice<'a>),
955
956    /// Target amount of minted extra currencies.
957    #[serde(transparent)]
958    7 => ConfigParam7(ExtraCurrencyCollection),
959
960    /// The lowest supported block version and required capabilities.
961    ///
962    /// Contains a [`GlobalVersion`].
963    #[serde(transparent)]
964    8 => ConfigParam8(GlobalVersion),
965
966    /// Params that must be present in config.
967    #[serde(transparent)]
968    9 => ConfigParam9(NonEmptyDict => Dict<u32, ()>),
969
970    /// Params that have a different set of update requirements.
971    #[serde(transparent)]
972    10 => ConfigParam10(NonEmptyDict => Dict<u32, ()>),
973
974    /// Config voting setup params.
975    ///
976    /// Contains a [`ConfigVotingSetup`].
977    #[serde(transparent)]
978    11 => ConfigParam11(ConfigVotingSetup),
979
980    /// Known workchain descriptions.
981    ///
982    /// Contains a dictionary with workchain id as key and [`WorkchainDescription`] as value.
983    #[serde(transparent)]
984    12 => ConfigParam12(Dict<i32, WorkchainDescription>),
985
986    /// Complaint pricing.
987    13 => ConfigParam13(CellSlice<'a>),
988
989    /// Block creation reward for masterchain and basechain.
990    ///
991    /// Contains a [`BlockCreationRewards`].
992    #[serde(transparent)]
993    14 => ConfigParam14(BlockCreationRewards),
994
995    /// Validators election timings.
996    ///
997    /// Contains [`ElectionTimings`].
998    #[serde(transparent)]
999    15 => ConfigParam15(ElectionTimings),
1000
1001    /// Range of number of validators.
1002    ///
1003    /// Contains a [`ValidatorCountParams`].
1004    #[serde(transparent)]
1005    16 => ConfigParam16(ValidatorCountParams),
1006
1007    /// Validator stake range and factor.
1008    ///
1009    /// Contains [`ValidatorStakeParams`]
1010    #[serde(transparent)]
1011    17 => ConfigParam17(ValidatorStakeParams),
1012
1013    /// Storage prices for different intervals of time.
1014    ///
1015    /// Contains a dictionary with a history of all [`StoragePrices`].
1016    #[serde(transparent)]
1017    18 => ConfigParam18(NonEmptyDict => Dict<u32, StoragePrices>),
1018
1019    /// Global ID.
1020    #[serde(transparent)]
1021    19 => ConfigParam19(i32),
1022
1023    /// Masterchain gas limits and prices.
1024    ///
1025    /// Contains [`GasLimitsPrices`].
1026    #[serde(transparent)]
1027    20 => ConfigParam20(GasLimitsPrices),
1028
1029    /// Base workchain gas limits and prices.
1030    ///
1031    /// Contains [`GasLimitsPrices`].
1032    #[serde(transparent)]
1033    21 => ConfigParam21(GasLimitsPrices),
1034
1035    /// Masterchain block limits.
1036    ///
1037    /// Contains [`BlockLimits`].
1038    #[serde(transparent)]
1039    22 => ConfigParam22(BlockLimits),
1040
1041    /// Base workchain block limits.
1042    ///
1043    /// Contains [`BlockLimits`].
1044    #[serde(transparent)]
1045    23 => ConfigParam23(BlockLimits),
1046
1047    /// Message forwarding prices for masterchain.
1048    ///
1049    /// Contains [`MsgForwardPrices`].
1050    #[serde(transparent)]
1051    24 => ConfigParam24(MsgForwardPrices),
1052
1053    /// Message forwarding prices for base workchain.
1054    ///
1055    /// Contains [`MsgForwardPrices`].
1056    #[serde(transparent)]
1057    25 => ConfigParam25(MsgForwardPrices),
1058
1059    /// Catchain configuration params.
1060    ///
1061    /// Contains a [`CatchainConfig`].
1062    #[cfg(not(feature = "tycho"))]
1063    #[serde(transparent)]
1064    28 => ConfigParam28(CatchainConfig),
1065
1066    /// Collation configuration params.
1067    ///
1068    /// Contains a [`CollationConfig`].
1069    #[cfg(feature = "tycho")]
1070    #[serde(transparent)]
1071    28 => ConfigParam28(CollationConfig),
1072
1073    /// Consensus configuration params.
1074    ///
1075    /// Contains a [`ConsensusConfig`].
1076    #[serde(transparent)]
1077    29 => ConfigParam29(ConsensusConfig),
1078
1079    /// Delector configuration params.
1080    30 => ConfigParam30(CellSlice<'a>),
1081
1082    /// Fundamental smartcontract addresses.
1083    ///
1084    /// Contains a dictionary with addresses (in masterchain) of fundamental contracts as keys.
1085    #[serde(remote = HashBytesList)]
1086    31 => ConfigParam31(Dict<HashBytes, ()>),
1087
1088    /// Previous validator set.
1089    ///
1090    /// Contains a [`ValidatorSet`].
1091    #[serde(transparent)]
1092    32 => ConfigParam32(ValidatorSet),
1093
1094    /// Previous temporary validator set.
1095    ///
1096    /// Contains a [`ValidatorSet`].
1097    #[serde(transparent)]
1098    33 => ConfigParam33(ValidatorSet),
1099
1100    /// Current validator set.
1101    ///
1102    /// Contains a [`ValidatorSet`].
1103    #[serde(transparent)]
1104    34 => ConfigParam34(ValidatorSet),
1105
1106    /// Current temporary validator set.
1107    ///
1108    /// Contains a [`ValidatorSet`].
1109    #[serde(transparent)]
1110    35 => ConfigParam35(ValidatorSet),
1111
1112    /// Next validator set.
1113    ///
1114    /// Contains a [`ValidatorSet`].
1115    #[serde(transparent)]
1116    36 => ConfigParam36(ValidatorSet),
1117
1118    /// Next temporary validator set.
1119    ///
1120    /// Contains a [`ValidatorSet`].
1121    #[serde(transparent)]
1122    37 => ConfigParam37(ValidatorSet),
1123
1124    /// Size limits.
1125    ///
1126    /// Contains a [`SizeLimitsConfig`].
1127    #[serde(transparent)]
1128    43 => ConfigParam43(SizeLimitsConfig),
1129
1130    /// Mint once config (can be used by L2 to mint native currency).
1131    ///
1132    /// Contains a [`MintOnceConfig`].
1133    #[serde(transparent)]
1134    50 => ConfigParam50(MintOnceConfig),
1135}
1136
1137#[cfg(feature = "serde")]
1138#[repr(transparent)]
1139struct HashBytesList(Dict<HashBytes, ()>);
1140
1141#[cfg(feature = "serde")]
1142impl serde::Serialize for HashBytesList {
1143    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1144        use serde::ser::SerializeSeq;
1145
1146        let mut seq = serializer.serialize_seq(None)?;
1147        for entry in self.0.iter() {
1148            match entry {
1149                Ok((ref key, _)) => ok!(seq.serialize_element(key)),
1150                Err(e) => return Err(serde::ser::Error::custom(e)),
1151            }
1152        }
1153        seq.end()
1154    }
1155}
1156
1157#[cfg(feature = "serde")]
1158impl<'de> serde::Deserialize<'de> for HashBytesList {
1159    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1160    where
1161        D: serde::Deserializer<'de>,
1162    {
1163        use serde::de::Error;
1164
1165        let parsed = ok!(Vec::<HashBytes>::deserialize(deserializer));
1166
1167        let mut res = Dict::new();
1168        for item in parsed {
1169            ok!(res.set(item, ()).map_err(Error::custom));
1170        }
1171
1172        Ok(Self(res))
1173    }
1174}