Skip to content

Genesis check uses pendingStateHash — hFG always 0, re-finalization guards disabled #7

@MastaP

Description

@MastaP

Summary

`txsystem/fgp_txsystem.go:108` — `LeaderPropose` checks `!bytes.Equal(s.pendingStateHash, s.genesisHash)` to determine if there is a previously certified block. However:

  • `pendingStateHash` is reset to `nil` after each `Commit()` or `Revert()`
  • `genesisHash` is also `nil`
  • So `bytes.Equal(nil, nil)` is always `true`, and the genesis branch is always taken

This means `hFG` is always 0, making these safety checks effectively dead code:

  • Line 118: `tip.Height <= hFG` — always `tip.Height <= 0`, never triggers
  • Line 129: `candidateHeight <= hFG` — always `candidateHeight <= 0`, never triggers

The system works "by accident" because the height comparison at line 131 (`candidateHeight <= s.committedStateHeight`) provides a partial guard, but the intended protection against re-certifying blocks at or below the last certified height is not functional.

Severity

High — safety guards for re-finalization are disabled. A chain reorganization below the last certified height would not be detected by the `hFG`-based checks.

Suggested Fix

Use `committedStateHash` instead of `pendingStateHash` for the genesis check:

if !bytes.Equal(s.committedStateHash, s.genesisHash) {

Related

  • `FollowerVerify` (lines 166-203) does not check that the proposed block height is greater than the last committed height at all.
  • `FollowerVerify` also skips the fork safety check (`GetChainTips`) that `LeaderPropose` performs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions