use tycho_types::cell::HashBytes;
use tycho_types::merkle::MerkleUpdate;
use tycho_types::models::{
BlockExtra, BlockId, BlockInfo, BlockRef, BlockchainConfig, McBlockExtra, McStateExtra,
OutMsgQueueUpdates, PrevBlockRef, ShardDescription, ShardFeeCreated, ShardIdent,
ShardStateUnsplit, ValueFlow,
};
use tycho_util::FastHashMap;
use crate::types::DebugDisplay;
use crate::types::processed_upto::ProcessedUptoInfoStuff;
pub struct BlockDebugInfo<'a> {
pub block_id: &'a BlockId,
pub block_info: &'a BlockInfo,
pub prev_ref: &'a PrevBlockRef,
pub state: &'a ShardStateUnsplit,
pub processed_upto: &'a ProcessedUptoInfoStuff,
pub out_msg_queue_updates: &'a OutMsgQueueUpdates,
pub value_flow: &'a ValueFlow,
pub mc_state_extra: Option<&'a McStateExtra>,
pub mc_top_shards: Option<&'a FastHashMap<ShardIdent, Box<ShardDescription>>>,
pub merkle_update_hash: &'a HashBytes,
pub merkle_update: &'a MerkleUpdate,
pub block_extra: &'a BlockExtra,
pub mc_block_extra: Option<&'a McBlockExtra>,
}
impl std::fmt::Debug for BlockDebugInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = f.debug_struct("BlockDebugInfo");
s.field("block_id", &DebugDisplay(self.block_id))
.field("info", &DebugBlockInfo(self.block_info))
.field("prev_ref", &DebugPrevRef(self.prev_ref))
.field("state", &DebugShardStateUnslit(self.state));
if let Some(mc_state_extra) = self.mc_state_extra {
s.field("mc_state_extra", &DebugMcStateExtra(mc_state_extra));
}
if let Some(mc_top_shards) = self.mc_top_shards {
s.field("mc_top_shards", &DebugTopShards(mc_top_shards));
}
s.field("value_flow", &DebugValueFlow(self.value_flow))
.field("processed_upto", self.processed_upto)
.field("out_msg_queue_updates", self.out_msg_queue_updates)
.field("merkle_update.hash", self.merkle_update_hash)
.field("merkle_update", &DebugMerkleUpdate(self.merkle_update))
.field("block_extra", &DebugBlockExtra(self.block_extra));
if let Some(mc_block_extra) = self.mc_block_extra {
s.field("mc_block_extra", &DebugMcBlockExtra(mc_block_extra));
}
s.finish()
}
}
pub struct DebugBlockInfo<'a>(pub &'a BlockInfo);
impl std::fmt::Debug for DebugBlockInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let gen_chain_time = self.0.gen_utime as u64 * 1000 + self.0.gen_utime_ms as u64;
f.debug_struct("BlockInfo")
.field("version", &self.0.version)
.field("flags", &self.0.flags)
.field("gen_chain_time", &gen_chain_time)
.field("start_lt", &self.0.start_lt)
.field("end_lt", &self.0.end_lt)
.field(
"gen_validator_list_hash_short",
&self.0.gen_validator_list_hash_short,
)
.field("gen_catchain_seqno", &self.0.gen_catchain_seqno)
.field("min_ref_mc_seqno", &self.0.min_ref_mc_seqno)
.field("prev_key_block_seqno", &self.0.prev_key_block_seqno)
.field("gen_software_version", &self.0.gen_software.version)
.field(
"gen_software_capabilities",
&self.0.gen_software.capabilities,
)
.finish()
}
}
pub struct DebugPrevRef<'a>(pub &'a PrevBlockRef);
impl std::fmt::Debug for DebugPrevRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.0 {
PrevBlockRef::Single(block_ref) => write!(f, "Single({})", DisplayBlockRef(block_ref)),
PrevBlockRef::AfterMerge { left, right } => f
.debug_struct("AfterMerge")
.field("left", &DisplayBlockRef(left))
.field("right", &DisplayBlockRef(right))
.finish(),
}
}
}
pub struct DisplayBlockRef<'a>(pub &'a BlockRef);
impl std::fmt::Debug for DisplayBlockRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}
impl std::fmt::Display for DisplayBlockRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"end_lt: {}, ref: {}:{}:{}",
self.0.end_lt, self.0.seqno, self.0.root_hash, self.0.file_hash
)
}
}
pub struct DebugShardStateUnslit<'a>(pub &'a ShardStateUnsplit);
impl std::fmt::Debug for DebugShardStateUnslit<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ShardStateUnsplit")
.field("global_id", &self.0.global_id)
.field(
"processed_upto.hash",
self.0.processed_upto.inner().repr_hash(),
)
.field("accounts.hash", self.0.accounts.inner().repr_hash())
.field("wu_used_from_last_anchor", &self.0.overload_history)
.field("shard_accounts_count", &self.0.underload_history)
.field(
"total_balance.tokens",
&DebugDisplay(self.0.total_balance.tokens),
)
.field(
"total_validator_fees.tokens",
&DebugDisplay(self.0.total_validator_fees.tokens),
)
.field(
"libraries.hash",
&self
.0
.libraries
.root()
.as_ref()
.map(|cell| cell.repr_hash()),
)
.field(
"master_ref",
&self.0.master_ref.as_ref().map(DisplayBlockRef),
)
.finish()
}
}
pub struct DebugMcStateExtra<'a>(pub &'a McStateExtra);
impl std::fmt::Debug for DebugMcStateExtra<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("McStateExtra")
.field("config", &DebugBlockchainConfig(&self.0.config))
.field(
"prev_blocks.hash",
&self
.0
.prev_blocks
.dict()
.root()
.as_ref()
.map(|cell| cell.repr_hash()),
)
.field("after_key_block", &self.0.after_key_block)
.field(
"last_key_block",
&self.0.last_key_block.as_ref().map(DisplayBlockRef),
)
.field(
"global_balance.tokens",
&DebugDisplay(self.0.global_balance.tokens),
)
.finish()
}
}
pub struct DebugBlockchainConfig<'a>(pub &'a BlockchainConfig);
impl std::fmt::Debug for DebugBlockchainConfig<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"params.hash: {:?}, address: {}",
self.0
.params
.as_dict()
.root()
.as_ref()
.map(|cell| cell.repr_hash()),
self.0.address,
)
}
}
pub struct DebugMerkleUpdate<'a>(pub &'a MerkleUpdate);
impl std::fmt::Debug for DebugMerkleUpdate<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MerkleUpdate")
.field("old_hash", &self.0.old_hash)
.field("new_hash", &self.0.new_hash)
.field("old_depth", &self.0.old_depth)
.field("new_depth", &self.0.new_depth)
.finish()
}
}
pub struct DebugBlockExtra<'a>(pub &'a BlockExtra);
impl std::fmt::Debug for DebugBlockExtra<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BlockExtra")
.field(
"in_msg_descr.hash",
self.0.in_msg_description.inner().repr_hash(),
)
.field(
"out_msg_descr.hash",
self.0.out_msg_description.inner().repr_hash(),
)
.field(
"account_blocks.hash",
self.0.account_blocks.inner().repr_hash(),
)
.field("rand_seed", &self.0.rand_seed)
.field("created_by", &self.0.created_by)
.finish()
}
}
pub struct DebugMcBlockExtra<'a>(pub &'a McBlockExtra);
impl std::fmt::Debug for DebugMcBlockExtra<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("McBlockExtra")
.field(
"fees.extra",
&DebugShardFeeCreated(self.0.fees.root_extra()),
)
.field("recover_create_msg", &self.0.recover_create_msg)
.field("mint_msg", &self.0.mint_msg)
.finish()
}
}
pub struct DebugShardFeeCreated<'a>(pub &'a ShardFeeCreated);
impl std::fmt::Debug for DebugShardFeeCreated<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ShardFeeCreated")
.field("fees.tokens", &DebugDisplay(self.0.fees.tokens))
.field("create.tokens", &DebugDisplay(self.0.create.tokens))
.finish()
}
}
pub struct DebugTopShards<'a>(pub &'a FastHashMap<ShardIdent, Box<ShardDescription>>);
impl std::fmt::Debug for DebugTopShards<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = f.debug_struct("McTopShards");
for (shard_id, shard) in self.0.iter() {
s.field("shard_id", &DebugDisplay(shard_id))
.field("shard_descr", &DebugShardDescription(shard));
}
s.finish()
}
}
pub struct DebugShardDescription<'a>(pub &'a ShardDescription);
impl std::fmt::Debug for DebugShardDescription<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ShardDescription")
.field("seqno", &self.0.seqno)
.field("reg_mc_seqno", &self.0.reg_mc_seqno)
.field("start_lt", &self.0.start_lt)
.field("end_lt", &self.0.end_lt)
.field("root_hash", &self.0.root_hash)
.field("file_hash", &self.0.file_hash)
.field(
"ext_processed_to_anchor_id",
&self.0.ext_processed_to_anchor_id,
)
.field("top_sc_block_updated", &self.0.top_sc_block_updated)
.field("min_ref_mc_seqno", &self.0.min_ref_mc_seqno)
.field("gen_utime", &self.0.gen_utime)
.field("fees_collected", &self.0.fees_collected.tokens)
.field("funds_created", &self.0.funds_created.tokens)
.finish()
}
}
pub struct DebugValueFlow<'a>(pub &'a ValueFlow);
impl std::fmt::Debug for DebugValueFlow<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn get_hash(
extra_currency: &tycho_types::models::ExtraCurrencyCollection,
) -> Option<&HashBytes> {
extra_currency
.as_dict()
.root()
.as_ref()
.map(|c| c.repr_hash())
}
f.debug_struct("ValueFlow")
.field("from_prev_block.tokens", &self.0.from_prev_block.tokens)
.field(
"from_prev_block.other.hash",
&get_hash(&self.0.from_prev_block.other),
)
.field("to_next_block.tokens", &self.0.to_next_block.tokens)
.field(
"to_next_block.other.hash",
&get_hash(&self.0.to_next_block.other),
)
.field("imported.tokens", &self.0.imported.tokens)
.field("imported.other.hash", &get_hash(&self.0.imported.other))
.field("exported.tokens", &self.0.exported.tokens)
.field("exported.other.hash", &get_hash(&self.0.exported.other))
.field("fees_collected.tokens", &self.0.fees_collected.tokens)
.field(
"fees_collected.other.hash",
&get_hash(&self.0.fees_collected.other),
)
.field("burned.tokens", &self.0.burned.tokens)
.field("burned.other.hash", &get_hash(&self.0.burned.other))
.field("fees_imported.tokens", &self.0.fees_imported.tokens)
.field(
"fees_imported.other.hash",
&get_hash(&self.0.fees_imported.other),
)
.field("recovered.tokens", &self.0.recovered.tokens)
.field("recovered.other.hash", &get_hash(&self.0.recovered.other))
.field("created.tokens", &self.0.created.tokens)
.field("created.other.hash", &get_hash(&self.0.created.other))
.field("minted.tokens", &self.0.minted.tokens)
.field("minted.other.hash", &get_hash(&self.0.minted.other))
.finish()
}
}