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