github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/docs/architecture/adr-047-handling-evidence-from-light-client.md (about)

     1  # ADR 047: Handling evidence from light client
     2  
     3  ## Changelog
     4  * 18-02-2020: Initial draft
     5  * 24-02-2020: Second version
     6  * 13-04-2020: Add PotentialAmnesiaEvidence and a few remarks
     7  
     8  ## Context
     9  
    10  If the light client is under attack, either directly -> lunatic/phantom
    11  validators (light fork) or indirectly -> full fork, it's supposed to halt and
    12  send evidence of misbehavior to a correct full node. Upon receiving an
    13  evidence, the full node should punish malicious validators (if possible).
    14  
    15  ## Decision
    16  
    17  When a light client sees two conflicting headers (`H1.Hash() != H2.Hash()`,
    18  `H1.Height == H2.Height`), both having 1/3+ of the voting power of the
    19  currently trusted validator set, it will submit a `ConflictingHeadersEvidence`
    20  to all full nodes it's connected to. Evidence needs to be submitted to all full
    21  nodes since there's no way to determine which full node is correct (honest).
    22  
    23  ```go
    24  type ConflictingHeadersEvidence struct {
    25    H1 types.SignedHeader
    26    H2 types.SignedHeader
    27  }
    28  ```
    29  
    30  _Remark_: Theoretically, only the header, which differs from what a full node
    31  has, needs to be sent. But sending two headers a) makes evidence easily
    32  verifiable b) simplifies the light client, which does not have query each
    33  witness as to which header it possesses.
    34  
    35  When a full node receives the `ConflictingHeadersEvidence` evidence, it should
    36  a) validate it b) figure out if malicious behaviour is obvious (immediately
    37  slashable) or the fork accountability protocol needs to be started.
    38  
    39  ### Validating headers
    40  
    41  Check both headers are valid (`ValidateBasic`), have the same height, and
    42  signed by 1/3+ of the validator set that the full node had at height
    43  `H1.Height`.
    44  
    45  - Q: What if light client validator set is not equal to full node's validator
    46    set (i.e. from full node's point of view both headers are not properly signed;
    47    this includes the case where none of the two headers were committed on the
    48    main chain)
    49  
    50    Reject the evidence. It means light client is following a fork, but, hey, at
    51    least it will halt.
    52  
    53  - Q: Don't we want to punish validators who signed something else even if they
    54    have less or equal than 1/3?
    55  
    56    No consensus so far. Ethan said no, Zarko said yes.
    57    https://github.com/tendermint/spec/pull/71#discussion_r374210533
    58  
    59  ### Figuring out if malicious behaviour is immediately slashable
    60  
    61  Let's say H1 was committed from this full node's perspective (see Appendix A).
    62  _If neither of the headers (H1 and H2) were committed from the full node's
    63  perspective, the evidence must be rejected._
    64  
    65  Intersect validator sets of H1 and H2.
    66  
    67  * if there are signers(H2) that are not part of validators(H1), they misbehaved as
    68  they are signing protocol messages in heights they are not validators =>
    69  immediately slashable (#F4).
    70  
    71  * if `H1.Round == H2.Round`, and some signers signed different precommit
    72  messages in both commits, then it is an equivocation misbehavior => immediately
    73  slashable (#F1).
    74  
    75  * if `H1.Round != H2.Round` we need to run full detection procedure => not
    76  immediately slashable.
    77  
    78  * if `ValidatorsHash`, `NextValidatorsHash`, `ConsensusHash`,
    79  `AppHash`, and `LastResultsHash` in H2 are different (incorrect application
    80  state transition), then it is a lunatic misbehavior => immediately slashable (#F5).
    81  
    82  If evidence is not immediately slashable, fork accountability needs to invoked
    83  (ADR does not yet exist).
    84  
    85  It's unclear if we should further break up `ConflictingHeadersEvidence` or
    86  gossip and commit it directly. See
    87  https://github.com/franono/tendermint/issues/4182#issuecomment-590339233
    88  
    89  If we'd go without breaking evidence, all we'll need to do is to strip the
    90  committed header from `ConflictingHeadersEvidence` (H1) and leave only the
    91  uncommitted header (H2):
    92  
    93  ```go
    94  type ConflictingHeaderEvidence struct {
    95    H types.SignedHeader
    96  }
    97  ```
    98  
    99  If we'd go with breaking evidence, here are the types we'll need:
   100  
   101  ### F1. Equivocation
   102  
   103  Existing `DuplicateVoteEvidence` needs to be created and gossiped.
   104  
   105  ### F4. Phantom validators
   106  
   107  A new type of evidence needs to be created:
   108  
   109  ```go
   110  type PhantomValidatorEvidence struct {
   111  	Header                      types.Header
   112  	Vote                        types.Vote
   113  	LastHeightValidatorWasInSet int64
   114  }
   115  ```
   116  
   117  It contains a validator's public key and a vote for a block, where this
   118  validator is not part of the validator set. `LastHeightValidatorWasInSet`
   119  indicates the last height validator was in the validator set.
   120  
   121  ### F5. Lunatic validator
   122  
   123  ```go
   124  type LunaticValidatorEvidence struct {
   125  	Header             types.Header
   126  	Vote               types.Vote
   127  	InvalidHeaderField string
   128  }
   129  ```
   130  
   131  To punish this attack, we need support for a new Evidence type -
   132  `LunaticValidatorEvidence`. This type includes a vote and a header. The header
   133  must contain fields that are invalid with respect to the previous block, and a
   134  vote for that header by a validator that was in a validator set within the
   135  unbonding period. While the attack is only possible if +1/3 of some validator
   136  set colludes, the evidence should be verifiable independently for each
   137  individual validator. This means the total evidence can be split into one piece
   138  of evidence per attacking validator and gossipped to nodes to be verified one
   139  piece at a time, reducing the DoS attack surface at the peer layer.
   140  
   141  Note it is not sufficient to simply compare this header with that committed for
   142  the corresponding height, as an honest node may vote for a header that is not
   143  ultimately committed. Certain fields may also be variable, for instance the
   144  `LastCommitHash` and the `Time` may depend on which votes the proposer includes.
   145  Thus, the header must be explicitly checked for invalid data.
   146  
   147  For the attack to succeed, VC must sign a header that changes the validator set
   148  to consist of something they control. Without doing this, they can not
   149  otherwise attack the light client, since the client verifies commits according
   150  to validator sets. Thus, it should be sufficient to check only that
   151  `ValidatorsHash` and `NextValidatorsHash` are correct with respect to the
   152  header that was committed at the corresponding height.
   153  
   154  That said, if the attack is conducted by +2/3 of the validator set, they don't
   155  need to make an invalid change to the validator set, since they already control
   156  it. Instead they would make invalid changes to the `AppHash`, or possibly other
   157  fields. In order to punish them, then, we would have to check all header
   158  fields.
   159  
   160  Note some header fields require the block itself to verify, which the light
   161  client, by definition, does not possess, so it may not be possible to check
   162  these fields. For now, then, `LunaticValidatorEvidence` must be checked against
   163  all header fields which are a function of the application at previous blocks.
   164  This includes `ValidatorsHash`, `NextValidatorsHash`, `ConsensusHash`,
   165  `AppHash`, and `LastResultsHash`. These should all match what's in the header
   166  for the block that was actually committed at the corresponding height, and
   167  should thus be easy to check.
   168  
   169  `InvalidHeaderField` contains the invalid field name. Note it's very likely
   170  that multiple fields diverge, but it's faster to check just one. This field
   171  MUST NOT be used to determine equality of `LunaticValidatorEvidence`.
   172  
   173  ### F2. Amnesia
   174  
   175  ```go
   176  type PotentialAmnesiaEvidence struct {
   177  	VoteA types.Vote
   178  	VoteB types.Vote
   179  }
   180  ```
   181  
   182  To punish this attack, votes under question needs to be sent. Fork
   183  accountability process should then use this evidence to request additional
   184  information from offended validators and construct a new type of evidence to
   185  punish those who conducted an amnesia attack.
   186  
   187  See ADR-056 for the architecture of the fork accountability procedure.
   188  
   189  ## Status
   190  
   191  Proposed.
   192  
   193  ## Consequences
   194  
   195  ### Positive
   196  
   197  * Tendermint will be able to detect & punish new types of misbehavior
   198  * light clients connected to multiple full nodes can help full nodes notice a
   199    fork faster
   200  
   201  ### Negative
   202  
   203  * Accepting `ConflictingHeadersEvidence` from light clients opens up a DDOS
   204  attack vector (same is fair for any RPC endpoint open to public; remember that
   205  RPC is not open by default).
   206  
   207  ### Neutral
   208  
   209  ## References
   210  
   211  * [Fork accountability spec](https://github.com/tendermint/spec/blob/master/spec/consensus/light-client/accountability.md)
   212  
   213  ## Appendix A
   214  
   215  If there is an actual fork (full fork), a full node may follow either one or
   216  another branch. So both H1 or H2 can be considered committed depending on which
   217  branch the full node is following. It's supposed to halt if it notices an
   218  actual fork, but there's a small chance it doesn't.