1pub 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#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct BlockchainConfig {
20 pub address: HashBytes,
22 pub params: BlockchainConfigParams,
24}
25
26impl BlockchainConfig {
27 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#[derive(Debug, Clone, Eq, PartialEq)]
56#[repr(transparent)]
57pub struct BlockchainConfigParams(Dict<u32, Cell>);
58
59impl BlockchainConfigParams {
60 pub fn from_raw(dict_root: Cell) -> Self {
64 Self(Dict::from_raw(Some(dict_root)))
65 }
66
67 pub fn get_elector_address(&self) -> Result<HashBytes, Error> {
71 ok!(self.get::<ConfigParam1>()).ok_or(Error::CellUnderflow)
72 }
73
74 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 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 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 pub fn get_burning_config(&self) -> Result<BurningConfig, Error> {
102 ok!(self.get::<ConfigParam5>()).ok_or(Error::CellUnderflow)
103 }
104
105 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 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 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 pub fn get_global_version(&self) -> Result<GlobalVersion, Error> {
133 ok!(self.get::<ConfigParam8>()).ok_or(Error::CellUnderflow)
134 }
135
136 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 pub fn get_mandatory_params(&self) -> Result<Dict<u32, ()>, Error> {
147 ok!(self.get::<ConfigParam9>()).ok_or(Error::CellUnderflow)
148 }
149
150 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 pub fn get_critical_params(&self) -> Result<Dict<u32, ()>, Error> {
168 ok!(self.get::<ConfigParam10>()).ok_or(Error::CellUnderflow)
169 }
170
171 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 pub fn get_workchains(&self) -> Result<Dict<i32, WorkchainDescription>, Error> {
189 ok!(self.get::<ConfigParam12>()).ok_or(Error::CellUnderflow)
190 }
191
192 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 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 pub fn get_block_creation_rewards(&self) -> Result<BlockCreationRewards, Error> {
218 ok!(self.get::<ConfigParam14>()).ok_or(Error::CellUnderflow)
219 }
220
221 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 pub fn get_election_timings(&self) -> Result<ElectionTimings, Error> {
235 ok!(self.get::<ConfigParam15>()).ok_or(Error::CellUnderflow)
236 }
237
238 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 pub fn get_validator_count_params(&self) -> Result<ValidatorCountParams, Error> {
249 ok!(self.get::<ConfigParam16>()).ok_or(Error::CellUnderflow)
250 }
251
252 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 pub fn get_validator_stake_params(&self) -> Result<ValidatorStakeParams, Error> {
266 ok!(self.get::<ConfigParam17>()).ok_or(Error::CellUnderflow)
267 }
268
269 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 pub fn get_storage_prices(&self) -> Result<Dict<u32, StoragePrices>, Error> {
283 ok!(self.get::<ConfigParam18>()).ok_or(Error::CellUnderflow)
284 }
285
286 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 pub fn get_global_id(&self) -> Result<i32, Error> {
302 ok!(self.get::<ConfigParam19>()).ok_or(Error::CellUnderflow)
303 }
304
305 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 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 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 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 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 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 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 #[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 #[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 #[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 #[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 pub fn get_consensus_config(&self) -> Result<ConsensusConfig, Error> {
433 ok!(self.get::<ConfigParam29>()).ok_or(Error::CellUnderflow)
434 }
435
436 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 pub fn get_fundamental_addresses(&self) -> Result<Dict<HashBytes, ()>, Error> {
447 ok!(self.get::<ConfigParam31>()).ok_or(Error::CellUnderflow)
448 }
449
450 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 pub fn contains_prev_validator_set(&self) -> Result<bool, Error> {
465 Ok(ok!(self.contains::<ConfigParam32>()) || ok!(self.contains::<ConfigParam33>()))
466 }
467
468 pub fn contains_next_validator_set(&self) -> Result<bool, Error> {
472 Ok(ok!(self.contains::<ConfigParam36>()) || ok!(self.contains::<ConfigParam37>()))
473 }
474
475 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 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 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 pub fn get_size_limits(&self) -> Result<SizeLimitsConfig, Error> {
507 ok!(self.get::<ConfigParam43>()).ok_or(Error::CellUnderflow)
508 }
509
510 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 pub fn get_authority_marks_config(&self) -> Result<AuthorityMarksConfig, Error> {
517 ok!(self.get::<ConfigParam100>()).ok_or(Error::CellUnderflow)
518 }
519
520 pub fn set_authority_marks_config(
522 &mut self,
523 params: &AuthorityMarksConfig,
524 ) -> Result<bool, Error> {
525 self.set_raw(ConfigParam100::ID, ok!(CellBuilder::build_from(params)))
526 }
527
528 pub fn contains<'a, T: KnownConfigParam<'a>>(&'a self) -> Result<bool, Error> {
530 self.0.contains_key(T::ID)
531 }
532
533 pub fn contains_raw(&self, id: u32) -> Result<bool, Error> {
535 self.0.contains_key(id)
536 }
537
538 pub fn get<'a, T: KnownConfigParam<'a>>(&'a self) -> Result<Option<T::Value>, Error> {
540 let Some(mut slice) = ok!(self.get_raw(T::ID)) else {
541 return Ok(None);
542 };
543 match <T::Wrapper as Load<'a>>::load_from(&mut slice) {
544 Ok(wrapped) => Ok(Some(wrapped.into_inner())),
545 Err(e) => Err(e),
546 }
547 }
548
549 pub fn set<'a, T: KnownConfigParam<'a>>(&'a mut self, value: &T::Value) -> Result<bool, Error> {
551 let value = ok!(CellBuilder::build_from(T::Wrapper::wrap_inner(value)));
552 self.set_raw(T::ID, value)
553 }
554
555 pub fn get_raw(&self, id: u32) -> Result<Option<CellSlice<'_>>, Error> {
557 match ok!(self.get_raw_cell_ref(id)) {
558 Some(cell) => cell.as_slice().map(Some),
559 None => Ok(None),
560 }
561 }
562
563 pub fn get_raw_cell(&self, id: u32) -> Result<Option<Cell>, Error> {
565 match ok!(self.0.get_raw(id)) {
566 Some(slice) => match slice.get_reference_cloned(0) {
567 Ok(cell) => Ok(Some(cell)),
568 Err(e) => Err(e),
569 },
570 None => Ok(None),
571 }
572 }
573
574 pub fn get_raw_cell_ref(&self, id: u32) -> Result<Option<&'_ DynCell>, Error> {
576 match ok!(self.0.get_raw(id)) {
577 Some(slice) => match slice.get_reference(0) {
578 Ok(cell) => Ok(Some(cell)),
579 Err(e) => Err(e),
580 },
581 None => Ok(None),
582 }
583 }
584
585 pub fn set_raw(&mut self, id: u32, value: Cell) -> Result<bool, Error> {
589 self.0.set(id, value)
590 }
591
592 pub fn remove(&mut self, id: u32) -> Result<Option<Cell>, Error> {
597 if id == 0 {
598 return Ok(None);
599 }
600 self.0.remove(id)
601 }
602
603 pub fn as_dict(&self) -> &Dict<u32, Cell> {
605 &self.0
606 }
607}
608
609impl Store for BlockchainConfigParams {
610 fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
611 match self.0.root() {
612 Some(root) => builder.store_reference(root.clone()),
613 None => Err(Error::InvalidData),
614 }
615 }
616}
617
618impl<'a> Load<'a> for BlockchainConfigParams {
619 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
620 let root = ok!(slice.load_reference_cloned());
621 Ok(Self(Dict::from(Some(root))))
622 }
623}
624
625pub trait KnownConfigParam<'a> {
627 const ID: u32;
629
630 type Value;
632
633 type Wrapper: ConfigParamWrapper<Self::Value> + Store + Load<'a>;
635}
636
637pub trait ConfigParamWrapper<T> {
639 fn into_inner(self) -> T;
641
642 fn wrap_inner(inner: &T) -> &Self;
644}
645
646#[repr(transparent)]
648pub struct ParamIdentity<T>(T);
649
650impl<T> ConfigParamWrapper<T> for ParamIdentity<T> {
651 #[inline]
652 fn into_inner(self) -> T {
653 self.0
654 }
655
656 #[inline]
657 fn wrap_inner(inner: &T) -> &Self {
658 unsafe { &*(inner as *const T).cast() }
660 }
661}
662
663impl<'a, T: Load<'a>> Load<'a> for ParamIdentity<T> {
664 #[inline]
665 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
666 match T::load_from(slice) {
667 Ok(value) => Ok(Self(value)),
668 Err(e) => Err(e),
669 }
670 }
671}
672
673impl<T: Store> Store for ParamIdentity<T> {
674 #[inline]
675 fn store_into(&self, builder: &mut CellBuilder, cx: &dyn CellContext) -> Result<(), Error> {
676 self.0.store_into(builder, cx)
677 }
678}
679
680#[cfg(feature = "serde")]
681impl<T: serde::Serialize> serde::Serialize for ParamIdentity<T> {
682 #[inline]
683 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
684 self.0.serialize(serializer)
685 }
686}
687
688#[cfg(feature = "serde")]
689impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for ParamIdentity<T> {
690 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
691 where
692 D: serde::Deserializer<'de>,
693 {
694 T::deserialize(deserializer).map(Self)
695 }
696}
697
698#[repr(transparent)]
700pub struct NonEmptyDict<T>(T);
701
702impl<T> ConfigParamWrapper<T> for NonEmptyDict<T> {
703 fn into_inner(self) -> T {
704 self.0
705 }
706
707 #[inline]
708 fn wrap_inner(inner: &T) -> &Self {
709 unsafe { &*(inner as *const T).cast() }
711 }
712}
713
714impl<'a, K, V> Load<'a> for NonEmptyDict<Dict<K, V>>
715where
716 K: DictKey,
717{
718 #[inline]
719 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
720 match Dict::load_from_root_ext(slice, Cell::empty_context()) {
721 Ok(value) => Ok(Self(value)),
722 Err(e) => Err(e),
723 }
724 }
725}
726
727impl<K, V> Store for NonEmptyDict<Dict<K, V>> {
728 fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
729 match self.0.root() {
730 Some(root) => builder.store_slice(ok!(root.as_slice())),
731 None => Err(Error::InvalidData),
732 }
733 }
734}
735
736#[cfg(feature = "serde")]
737impl serde::Serialize for NonEmptyDict<Dict<u32, ()>> {
738 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
739 use serde::ser::SerializeSeq;
740
741 let mut seq = serializer.serialize_seq(None)?;
742 for entry in self.0.iter() {
743 match entry {
744 Ok((key, _)) => ok!(seq.serialize_element(&key)),
745 Err(e) => return Err(serde::ser::Error::custom(e)),
746 }
747 }
748 seq.end()
749 }
750}
751
752#[cfg(feature = "serde")]
753impl<'de> serde::Deserialize<'de> for NonEmptyDict<Dict<u32, ()>> {
754 #[inline]
755 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
756 use serde::de::Error;
757
758 let parsed = ok!(Vec::<u32>::deserialize(deserializer));
759 if parsed.is_empty() {
760 return Err(Error::custom("dictionary is empty"));
761 }
762
763 let mut res = Dict::new();
764 for item in parsed {
765 ok!(res.set(item, ()).map_err(Error::custom));
766 }
767
768 Ok(Self(res))
769 }
770}
771
772#[cfg(feature = "serde")]
773impl serde::Serialize for NonEmptyDict<Dict<u32, StoragePrices>> {
774 #[inline]
775 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
776 self.0.serialize(serializer)
777 }
778}
779
780#[cfg(feature = "serde")]
781impl<'de> serde::Deserialize<'de> for NonEmptyDict<Dict<u32, StoragePrices>> {
782 #[inline]
783 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
784 let res = ok!(Dict::deserialize(deserializer));
785 if res.is_empty() {
786 return Err(serde::de::Error::custom("dictionary is empty"));
787 }
788 Ok(Self(res))
789 }
790}
791
792macro_rules! define_config_params {
793 ($(
794 $(#[doc = $doc:expr])*
795 $(#[cfg($($cfg_attrs:tt)*)])?
796 $(#[serde($($serde_attrs:tt)*)])?
797 $id:literal => $ident:ident($($ty:tt)*)
798 ),*$(,)?) => {
799 $(
800 $(#[cfg($($cfg_attrs)*)])?
801 $(#[doc = $doc])*
802 pub struct $ident;
803
804 $(#[cfg($($cfg_attrs)*)])?
805 impl<'a> KnownConfigParam<'a> for $ident {
806 const ID: u32 = $id;
807
808 define_config_params!(@wrapper $($ty)*);
809 }
810 )*
811
812 #[cfg(feature = "serde")]
813 impl serde::Serialize for BlockchainConfigParams {
814 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
815 where
816 S: serde::Serializer,
817 {
818 use serde::ser::{Error, SerializeMap};
819
820 let dict = &self.0;
821 if !serializer.is_human_readable() {
822 return crate::boc::BocRepr::serialize(dict, serializer);
823 }
824
825 let mut map = serializer.serialize_map(None)?;
826
827 for entry in dict.iter() {
828 let (key, value) = match entry {
829 Ok(entry) => entry,
830 Err(e) => return Err(Error::custom(e)),
831 };
832
833 {
834 match key {
835 $(
836 $(#[cfg($($cfg_attrs)*)])?
837 $($id => {
838 let value = define_config_params!(
839 @ser
840 $ident,
841 value,
842 $($serde_attrs)*
843 );
844 ok!(map.serialize_entry(&key, &value));
845 },)?
846 )*
847 _ => ok!(map.serialize_entry(&key, value.as_ref())),
848 }
849 }
850 }
851
852 map.end()
853 }
854 }
855
856 #[cfg(feature = "serde")]
857 impl<'de> serde::Deserialize<'de> for BlockchainConfigParams {
858 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
859 where
860 D: serde::Deserializer<'de>,
861 {
862 use serde::de::{Error, Visitor, MapAccess};
863
864 #[derive(serde::Deserialize)]
865 struct RawValue(#[serde(with = "crate::boc::Boc")] Cell);
866
867 struct MapVisitor;
868
869 impl<'de> Visitor<'de> for MapVisitor {
870 type Value = BlockchainConfigParams;
871
872 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
873 f.write_str("a config params map")
874 }
875
876 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
877 where
878 M: MapAccess<'de>,
879 {
880 let mut dict = Dict::new();
881
882 while let Some(key) = access.next_key::<u32>()? {
883 let value = match key {
884 $(
885 $(#[cfg($($cfg_attrs)*)])?
886 $($id => define_config_params!(
887 @de
888 $ident,
889 access,
890 $($serde_attrs)*
891 ),)?
892 )*
893 _ => {
894 let RawValue(cell) = ok!(access.next_value());
895 cell
896 }
897 };
898 ok!(dict.set(key, value).map_err(Error::custom));
899 }
900
901 Ok(BlockchainConfigParams(dict))
902 }
903 }
904
905 if deserializer.is_human_readable() {
906 deserializer.deserialize_map(MapVisitor)
907 } else {
908 crate::boc::BocRepr::deserialize(deserializer)
909 }
910 }
911 }
912 };
913
914 (@wrapper $wrapper:ident => $($ty:tt)*) => {
915 type Value = $($ty)*;
916 type Wrapper = $wrapper<Self::Value>;
917 };
918 (@wrapper $($ty:tt)*) => {
919 type Value = $($ty)*;
920 type Wrapper = ParamIdentity<Self::Value>;
921 };
922
923 (@ser $ident:ident, $value:ident, transparent) => {{
924 ok!($value.parse::<<$ident as KnownConfigParam>::Wrapper>().map_err(Error::custom))
925 }};
926 (@ser $ident:ident, $value:ident, remote = $remote:ident) => {{
927 let value = ok!($value.parse::<<$ident as KnownConfigParam>::Wrapper>().map_err(Error::custom));
928 $remote(<<$ident as KnownConfigParam>::Wrapper>::into_inner(value))
929 }};
930
931 (@de $ident:ident, $access:ident, transparent) => {{
932 let parsed = ok!($access.next_value::<<$ident as KnownConfigParam>::Wrapper>());
933 ok!(CellBuilder::build_from(&parsed).map_err(Error::custom))
934 }};
935 (@de $ident:ident, $access:ident, remote = $remote:ident) => {{
936 let parsed = ok!($access.next_value::<$remote>());
937 ok!(CellBuilder::build_from(&parsed.0).map_err(Error::custom))
938 }};
939}
940
941define_config_params! {
942 #[serde(transparent)]
944 0 => ConfigParam0(HashBytes),
945
946 #[serde(transparent)]
948 1 => ConfigParam1(HashBytes),
949
950 #[serde(transparent)]
952 2 => ConfigParam2(HashBytes),
953
954 #[serde(transparent)]
956 3 => ConfigParam3(HashBytes),
957
958 #[serde(transparent)]
960 4 => ConfigParam4(HashBytes),
961
962 #[serde(transparent)]
964 5 => ConfigParam5(BurningConfig),
965
966 6 => ConfigParam6(CellSlice<'a>),
968
969 #[serde(transparent)]
971 7 => ConfigParam7(ExtraCurrencyCollection),
972
973 #[serde(transparent)]
977 8 => ConfigParam8(GlobalVersion),
978
979 #[serde(transparent)]
981 9 => ConfigParam9(NonEmptyDict => Dict<u32, ()>),
982
983 #[serde(transparent)]
985 10 => ConfigParam10(NonEmptyDict => Dict<u32, ()>),
986
987 #[serde(transparent)]
991 11 => ConfigParam11(ConfigVotingSetup),
992
993 #[serde(transparent)]
997 12 => ConfigParam12(Dict<i32, WorkchainDescription>),
998
999 13 => ConfigParam13(CellSlice<'a>),
1001
1002 #[serde(transparent)]
1006 14 => ConfigParam14(BlockCreationRewards),
1007
1008 #[serde(transparent)]
1012 15 => ConfigParam15(ElectionTimings),
1013
1014 #[serde(transparent)]
1018 16 => ConfigParam16(ValidatorCountParams),
1019
1020 #[serde(transparent)]
1024 17 => ConfigParam17(ValidatorStakeParams),
1025
1026 #[serde(transparent)]
1030 18 => ConfigParam18(NonEmptyDict => Dict<u32, StoragePrices>),
1031
1032 #[serde(transparent)]
1034 19 => ConfigParam19(i32),
1035
1036 #[serde(transparent)]
1040 20 => ConfigParam20(GasLimitsPrices),
1041
1042 #[serde(transparent)]
1046 21 => ConfigParam21(GasLimitsPrices),
1047
1048 #[serde(transparent)]
1052 22 => ConfigParam22(BlockLimits),
1053
1054 #[serde(transparent)]
1058 23 => ConfigParam23(BlockLimits),
1059
1060 #[serde(transparent)]
1064 24 => ConfigParam24(MsgForwardPrices),
1065
1066 #[serde(transparent)]
1070 25 => ConfigParam25(MsgForwardPrices),
1071
1072 #[cfg(not(feature = "tycho"))]
1076 #[serde(transparent)]
1077 28 => ConfigParam28(CatchainConfig),
1078
1079 #[cfg(feature = "tycho")]
1083 #[serde(transparent)]
1084 28 => ConfigParam28(CollationConfig),
1085
1086 #[serde(transparent)]
1090 29 => ConfigParam29(ConsensusConfig),
1091
1092 30 => ConfigParam30(CellSlice<'a>),
1094
1095 #[serde(remote = HashBytesList)]
1099 31 => ConfigParam31(Dict<HashBytes, ()>),
1100
1101 #[serde(transparent)]
1105 32 => ConfigParam32(ValidatorSet),
1106
1107 #[serde(transparent)]
1111 33 => ConfigParam33(ValidatorSet),
1112
1113 #[serde(transparent)]
1117 34 => ConfigParam34(ValidatorSet),
1118
1119 #[serde(transparent)]
1123 35 => ConfigParam35(ValidatorSet),
1124
1125 #[serde(transparent)]
1129 36 => ConfigParam36(ValidatorSet),
1130
1131 #[serde(transparent)]
1135 37 => ConfigParam37(ValidatorSet),
1136
1137 #[serde(transparent)]
1141 43 => ConfigParam43(SizeLimitsConfig),
1142
1143 #[serde(transparent)]
1147 50 => ConfigParam50(MintOnceConfig),
1148
1149 #[serde(transparent)]
1153 100 => ConfigParam100(AuthorityMarksConfig),
1154}
1155
1156#[cfg(feature = "serde")]
1157#[repr(transparent)]
1158struct HashBytesList(Dict<HashBytes, ()>);
1159
1160#[cfg(feature = "serde")]
1161impl serde::Serialize for HashBytesList {
1162 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1163 use serde::ser::SerializeSeq;
1164
1165 let mut seq = serializer.serialize_seq(None)?;
1166 for entry in self.0.iter() {
1167 match entry {
1168 Ok((ref key, _)) => ok!(seq.serialize_element(key)),
1169 Err(e) => return Err(serde::ser::Error::custom(e)),
1170 }
1171 }
1172 seq.end()
1173 }
1174}
1175
1176#[cfg(feature = "serde")]
1177impl<'de> serde::Deserialize<'de> for HashBytesList {
1178 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1179 where
1180 D: serde::Deserializer<'de>,
1181 {
1182 use serde::de::Error;
1183
1184 let parsed = ok!(Vec::<HashBytes>::deserialize(deserializer));
1185
1186 let mut res = Dict::new();
1187 for item in parsed {
1188 ok!(res.set(item, ()).map_err(Error::custom));
1189 }
1190
1191 Ok(Self(res))
1192 }
1193}