I was exploring GRANDPA verification algorithm and stumbled upon this code by the link https://github.com/paritytech/finality-grandpa/blame/master/src/lib.rs#L494
Source
This is the part of method validate_commit
which verifies that GRANDPA finalized correctly a block given particular voter set. The usage of equivocated
set is not completely clear to me. It is used only in this part of the method.
...
let mut equivocated = std::collections::BTreeSet::new();
// add all precommits to the round with correct counting logic
let mut round = round::Round::new(round::RoundParams {
round_number: 0, // doesn't matter here.
voters: voters.clone(),
base,
});
for SignedPrecommit { precommit, id, signature } in &valid_precommits {
match round.import_precommit(chain, precommit.clone(), id.clone(), signature.clone())? {
ImportResult { equivocation: Some(_), .. } => {
validation_result.num_equivocations += 1;
// allow only one equivocation per voter, as extras are redundant.
if !equivocated.insert(id) {
return Ok(validation_result)
}
},
ImportResult { duplicated, .. } =>
if duplicated {
validation_result.num_duplicated_precommits += 1;
},
}
}
...
This is how I understand this code:
- We detect equivocations and duplicates in
round.import_precommit(...)
. - We register the detected equivocations in
equivocated
set by addingid
of the voter there. - If it's only first time we observe this voter equivocating — we continue.
- If we've already seen the voter equivocating — we return.
validation_result.valid
is false
in this case (default value).
If we detect duplicates, they don't affect validity status.
In the end, validity status is set to
true
if we computed valid GHOST.
So, validate_commit
still can succeed even in presence of equivocations.
Questions
I've scanned GRANDPA docs, W3F website and GitHub issues but couldn't find anything about tolerance to equivocations. Please, could anyone clarify it to me?
Are the following statements correct?
- The method
validate_commit
is intended to be used in a light client. - Successful status of
validate_commit
, i.e.CommitValidationResult::valid == true
, means that the header containing it CAN be accepted and update the light client. - Failed status of
validate_commit
, i.e.CommitValidationResult::valid == false
, means that the header containing this proof MUST NOT be accepted. - Equivocations are forbidden in any amount, all voters from
equivocated
set must get slashed. - Equivocations don't make the finality proof invalid.
- Finality proof SHOULD contain equivocations if there been any. This "seals" fact of misbehaviour into the blockchain.
- Finality proof MUST NOT contain more than 1 equivocation for a voter, this is important because we don't want to bloat the proofs.
Probably, all of the above is correct, or none of it.
Please, make it clear!