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

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