Browse Source

evidence: add section explaining evidence (#324)

pull/7804/head
Callum Waters 3 years ago
committed by GitHub
parent
commit
8029cf7a0f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 234 additions and 61 deletions
  1. +199
    -0
      spec/consensus/evidence.md
  2. +35
    -61
      spec/core/data_structures.md

+ 199
- 0
spec/consensus/evidence.md View File

@ -0,0 +1,199 @@
# Evidence
Evidence is an important component of Tendermint's security model. Whilst the core
consensus protocol provides correctness gaurantees for state machine replication
that can tolerate less than 1/3 failures, the evidence system looks to detect and
gossip byzantine faults whose combined power is greater than or equal to 1/3. It is worth noting that
the evidence system is designed purely to detect possible attacks, gossip them,
commit them on chain and inform the application running on top of Tendermint.
Evidence in itself does not punish "bad actors", this is left to the discretion
of the application. A common form of punishment is slashing where the validators
that were caught violating the protocol have all or a portion of their voting
power removed. Evidence, given the assumption that 1/3+ of the network is still
byzantine, is susceptible to censorship and should therefore be considered added
security on a "best effort" basis.
This document walks through the various forms of evidence, how they are detected,
gossiped, verified and committed.
> NOTE: Evidence here is internal to tendermint and should not be confused with
> application evidence
## Detection
### Equivocation
Equivocation is the most fundamental of byzantine faults. Simply put, to prevent
replication of state across all nodes, a validator tries to convince some subset
of nodes to commit one block whilst convincing another subset to commit a
different block. This is achieved by double voting (hence
`DuplicateVoteEvidence`). A successful duplicate vote attack requires greater
than 1/3 voting power and a (temporary) network partition between the aforementioned
subsets. This is because in consensus, votes are gossiped around. When a node
observes two conflicting votes from the same peer, it will use the two votes of
evidence and begin gossiping this evidence to other nodes. [Verification](#duplicatevoteevidence) is addressed further down.
```go
type DuplicateVoteEvidence struct {
VoteA Vote
VoteB Vote
// and abci specific fields
}
```
### Light Client Attacks
Light clients also comply with the 1/3+ security model, however, by using a
different, more lightweight verification method they are subject to a
different kind of 1/3+ attack whereby the byzantine validators could sign an
alternative light block that the light client will think is valid. Detection,
explained in greater detail
[here](../light-client/detection/detection_003_reviewed.md), involves comparison
with multiple other nodes in the hope that at least one is "honest". An "honest"
node will return a challenging light block for the light client to validate. If
this challenging light block also meets the
[validation criteria](../light-client/verification/verification_001_published.md)
then the light client sends the "forged" light block to the node.
[Verification](#lightclientattackevidence) is addressed further down.
```go
type LightClientAttackEvidence struct {
ConflictingBlock LightBlock
CommonHeight int64
// and abci specific fields
}
```
## Verification
If a node receives evidence, it will first try to verify it, then persist it.
Evidence of byzantine behavior should only be committed once (uniqueness) and
should be committed within a certain period from the point that it occurred
(timely). Timelines is defined by the `EvidenceParams`: `MaxAgeNumBlocks` and
`MaxAgeDuration`. In Proof of Stake chains where validators are bonded, evidence
age should be less than the unbonding period so validators still can be
punished. Given these two propoerties the following initial checks are made.
1. Has the evidence expired? This is done by taking the height of the `Vote`
within `DuplicateVoteEvidence` or `CommonHeight` within
`LightClientAttakEvidence`. The evidence height is then used to retrieve the
header and thus the time of the block that corresponds to the evidence. If
`CurrentHeight - MaxAgeNumBlocks > EvidenceHeight` && `CurrentTime -
MaxAgeDuration > EvidenceTime`, the evidence is considered expired and
ignored.
2. Has the evidence already been committed? The evidence pool tracks the hash of
all committed evidence and uses this to determine uniqueness. If a new
evidence has the same hash as a committed one, the new evidence will be
ignored.
### DuplicateVoteEvidence
Valid `DuplicateVoteEvidence` must adhere to the following rules:
- Validator Address, Height, Round and Type must be the same for both votes
- BlockID must be different for both votes (BlockID can be for a nil block)
- Validator must have been in the validator set at that height
- Vote signature must be correctly signed. This also uses `ChainID` so we know
that the fault occurred on this chain
### LightClientAttackEvidence
Valid Light Client Attack Evidence must adhere to the following rules:
- If the header of the light block is invalid, thus indicating a lunatic attack,
the node must check that they can use `verifySkipping` from their header at
the common height to the conflicting header
- If the header is valid, then the validator sets are the same and this is
either a form of equivocation or amnesia. We therefore check that 2/3 of the
validator set also signed the conflicting header.
- The nodes own header at the same height as the conflicting header must have a
different hash to the conflicting header.
- If the nodes latest header is less in height to the conflicting header, then
the node must check that the conflicting block has a time that is less than
this latest header (This is a forward lunatic attack).
## Gossiping
If a node verifies evidence it then broadcasts it to all peers, continously sending
the same evidence once every 10 seconds until the evidence is seen on chain or
expires.
## Commiting on Chain
Evidence takes strict priority over regular transactions, thus a block is filled
with evidence first and transactions take up the remainder of the space. To
mitigate the threat of an already punished node from spamming the network with
more evidence, the size of the evidence in a block can be capped by
`EvidenceParams.MaxBytes`. Nodes receiving blocks with evidence will validate
the evidence before sending `Prevote` and `Precommit` votes. The evidence pool
will usually cache verifications so that this process is much quicker.
## Sending Evidence to the Application
After evidence is committed, the block is then processed by the block executor
which delivers the evidence to the application via `EndBlock`. Evidence is
stripped of the actual proof, split up per faulty validator and only the
validator, height, time and evidence type is sent.
```proto
enum EvidenceType {
UNKNOWN = 0;
DUPLICATE_VOTE = 1;
LIGHT_CLIENT_ATTACK = 2;
}
message Evidence {
EvidenceType type = 1;
// The offending validator
Validator validator = 2 [(gogoproto.nullable) = false];
// The height when the offense occurred
int64 height = 3;
// The corresponding time where the offense occurred
google.protobuf.Timestamp time = 4 [
(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// Total voting power of the validator set in case the ABCI application does
// not store historical validators.
// https://github.com/tendermint/tendermint/issues/4581
int64 total_voting_power = 5;
}
```
`DuplicateVoteEvidence` and `LightClientAttackEvidence` are self-contained in
the sense that the evidence can be used to derive the `abci.Evidence` that is
sent to the application. Because of this, extra fields are necessary:
```go
type DuplicateVoteEvidence struct {
VoteA *Vote
VoteB *Vote
// abci specific information
TotalVotingPower int64
ValidatorPower int64
Timestamp time.Time
}
type LightClientAttackEvidence struct {
ConflictingBlock *LightBlock
CommonHeight int64
// abci specific information
ByzantineValidators []*Validator
TotalVotingPower int64
Timestamp time.Time
}
```
These ABCI specific fields don't affect validity of the evidence itself but must
be consistent amongst nodes and agreed upon on chain. If evidence with the
incorrect abci information is sent, a node will create new evidence from it and
replace the ABCI fields with the correct information.

+ 35
- 61
spec/core/data_structures.md View File

@ -4,33 +4,39 @@ Here we describe the data structures in the Tendermint blockchain and the rules
The Tendermint blockchains consists of a short list of data types:
- [`Block`](#block)
- [`Header`](#header)
- [`Version`](#version)
- [`BlockID`](#blockid)
- [`PartSetHeader`](#partsetheader)
- [`Time`](#time)
- [`Data` (for transactions)](#data)
- [`Commit`](#commit)
- [`CommitSig`](#commitsig)
- [`BlockIDFlag`](#blockidflag)
- [`Vote`](#vote)
- [`CanonicalVote`](#canonicalvote)
- [`SignedMsgType`](#signedmsgtype)
- [`EvidenceList`](#evidence_list)
- [`Evidence`](#evidence)
- [`DuplicateVoteEvidence`](#duplicatevoteevidence)
- [`LightClientAttackEvidence`](#lightclientattackevidence)
- [`LightBlock`](#lightblock)
- [`SignedHeader`](#signedheader)
- [`Validator`](#validator)
- [`ValidatorSet`](#validatorset)
- [`Address`](#address)
- [`ConsensusParams`](#consensusparams)
- [`BlockParams`](#blockparams)
- [`EvidenceParams`](#evidenceparams)
- [`ValidatorParams`](#validatorparams)
- [`VersionParams`](#versionparams)
- [Data Structures](#data-structures)
- [Block](#block)
- [Execution](#execution)
- [Header](#header)
- [Version](#version)
- [BlockID](#blockid)
- [PartSetHeader](#partsetheader)
- [Part](#part)
- [Time](#time)
- [Data](#data)
- [Commit](#commit)
- [CommitSig](#commitsig)
- [BlockIDFlag](#blockidflag)
- [Vote](#vote)
- [CanonicalVote](#canonicalvote)
- [Proposal](#proposal)
- [SignedMsgType](#signedmsgtype)
- [Signature](#signature)
- [EvidenceList](#evidencelist)
- [Evidence](#evidence)
- [DuplicateVoteEvidence](#duplicatevoteevidence)
- [LightClientAttackEvidence](#lightclientattackevidence)
- [LightBlock](#lightblock)
- [SignedHeader](#signedheader)
- [ValidatorSet](#validatorset)
- [Validator](#validator)
- [Address](#address)
- [ConsensusParams](#consensusparams)
- [BlockParams](#blockparams)
- [EvidenceParams](#evidenceparams)
- [ValidatorParams](#validatorparams)
- [VersionParams](#versionparams)
- [Proof](#proof)
## Block
@ -323,8 +329,7 @@ EvidenceList is a simple wrapper for a list of evidence:
Evidence in Tendermint is used to indicate breaches in the consensus by a validator.
The [Fork Accountability](../light-client/accountability.md) document provides a good overview of evidence and how they occur. For evidence to be committed onchain, it must adhere to the validation rules of each evidence and must not be expired. The expiration age, measured in both block height and time is set in `EvidenceParams`. Each evidence uses
the timestamp of the block that the evidence occurred at to indicate the age of the evidence.
More information on how evidence works in Tendermint can be found [here](../consensus/evidence.md)
### DuplicateVoteEvidence
@ -339,23 +344,9 @@ in the same round of the same height. Votes are lexicographically sorted on `Blo
| ValidatorPower | int64 | Power of the equivocating validator at the height | Must be equal to the nodes own copy of the data |
| Timestamp | [Time](#Time) | Time of the block where the equivocation occurred | Must be equal to the nodes own copy of the data |
Valid Duplicate Vote Evidence must adhere to the following rules:
- Validator Address, Height, Round and Type must be the same for both votes
- BlockID must be different for both votes (BlockID can be for a nil block)
- Validator must have been in the validator set at that height
- Vote signature must be valid (using the chainID)
- For DuplicateVoteEvidence to be included in a block it must be within the time period outlined in [evidenceParams](../abci/abci.md#evidenceparams). Evidence expiration is measured as a combination of age in terms of height and time.
- Information required to form ABCI evidence (`TotalVotingPower`, `ValidatorPower` and `Timestamp`) must all match the nodes own state at that height.
### LightClientAttackEvidence
LightClientAttackEvidence is a generalized evidence that captures all forms of known attacks on
`LightClientAttackEvidence` is a generalized evidence that captures all forms of known attacks on
a light client such that a full node can verify, propose and commit the evidence on-chain for
punishment of the malicious validators. There are three forms of attacks: Lunatic, Equivocation
and Amnesia. These attacks are exhaustive. You can find a more detailed overview of this [here](../light-client/accountability#the_misbehavior_of_faulty_validators)
@ -368,23 +359,6 @@ and Amnesia. These attacks are exhaustive. You can find a more detailed overview
| TotalVotingPower | int64 | The total power of the validator set at the height of the infraction | Must be equal to the nodes own copy of the data |
| Timestamp | [Time](#Time) | Time of the block where the infraction occurred | Must be equal to the nodes own copy of the data |
Valid Light Client Attack Evidence must adhere to the following rules:
- If the header of the light block is invalid, thus indicating a lunatic attack, the node must check that
they can use `verifySkipping` from their header at the common height to the conflicting header
- If the header is valid, then the validator sets are the same and this is either a form of equivocation
or amnesia. We therefore check that 2/3 of the validator set also signed the conflicting header.
- The trusted header of the node at the same height as the conflicting header must have a different hash to
the conflicting header.
- The `ByzantineValidators` provided must be the overlap between validators in the common validator set and those that voted in the commit of the conflicting block.
- For LightClientAttackEvidence to be included in a block it must be within the time period outlined in [evidenceParams](../abci/abci.md#evidenceparams). Evidence expiration is measured as a combination of age in terms of height and time.
- Information required to form ABCI evidence (`TotalVotingPower` and `Timestamp`) must all match the nodes own state at that height.
## LightBlock
LightBlock is the core data structure of the [light client](../light-client/README.md). It combines two data structures needed for verification ([signedHeader](#signedheader) & [validatorSet](#validatorset)).


Loading…
Cancel
Save