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