Skip to content

kip-227: report candidate failures against the proposer's own prior block - #126

Merged
hyunsooda merged 3 commits into
kaiachain:mainfrom
hyunsooda:kip-227-cfreport-own-proposal
Aug 20, 2026
Merged

kip-227: report candidate failures against the proposer's own prior block#126
hyunsooda merged 3 commits into
kaiachain:mainfrom
hyunsooda:kip-227-cfreport-own-proposal

Conversation

@hyunsooda

@hyunsooda hyunsooda commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

Aligns KIP-227 with a change to how candidate failures are attributed. Previously cfReport(N) covered block N-1 and was written by the proposer of block N — a writer that is not the validator that solicited the candidate responses. That lets a proposer withhold its VRankPreprepare and have the induced failures spread across honest writers, surviving the top-F byzantine filter.

Now a cfReport reports on the writer's own most recent prior proposal in the same epoch. A candidate failure is scored against the reporting block's own proposer, so any withheld or fabricated failure lands in that proposer's own byzantine-filterable column and is filtered — the report carries only the failed candidate list. Reports without such a prior proposal (or that would cross an epoch boundary) are empty. Message flow, PFS, MAX_ROUND, and the byzantine filter are unchanged.

Types of changes

  • Bugfix
  • KIP Proposal
  • KIP Improvement

Checklist

  • Used the suggested template: https://github.com/kaiachain/KIPs/blob/main/kip-template.md
  • I have read the CLA and signed by comment I have read the CLA Document and I hereby sign the CLA in first time contribution
  • I have added necessary documentation (if appropriate)
  • Any dependent changes have been merged and published in downstream modules

Related issues

Further comments

…lock

A cfReport now targets the writer's own most recent prior proposal in the same
epoch (so the report writer is the validator that solicited the candidates), and
header.VRank carries that target block. Verification requires the target to be a
prior, same-epoch block with the same proposer as the reporting block, so any
withheld or fabricated failure is attributed to that proposer's own column under
CFS aggregation. Reports without such a prior proposal (or across an epoch
boundary) are empty. Message flow, PFS, MAX_ROUND, and the byzantine filter are
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hyunsooda hyunsooda self-assigned this Jul 22, 2026
The cfReport no longer carries the evaluated (target) block, only the failed
candidate list. A candidate failure is scored against the reporting block's own
proposer, so storing and verifying the target block added nothing; the format,
the writer/reader note, and the block-validation target/proposer-match checks
drop with it.
A candidate now sends VRankCandidate to the proposer that sent the
VRankPreprepare, instead of broadcasting to all validators in ValActive. Only
that proposer records preprepared_time and collects the replies, since it is the
node that reports on the view from its own next proposal.

Drop the "arrives before preprepared_time" on-time case: the proposer records
preprepared_time before requesting the responses, so a reply never precedes it.
@hyunsooda
hyunsooda merged commit 47e2a08 into kaiachain:main Aug 20, 2026
2 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants