github.com/MagHErmit/tendermint@v0.282.1/spec/light-client/detection/detection_003_reviewed.md (about) 1 # Light Client Attack Detector 2 3 In this specification, we strengthen the light client to be resistant 4 against so-called light client attacks. In a light client attack, all 5 the correct Tendermint full nodes agree on the sequence of generated 6 blocks (no fork), but a set of faulty full nodes attack a light client 7 by generating (signing) a block that deviates from the block of the 8 same height on the blockchain. In order to do so, some of these faulty 9 full nodes must have been validators before and violate the assumption 10 of more than two thirds of "correct voting power" 11 [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link], as otherwise, if 12 [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link] would hold, 13 [verification][verification] would satisfy 14 [[LCV-SEQ-SAFE.1]][LCV-SEQ-SAFE-link]. 15 16 An attack detector (or detector for short) is a mechanism that is used 17 by the light client [supervisor][supervisor] after 18 [verification][verification] of a new light block 19 with the primary, to cross-check the newly learned light block with 20 other peers (secondaries). It expects as input a light block with some 21 height *root* (that serves as a root of trust), and a verification 22 trace (a sequence of lightblocks) that the primary provided. 23 24 In case the detector observes a light client attack, it computes 25 evidence data that can be used by Tendermint full nodes to isolate a 26 set of faulty full nodes that are still within the unbonding period 27 (more than 1/3 of the voting power of the validator set at some block 28 of the chain), and report them via ABCI (application/blockchain 29 interface) 30 to the application of a 31 Tendermint blockchain in order to punish faulty nodes. 32 33 ## Context of this document 34 35 The light client [verification][verification] specification is 36 designed for the Tendermint failure model (1/3 assumption) 37 [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link]. It is safe under this 38 assumption, and live if it can reliably (that is, no message loss, no 39 duplication, and eventually delivered) and timely communicate with a 40 correct full node. If [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link] 41 assumption is violated, the light client can be fooled to trust a 42 light block that was not generated by Tendermint consensus. 43 44 This specification, the attack detector, is a "second line of 45 defense", in case the 1/3 assumption is violated. Its goal is to 46 detect a light client attack (conflicting light blocks) and collect 47 evidence. However, it is impractical to probe all full nodes. At this 48 time we consider a simple scheme of maintaining an address book of 49 known full nodes from which a small subset (e.g., 4) are chosen 50 initially to communicate with. More involved book keeping with 51 probabilistic guarantees can be considered at later stages of the 52 project. 53 54 The light client maintains a simple address book containing addresses 55 of full nodes that it can pick as primary and secondaries. To obtain 56 a new light block, the light client first does 57 [verification][verification] with the primary, and then cross-checks 58 the light block (and the trace of light blocks that led to it) with 59 the secondaries using this specification. 60 61 # Outline 62 63 - [Part I](#part-i---Tendermint-Consensus-and-Light-Client-Attacks): 64 Formal definitions of lightclient attacks, based on basic 65 properties of Tendermint consensus. 66 - [Node-based characterization of 67 attacks](#Node-based-characterization-of-attacks). The 68 definition of attacks used in the problem statement of 69 this specification. 70 71 - [Block-based characterization of attacks](#Block-based-characterization-of-attacks). Alternative definitions 72 provided for future reference. 73 74 - [Part II](#part-ii---problem-statement): Problem statement of 75 lightclient attack detection 76 77 - [Informal Problem Statement](#informal-problem-statement) 78 - [Assumptions](#Assumptions) 79 - [Definitions](#definitions) 80 - [Distributed Problem statement](#Distributed-Problem-statement) 81 82 - [Part III](#part-iii---protocol): The protocol 83 84 - [Functions and Data defined in other Specifications](#Functions-and-Data-defined-in-other-Specifications) 85 - [Outline of Solution](#Outline-of-solution) 86 - [Details of the functions](#Details-of-the-functions) 87 - [Correctness arguments](#Correctness-arguments) 88 89 # Part I - Tendermint Consensus and Light Client Attacks 90 91 In this section we will give some mathematical definitions of what we 92 mean by light client attacks (that are considered in this 93 specification) and how they differ from main-chain forks. To this end, 94 we start by defining some properties of the sequence of blocks that is 95 decided upon by Tendermint consensus in normal operation (if the 96 Tendermint failure model holds 97 [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link]), 98 and then define different 99 deviations that correspond to attack scenarios. We consider the notion 100 of [light blocks][LCV-LB-link] and [headers][LVC-HD-link]. 101 102 #### **[TMBC-GENESIS.1]** 103 104 Let *Genesis* be the agreed-upon initial block (file). 105 106 #### **[TMBC-FUNC-SIGN.1]** 107 108 Let *b* and *c* be two light blocks with *b.Header.Height + 1 = 109 c.Header.Height*. We define the predicate **signs(b,c)** to hold 110 iff *c.Header.LastCommit* is in *PossibleCommit(b)*. 111 [[TMBC-SOUND-DISTR-POSS-COMMIT.1]][TMBC-SOUND-DISTR-POSS-COMMIT-link]. 112 113 > The above encodes sequential verification, that is, intuitively, 114 > b.Header.NextValidators = c.Header.Validators and 2/3 of 115 > these Validators signed c. 116 117 #### **[TMBC-FUNC-SUPPORT.1]** 118 119 Let *b* and *c* be two light blocks. We define the predicate 120 **supports(b,c,t)** to hold iff 121 122 - *t - trustingPeriod < b.Header.Time < t* 123 - the voting power in *b.NextValidators* of nodes in *c.Commit* 124 is more than 1/3 of *TotalVotingPower(b.Header.NextValidators)* 125 126 > That is, if the [Tendermint failure model][TMBC-FM-2THIRDS-link] 127 > holds, then *c* has been signed by at least one correct full node, cf. 128 > [[TMBC-VAL-CONTAINS-CORR.1]][TMBC-VAL-CONTAINS-CORR-link]. 129 > The following formalizes that *b* was properly generated by 130 > Tendermint; *b* can be traced back to genesis. 131 132 #### **[TMBC-SEQ-ROOTED.1]** 133 134 Let *b* be a light block. 135 We define *sequ-rooted(b)* iff for all *i*, *1 <= i < h = b.Header.Height*, 136 there exist light blocks *a(i)* s.t. 137 138 - *a(1) = Genesis* and 139 - *a(h) = b* and 140 - *signs( a(i) , a(i+1) )*. 141 142 > The following formalizes that *c* is trusted based on *b* in 143 > skipping verification. Observe that we do not require here (yet) 144 > that *b* was properly generated. 145 146 #### **[TMBC-SKIP-TRACE.1]** 147 148 Let *b* and *c* be light blocks. We define *skip-trace(b,c,t)* if at 149 time t there exists an integer *h* and a sequence *a(1)*, ... *a(h)* s.t. 150 151 - *a(1) = b* and 152 - *a(h) = c* and 153 - *supports( a(i), a(i+1), t)*, for all i, *1 <= i < h*. 154 155 We call such a sequence *a(1)*, ... *a(h)* a **verification trace**. 156 157 > The following formalizes that two light blocks of the same height 158 > should agree on the content of the header. Observe that *b* and *c* 159 > may disagree on the Commit. This is a special case if the canonical 160 > commit has not been decided on yet, that is, if b.Header.Height is the 161 > maximum height of all blocks decided upon by Tendermint at this 162 > moment. 163 164 #### **[TMBC-SIGN-SKIP-MATCH.1]** 165 166 Let *a*, *b*, *c*, be light blocks and *t* a time, we define 167 *sign-skip-match(a,b,c,t) = true* iff the following implication 168 evaluates to true: 169 170 - *sequ-rooted(a)* and 171 - *b.Header.Height = c.Header.Height* and 172 - *skip-trace(a,b,t)* 173 - *skip-trace(a,c,t)* 174 175 implies *b.Header = c.Header*. 176 177 > Observe that *sign-skip-match* is defined via an implication. If it 178 > evaluates to false this means that the left-hand-side of the 179 > implication evaluates to true, and the right-hand-side evaluates to 180 > false. In particular, there are two **different** headers *b* and 181 > *c* that both can be verified from a common block *a* from the 182 > chain. Thus, the following describes an attack. 183 184 #### **[TMBC-ATTACK.1]** 185 186 If there exists three light blocks a, b, and c, with 187 *sign-skip-match(a,b,c,t) = false* then we have an *attack*. We say 188 we have **an attack at height** *b.Header.Height* and write 189 *attack(a,b,c,t)*. 190 191 > The lightblock *a* need not be unique, that is, there may be 192 > several blocks that satisfy the above requirement for the same 193 > blocks *b* and *c*. 194 195 [[TMBC-ATTACK.1]](#TMBC-ATTACK1) is a formalization of the violation 196 of the agreement property based on the result of consensus, that is, 197 the generated blocks. 198 199 **Remark.** 200 Violation of agreement is only possible if more than 1/3 of the validators (or 201 next validators) of some previous block deviated from the protocol. The 202 upcoming "accountability" specification will describe how to compute 203 a set of at least 1/3 faulty nodes from two conflicting blocks. [] 204 205 There are different ways to characterize forks 206 and attack scenarios. This specification uses the "node-based 207 characterization of attacks" which focuses on what kinds of nodes are 208 affected (light nodes vs. full nodes). For future reference and 209 discussion we also provide a 210 "block-based characterization of attacks" below. 211 212 ## Node-based characterization of attacks 213 214 #### **[TMBC-MC-FORK.1]** 215 216 We say there is a (main chain) fork at time *t* if 217 218 - there are two correct full nodes *i* and *j* and 219 - *i* is different from *j* and 220 - *i* has decided on *b* and 221 - *j* has decided on *c* and 222 - there exist *a* such that *attack(a,b,c,t)*. 223 224 #### **[TMBC-LC-ATTACK.1]** 225 226 We say there is a light client attack at time *t*, if 227 228 - there is **no** (main chain) fork [[TMBC-MC-FORK.1]](#TMBC-MC-FORK1), and 229 - there exist nodes that have computed light blocks *b* and *c* and 230 - there exist *a* such that *attack(a,b,c,t)*. 231 232 We say the attack is at height *a.Header.Height*. 233 234 > In this specification we consider detection of light client 235 > attacks. Intuitively, the case we consider is that 236 > light block *b* is the one from the 237 > blockchain, and some attacker has computed *c* and tries to wrongly 238 > convince 239 > the light client that *c* is the block from the chain. 240 241 #### **[TMBC-LC-ATTACK-EVIDENCE.1]** 242 243 We consider the following case of a light client attack 244 [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1): 245 246 - *attack(a,b,c,t)* 247 - there is a peer p1 that has a sequence *chain* of blocks from *a* to *b* 248 - *skip-trace(a,c,t)*: by [[TMBC-SKIP-TRACE.1]](#TMBC-SKIP-TRACE1) there is a 249 verification trace *v* of the form *a = v(1)*, ... *v(h) = c* 250 251 Evidence for p1 (that proves an attack to p1) consists for index i 252 of v(i) and v(i+1) such that 253 254 - E1(i). v(i) is equal to the block of *chain* at height v(i).Height, and 255 - E2(i). v(i+1) that is different from the block of *chain* at 256 height v(i+1).height 257 258 > Observe p1 can 259 > 260 > - check that v(i+1) differs from its block at that height, and 261 > - verify v(i+1) in one step from v(i) as v is a verification trace. 262 263 #### **[TMBC-LC-EVIDENCE-DATA.1]** 264 265 To prove the attack to p1, because of Point E1, it is sufficient to 266 submit 267 268 - v(i).Height (rather than v(i)). 269 - v(i+1) 270 271 This information is *evidence for height v(i).Height*. 272 273 ## Block-based characterization of attacks 274 275 In this section we provide a different characterization of attacks. It 276 is not defined on the nodes that are affected but purely on the 277 content of the blocks. In that sense these definitions are less 278 operational. 279 280 > They might be relevant for a closer analysis of fork scenarios on the 281 > chain, which is out of the scope of this specification. 282 283 #### **[TMBC-SIGN-UNIQUE.1]** 284 285 Let *b* and *c* be light blocks, we define the predicate 286 *sign-unique(b,c)* to evaluate to true iff the following implication 287 evaluates to true: 288 289 - *b.Header.Height = c.Header.Height* and 290 - *sequ-rooted(b)* and 291 - *sequ-rooted(c)* 292 293 implies *b = c*. 294 295 #### **[TMBC-BLOCKS-MCFORK.1]** 296 297 If there exists two light blocks b and c, with *sign-unique(b,c) = 298 false* then we have a *fork*. 299 300 > The difference of the above definition to 301 > [[TMBC-MC-FORK.1]](#TMBC-MC-FORK1) is subtle. The latter requires a 302 > full node being affected by a bad block while 303 > [[TMBC-BLOCKS-MCFORK.1]](#TMBC-BLOCKS-MCFORK1) just requires that a 304 > bad block exists, possibly in memory of an attacker. 305 > The following captures a light client fork. There is no fork up to 306 > the height of block b. However, c is of that height, is different, 307 > and passes skipping verification. It is a stricter property than 308 > [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1), as 309 > [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1) requires that no correct full 310 > node is affected. 311 312 #### **[TMBC-BLOCKS-LCFORK.1]** 313 314 Let *a*, *b*, *c*, be light blocks and *t* a time. We define 315 *light-client-fork(a,b,c,t)* iff 316 317 - *sign-skip-match(a,b,c,t) = false* and 318 - *sequ-rooted(b)* and 319 - *b* is "unique", that is, for all *d*, *sequ-rooted(d)* and 320 *d.Header.Height = b.Header.Height* implies *d = b* 321 322 > Finally, let us also define bogus blocks that have no support. 323 > Observe that bogus is even defined if there is a fork. 324 > Also, for the definition it would be sufficient to restrict *a* to 325 > *a.height < b.height* (which is implied by the definitions which 326 > unfold until *supports()*). 327 328 #### **[TMBC-BOGUS.1]** 329 330 Let *b* be a light block and *t* a time. We define *bogus(b,t)* iff 331 332 - *sequ-rooted(b) = false* and 333 - for all *a*, *sequ-rooted(a)* implies *skip-trace(a,b,t) = false* 334 335 # Part II - Problem Statement 336 337 ## Informal Problem statement 338 339 There is no sequential specification: the detector only makes sense 340 in a distributed systems where some nodes misbehave. 341 342 We work under the assumption that full nodes and validators are 343 responsible for detecting attacks on the main chain, and the evidence 344 reactor takes care of broadcasting evidence to communicate 345 misbehaving nodes via ABCI to the application, and halt the chain in 346 case of a fork. The point of this specification is to shield a light 347 clients against attacks that cannot be detected by full nodes, and 348 are fully addressed at light clients (and consequently IBC relayers, 349 which use the light client protocols to observe the state of a 350 blockchain). In order to provide full nodes the incentive to follow 351 the protocols when communicating with the light client, this 352 specification also considers the generation of evidence that will 353 also be processed by the Tendermint blockchain. 354 355 #### **[LCD-IP-MODEL.1]** 356 357 The detector is designed under the assumption that 358 359 - [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link] may be violated 360 - there is no fork on the main chain. 361 362 > As a result some faulty full nodes may launch an attack on a light 363 > client. 364 365 The following requirements are operational in that they describe how 366 things should be done, rather than what should be done. However, they 367 do not constitute temporal logic verification conditions. For those, 368 see [LCD-DIST-*] below. 369 370 The detector is called in the [supervisor][supervisor] as follows 371 372 ```go 373 Evidences := AttackDetector(root_of_trust, verifiedLS);` 374 ``` 375 376 where 377 378 - `root-of-trust` is a light block that is trusted (that is, 379 except upon initialization, the primary and the secondaries 380 agreed on in the past), and 381 - `verifiedLS` is a lightstore that contains a verification trace that 382 starts from a lightblock that can be verified with the 383 `root-of-trust` in one step and ends with a lightblock of the height 384 requested by the user 385 - `Evidences` is a list of evidences for misbehavior 386 387 #### **[LCD-IP-STATEMENT.1]** 388 389 Whenever AttackDetector is called, the detector should for each 390 secondary cross check the largest header in verifiedLS with the 391 corresponding header of the same height provided by the secondary. If 392 there is a deviation, the detector should 393 try to replay the verification trace `verifiedLS` with the 394 secondary 395 396 - in case replaying leads to detection of a light client attack 397 (one of the lightblocks differ from the one in verifiedLS with 398 the same height), we should return evidence 399 - if the secondary cannot provide a verification trace, we have no 400 proof for an attack. Block *b* may be bogus. In this case the 401 secondary is faulty and it should be replaced. 402 403 ## Assumptions 404 405 It is not in the interest of faulty full nodes to talk to the 406 detector as long as the detector is connected to at least one 407 correct full node. This would only increase the likelihood of 408 misbehavior being detected. Also we cannot punish them easily 409 (cheaply). The absence of a response need not be the fault of the full 410 node. 411 412 Correct full nodes have the incentive to respond, because the 413 detector may help them to understand whether their header is a good 414 one. We can thus base liveness arguments of the detector on 415 the assumptions that correct full nodes reliably talk to the 416 detector. 417 418 #### **[LCD-A-CorrFull.1]** 419 420 At all times there is at least one correct full 421 node among the primary and the secondaries. 422 423 > For this version of the detection we take this assumption. It 424 > allows us to establish the invariant that the lightblock 425 > `root-of-trust` is always the one from the blockchain, and we can 426 > use it as starting point for the evidence computation. Moreover, it 427 > allows us to establish the invariant at the supervisor that any 428 > lightblock in the (top-level) lightstore is from the blockchain. 429 > In the future we might design a lightclient based on the assumption 430 > that at least in regular intervals the lightclient is connected to a 431 > correct full node. This will require the detector to reconsider 432 > `root-of-trust`, and remove lightblocks from the top-level 433 > lightstore. 434 435 #### **[LCD-A-RelComm.1]** 436 437 Communication between the detector and a correct full node is 438 reliable and bounded in time. Reliable communication means that 439 messages are not lost, not duplicated, and eventually delivered. There 440 is a (known) end-to-end delay *Delta*, such that if a message is sent 441 at time *t* then it is received and processed by time *t + Delta*. 442 This implies that we need a timeout of at least *2 Delta* for remote 443 procedure calls to ensure that the response of a correct peer arrives 444 before the timeout expires. 445 446 ## Definitions 447 448 ### Evidence 449 450 Following the definition of 451 [[TMBC-LC-ATTACK-EVIDENCE.1]](#TMBC-LC-ATTACK-EVIDENCE1), by evidence 452 we refer to a variable of the following type 453 454 #### **[LC-DATA-EVIDENCE.1]** 455 456 ```go 457 type LightClientAttackEvidence struct { 458 ConflictingBlock LightBlock 459 CommonHeight int64 460 461 // Evidence also includes application specific data which is not 462 // part of verification but is sent to the application once the 463 // evidence gets committed on chain. 464 } 465 ``` 466 467 As the above data is computed for a specific peer, the following 468 data structure wraps the evidence and adds the peerID. 469 470 #### **[LC-DATA-EVIDENCE-INT.1]** 471 472 ```go 473 type InternalEvidence struct { 474 Evidence LightClientAttackEvidence 475 Peer PeerID 476 } 477 ``` 478 479 #### **[LC-SUMBIT-EVIDENCE.1]** 480 481 ```go 482 func submitEvidence(Evidences []InternalEvidence) 483 ``` 484 485 - Expected postcondition 486 - for each `ev` in `Evidences`: submit `ev.Evidence` to `ev.Peer` 487 488 --- 489 490 ### LightStore 491 492 Lightblocks and LightStores are defined in the verification 493 specification [[LCV-DATA-LIGHTBLOCK.1]][LCV-LB-link] 494 and [[LCV-DATA-LIGHTSTORE.2]][LCV-LS-link]. See 495 the [verification specification][verification] for details. 496 497 ## Distributed Problem statement 498 499 > As the attack detector is there to reduce the impact of faulty 500 > nodes, and faulty nodes imply that there is a distributed system, 501 > there is no sequential specification to which this distributed 502 > problem statement may refer to. 503 504 The detector gets as input a trusted lightblock called *root* and an 505 auxiliary lightstore called *primary_trace* with lightblocks that have 506 been verified before, and that were provided by the primary. 507 508 #### **[LCD-DIST-INV-ATTACK.1]** 509 510 If the detector returns evidence for height *h* 511 [[TMBC-LC-EVIDENCE-DATA.1]](#TMBC-LC-EVIDENCE-DATA1), then there is an 512 attack at height *h*. [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1) 513 514 #### **[LCD-DIST-INV-STORE.1]** 515 516 If the detector does not return evidence, then *primary_trace* 517 contains only blocks from the blockchain. 518 519 #### **[LCD-DIST-LIVE.1]** 520 521 The detector eventually terminates. 522 523 #### **[LCD-DIST-TERM-NORMAL.1]** 524 525 If 526 527 - the *primary_trace* contains only blocks from the blockchain, and 528 - there is no attack, and 529 - *Secondaries* is always non-empty, and 530 - the age of *root* is always less than the trusting period, 531 532 then the detector does not return evidence. 533 534 #### **[LCD-DIST-TERM-ATTACK.1]** 535 536 If 537 538 - there is an attack, and 539 - a secondary reports a block that conflicts 540 with one of the blocks in *primary_trace*, and 541 - *Secondaries* is always non-empty, and 542 - the age of *root* is always less than the trusting period, 543 544 then the detector returns evidence. 545 546 > Observe that above we require that "a secondary reports a block that 547 > conflicts". If there is an attack, but no secondary tries to launch 548 > it against the detector (or the message from the secondary is lost 549 > by the network), then there is nothing to detect for us. 550 551 #### **[LCD-DIST-SAFE-SECONDARY.1]** 552 553 No correct secondary is ever replaced. 554 555 #### **[LCD-DIST-SAFE-BOGUS.1]** 556 557 If 558 559 - a secondary reports a bogus lightblock, 560 - the age of *root* is always less than the trusting period, 561 562 then the secondary is replaced before the detector terminates. 563 564 > The above property is quite operational (e.g., the usage of 565 > "reports"), but it captures closely the requirement. As the 566 > detector only makes sense in a distributed setting, and does not 567 > have a sequential specification, a less "pure" specification are 568 > acceptable. 569 570 # Part III - Protocol 571 572 ## Functions and Data defined in other Specifications 573 574 ### From the [supervisor][supervisor] 575 576 [[LC-FUNC-REPLACE-SECONDARY.1]][repl] 577 578 ```go 579 Replace_Secondary(addr Address, root-of-trust LightBlock) 580 ``` 581 582 ### From the [verifier][verification] 583 584 [[LCV-FUNC-MAIN.2]][vtt] 585 586 ```go 587 func VerifyToTarget(primary PeerID, root LightBlock, 588 targetHeight Height) (LightStore, Result) 589 ``` 590 591 Observe that `VerifyToTarget` does communication with the secondaries 592 via the function [FetchLightBlock][fetch]. 593 594 ### Shared data of the light client 595 596 - a pool of full nodes *FullNodes* that have not been contacted before 597 - peer set called *Secondaries* 598 - primary 599 600 > Note that the lightStore is not needed to be shared. 601 602 ## Outline of solution 603 604 The problem laid out is solved by calling the function `AttackDetector` 605 with a lightstore that contains a light block that has just been 606 verified by the verifier. 607 608 Then `AttackDetector` downloads headers from the secondaries. In case 609 a conflicting header is downloaded from a secondary, it calls 610 `CreateEvidenceForPeer` which computes evidence in the case that 611 indeed an attack is confirmed. It could be that the secondary reports 612 a bogus block, which means that there need not be an attack, and the 613 secondary is replaced. 614 615 ## Details of the functions 616 617 #### **[LCD-FUNC-DETECTOR.2]:** 618 619 ```go 620 func AttackDetector(root LightBlock, primary_trace []LightBlock) 621 ([]InternalEvidence) { 622 623 Evidences := new []InternalEvidence; 624 625 for each secondary in Secondaries { 626 lb, result := FetchLightBlock(secondary,primary_trace.Latest().Header.Height); 627 if result != ResultSuccess { 628 Replace_Secondary(root); 629 } 630 else if lb.Header != primary_trace.Latest().Header { 631 632 // we replay the primary trace with the secondary, in 633 // order to generate evidence that we can submit to the 634 // secondary. We return the evidence + the trace the 635 // secondary told us that spans the evidence at its local store 636 637 EvidenceForSecondary, newroot, secondary_trace, result := 638 CreateEvidenceForPeer(secondary, 639 root, 640 primary_trace); 641 if result == FaultyPeer { 642 Replace_Secondary(root); 643 } 644 else if result == FoundEvidence { 645 // the conflict is not bogus 646 Evidences.Add(EvidenceForSecondary); 647 // we replay the secondary trace with the primary, ... 648 EvidenceForPrimary, _, result := 649 CreateEvidenceForPeer(primary, 650 newroot, 651 secondary_trace); 652 if result == FoundEvidence { 653 Evidences.Add(EvidenceForPrimary); 654 } 655 // At this point we do not care about the other error 656 // codes. We already have generated evidence for an 657 // attack and need to stop the lightclient. It does not 658 // help to call replace_primary. Also we will use the 659 // same primary to check with other secondaries in 660 // later iterations of the loop 661 } 662 // In the case where the secondary reports NoEvidence 663 // after initially it reported a conflicting header. 664 // secondary is faulty 665 Replace_Secondary(root); 666 } 667 } 668 return Evidences; 669 } 670 ``` 671 672 - Expected precondition 673 - root and primary trace are a verification trace 674 - Expected postcondition 675 - solves the problem statement (if attack found, then evidence is reported) 676 - Error condition 677 - `ErrorTrustExpired`: fails if root expires (outside trusting 678 period) [[LCV-INV-TP.1]][LCV-INV-TP1-link] 679 - `ErrorNoPeers`: if no peers are left to replace secondaries, and 680 no evidence was found before that happened 681 682 --- 683 684 ```go 685 func CreateEvidenceForPeer(peer PeerID, root LightBlock, trace LightStore) 686 (Evidence, LightBlock, LightStore, result) { 687 688 common := root; 689 690 for i in 1 .. len(trace) { 691 auxLS, result := VerifyToTarget(peer, common, trace[i].Header.Height) 692 693 if result != ResultSuccess { 694 // something went wrong; peer did not provide a verifiable block 695 return (nil, nil, nil, FaultyPeer) 696 } 697 else { 698 if auxLS.LatestVerified().Header != trace[i].Header { 699 // the header reported by the peer differs from the 700 // reference header in trace but both could be 701 // verified from common in one step. 702 // we can create evidence for submission to the secondary 703 ev := new InternalEvidence; 704 ev.Evidence.ConflictingBlock := trace[i]; 705 // CommonHeight is used to indicate the type of attack 706 // if the CommonHeight != ConflictingBlock.Height this 707 // is by definition a lunatic attack else it is an 708 // equivocation attack 709 ev.Evidence.CommonHeight := common.Height; 710 ev.Peer := peer 711 return (ev, common, auxLS, FoundEvidence) 712 } 713 else { 714 // the peer agrees with the trace, we move common forward. 715 // we could delete auxLS as it will be overwritten in 716 // the next iteration 717 common := trace[i] 718 } 719 } 720 } 721 return (nil, nil, nil, NoEvidence) 722 } 723 ``` 724 725 - Expected precondition 726 - root and trace are a verification trace 727 - Expected postcondition 728 - finds evidence where trace and peer diverge 729 - Error condition 730 - `ErrorTrustExpired`: fails if root expires (outside trusting 731 period) [[LCV-INV-TP.1]][LCV-INV-TP1-link] 732 - If `VerifyToTarget` returns error but root is not expired then return 733 `FaultyPeer` 734 735 --- 736 737 ## Correctness arguments 738 739 #### On the existence of evidence 740 741 **Proposition.** In the case of attack, 742 evidence [[TMBC-LC-ATTACK-EVIDENCE.1]](#TMBC-LC-ATTACK-EVIDENCE1) 743 exists. 744 *Proof.* First observe that 745 746 - (A). (NOT E2(i)) implies E1(i+1) 747 748 Now by contradiction assume there is no evidence. Thus 749 750 - for all i, we have NOT E1(i) or NOT E2(i) 751 - for i = 1 we have E1(1) and thus NOT E2(1) 752 thus by induction on i, by (A) we have for all i that **E1(i)** 753 - from attack we have E2(h-1), and as there is no evidence for 754 i = h - 1 we get **NOT E1(h-1)**. Contradiction. 755 QED. 756 757 #### Argument for [[LCD-DIST-INV-ATTACK.1]](#LCD-DIST-INV-ATTACK1) 758 759 Under the assumption that root and trace are a verification trace, 760 when in `CreateEvidenceForPeer` the detector creates 761 evidence, then the lightclient has seen two different headers (one via 762 `trace` and one via `VerifyToTarget`) for the same height that can both 763 be verified in one step. 764 765 #### Argument for [[LCD-DIST-INV-STORE.1]](#LCD-DIST-INV-STORE1) 766 767 We assume that there is at least one correct peer, and there is no 768 fork. As a result, the correct peer has the correct sequence of 769 blocks. Since the primary_trace is checked block-by-block also against 770 each secondary, and at no point evidence was generated that means at 771 no point there were conflicting blocks. 772 773 #### Argument for [[LCD-DIST-LIVE.1]](#LCD-DIST-LIVE1) 774 775 At the latest when [[LCV-INV-TP.1]][LCV-INV-TP1-link] is violated, 776 `AttackDetector` terminates. 777 778 #### Argument for [[LCD-DIST-TERM-NORMAL.1]](#LCD-DIST-TERM-NORMAL1) 779 780 As there are finitely many peers, eventually the main loop 781 terminates. As there is no attack no evidence can be generated. 782 783 #### Argument for [[LCD-DIST-TERM-ATTACK.1]](#LCD-DIST-TERM-ATTACK1) 784 785 Argument similar to [[LCD-DIST-TERM-NORMAL.1]](#LCD-DIST-TERM-NORMAL1) 786 787 #### Argument for [[LCD-DIST-SAFE-SECONDARY.1]](#LCD-DIST-SAFE-SECONDARY1) 788 789 Secondaries are only replaced if they time-out or if they report bogus 790 blocks. The former is ruled out by the timing assumption, the latter 791 by correct peers only reporting blocks from the chain. 792 793 #### Argument for [[LCD-DIST-SAFE-BOGUS.1]](#LCD-DIST-SAFE-BOGUS1) 794 795 Once a bogus block is recognized as such the secondary is removed. 796 797 # References 798 799 > links to other specifications/ADRs this document refers to 800 801 [[verification]] The specification of the light client verification. 802 803 [[supervisor]] The specification of the light client supervisor. 804 805 [verification]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md 806 807 [supervisor]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/supervisor/supervisor_001_draft.md 808 809 [block]: https://github.com/tendermint/spec/blob/d46cd7f573a2c6a2399fcab2cde981330aa63f37/spec/core/data_structures.md 810 811 [TMBC-FM-2THIRDS-link]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-fm-2thirds1 812 813 [TMBC-SOUND-DISTR-POSS-COMMIT-link]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-sound-distr-poss-commit1 814 815 [LCV-SEQ-SAFE-link]:https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-seq-safe1 816 817 [TMBC-VAL-CONTAINS-CORR-link]: 818 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-val-contains-corr1 819 820 [fetch]: 821 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-func-fetch1 822 823 [LCV-INV-TP1-link]: 824 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-inv-tp1 825 826 [LCV-LB-link]: 827 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-data-lightblock1 828 829 [LCV-LS-link]: 830 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-data-lightstore2 831 832 [LVC-HD-link]: 833 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-header-fields2 834 835 [repl]: 836 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/supervisor/supervisor_001_draft.md#lc-func-replace-secondary1 837 838 [vtt]: 839 https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-func-main2