You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
8.8 KiB

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