Skip to content

Rust accepts empty Simplex candidates whose referenced block is not the FSM tip, while C++ rejects them #43

@EmelyanenkoK

Description

@EmelyanenkoK

Rust and C++ do not enforce the same validity rule for empty Simplex candidates.

An empty candidate carries a referenced block id. C++ rejects the candidate unless that referenced block exactly matches the current normal FSM state for the slot. Rust does not perform that check and auto-approves empty candidates once signature and parent-chain checks pass.

This is consensus-critical because it allows Rust validators to approve and vote for an empty candidate that C++ validators reject.

Affected code

  • Rust: rust_implementation/ton-rust-node/src/node/simplex/src/block.rs:908-1018
  • Rust: rust_implementation/ton-rust-node/src/node/simplex/src/session_processor.rs:5812-5820
  • Rust: rust_implementation/ton-rust-node/src/node/simplex/src/session_processor.rs:5886-5895
  • C++: validator/consensus/block-validator.cpp:68-75

Rust/C++ discrepancy

C++ empty-candidate validation does:

  • reject unless block == event->state->as_normal()

Rust does not have an equivalent state-tip comparison.

In Rust:

  1. RawCandidate::from_tl() extracts the referenced block for Consensus_Empty
  2. it checks signature validity and parent presence
  3. check_validation() explicitly skips further validation for empty blocks
  4. try_approve_block() auto-approves them immediately

So Rust accepts an empty candidate without confirming that its referenced block matches the active FSM tip.

Trigger

The discrepancy is reachable when a leader emits an empty candidate such that:

  1. the candidate is correctly signed
  2. the parent chain is resolvable
  3. the block field refers to some block other than the FSM's current normal state for that slot

This is not a malformed-wire-format issue. The candidate can be well-formed and signed by the expected leader.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions