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

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