1#[cfg(feature = "sync")]
4use std::sync::OnceLock;
5
6pub use self::shard_accounts::*;
7pub use self::shard_extra::*;
8#[cfg(feature = "tycho")]
9use super::MsgsExecutionParams;
10use crate::cell::*;
11use crate::dict::Dict;
12use crate::error::*;
13use crate::models::block::{BlockRef, ShardIdent};
14use crate::models::currency::CurrencyCollection;
15#[cfg(feature = "tycho")]
16use crate::models::ShardIdentFull;
17
18mod shard_accounts;
19mod shard_extra;
20
21#[cfg(test)]
22mod tests;
23
24#[allow(clippy::large_enum_variant)]
26#[derive(Debug, Clone, Eq, PartialEq)]
27pub enum ShardState {
28 Unsplit(ShardStateUnsplit),
30 Split(ShardStateSplit),
32}
33
34impl Store for ShardState {
35 fn store_into(
36 &self,
37 builder: &mut CellBuilder,
38 context: &dyn CellContext,
39 ) -> Result<(), Error> {
40 match self {
41 Self::Unsplit(state) => state.store_into(builder, context),
42 Self::Split(state) => state.store_into(builder, context),
43 }
44 }
45}
46
47impl<'a> Load<'a> for ShardState {
48 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
49 Ok(if ok!(slice.get_bit(0)) {
50 match ShardStateUnsplit::load_from(slice) {
51 Ok(state) => Self::Unsplit(state),
52 Err(e) => return Err(e),
53 }
54 } else {
55 match ShardStateSplit::load_from(slice) {
56 Ok(state) => Self::Split(state),
57 Err(e) => return Err(e),
58 }
59 })
60 }
61}
62
63#[derive(Debug, Clone, Eq, PartialEq)]
115pub struct ShardStateUnsplit {
116 pub global_id: i32,
118 pub shard_ident: ShardIdent,
120 pub seqno: u32,
122 pub vert_seqno: u32,
124 pub gen_utime: u32,
126 #[cfg(feature = "tycho")]
128 pub gen_utime_ms: u16,
129 pub gen_lt: u64,
131 pub min_ref_mc_seqno: u32,
133
134 #[cfg(not(feature = "tycho"))]
136 pub out_msg_queue_info: Cell,
137
138 #[cfg(feature = "tycho")]
140 pub processed_upto: Lazy<ProcessedUptoInfo>,
141
142 pub before_split: bool,
144 pub accounts: Lazy<ShardAccounts>,
146 pub overload_history: u64,
148 pub underload_history: u64,
150 pub total_balance: CurrencyCollection,
152 pub total_validator_fees: CurrencyCollection,
154 pub libraries: Dict<HashBytes, LibDescr>,
156 pub master_ref: Option<BlockRef>,
158 pub custom: Option<Lazy<McStateExtra>>,
160}
161
162#[cfg(feature = "sync")]
163impl Default for ShardStateUnsplit {
164 fn default() -> Self {
165 Self {
166 global_id: 0,
167 shard_ident: ShardIdent::MASTERCHAIN,
168 seqno: 0,
169 vert_seqno: 0,
170 gen_utime: 0,
171 #[cfg(feature = "tycho")]
172 gen_utime_ms: 0,
173 gen_lt: 0,
174 min_ref_mc_seqno: 0,
175 #[cfg(not(feature = "tycho"))]
176 out_msg_queue_info: Cell::default(),
177 #[cfg(feature = "tycho")]
178 processed_upto: Self::empty_processed_upto_info().clone(),
179 before_split: false,
180 accounts: Self::empty_shard_accounts().clone(),
181 overload_history: 0,
182 underload_history: 0,
183 total_balance: CurrencyCollection::ZERO,
184 total_validator_fees: CurrencyCollection::ZERO,
185 libraries: Dict::new(),
186 master_ref: None,
187 custom: None,
188 }
189 }
190}
191
192impl ShardStateUnsplit {
193 const TAG_V1: u32 = 0x9023afe2;
194 #[cfg(feature = "tycho")]
195 const TAG_V2: u32 = 0x9023aeee;
196
197 #[cfg(all(feature = "sync", feature = "tycho"))]
199 pub fn empty_processed_upto_info() -> &'static Lazy<ProcessedUptoInfo> {
200 static PROCESSED_UPTO_INFO: OnceLock<Lazy<ProcessedUptoInfo>> = OnceLock::new();
201 PROCESSED_UPTO_INFO.get_or_init(|| Lazy::new(&ProcessedUptoInfo::default()).unwrap())
202 }
203
204 #[cfg(feature = "sync")]
206 pub fn empty_shard_accounts() -> &'static Lazy<ShardAccounts> {
207 static SHARD_ACCOUNTS: OnceLock<Lazy<ShardAccounts>> = OnceLock::new();
208 SHARD_ACCOUNTS.get_or_init(|| Lazy::new(&ShardAccounts::new()).unwrap())
209 }
210
211 pub fn load_accounts(&self) -> Result<ShardAccounts, Error> {
213 self.accounts.load()
214 }
215
216 pub fn load_custom(&self) -> Result<Option<McStateExtra>, Error> {
218 match &self.custom {
219 Some(custom) => match custom.load() {
220 Ok(custom) => Ok(Some(custom)),
221 Err(e) => Err(e),
222 },
223 None => Ok(None),
224 }
225 }
226
227 pub fn set_custom(&mut self, value: Option<&McStateExtra>) -> Result<(), Error> {
229 match (&mut self.custom, value) {
230 (None, None) => Ok(()),
231 (None, Some(value)) => {
232 self.custom = Some(ok!(Lazy::new(value)));
233 Ok(())
234 }
235 (Some(_), None) => {
236 self.custom = None;
237 Ok(())
238 }
239 (Some(custom), Some(value)) => custom.set(value),
240 }
241 }
242}
243
244impl Store for ShardStateUnsplit {
245 fn store_into(
246 &self,
247 builder: &mut CellBuilder,
248 context: &dyn CellContext,
249 ) -> Result<(), Error> {
250 let child_cell = {
251 let mut builder = CellBuilder::new();
252 ok!(builder.store_u64(self.overload_history));
253 ok!(builder.store_u64(self.underload_history));
254 ok!(self.total_balance.store_into(&mut builder, context));
255 ok!(self.total_validator_fees.store_into(&mut builder, context));
256 ok!(self.libraries.store_into(&mut builder, context));
257 ok!(self.master_ref.store_into(&mut builder, context));
258 ok!(builder.build_ext(context))
259 };
260
261 #[cfg(not(feature = "tycho"))]
262 ok!(builder.store_u32(Self::TAG_V1));
263 #[cfg(feature = "tycho")]
264 ok!(builder.store_u32(Self::TAG_V2));
265
266 ok!(builder.store_u32(self.global_id as u32));
267 ok!(self.shard_ident.store_into(builder, context));
268 ok!(builder.store_u32(self.seqno));
269 ok!(builder.store_u32(self.vert_seqno));
270 ok!(builder.store_u32(self.gen_utime));
271
272 #[cfg(feature = "tycho")]
273 ok!(builder.store_u16(self.gen_utime_ms));
274
275 ok!(builder.store_u64(self.gen_lt));
276 ok!(builder.store_u32(self.min_ref_mc_seqno));
277 #[cfg(not(feature = "tycho"))]
278 ok!(self.out_msg_queue_info.store_into(builder, context));
279 #[cfg(feature = "tycho")]
280 ok!(self.processed_upto.store_into(builder, context));
281 ok!(builder.store_bit(self.before_split));
282 ok!(builder.store_reference(self.accounts.inner().clone()));
283 ok!(builder.store_reference(child_cell));
284
285 ok!(self.custom.store_into(builder, context));
286
287 Ok(())
288 }
289}
290
291impl<'a> Load<'a> for ShardStateUnsplit {
292 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
293 let fast_finality = match slice.load_u32() {
294 Ok(Self::TAG_V1) => false,
295 #[cfg(feature = "tycho")]
296 Ok(Self::TAG_V2) => true,
297 Ok(_) => return Err(Error::InvalidTag),
298 Err(e) => return Err(e),
299 };
300
301 #[cfg(not(feature = "tycho"))]
302 let _ = fast_finality;
303
304 #[cfg(not(feature = "tycho"))]
305 let out_msg_queue_info = ok!(<_>::load_from(slice));
306
307 #[cfg(feature = "tycho")]
308 let processed_upto = ok!(Lazy::load_from(slice));
309
310 let accounts = ok!(Lazy::load_from(slice));
311
312 let child_slice = &mut ok!(slice.load_reference_as_slice());
313
314 let global_id = ok!(slice.load_u32()) as i32;
315 let shard_ident = ok!(ShardIdent::load_from(slice));
316
317 Ok(Self {
318 global_id,
319 shard_ident,
320 seqno: ok!(slice.load_u32()),
321 vert_seqno: ok!(slice.load_u32()),
322 gen_utime: ok!(slice.load_u32()),
323 #[cfg(feature = "tycho")]
324 gen_utime_ms: if fast_finality {
325 ok!(slice.load_u16())
326 } else {
327 0
328 },
329 gen_lt: ok!(slice.load_u64()),
330 min_ref_mc_seqno: ok!(slice.load_u32()),
331 before_split: ok!(slice.load_bit()),
332 accounts,
333 overload_history: ok!(child_slice.load_u64()),
334 underload_history: ok!(child_slice.load_u64()),
335 total_balance: ok!(CurrencyCollection::load_from(child_slice)),
336 total_validator_fees: ok!(CurrencyCollection::load_from(child_slice)),
337 libraries: ok!(Dict::load_from(child_slice)),
338 master_ref: ok!(Option::<BlockRef>::load_from(child_slice)),
339 #[cfg(not(feature = "tycho"))]
340 out_msg_queue_info,
341 #[cfg(feature = "tycho")]
342 processed_upto,
343 #[allow(unused_labels)]
344 custom: ok!(Option::<Lazy<McStateExtra>>::load_from(slice)),
345 })
346 }
347}
348
349#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
351#[tlb(tag = "#5f327da5")]
352pub struct ShardStateSplit {
353 pub left: Lazy<ShardStateUnsplit>,
355 pub right: Lazy<ShardStateUnsplit>,
357}
358
359#[derive(Debug, Clone, Eq, PartialEq)]
361pub struct LibDescr {
362 pub lib: Cell,
364 pub publishers: Dict<HashBytes, ()>,
366}
367
368impl Store for LibDescr {
369 fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
370 ok!(builder.store_small_uint(0, 2));
371 ok!(builder.store_reference(self.lib.clone()));
372 match self.publishers.root() {
373 Some(root) => builder.store_slice(root.as_slice_allow_exotic()),
374 None => Err(Error::InvalidData),
375 }
376 }
377}
378
379impl<'a> Load<'a> for LibDescr {
380 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
381 if ok!(slice.load_small_uint(2)) != 0 {
382 return Err(Error::InvalidTag);
383 }
384 Ok(Self {
385 lib: ok!(slice.load_reference_cloned()),
386 publishers: ok!(Dict::load_from_root_ext(slice, Cell::empty_context())),
387 })
388 }
389}
390
391#[cfg(feature = "tycho")]
403#[derive(Debug, Default, Clone, Store, Load)]
404#[tlb(tag = "#00")]
405pub struct ProcessedUptoInfo {
406 pub partitions: Dict<u16, ProcessedUptoPartition>,
409
410 pub msgs_exec_params: Option<Lazy<MsgsExecutionParams>>,
415}
416
417#[cfg(feature = "tycho")]
428#[derive(Debug, Default, Clone, Store, Load)]
429#[tlb(tag = "#00")]
430pub struct ProcessedUptoPartition {
431 pub externals: ExternalsProcessedUpto,
433
434 pub internals: InternalsProcessedUpto,
436}
437
438#[cfg(feature = "tycho")]
452#[derive(Debug, Default, Clone, Store, Load)]
453#[tlb(tag = "#00")]
454pub struct ExternalsProcessedUpto {
455 pub processed_to: (u32, u64),
459
460 pub ranges: Dict<u32, ExternalsRange>,
462}
463
464#[cfg(feature = "tycho")]
480#[derive(Debug, Default, Clone, Store, Load)]
481#[tlb(tag = "#00")]
482pub struct ExternalsRange {
483 pub from: (u32, u64),
485 pub to: (u32, u64),
487
488 pub chain_time: u64,
490
491 pub skip_offset: u32,
494 pub processed_offset: u32,
498}
499
500#[cfg(feature = "tycho")]
513#[derive(Debug, Default, Clone, Store, Load)]
514#[tlb(tag = "#00")]
515pub struct InternalsProcessedUpto {
516 pub processed_to: Dict<ShardIdentFull, (u64, HashBytes)>,
520
521 pub ranges: Dict<u32, InternalsRange>,
523}
524
525#[cfg(feature = "tycho")]
537#[derive(Debug, Default, Clone, Store, Load)]
538#[tlb(tag = "#00")]
539pub struct InternalsRange {
540 pub skip_offset: u32,
543 pub processed_offset: u32,
547
548 pub shards: Dict<ShardIdentFull, ShardRange>,
550}
551
552#[cfg(feature = "tycho")]
563#[derive(Debug, Default, Clone, Store, Load)]
564#[tlb(tag = "#00")]
565pub struct ShardRange {
566 pub from: u64,
568 pub to: u64,
570}