github.com/aakash4dev/cometbft@v0.38.2/spec/light-client/detection/detection_001_reviewed.md (about)

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