diff --git a/src/models/block/mod.rs b/src/models/block/mod.rs index 594f693b..ddde9d6b 100755 --- a/src/models/block/mod.rs +++ b/src/models/block/mod.rs @@ -40,12 +40,17 @@ pub struct Block { /// Merkle update for the shard state. pub state_update: Lazy, /// Merkle updates for the outgoing messages queue. + #[cfg(not(feature = "tycho"))] pub out_msg_queue_updates: Option>>, + /// Out messages queue info. + #[cfg(feature = "tycho")] + pub out_msg_queue_updates: OutMsgQueueUpdates, /// Block content. pub extra: Lazy, } impl Block { + #[cfg(not(feature = "tycho"))] const TAG_V1: u32 = 0x11ef55aa; const TAG_V2: u32 = 0x11ef55bb; @@ -88,30 +93,36 @@ impl Store for Block { builder: &mut CellBuilder, context: &mut dyn CellContext, ) -> Result<(), Error> { + #[cfg(not(feature = "tycho"))] let tag = if self.out_msg_queue_updates.is_none() { Self::TAG_V1 } else { Self::TAG_V2 }; + #[cfg(feature = "tycho")] + let tag = Self::TAG_V2; ok!(builder.store_u32(tag)); ok!(builder.store_u32(self.global_id as u32)); ok!(builder.store_reference(self.info.cell.clone())); ok!(builder.store_reference(self.value_flow.cell.clone())); - ok!( - if let Some(out_msg_queue_updates) = &self.out_msg_queue_updates { - let cell = { - let mut builder = CellBuilder::new(); - ok!(self.state_update.store_into(&mut builder, context)); - ok!(out_msg_queue_updates.store_into(&mut builder, context)); - ok!(builder.build_ext(context)) - }; - builder.store_reference(cell) - } else { - self.state_update.store_into(builder, context) - } - ); + #[cfg(not(feature = "tycho"))] + let out_msg_queue_updates = self.out_msg_queue_updates.as_ref(); + #[cfg(feature = "tycho")] + let out_msg_queue_updates = Some(&self.out_msg_queue_updates); + + ok!(if let Some(out_msg_queue_updates) = out_msg_queue_updates { + let cell = { + let mut builder = CellBuilder::new(); + ok!(self.state_update.store_into(&mut builder, context)); + ok!(out_msg_queue_updates.store_into(&mut builder, context)); + ok!(builder.build_ext(context)) + }; + builder.store_reference(cell) + } else { + self.state_update.store_into(builder, context) + }); self.extra.store_into(builder, context) } @@ -119,15 +130,23 @@ impl Store for Block { impl<'a> Load<'a> for Block { fn load_from(slice: &mut CellSlice<'a>) -> Result { + #[cfg(not(feature = "tycho"))] let with_out_msg_queue_updates = match ok!(slice.load_u32()) { Self::TAG_V1 => false, Self::TAG_V2 => true, _ => return Err(Error::InvalidTag), }; + #[cfg(feature = "tycho")] + if ok!(slice.load_u32()) != Self::TAG_V2 { + return Err(Error::InvalidTag); + } + let global_id = ok!(slice.load_u32()) as i32; let info = ok!(Lazy::load_from(slice)); let value_flow = ok!(Lazy::load_from(slice)); + + #[cfg(not(feature = "tycho"))] let (state_update, out_msg_queue_updates) = if with_out_msg_queue_updates { let slice = &mut ok!(slice.load_reference_as_slice()); ( @@ -138,6 +157,12 @@ impl<'a> Load<'a> for Block { (ok!(Lazy::load_from(slice)), None) }; + #[cfg(feature = "tycho")] + let (state_update, out_msg_queue_updates) = { + let slice = &mut ok!(slice.load_reference_as_slice()); + (ok!(<_>::load_from(slice)), ok!(<_>::load_from(slice))) + }; + Ok(Self { global_id, info, @@ -669,3 +694,13 @@ impl<'a> Load<'a> for ValueFlow { }) } } + +/// Outgoing message queue updates. +#[cfg(feature = "tycho")] +#[derive(Debug, Clone, Eq, PartialEq, Store, Load)] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[tlb(tag = "#1")] +pub struct OutMsgQueueUpdates { + /// Hash of the serialized queue diff. + pub diff_hash: HashBytes, +} diff --git a/src/models/block/tests/mod.rs b/src/models/block/tests/mod.rs index cb652af8..f39c87bc 100644 --- a/src/models/block/tests/mod.rs +++ b/src/models/block/tests/mod.rs @@ -351,3 +351,116 @@ fn proof_for_shardchain_block() { assert_eq!(serialize_any(proof).as_ref(), boc.as_ref()); } + +#[test] +#[cfg(feature = "tycho")] +fn block_with_tycho_updates_store_load() { + use crate::models::{ExtraCurrencyCollection, GlobalCapabilities}; + + let block = Block { + global_id: 42, + info: Lazy::new(&BlockInfo { + version: 0, + gen_utime_ms: 123, + after_merge: false, + before_split: false, + after_split: false, + want_split: false, + want_merge: true, + key_block: false, + flags: 1, + seqno: 24721433, + vert_seqno: 0, + shard: ShardIdent::new(-1, 0x8000000000000000).unwrap(), + gen_utime: 1674507085, + start_lt: 34671157000000, + end_lt: 34671157000005, + gen_validator_list_hash_short: 3236125243, + gen_catchain_seqno: 343054, + min_ref_mc_seqno: 24721430, + prev_key_block_seqno: 24715347, + gen_software: GlobalVersion { + version: 34, + capabilities: GlobalCapabilities::new(464814), + }, + master_ref: None, + prev_ref: Cell::empty_cell(), + prev_vert_ref: None, + }) + .unwrap(), + value_flow: Lazy::new(&ValueFlow { + from_prev_block: CurrencyCollection { + tokens: Tokens::new(3610625966274374005), + other: ExtraCurrencyCollection::new(), + }, + to_next_block: CurrencyCollection { + tokens: Tokens::new(3610625969470214036), + other: ExtraCurrencyCollection::new(), + }, + imported: CurrencyCollection { + tokens: Tokens::new(0), + other: ExtraCurrencyCollection::new(), + }, + exported: CurrencyCollection { + tokens: Tokens::new(0), + other: ExtraCurrencyCollection::new(), + }, + fees_collected: CurrencyCollection { + tokens: Tokens::new(3195840031), + other: ExtraCurrencyCollection::new(), + }, + fees_imported: CurrencyCollection { + tokens: Tokens::new(1495840031), + other: ExtraCurrencyCollection::new(), + }, + recovered: CurrencyCollection { + tokens: Tokens::new(3195840031), + other: ExtraCurrencyCollection::new(), + }, + created: CurrencyCollection { + tokens: Tokens::new(1700000000), + other: ExtraCurrencyCollection::new(), + }, + minted: CurrencyCollection { + tokens: Tokens::new(0), + other: ExtraCurrencyCollection::new(), + }, + copyleft_rewards: Dict::new(), + }) + .unwrap(), + state_update: Lazy::new(&MerkleUpdate { + old_hash: HashBytes::ZERO, + new_hash: HashBytes::ZERO, + old_depth: 182, + new_depth: 182, + old: Cell::empty_cell(), + new: Cell::empty_cell(), + }) + .unwrap(), + extra: Lazy::new(&BlockExtra { + in_msg_description: Lazy::new(&AugDict::new()).unwrap(), + out_msg_description: Lazy::new(&AugDict::new()).unwrap(), + account_blocks: Lazy::new(&AugDict::new()).unwrap(), + rand_seed: HashBytes::ZERO, + created_by: HashBytes::ZERO, + custom: None, + }) + .unwrap(), + out_msg_queue_updates: OutMsgQueueUpdates { + diff_hash: HashBytes::ZERO, + }, + }; + let encoded = BocRepr::encode(&block).unwrap(); + + let cell = Boc::decode(&*encoded).unwrap(); + + let decoded = cell.parse::().unwrap(); + assert_eq!(decoded, block); + + assert_eq!( + decoded.out_msg_queue_updates, + OutMsgQueueUpdates { + diff_hash: HashBytes::ZERO, + } + ); +}