mirror of
https://github.com/tendermint/tendermint.git
synced 2026-10-01 12:15:45 +00:00
evidence: handling evidence from light client(s) (#4532)
Closes: #4530 This PR contains logic for both submitting an evidence by the light client (lite2 package) and receiving it on the Tendermint side (/broadcast_evidence RPC and/or EvidenceReactor#Receive). Upon receiving the ConflictingHeadersEvidence (introduced by this PR), the Tendermint validates it, then breaks it down into smaller pieces (DuplicateVoteEvidence, LunaticValidatorEvidence, PhantomValidatorEvidence, PotentialAmnesiaEvidence). Afterwards, each piece of evidence is verified against the state of the full node and added to the pool, from which it's reaped upon block creation. * rpc/client: do not pass height param if height ptr is nil * rpc/core: validate incoming evidence! * only accept ConflictingHeadersEvidence if one of the headers is committed from this full node's perspective This simplifies the code. Plus, if there are multiple forks, we'll likely to receive multiple ConflictingHeadersEvidence anyway. * swap CommitSig with Vote in LunaticValidatorEvidence Vote is needed to validate signature * no need to embed client http is a provider and should not be used as a client
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
## Changelog
|
||||
* 18-02-2020: Initial draft
|
||||
* 24-02-2020: Second version
|
||||
* 13-04-2020: Add PotentialAmnesiaEvidence and a few remarks
|
||||
|
||||
## Context
|
||||
|
||||
@@ -26,6 +27,11 @@ type ConflictingHeadersEvidence struct {
|
||||
}
|
||||
```
|
||||
|
||||
_Remark_: Theoretically, only the header, which differs from what a full node
|
||||
has, needs to be sent. But sending two headers a) makes evidence easily
|
||||
verifiable b) simplifies the light client, which does not have query each
|
||||
witness as to which header it possesses.
|
||||
|
||||
When a full node receives the `ConflictingHeadersEvidence` evidence, it should
|
||||
a) validate it b) figure out if malicious behaviour is obvious (immediately
|
||||
slashable) or the fork accountability protocol needs to be started.
|
||||
@@ -34,7 +40,7 @@ slashable) or the fork accountability protocol needs to be started.
|
||||
|
||||
Check both headers are valid (`ValidateBasic`), have the same height, and
|
||||
signed by 1/3+ of the validator set that the full node had at height
|
||||
`H1.Height-1`.
|
||||
`H1.Height`.
|
||||
|
||||
- Q: What if light client validator set is not equal to full node's validator
|
||||
set (i.e. from full node's point of view both headers are not properly signed;
|
||||
@@ -53,6 +59,9 @@ signed by 1/3+ of the validator set that the full node had at height
|
||||
### Figuring out if malicious behaviour is immediately slashable
|
||||
|
||||
Let's say H1 was committed from this full node's perspective (see Appendix A).
|
||||
_If neither of the headers (H1 and H2) were committed from the full node's
|
||||
perspective, the evidence must be rejected._
|
||||
|
||||
Intersect validator sets of H1 and H2.
|
||||
|
||||
* if there are signers(H2) that are not part of validators(H1), they misbehaved as
|
||||
@@ -99,20 +108,23 @@ A new type of evidence needs to be created:
|
||||
|
||||
```go
|
||||
type PhantomValidatorEvidence struct {
|
||||
PubKey crypto.PubKey
|
||||
Vote types.Vote
|
||||
Header types.Header
|
||||
Vote types.Vote
|
||||
LastHeightValidatorWasInSet int64
|
||||
}
|
||||
```
|
||||
|
||||
It contains a validator's public key and a vote for a block, where this
|
||||
validator is not part of the validator set.
|
||||
validator is not part of the validator set. `LastHeightValidatorWasInSet`
|
||||
indicates the last height validator was in the validator set.
|
||||
|
||||
### F5. Lunatic validator
|
||||
|
||||
```go
|
||||
type LunaticValidatorEvidence struct {
|
||||
Header types.Header
|
||||
Vote types.Vote
|
||||
Header types.Header
|
||||
Vote types.Vote
|
||||
InvalidHeaderField string
|
||||
}
|
||||
```
|
||||
|
||||
@@ -154,6 +166,26 @@ This includes `ValidatorsHash`, `NextValidatorsHash`, `ConsensusHash`,
|
||||
for the block that was actually committed at the corresponding height, and
|
||||
should thus be easy to check.
|
||||
|
||||
`InvalidHeaderField` contains the invalid field name. Note it's very likely
|
||||
that multiple fields diverge, but it's faster to check just one. This field
|
||||
MUST NOT be used to determine equality of `LunaticValidatorEvidence`.
|
||||
|
||||
### F2. Amnesia
|
||||
|
||||
```go
|
||||
type PotentialAmnesiaEvidence struct {
|
||||
VoteA types.Vote
|
||||
VoteB types.Vote
|
||||
}
|
||||
```
|
||||
|
||||
To punish this attack, votes under question needs to be sent. Fork
|
||||
accountability process should then use this evidence to request additional
|
||||
information from offended validators and construct a new type of evidence to
|
||||
punish those who conducted an amnesia attack.
|
||||
|
||||
See ADR-056 for the architecture of the fork accountability procedure.
|
||||
|
||||
## Status
|
||||
|
||||
Proposed.
|
||||
|
||||
Reference in New Issue
Block a user