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 contains<'a, T: KnownConfigParam<'a>>(&'a self) -> Result<bool, Error> {
517 self.0.contains_key(T::ID)
518 }
519
520 pub fn contains_raw(&self, id: u32) -> Result<bool, Error> {
522 self.0.contains_key(id)
523 }
524
525 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 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 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 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 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 pub fn set_raw(&mut self, id: u32, value: Cell) -> Result<bool, Error> {
576 self.0.set(id, value)
577 }
578
579 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 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
612pub trait KnownConfigParam<'a> {
614 const ID: u32;
616
617 type Value;
619
620 type Wrapper: ConfigParamWrapper<Self::Value> + Store + Load<'a>;
622}
623
624pub trait ConfigParamWrapper<T> {
626 fn into_inner(self) -> T;
628
629 fn wrap_inner(inner: &T) -> &Self;
631}
632
633#[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 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#[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 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 #[serde(transparent)]
931 0 => ConfigParam0(HashBytes),
932
933 #[serde(transparent)]
935 1 => ConfigParam1(HashBytes),
936
937 #[serde(transparent)]
939 2 => ConfigParam2(HashBytes),
940
941 #[serde(transparent)]
943 3 => ConfigParam3(HashBytes),
944
945 #[serde(transparent)]
947 4 => ConfigParam4(HashBytes),
948
949 #[serde(transparent)]
951 5 => ConfigParam5(BurningConfig),
952
953 6 => ConfigParam6(CellSlice<'a>),
955
956 #[serde(transparent)]
958 7 => ConfigParam7(ExtraCurrencyCollection),
959
960 #[serde(transparent)]
964 8 => ConfigParam8(GlobalVersion),
965
966 #[serde(transparent)]
968 9 => ConfigParam9(NonEmptyDict => Dict<u32, ()>),
969
970 #[serde(transparent)]
972 10 => ConfigParam10(NonEmptyDict => Dict<u32, ()>),
973
974 #[serde(transparent)]
978 11 => ConfigParam11(ConfigVotingSetup),
979
980 #[serde(transparent)]
984 12 => ConfigParam12(Dict<i32, WorkchainDescription>),
985
986 13 => ConfigParam13(CellSlice<'a>),
988
989 #[serde(transparent)]
993 14 => ConfigParam14(BlockCreationRewards),
994
995 #[serde(transparent)]
999 15 => ConfigParam15(ElectionTimings),
1000
1001 #[serde(transparent)]
1005 16 => ConfigParam16(ValidatorCountParams),
1006
1007 #[serde(transparent)]
1011 17 => ConfigParam17(ValidatorStakeParams),
1012
1013 #[serde(transparent)]
1017 18 => ConfigParam18(NonEmptyDict => Dict<u32, StoragePrices>),
1018
1019 #[serde(transparent)]
1021 19 => ConfigParam19(i32),
1022
1023 #[serde(transparent)]
1027 20 => ConfigParam20(GasLimitsPrices),
1028
1029 #[serde(transparent)]
1033 21 => ConfigParam21(GasLimitsPrices),
1034
1035 #[serde(transparent)]
1039 22 => ConfigParam22(BlockLimits),
1040
1041 #[serde(transparent)]
1045 23 => ConfigParam23(BlockLimits),
1046
1047 #[serde(transparent)]
1051 24 => ConfigParam24(MsgForwardPrices),
1052
1053 #[serde(transparent)]
1057 25 => ConfigParam25(MsgForwardPrices),
1058
1059 #[cfg(not(feature = "tycho"))]
1063 #[serde(transparent)]
1064 28 => ConfigParam28(CatchainConfig),
1065
1066 #[cfg(feature = "tycho")]
1070 #[serde(transparent)]
1071 28 => ConfigParam28(CollationConfig),
1072
1073 #[serde(transparent)]
1077 29 => ConfigParam29(ConsensusConfig),
1078
1079 30 => ConfigParam30(CellSlice<'a>),
1081
1082 #[serde(remote = HashBytesList)]
1086 31 => ConfigParam31(Dict<HashBytes, ()>),
1087
1088 #[serde(transparent)]
1092 32 => ConfigParam32(ValidatorSet),
1093
1094 #[serde(transparent)]
1098 33 => ConfigParam33(ValidatorSet),
1099
1100 #[serde(transparent)]
1104 34 => ConfigParam34(ValidatorSet),
1105
1106 #[serde(transparent)]
1110 35 => ConfigParam35(ValidatorSet),
1111
1112 #[serde(transparent)]
1116 36 => ConfigParam36(ValidatorSet),
1117
1118 #[serde(transparent)]
1122 37 => ConfigParam37(ValidatorSet),
1123
1124 #[serde(transparent)]
1128 43 => ConfigParam43(SizeLimitsConfig),
1129
1130 #[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}