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