Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public void Initialize(XdcBlockHeader current)
{
IXdcReleaseSpec spec = _specProvider.GetXdcSpec(current);
QuorumCertificate latestQc;
if (current.Number == spec.SwitchBlock)
if (current.Number == spec.SwitchBlock || current.ExtraConsensusData is null)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium — Silent fallback without a warning log

When current.ExtraConsensusData is null on a block that is not the switch block, Initialize silently treats it as a genesis block: round is reset to 1 and a synthetic zero-round QC is constructed. This is the correct action to avoid an NPE (the original bug), but it is inconsistent with how the rest of the file handles the same condition — CommitBlock at line 95 logs a warning and returns an error for the same missing-data scenario ("Chain might be corrupt!").

Without a warning log here, chain corruption or a deserialization bug that leaves ExtraConsensusData null on a mid-chain block will produce no observable signal; the node will just silently restart consensus from round 1.

Suggested fix — add a warn log inside the branch when it isn't the switch block:

Suggested change
if (current.Number == spec.SwitchBlock || current.ExtraConsensusData is null)
if (current.Number == spec.SwitchBlock || current.ExtraConsensusData is null)
{
if (current.Number != spec.SwitchBlock && _logger.IsWarn)
_logger.Warn($"Block {current.ToString(BlockHeader.Format.FullHashAndNumber)} has no consensus data; initializing consensus from genesis state.");

Fix this →

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The null guard is correct and prevents the NRE in the else branch. Two suggestions:

  1. Regression test — please add a test in QuorumCertificateManagerTest covering Initialize with a V1 block (ExtraConsensusData is null, Number != spec.SwitchBlock). The existing test helpers make this straightforward.

  2. Observability — a _logger.Warn on the null path (when Number != spec.SwitchBlock) would make it visible if this is ever hit unexpectedly for a V2 block due to serialization or DB issues, rather than silently resetting to round 1.

Suggested change
if (current.Number == spec.SwitchBlock || current.ExtraConsensusData is null)
if (current.Number == spec.SwitchBlock || current.ExtraConsensusData is null)
{
if (current.ExtraConsensusData is null && current.Number != spec.SwitchBlock)
if (_logger.IsWarn) _logger.Warn($"Block #{current.Number} ({current.Hash}) has no V2 consensus data, initializing consensus from V1 genesis.");

{
latestQc = new QuorumCertificate(new BlockRoundInfo(current.Hash, 0, current.Number), Array.Empty<Signature>(),
(ulong)Math.Max(0, current.Number - spec.Gap));
Expand Down
Loading