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