github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/spec/light-client/detection/detection_001_reviewed.md (about)

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