/// <summary> /// Recalculates and complements all <i>missing</i> block states including and upto given /// <paramref name="blockHash"/> starting from the last known states in /// <see cref="StateStore"/> before <paramref name="blockHash"/> if the states are missing /// for <paramref name="blockHash"/>. /// </summary> /// <param name="blockHash">The starting point for searching backwards.</param> internal void ComplementLatestBlockStates(BlockHash blockHash) { _logger.Verbose("Complementing latest block states upto {BlockHash}...", blockHash); // Prevent recursive trial to recalculate & complement incomplete block states by // mistake; if the below code works as intended, these state completers must never // be invoked. StateCompleterSet <T> stateCompleters = StateCompleterSet <T> .Reject; Stack <BlockHash> stack = new Stack <BlockHash>(); BlockHash? pointer = blockHash; while (pointer is { } p) { HashDigest <SHA256>?stateRootHash = Store.GetStateRootHash(p); if (stateRootHash is { } h&& StateStore.ContainsStateRoot(h)) { break; }
/// <summary> /// Recalculates and complements all <i>missing</i> block states including and upto given /// <paramref name="blockHash"/> starting from the genesis block. /// </summary> /// <param name="blockHash">The inclusive limit of target hash to terminate complementation. /// </param> /// <remarks> /// <para> /// If a complementation of the entire blockchain is needed, call with the tip hash of the /// <see cref="BlockChain{T}"/>. /// </para> /// <para> /// Unlike <see cref="RecalculateBlockStates"/>, this method skips recalculations if states /// are found for intermediate blocks. This may not be fully secure if states for /// blocks in <see cref="IStateStore"/> are somehow corrupted. /// </para> /// </remarks> internal void ComplementAllBlockStates(BlockHash blockHash) { _logger.Verbose("Complementing all block states upto {BlockHash}...", blockHash); // Prevent recursive trial to recalculate & complement incomplete block states by // mistake; if the below code works as intended, these state completers must never // be invoked. StateCompleterSet <T> stateCompleters = StateCompleterSet <T> .Reject; // Calculates and fills the incomplete states on the fly. foreach (BlockHash hash in BlockHashes) { Block <T> block = this[hash]; if (StateStore.ContainsStateRoot(block.StateRootHash)) { continue; } IReadOnlyList <ActionEvaluation> evaluations = ActionEvaluator.Evaluate( block, stateCompleters); _rwlock.EnterWriteLock(); try { SetStates(block, evaluations); } finally { _rwlock.ExitWriteLock(); } if (blockHash.Equals(hash)) { break; } } }