everscale_types/models/config/
mod.rs

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