cfxcore/consensus/consensus_inner/
mod.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5mod blame_verifier;
6pub mod confirmation_meter;
7pub mod consensus_executor;
8pub mod consensus_new_block_handler;
9use cfxcore_errors::ProviderBlockError;
10use cfxcore_pow as pow;
11
12use pow::{PowComputer, ProofOfWorkConfig};
13
14use crate::{
15    block_data_manager::{
16        BlockDataManager, BlockExecutionResultWithEpoch, DataVersionTuple,
17        EpochExecutionContext,
18    },
19    consensus::{
20        anticone_cache::AnticoneCache,
21        consensus_inner::consensus_executor::ConsensusExecutor,
22        debug_recompute::log_invalid_state_root, pastset_cache::PastSetCache,
23        pos_handler::PosVerifier,
24    },
25    pos::pow_handler::POS_TERM_EPOCHS,
26    state_exposer::{ConsensusGraphBlockExecutionState, STATE_EXPOSER},
27    verification::VerificationConfig,
28};
29use cfx_internal_common::{
30    consensus_api::StateMaintenanceTrait, EpochExecutionCommitment,
31};
32use cfx_parameters::{consensus::*, consensus_internal::*};
33use cfx_types::{H256, U256, U512};
34use dag::{
35    get_future, topological_sort, Graph, RichDAG, RichTreeGraph, TreeGraph, DAG,
36};
37use hashbrown::HashMap as FastHashMap;
38use hibitset::{BitSet, BitSetLike, DrainableBitSet};
39use link_cut_tree::{CaterpillarMinLinkCutTree, SizeMinLinkCutTree};
40use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
41use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
42use metrics::{Counter, CounterUsize};
43use primitives::{
44    pos::PosBlockId, Block, BlockHeader, BlockHeaderBuilder, EpochId,
45};
46use slab::Slab;
47use std::{
48    cmp::{max, min},
49    collections::{BinaryHeap, HashMap, HashSet, VecDeque},
50    convert::TryFrom,
51    mem,
52    sync::Arc,
53};
54lazy_static! {
55    static ref INVALID_BLAME_OR_STATE_ROOT_COUNTER: Arc<dyn Counter<usize>> =
56        CounterUsize::register_with_group(
57            "system_metrics",
58            "invalid_blame_or_state_root_count"
59        );
60}
61
62#[derive(Clone)]
63pub struct ConsensusInnerConfig {
64    /// Beta is the threshold in GHAST algorithm
65    pub adaptive_weight_beta: u64,
66    /// The heavy block ratio (h) in GHAST algorithm
67    pub heavy_block_difficulty_ratio: u64,
68    /// The timer block ratio in timer chain algorithm
69    pub timer_chain_block_difficulty_ratio: u64,
70    /// The timer chain beta ratio
71    pub timer_chain_beta: u64,
72    /// The number of epochs per era. Each era is a potential checkpoint
73    /// position. The parent_edge checking and adaptive checking are defined
74    /// relative to the era start blocks.
75    pub era_epoch_count: u64,
76    /// Optimistic execution is the feature to execute ahead of the deferred
77    /// execution boundary. The goal is to pipeline the transaction
78    /// execution and the block packaging and verification.
79    /// optimistic_executed_height is the number of step to go ahead
80    pub enable_optimistic_execution: bool,
81    /// Control whether we enable the state exposer for the testing purpose.
82    pub enable_state_expose: bool,
83    /// The deferred epoch count before a confirmed epoch.
84    pub pos_pivot_decision_defer_epoch_count: u64,
85
86    pub cip113_pivot_decision_defer_epoch_count: u64,
87    pub cip113_transition_height: u64,
88
89    /// If we hit invalid state root, we will dump the information into a
90    /// directory specified here. This is useful for testing.
91    pub debug_dump_dir_invalid_state_root: Option<String>,
92    pub debug_invalid_state_root_epoch: Option<H256>,
93    pub force_recompute_height_during_construct_pivot: Option<u64>,
94    pub recovery_latest_mpt_snapshot: bool,
95    pub use_isolated_db_for_mpt_table: bool,
96}
97
98impl ConsensusInnerConfig {
99    pub fn pos_pivot_decision_defer_epoch_count(
100        &self, confirmed_height: u64,
101    ) -> u64 {
102        if confirmed_height >= self.cip113_transition_height {
103            self.cip113_pivot_decision_defer_epoch_count
104        } else {
105            self.pos_pivot_decision_defer_epoch_count
106        }
107    }
108}
109
110#[derive(Copy, Clone, DeriveMallocSizeOf)]
111pub struct StateBlameInfo {
112    pub blame: u32,
113    pub state_vec_root: H256,
114    pub receipts_vec_root: H256,
115    pub logs_bloom_vec_root: H256,
116}
117
118/// ConsensusGraphNodeData contains all extra information of a block that will
119/// change as the consensus graph state evolves (e.g., pivot chain changes).
120/// Unlike the ConsensusGraphNode fields, fields in ConsensusGraphNodeData will
121/// only be available after the block is *preactivated* (after calling
122/// preactivate_block().
123#[derive(DeriveMallocSizeOf)]
124pub struct ConsensusGraphNodeData {
125    /// It indicates the epoch number of the block, i.e., the height of the
126    /// corresponding pivot chain block of this one
127    pub epoch_number: u64,
128    /// It indicates whether the block is partial invalid or not. A block
129    /// is partial invalid if it selects an incorrect parent or filling an
130    /// incorrect adaptive field.
131    partial_invalid: bool,
132    /// It indicates whether the block is pending or not. A block is pending if
133    /// the consensus engine determines that it is not necessary to determine
134    /// its partial invalid status.
135    pending: bool,
136    /// This is a special counter marking whether the block is active or not.
137    /// A block is active only if the counter is zero
138    /// A partial invalid block will get a NULL counter
139    /// A normal block which referenced directly or indirectly will have a
140    /// positive counter
141    inactive_dependency_cnt: usize,
142    /// This is an implementation flag indicate whether the node is active or
143    /// not. Because multiple blocks may have their `inactive_dependency_cnt`
144    /// turning zero in the same time, we need this flag to process them
145    /// correctly one by one.
146    activated: bool,
147    /// This records the force confirm point in the past view of this block.
148    force_confirm: usize,
149    /// The indices set of the blocks in the epoch when the current
150    /// block is as pivot chain block. This set does not contain
151    /// the block itself.
152    blockset_in_own_view_of_epoch: Vec<usize>,
153    /// Ordered executable blocks in this epoch. This filters out blocks that
154    /// are not in the same era of the epoch pivot block.
155    ///
156    /// For cur_era_genesis, this field should NOT be used because they contain
157    /// out-of-era blocks not maintained in the memory.
158    ordered_executable_epoch_blocks: Vec<usize>,
159    /// If an epoch has more than ``EPOCH_EXECUTED_BLOCK_BOUND''. We will only
160    /// execute the last ``EPOCH_EXECUTED_BLOCK_BOUND'' and skip the
161    /// remaining. The `skipped_epoch_blocks` also contain those blocks that
162    /// are not in the same era of the pivot block.
163    /// We use the block hashes instead of block arena indices here to ensure
164    /// the consistency with the database after making a checkpoint.
165    skipped_epoch_blocks: Vec<H256>,
166    /// It indicates whether `blockset_in_own_view_of_epoch` and
167    /// `skipped_epoch_blocks` are cleared due to its size.
168    blockset_cleared: bool,
169    /// The sequence number is used to identify the order of each block
170    /// entering the consensus. The sequence number of the genesis is used
171    /// by the syncronization layer to determine whether a block exists in
172    /// the consensus or not.
173    sequence_number: u64,
174    /// The longest chain of all timer blocks.
175    past_view_timer_longest_difficulty: i128,
176    /// The last timer block index in the chain.
177    past_view_last_timer_block_arena_index: usize,
178    /// The height of the closest timer block in the longest timer chain.
179    /// Note that this only considers the current longest timer chain and
180    /// ignores the remaining timer blocks.
181    ledger_view_timer_chain_height: u64,
182    /// vote_valid_lca_height indicates the fork_at height that the vote_valid
183    /// field corresponds to.
184    vote_valid_lca_height: u64,
185    /// It indicates whether the blame voting information of this block is
186    /// correct or not.
187    vote_valid: bool,
188    /// It denotes the height of the last pivot chain in the past set of this
189    /// block.
190    last_pivot_in_past: u64,
191    /// It indicates whether the states stored in header is correct or not.
192    /// It's evaluated when needed, i.e., when we need the blame information to
193    /// generate a new block or to compute rewards.
194    pub state_valid: Option<bool>,
195    /// It stores the correct blame info for the block if its state is invalid.
196    /// It's evaluated when needed and acts as a cache.
197    blame_info: Option<StateBlameInfo>,
198}
199
200impl ConsensusGraphNodeData {
201    fn new(
202        epoch_number: u64, sequence_number: u64, inactive_dependency_cnt: usize,
203    ) -> Self {
204        ConsensusGraphNodeData {
205            epoch_number,
206            partial_invalid: false,
207            pending: false,
208            inactive_dependency_cnt,
209            activated: false,
210            force_confirm: NULL,
211            blockset_in_own_view_of_epoch: Default::default(),
212            ordered_executable_epoch_blocks: Default::default(),
213            skipped_epoch_blocks: Default::default(),
214            blockset_cleared: true,
215            sequence_number,
216            past_view_timer_longest_difficulty: 0,
217            past_view_last_timer_block_arena_index: NULL,
218            ledger_view_timer_chain_height: 0,
219            vote_valid_lca_height: NULLU64,
220            vote_valid: true,
221            last_pivot_in_past: 0,
222            state_valid: None,
223            blame_info: None,
224        }
225    }
226}
227
228#[derive(DeriveMallocSizeOf)]
229struct ConsensusGraphPivotData {
230    /// The set of blocks whose last_pivot_in_past point to this pivot chain
231    /// location
232    last_pivot_in_past_blocks: HashSet<usize>,
233    /// The total weight of the past set of the pivot block. This value
234    /// is used by the confirmation meter.
235    past_weight: i128,
236}
237
238impl Default for ConsensusGraphPivotData {
239    fn default() -> Self {
240        ConsensusGraphPivotData {
241            last_pivot_in_past_blocks: HashSet::new(),
242            past_weight: 0,
243        }
244    }
245}
246
247/// # Implementation details of Eras, Timer chain and Checkpoints
248///
249/// Era in Conflux is defined based on the height of a block. Every
250/// epoch_block_count height corresponds to one era. For example, if
251/// era_block_count is 50000, then blocks at height 0 (the original genesis)
252/// is the era genesis of the first era. The blocks at height 50000 are era
253/// genesis blocks of the following era. Note that it is possible to have
254/// multiple era genesis blocks for one era period. Eventually, only
255/// one era genesis block and its subtree will become dominant and all other
256/// genesis blocks together with their subtrees will be discarded. The
257/// definition of Era enables Conflux to form checkpoints at the stabilized
258/// era genesis blocks.
259///
260/// # Implementation details of the Timer chain
261///
262/// Timer chain contains special blocks whose PoW qualities are significantly
263/// higher than normal blocks. The goal of timer chain is to enable a slowly
264/// growing longest chain to indicate the time elapsed between two blocks.
265/// Timer chain also provides a force confirmation rule which will enable us
266/// to safely form the checkpoint.
267///
268/// Any block whose PoW quality is timer_chain_block_difficulty_ratio times
269/// higher than its supposed difficulty is *timer block*. The longest chain of
270/// timer blocks (counting both parent edges and reference edges) is the timer
271/// chain. When timer_chain_beta is large enough, malicious attackers can
272/// neither control the timer chain nor stop its growth. We use Timer(G) to
273/// denote the number of timer chain blocks in G. We use TimerDis(b_1, b_2) to
274/// denote Timer(Past(B_1)) - Timer(Past(B_2)). In case that b_2 \in
275/// Future(b_1), TimerDis(b_1, b_2) is a good indicator about how long it has
276/// past between the generation of the two blocks.
277///
278/// A block b in G is considered force-confirm if 1) there are *consecutively*
279/// timer_chain_beta timer chain blocks under the subtree of b and 2) there are
280/// at least timer_chain_beta blocks after these blocks (not necessarily in the
281/// subtree of b). Force-confirm rule overrides any GHAST weight rule, i.e.,
282/// new blocks will always be generated under b.
283///
284///
285/// # Implementation details of the GHAST algorithm
286///
287/// Conflux uses the Greedy Heaviest Adaptive SubTree (GHAST) algorithm to
288/// select a chain from the genesis block to one of the leaf blocks as the pivot
289/// chain. For each block b, GHAST algorithm computes it is adaptive
290///
291/// ```python
292/// B = Past(b)
293/// f is the force confirm point of b in the view of Past(b)
294/// a = b.parent
295/// adaptive = False
296/// Let f(x) = 2 * SubTW(B, x) - SubTW(B, x.parent) + x.parent.weight
297/// Let g(x) = adaptive_weight_beta * b.diff
298/// while a != force_confirm do
299///     if TimerDis(a, b) >= timer_chain_beta and f(a) < g(a) then
300///         adaptive = True
301///     a = a.parent
302/// ```
303///
304/// To efficiently compute adaptive, we maintain a link-cut tree called
305/// adaptive_weight_tree. The value for x in the link-cut-tree is
306/// 2 * SubTW(B, x) + x.parent.weight - SubTW(B, x.parent). Note that we need to
307/// do special caterpillar update in the Link-Cut-Tree, i.e., given a node X, we
308/// need to update the values of all of those nodes A such that A is the child
309/// of one of the node in the path from Genesis to X.
310///
311/// For an adaptive block, its weights will be calculated in a special way. If
312/// its PoW quality is adaptive_heavy_weight_ratio times higher than the normal
313/// difficulty, its weight will be adaptive_heavy_weight_ratio instead of one.
314/// Otherwise, the weight will be zero. The goal of adaptive weight is to deal
315/// with potential liveness attacks that balance two subtrees. Note that when
316/// computing adaptive we only consider the nodes after force_confirm.
317///
318/// # Implementation details of partial invalid blocks
319///
320/// One block may become partial invalid because 1) it chooses incorrect parent
321/// or 2) it generates an adaptive block when it should not. In normal
322/// situations, we should verify every block we receive and determine whether it
323/// is partial invalid or not. For a partial invalid block b, it will not
324/// receive any reward. Normal nodes will also refrain from *directly or
325/// indirectly* referencing b until TimerDis(*b*, new_block) is greater than or
326/// equal to timer_dis_delta. Normal nodes essentially ignores partial invalid
327/// blocks for a while. We implement this via our inactive_dependency_cnt field.
328/// Last but not least, we exclude *partial invalid* blocks from the timer chain
329/// consideration. They are not timer blocks!
330///
331/// # Implementation details of checkpoints
332///
333/// Our consensus engine will form a checkpoint pair (a, b) given a DAG state G
334/// if:
335///
336/// 1) b is force confirmed in G
337/// 2) a is force confirmed in Past(b)
338///
339/// Now we are safe to remove all blocks that are not in Future(a). For those
340/// blocks that are in the Future(a) but not in Subtree(a), we can also redirect
341/// a as their parents. We call *a* the cur_era_genesis_block and *b* the
342/// cur_era_stable_block.
343///
344/// We no longer need to check the partial invalid block which does not
345/// referencing b (directly and indirectly), because such block would never go
346/// into the timer chain. Our assumption is that the timer chain will not reorg
347/// on a length greater than timer_chain_beta. For those blocks which
348/// referencing *b* but also not under the subtree of a, they are by default
349/// partial invalid. We can ignore them as well. Therefore *a* can be treated as
350/// a new genesis block. We are going to check the possibility of making
351/// checkpoints only at the era boundary.
352///
353/// Note that we have the assumption that the force confirmation point will
354/// always move along parental edges, i.e., it is not possible for the point
355/// to move to a sibling tree. This assumption is true if the timer_chain_beta
356/// and the timer_chain_difficulty_ratio are set to large enough values.
357///
358/// # Introduction of blaming mechanism
359///
360/// Blaming is used to provide proof for state root of a specific pivot block.
361/// The rationale behind is as follows. Verifying state roots of blocks off
362/// pivot chain is very costly and sometimes impractical, e.g., when the block
363/// refers to another block that is not in the current era. It is preferred to
364/// avoid this verification if possible. Normally, Conflux only needs to store
365/// correct state root in header of pivot block to provide proof for light node.
366/// However, the pivot chain may oscillate at the place close to ledger tail,
367/// which means that a block that is off pivot at some point may become pivot
368/// block in the future. If we do not verify the state root in the header of
369/// that block, when it becomes a pivot block later, we cannot guarantee the
370/// correctness of the state root in its header. Therefore, if we do not verify
371/// the state root in off-pivot block, we cannot guarantee the correctness of
372/// state root in pivot block. Of course, one may argue that you can switch
373/// pivot chain when incorrect state root in pivot block is observed. However,
374/// this makes the check for the correct parent selection rely on state root
375/// checking. Then, since Conflux is an inclusive protocol which adopts
376/// off-pivot blocks in its final ledger, it needs to verify the correctness of
377/// parent selection of off-pivot blocks and this relies on the state
378/// verification on all the parent candidates of the off-pivot blocks.
379/// Therefore, this eventually will lead to state root verification on any
380/// blocks including off-pivot ones. This violates the original goal of saving
381/// cost of the state root verification in off-pivot blocks.
382///
383/// We therefore allow incorrect state root in pivot block header, and use the
384/// blaming mechanism to enable the proof generation of the correct state root.
385/// A full/archive node verifies the deferred state root and the blaming
386/// information stored in the header of each pivot block. It blames the blocks
387/// with incorrect information and stores the blaming result in the header of
388/// the newly mined block. The blaming result is simply a count which represents
389/// the distance (in the number of blocks) between the last correct block on the
390/// pivot chain and the newly mined block. For example, consider the blocks
391/// Bi-1, Bi, Bi+1, Bi+2, Bi+3. Assume the blaming count in Bi+3 is 2.
392/// This means when Bi+3 was mined, the node thinks Bi's information is correct,
393/// while the information in Bi+1 and Bi+2 are wrong. Therefore, the node
394/// recovers the true deferred state roots (DSR) of Bi+1, Bi+2, and Bi+3 by
395/// computing locally, and then computes keccak(DSRi+3, keccak(DSRi+2, DSRi+1))
396/// and stores the hash into the header of Bi+3 as its final deferred
397/// state root. A special case is if the blaming count is 0, the final deferred
398/// state root of the block is simply the original deferred state root, i.e.,
399/// DSRi+3 for block Bi+3 in the above case.
400///
401/// Computing the reward for a block relies on correct blaming behavior of
402/// the block. If the block is a pivot block when computing its reward,
403/// it is required that:
404///
405/// 1. the block correctly chooses its parent;
406/// 2. the block contains the correct deferred state root;
407/// 3. the block correctly blames all its previous blocks following parent
408///    edges.
409///
410/// If the block is an off-pivot block when computing its reward,
411/// it is required that:
412/// 1. the block correctly chooses its parent;
413/// 2. the block correctly blames the blocks in the intersection of pivot chain
414///    blocks and all its previous blocks following parent edges. (This is to
415///    encourage the node generating the off-pivot block to keep verifying pivot
416///    chain blocks.)
417///
418/// To provide proof of state root to light node (or a full node when it tries
419/// to recover from a checkpoint), the protocol goes through the following
420/// steps. Let's assume the verifier has a subtree of block headers which
421/// includes the block whose state root is to be verified.
422///
423/// 1. The verifier node gets a merkle path whose merkle root corresponds
424/// to the state root after executing block Bi. Let's call it the path root
425/// which is to be verified.
426///
427/// 2. Assume deferred count is 2, the verifier node gets block header Bi+2
428/// whose deferred state root should be the state root of Bi.
429///
430/// 3. The verifier node locally searches for the first block whose information
431/// in header is correct, starting from block Bi+2 along with the pivot
432/// chain. The correctness of header information of a block is decided based
433/// on the ratio of the number of blamers in the subtree of the block. If the
434/// ratio is small enough, the information is correct. Assume the first such
435/// block is block Bj.
436///
437/// 4. The verifier then searches backward along the pivot chain from Bj for
438/// the block whose blaming count is larger than or equal to the distance
439/// between block Bi+2 and it. Let's call this block as Bk.
440///
441/// 5. The verifier asks the prover which is a full or archive node to get the
442/// deferred state root of block Bk and its DSR vector, i.e., [..., DSRi+2,
443/// ...].
444///
445/// 6. The verifier verifies the accumulated keccak hash of [..., DSRi+2, ...]
446/// equals to deferred state root of Bk, and then verifies that DSRi+2 equals
447/// to the path root of Bi.
448///
449/// In ConsensusGraphInner, every block corresponds to a ConsensusGraphNode and
450/// each node has an internal index. This enables fast internal implementation
451/// to use integer index instead of H256 block hashes.
452pub struct ConsensusGraphInner {
453    /// data_man is the handle to access raw block data
454    pub data_man: Arc<BlockDataManager>,
455    pub pos_verifier: Arc<PosVerifier>,
456    pub inner_conf: ConsensusInnerConfig,
457    pub pow_config: ProofOfWorkConfig,
458    pub pow: Arc<PowComputer>,
459    //executor: Arc<ConsensusExecutor>,
460    /// This slab hold consensus graph node data and the array index is the
461    /// internal index.
462    pub arena: Slab<ConsensusGraphNode>,
463    /// indices maps block hash to internal index.
464    pub hash_to_arena_indices: FastHashMap<H256, usize>,
465    /// The current pivot chain indexes.
466    pivot_chain: Vec<usize>,
467    /// The metadata associated with each pivot chain block
468    pivot_chain_metadata: Vec<ConsensusGraphPivotData>,
469    /// The longest timer chain block indexes
470    timer_chain: Vec<usize>,
471    /// The accumulative LCA of timer_chain for consecutive
472    timer_chain_accumulative_lca: Vec<usize>,
473    /// The set of *graph* tips in the TreeGraph for mining.
474    /// Note that this set does not include non-active partial invalid blocks
475    terminal_hashes: HashSet<H256>,
476    /// The ``current'' era_genesis block index. It will start being the
477    /// original genesis. As time goes, it will move to future era genesis
478    /// checkpoint.
479    cur_era_genesis_block_arena_index: usize,
480    /// The height of the ``current'' era_genesis block
481    cur_era_genesis_height: u64,
482    /// The height of the ``stable'' era block, unless from the start, it is
483    /// always era_epoch_count higher than era_genesis_height
484    cur_era_stable_height: u64,
485    /// If this value is not none, then we are still expecting the initial
486    /// stable block to come. This value would equal to the expected hash of
487    /// the block.
488    cur_era_stable_block_hash: H256,
489    /// If this value is not none, then we are manually maintain the future set
490    /// of the expected stable block. We have to do this because during the
491    /// initial stage it may not be always on the pivot chain.
492    initial_stable_future: Option<BitSet>,
493    /// The timer chain height of the ``current'' era_genesis block
494    cur_era_genesis_timer_chain_height: u64,
495    /// The best timer chain difficulty and hash in the current graph
496    best_timer_chain_difficulty: i128,
497    best_timer_chain_hash: H256,
498
499    // TODO(lpl): This is initialized as cur_era_genesis for now.
500    // TODO(lpl): It's always used after being updated, so this should be okay.
501    /// The pivot decision of the best (the round is the largest) pos
502    /// reference.
503    best_pos_pivot_decision: (H256, u64),
504
505    /// weight_tree maintains the subtree weight of each node in the TreeGraph
506    weight_tree: SizeMinLinkCutTree,
507    /// adaptive_tree maintains 2 * SubStableTW(B, x) - SubTW(B, P(x)) +
508    /// Weight(P(x))
509    adaptive_tree: CaterpillarMinLinkCutTree,
510    /// A priority that holds for every non-active partial invalid block, the
511    /// timer chain stamp that will become valid
512    invalid_block_queue: BinaryHeap<(i128, usize)>,
513    /// It maintains the expected difficulty of the next local mined block.
514    pub current_difficulty: U256,
515    /// The cache to store Anticone information of each node. This could be
516    /// very large so we periodically remove old ones in the cache.
517    anticone_cache: AnticoneCache,
518    pastset_cache: PastSetCache,
519    sequence_number_of_block_entrance: u64,
520
521    /// This is a cache map to speed up the lca computation of terminals in the
522    /// best terminals call. The basic idea is that if no major
523    /// reorganization happens, then it could use the last results
524    /// instead of calling it again.
525    best_terminals_lca_height_cache: FastHashMap<usize, u64>,
526    /// This is to record the pivot chain reorganization height since the last
527    /// invocation of best_terminals()
528    best_terminals_reorg_height: u64,
529    /// This is a cache to record history of checking whether a block has timer
530    /// block in its anticone.
531    has_timer_block_in_anticone_cache: HashSet<usize>,
532
533    /// `true` before we enter `CacheUpSyncBlock`. We need to execute
534    /// transactions and process state if it's `false`.
535    header_only: bool,
536}
537
538impl MallocSizeOf for ConsensusGraphInner {
539    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
540        self.arena.size_of(ops)
541            + self.hash_to_arena_indices.size_of(ops)
542            + self.pivot_chain.size_of(ops)
543            + self.pivot_chain_metadata.size_of(ops)
544            + self.timer_chain.size_of(ops)
545            + self.timer_chain_accumulative_lca.size_of(ops)
546            + self.terminal_hashes.size_of(ops)
547            + self.initial_stable_future.size_of(ops)
548            + self.weight_tree.size_of(ops)
549            + self.adaptive_tree.size_of(ops)
550            + self.invalid_block_queue.size_of(ops)
551            + self.pow_config.size_of(ops)
552            + self.data_man.size_of(ops)
553            + self.anticone_cache.size_of(ops)
554            + self.pastset_cache.size_of(ops)
555            + self.best_terminals_lca_height_cache.size_of(ops)
556            + self.best_terminals_reorg_height.size_of(ops)
557    }
558}
559
560#[derive(DeriveMallocSizeOf)]
561pub struct ConsensusGraphNode {
562    pub hash: H256,
563    pub height: u64,
564    pub parent: usize,
565    difficulty: U256,
566    is_heavy: bool,
567    is_timer: bool,
568    /// The total number of *executed* blocks in its past (not including self)
569    past_num_blocks: u64,
570    adaptive: bool,
571
572    /// The genesis arena index of the era that `self` is in.
573    ///
574    /// It is `NULL` if `self` is not in the subtree of `cur_era_genesis`.
575    era_block: usize,
576    children: Vec<usize>,
577    referrers: Vec<usize>,
578    referees: Vec<usize>,
579    /// data contains all extra information of a block that will change as the
580    /// consensus graph state evolves (e.g., pivot chain changes). Unlike the
581    /// above fields, this information will only be available after the
582    /// block is *preactivated* (after calling preactivate_block().
583    pub data: ConsensusGraphNodeData,
584}
585
586impl ConsensusGraphNode {
587    pub fn past_num_blocks(&self) -> u64 { self.past_num_blocks }
588
589    pub fn adaptive(&self) -> bool { self.adaptive }
590
591    pub fn pending(&self) -> bool { self.data.pending }
592
593    pub fn partial_invalid(&self) -> bool { self.data.partial_invalid }
594
595    pub fn era_block(&self) -> usize { self.era_block }
596}
597
598impl ConsensusGraphInner {
599    pub fn with_era_genesis(
600        pow_config: ProofOfWorkConfig, pow: Arc<PowComputer>,
601        pos_verifier: Arc<PosVerifier>, data_man: Arc<BlockDataManager>,
602        inner_conf: ConsensusInnerConfig, cur_era_genesis_block_hash: &H256,
603        cur_era_stable_block_hash: &H256,
604    ) -> Self {
605        let genesis_block_header = data_man
606            .block_header_by_hash(cur_era_genesis_block_hash)
607            .expect("genesis block header should exist here");
608        let cur_era_genesis_height = genesis_block_header.height();
609        let stable_block_header = data_man
610            .block_header_by_hash(cur_era_stable_block_hash)
611            .expect("stable genesis block header should exist here");
612        let cur_era_stable_height = stable_block_header.height();
613        let initial_difficulty = pow_config.initial_difficulty;
614        let mut inner = ConsensusGraphInner {
615            arena: Slab::new(),
616            hash_to_arena_indices: FastHashMap::new(),
617            pivot_chain: Vec::new(),
618            pivot_chain_metadata: Vec::new(),
619            timer_chain: Vec::new(),
620            timer_chain_accumulative_lca: Vec::new(),
621            terminal_hashes: Default::default(),
622            cur_era_genesis_block_arena_index: NULL,
623            cur_era_genesis_height,
624            cur_era_stable_height,
625            // Timer chain height is an internal number. We always start from
626            // zero.
627            cur_era_stable_block_hash: cur_era_stable_block_hash.clone(),
628            initial_stable_future: Some(BitSet::new()),
629            cur_era_genesis_timer_chain_height: 0,
630            best_timer_chain_difficulty: 0,
631            best_timer_chain_hash: Default::default(),
632            best_pos_pivot_decision: (
633                *cur_era_genesis_block_hash,
634                cur_era_genesis_height,
635            ),
636            weight_tree: SizeMinLinkCutTree::new(),
637            adaptive_tree: CaterpillarMinLinkCutTree::new(),
638            invalid_block_queue: BinaryHeap::new(),
639            pow_config,
640            pow,
641            current_difficulty: initial_difficulty.into(),
642            data_man: data_man.clone(),
643            pos_verifier,
644            inner_conf,
645            anticone_cache: AnticoneCache::new(),
646            pastset_cache: Default::default(),
647            sequence_number_of_block_entrance: 0,
648            best_terminals_lca_height_cache: Default::default(),
649            best_terminals_reorg_height: NULLU64,
650            has_timer_block_in_anticone_cache: Default::default(),
651            header_only: true,
652        };
653
654        // NOTE: Only genesis block will be first inserted into consensus graph
655        // and then into synchronization graph. All the other blocks will be
656        // inserted first into synchronization graph then consensus graph.
657        // For genesis block, its past weight is simply zero (default value).
658        let (genesis_arena_index, _) = inner.insert(&genesis_block_header);
659        if cur_era_genesis_block_hash == cur_era_stable_block_hash {
660            inner
661                .initial_stable_future
662                .as_mut()
663                .unwrap()
664                .add(genesis_arena_index as u32);
665        }
666        inner.arena[genesis_arena_index].data.blockset_cleared = false;
667        if genesis_block_header.height() == 0 {
668            inner.arena[genesis_arena_index].data.state_valid = Some(true);
669        }
670        inner.cur_era_genesis_block_arena_index = genesis_arena_index;
671        inner.arena[genesis_arena_index].data.activated = true;
672        let genesis_block_weight = genesis_block_header.difficulty().low_u128();
673        inner
674            .weight_tree
675            .make_tree(inner.cur_era_genesis_block_arena_index);
676        inner.weight_tree.path_apply(
677            inner.cur_era_genesis_block_arena_index,
678            genesis_block_weight as i128,
679        );
680        inner
681            .adaptive_tree
682            .make_tree(inner.cur_era_genesis_block_arena_index);
683        // The genesis node can be zero in adaptive_tree because it is never
684        // used!
685        inner
686            .adaptive_tree
687            .set(inner.cur_era_genesis_block_arena_index, 0);
688        inner.arena[inner.cur_era_genesis_block_arena_index]
689            .data
690            .epoch_number = cur_era_genesis_height;
691        let genesis_epoch_size = inner
692            .data_man
693            .executed_epoch_set_hashes_from_db(cur_era_genesis_height)
694            .expect("Genesis epoch set should be in data manager.")
695            .len();
696        inner.arena[inner.cur_era_genesis_block_arena_index].past_num_blocks =
697            inner
698                .data_man
699                .get_epoch_execution_context(cur_era_genesis_block_hash)
700                .expect("ExecutionContext for cur_era_genesis exists")
701                .start_block_number
702                + genesis_epoch_size as u64
703                - 1;
704        inner.arena[inner.cur_era_genesis_block_arena_index]
705            .data
706            .last_pivot_in_past = cur_era_genesis_height;
707        inner
708            .pivot_chain
709            .push(inner.cur_era_genesis_block_arena_index);
710        let mut last_pivot_in_past_blocks = HashSet::new();
711        last_pivot_in_past_blocks
712            .insert(inner.cur_era_genesis_block_arena_index);
713        inner.pivot_chain_metadata.push(ConsensusGraphPivotData {
714            last_pivot_in_past_blocks,
715            past_weight: genesis_block_weight as i128,
716        });
717        if inner.arena[inner.cur_era_genesis_block_arena_index].is_timer {
718            inner
719                .timer_chain
720                .push(inner.cur_era_genesis_block_arena_index);
721        }
722        inner.arena[inner.cur_era_genesis_block_arena_index]
723            .data
724            .ledger_view_timer_chain_height = 0;
725        inner.best_timer_chain_difficulty =
726            inner.get_timer_difficulty(inner.cur_era_genesis_block_arena_index);
727
728        inner
729            .anticone_cache
730            .update(inner.cur_era_genesis_block_arena_index, &BitSet::new());
731
732        inner
733    }
734
735    fn persist_epoch_set_hashes(&mut self, pivot_index: usize) {
736        let height = self.pivot_index_to_height(pivot_index);
737        let arena_index = self.pivot_chain[pivot_index];
738        let epoch_set_hashes = self
739            .get_ordered_executable_epoch_blocks(arena_index)
740            .iter()
741            .map(|arena_index| self.arena[*arena_index].hash)
742            .collect();
743        let skipped_set_hashes = self
744            .get_or_compute_skipped_epoch_blocks(arena_index)
745            .clone();
746        self.data_man
747            .insert_executed_epoch_set_hashes_to_db(height, &epoch_set_hashes);
748        self.data_man
749            .insert_skipped_epoch_set_hashes_to_db(height, &skipped_set_hashes);
750    }
751
752    #[inline]
753    pub fn current_era_genesis_seq_num(&self) -> u64 {
754        self.arena[self.cur_era_genesis_block_arena_index]
755            .data
756            .sequence_number
757    }
758
759    #[inline]
760    /// The caller should ensure that `height` is within the current
761    /// `self.pivot_chain` range. Otherwise the function may panic.
762    pub fn get_pivot_block_arena_index(&self, height: u64) -> usize {
763        let pivot_index = (height - self.cur_era_genesis_height) as usize;
764        assert!(pivot_index < self.pivot_chain.len());
765        self.pivot_chain[pivot_index]
766    }
767
768    #[inline]
769    pub fn get_pivot_height(&self) -> u64 {
770        self.cur_era_genesis_height + self.pivot_chain.len() as u64
771    }
772
773    #[inline]
774    pub fn height_to_pivot_index(&self, height: u64) -> usize {
775        (height - self.cur_era_genesis_height) as usize
776    }
777
778    #[inline]
779    pub fn pivot_index_to_height(&self, pivot_index: usize) -> u64 {
780        self.cur_era_genesis_height + pivot_index as u64
781    }
782
783    #[inline]
784    fn get_next_sequence_number(&mut self) -> u64 {
785        let sn = self.sequence_number_of_block_entrance;
786        self.sequence_number_of_block_entrance += 1;
787        sn
788    }
789
790    #[inline]
791    pub fn set_initial_sequence_number(&mut self, initial_sn: u64) {
792        self.arena[self.cur_era_genesis_block_arena_index]
793            .data
794            .sequence_number = initial_sn;
795        self.sequence_number_of_block_entrance = initial_sn + 1;
796    }
797
798    #[inline]
799    fn is_heavier(a: (i128, &H256), b: (i128, &H256)) -> bool {
800        (a.0 > b.0) || ((a.0 == b.0) && (*a.1 > *b.1))
801    }
802
803    #[inline]
804    fn ancestor_at(&self, me: usize, height: u64) -> usize {
805        let height_index = self.height_to_pivot_index(height);
806        self.weight_tree.ancestor_at(me, height_index)
807    }
808
809    #[inline]
810    /// for outside era block, consider the lca is NULL
811    fn lca(&self, me: usize, v: usize) -> usize {
812        if self.arena[v].era_block == NULL || self.arena[me].era_block == NULL {
813            return NULL;
814        }
815        self.weight_tree.lca(me, v)
816    }
817
818    #[inline]
819    fn get_era_genesis_height(&self, parent_height: u64) -> u64 {
820        parent_height / self.inner_conf.era_epoch_count
821            * self.inner_conf.era_epoch_count
822    }
823
824    #[inline]
825    pub fn get_cur_era_genesis_height(&self) -> u64 {
826        self.cur_era_genesis_height
827    }
828
829    #[inline]
830    fn get_era_genesis_block_with_parent(&self, parent: usize) -> usize {
831        if parent == NULL {
832            return 0;
833        }
834        let height = self.arena[parent].height;
835        let era_genesis_height = self.get_era_genesis_height(height);
836        trace!(
837            "height={} era_height={} era_genesis_height={}",
838            height,
839            era_genesis_height,
840            self.cur_era_genesis_height
841        );
842        self.ancestor_at(parent, era_genesis_height)
843    }
844
845    #[inline]
846    pub fn get_epoch_block_hashes(
847        &self, epoch_arena_index: usize,
848    ) -> Vec<H256> {
849        self.get_ordered_executable_epoch_blocks(epoch_arena_index)
850            .iter()
851            .map(|idx| self.arena[*idx].hash)
852            .collect()
853    }
854
855    #[inline]
856    fn get_epoch_start_block_number(&self, epoch_arena_index: usize) -> u64 {
857        let parent = self.arena[epoch_arena_index].parent;
858
859        return self.arena[parent].past_num_blocks + 1;
860    }
861
862    #[inline]
863    fn is_legacy_block(&self, index: usize) -> bool {
864        self.arena[index].era_block == NULL
865    }
866
867    /// This function computes the epoch set of block *pivot* based on
868    /// the past set of block *lca* which is the parental ancestor of
869    /// *pivot*. The algorithm processes the blocks along the parental
870    /// path from *lca* to *pivot* to produce the *visited* block set,
871    /// and then compute the epoch block set of *pivot* based on the
872    /// *pastset* and the *visited*. The following figure illustrates
873    /// this process. B[lca] refers to the block *lca*, B[piv] refers
874    /// to the block *pivot*, and B[par] refers to the parent of *pivot*
875    ///
876    /// I    ------------\-------------------\-------------------\
877    /// I        lca      \                   \       epoch       \
878    /// I    -- pastset -B[lca]-- visited --B[par]-- blockset --B[piv]
879    /// I                 /                   /                   /
880    /// I    ------------/-------------------/-------------------/
881    fn compute_blockset_in_own_view_of_epoch_impl(
882        &mut self, lca: usize, pivot: usize,
883    ) {
884        let pastset = self.pastset_cache.get(lca).unwrap();
885        let mut path_to_lca = Vec::new();
886        let mut cur = pivot;
887        while cur != lca {
888            path_to_lca.push(cur);
889            cur = self.arena[cur].parent;
890        }
891        path_to_lca.reverse();
892        let mut visited = BitSet::new();
893        for ancestor_arena_index in path_to_lca {
894            visited.add(ancestor_arena_index as u32);
895            if ancestor_arena_index == pivot
896                || self.arena[ancestor_arena_index].data.blockset_cleared
897            {
898                let mut queue = VecDeque::new();
899                for referee in &self.arena[ancestor_arena_index].referees {
900                    if !pastset.contains(*referee as u32)
901                        && !visited.contains(*referee as u32)
902                    {
903                        visited.add(*referee as u32);
904                        queue.push_back(*referee);
905                    }
906                }
907                while let Some(index) = queue.pop_front() {
908                    if ancestor_arena_index == pivot {
909                        self.arena[pivot]
910                            .data
911                            .blockset_in_own_view_of_epoch
912                            .push(index);
913                    }
914                    let parent = self.arena[index].parent;
915                    if parent != NULL
916                        && !pastset.contains(parent as u32)
917                        && !visited.contains(parent as u32)
918                    {
919                        visited.add(parent as u32);
920                        queue.push_back(parent);
921                    }
922                    for referee in &self.arena[index].referees {
923                        if !pastset.contains(*referee as u32)
924                            && !visited.contains(*referee as u32)
925                        {
926                            visited.add(*referee as u32);
927                            queue.push_back(*referee);
928                        }
929                    }
930                }
931            } else {
932                for index in &self.arena[ancestor_arena_index]
933                    .data
934                    .blockset_in_own_view_of_epoch
935                {
936                    visited.add(*index as u32);
937                }
938            }
939        }
940    }
941
942    /// This function computes the epoch block set under the view of
943    /// block *pivot*. It also computes the ordered set of executable
944    /// blocks in the epoch. This set has a bound specified by
945    /// EPOCH_EXECUTED_BLOCK_BOUND. To compute this set, it first
946    /// filters out the blocks in the raw epoch set but not in the
947    /// same era with *pivot*. It then topologically sorts the retained
948    /// blocks and preserves at most the last EPOCH_EXECUTED_BLOCK_BOUND
949    /// blocks. All the filtered-out blocks are added into
950    /// *skipped_epoch_blocks*.
951    fn compute_blockset_in_own_view_of_epoch(&mut self, pivot: usize) {
952        if !self.arena[pivot].data.blockset_cleared {
953            return;
954        }
955        // TODO: consider the speed for recovery from db
956        let parent = self.arena[pivot].parent;
957        if parent != NULL {
958            let last = *self.pivot_chain.last().unwrap();
959            let lca = self.lca(last, parent);
960            assert!(lca != NULL);
961            if self.pastset_cache.get_and_update_cache(lca).is_none() {
962                let pastset = self.compute_pastset_brutal(lca);
963                self.pastset_cache.update(lca, pastset);
964            }
965            self.compute_blockset_in_own_view_of_epoch_impl(lca, pivot);
966        }
967
968        let mut filtered_blockset = HashSet::new();
969        let mut different_era_blocks = Vec::new();
970        for idx in &self.arena[pivot].data.blockset_in_own_view_of_epoch {
971            if self.is_same_era(*idx, pivot) {
972                filtered_blockset.insert(*idx);
973            } else {
974                different_era_blocks.push(*idx);
975            }
976        }
977
978        let mut ordered_executable_epoch_blocks = self
979            .topological_sort_with_order_indicator(filtered_blockset, |i| {
980                self.arena[i].hash
981            });
982        ordered_executable_epoch_blocks.push(pivot);
983        let skipped_epoch_block_indices = if ordered_executable_epoch_blocks
984            .len()
985            > EPOCH_EXECUTED_BLOCK_BOUND
986        {
987            let cut_off = ordered_executable_epoch_blocks.len()
988                - EPOCH_EXECUTED_BLOCK_BOUND;
989            let mut skipped_epoch_block_indices =
990                ordered_executable_epoch_blocks;
991            ordered_executable_epoch_blocks =
992                skipped_epoch_block_indices.split_off(cut_off);
993            skipped_epoch_block_indices.append(&mut different_era_blocks);
994            skipped_epoch_block_indices
995        } else {
996            different_era_blocks
997        };
998
999        self.arena[pivot].data.skipped_epoch_blocks =
1000            skipped_epoch_block_indices
1001                .into_iter()
1002                .map(|i| self.arena[i].hash)
1003                .collect();
1004        self.arena[pivot].data.ordered_executable_epoch_blocks =
1005            ordered_executable_epoch_blocks;
1006        self.arena[pivot].data.blockset_cleared = false;
1007    }
1008
1009    #[inline]
1010    fn exchange_or_compute_blockset_in_own_view_of_epoch(
1011        &mut self, index: usize, blockset_opt: Option<Vec<usize>>,
1012    ) -> Vec<usize> {
1013        if let Some(blockset) = blockset_opt {
1014            mem::replace(
1015                &mut self.arena[index].data.blockset_in_own_view_of_epoch,
1016                blockset,
1017            )
1018        } else {
1019            if self.arena[index].data.blockset_cleared {
1020                self.compute_blockset_in_own_view_of_epoch(index);
1021            }
1022            mem::replace(
1023                &mut self.arena[index].data.blockset_in_own_view_of_epoch,
1024                Default::default(),
1025            )
1026        }
1027    }
1028
1029    #[inline]
1030    pub fn get_ordered_executable_epoch_blocks(
1031        &self, index: usize,
1032    ) -> &Vec<usize> {
1033        &self.arena[index].data.ordered_executable_epoch_blocks
1034    }
1035
1036    #[inline]
1037    pub fn get_or_compute_skipped_epoch_blocks(
1038        &mut self, index: usize,
1039    ) -> &Vec<H256> {
1040        if self.arena[index].data.blockset_cleared {
1041            self.compute_blockset_in_own_view_of_epoch(index);
1042        }
1043        &self.arena[index].data.skipped_epoch_blocks
1044    }
1045
1046    #[inline]
1047    pub fn get_skipped_epoch_blocks(&self, index: usize) -> Option<&Vec<H256>> {
1048        if self.arena[index].data.blockset_cleared {
1049            None
1050        } else {
1051            Some(&self.arena[index].data.skipped_epoch_blocks)
1052        }
1053    }
1054
1055    fn get_blame(&self, arena_index: usize) -> u32 {
1056        let block_header = self
1057            .data_man
1058            .block_header_by_hash(&self.arena[arena_index].hash)
1059            .unwrap();
1060        block_header.blame()
1061    }
1062
1063    fn get_blame_with_pivot_index(&self, pivot_index: usize) -> u32 {
1064        let arena_index = self.pivot_chain[pivot_index];
1065        self.get_blame(arena_index)
1066    }
1067
1068    /// `blame` is an unbounded, attacker-controlled header field (no
1069    /// acceptance check), so `trusted_index - blame - 1` can underflow. Honest
1070    /// headers have `blame < trusted_index`, so `None` only replaces a panic on
1071    /// malformed input; the honest walk is unchanged.
1072    fn prev_trusted_pivot_index(
1073        trusted_index: usize, blame: u32, from: usize,
1074    ) -> Option<usize> {
1075        match trusted_index
1076            .checked_sub(blame as usize)
1077            .and_then(|v| v.checked_sub(1))
1078        {
1079            Some(prev) if prev >= from => Some(prev),
1080            _ => None,
1081        }
1082    }
1083
1084    /// Height just below the range of ancestors a header with the given
1085    /// `blame` vouches for. `blame` is attacker-controlled and unbounded, so
1086    /// `height - blame - 1` can underflow; `None` means the header blames past
1087    /// genesis (impossible for an honest header) and its vote is invalid.
1088    fn blame_covered_start_height(height: u64, blame: u32) -> Option<u64> {
1089        height.checked_sub(blame as u64 + 1)
1090    }
1091
1092    pub fn find_first_index_with_correct_state_of(
1093        &self, pivot_index: usize, blame_bound: Option<u32>,
1094        min_vote_count: usize,
1095    ) -> Option<usize> {
1096        // this is the earliest block we need to consider; blocks before `from`
1097        // cannot have any information about the state root of `pivot_index`
1098        let from = pivot_index + DEFERRED_STATE_EPOCH_COUNT as usize;
1099
1100        self.find_first_trusted_starting_from(from, blame_bound, min_vote_count)
1101    }
1102
1103    pub fn find_first_trusted_starting_from(
1104        &self, from: usize, blame_bound: Option<u32>, min_vote_count: usize,
1105    ) -> Option<usize> {
1106        let mut trusted_index = match self
1107            .find_first_with_trusted_blame_starting_from(
1108                from,
1109                blame_bound,
1110                min_vote_count,
1111            ) {
1112            None => return None,
1113            Some(index) => index,
1114        };
1115
1116        // iteratively search for the smallest trusted index greater than
1117        // or equal to `from`
1118        while trusted_index != from {
1119            let blame = self.get_blame_with_pivot_index(trusted_index);
1120            match Self::prev_trusted_pivot_index(trusted_index, blame, from) {
1121                Some(prev_trusted) => trusted_index = prev_trusted,
1122                None => break,
1123            }
1124        }
1125
1126        Some(trusted_index)
1127    }
1128
1129    fn find_first_with_trusted_blame_starting_from(
1130        &self, pivot_index: usize, blame_bound: Option<u32>,
1131        min_vote_count: usize,
1132    ) -> Option<usize> {
1133        trace!(
1134            "find_first_with_trusted_blame_starting_from pivot_index={:?}",
1135            pivot_index
1136        );
1137        let mut cur_pivot_index = pivot_index;
1138        while cur_pivot_index < self.pivot_chain.len() {
1139            let arena_index = self.pivot_chain[cur_pivot_index];
1140            let blame_ratio = self.compute_blame_ratio(
1141                arena_index,
1142                blame_bound,
1143                min_vote_count,
1144            );
1145            trace!(
1146                "blame_ratio for {:?} is {}",
1147                self.arena[arena_index].hash,
1148                blame_ratio
1149            );
1150            if blame_ratio < MAX_BLAME_RATIO_FOR_TRUST {
1151                return Some(cur_pivot_index);
1152            }
1153            cur_pivot_index += 1;
1154        }
1155
1156        None
1157    }
1158
1159    // Compute the ratio of blames that the block gets
1160    fn compute_blame_ratio(
1161        &self, arena_index: usize, blame_bound: Option<u32>,
1162        min_vote_count: usize,
1163    ) -> f64 {
1164        let blame_bound = if let Some(bound) = blame_bound {
1165            bound
1166        } else {
1167            u32::max_value()
1168        };
1169        let mut total_blame_count = 0 as u64;
1170        let mut queue = VecDeque::new();
1171        let mut votes = HashMap::new();
1172        queue.push_back((arena_index, 0 as u32));
1173        while let Some((index, step)) = queue.pop_front() {
1174            if index == arena_index {
1175                votes.insert(index, true);
1176            } else {
1177                let mut my_blame = self.get_blame(index);
1178                let mut parent = index;
1179                loop {
1180                    parent = self.arena[parent].parent;
1181                    if my_blame == 0 {
1182                        let parent_vote = *votes.get(&parent).unwrap();
1183                        votes.insert(index, parent_vote);
1184                        if !parent_vote {
1185                            total_blame_count += 1;
1186                        }
1187                        break;
1188                    } else if parent == arena_index {
1189                        votes.insert(index, false);
1190                        total_blame_count += 1;
1191                        break;
1192                    }
1193                    my_blame -= 1;
1194                }
1195            }
1196
1197            if step == blame_bound {
1198                continue;
1199            }
1200
1201            let next_step = step + 1;
1202            for child in &self.arena[index].children {
1203                queue.push_back((*child, next_step));
1204            }
1205        }
1206
1207        let total_vote_count = votes.len();
1208
1209        if total_vote_count < min_vote_count {
1210            // if we do not have enough votes, we will signal 100% blame
1211            return 1.0;
1212        }
1213
1214        // TODO(thegaram): compute `total_vote_count` on non-past set,
1215        // not on future
1216        total_blame_count as f64 / total_vote_count as f64
1217    }
1218
1219    pub fn check_mining_adaptive_block(
1220        &mut self, parent_arena_index: usize, referee_indices: Vec<usize>,
1221        difficulty: U256, pos_reference: Option<PosBlockId>,
1222    ) -> bool {
1223        // We first compute anticone barrier for newly mined block
1224        let parent_anticone_opt = self.anticone_cache.get(parent_arena_index);
1225        let mut anticone;
1226        if parent_anticone_opt.is_none() {
1227            anticone = consensus_new_block_handler::ConsensusNewBlockHandler::compute_anticone_bruteforce(
1228                self, parent_arena_index,
1229            );
1230            for i in self.compute_future_bitset(parent_arena_index) {
1231                anticone.add(i);
1232            }
1233        } else {
1234            anticone = self.compute_future_bitset(parent_arena_index);
1235            for index in parent_anticone_opt.unwrap() {
1236                anticone.add(*index as u32);
1237            }
1238        }
1239        let mut my_past = BitSet::new();
1240        let mut queue: VecDeque<usize> = VecDeque::new();
1241        for index in &referee_indices {
1242            queue.push_back(*index);
1243        }
1244        while let Some(index) = queue.pop_front() {
1245            if my_past.contains(index as u32) {
1246                continue;
1247            }
1248            my_past.add(index as u32);
1249            let idx_parent = self.arena[index].parent;
1250            if idx_parent != NULL {
1251                if anticone.contains(idx_parent as u32)
1252                    || self.arena[idx_parent].era_block == NULL
1253                {
1254                    queue.push_back(idx_parent);
1255                }
1256            }
1257            for referee in &self.arena[index].referees {
1258                if anticone.contains(*referee as u32)
1259                    || self.arena[*referee].era_block == NULL
1260                {
1261                    queue.push_back(*referee);
1262                }
1263            }
1264        }
1265        for index in my_past.drain() {
1266            anticone.remove(index);
1267        }
1268
1269        let mut anticone_barrier = BitSet::new();
1270        for index in (&anticone).iter() {
1271            let parent = self.arena[index as usize].parent as u32;
1272            if self.arena[index as usize].era_block != NULL
1273                && !anticone.contains(parent)
1274            {
1275                anticone_barrier.add(index);
1276            }
1277        }
1278
1279        let timer_chain_tuple = self.compute_timer_chain_tuple(
1280            parent_arena_index,
1281            &referee_indices,
1282            Some(&anticone),
1283        );
1284
1285        self.adaptive_weight_impl(
1286            parent_arena_index,
1287            &anticone_barrier,
1288            None,
1289            &timer_chain_tuple,
1290            i128::try_from(difficulty.low_u128()).unwrap(),
1291            pos_reference,
1292        )
1293    }
1294
1295    /// This function computes the subtree weight for each node
1296    /// in the subtree of the past view of *me* by conducting
1297    /// DFS from the cur_era_genesis. The subtree to process
1298    /// is illustrated as follows:
1299    ///                     cur_era_genesis
1300    /// I                        / \
1301    /// I                      /     \
1302    /// I                    /  the    \
1303    /// I                  /   subtree   \
1304    /// I                /   to process    \
1305    /// I                \__             __/
1306    /// I                 a \__       __/ a
1307    /// I                    a \_____/ a
1308    /// I                      a me a
1309    ///
1310    /// *a* refers to the elements in anticone barrier who are
1311    /// anticone of *me* while whose parents are in the past set
1312    /// of *me*. The subtree to process does not include *a* and
1313    /// *me*.
1314    fn compute_subtree_weights(
1315        &self, me: usize, anticone_barrier: &BitSet,
1316    ) -> Vec<i128> {
1317        let mut subtree_weight = Vec::new();
1318        let n = self.arena.capacity();
1319        subtree_weight.resize_with(n, Default::default);
1320        let mut stack = Vec::new();
1321        stack.push((0, self.cur_era_genesis_block_arena_index));
1322        while let Some((stage, index)) = stack.pop() {
1323            if stage == 0 {
1324                stack.push((1, index));
1325                subtree_weight[index] = 0;
1326                for child in &self.arena[index].children {
1327                    if !anticone_barrier.contains(*child as u32) && *child != me
1328                    {
1329                        stack.push((0, *child));
1330                    }
1331                }
1332            } else {
1333                let weight = self.block_weight(index);
1334                subtree_weight[index] += weight;
1335                let parent = self.arena[index].parent;
1336                if parent != NULL {
1337                    subtree_weight[parent] += subtree_weight[index];
1338                }
1339            }
1340        }
1341        subtree_weight
1342    }
1343
1344    fn get_best_timer_tick(
1345        &self,
1346        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
1347    ) -> u64 {
1348        let (fork_at, _, _, c) = timer_chain_tuple;
1349        *fork_at + c.len() as u64
1350    }
1351
1352    fn get_timer_tick(
1353        &self, me: usize,
1354        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
1355    ) -> u64 {
1356        let (fork_at, m, _, _) = timer_chain_tuple;
1357        if let Some(t) = m.get(&me) {
1358            return *t;
1359        } else {
1360            assert!(
1361                self.arena[me].data.ledger_view_timer_chain_height <= *fork_at
1362            );
1363        }
1364        return self.arena[me].data.ledger_view_timer_chain_height;
1365    }
1366
1367    fn adaptive_weight_impl_brutal(
1368        &self, parent_0: usize, subtree_weight: &Vec<i128>,
1369        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
1370        force_confirm: usize, difficulty: i128,
1371    ) -> bool {
1372        let mut parent = parent_0;
1373
1374        let force_confirm_height = self.arena[force_confirm].height;
1375        let timer_me = self.get_best_timer_tick(timer_chain_tuple);
1376
1377        let adjusted_beta =
1378            (self.inner_conf.adaptive_weight_beta as i128) * difficulty;
1379
1380        let mut adaptive = false;
1381        while self.arena[parent].height != force_confirm_height {
1382            let grandparent = self.arena[parent].parent;
1383            let timer_parent = self.get_timer_tick(parent, timer_chain_tuple);
1384            assert!(timer_me >= timer_parent);
1385            if timer_me - timer_parent >= self.inner_conf.timer_chain_beta {
1386                let w = 2 * subtree_weight[parent]
1387                    - subtree_weight[grandparent]
1388                    + self.block_weight(grandparent);
1389                if w < adjusted_beta {
1390                    adaptive = true;
1391                    break;
1392                }
1393            }
1394            parent = grandparent;
1395        }
1396
1397        adaptive
1398    }
1399
1400    fn adaptive_weight_impl(
1401        &mut self, parent_0: usize, anticone_barrier: &BitSet,
1402        weight_tuple: Option<&Vec<i128>>,
1403        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
1404        difficulty: i128, pos_reference: Option<PosBlockId>,
1405    ) -> bool {
1406        let mut parent = parent_0;
1407        let force_confirm =
1408            self.compute_block_force_confirm(timer_chain_tuple, pos_reference);
1409        let force_confirm_height = self.arena[force_confirm].height;
1410        // This may happen if we are forced to generate at a position choosing
1411        // incorrect parent. We should return false here.
1412        if self.arena[parent].height < force_confirm_height
1413            || self.ancestor_at(parent, force_confirm_height) != force_confirm
1414        {
1415            return false;
1416        }
1417        if let Some(subtree_weight) = weight_tuple {
1418            return self.adaptive_weight_impl_brutal(
1419                parent_0,
1420                subtree_weight,
1421                timer_chain_tuple,
1422                force_confirm,
1423                difficulty,
1424            );
1425        }
1426
1427        let mut weight_delta = HashMap::new();
1428
1429        for index in anticone_barrier.iter() {
1430            assert!(!self.is_legacy_block(index as usize));
1431            weight_delta
1432                .insert(index as usize, self.weight_tree.get(index as usize));
1433        }
1434
1435        for (index, delta) in &weight_delta {
1436            self.weight_tree.path_apply(*index, -*delta);
1437            let parent = self.arena[*index].parent;
1438            assert!(parent != NULL);
1439            self.adaptive_tree.caterpillar_apply(parent, *delta);
1440            self.adaptive_tree.path_apply(*index, -*delta * 2);
1441        }
1442
1443        let timer_me = self.get_best_timer_tick(timer_chain_tuple);
1444        let adjusted_beta = self.inner_conf.timer_chain_beta;
1445
1446        let mut high = self.arena[parent].height;
1447        let mut low = force_confirm_height + 1;
1448        // [low, high]
1449        let mut best = force_confirm_height;
1450
1451        while low <= high {
1452            let mid = (low + high) / 2;
1453            let p = self.ancestor_at(parent, mid);
1454            let timer_mid = self.get_timer_tick(p, timer_chain_tuple);
1455            assert!(timer_me >= timer_mid);
1456            if timer_me - timer_mid >= adjusted_beta {
1457                best = mid;
1458                low = mid + 1;
1459            } else {
1460                high = mid - 1;
1461            }
1462        }
1463
1464        let adaptive = if best != force_confirm_height {
1465            parent = self.ancestor_at(parent, best);
1466
1467            let a = self
1468                .adaptive_tree
1469                .path_aggregate_chop(parent, force_confirm);
1470            let b = self.inner_conf.adaptive_weight_beta as i128 * difficulty;
1471
1472            if a < b {
1473                debug!("block is adaptive: {:?} < {:?}!", a, b);
1474            } else {
1475                debug!("block is not adaptive: {:?} >= {:?}!", a, b);
1476            }
1477            a < b
1478        } else {
1479            debug!(
1480                "block is not adaptive: too close to genesis, timer tick {:?}",
1481                timer_me
1482            );
1483            false
1484        };
1485
1486        for (index, delta) in &weight_delta {
1487            self.weight_tree.path_apply(*index, *delta);
1488            let parent = self.arena[*index].parent;
1489            self.adaptive_tree.caterpillar_apply(parent, -*delta);
1490            self.adaptive_tree.path_apply(*index, *delta * 2)
1491        }
1492
1493        adaptive
1494    }
1495
1496    /// Determine whether we should generate adaptive blocks or not. It is used
1497    /// both for block generations and for block validations.
1498    fn adaptive_weight(
1499        &mut self, me: usize, anticone_barrier: &BitSet,
1500        weight_tuple: Option<&Vec<i128>>,
1501        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
1502    ) -> bool {
1503        let parent = self.arena[me].parent;
1504        assert!(parent != NULL);
1505
1506        let difficulty =
1507            i128::try_from(self.arena[me].difficulty.low_u128()).unwrap();
1508
1509        self.adaptive_weight_impl(
1510            parent,
1511            anticone_barrier,
1512            weight_tuple,
1513            timer_chain_tuple,
1514            difficulty,
1515            self.data_man
1516                .pos_reference_by_hash(&self.arena[me].hash)
1517                .expect("header exist"),
1518        )
1519    }
1520
1521    #[inline]
1522    fn is_same_era(&self, me: usize, pivot: usize) -> bool {
1523        self.arena[me].era_block == self.arena[pivot].era_block
1524    }
1525
1526    fn compute_pastset_brutal(&mut self, me: usize) -> BitSet {
1527        let mut path = Vec::new();
1528        let mut cur = me;
1529        while cur != NULL && self.pastset_cache.get(cur).is_none() {
1530            path.push(cur);
1531            cur = self.arena[cur].parent;
1532        }
1533        path.reverse();
1534        let mut result = self
1535            .pastset_cache
1536            .get(cur)
1537            .unwrap_or(&BitSet::new())
1538            .clone();
1539        for ancestor_arena_index in path {
1540            result.add(ancestor_arena_index as u32);
1541            if self.arena[ancestor_arena_index].data.blockset_cleared {
1542                let mut queue = VecDeque::new();
1543                queue.push_back(ancestor_arena_index);
1544                while let Some(index) = queue.pop_front() {
1545                    let parent = self.arena[index].parent;
1546                    if parent != NULL && !result.contains(parent as u32) {
1547                        result.add(parent as u32);
1548                        queue.push_back(parent);
1549                    }
1550                    for referee in &self.arena[index].referees {
1551                        if !result.contains(*referee as u32) {
1552                            result.add(*referee as u32);
1553                            queue.push_back(*referee);
1554                        }
1555                    }
1556                }
1557            } else {
1558                let blockset = self
1559                    .exchange_or_compute_blockset_in_own_view_of_epoch(
1560                        ancestor_arena_index,
1561                        None,
1562                    );
1563                for index in &blockset {
1564                    result.add(*index as u32);
1565                }
1566                self.exchange_or_compute_blockset_in_own_view_of_epoch(
1567                    ancestor_arena_index,
1568                    Some(blockset),
1569                );
1570            }
1571        }
1572        result
1573    }
1574
1575    /// All referees should be in the anticone of each other.
1576    /// If there is a path from a referee `A` to another referee `B` by
1577    /// following edges towards parent/referees, we will treat `A` as a
1578    /// valid referee and ignore `B` because `B` is not the graph terminal.
1579    /// This should only happen if the miner generating this
1580    /// block is malicious. TODO: Explain why not `partial_invalid`?
1581    fn insert_referee_if_not_duplicate(
1582        &self, referees: &mut Vec<usize>, me: usize,
1583    ) {
1584        for i in 0..referees.len() {
1585            let x = referees[i];
1586            let lca = self.lca(x, me);
1587            if lca == me {
1588                // `me` is an ancestor of `x`
1589                return;
1590            } else if lca == x {
1591                // `x` is an ancestor of `me`
1592                referees[i] = me;
1593                return;
1594            }
1595        }
1596        referees.push(me)
1597    }
1598
1599    /// Try to insert an outside era block, return it's sequence number. If both
1600    /// it's parent and referees are empty, we will not insert it into
1601    /// `arena`.
1602    pub fn insert_out_era_block(
1603        &mut self, block_header: &BlockHeader, partial_invalid: bool,
1604    ) -> (u64, usize) {
1605        let sn = self.get_next_sequence_number();
1606        let hash = block_header.hash();
1607        // we make cur_era_genesis be it's parent if it doesn‘t has one.
1608        let parent = self
1609            .hash_to_arena_indices
1610            .get(block_header.parent_hash())
1611            .cloned()
1612            .unwrap_or(NULL);
1613
1614        let mut referees: Vec<usize> = Vec::new();
1615        for hash in block_header.referee_hashes().iter() {
1616            if let Some(x) = self.hash_to_arena_indices.get(hash) {
1617                self.insert_referee_if_not_duplicate(&mut referees, *x);
1618            }
1619        }
1620
1621        if parent == NULL && referees.is_empty() {
1622            return (sn, NULL);
1623        }
1624
1625        let mut inactive_dependency_cnt = 0;
1626        for referee in &referees {
1627            if !self.arena[*referee].data.activated {
1628                inactive_dependency_cnt += 1;
1629            }
1630        }
1631
1632        // actually, we only need these fields: `parent`, `referees`,
1633        // `children`, `referrers`, `era_block`
1634        let index = self.arena.insert(ConsensusGraphNode {
1635            hash,
1636            height: block_header.height(),
1637            is_heavy: true,
1638            difficulty: *block_header.difficulty(),
1639            past_num_blocks: 0,
1640            is_timer: false,
1641            // Block header contains an adaptive field, we will verify with our
1642            // own computation
1643            adaptive: block_header.adaptive(),
1644            parent,
1645            era_block: NULL,
1646            children: Vec::new(),
1647            referees,
1648            referrers: Vec::new(),
1649            data: ConsensusGraphNodeData::new(
1650                NULLU64,
1651                sn,
1652                inactive_dependency_cnt,
1653            ),
1654        });
1655        self.arena[index].data.pending = true;
1656        self.arena[index].data.activated = false;
1657        self.arena[index].data.partial_invalid = partial_invalid;
1658        self.hash_to_arena_indices.insert(hash, index);
1659
1660        let referees = self.arena[index].referees.clone();
1661        for referee in referees {
1662            self.arena[referee].referrers.push(index);
1663        }
1664        if parent != NULL {
1665            self.arena[parent].children.push(index);
1666        }
1667
1668        self.weight_tree.make_tree(index);
1669        self.adaptive_tree.make_tree(index);
1670
1671        (sn, index)
1672    }
1673
1674    fn get_timer_difficulty(&self, me: usize) -> i128 {
1675        if self.arena[me].is_timer && !self.arena[me].data.partial_invalid {
1676            i128::try_from(self.arena[me].difficulty.low_u128()).unwrap()
1677        } else {
1678            0
1679        }
1680    }
1681
1682    fn compute_global_force_confirm(&self) -> usize {
1683        let timer_chain_choice =
1684            if let Some(x) = self.timer_chain_accumulative_lca.last() {
1685                *x
1686            } else {
1687                self.cur_era_genesis_block_arena_index
1688            };
1689        self.compute_force_confirm(
1690            timer_chain_choice,
1691            &self.best_pos_pivot_decision,
1692        )
1693    }
1694
1695    fn compute_block_force_confirm(
1696        &self,
1697        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
1698        pos_reference: Option<PosBlockId>,
1699    ) -> usize {
1700        let (fork_at, _, extra_lca, tmp_chain) = timer_chain_tuple;
1701        let fork_end_index =
1702            (*fork_at - self.cur_era_genesis_timer_chain_height) as usize
1703                + tmp_chain.len();
1704        let acc_lca_ref = extra_lca;
1705        let timer_chain_choice = if let Some(x) = acc_lca_ref.last() {
1706            *x
1707        } else if fork_end_index > self.inner_conf.timer_chain_beta as usize {
1708            self.timer_chain_accumulative_lca
1709                [fork_end_index - self.inner_conf.timer_chain_beta as usize - 1]
1710        } else {
1711            self.cur_era_genesis_block_arena_index
1712        };
1713        match pos_reference {
1714            None => timer_chain_choice,
1715            Some(pos_reference) => {
1716                let pos_pivot_decision = self
1717                    .pos_verifier
1718                    .get_pivot_decision(&pos_reference)
1719                    .expect("pos_reference checked");
1720                self.compute_force_confirm(
1721                    timer_chain_choice,
1722                    &(
1723                        pos_pivot_decision,
1724                        self.data_man
1725                            .block_height_by_hash(&pos_pivot_decision)
1726                            .expect("pos pivot decision checked"),
1727                    ),
1728                )
1729            }
1730        }
1731    }
1732
1733    fn compute_force_confirm(
1734        &self, timer_chain_choice: usize, pos_pivot_decision: &(H256, u64),
1735    ) -> usize {
1736        if let Some(arena_index) =
1737            self.hash_to_arena_indices.get(&pos_pivot_decision.0)
1738        {
1739            if self.arena[timer_chain_choice].height > pos_pivot_decision.1
1740                && self.lca(timer_chain_choice, *arena_index) == *arena_index
1741            {
1742                // timer chain force confirm is newer and following pos
1743                // reference.
1744                timer_chain_choice
1745            } else {
1746                // timer chain force confirm should be overwritten by a conflict
1747                // pos reference.
1748                *arena_index
1749            }
1750        } else {
1751            // If pos_pivot_decision is before checkpoint, we just think it's on
1752            // the pivot chain.
1753            timer_chain_choice
1754        }
1755    }
1756
1757    fn insert(&mut self, block_header: &BlockHeader) -> (usize, usize) {
1758        let hash = block_header.hash();
1759
1760        let pow_quality =
1761            U512::from(VerificationConfig::get_or_compute_header_pow_quality(
1762                &self.pow,
1763                block_header,
1764            ));
1765        let is_heavy = pow_quality
1766            >= U512::from(self.inner_conf.heavy_block_difficulty_ratio)
1767                * U512::from(block_header.difficulty());
1768        let is_timer = pow_quality
1769            >= U512::from(self.inner_conf.timer_chain_block_difficulty_ratio)
1770                * U512::from(block_header.difficulty());
1771
1772        let parent =
1773            if hash != self.data_man.get_cur_consensus_era_genesis_hash() {
1774                self.hash_to_arena_indices
1775                    .get(block_header.parent_hash())
1776                    .cloned()
1777                    .unwrap()
1778            } else {
1779                NULL
1780            };
1781
1782        let mut referees: Vec<usize> = Vec::new();
1783        for hash in block_header.referee_hashes().iter() {
1784            if let Some(x) = self.hash_to_arena_indices.get(hash) {
1785                self.insert_referee_if_not_duplicate(&mut referees, *x);
1786            }
1787        }
1788
1789        let mut inactive_dependency_cnt =
1790            if parent != NULL && !self.arena[parent].data.activated {
1791                1
1792            } else {
1793                0
1794            };
1795        for referee in &referees {
1796            if !self.arena[*referee].data.activated {
1797                inactive_dependency_cnt += 1;
1798            }
1799        }
1800
1801        let my_height = block_header.height();
1802        let sn = self.get_next_sequence_number();
1803        let index = self.arena.insert(ConsensusGraphNode {
1804            hash,
1805            height: my_height,
1806            is_heavy,
1807            difficulty: *block_header.difficulty(),
1808            past_num_blocks: 0,
1809            is_timer,
1810            // Block header contains an adaptive field, we will verify with our
1811            // own computation
1812            adaptive: block_header.adaptive(),
1813            parent,
1814            era_block: self.get_era_genesis_block_with_parent(parent),
1815            children: Vec::new(),
1816            referees,
1817            referrers: Vec::new(),
1818            data: ConsensusGraphNodeData::new(
1819                NULLU64,
1820                sn,
1821                inactive_dependency_cnt,
1822            ),
1823        });
1824        self.hash_to_arena_indices.insert(hash, index);
1825
1826        if parent != NULL {
1827            self.arena[parent].children.push(index);
1828        }
1829        let referees = self.arena[index].referees.clone();
1830        for referee in referees {
1831            self.arena[referee].referrers.push(index);
1832        }
1833
1834        self.compute_blockset_in_own_view_of_epoch(index);
1835        let executed_epoch_len =
1836            self.get_ordered_executable_epoch_blocks(index).len();
1837
1838        if parent != NULL {
1839            let past_num_blocks =
1840                self.arena[parent].past_num_blocks + executed_epoch_len as u64;
1841
1842            self.data_man.insert_epoch_execution_context(
1843                hash.clone(),
1844                EpochExecutionContext {
1845                    start_block_number: self
1846                        .get_epoch_start_block_number(index),
1847                },
1848                true, /* persistent to db */
1849            );
1850
1851            self.arena[index].past_num_blocks = past_num_blocks;
1852        }
1853
1854        debug!(
1855            "Block {} inserted into Consensus with index={}",
1856            hash, index
1857        );
1858
1859        (index, self.hash_to_arena_indices.len())
1860    }
1861
1862    fn compute_future_bitset(&self, me: usize) -> BitSet {
1863        // Compute future set of parent
1864        let mut queue: VecDeque<usize> = VecDeque::new();
1865        let mut visited = BitSet::with_capacity(self.arena.len() as u32);
1866        queue.push_back(me);
1867        visited.add(me as u32);
1868        while let Some(index) = queue.pop_front() {
1869            for child in &self.arena[index].children {
1870                if !visited.contains(*child as u32)
1871                    && (self.arena[*child].data.activated
1872                        || self.arena[*child].data.inactive_dependency_cnt
1873                            == NULL)
1874                /* We include all preactivated blocks */
1875                {
1876                    visited.add(*child as u32);
1877                    queue.push_back(*child);
1878                }
1879            }
1880            for referrer in &self.arena[index].referrers {
1881                if !visited.contains(*referrer as u32)
1882                    && (self.arena[*referrer].data.activated
1883                        || self.arena[*referrer].data.inactive_dependency_cnt
1884                            == NULL)
1885                /* We include all preactivated blocks */
1886                {
1887                    visited.add(*referrer as u32);
1888                    queue.push_back(*referrer);
1889                }
1890            }
1891        }
1892        visited.remove(me as u32);
1893        visited
1894    }
1895
1896    /// Return the consensus graph indexes of the pivot block where the rewards
1897    /// of its epoch should be computed.
1898    ///
1899    ///   epoch to                         Block holding
1900    ///   compute reward                   the reward state
1901    ///                         Block epoch                  Block with
1902    ///   | \[Bi1\]   |           for cared                    \[Bj\]'s state
1903    ///   |     \   |           anticone                     as deferred root
1904    /// --|----\[Bi\]-|--------------\[Ba\]---------\[Bj\]----------\[Bt\]
1905    ///   |    /    |
1906    ///   | \[Bi2\]   |
1907    ///
1908    /// Let i(\[Bi\]) is the arena index of \[Bi\].
1909    /// Let h(\[Bi\]) is the height of \[Bi\].
1910    ///
1911    /// Params:
1912    ///   epoch_arena_index: the arena index of \[Bj\]
1913    /// Return:
1914    ///   Option<(i(\[Bi\]), i(\[Ba\]))>
1915    ///
1916    /// The gap between \[Bj\] and \[Bi\], i.e., h(\[Bj\])-h(\[Bi\]),
1917    /// is REWARD_EPOCH_COUNT.
1918    /// Let D is the gap between the parent of the genesis of next era and
1919    /// \[Bi\]. The gap between \[Ba\] and \[Bi\] is
1920    ///     min(ANTICONE_PENALTY_UPPER_EPOCH_COUNT, D).
1921    pub fn get_pivot_reward_index(
1922        &self, epoch_arena_index: usize,
1923    ) -> Option<(usize, usize)> {
1924        // We are going to exclude the original genesis block here!
1925        if self.arena[epoch_arena_index].height <= REWARD_EPOCH_COUNT {
1926            return None;
1927        }
1928        let parent_index = self.arena[epoch_arena_index].parent;
1929        // Recompute epoch.
1930        let anticone_cut_height =
1931            REWARD_EPOCH_COUNT - ANTICONE_PENALTY_UPPER_EPOCH_COUNT;
1932        let mut anticone_penalty_cutoff_epoch_block = parent_index;
1933        for _i in 1..anticone_cut_height {
1934            if anticone_penalty_cutoff_epoch_block == NULL {
1935                break;
1936            }
1937            anticone_penalty_cutoff_epoch_block =
1938                self.arena[anticone_penalty_cutoff_epoch_block].parent;
1939        }
1940        let mut reward_epoch_block = anticone_penalty_cutoff_epoch_block;
1941        for _i in 0..ANTICONE_PENALTY_UPPER_EPOCH_COUNT {
1942            if reward_epoch_block == NULL {
1943                break;
1944            }
1945            reward_epoch_block = self.arena[reward_epoch_block].parent;
1946        }
1947        if reward_epoch_block != NULL {
1948            // The anticone_penalty_cutoff respect the era bound!
1949            while !self.is_same_era(
1950                reward_epoch_block,
1951                anticone_penalty_cutoff_epoch_block,
1952            ) {
1953                anticone_penalty_cutoff_epoch_block =
1954                    self.arena[anticone_penalty_cutoff_epoch_block].parent;
1955            }
1956        }
1957        let reward_index = if reward_epoch_block == NULL {
1958            None
1959        } else {
1960            Some((reward_epoch_block, anticone_penalty_cutoff_epoch_block))
1961        };
1962        reward_index
1963    }
1964
1965    fn get_executable_epoch_blocks(
1966        &self, epoch_arena_index: usize,
1967    ) -> Vec<Arc<Block>> {
1968        let mut epoch_blocks = Vec::new();
1969        for idx in self.get_ordered_executable_epoch_blocks(epoch_arena_index) {
1970            let block = self
1971                .data_man
1972                .block_by_hash(
1973                    &self.arena[*idx].hash,
1974                    true, /* update_cache */
1975                )
1976                .expect("Exist");
1977            epoch_blocks.push(block);
1978        }
1979        epoch_blocks
1980    }
1981
1982    /// Compute the expected difficulty of a new block given its parent.
1983    /// Assume the difficulty adjustment period being p.
1984    /// The period boundary is [i*p+1, (i+1)*p].
1985    /// Genesis block does not belong to any period, and the first
1986    /// period is [1, p]. Then, if parent height is less than p, the
1987    /// current block belongs to the first period, and its difficulty
1988    /// should be the initial difficulty. Otherwise, we need to consider
1989    /// 2 cases:
1990    ///
1991    /// 1. The parent height is at the period boundary, i.e., the height
1992    /// is exactly divisible by p. In this case, the new block and its
1993    /// parent do not belong to the same period. The expected difficulty
1994    /// of the new block should be computed based on the situation of
1995    /// parent's period.
1996    ///
1997    /// 2. The parent height is not at the period boundary. In this case,
1998    /// the new block and its parent belong to the same period, and hence,
1999    /// its difficulty should be same as its parent's.
2000    pub fn expected_difficulty(&self, parent_hash: &H256) -> U256 {
2001        let parent_arena_index =
2002            *self.hash_to_arena_indices.get(parent_hash).unwrap();
2003        let parent_epoch = self.arena[parent_arena_index].height;
2004        if parent_epoch
2005            < self
2006                .pow_config
2007                .difficulty_adjustment_epoch_period(parent_epoch)
2008        {
2009            // Use initial difficulty for early epochs
2010            self.pow_config.initial_difficulty.into()
2011        } else {
2012            let last_period_upper = (parent_epoch
2013                / self
2014                    .pow_config
2015                    .difficulty_adjustment_epoch_period(parent_epoch))
2016                * self
2017                    .pow_config
2018                    .difficulty_adjustment_epoch_period(parent_epoch);
2019            if last_period_upper != parent_epoch {
2020                self.arena[parent_arena_index].difficulty
2021            } else {
2022                self.data_man.target_difficulty_manager.target_difficulty(
2023                    self,
2024                    // &self.data_man.target_difficulty_manager,
2025                    &self.pow_config,
2026                    &self.arena[parent_arena_index].hash,
2027                )
2028            }
2029        }
2030    }
2031
2032    fn adjust_difficulty(&mut self, new_best_arena_index: usize) {
2033        let new_best_hash = self.arena[new_best_arena_index].hash.clone();
2034        let new_best_difficulty = self.arena[new_best_arena_index].difficulty;
2035        let old_best_arena_index = *self.pivot_chain.last().expect("not empty");
2036        if old_best_arena_index == self.arena[new_best_arena_index].parent {
2037            // Pivot chain prolonged
2038            assert!(self.current_difficulty == new_best_difficulty);
2039        }
2040
2041        let epoch = self.arena[new_best_arena_index].height;
2042        if epoch == 0 {
2043            // This may happen since the block at height 1 may have wrong
2044            // state root and do not update the pivot chain.
2045            self.current_difficulty = self.pow_config.initial_difficulty.into();
2046        } else if epoch
2047            == (epoch
2048                / self.pow_config.difficulty_adjustment_epoch_period(epoch))
2049                * self.pow_config.difficulty_adjustment_epoch_period(epoch)
2050        {
2051            let this: &ConsensusGraphInner = self;
2052            self.current_difficulty = self
2053                .data_man
2054                .target_difficulty_manager
2055                .target_difficulty(this, &self.pow_config, &new_best_hash);
2056        } else {
2057            self.current_difficulty = new_best_difficulty;
2058        }
2059    }
2060
2061    pub fn best_block_hash(&self) -> H256 {
2062        self.arena[*self.pivot_chain.last().unwrap()].hash
2063    }
2064
2065    pub fn best_block_number(&self) -> u64 {
2066        self.arena[*self.pivot_chain.last().unwrap()].past_num_blocks
2067    }
2068
2069    /// Return the latest epoch number whose state has been enqueued.
2070    ///
2071    /// The state may not exist, so the caller should wait for the result if its
2072    /// state will be used.
2073    pub fn best_state_epoch_number(&self) -> u64 {
2074        let pivot_height = self.pivot_index_to_height(self.pivot_chain.len());
2075        if pivot_height < DEFERRED_STATE_EPOCH_COUNT {
2076            0
2077        } else {
2078            pivot_height - DEFERRED_STATE_EPOCH_COUNT
2079        }
2080    }
2081
2082    fn best_state_arena_index(&self) -> usize {
2083        self.get_pivot_block_arena_index(self.best_state_epoch_number())
2084    }
2085
2086    pub fn best_state_block_hash(&self) -> H256 {
2087        self.arena[self.best_state_arena_index()].hash
2088    }
2089
2090    pub fn get_state_block_with_delay(
2091        &self, block_hash: &H256, delay: usize,
2092    ) -> Result<&H256, String> {
2093        let idx_opt = self.hash_to_arena_indices.get(block_hash);
2094        if idx_opt == None {
2095            return Err(
2096                "Parent hash is too old for computing the deferred state"
2097                    .to_owned(),
2098            );
2099        }
2100        let mut idx = *idx_opt.unwrap();
2101        for _i in 0..delay {
2102            trace!(
2103                "get_state_block_with_delay: idx={}, height={}",
2104                idx,
2105                self.arena[idx].height
2106            );
2107            if idx == self.cur_era_genesis_block_arena_index {
2108                // If it is the original genesis, we just break
2109                if self.arena[self.cur_era_genesis_block_arena_index].height
2110                    == 0
2111                {
2112                    break;
2113                } else {
2114                    return Err(
2115                        "Parent is too old for computing the deferred state"
2116                            .to_owned(),
2117                    );
2118                }
2119            }
2120            idx = self.arena[idx].parent;
2121        }
2122        Ok(&self.arena[idx].hash)
2123    }
2124
2125    pub fn best_epoch_number(&self) -> u64 {
2126        self.cur_era_genesis_height + self.pivot_chain.len() as u64 - 1
2127    }
2128
2129    pub fn best_timer_chain_height(&self) -> u64 {
2130        self.cur_era_genesis_timer_chain_height + self.timer_chain.len() as u64
2131            - 1
2132    }
2133
2134    fn get_arena_index_from_epoch_number(
2135        &self, epoch_number: u64,
2136    ) -> Result<usize, String> {
2137        if epoch_number >= self.cur_era_genesis_height {
2138            let pivot_index =
2139                (epoch_number - self.cur_era_genesis_height) as usize;
2140            if pivot_index >= self.pivot_chain.len() {
2141                Err("Epoch number larger than the current pivot chain tip"
2142                    .into())
2143            } else {
2144                Ok(self.get_pivot_block_arena_index(epoch_number))
2145            }
2146        } else {
2147            Err("Invalid params: epoch number is too old and not maintained by consensus graph".to_owned())
2148        }
2149    }
2150
2151    /// Get the pivot hash from an epoch number. This function will try to query
2152    /// the data manager if it is not available in the ConsensusGraph due to
2153    /// out of the current era.
2154    pub fn get_pivot_hash_from_epoch_number(
2155        &self, epoch_number: u64,
2156    ) -> Result<EpochId, ProviderBlockError> {
2157        let height = epoch_number;
2158        if height >= self.cur_era_genesis_height {
2159            let pivot_index = (height - self.cur_era_genesis_height) as usize;
2160            if pivot_index >= self.pivot_chain.len() {
2161                Err("Epoch number larger than the current pivot chain tip"
2162                    .into())
2163            } else {
2164                Ok(self.arena[self.get_pivot_block_arena_index(height)].hash)
2165            }
2166        } else {
2167            self.data_man.executed_epoch_set_hashes_from_db(epoch_number).ok_or(
2168                format!("get_hash_from_epoch_number: Epoch hash set not in db, epoch_number={}", epoch_number).into()
2169            ).and_then(|epoch_hashes|
2170                epoch_hashes.last().map(Clone::clone).ok_or("Epoch set is empty".into())
2171            )
2172        }
2173    }
2174
2175    /// This function differs from `get_pivot_hash_from_epoch_number` in that it
2176    /// only returns the hash if it is in the current consensus graph.
2177    pub fn epoch_hash(&self, epoch_number: u64) -> Option<H256> {
2178        let pivot_index = self.height_to_pivot_index(epoch_number);
2179        self.pivot_chain
2180            .get(pivot_index)
2181            .map(|idx| self.arena[*idx].hash)
2182    }
2183
2184    pub fn block_hashes_by_epoch(
2185        &self, epoch_number: u64,
2186    ) -> Result<Vec<H256>, ProviderBlockError> {
2187        debug!(
2188            "block_hashes_by_epoch epoch_number={:?} pivot_chain.len={:?}",
2189            epoch_number,
2190            self.pivot_chain.len()
2191        );
2192
2193        let e;
2194        // We first try to get it from the consensus. Note that we cannot use
2195        // the info for the genesis because it may contain out-of-era
2196        // blocks that is not maintained anymore.
2197        match self.get_arena_index_from_epoch_number(epoch_number) {
2198            Ok(pivot_arena_index) => {
2199                if pivot_arena_index != self.cur_era_genesis_block_arena_index {
2200                    return Ok(self
2201                        .get_ordered_executable_epoch_blocks(pivot_arena_index)
2202                        .iter()
2203                        .map(|index| self.arena[*index].hash)
2204                        .collect());
2205                }
2206                e = "Epoch set of the current genesis is not maintained".into();
2207            }
2208            Err(err) => e = err,
2209        }
2210
2211        self.data_man
2212            .executed_epoch_set_hashes_from_db(epoch_number)
2213            .ok_or(
2214                format!(
2215                    "Epoch set not in db epoch_number={}, in mem err={:?}",
2216                    epoch_number, e
2217                )
2218                .into(),
2219            )
2220    }
2221
2222    pub fn skipped_block_hashes_by_epoch(
2223        &self, epoch_number: u64,
2224    ) -> Result<Vec<H256>, ProviderBlockError> {
2225        debug!(
2226            "skipped_block_hashes_by_epoch epoch_number={:?} pivot_chain.len={:?}",
2227            epoch_number,
2228            self.pivot_chain.len()
2229        );
2230
2231        let e;
2232        // We first try to get it from the consensus. Note that we cannot use
2233        // the info for the genesis because it may contain out-of-era
2234        // blocks that is not maintained anymore.
2235        match self.get_arena_index_from_epoch_number(epoch_number) {
2236            Ok(pivot_arena_index) => {
2237                if pivot_arena_index != self.cur_era_genesis_block_arena_index {
2238                    if let Some(skipped_block_set) =
2239                        self.get_skipped_epoch_blocks(pivot_arena_index)
2240                    {
2241                        return Ok(skipped_block_set.clone());
2242                    }
2243                }
2244                e = "Skipped epoch set of the current genesis is not maintained".into();
2245            }
2246            Err(err) => e = err,
2247        }
2248
2249        self.data_man
2250            .skipped_epoch_set_hashes_from_db(epoch_number)
2251            .ok_or(
2252                format!(
2253                    "Skipped epoch set not in db epoch_number={}, in mem err={:?}",
2254                    epoch_number, e
2255                )
2256                    .into(),
2257            )
2258    }
2259
2260    fn get_epoch_hash_for_block(&self, hash: &H256) -> Option<H256> {
2261        self.get_block_epoch_number(&hash)
2262            .and_then(|epoch_number| self.epoch_hash(epoch_number))
2263    }
2264
2265    pub fn bounded_terminal_block_hashes(
2266        &mut self, referee_bound: usize,
2267    ) -> Vec<H256> {
2268        let best_block_arena_index = *self.pivot_chain.last().unwrap();
2269        if self.terminal_hashes.len() > referee_bound {
2270            self.best_terminals(best_block_arena_index, referee_bound)
2271        } else {
2272            self.terminal_hashes
2273                .iter()
2274                .map(|hash| hash.clone())
2275                .collect()
2276        }
2277    }
2278
2279    pub fn get_block_epoch_number(&self, hash: &H256) -> Option<u64> {
2280        self.hash_to_arena_indices.get(hash).and_then(|index| {
2281            match self.arena[*index].data.epoch_number {
2282                NULLU64 => None,
2283                epoch => Some(epoch),
2284            }
2285        })
2286    }
2287
2288    pub fn all_blocks_with_topo_order(&self) -> Vec<H256> {
2289        let epoch_number = self.best_epoch_number();
2290        let mut current_number = 0;
2291        let mut hashes = Vec::new();
2292        while current_number <= epoch_number {
2293            let epoch_hashes =
2294                self.block_hashes_by_epoch(current_number.into()).unwrap();
2295            for hash in epoch_hashes {
2296                hashes.push(hash);
2297            }
2298            current_number += 1;
2299        }
2300        hashes
2301    }
2302
2303    /// Return the block receipts in the current pivot view and the epoch block
2304    /// hash. If `hash` is not executed in the current view, return None.
2305    pub fn block_execution_results_by_hash(
2306        &self, hash: &H256, update_cache: bool,
2307    ) -> Option<BlockExecutionResultWithEpoch> {
2308        match self.get_epoch_hash_for_block(hash) {
2309            Some(epoch) => {
2310                trace!("Block {} is in epoch {}", hash, epoch);
2311                let execution_result =
2312                    self.data_man.block_execution_result_by_hash_with_epoch(
2313                        hash,
2314                        &epoch,
2315                        false, /* update_pivot_assumption */
2316                        update_cache,
2317                    )?;
2318                Some(DataVersionTuple(epoch, execution_result))
2319            }
2320            None => {
2321                debug!("Block {:?} not in mem, try to read from db", hash);
2322
2323                // result in db might be outdated
2324                // (after chain reorg but before re-execution)
2325                let res = match self
2326                    .data_man
2327                    .block_execution_result_by_hash_from_db(hash)
2328                {
2329                    None => return None,
2330                    Some(res) => res,
2331                };
2332
2333                let execution_pivot_hash = res.0;
2334                let epoch_number = self
2335                    .data_man
2336                    .block_header_by_hash(&execution_pivot_hash)?
2337                    .height();
2338
2339                match self.get_pivot_hash_from_epoch_number(epoch_number) {
2340                    // pivot chain has not changed, result should be correct
2341                    Ok(h) if h == execution_pivot_hash => Some(res),
2342
2343                    // pivot chain has changed, block is not re-executed yet
2344                    _ => None,
2345                }
2346            }
2347        }
2348    }
2349
2350    pub fn is_timer_block(&self, block_hash: &H256) -> Option<bool> {
2351        self.hash_to_arena_indices
2352            .get(block_hash)
2353            .and_then(|index| Some(self.arena[*index].is_timer))
2354    }
2355
2356    pub fn is_adaptive(&self, block_hash: &H256) -> Option<bool> {
2357        self.hash_to_arena_indices
2358            .get(block_hash)
2359            .and_then(|index| Some(self.arena[*index].adaptive))
2360    }
2361
2362    pub fn is_partial_invalid(&self, block_hash: &H256) -> Option<bool> {
2363        self.hash_to_arena_indices
2364            .get(block_hash)
2365            .and_then(|index| Some(self.arena[*index].data.partial_invalid))
2366    }
2367
2368    pub fn is_pending(&self, block_hash: &H256) -> Option<bool> {
2369        self.hash_to_arena_indices
2370            .get(block_hash)
2371            .and_then(|index| Some(self.arena[*index].data.pending))
2372    }
2373
2374    pub fn check_block_pivot_assumption(
2375        &self, pivot_hash: &H256, epoch: u64,
2376    ) -> Result<(), ProviderBlockError> {
2377        let last_number = self.best_epoch_number();
2378        let hash = self.get_pivot_hash_from_epoch_number(epoch)?;
2379        if epoch > last_number || hash != *pivot_hash {
2380            return Err("Error: pivot chain assumption failed".into());
2381        }
2382        Ok(())
2383    }
2384
2385    /// Compute the block weight following the GHAST algorithm:
2386    /// If a block is not adaptive, the weight is its difficulty
2387    /// If a block is adaptive, then for the heavy blocks, it equals to
2388    /// the heavy block ratio times the difficulty. Otherwise, it is zero.
2389    fn block_weight(&self, me: usize) -> i128 {
2390        if !self.arena[me].data.activated || self.arena[me].era_block == NULL {
2391            return 0 as i128;
2392        }
2393        let is_heavy = self.arena[me].is_heavy;
2394        let is_adaptive = self.arena[me].adaptive;
2395        if is_adaptive {
2396            if is_heavy {
2397                self.inner_conf.heavy_block_difficulty_ratio as i128
2398                    * i128::try_from(self.arena[me].difficulty.low_u128())
2399                        .unwrap()
2400            } else {
2401                0 as i128
2402            }
2403        } else {
2404            i128::try_from(self.arena[me].difficulty.low_u128()).unwrap()
2405        }
2406    }
2407
2408    /// ```text
2409    ///                   _________ 5 __________
2410    ///                   |                    |
2411    ///  state_valid:           t    f    f    f
2412    /// <----------------[Bl]-[Bk]-[Bj]-[Bi]-[Bp]-[Bm]----
2413    ///   [Dj]-[Di]-[Dp]-[Dm]
2414    ///
2415    /// [Bp] is the parent of [Bm]
2416    /// [Dm] is the deferred state root of [Bm]. This is a rough definition
2417    /// representing deferred state/receipt/blame root
2418    /// i([Bm]) is the arena index of [Bm]
2419    /// e([Bm]) is the execution commitment of [Bm]
2420    /// [Dm] can be generated from e([Bl])
2421    ///
2422    /// Param:
2423    ///   i([Bp]),
2424    ///   e([Bl]),
2425    /// Return:
2426    ///   The blame and the deferred blame roots information that should be
2427    ///   contained in header of [Bm].
2428    ///   (blame,
2429    ///    deferred_blame_state_root,
2430    ///    deferred_blame_receipt_root,
2431    ///    deferred_blame_bloom_root)
2432    ///
2433    /// Assumption:
2434    ///   * [Bm] is a pivot block on current pivot chain.
2435    ///   This assumption is derived from the following cases:
2436    ///   1. This function may be triggered when evaluating the reward for the
2437    ///      blocks in epoch of [Bm]. This relies on the state_valid value of
2438    ///      [Bm]. In other words, in this case, this function is triggered
2439    ///      when computing the state_valid value of [Bm].
2440    ///   2. This function may be triggered when mining [Bm].
2441    ///
2442    ///   * The execution commitments of blocks needed do exist.
2443    ///
2444    ///   * [Bm] is in stable era.
2445    ///   This assumption is derived from the following cases:
2446    ///   1. In normal run, before updating stable era genesis, we always
2447    ///      make state_valid of all the pivot blocks before the new
2448    ///      stable era genesis computed.
2449    ///   2. The recover phase (including both archive and full node)
2450    ///      prepares the graph state to the normal run state before
2451    ///      calling this function.
2452    ///
2453    /// This function searches backward for all the blocks whose
2454    /// state_valid are false, starting from [Bp]. The number of found
2455    /// blocks is the 'blame' of [Bm]. if 'blame' == 0, the deferred blame
2456    /// root information of [Bm] is simply [Dm], otherwise, it is computed
2457    /// from the vector of deferred state roots of these found blocks
2458    /// together with [Bm], e.g., in the above example, 'blame'==3, and
2459    /// the vector of deferred roots of these blocks is
2460    /// ([Dm], [Dp], [Di], [Dj]), therefore, the deferred blame root of
2461    /// [Bm] is keccak([Dm], keccak([Dp], keccak([Di], [Dj]))).
2462    /// The reason that we use this recursive way to compute deferred
2463    /// blame root is to be able to leverage the computed value of previous
2464    /// block. For example, the deferred blame root of [Bm] is exactly the
2465    /// keccak of [Dm] and the deferred blame root of [Bp].
2466    /// ```
2467    fn compute_blame_and_state_with_execution_result(
2468        &mut self, parent: usize, state_root_hash: H256,
2469        receipts_root_hash: H256, logs_bloom_hash: H256,
2470    ) -> Result<StateBlameInfo, String> {
2471        let mut cur = parent;
2472        let mut blame_cnt: u32 = 0;
2473        let mut state_blame_vec = Vec::new();
2474        let mut receipt_blame_vec = Vec::new();
2475        let mut bloom_blame_vec = Vec::new();
2476        let mut blame_info_to_fill = Vec::new();
2477        state_blame_vec.push(state_root_hash);
2478        receipt_blame_vec.push(receipts_root_hash);
2479        bloom_blame_vec.push(logs_bloom_hash);
2480        loop {
2481            if self.arena[cur]
2482                .data
2483                .state_valid
2484                .expect("computed by the caller")
2485            {
2486                // The state_valid for this block and blocks before have been
2487                // computed. In this case, we need to fill the last one with
2488                // blame 0.
2489                if let Some(last_blame_info) = blame_info_to_fill.pop() {
2490                    self.arena[last_blame_info].data.blame_info =
2491                        Some(StateBlameInfo {
2492                            blame: 0,
2493                            state_vec_root: state_blame_vec
2494                                .last()
2495                                .unwrap()
2496                                .clone(),
2497                            receipts_vec_root: receipt_blame_vec
2498                                .last()
2499                                .unwrap()
2500                                .clone(),
2501                            logs_bloom_vec_root: bloom_blame_vec
2502                                .last()
2503                                .unwrap()
2504                                .clone(),
2505                        });
2506                    blame_cnt = 1;
2507                }
2508                break;
2509            }
2510
2511            debug!("compute_blame_and_state_with_execution_result: cur={} height={}", cur, self.arena[cur].height);
2512            // Note that this function should never return errors for pivot
2513            // chain blocks, because our assumption is that stable
2514            // blocks will always already have `state_valid` and
2515            // `blame_info` computed.
2516            let deferred_arena_index =
2517                self.get_deferred_state_arena_index(cur)?;
2518            let deferred_block_commitment = self
2519                .data_man
2520                .get_epoch_execution_commitment(
2521                    &self.arena[deferred_arena_index].hash,
2522                )
2523                .ok_or("State block commitment missing")?;
2524            // We can retrieve the already filled info and maybe stop here
2525            if let Some(blame_info) = self.arena[cur].data.blame_info {
2526                blame_cnt = blame_info.blame + 1;
2527                state_blame_vec.push(blame_info.state_vec_root);
2528                receipt_blame_vec.push(blame_info.receipts_vec_root);
2529                bloom_blame_vec.push(blame_info.logs_bloom_vec_root);
2530                break;
2531            }
2532            blame_info_to_fill.push(cur);
2533            if self.arena[cur].height == self.cur_era_genesis_height {
2534                // Note that this should never happen for pivot chain blocks,
2535                // because we guarantee that the blame vector at
2536                // the stable genesis will not stretch beyond the checkpoint
2537                // genesis. So the blame vector should stop at
2538                // some point unless the stable genesis is reverted.
2539                return Err(
2540                    "Failed to compute blame and state due to out of era. The blockchain data is probably corrupted."
2541                        .to_owned(),
2542                );
2543            }
2544            state_blame_vec.push(
2545                deferred_block_commitment
2546                    .state_root_with_aux_info
2547                    .aux_info
2548                    .state_root_hash,
2549            );
2550            receipt_blame_vec
2551                .push(deferred_block_commitment.receipts_root.clone());
2552            bloom_blame_vec
2553                .push(deferred_block_commitment.logs_bloom_hash.clone());
2554            cur = self.arena[cur].parent;
2555        }
2556        let blame = blame_cnt + blame_info_to_fill.len() as u32;
2557
2558        // To this point:
2559        //                   _________ 5 __________
2560        //                   |                    |
2561        //  state_valid:           t    f    f    f
2562        // <----------------[Bl]-[Bk]-[Bj]-[Bi]-[Bp]-[Bm]----
2563        //   [Dj]-[Di]-[Dp]-[Dm]
2564        //                                   1    0
2565        //                                   |----|   blame_info_to_fill
2566        //    3    2    1    0
2567        //    |--------------|  state_blame_vec
2568        if blame > 0 {
2569            let mut accumulated_state_root =
2570                state_blame_vec.last().unwrap().clone();
2571            let mut accumulated_receipts_root =
2572                receipt_blame_vec.last().unwrap().clone();
2573            let mut accumulated_logs_bloom_root =
2574                bloom_blame_vec.last().unwrap().clone();
2575            for i in (0..blame_info_to_fill.len()).rev() {
2576                accumulated_state_root =
2577                    BlockHeaderBuilder::compute_blame_state_root_incremental(
2578                        state_blame_vec[i + 1],
2579                        accumulated_state_root,
2580                    );
2581                accumulated_receipts_root =
2582                    BlockHeaderBuilder::compute_blame_state_root_incremental(
2583                        receipt_blame_vec[i + 1],
2584                        accumulated_receipts_root,
2585                    );
2586                accumulated_logs_bloom_root =
2587                    BlockHeaderBuilder::compute_blame_state_root_incremental(
2588                        bloom_blame_vec[i + 1],
2589                        accumulated_logs_bloom_root,
2590                    );
2591                self.arena[blame_info_to_fill[i]].data.blame_info =
2592                    Some(StateBlameInfo {
2593                        blame: blame_cnt,
2594                        state_vec_root: accumulated_state_root,
2595                        receipts_vec_root: accumulated_receipts_root,
2596                        logs_bloom_vec_root: accumulated_logs_bloom_root,
2597                    });
2598                blame_cnt += 1;
2599            }
2600            let state_vec_root =
2601                BlockHeaderBuilder::compute_blame_state_root_incremental(
2602                    state_blame_vec[0],
2603                    accumulated_state_root,
2604                );
2605            let receipts_vec_root =
2606                BlockHeaderBuilder::compute_blame_state_root_incremental(
2607                    receipt_blame_vec[0],
2608                    accumulated_receipts_root,
2609                );
2610            let logs_bloom_vec_root =
2611                BlockHeaderBuilder::compute_blame_state_root_incremental(
2612                    bloom_blame_vec[0],
2613                    accumulated_logs_bloom_root,
2614                );
2615            Ok(StateBlameInfo {
2616                blame,
2617                state_vec_root,
2618                receipts_vec_root,
2619                logs_bloom_vec_root,
2620            })
2621        } else {
2622            Ok(StateBlameInfo {
2623                blame: 0,
2624                state_vec_root: state_blame_vec.pop().unwrap(),
2625                receipts_vec_root: receipt_blame_vec.pop().unwrap(),
2626                logs_bloom_vec_root: bloom_blame_vec.pop().unwrap(),
2627            })
2628        }
2629    }
2630
2631    /// Compute `state_valid` and `blame_info` for `me`.
2632    /// Assumption:
2633    ///   1. The precedents of `me` have computed state_valid
2634    ///   2. The execution_commitment for deferred state block of `me` exist.
2635    ///   3. `me` is in stable era.
2636    fn compute_state_valid_and_blame_info_for_block(
2637        &mut self, me: usize, executor: &ConsensusExecutor,
2638    ) -> Result<(), String> {
2639        let block_height = self.arena[me].height;
2640        let block_hash = self.arena[me].hash;
2641        debug!("compute_state_valid: me={} height={}", me, block_height);
2642        let deferred_state_arena_index =
2643            self.get_deferred_state_arena_index(me)?;
2644        let exec_commitment = self
2645            .data_man
2646            .get_epoch_execution_commitment(
2647                &self.arena[deferred_state_arena_index].hash,
2648            )
2649            .expect("Commitment exist");
2650        let parent = self.arena[me].parent;
2651        let original_deferred_state_root =
2652            exec_commitment.state_root_with_aux_info.clone();
2653        let original_deferred_receipt_root =
2654            exec_commitment.receipts_root.clone();
2655        let original_deferred_logs_bloom_hash =
2656            exec_commitment.logs_bloom_hash.clone();
2657
2658        let state_blame_info = self
2659            .compute_blame_and_state_with_execution_result(
2660                parent,
2661                original_deferred_state_root
2662                    .aux_info
2663                    .state_root_hash
2664                    .clone(),
2665                original_deferred_receipt_root.clone(),
2666                original_deferred_logs_bloom_hash.clone(),
2667            )?;
2668        let block_header = self
2669            .data_man
2670            .block_header_by_hash(&self.arena[me].hash)
2671            .unwrap();
2672        let state_valid = block_header.blame() == state_blame_info.blame
2673            && *block_header.deferred_state_root()
2674                == state_blame_info.state_vec_root
2675            && *block_header.deferred_receipts_root()
2676                == state_blame_info.receipts_vec_root
2677            && *block_header.deferred_logs_bloom_hash()
2678                == state_blame_info.logs_bloom_vec_root;
2679
2680        let mut debug_recompute = false;
2681        if state_valid {
2682            debug!(
2683                "compute_state_valid_for_block(): Block {} state/blame is valid.",
2684                block_hash,
2685            );
2686        } else {
2687            warn!(
2688                "compute_state_valid_for_block(): Block {:?} state/blame is invalid! \
2689                header blame {:?}, our blame {:?}, header state_root {:?}, \
2690                our state root {:?}, header receipt_root {:?}, our receipt root {:?}, \
2691                header logs_bloom_hash {:?}, our logs_bloom_hash {:?}.",
2692                block_hash, block_header.blame(), state_blame_info.blame,
2693                block_header.deferred_state_root(), state_blame_info.state_vec_root,
2694                block_header.deferred_receipts_root(), state_blame_info.receipts_vec_root,
2695                block_header.deferred_logs_bloom_hash(), state_blame_info.logs_bloom_vec_root,
2696            );
2697            INVALID_BLAME_OR_STATE_ROOT_COUNTER.inc(1);
2698
2699            if self.inner_conf.debug_dump_dir_invalid_state_root.is_some() {
2700                debug_recompute = true;
2701            }
2702        }
2703        if let Some(debug_epoch) =
2704            &self.inner_conf.debug_invalid_state_root_epoch
2705        {
2706            if block_hash.eq(debug_epoch) {
2707                debug_recompute = true;
2708            }
2709        }
2710        if debug_recompute {
2711            if let Ok(epoch_arena_index) =
2712                self.get_deferred_state_arena_index(me)
2713            {
2714                let state_availability_lower_bound = self
2715                    .data_man
2716                    .state_availability_boundary
2717                    .read()
2718                    .lower_bound;
2719                // Can not run debug_recompute when the parent state is not
2720                // available.
2721                if state_availability_lower_bound < block_height {
2722                    // Maybe this block isn't valid, when our node is correct.
2723                    log_invalid_state_root(
2724                        epoch_arena_index,
2725                        self,
2726                        executor,
2727                        block_hash,
2728                        block_height,
2729                        &original_deferred_state_root,
2730                    )
2731                    .ok();
2732
2733                    // Maybe this block is valid, but we are not. So we find the
2734                    // first state we think is correct however this block things
2735                    // wrong.
2736                    let header_blame = block_header.blame() as u64;
2737                    let mut block_arena_index = self.arena[me].parent;
2738                    let mut earliest_mismatch_arena_index = me;
2739                    for i in 1..header_blame {
2740                        if block_height - i <= state_availability_lower_bound {
2741                            break;
2742                        }
2743                        if self.arena[block_arena_index].data.state_valid
2744                            != Some(false)
2745                        {
2746                            earliest_mismatch_arena_index = block_arena_index;
2747                        }
2748                        block_arena_index =
2749                            self.arena[block_arena_index].parent;
2750                    }
2751                    if earliest_mismatch_arena_index != me {
2752                        if let Ok(state_epoch_arena_index) = self
2753                            .get_deferred_state_arena_index(
2754                                earliest_mismatch_arena_index,
2755                            )
2756                        {
2757                            let block_hash =
2758                                self.arena[earliest_mismatch_arena_index].hash;
2759                            let block_height = self.arena
2760                                [earliest_mismatch_arena_index]
2761                                .height;
2762                            let state_root = self
2763                                .data_man
2764                                .get_epoch_execution_commitment(
2765                                    &self.arena[state_epoch_arena_index].hash,
2766                                )
2767                                .expect("Commitment exist")
2768                                .state_root_with_aux_info
2769                                .clone();
2770                            log_invalid_state_root(
2771                                state_epoch_arena_index,
2772                                self,
2773                                executor,
2774                                block_hash,
2775                                block_height,
2776                                &state_root,
2777                            )
2778                            .ok();
2779                        }
2780                    }
2781                }
2782            }
2783        }
2784
2785        self.arena[me].data.state_valid = Some(state_valid);
2786        if !state_valid {
2787            self.arena[me].data.blame_info = Some(state_blame_info);
2788        }
2789
2790        if self.inner_conf.enable_state_expose {
2791            STATE_EXPOSER
2792                .consensus_graph
2793                .lock()
2794                .block_execution_state_vec
2795                .push(ConsensusGraphBlockExecutionState {
2796                    block_hash,
2797                    deferred_state_root: original_deferred_state_root
2798                        .aux_info
2799                        .state_root_hash,
2800                    deferred_receipt_root: original_deferred_receipt_root,
2801                    deferred_logs_bloom_hash: original_deferred_logs_bloom_hash,
2802                    state_valid: self.arena[me]
2803                        .data
2804                        .state_valid
2805                        .unwrap_or(true),
2806                })
2807        }
2808
2809        Ok(())
2810    }
2811
2812    fn compute_vote_valid_for_pivot_block(
2813        &mut self, me: usize, pivot_arena_index: usize,
2814    ) -> bool {
2815        let lca = self.lca(me, pivot_arena_index);
2816        let lca_height = self.arena[lca].height;
2817        debug!(
2818            "compute_vote_valid_for_pivot_block: lca={}, lca_height={}",
2819            lca, lca_height
2820        );
2821        let mut stack = Vec::new();
2822        stack.push((0, me, 0));
2823        while !stack.is_empty() {
2824            let (stage, index, a) = stack.pop().unwrap();
2825            if stage == 0 {
2826                if self.arena[index].data.vote_valid_lca_height != lca_height {
2827                    let header = self
2828                        .data_man
2829                        .block_header_by_hash(&self.arena[index].hash)
2830                        .unwrap();
2831                    let blame = header.blame();
2832                    if self.arena[index].height > lca_height + 1 + blame as u64
2833                    {
2834                        let ancestor = self.ancestor_at(
2835                            index,
2836                            self.arena[index].height - blame as u64 - 1,
2837                        );
2838                        stack.push((1, index, ancestor));
2839                        stack.push((0, ancestor, 0));
2840                    } else {
2841                        // We need to make sure the ancestor at height
2842                        // self.arena[index].height - blame - 1 is state valid,
2843                        // and the remainings are not
2844                        let vote_valid = match Self::blame_covered_start_height(
2845                            self.arena[index].height,
2846                            blame,
2847                        ) {
2848                            Some(start_height) => {
2849                                let mut cur_height = lca_height;
2850                                let mut cur = lca;
2851                                let mut vote_valid = true;
2852                                while cur_height > start_height {
2853                                    if self.arena[cur].data.state_valid
2854                                        .expect("state_valid for me has been computed in \
2855                                        wait_and_compute_state_valid_locked by the caller, \
2856                                        so the precedents should have state_valid") {
2857                                        vote_valid = false;
2858                                        break;
2859                                    }
2860                                    cur_height -= 1;
2861                                    cur = self.arena[cur].parent;
2862                                }
2863                                vote_valid
2864                                    && self.arena[cur].data.state_valid.expect(
2865                                        "state_valid for me has been computed in \
2866                                    wait_and_compute_state_valid_locked by the caller, \
2867                                    so the precedents should have state_valid",
2868                                    )
2869                            }
2870                            None => false,
2871                        };
2872                        self.arena[index].data.vote_valid_lca_height =
2873                            lca_height;
2874                        self.arena[index].data.vote_valid = vote_valid;
2875                    }
2876                }
2877            } else {
2878                self.arena[index].data.vote_valid_lca_height = lca_height;
2879                self.arena[index].data.vote_valid =
2880                    self.arena[a].data.vote_valid;
2881            }
2882        }
2883        self.arena[me].data.vote_valid
2884    }
2885
2886    /// Compute the total weight in the epoch represented by the block of
2887    /// my_hash.
2888    fn total_weight_in_own_epoch(
2889        &self, blockset_in_own_epoch: &Vec<usize>, genesis: usize,
2890    ) -> i128 {
2891        let gen_arena_index = if genesis != NULL {
2892            genesis
2893        } else {
2894            self.cur_era_genesis_block_arena_index
2895        };
2896        let gen_height = self.arena[gen_arena_index].height;
2897        let mut total_weight = 0 as i128;
2898        for index in blockset_in_own_epoch.iter() {
2899            if gen_arena_index != self.cur_era_genesis_block_arena_index {
2900                let height = self.arena[*index].height;
2901                if height < gen_height {
2902                    continue;
2903                }
2904                let era_arena_index = self.ancestor_at(*index, gen_height);
2905                if gen_arena_index != era_arena_index {
2906                    continue;
2907                }
2908            }
2909            total_weight += self.block_weight(*index);
2910        }
2911        total_weight
2912    }
2913
2914    /// Recompute metadata associated information on pivot chain changes
2915    fn recompute_metadata(
2916        &mut self, start_at: u64, mut to_update: HashSet<usize>,
2917    ) {
2918        self.pivot_chain_metadata
2919            .resize_with(self.pivot_chain.len(), Default::default);
2920        let pivot_height = self.get_pivot_height();
2921        for i in start_at..pivot_height {
2922            let me = self.get_pivot_block_arena_index(i);
2923            self.arena[me].data.last_pivot_in_past = i;
2924            let i_pivot_index = self.height_to_pivot_index(i);
2925            self.pivot_chain_metadata[i_pivot_index]
2926                .last_pivot_in_past_blocks
2927                .clear();
2928            self.pivot_chain_metadata[i_pivot_index]
2929                .last_pivot_in_past_blocks
2930                .insert(me);
2931            self.pivot_chain_metadata[i_pivot_index].past_weight =
2932                if i_pivot_index > 0 {
2933                    let blockset = self
2934                        .exchange_or_compute_blockset_in_own_view_of_epoch(
2935                            me, None,
2936                        );
2937                    let blockset_weight = self.total_weight_in_own_epoch(
2938                        &blockset,
2939                        self.cur_era_genesis_block_arena_index,
2940                    );
2941                    self.exchange_or_compute_blockset_in_own_view_of_epoch(
2942                        me,
2943                        Some(blockset),
2944                    );
2945                    self.pivot_chain_metadata[i_pivot_index - 1].past_weight
2946                        + blockset_weight
2947                        + self.block_weight(me)
2948                } else {
2949                    self.block_weight(me)
2950                };
2951            to_update.remove(&me);
2952        }
2953        let mut stack = Vec::new();
2954        let to_visit = to_update.clone();
2955        for i in &to_update {
2956            stack.push((0, *i));
2957        }
2958        while !stack.is_empty() {
2959            let (stage, me) = stack.pop().unwrap();
2960            if !to_visit.contains(&me) {
2961                continue;
2962            }
2963            let parent = self.arena[me].parent;
2964            if stage == 0 {
2965                if to_update.contains(&me) {
2966                    to_update.remove(&me);
2967                    stack.push((1, me));
2968                    stack.push((0, parent));
2969                    for referee in &self.arena[me].referees {
2970                        stack.push((0, *referee));
2971                    }
2972                }
2973            } else if stage == 1 && me != self.cur_era_genesis_block_arena_index
2974            {
2975                let mut last_pivot = if parent == NULL {
2976                    0
2977                } else {
2978                    self.arena[parent].data.last_pivot_in_past
2979                };
2980                for referee in &self.arena[me].referees {
2981                    let x = self.arena[*referee].data.last_pivot_in_past;
2982                    last_pivot = max(last_pivot, x);
2983                }
2984                self.arena[me].data.last_pivot_in_past = last_pivot;
2985                let last_pivot_index = self.height_to_pivot_index(last_pivot);
2986                self.pivot_chain_metadata[last_pivot_index]
2987                    .last_pivot_in_past_blocks
2988                    .insert(me);
2989            }
2990        }
2991    }
2992
2993    fn get_timer_chain_index(&self, me: usize) -> usize {
2994        if !self.arena[me].is_timer || self.arena[me].data.partial_invalid {
2995            return NULL;
2996        }
2997        if self.arena[me].data.ledger_view_timer_chain_height
2998            < self.cur_era_genesis_timer_chain_height
2999        {
3000            // This is only possible if `me` is in the anticone of
3001            // `cur_era_genesis`.
3002            return NULL;
3003        }
3004        let timer_chain_index =
3005            (self.arena[me].data.ledger_view_timer_chain_height
3006                - self.cur_era_genesis_timer_chain_height) as usize;
3007        if self.timer_chain.len() > timer_chain_index
3008            && self.timer_chain[timer_chain_index] == me
3009        {
3010            timer_chain_index
3011        } else {
3012            NULL
3013        }
3014    }
3015
3016    fn compute_timer_chain_past_view_info(
3017        &self, parent: usize, referees: &Vec<usize>,
3018    ) -> (i128, usize) {
3019        let mut timer_longest_difficulty = 0;
3020        let mut longest_referee = parent;
3021        if parent != NULL {
3022            timer_longest_difficulty =
3023                self.arena[parent].data.past_view_timer_longest_difficulty
3024                    + self.get_timer_difficulty(parent);
3025        }
3026        for referee in referees {
3027            let timer_difficulty =
3028                self.arena[*referee].data.past_view_timer_longest_difficulty
3029                    + self.get_timer_difficulty(*referee);
3030            if longest_referee == NULL
3031                || ConsensusGraphInner::is_heavier(
3032                    (timer_difficulty, &self.arena[*referee].hash),
3033                    (
3034                        timer_longest_difficulty,
3035                        &self.arena[longest_referee].hash,
3036                    ),
3037                )
3038            {
3039                timer_longest_difficulty = timer_difficulty;
3040                longest_referee = *referee;
3041            }
3042        }
3043        let last_timer_block_arena_index = if longest_referee == NULL
3044            || self.arena[longest_referee].is_timer
3045                && !self.arena[longest_referee].data.partial_invalid
3046        {
3047            longest_referee
3048        } else {
3049            self.arena[longest_referee]
3050                .data
3051                .past_view_last_timer_block_arena_index
3052        };
3053        (timer_longest_difficulty, last_timer_block_arena_index)
3054    }
3055
3056    fn compute_timer_chain_tuple(
3057        &self, parent: usize, referees: &Vec<usize>,
3058        anticone_opt: Option<&BitSet>,
3059    ) -> (u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>) {
3060        let empty_set = BitSet::new();
3061        let anticone = if let Some(a) = anticone_opt {
3062            a
3063        } else {
3064            &empty_set
3065        };
3066        let mut tmp_chain = Vec::new();
3067        let mut tmp_chain_set = HashSet::new();
3068        let (_, past_view_last_timer_block_arena_index) =
3069            self.compute_timer_chain_past_view_info(parent, referees);
3070        let mut i = past_view_last_timer_block_arena_index;
3071        while i != NULL && self.get_timer_chain_index(i) == NULL {
3072            tmp_chain.push(i);
3073            tmp_chain_set.insert(i);
3074            i = self.arena[i].data.past_view_last_timer_block_arena_index;
3075        }
3076        tmp_chain.reverse();
3077        let fork_at;
3078        let fork_at_index;
3079        if i != NULL {
3080            fork_at = self.arena[i].data.ledger_view_timer_chain_height + 1;
3081            assert!(fork_at >= self.cur_era_genesis_timer_chain_height);
3082            fork_at_index =
3083                (fork_at - self.cur_era_genesis_timer_chain_height) as usize;
3084        } else {
3085            fork_at = self.cur_era_genesis_timer_chain_height;
3086            fork_at_index = 0;
3087        }
3088
3089        let mut res = HashMap::new();
3090        if fork_at_index < self.timer_chain.len() {
3091            debug!("New block parent = {} referees = {:?} not extending timer chain (len = {}), fork at timer chain height {}, timer chain index {}", parent, referees, self.timer_chain.len(), fork_at, fork_at_index);
3092            // Now we need to update the timer_chain_height field of the
3093            // remaining blocks with topological sort
3094            let start_point = if i == NULL {
3095                self.cur_era_genesis_block_arena_index
3096            } else {
3097                self.timer_chain[fork_at_index - 1]
3098            };
3099            let mut start_set = HashSet::new();
3100            start_set.insert(start_point);
3101            let visited: BitSet = get_future(
3102                start_set,
3103                // TODO: This conversion overhead can be avoided
3104                |i| self.successor_edges(i as usize),
3105                |i| anticone.contains(i as u32),
3106            );
3107            let visited_in_order: Vec<usize> = topological_sort(
3108                visited,
3109                |i| {
3110                    self.predecessor_edges(i as usize)
3111                        .into_iter()
3112                        .map(|i| i as u32)
3113                        .collect()
3114                },
3115                |_| true,
3116            );
3117            for x in visited_in_order {
3118                let x = x as usize;
3119                let mut timer_chain_height = 0;
3120                for pred in &self.predecessor_edges(x) {
3121                    let mut height = if let Some(v) = res.get(pred) {
3122                        *v
3123                    } else {
3124                        self.arena[*pred].data.ledger_view_timer_chain_height
3125                    };
3126                    if tmp_chain_set.contains(pred)
3127                        || self.get_timer_chain_index(*pred) < fork_at_index
3128                    {
3129                        height += 1;
3130                    }
3131                    if height > timer_chain_height {
3132                        timer_chain_height = height;
3133                    }
3134                }
3135                res.insert(x, timer_chain_height);
3136            }
3137        }
3138
3139        // We compute the accumulative lca list after this
3140        let mut tmp_lca = Vec::new();
3141        if tmp_chain.len() > self.timer_chain.len() - fork_at_index
3142            && self.timer_chain.len() - fork_at_index
3143                < self.inner_conf.timer_chain_beta as usize
3144        {
3145            let mut last_lca = match self.timer_chain_accumulative_lca.last() {
3146                Some(last_lca) => *last_lca,
3147                None => self.cur_era_genesis_block_arena_index,
3148            };
3149            let s = max(
3150                self.timer_chain.len(),
3151                self.inner_conf.timer_chain_beta as usize,
3152            );
3153            let e =
3154                min(tmp_chain.len(), self.inner_conf.timer_chain_beta as usize);
3155            for i in s..(fork_at_index + e) {
3156                // `end` is the timer chain index of the end of
3157                // `timer_chain_beta` consecutive blocks which
3158                // we will compute accumulative lca.
3159                let end = i - self.inner_conf.timer_chain_beta as usize;
3160                if end < self.inner_conf.timer_chain_beta as usize {
3161                    tmp_lca.push(self.cur_era_genesis_block_arena_index);
3162                    continue;
3163                }
3164                let mut lca = self.timer_chain[end];
3165                for j in
3166                    (end - self.inner_conf.timer_chain_beta as usize + 1)..end
3167                {
3168                    // Note that we may have timer_chain blocks that are
3169                    // outside the genesis tree temporarily.
3170                    // Therefore we have to deal with the case that lca
3171                    // becomes NULL
3172                    if lca == NULL {
3173                        break;
3174                    }
3175                    lca = self.lca(lca, self.timer_chain[j]);
3176                }
3177                // Note that we have the assumption that the force
3178                // confirmation point will always move
3179                // along parental edges, i.e., it is not possible for the
3180                // point to move to a sibling tree. This
3181                // assumption is true if the timer_chain_beta
3182                // and the timer_chain_difficulty_ratio are set to large
3183                // enough values.
3184                //
3185                // It is therefore safe here to use the height to compare.
3186                if lca != NULL
3187                    && self.arena[last_lca].height < self.arena[lca].height
3188                {
3189                    last_lca = lca;
3190                }
3191                tmp_lca.push(last_lca);
3192            }
3193        }
3194        if tmp_chain.len() > self.inner_conf.timer_chain_beta as usize {
3195            let mut last_lca = if let Some(lca) = tmp_lca.last() {
3196                *lca
3197            } else if fork_at_index == 0 {
3198                self.cur_era_genesis_block_arena_index
3199            } else {
3200                // This is guaranteed to be inside the bound because it
3201                // means that the lca computation on old nodes do not need to
3202                // be extended. The gap between the fork_at_index and the
3203                // self.timer_chain.len() is greater than or equal to
3204                // timer_chain_beta.
3205                self.timer_chain_accumulative_lca[fork_at_index - 1]
3206            };
3207            for i in 0..(tmp_chain.len()
3208                - (self.inner_conf.timer_chain_beta as usize))
3209            {
3210                if fork_at_index + i + 1
3211                    < self.inner_conf.timer_chain_beta as usize
3212                {
3213                    tmp_lca.push(self.cur_era_genesis_block_arena_index)
3214                } else {
3215                    let mut lca = tmp_chain[i];
3216                    // We only go over timer_chain_beta elements to compute lca
3217                    let s = if i < self.inner_conf.timer_chain_beta as usize - 1
3218                    {
3219                        0
3220                    } else {
3221                        i + 1 - self.inner_conf.timer_chain_beta as usize
3222                    };
3223                    for j in s..i {
3224                        // Note that we may have timer_chain blocks that are
3225                        // outside the genesis tree temporarily.
3226                        // Therefore we have to deal with the case that lca
3227                        // becomes NULL
3228                        if lca == NULL {
3229                            break;
3230                        }
3231                        lca = self.lca(lca, tmp_chain[j]);
3232                    }
3233                    for j in (fork_at_index + i + 1
3234                        - self.inner_conf.timer_chain_beta as usize)
3235                        ..fork_at_index
3236                    {
3237                        // Note that we may have timer_chain blocks that are
3238                        // outside the genesis tree temporarily.
3239                        // Therefore we have to deal with the case that lca
3240                        // becomes NULL
3241                        if lca == NULL {
3242                            break;
3243                        }
3244                        lca = self.lca(lca, self.timer_chain[j]);
3245                    }
3246                    // Note that we have the assumption that the force
3247                    // confirmation point will always move
3248                    // along parental edges, i.e., it is not possible for the
3249                    // point to move to a sibling tree. This
3250                    // assumption is true if the timer_chain_beta
3251                    // and the timer_chain_difficulty_ratio are set to large
3252                    // enough values.
3253                    //
3254                    // It is therefore safe here to use the height to compare.
3255                    if lca != NULL
3256                        && self.arena[last_lca].height < self.arena[lca].height
3257                    {
3258                        last_lca = lca;
3259                    }
3260                    tmp_lca.push(last_lca);
3261                }
3262            }
3263        }
3264
3265        (fork_at, res, tmp_lca, tmp_chain)
3266    }
3267
3268    fn update_timer_chain(&mut self, me: usize) {
3269        let (fork_at, res, extra_lca, tmp_chain) = self
3270            .compute_timer_chain_tuple(
3271                self.arena[me].parent,
3272                &self.arena[me].referees,
3273                None,
3274            );
3275
3276        let fork_at_index =
3277            (fork_at - self.cur_era_genesis_timer_chain_height) as usize;
3278        self.timer_chain.resize(fork_at_index + tmp_chain.len(), 0);
3279        let new_chain_lca_size = if self.timer_chain.len()
3280            > self.inner_conf.timer_chain_beta as usize
3281        {
3282            self.timer_chain.len() - self.inner_conf.timer_chain_beta as usize
3283        } else {
3284            0
3285        };
3286        self.timer_chain_accumulative_lca
3287            .resize(new_chain_lca_size, 0);
3288        for i in 0..tmp_chain.len() {
3289            self.timer_chain[fork_at_index + i] = tmp_chain[i];
3290        }
3291        for i in 0..extra_lca.len() {
3292            self.timer_chain_accumulative_lca
3293                [new_chain_lca_size - extra_lca.len() + i] = extra_lca[i];
3294        }
3295        // In case of extending the key chain, me may not be inside the result
3296        // map and we will set it to the end of the timer chain.
3297        if !res.contains_key(&me) {
3298            assert!(
3299                self.cur_era_genesis_timer_chain_height
3300                    + self.timer_chain.len() as u64
3301                    == fork_at
3302            );
3303            self.arena[me].data.ledger_view_timer_chain_height = fork_at;
3304        }
3305        for (k, v) in res {
3306            self.arena[k].data.ledger_view_timer_chain_height = v;
3307        }
3308        if self.arena[me].is_timer && !self.arena[me].data.partial_invalid {
3309            self.timer_chain.push(me);
3310            if self.timer_chain.len()
3311                >= 2 * self.inner_conf.timer_chain_beta as usize
3312            {
3313                let s = self.timer_chain.len()
3314                    - 2 * self.inner_conf.timer_chain_beta as usize;
3315                let e = self.timer_chain.len()
3316                    - self.inner_conf.timer_chain_beta as usize;
3317                let mut lca = self.timer_chain[e - 1];
3318                for i in s..(e - 1) {
3319                    // Note that we may have timer_chain blocks that are outside
3320                    // the genesis tree temporarily.
3321                    // Therefore we have to deal with the case that lca becomes
3322                    // NULL
3323                    if lca == NULL {
3324                        break;
3325                    }
3326                    lca = self.lca(lca, self.timer_chain[i]);
3327                }
3328                let last_lca =
3329                    if let Some(x) = self.timer_chain_accumulative_lca.last() {
3330                        *x
3331                    } else {
3332                        self.cur_era_genesis_block_arena_index
3333                    };
3334                // Note that we have the assumption that the force confirmation
3335                // point will always move along parental edges,
3336                // i.e., it is not possible for the point
3337                // to move to a sibling tree. This assumption is true if the
3338                // timer_chain_beta
3339                // and the timer_chain_difficulty_ratio are set to large enough
3340                // values.
3341                //
3342                // It is therefore safe here to use the height to compare.
3343                if lca != NULL
3344                    && self.arena[last_lca].height < self.arena[lca].height
3345                {
3346                    self.timer_chain_accumulative_lca.push(lca);
3347                } else {
3348                    self.timer_chain_accumulative_lca.push(last_lca);
3349                }
3350                assert_eq!(
3351                    self.timer_chain_accumulative_lca.len(),
3352                    self.timer_chain.len()
3353                        - self.inner_conf.timer_chain_beta as usize
3354                );
3355            } else if self.timer_chain.len()
3356                > self.inner_conf.timer_chain_beta as usize
3357            {
3358                self.timer_chain_accumulative_lca
3359                    .push(self.cur_era_genesis_block_arena_index);
3360            }
3361        }
3362        debug!(
3363            "Timer chain updated to {:?} accumulated lca {:?}",
3364            self.timer_chain, self.timer_chain_accumulative_lca
3365        );
3366    }
3367
3368    pub fn total_processed_block_count(&self) -> u64 {
3369        self.sequence_number_of_block_entrance
3370    }
3371
3372    pub fn get_trusted_blame_block(
3373        &self, checkpoint_hash: &H256, plus_depth: usize,
3374    ) -> Option<H256> {
3375        let arena_index_opt = self.hash_to_arena_indices.get(checkpoint_hash);
3376        // checkpoint has changed, wait for next checkpoint
3377        if arena_index_opt.is_none() {
3378            debug!(
3379                "get_trusted_blame_block: block {:?} not in consensus",
3380                checkpoint_hash
3381            );
3382            return None;
3383        }
3384        let arena_index = *arena_index_opt.unwrap();
3385        let pivot_index =
3386            self.height_to_pivot_index(self.arena[arena_index].height);
3387        // the given checkpoint hash is invalid
3388        if pivot_index >= self.pivot_chain.len()
3389            || self.pivot_chain[pivot_index] != arena_index
3390        {
3391            debug!(
3392                "get_trusted_blame_block: block {:?} not on pivot chain",
3393                checkpoint_hash
3394            );
3395            return None;
3396        }
3397        self.find_first_index_with_correct_state_of(
3398            pivot_index + plus_depth,
3399            None, /* blame_bound */
3400            0,    /* min_vote_count */
3401        )
3402        .and_then(|index| Some(self.arena[self.pivot_chain[index]].hash))
3403    }
3404
3405    /// Find a trusted blame block for snapshot full sync
3406    pub fn get_trusted_blame_block_for_snapshot(
3407        &self, snapshot_epoch_id: &EpochId,
3408    ) -> Option<H256> {
3409        self.get_trusted_blame_block(
3410            snapshot_epoch_id,
3411            self.data_man.get_snapshot_blame_plus_depth(),
3412        )
3413    }
3414
3415    /// Return the epoch that we are going to sync the state
3416    pub fn get_to_sync_epoch_id(&self) -> EpochId {
3417        let height_to_sync = self.latest_snapshot_height();
3418        // The height_to_sync is within the range of `self.pivit_chain`.
3419        let epoch_to_sync = self.arena
3420            [self.pivot_chain[self.height_to_pivot_index(height_to_sync)]]
3421        .hash;
3422        epoch_to_sync
3423    }
3424
3425    /// FIXME Use snapshot-related information when we can sync snapshot states.
3426    /// Return the latest height that a snapshot should be available.
3427    fn latest_snapshot_height(&self) -> u64 { self.cur_era_stable_height }
3428
3429    fn collect_defer_blocks_missing_execution_commitments(
3430        &self, me: usize,
3431    ) -> Result<Vec<H256>, String> {
3432        let mut cur = self.get_deferred_state_arena_index(me)?;
3433        let mut waiting_blocks = Vec::new();
3434        debug!(
3435            "collect_blocks_missing_execution_commitments: me={}, height={}",
3436            me, self.arena[me].height
3437        );
3438        // FIXME: Same here. Be explicit about whether a checkpoint or a synced
3439        // FIXME: snapshot is requested, and distinguish two cases.
3440        let state_boundary_height =
3441            self.data_man.state_availability_boundary.read().lower_bound;
3442        loop {
3443            let deferred_block_hash = self.arena[cur].hash;
3444
3445            if self
3446                .data_man
3447                .get_epoch_execution_commitment(&deferred_block_hash)
3448                .is_some()
3449                || self.arena[cur].height <= state_boundary_height
3450            {
3451                // This block and the blocks before have been executed or will
3452                // not be executed
3453                break;
3454            }
3455            waiting_blocks.push(deferred_block_hash);
3456            cur = self.arena[cur].parent;
3457        }
3458        waiting_blocks.reverse();
3459        Ok(waiting_blocks)
3460    }
3461
3462    /// Compute missing `state_valid` for `me` and all the precedents.
3463    fn compute_state_valid_and_blame_info(
3464        &mut self, me: usize, executor: &ConsensusExecutor,
3465    ) -> Result<(), String> {
3466        // Collect all precedents whose state_valid is empty, and evaluate them
3467        // in order
3468        let mut blocks_to_compute = Vec::new();
3469        let mut cur = me;
3470        // FIXME: Same here. Be explicit about whether a checkpoint or a synced
3471        // FIXME: snapshot is requested, and distinguish two cases.
3472        //let state_boundary_height =
3473        //    self.data_man.state_availability_boundary.read().lower_bound;
3474        loop {
3475            if self.arena[cur].data.state_valid.is_some() {
3476                break;
3477            }
3478            // FIXME: the assersion isn't on state boundary,
3479            // FIXME: correct the assersion.
3480            // See comments on compute_blame_and_state_with_execution_result()
3481            // for explanation of this assumption.
3482            //assert!(self.arena[cur].height >= state_boundary_height);
3483            blocks_to_compute.push(cur);
3484            cur = self.arena[cur].parent;
3485        }
3486        blocks_to_compute.reverse();
3487
3488        for index in blocks_to_compute {
3489            self.compute_state_valid_and_blame_info_for_block(index, executor)?;
3490        }
3491        Ok(())
3492    }
3493
3494    fn split_root(&mut self, me: usize) {
3495        let parent = self.arena[me].parent;
3496        assert!(parent != NULL);
3497        self.weight_tree.split_root(parent, me);
3498        self.adaptive_tree.split_root(parent, me);
3499        self.arena[me].parent = NULL;
3500    }
3501
3502    pub fn reset_epoch_number_in_epoch(&mut self, pivot_arena_index: usize) {
3503        self.set_epoch_number_in_epoch(pivot_arena_index, NULLU64);
3504    }
3505
3506    fn set_epoch_number_in_epoch(
3507        &mut self, pivot_arena_index: usize, epoch_number: u64,
3508    ) {
3509        assert!(!self.arena[pivot_arena_index].data.blockset_cleared);
3510        let block_set = self.exchange_or_compute_blockset_in_own_view_of_epoch(
3511            pivot_arena_index,
3512            None,
3513        );
3514        for idx in &block_set {
3515            self.arena[*idx].data.epoch_number = epoch_number
3516        }
3517        self.exchange_or_compute_blockset_in_own_view_of_epoch(
3518            pivot_arena_index,
3519            Some(block_set),
3520        );
3521        self.arena[pivot_arena_index].data.epoch_number = epoch_number;
3522    }
3523
3524    fn get_deferred_state_arena_index(
3525        &self, me: usize,
3526    ) -> Result<usize, String> {
3527        let height = self.arena[me].height;
3528        // We are in the very early of the blockchain, here we can just
3529        // return cur_era_genesis_block_arena_index and it will be the true
3530        // genesis.
3531        if height <= DEFERRED_STATE_EPOCH_COUNT {
3532            return Ok(self.cur_era_genesis_block_arena_index);
3533        }
3534        // This is the case we cannot handle, the block is no longer maintained.
3535        if self.cur_era_genesis_height + DEFERRED_STATE_EPOCH_COUNT > height {
3536            return Err(
3537                "Parent is too old for computing the deferred state".to_owned()
3538            );
3539        }
3540        let target_height = height - DEFERRED_STATE_EPOCH_COUNT;
3541        let pivot_idx = self.height_to_pivot_index(height);
3542        // If it is on the pivot chain already, we can avoid O(log n) lca query
3543        if pivot_idx < self.pivot_chain.len()
3544            && self.pivot_chain[pivot_idx] == me
3545        {
3546            return Ok(
3547                self.pivot_chain[self.height_to_pivot_index(target_height)]
3548            );
3549        } else {
3550            return Ok(self.ancestor_at(me, target_height));
3551        }
3552    }
3553
3554    /// Find the first state valid block on the pivot chain after
3555    /// `state_boundary_height` and set `state_valid` of it and its blamed
3556    /// blocks. This block is found according to blame_ratio.
3557    pub fn recover_state_valid(&mut self) {
3558        // FIXME: Same here. Be explicit about whether a checkpoint or a synced
3559        // FIXME: snapshot is requested, and distinguish two cases.
3560        let start_pivot_index =
3561            (self.data_man.state_availability_boundary.read().lower_bound
3562                - self.cur_era_genesis_height) as usize;
3563        if start_pivot_index >= self.pivot_chain.len() {
3564            // TODO: Handle this after refactoring
3565            // `state_availability_boundary`.
3566            return;
3567        }
3568        let start_epoch_hash =
3569            self.arena[self.pivot_chain[start_pivot_index]].hash;
3570        // We will get the first
3571        // pivot block whose `state_valid` is `true` after `start_epoch_hash`
3572        // (include `start_epoch_hash` itself).
3573        let maybe_trusted_blame_block =
3574            self.get_trusted_blame_block(&start_epoch_hash, 0);
3575        debug!("recover_state_valid: checkpoint={:?}, maybe_trusted_blame_block={:?}", start_epoch_hash, maybe_trusted_blame_block);
3576
3577        // Set `state_valid` of `trusted_blame_block` to true,
3578        // and set that of the blocks blamed by it to false
3579        if let Some(trusted_blame_block) = maybe_trusted_blame_block {
3580            let mut cur = *self
3581                .hash_to_arena_indices
3582                .get(&trusted_blame_block)
3583                .unwrap();
3584            while cur != NULL {
3585                let blame = self
3586                    .data_man
3587                    .block_header_by_hash(&self.arena[cur].hash)
3588                    .unwrap()
3589                    .blame();
3590                // `0..=blame` avoids overflowing the u32 counter at the
3591                // attacker-controlled `blame == u32::MAX` (equivalent to the
3592                // former `0..blame + 1`). The loop breaks at `cur == NULL`, so
3593                // the walk is bounded by the parent chain and a large `blame`
3594                // never iterates past genesis.
3595                for i in 0..=blame {
3596                    self.arena[cur].data.state_valid = Some(i == 0);
3597                    trace!(
3598                        "recover_state_valid: index={} hash={} state_valid={}",
3599                        cur,
3600                        self.arena[cur].hash,
3601                        i == 0
3602                    );
3603                    cur = self.arena[cur].parent;
3604                    if cur == NULL {
3605                        break;
3606                    }
3607                }
3608            }
3609        } else {
3610            if start_epoch_hash != self.data_man.true_genesis.hash() {
3611                error!(
3612                    "Fail to recover state_valid: start_epoch_hash={:?}",
3613                    start_epoch_hash
3614                );
3615            }
3616        }
3617    }
3618
3619    pub fn block_node(&self, block_hash: &H256) -> Option<&ConsensusGraphNode> {
3620        self.hash_to_arena_indices
3621            .get(block_hash)
3622            .and_then(|arena_index| self.arena.get(*arena_index))
3623    }
3624
3625    /// Return the list of best terminals when respecting a bound (for
3626    /// referencing edges). We sort the terminals based on its lca so that
3627    /// it will not change the parent selection results if we exclude last
3628    /// few terminals in the sorted order.
3629    pub fn best_terminals(
3630        &mut self, best_index: usize, ref_bound: usize,
3631    ) -> Vec<H256> {
3632        let pastset_tmp;
3633        let pastset = if let Some(s) = self.pastset_cache.get(best_index) {
3634            s
3635        } else {
3636            pastset_tmp = self.compute_pastset_brutal(best_index);
3637            &pastset_tmp
3638        };
3639
3640        let lca_height_cache = mem::replace(
3641            &mut self.best_terminals_lca_height_cache,
3642            Default::default(),
3643        );
3644
3645        // We prepare a counter_map to denote the number of erased incoming
3646        // edges for each block.
3647        let mut counter_map = FastHashMap::new();
3648        let mut queue = BinaryHeap::new();
3649        for hash in self.terminal_hashes.iter() {
3650            let a_idx = self.hash_to_arena_indices.get(hash).unwrap();
3651            let mut a_lca_height = NULLU64;
3652            if let Some(h) = lca_height_cache.get(a_idx) {
3653                if *h < self.best_terminals_reorg_height {
3654                    a_lca_height = *h;
3655                }
3656            }
3657            if a_lca_height == NULLU64 {
3658                let a_lca = self.lca(*a_idx, best_index);
3659                a_lca_height = self.arena[a_lca].height;
3660            }
3661            self.best_terminals_lca_height_cache
3662                .insert(*a_idx, a_lca_height);
3663            queue.push((-(a_lca_height as i128), *a_idx));
3664        }
3665
3666        // The basic idea is to have a loop go over the refs in the priority
3667        // queue. We remove tips that have the smallest lca height. When
3668        // we remove a tip, we add those blocks the tip references back
3669        // to the queue. Eventually, we will get a set of referees
3670        // that is 1) within the ref_bound and 2) still holding best_index as
3671        // their parent.
3672        //
3673        // Note that we ignore the case where the force confirm mechanism will
3674        // influence the result here. The idea is that in normal
3675        // scenarios with good parameter setting. Force confirmation will
3676        // happen only when a block is already very stable.
3677        while queue.len() > ref_bound
3678            || queue
3679                .peek()
3680                .map_or(false, |(v, _)| *v == -(NULLU64 as i128))
3681        {
3682            let (_, idx) = queue.pop().unwrap();
3683            let parent = self.arena[idx].parent;
3684            if parent != NULL {
3685                if let Some(p) = counter_map.get_mut(&parent) {
3686                    *p = *p + 1;
3687                } else if !pastset.contains(parent as u32) {
3688                    counter_map.insert(parent, 1);
3689                }
3690                if let Some(p) = counter_map.get(&parent) {
3691                    if *p
3692                        == self.arena[parent].children.len()
3693                            + self.arena[parent].referrers.len()
3694                    {
3695                        // Note that although original terminal_hashes do not
3696                        // have out-of-era blocks,
3697                        // we can now get out-of-era blocks. We need to handle
3698                        // them.
3699                        if self.arena[parent].era_block == NULL {
3700                            queue.push((-(NULLU64 as i128), parent));
3701                        } else {
3702                            let mut a_lca_height = NULLU64;
3703                            if let Some(h) = lca_height_cache.get(&parent) {
3704                                if *h < self.best_terminals_reorg_height {
3705                                    a_lca_height = *h;
3706                                }
3707                            }
3708                            if a_lca_height == NULLU64 {
3709                                let a_lca = self.lca(parent, best_index);
3710                                a_lca_height = self.arena[a_lca].height;
3711                            }
3712                            self.best_terminals_lca_height_cache
3713                                .insert(parent, a_lca_height);
3714                            queue.push((-(a_lca_height as i128), parent));
3715                        }
3716                    }
3717                }
3718            }
3719            for referee in &self.arena[idx].referees {
3720                if let Some(p) = counter_map.get_mut(referee) {
3721                    *p = *p + 1;
3722                } else if !pastset.contains(*referee as u32) {
3723                    counter_map.insert(*referee, 1);
3724                }
3725                if let Some(p) = counter_map.get(referee) {
3726                    if *p
3727                        == self.arena[*referee].children.len()
3728                            + self.arena[*referee].referrers.len()
3729                    {
3730                        // Note that although original terminal_hashes do not
3731                        // have out-of-era blocks,
3732                        // we can now get out-of-era blocks. We need to handle
3733                        // them.
3734                        if self.arena[*referee].era_block == NULL {
3735                            queue.push((-(NULLU64 as i128), *referee));
3736                        } else {
3737                            let mut a_lca_height = NULLU64;
3738                            if let Some(h) = lca_height_cache.get(referee) {
3739                                if *h < self.best_terminals_reorg_height {
3740                                    a_lca_height = *h;
3741                                }
3742                            }
3743                            if a_lca_height == NULLU64 {
3744                                let a_lca = self.lca(*referee, best_index);
3745                                a_lca_height = self.arena[a_lca].height;
3746                            }
3747                            self.best_terminals_lca_height_cache
3748                                .insert(*referee, a_lca_height);
3749                            queue.push((-(a_lca_height as i128), *referee));
3750                        }
3751                    }
3752                }
3753            }
3754        }
3755        self.best_terminals_reorg_height = NULLU64;
3756        let bounded_hashes =
3757            queue.iter().map(|(_, b)| self.arena[*b].hash).collect();
3758        bounded_hashes
3759    }
3760
3761    pub fn finish_block_recovery(&mut self) { self.header_only = false; }
3762
3763    pub fn get_pivot_chain_and_weight(
3764        &self, height_range: Option<(u64, u64)>,
3765    ) -> Result<Vec<(H256, U256)>, String> {
3766        let min_height = self.get_cur_era_genesis_height();
3767        let max_height = self.arena[*self.pivot_chain.last().unwrap()].height;
3768        let (start, end) = height_range.unwrap_or((min_height, max_height));
3769        if start < min_height || end > max_height {
3770            bail!(
3771                "height_range out of bound: requested={:?} min={} max={}",
3772                height_range,
3773                min_height,
3774                max_height
3775            );
3776        }
3777
3778        let mut chain = Vec::new();
3779        for i in start..=end {
3780            let pivot_arena_index = self.get_pivot_block_arena_index(i);
3781            chain.push((
3782                self.arena[pivot_arena_index].hash.into(),
3783                (self.weight_tree.get(pivot_arena_index) as u64).into(),
3784            ));
3785        }
3786        Ok(chain)
3787    }
3788
3789    /// Return `None` if `root_block` is not in consensus.
3790    pub fn get_subtree(&self, root_block: &H256) -> Option<Vec<H256>> {
3791        let root_arena_index = *self.hash_to_arena_indices.get(root_block)?;
3792        let mut queue = VecDeque::new();
3793        let mut subtree = Vec::new();
3794        queue.push_back(root_arena_index);
3795        while let Some(i) = queue.pop_front() {
3796            subtree.push(self.arena[i].hash);
3797            for child in &self.arena[i].children {
3798                queue.push_back(*child);
3799            }
3800        }
3801        Some(subtree)
3802    }
3803
3804    pub fn get_next_pivot_decision(
3805        &self, parent_decision_hash: &H256, confirmed_height: u64,
3806    ) -> Option<(u64, H256)> {
3807        let r = match self.hash_to_arena_indices.get(parent_decision_hash) {
3808            None => {
3809                // parent_decision is before the current checkpoint, so we just
3810                // choose the latest block as a new pivot
3811                // decision.
3812                let new_decision_height = (confirmed_height.saturating_sub(
3813                    self.inner_conf
3814                        .pos_pivot_decision_defer_epoch_count(confirmed_height),
3815                )) / POS_TERM_EPOCHS
3816                    * POS_TERM_EPOCHS;
3817                if new_decision_height <= self.cur_era_genesis_height {
3818                    None
3819                } else {
3820                    let new_decision_arena_index =
3821                        self.get_pivot_block_arena_index(new_decision_height);
3822                    Some((
3823                        self.arena[new_decision_arena_index].height,
3824                        self.arena[new_decision_arena_index].hash,
3825                    ))
3826                }
3827            }
3828            Some(parent_decision) => {
3829                let parent_decision_height =
3830                    self.arena[*parent_decision].height;
3831                assert_eq!(parent_decision_height % POS_TERM_EPOCHS, 0);
3832                // `parent` should be on the pivot chain.
3833                if self.get_pivot_block_arena_index(parent_decision_height)
3834                    == *parent_decision
3835                {
3836                    // TODO(lpl): Use confirmed epoch with a delay in
3837                    // pos-finality spec.
3838                    let new_decision_height =
3839                        (confirmed_height.saturating_sub(
3840                            self.inner_conf
3841                                .pos_pivot_decision_defer_epoch_count(
3842                                    confirmed_height,
3843                                ),
3844                        )) / POS_TERM_EPOCHS
3845                            * POS_TERM_EPOCHS;
3846                    if new_decision_height <= parent_decision_height {
3847                        None
3848                    } else {
3849                        let new_decision_arena_index = self
3850                            .get_pivot_block_arena_index(new_decision_height);
3851                        Some((
3852                            self.arena[new_decision_arena_index].height,
3853                            self.arena[new_decision_arena_index].hash,
3854                        ))
3855                    }
3856                } else {
3857                    None
3858                }
3859            }
3860        };
3861        debug!(
3862            "next_pivot_decision: parent={:?} return={:?}",
3863            parent_decision_hash, r
3864        );
3865        r
3866    }
3867
3868    pub fn validate_pivot_decision(
3869        &self, ancestor_hash: &H256, me_hash: &H256,
3870    ) -> bool {
3871        if ancestor_hash == me_hash {
3872            return true;
3873        }
3874        debug!(
3875            "validate_pivot_decision: ancestor={:?}, me={:?}",
3876            ancestor_hash, me_hash
3877        );
3878        match (
3879            self.hash_to_arena_indices.get(ancestor_hash),
3880            self.hash_to_arena_indices.get(me_hash),
3881        ) {
3882            (Some(ancestor), Some(me)) => {
3883                if self.arena[*me].height % POS_TERM_EPOCHS != 0 {
3884                    return false;
3885                }
3886                // Both in memory. Just use Link-Cut-Tree.
3887                self.ancestor_at(*me, self.arena[*ancestor].height) == *ancestor
3888            }
3889            // TODO(lpl): Check if it's possible to go beyond checkpoint.
3890            // TODO(lpl): If we want to check ancestor and me are both on pivot
3891            // chain, we might need to always persist
3892            // block_execution_result for full nodes. Or include
3893            // height in the validation?
3894            (_, Some(_me)) => {
3895                // This should not happen after catching up for a normal node.
3896                if !self.header_only {
3897                    warn!(
3898                        "ancestor not in consensus graph: processed={}",
3899                        self.pivot_block_processed(ancestor_hash)
3900                    );
3901                }
3902                // ancestor is before checkpoint and is on pivot chain, so me
3903                // must be in the subtree.
3904                true
3905            }
3906            (_, _) => {
3907                // This should not happen after catching up for a normal node.
3908                if !self.header_only {
3909                    warn!("ancestor and me are both not in consensus graph, processed={} {}", self.pivot_block_processed(ancestor_hash), self.pivot_block_processed(me_hash));
3910                }
3911                true
3912            }
3913        }
3914    }
3915
3916    /// Return error if the header does not exist or the header does not have
3917    /// pos_reference or the pos_reference does not exist.
3918    fn get_pos_reference_pivot_decision(
3919        &self, block_hash: &H256,
3920    ) -> Result<H256, String> {
3921        let pos_reference = self
3922            .data_man
3923            .pos_reference_by_hash(block_hash)
3924            .ok_or("header exist".to_string())?
3925            .ok_or("pos reference checked in sync graph".to_string())?;
3926        self.pos_verifier
3927            .get_pivot_decision(&pos_reference)
3928            .ok_or("pos validity checked in sync graph".to_string())
3929    }
3930
3931    fn update_pos_pivot_decision(&mut self, me: usize) {
3932        let h = self.arena[me].hash;
3933        if let Ok(pivot_decision) = self.get_pos_reference_pivot_decision(&h) {
3934            let pivot_decision_height = self
3935                .data_man
3936                .block_height_by_hash(&pivot_decision)
3937                .expect("pos_reference checked");
3938            if pivot_decision_height > self.best_pos_pivot_decision.1 {
3939                self.best_pos_pivot_decision =
3940                    (pivot_decision, pivot_decision_height);
3941            }
3942        }
3943    }
3944
3945    // TODO(lpl): Copied from `check_mining_adaptive_block`.
3946    /// Return possibly new parent.
3947    pub fn choose_correct_parent(
3948        &mut self, parent_arena_index: usize, referee_indices: Vec<usize>,
3949        pos_reference: Option<PosBlockId>,
3950    ) -> usize {
3951        // We first compute anticone barrier for newly mined block
3952        let parent_anticone_opt = self.anticone_cache.get(parent_arena_index);
3953        let mut anticone;
3954        if parent_anticone_opt.is_none() {
3955            anticone = consensus_new_block_handler::ConsensusNewBlockHandler::compute_anticone_bruteforce(
3956                self, parent_arena_index,
3957            );
3958            for i in self.compute_future_bitset(parent_arena_index) {
3959                anticone.add(i);
3960            }
3961        } else {
3962            anticone = self.compute_future_bitset(parent_arena_index);
3963            for index in parent_anticone_opt.unwrap() {
3964                anticone.add(*index as u32);
3965            }
3966        }
3967        let mut my_past = BitSet::new();
3968        let mut queue: VecDeque<usize> = VecDeque::new();
3969        for index in &referee_indices {
3970            queue.push_back(*index);
3971        }
3972        while let Some(index) = queue.pop_front() {
3973            if my_past.contains(index as u32) {
3974                continue;
3975            }
3976            my_past.add(index as u32);
3977            let idx_parent = self.arena[index].parent;
3978            if idx_parent != NULL {
3979                if anticone.contains(idx_parent as u32)
3980                    || self.arena[idx_parent].era_block == NULL
3981                {
3982                    queue.push_back(idx_parent);
3983                }
3984            }
3985            for referee in &self.arena[index].referees {
3986                if anticone.contains(*referee as u32)
3987                    || self.arena[*referee].era_block == NULL
3988                {
3989                    queue.push_back(*referee);
3990                }
3991            }
3992        }
3993        for index in my_past.drain() {
3994            anticone.remove(index);
3995        }
3996
3997        let mut anticone_barrier = BitSet::new();
3998        for index in (&anticone).iter() {
3999            let parent = self.arena[index as usize].parent as u32;
4000            if self.arena[index as usize].era_block != NULL
4001                && !anticone.contains(parent)
4002            {
4003                anticone_barrier.add(index);
4004            }
4005        }
4006
4007        let timer_chain_tuple = self.compute_timer_chain_tuple(
4008            parent_arena_index,
4009            &referee_indices,
4010            Some(&anticone),
4011        );
4012
4013        self.choose_correct_parent_impl(
4014            parent_arena_index,
4015            &anticone_barrier,
4016            &timer_chain_tuple,
4017            pos_reference,
4018        )
4019    }
4020
4021    fn choose_correct_parent_impl(
4022        &mut self, parent: usize, anticone_barrier: &BitSet,
4023        timer_chain_tuple: &(u64, HashMap<usize, u64>, Vec<usize>, Vec<usize>),
4024        pos_reference: Option<PosBlockId>,
4025    ) -> usize {
4026        let force_confirm =
4027            self.compute_block_force_confirm(timer_chain_tuple, pos_reference);
4028        let force_confirm_height = self.arena[force_confirm].height;
4029
4030        if self.ancestor_at(parent, force_confirm_height) == force_confirm {
4031            // `parent` is the correct parent.
4032            return parent;
4033        }
4034
4035        let mut weight_delta = HashMap::new();
4036
4037        for index in anticone_barrier.iter() {
4038            assert!(!self.is_legacy_block(index as usize));
4039            weight_delta
4040                .insert(index as usize, self.weight_tree.get(index as usize));
4041        }
4042
4043        for (index, delta) in &weight_delta {
4044            self.weight_tree.path_apply(*index, -*delta);
4045        }
4046
4047        let mut new_parent = force_confirm;
4048        // Recursively find the correct pivot chain with the heaviest subtree
4049        // weight.
4050        while !self.arena[new_parent].children.is_empty() {
4051            let mut children = self.arena[new_parent].children.clone();
4052            let mut pivot = children.pop().expect("non-empty");
4053            for child in children {
4054                if ConsensusGraphInner::is_heavier(
4055                    (self.weight_tree.get(child), &self.arena[child].hash),
4056                    (self.weight_tree.get(pivot), &self.arena[pivot].hash),
4057                ) {
4058                    pivot = child;
4059                }
4060            }
4061            new_parent = pivot;
4062        }
4063
4064        for (index, delta) in &weight_delta {
4065            self.weight_tree.path_apply(*index, *delta);
4066        }
4067
4068        new_parent
4069    }
4070
4071    pub fn pivot_block_processed(&self, pivot_hash: &H256) -> bool {
4072        if let Some(height) = self.data_man.block_height_by_hash(pivot_hash) {
4073            if let Ok(epoch_hash) =
4074                self.get_pivot_hash_from_epoch_number(height)
4075            {
4076                if epoch_hash == *pivot_hash {
4077                    return true;
4078                } else {
4079                    debug!(
4080                        "pivot_block_processed: {:?} is not on pivot chain",
4081                        pivot_hash
4082                    );
4083                }
4084            } else {
4085                debug!("pivot_block_processed: epoch not processed height={:?} pivot={:?}", height, pivot_hash);
4086            }
4087        } else {
4088            debug!("pivot_block_processed: {:?} is not processed", pivot_hash);
4089        }
4090        false
4091    }
4092
4093    /// Return if a block has been confirmed by the pivot decision by the latest
4094    /// committed PoS block.
4095    ///
4096    /// This function needs persisted `BlockExecutionResult` to respond
4097    /// correctly for blocks before the checkpoint. If the data are not
4098    /// persisted, it will return `false` for blocks before the checkpoint even
4099    /// though they have been confirmed.
4100    pub fn is_confirmed_by_pos(&self, block_hash: &H256) -> bool {
4101        let epoch_number = match self.get_block_epoch_number(block_hash) {
4102            Some(epoch_number) => epoch_number,
4103            None => match self
4104                .data_man
4105                .block_execution_result_by_hash_from_db(block_hash)
4106            {
4107                Some(r) => {
4108                    let epoch_hash = r.0;
4109                    self.data_man
4110                        .block_height_by_hash(&epoch_hash)
4111                        .expect("executed header exists")
4112                }
4113                // We cannot find the BlockExecutionResult.
4114                None => return false,
4115            },
4116        };
4117        // All epochs before the confirmed epoch are regarded PoS-confirmed.
4118        epoch_number <= self.best_pos_pivot_decision.1
4119    }
4120
4121    /// Return the latest PoS pivot decision processed in ConsensusGraph.
4122    pub fn latest_epoch_confirmed_by_pos(&self) -> &(H256, u64) {
4123        &self.best_pos_pivot_decision
4124    }
4125
4126    /// Cap the confirmed height for state maintenance at the PoS
4127    /// finalized height. Snapshots above the PoS finalized height
4128    /// must not be pruned.
4129    pub fn confirmed_height_for_state_maintenance(
4130        &self, confirmed_height: u64,
4131    ) -> u64 {
4132        std::cmp::min(confirmed_height, self.best_pos_pivot_decision.1)
4133    }
4134}
4135
4136impl pow::ConsensusProvider for &ConsensusGraphInner {
4137    fn num_blocks_in_epoch(&self, h: &H256) -> u64 {
4138        let index = self.hash_to_arena_indices.get(h).unwrap(); // TODO handle None
4139        let parent = self.arena[*index].parent;
4140        (self.arena[*index].past_num_blocks
4141            - self.arena[parent].past_num_blocks) as u64
4142    }
4143
4144    fn block_header_by_hash(&self, hash: &H256) -> Option<Arc<BlockHeader>> {
4145        self.data_man.block_header_by_hash(hash)
4146    }
4147}
4148
4149impl Graph for ConsensusGraphInner {
4150    type NodeIndex = usize;
4151}
4152
4153impl TreeGraph for ConsensusGraphInner {
4154    fn parent(&self, node_index: Self::NodeIndex) -> Option<Self::NodeIndex> {
4155        if self.arena[node_index].parent != NULL {
4156            Some(self.arena[node_index].parent)
4157        } else {
4158            None
4159        }
4160    }
4161
4162    fn referees(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex> {
4163        self.arena[node_index].referees.clone()
4164    }
4165}
4166
4167impl RichTreeGraph for ConsensusGraphInner {
4168    fn children(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex> {
4169        self.arena[node_index].children.clone()
4170    }
4171
4172    fn referrers(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex> {
4173        self.arena[node_index].referrers.clone()
4174    }
4175}
4176
4177impl StateMaintenanceTrait for ConsensusGraphInner {
4178    fn get_pivot_hash_from_epoch_number(
4179        &self, epoch_number: u64,
4180    ) -> Result<EpochId, String> {
4181        ConsensusGraphInner::get_pivot_hash_from_epoch_number(
4182            self,
4183            epoch_number,
4184        )
4185        .map_err(|e| e.to_string())
4186    }
4187
4188    fn get_epoch_execution_commitment_with_db(
4189        &self, block_hash: &EpochId,
4190    ) -> Option<EpochExecutionCommitment> {
4191        self.data_man
4192            .get_epoch_execution_commitment_with_db(block_hash)
4193    }
4194}
4195
4196#[cfg(test)]
4197mod blame_underflow_tests {
4198    use super::ConsensusGraphInner;
4199
4200    // Reference "honest" arithmetic these helpers must reproduce exactly when
4201    // the raw subtraction does not underflow.
4202    fn naive_prev(
4203        trusted_index: usize, blame: u32, from: usize,
4204    ) -> Option<usize> {
4205        let prev = trusted_index - blame as usize - 1;
4206        if prev >= from {
4207            Some(prev)
4208        } else {
4209            None
4210        }
4211    }
4212
4213    #[test]
4214    fn blame_prev_trusted_pivot_index_matches_naive_on_honest_inputs() {
4215        for &(trusted_index, blame, from) in &[
4216            (100usize, 0u32, 10usize),
4217            (100, 3, 10),
4218            (100, 89, 10), // prev == from
4219            (100, 90, 10), // prev < from -> None
4220        ] {
4221            assert_eq!(
4222                ConsensusGraphInner::prev_trusted_pivot_index(
4223                    trusted_index,
4224                    blame,
4225                    from
4226                ),
4227                naive_prev(trusted_index, blame, from),
4228                "trusted_index={trusted_index} blame={blame} from={from}",
4229            );
4230        }
4231    }
4232
4233    #[test]
4234    fn blame_prev_trusted_pivot_index_no_panic_on_malicious_blame() {
4235        // blame >= trusted_index underflows the old `trusted_index - blame -
4236        // 1`.
4237        assert_eq!(
4238            ConsensusGraphInner::prev_trusted_pivot_index(5, 5, 0),
4239            None
4240        );
4241        assert_eq!(
4242            ConsensusGraphInner::prev_trusted_pivot_index(5, 10, 0),
4243            None
4244        );
4245        assert_eq!(
4246            ConsensusGraphInner::prev_trusted_pivot_index(0, u32::MAX, 0),
4247            None
4248        );
4249        assert_eq!(
4250            ConsensusGraphInner::prev_trusted_pivot_index(3, u32::MAX, 0),
4251            None
4252        );
4253    }
4254
4255    #[test]
4256    fn blame_covered_start_height_matches_naive_on_honest_inputs() {
4257        for &(height, blame) in &[(100u64, 0u32), (100, 3), (100, 94)] {
4258            assert_eq!(
4259                ConsensusGraphInner::blame_covered_start_height(height, blame),
4260                Some(height - blame as u64 - 1),
4261                "height={height} blame={blame}",
4262            );
4263        }
4264    }
4265
4266    #[test]
4267    fn blame_covered_start_height_no_panic_on_malicious_blame() {
4268        // blame >= height underflows the old `height - blame - 1`.
4269        assert_eq!(ConsensusGraphInner::blame_covered_start_height(5, 5), None);
4270        assert_eq!(
4271            ConsensusGraphInner::blame_covered_start_height(5, 10),
4272            None
4273        );
4274        assert_eq!(ConsensusGraphInner::blame_covered_start_height(0, 0), None);
4275        assert_eq!(
4276            ConsensusGraphInner::blame_covered_start_height(3, u32::MAX),
4277            None
4278        );
4279    }
4280}