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.