pub fn log_debug_epoch_computation(
epoch_arena_index: usize, inner: &mut ConsensusGraphInner,
executor: &ConsensusExecutor, block_hash: H256, block_height: u64,
state_root: &StateRootWithAuxInfo,
) -> ComputeEpochDebugRecord {
let parent_arena_index = inner.arena[epoch_arena_index].parent;
let parent_epoch_hash = inner.arena[parent_arena_index].hash;
let parent_state_root = inner
.data_man
.get_epoch_execution_commitment(&parent_epoch_hash)
.unwrap()
.state_root_with_aux_info
.clone();
let reward_index = inner.get_pivot_reward_index(epoch_arena_index);
let reward_execution_info =
executor.get_reward_execution_info_from_index(inner, reward_index);
let task = EpochExecutionTask::new(
epoch_arena_index,
inner,
reward_execution_info,
false, false, );
let mut debug_record = ComputeEpochDebugRecord::default();
{
debug_record.block_height = block_height;
debug_record.block_hash = block_hash;
debug_record.state_root_after_applying_rewards = state_root.clone();
debug_record.parent_epoch_hash = parent_epoch_hash;
debug_record.parent_state_root = parent_state_root;
debug_record.reward_epoch_hash =
if let Some((reward_epoch_block, _)) = reward_index.clone() {
Some(inner.arena[reward_epoch_block].hash)
} else {
None
};
debug_record.anticone_penalty_cutoff_epoch_hash =
if let Some((_, anticone_penalty_cutoff_epoch_block)) =
reward_index.clone()
{
Some(inner.arena[anticone_penalty_cutoff_epoch_block].hash)
} else {
None
};
let epoch_block_hashes =
inner.get_epoch_block_hashes(epoch_arena_index);
let blocks = epoch_block_hashes
.iter()
.map(|hash| {
inner
.data_man
.block_by_hash(hash, false )
.unwrap()
})
.collect::<Vec<_>>();
debug_record.block_hashes = epoch_block_hashes;
debug_record.block_txs = blocks
.iter()
.map(|block| block.transactions.len())
.collect::<Vec<_>>();
debug_record.transactions = blocks
.iter()
.flat_map(|block| block.transactions.clone())
.collect::<Vec<_>>();
debug_record.block_authors = blocks
.iter()
.map(|block| *block.block_header.author())
.collect::<Vec<_>>();
}
executor.compute_epoch(task, Some(&mut debug_record), false);
debug_record
}
pub fn log_invalid_state_root(
deferred: usize, inner: &mut ConsensusGraphInner,
executor: &ConsensusExecutor, block_hash: H256, block_height: u64,
state_root: &StateRootWithAuxInfo,
) -> std::io::Result<()> {
if let Some(dump_dir) =
inner.inner_conf.debug_dump_dir_invalid_state_root.clone()
{
let invalid_state_root_path =
dump_dir.clone() + &format!("{}_{:?}", block_height, block_hash);
let txt_path = invalid_state_root_path.clone() + ".txt";
if Path::new(&txt_path).exists() {
return Ok(());
}
let debug_record = log_debug_epoch_computation(
deferred,
inner,
executor,
block_hash,
block_height,
state_root,
);
let deferred_block_hash = inner.arena[deferred].hash;
let got_state_root = inner
.data_man
.get_epoch_execution_commitment(&deferred_block_hash)
.unwrap()
.state_root_with_aux_info
.clone();
{
std::fs::create_dir_all(dump_dir)?;
let mut debug_file = File::create(&txt_path)?;
debug_file.write_all(format!("{:?}", debug_record).as_bytes())?;
let json_path = invalid_state_root_path + ".json.txt";
let mut json_file = File::create(&json_path)?;
json_file
.write_all(serde_json::to_string(&debug_record)?.as_bytes())?;
}
warn!(
"State debug recompute: got {:?}, deferred block: {:?}, block hash: {:?}\
reward epoch bock: {:?}, anticone cutoff block: {:?}, \
number of blocks in epoch: {:?}, number of transactions in epoch: {:?}, rewards: {:?}",
got_state_root,
deferred_block_hash,
block_hash,
debug_record.reward_epoch_hash,
debug_record.anticone_penalty_cutoff_epoch_hash,
debug_record.block_hashes.len(),
debug_record.transactions.len(),
debug_record.merged_rewards_by_author,
);
}
Ok(())
}
use crate::consensus::{
consensus_inner::consensus_executor::{
ConsensusExecutor, EpochExecutionTask,
},
ConsensusGraphInner,
};
use cfx_internal_common::{
debug::ComputeEpochDebugRecord, StateRootWithAuxInfo,
};
use cfx_types::H256;
use serde_json;
use std::{fs::File, io::Write, path::Path};