github.com/vipernet-xyz/tm@v0.34.24/spec/light-client/detection/detection_001_reviewed.md (about)

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