use crate::cell::*;
use crate::dict::RawDict;
use crate::error::*;
use crate::models::block::{BlockRef, ShardIdent};
use crate::models::currency::CurrencyCollection;
use crate::models::Lazy;
pub use self::shard_accounts::*;
pub use self::shard_extra::*;
#[cfg(feature = "venom")]
use super::ShardBlockRefs;
mod shard_accounts;
mod shard_extra;
#[cfg(test)]
mod tests;
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ShardState {
Unsplit(ShardStateUnsplit),
Split(ShardStateSplit),
}
impl Store for ShardState {
fn store_into(
&self,
builder: &mut CellBuilder,
finalizer: &mut dyn Finalizer,
) -> Result<(), Error> {
match self {
Self::Unsplit(state) => state.store_into(builder, finalizer),
Self::Split(state) => state.store_into(builder, finalizer),
}
}
}
impl<'a> Load<'a> for ShardState {
fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
Ok(if ok!(slice.get_bit(0)) {
match ShardStateUnsplit::load_from(slice) {
Ok(state) => Self::Unsplit(state),
Err(e) => return Err(e),
}
} else {
match ShardStateSplit::load_from(slice) {
Ok(state) => Self::Split(state),
Err(e) => return Err(e),
}
})
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ShardStateUnsplit {
pub global_id: i32,
pub shard_ident: ShardIdent,
pub seqno: u32,
pub vert_seqno: u32,
pub gen_utime: u32,
#[cfg(feature = "venom")]
pub gen_utime_ms: u16,
pub gen_lt: u64,
pub min_ref_mc_seqno: u32,
pub out_msg_queue_info: Cell,
pub before_split: bool,
pub accounts: Lazy<ShardAccounts>,
pub overload_history: u64,
pub underload_history: u64,
pub total_balance: CurrencyCollection,
pub total_validator_fees: CurrencyCollection,
pub libraries: RawDict<256>,
pub master_ref: Option<BlockRef>,
pub custom: Option<Lazy<McStateExtra>>,
#[cfg(feature = "venom")]
pub shard_block_refs: Option<ShardBlockRefs>,
}
impl ShardStateUnsplit {
const TAG_V1: u32 = 0x9023afe2;
#[cfg(feature = "venom")]
const TAG_V2: u32 = 0x9023aeee;
pub fn load_accounts(&self) -> Result<ShardAccounts, Error> {
self.accounts.load()
}
pub fn load_custom(&self) -> Result<Option<McStateExtra>, Error> {
match &self.custom {
Some(custom) => match custom.load() {
Ok(custom) => Ok(Some(custom)),
Err(e) => Err(e),
},
None => Ok(None),
}
}
}
impl Store for ShardStateUnsplit {
fn store_into(
&self,
builder: &mut CellBuilder,
finalizer: &mut dyn Finalizer,
) -> Result<(), Error> {
let child_cell = {
let mut builder = CellBuilder::new();
ok!(builder.store_u64(self.overload_history));
ok!(builder.store_u64(self.underload_history));
ok!(self.total_balance.store_into(&mut builder, finalizer));
ok!(self
.total_validator_fees
.store_into(&mut builder, finalizer));
ok!(self.libraries.store_into(&mut builder, finalizer));
ok!(self.master_ref.store_into(&mut builder, finalizer));
ok!(builder.build_ext(finalizer))
};
#[cfg(not(feature = "venom"))]
ok!(builder.store_u32(Self::TAG_V1));
#[cfg(feature = "venom")]
ok!(builder.store_u32(Self::TAG_V2));
ok!(builder.store_u32(self.global_id as u32));
ok!(self.shard_ident.store_into(builder, finalizer));
ok!(builder.store_u32(self.seqno));
ok!(builder.store_u32(self.vert_seqno));
ok!(builder.store_u32(self.gen_utime));
ok!(builder.store_u64(self.gen_lt));
ok!(builder.store_u32(self.min_ref_mc_seqno));
ok!(builder.store_reference(self.out_msg_queue_info.clone()));
ok!(builder.store_bit(self.before_split));
ok!(builder.store_reference(self.accounts.cell.clone()));
ok!(builder.store_reference(child_cell));
#[cfg(not(feature = "venom"))]
ok!(self.custom.store_into(builder, finalizer));
#[cfg(feature = "venom")]
if self.custom.is_some() && self.shard_block_refs.is_some() {
return Err(Error::InvalidData);
} else if let Some(refs) = &self.shard_block_refs {
ok!(refs.store_into(builder, finalizer));
} else {
ok!(self.custom.store_into(builder, finalizer));
}
Ok(())
}
}
impl<'a> Load<'a> for ShardStateUnsplit {
fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
let fast_finality = match slice.load_u32() {
Ok(Self::TAG_V1) => false,
#[cfg(feature = "venom")]
Ok(Self::TAG_V2) => true,
Ok(_) => return Err(Error::InvalidTag),
Err(e) => return Err(e),
};
#[cfg(not(feature = "venom"))]
let _ = fast_finality;
let out_msg_queue_info = ok!(slice.load_reference_cloned());
let accounts = ok!(Lazy::load_from(slice));
let child_slice = &mut ok!(slice.load_reference_as_slice());
let global_id = ok!(slice.load_u32()) as i32;
let shard_ident = ok!(ShardIdent::load_from(slice));
Ok(Self {
global_id,
shard_ident,
seqno: ok!(slice.load_u32()),
vert_seqno: ok!(slice.load_u32()),
gen_utime: ok!(slice.load_u32()),
#[cfg(feature = "venom")]
gen_utime_ms: if fast_finality {
ok!(slice.load_u16())
} else {
0
},
gen_lt: ok!(slice.load_u64()),
min_ref_mc_seqno: ok!(slice.load_u32()),
out_msg_queue_info,
before_split: ok!(slice.load_bit()),
accounts,
overload_history: ok!(child_slice.load_u64()),
underload_history: ok!(child_slice.load_u64()),
total_balance: ok!(CurrencyCollection::load_from(child_slice)),
total_validator_fees: ok!(CurrencyCollection::load_from(child_slice)),
libraries: ok!(RawDict::load_from(child_slice)),
master_ref: ok!(Option::<BlockRef>::load_from(child_slice)),
#[allow(unused_labels)]
custom: 'custom: {
#[cfg(feature = "venom")]
if !shard_ident.is_masterchain() {
break 'custom None;
}
ok!(Option::<Lazy<McStateExtra>>::load_from(slice))
},
#[cfg(feature = "venom")]
shard_block_refs: if shard_ident.is_masterchain() {
None
} else {
Some(ok!(ShardBlockRefs::load_from(slice)))
},
})
}
}
#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
#[tlb(tag = "#5f327da5")]
pub struct ShardStateSplit {
pub left: Lazy<ShardStateUnsplit>,
pub right: Lazy<ShardStateUnsplit>,
}