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

     1  <!-- markdown-link-check-disable -->
     2  
     3  # Light Client Verification
     4  
     5  The light client implements a read operation of a
     6  [header][TMBC-HEADER-link] from the [blockchain][TMBC-SEQ-link], by
     7  communicating with full nodes.  As some full nodes may be faulty, this
     8  functionality must be implemented in a fault-tolerant way.
     9  
    10  In the Tendermint blockchain, the validator set may change with every
    11  new block.  The staking and unbonding mechanism induces a [security
    12  model][TMBC-FM-2THIRDS-link]: starting at time *Time* of the
    13  [header][TMBC-HEADER-link],
    14  more than two-thirds of the next validators of a new block are correct
    15  for the duration of *TrustedPeriod*. The fault-tolerant read
    16  operation is designed for this security model.
    17  
    18  The challenge addressed here is that the light client might have a
    19  block of height *h1* and needs to read the block of height *h2*
    20  greater than *h1*.  Checking all headers of heights from *h1* to *h2*
    21  might be too costly (e.g., in terms of energy for mobile devices).
    22  This specification tries to reduce the number of intermediate blocks
    23  that need to be checked, by exploiting the guarantees provided by the
    24  [security model][TMBC-FM-2THIRDS-link].
    25  
    26  # Status
    27  
    28  ## Previous Versions
    29  
    30  - [[001_published]](./verification_001_published.md)
    31   is thoroughly reviewed, and the protocol has been
    32  formalized in TLA+ and model checked.
    33  
    34  ## Issues that are addressed in this revision
    35  
    36  As it is part of the larger light node, its data structures and
    37  functions interact with the attack dectection functionality of the light
    38  client. As a result of the work on
    39  
    40  - [attack detection](https://github.com/tendermint/spec/pull/164) for light nodes
    41  
    42  - attack detection for IBC and [relayer requirements](https://github.com/informalsystems/tendermint-rs/issues/497)
    43  
    44  - light client
    45    [supervisor](https://github.com/tendermint/spec/pull/159) (also in
    46    [Rust proposal](https://github.com/informalsystems/tendermint-rs/pull/509))
    47    
    48  adaptations to the semantics and functions exposed by the LightStore
    49  needed to be made. In contrast to [version
    50  001](./verification_001_published.md) we specify the following:
    51  
    52  - `VerifyToTarget` and `Backwards` are called with a single lightblock
    53    as root of trust in contrast to passing the complete lightstore.
    54  
    55  - During verification, we record for each lightblock which other
    56    lightblock can be used to verify it in one step. This is needed to
    57    generate verification traces that are needed for IBC.
    58    
    59  # Outline
    60  
    61  - [Part I](#part-i---tendermint-blockchain): Introduction of
    62   relevant terms of the Tendermint
    63  blockchain.
    64  
    65  - [Part II](#part-ii---sequential-definition-of-the-verification-problem): Introduction
    66  of the problem addressed by the Lightclient Verification protocol.
    67      - [Verification Informal Problem
    68        statement](#Verification-Informal-Problem-statement): For the general
    69        audience, that is, engineers who want to get an overview over what
    70        the component is doing from a bird's eye view.
    71      - [Sequential Problem statement](#Sequential-Problem-statement):
    72        Provides a mathematical definition of the problem statement in
    73        its sequential form, that is, ignoring the distributed aspect of
    74        the implementation of the blockchain.
    75  
    76  - [Part III](#part-iii---light-client-as-distributed-system): Distributed
    77    aspects of the light client, system assumptions and temporal
    78    logic specifications.
    79  
    80      - [Incentives](#incentives): how faulty full nodes may benefit from
    81      misbehaving and how correct full nodes benefit from cooperating.
    82    
    83      - [Computational Model](#Computational-Model):
    84        timing and correctness assumptions.
    85  
    86      - [Distributed Problem Statement](#Distributed-Problem-Statement):
    87        temporal properties that formalize safety and liveness
    88        properties in the distributed setting.
    89  
    90  - [Part IV](#part-iv---light-client-verification-protocol):
    91    Specification of the protocols.
    92  
    93      - [Definitions](#Definitions): Describes inputs, outputs,
    94         variables used by the protocol, auxiliary functions
    95  
    96      - [Core Verification](#core-verification): gives an outline of the solution,
    97         and details of the functions used (with preconditions,
    98         postconditions, error conditions).
    99  
   100      - [Liveness Scenarios](#liveness-scenarios): when the light
   101         client makes progress depends heavily on the changes in the
   102         validator sets of the blockchain. We discuss some typical scenarios.
   103  
   104  - [Part V](#part-v---supporting-the-ibc-relayer): The above parts
   105    focus on a common case where the last verified block has height *h1*
   106    and the
   107    requested height *h2* satisfies *h2 > h1*. For IBC, there are
   108    scenarios where this might not be the case. In this part, we provide
   109    some preliminaries for supporting this. As not all details of the
   110    IBC requirements are clear by now, we do not provide a complete
   111    specification at this point. We mark with "Open Question" points
   112    that need to be addressed in order to finalize this specification.
   113    It should be noted that the technically
   114    most challenging case is the one specified in Part IV.
   115  
   116  In this document we quite extensively use tags in order to be able to
   117  reference assumptions, invariants, etc. in future communication. In
   118  these tags we frequently use the following short forms:
   119  
   120  - TMBC: Tendermint blockchain
   121  - SEQ: for sequential specifications
   122  - LCV: Lightclient Verification
   123  - LIVE: liveness
   124  - SAFE: safety
   125  - FUNC: function
   126  - INV: invariant
   127  - A: assumption
   128  
   129  # Part I - Tendermint Blockchain
   130  
   131  ## Header Fields necessary for the Light Client
   132  
   133  #### **[TMBC-HEADER.1]**
   134  
   135  A set of blockchain transactions is stored in a data structure called
   136  *block*, which contains a field called *header*. (The data structure
   137  *block* is defined [here][block]).  As the header contains hashes to
   138  the relevant fields of the block, for the purpose of this
   139  specification, we will assume that the blockchain is a list of
   140  headers, rather than a list of blocks.
   141  
   142  #### **[TMBC-HASH-UNIQUENESS.1]**
   143  
   144  We assume that every hash in the header identifies the data it hashes.
   145  Therefore, in this specification, we do not distinguish between hashes and the
   146  data they represent.
   147  
   148  #### **[TMBC-HEADER-FIELDS.2]**
   149  
   150  A header contains the following fields:
   151  
   152  - `Height`: non-negative integer
   153  - `Time`: time (non-negative integer)
   154  - `LastBlockID`: Hashvalue
   155  - `LastCommit` DomainCommit
   156  - `Validators`: DomainVal
   157  - `NextValidators`: DomainVal
   158  - `Data`: DomainTX
   159  - `AppState`: DomainApp
   160  - `LastResults`: DomainRes
   161  
   162  #### **[TMBC-SEQ.1]**
   163  
   164  The Tendermint blockchain is a list *chain* of headers.
   165  
   166  #### **[TMBC-VALIDATOR-PAIR.1]**
   167  
   168  Given a full node, a
   169  *validator pair* is a pair *(peerID, voting_power)*, where
   170  
   171  - *peerID* is the PeerID (public key) of a full node,
   172  - *voting_power* is an integer (representing the full node's
   173    voting power in a certain consensus instance).
   174    
   175  > In the Golang implementation the data type for *validator
   176  pair* is called `Validator`
   177  
   178  #### **[TMBC-VALIDATOR-SET.1]**
   179  
   180  A *validator set* is a set of validator pairs. For a validator set
   181  *vs*, we write *TotalVotingPower(vs)* for the sum of the voting powers
   182  of its validator pairs.
   183  
   184  #### **[TMBC-VOTE.1]**
   185  
   186  A *vote* contains a `prevote` or `precommit` message sent and signed by
   187  a validator node during the execution of [consensus][arXiv]. Each
   188  message contains the following fields
   189  
   190  - `Type`: prevote or precommit
   191  - `Height`: positive integer
   192  - `Round` a positive integer
   193  - `BlockID` a Hashvalue of a block (not necessarily a block of the chain)
   194  
   195  #### **[TMBC-COMMIT.1]**
   196  
   197  A commit is a set of `precommit` message.
   198  
   199  ## Tendermint Failure Model
   200  
   201  #### **[TMBC-AUTH-BYZ.1]**
   202  
   203  We assume the authenticated Byzantine fault model in which no node (faulty or
   204  correct) may break digital signatures, but otherwise, no additional
   205  assumption is made about the internal behavior of faulty
   206  nodes. That is, faulty nodes are only limited in that they cannot forge
   207  messages.
   208  
   209  #### **[TMBC-TIME-PARAMS.1]**
   210  
   211  A Tendermint blockchain has the following configuration parameters:
   212  
   213  - *unbondingPeriod*: a time duration.
   214  - *trustingPeriod*: a time duration smaller than *unbondingPeriod*.
   215  
   216  #### **[TMBC-CORRECT.1]**
   217  
   218  We define a predicate *correctUntil(n, t)*, where *n* is a node and *t* is a
   219  time point.
   220  The predicate *correctUntil(n, t)* is true if and only if the node *n*
   221  follows all the protocols (at least) until time *t*.
   222  
   223  #### **[TMBC-FM-2THIRDS.1]**
   224  
   225  If a block *h* is in the chain,
   226  then there exists a subset *CorrV*
   227  of *h.NextValidators*, such that:
   228  
   229  - *TotalVotingPower(CorrV) > 2/3
   230      TotalVotingPower(h.NextValidators)*; cf. [TMBC-VALIDATOR-SET.1]
   231  - For every validator pair *(n,p)* in *CorrV*, it holds *correctUntil(n,
   232      h.Time + trustingPeriod)*; cf. [TMBC-CORRECT.1]
   233  
   234  > The definition of correct
   235  > [**[TMBC-CORRECT.1]**][TMBC-CORRECT-link] refers to realtime, while it
   236  > is used here with *Time* and *trustingPeriod*, which are "hardware
   237  > times".  We do not make a distinction here.
   238  
   239  #### **[TMBC-CORR-FULL.1]**
   240  
   241  Every correct full node locally stores a prefix of the
   242  current list of headers from [**[TMBC-SEQ.1]**][TMBC-SEQ-link].
   243  
   244  ## What the Light Client Checks
   245  
   246  > From [TMBC-FM-2THIRDS.1] we directly derive the following observation:
   247  
   248  #### **[TMBC-VAL-CONTAINS-CORR.1]**
   249  
   250  Given a (trusted) block *tb* of the blockchain, a given set of full nodes
   251  *N* contains a correct node at a real-time *t*, if
   252  
   253  - *t - trustingPeriod < tb.Time < t*
   254  - the voting power in tb.NextValidators of nodes in *N* is more
   255       than 1/3 of *TotalVotingPower(tb.NextValidators)*
   256  
   257  > The following describes how a commit for a given block *b* must look
   258  > like.
   259  
   260  #### **[TMBC-SOUND-DISTR-POSS-COMMIT.1]**
   261  
   262  For a block *b*, each element *pc* of *PossibleCommit(b)* satisfies:
   263  
   264  - *pc* contains only votes (cf. [TMBC-VOTE.1])
   265    by validators from *b.Validators*
   266  - the sum of the voting powers in *pc* is greater than 2/3
   267    *TotalVotingPower(b.Validators)*
   268  - and there is an *r* such that  each vote *v* in *pc* satisfies
   269      - v.Type = precommit
   270      - v.Height = b.Height
   271      - v.Round = r
   272      - v.blockID = hash(b)
   273  
   274  > The following property comes from the validity of the [consensus][arXiv]: A
   275  > correct validator node only sends `prevote` or `precommit`, if
   276  > `BlockID` of the new (to-be-decided) block is equal to the hash of
   277  > the last block.
   278  
   279  #### **[TMBC-VAL-COMMIT.1]**
   280  
   281  If for a block *b*,  a commit *c*
   282  
   283  - contains at least one validator pair *(v,p)* such that *v* is a
   284      **correct** validator node, and
   285  - is contained in *PossibleCommit(b)*
   286    
   287  then the block *b* is on the blockchain.
   288  
   289  ## Context of this document
   290  
   291  In this document we specify the light client verification component,
   292  called *Core Verification*.  The *Core Verification* communicates with
   293  a full node.  As full nodes may be faulty, it cannot trust the
   294  received information, but the light client has to check whether the
   295  header it receives coincides with the one generated by Tendermint
   296  consensus.
   297  
   298  The two
   299   properties [[TMBC-VAL-CONTAINS-CORR.1]][TMBC-VAL-CONTAINS-CORR-link] and
   300  [[TMBC-VAL-COMMIT]][TMBC-VAL-COMMIT-link]  formalize the checks done
   301   by this specification:
   302  Given a trusted block *tb* and an untrusted block *ub* with a commit *cub*,
   303  one has to check that *cub* is in *PossibleCommit(ub)*, and that *cub*
   304  contains a correct node using *tb*.
   305  
   306  # Part II - Sequential Definition of the Verification Problem
   307  
   308  ## Verification Informal Problem statement
   309  
   310  Given a height *targetHeight* as an input, the *Verifier* eventually
   311  stores a header *h* of height *targetHeight* locally.  This header *h*
   312  is generated by the Tendermint [blockchain][block]. In
   313  particular, a header that was not generated by the blockchain should
   314  never be stored.
   315  
   316  ## Sequential Problem statement
   317  
   318  #### **[LCV-SEQ-LIVE.1]**
   319  
   320  The *Verifier* gets as input a height *targetHeight*, and eventually stores the
   321  header of height *targetHeight* of the blockchain.
   322  
   323  #### **[LCV-SEQ-SAFE.1]**
   324  
   325  The *Verifier* never stores a header which is not in the blockchain.
   326  
   327  # Part III - Light Client as Distributed System
   328  
   329  ## Incentives
   330  
   331  Faulty full nodes may benefit from lying to the light client, by making the
   332  light client accept a block that deviates (e.g., contains additional
   333  transactions) from the one generated by Tendermint consensus.
   334  Users using the light client might be harmed by accepting a forged header.
   335  
   336  The [attack detector][attack-detector] of the light client may help the
   337  correct full nodes to understand whether their header is a good one.
   338  Hence, in combination with the light client detector, the correct full
   339  nodes have the incentive to respond.  We can thus base liveness
   340  arguments on the assumption that correct full nodes reliably talk to
   341  the light client.
   342  
   343  ## Computational Model
   344  
   345  #### **[LCV-A-PEER.1]**
   346  
   347  The verifier communicates with a full node called *primary*. No assumption is made about the full node (it may be correct or faulty).
   348  
   349  #### **[LCV-A-COMM.1]**
   350  
   351  Communication between the light client and a correct full node is
   352  reliable and bounded in time. Reliable communication means that
   353  messages are not lost, not duplicated, and eventually delivered. There
   354  is a (known) end-to-end delay *Delta*, such that if a message is sent
   355  at time *t* then it is received and processes by time *t + Delta*.
   356  This implies that we need a timeout of at least *2 Delta* for remote
   357  procedure calls to ensure that the response of a correct peer arrives
   358  before the timeout expires.
   359  
   360  #### **[LCV-A-TFM.1]**
   361  
   362  The Tendermint blockchain satisfies the Tendermint failure model [**[TMBC-FM-2THIRDS.1]**][TMBC-FM-2THIRDS-link].
   363  
   364  #### **[LCV-A-VAL.1]**
   365  
   366  The system satisfies [**[TMBC-AUTH-BYZ.1]**][TMBC-Auth-Byz-link] and
   367  [**[TMBC-FM-2THIRDS.1]**][TMBC-FM-2THIRDS-link]. Thus, there is a
   368  blockchain that satisfies the soundness requirements (that is, the
   369  validation rules in [[block]]).
   370  
   371  ## Distributed Problem Statement
   372  
   373  ### Two Kinds of Termination
   374  
   375  We do not assume that *primary* is correct. Under this assumption no
   376  protocol can guarantee the combination of the sequential
   377  properties. Thus, in the (unreliable) distributed setting, we consider
   378  two kinds of termination (successful and failure) and we will specify
   379  below under what (favorable) conditions *Core Verification* ensures to
   380  terminate successfully, and satisfy the requirements of the sequential
   381  problem statement:
   382  
   383  #### **[LCV-DIST-TERM.1]**
   384  
   385  *Core Verification* either *terminates
   386  successfully* or it *terminates with failure*.
   387  
   388  ### Design choices
   389  
   390  #### **[LCV-DIST-STORE.2]**
   391  
   392  *Core Verification* returns a data structure called *LightStore* that
   393  contains light blocks (that contain a header).
   394  
   395  #### **[LCV-DIST-INIT.2]**
   396  
   397  *Core Verification* is called with
   398  
   399  - *primary*: the PeerID of a full node (with verification communicates)
   400  - *root*: a light block (the root of trust)
   401  - *targetHeight*: a height (the height of a header that should be obtained)
   402  
   403  ### Temporal Properties
   404  
   405  #### **[LCV-DIST-SAFE.2]**
   406  
   407  It is always the case that every header in *LightStore* was
   408  generated by an instance of Tendermint consensus.
   409  
   410  #### **[LCV-DIST-LIVE.2]**
   411  
   412  If a new instance of *Core Verification* is called with a
   413  height *targetHeight* greater than root.Header.Height it must
   414  must eventually terminate.
   415  
   416  - If
   417      - the  *primary* is correct (and locally has the block of
   418         *targetHeight*), and
   419      - the age of root is always less than the trusting period,  
   420      then *Core Verification* adds a verified header *hd* with height
   421      *targetHeight* to *LightStore* and it **terminates successfully**
   422  
   423  > These definitions imply that if the primary is faulty, a header may or
   424  > may not be added to *LightStore*. In any case,
   425  > [**[LCV-DIST-SAFE.2]**](#lcv-dist-safe2) must hold.
   426  > The invariant [**[LCV-DIST-SAFE.2]**](#lcv-dist-safe2) and the liveness
   427  > requirement [**[LCV-DIST-LIVE.2]**](#lcv-dist-life)
   428  > allow that verified headers are added to *LightStore* whose
   429  > height was not passed
   430  > to the verifier (e.g., intermediate headers used in bisection; see below).
   431  > Note that for liveness, initially having a *root* within
   432  > the *trustinPeriod* is not sufficient. However, as this
   433  > specification will leave some freedom with respect to the strategy
   434  > in which order to download intermediate headers, we do not give a
   435  > more precise liveness specification here. After giving the
   436  > specification of the protocol, we will discuss some liveness
   437  > scenarios [below](#liveness-scenarios).
   438  
   439  ### Solving the sequential specification
   440  
   441  This specification provides a partial solution to the sequential specification.
   442  The *Verifier* solves the invariant of the sequential part
   443  
   444  [**[LCV-DIST-SAFE.2]**](#lcv-dist-safe2) => [**[LCV-SEQ-SAFE.1]**](#lcv-seq-safe1)
   445  
   446  In the case the primary is correct, and *root*  is a recent header in *LightStore*, the verifier satisfies the liveness requirements.
   447  
   448  ⋀ *primary is correct*  
   449  ⋀ *root.header.Time* > *now* - *trustingPeriod*  
   450  ⋀ [**[LCV-A-Comm.1]**](#lcv-a-comm) ⋀ (
   451         ( [**[TMBC-CorrFull.1]**][TMBC-CorrFull-link] ⋀
   452           [**[LCV-DIST-LIVE.2]**](#lcv-dist-live2) )
   453         ⟹ [**[LCV-SEQ-LIVE.1]**](#lcv-seq-live1)
   454  )
   455  
   456  # Part IV - Light Client Verification Protocol
   457  
   458  We provide a specification for Light Client Verification. The local
   459  code for verification is presented by a sequential function
   460  `VerifyToTarget` to highlight the control flow of this functionality.
   461  We note that if a different concurrency model is considered for
   462  an implementation, the sequential flow of the function may be
   463  implemented with mutexes, etc. However, the light client verification
   464  is partitioned into three blocks that can be implemented and tested
   465  independently:
   466  
   467  - `FetchLightBlock` is called to download a light block (header) of a
   468    given height from a peer.
   469  - `ValidAndVerified` is a local code that checks the header.
   470  - `Schedule` decides which height to try to verify next. We keep this
   471    underspecified as different implementations (currently in Goland and
   472    Rust) may implement different optimizations here. We just provide
   473    necessary conditions on how the height may evolve.
   474    
   475  <!-- > `ValidAndVerified` is the function that is sometimes called "Light -->
   476  <!-- > Client" in the IBC context. -->
   477  
   478  ## Definitions
   479  
   480  ### Data Types
   481  
   482  The core data structure of the protocol is the LightBlock.
   483  
   484  #### **[LCV-DATA-LIGHTBLOCK.1]**
   485  
   486  ```go
   487  type LightBlock struct {
   488    Header          Header
   489    Commit          Commit
   490    Validators      ValidatorSet
   491  }
   492  ```
   493  
   494  #### **[LCV-DATA-LIGHTSTORE.2]**
   495  
   496  LightBlocks are stored in a structure which stores all LightBlock from
   497  initialization or received from peers.
   498  
   499  ```go
   500  type LightStore struct {
   501   ...
   502  }
   503  
   504  ```
   505  
   506  #### **[LCV-DATA-LS-ROOT.2]**
   507  
   508  For each lightblock in a lightstore we record in a field `verification-root` of
   509  type Height.
   510  
   511  > `verification-root` records the height of a lightblock that can be used to verify
   512  > the lightblock in one step
   513  
   514  #### **[LCV-INV-LS-ROOT.2]**
   515  
   516  At all times, if a lightblock *b* in a lightstore has *b.verification-root = h*,
   517  then
   518  
   519  - the lightstore contains a lightblock with height *h*, or
   520  - *b* has the minimal height of all lightblocks in lightstore, then
   521    b.verification-root should be nil.
   522  
   523  The LightStore exposes the following functions to query stored LightBlocks.
   524  
   525  #### **[LCV-DATA-LS-STATE.1]**
   526  
   527  Each LightBlock is in one of the following states:
   528  
   529  ```go
   530  type VerifiedState int
   531  
   532  const (
   533   StateUnverified = iota + 1
   534   StateVerified
   535   StateFailed
   536   StateTrusted
   537  )
   538  ```
   539  
   540  #### **[LCV-FUNC-GET.1]**
   541  
   542  ```go
   543  func (ls LightStore) Get(height Height) (LightBlock, bool)
   544  ```
   545  
   546  - Expected postcondition
   547      - returns a LightBlock at a given height or false in the second argument if
   548      the LightStore does not contain the specified LightBlock.
   549  
   550  #### **[LCV-FUNC-LATEST.1]**
   551  
   552  ```go
   553  func (ls LightStore) Latest() LightBlock
   554  ```
   555  
   556  - Expected postcondition
   557      - returns the highest light block
   558  
   559  #### **[LCV-FUNC-ADD.1]**
   560  
   561  ```go
   562  func (ls LightStore) Add(newBlock)
   563  ```
   564  
   565  - Expected precondition
   566      - the lightstore is empty
   567  - Expected postcondition
   568      - adds newBlock into light store
   569  
   570  #### **[LCV-FUNC-STORE.1]**
   571  
   572  ```go
   573  func (ls LightStore) store_chain(newLS LightStore)
   574  ```
   575  
   576  - Expected postcondition
   577      - adds `newLS` to the lightStore.
   578  
   579  #### **[LCV-FUNC-LATEST-VERIF.2]**
   580  
   581  ```go
   582  func (ls LightStore) LatestVerified() LightBlock
   583  ```
   584  
   585  - Expected postcondition
   586      - returns the highest light block whose state is `StateVerified`
   587  
   588  #### **[LCV-FUNC-FILTER.1]**
   589  
   590  ```go
   591  func (ls LightStore) FilterVerified() LightStore
   592  ```
   593  
   594  - Expected postcondition
   595      - returns all the lightblocks of the lightstore with state `StateVerified`
   596  
   597  #### **[LCV-FUNC-UPDATE.2]**
   598  
   599  ```go
   600  func (ls LightStore) Update(lightBlock LightBlock, verfiedState
   601  VerifiedState, root-height Height)
   602  ```
   603  
   604  - Expected postcondition
   605      - the lightblock is part of the lightstore
   606      - The state of the LightBlock is set to *verifiedState*.
   607      - The verification-root of the LightBlock is set to *root-height*
   608  
   609  ```go
   610  func (ls LightStore) TraceTo(lightBlock LightBlock) (LightBlock, LightStore)
   611  ```
   612  
   613  - Expected postcondition
   614      - returns a **trusted** lightblock `root` from the lightstore with a height
   615        less than `lightBlock`
   616      - returns a lightstore that contains lightblocks that constitute a
   617        [verification trace](TODOlinkToDetectorSpecOnceThere) from
   618        `root` to `lightBlock` (including `lightBlock`)
   619  
   620  ### Inputs
   621  
   622  - *root*: A light block that is trusted
   623  - *primary*: peerID
   624  - *targetHeight*: the height of the needed header
   625  
   626  ### Configuration Parameters
   627  
   628  - *trustThreshold*: a float. Can be used if correctness should not be based on more voting power and 1/3.
   629  - *trustingPeriod*: a time duration [**[TMBC-TIME_PARAMS.1]**][TMBC-TIME_PARAMS-link].
   630  - *clockDrift*: a time duration. Correction parameter dealing with only approximately synchronized clocks.
   631  
   632  ### Variables
   633  
   634  - *nextHeight*: initially *targetHeight*
   635    > *nextHeight* should be thought of the "height of the next header we need
   636    > to download and verify"
   637  
   638  ### Assumptions
   639  
   640  #### **[LCV-A-INIT.2]**
   641  
   642  - *root* is from the blockchain
   643  
   644  - *targetHeight > root.Header.Height*
   645  
   646  ### Invariants
   647  
   648  #### **[LCV-INV-TP.1]**
   649  
   650  It is always the case that *LightStore.LatestTrusted.Header.Time > now - trustingPeriod*.
   651  
   652  > If the invariant is violated, the light client does not have a
   653  > header it can trust. A trusted header must be obtained externally,
   654  > its trust can only be based on social consensus.  
   655  > We use the convention that root is assumed to be verified.
   656  
   657  ### Used Remote Functions
   658  
   659  We use the functions `commit` and `validators` that are provided
   660  by the [RPC client for Tendermint][RPC].
   661  
   662  ```go
   663  func Commit(height int64) (SignedHeader, error)
   664  ```
   665  
   666  - Implementation remark
   667      - RPC to full node *n*
   668      - JSON sent:
   669  
   670  ```javascript
   671  // POST /commit
   672  {
   673   "jsonrpc": "2.0",
   674   "id": "ccc84631-dfdb-4adc-b88c-5291ea3c2cfb", // UUID v4, unique per request
   675   "method": "commit",
   676   "params": {
   677    "height": 1234
   678   }
   679  }
   680  ```
   681  
   682  - Expected precondition
   683      - header of `height` exists on blockchain
   684  - Expected postcondition
   685      - if *n* is correct: Returns the signed header of height `height`
   686    from the blockchain if communication is timely (no timeout)
   687      - if *n* is faulty: Returns a signed header with arbitrary content
   688  - Error condition
   689      - if *n* is correct: precondition violated or timeout
   690      - if *n* is faulty: arbitrary error
   691  
   692  ----;
   693  
   694  ```go
   695  func Validators(height int64) (ValidatorSet, error)
   696  ```
   697  
   698  - Implementation remark
   699      - RPC to full node *n*
   700      - JSON sent:
   701  
   702  ```javascript
   703  // POST /validators
   704  {
   705   "jsonrpc": "2.0",
   706   "id": "ccc84631-dfdb-4adc-b88c-5291ea3c2cfb", // UUID v4, unique per request
   707   "method": "validators",
   708   "params": {
   709    "height": 1234
   710   }
   711  }
   712  ```
   713  
   714  - Expected precondition
   715      - header of `height` exists on blockchain
   716  - Expected postcondition
   717      - if *n* is correct: Returns the validator set of height `height`
   718    from the blockchain if communication is timely (no timeout)
   719      - if *n* is faulty: Returns arbitrary validator set
   720  - Error condition
   721      - if *n* is correct: precondition violated or timeout
   722      - if *n* is faulty: arbitrary error
   723  
   724  ----;
   725  
   726  ### Communicating Function
   727  
   728  #### **[LCV-FUNC-FETCH.1]**
   729  
   730    ```go
   731  func FetchLightBlock(peer PeerID, height Height) LightBlock
   732  ```
   733  
   734  - Implementation remark
   735      - RPC to peer at *PeerID*
   736      - calls `Commit` for *height* and `Validators` for *height* and *height+1*
   737  - Expected precondition
   738      - `height` is less than or equal to height of the peer **[LCV-IO-PRE-HEIGHT.1]**
   739  - Expected postcondition:
   740      - if *node* is correct:
   741          - Returns the LightBlock *lb* of height `height`
   742        that is consistent with the blockchain
   743          - *lb.provider = peer* **[LCV-IO-POST-PROVIDER.1]**
   744          - *lb.Header* is a header consistent with the blockchain
   745          - *lb.Validators* is the validator set of the blockchain at height *nextHeight*
   746          - *lb.NextValidators* is the validator set of the blockchain at height *nextHeight + 1*
   747      - if *node* is faulty: Returns a LightBlock with arbitrary content
   748      [**[TMBC-AUTH-BYZ.1]**][TMBC-Auth-Byz-link]
   749  - Error condition
   750      - if *n* is correct: precondition violated
   751      - if *n* is faulty: arbitrary error
   752      - if *lb.provider != peer*
   753      - times out after 2 Delta (by assumption *n* is faulty)
   754  
   755  ----;
   756  
   757  ## Core Verification
   758  
   759  ### Outline
   760  
   761  The `VerifyToTarget` is the main function and uses the following functions.
   762  
   763  - `FetchLightBlock` is called to download the next light block. It is
   764    the only function that communicates with other nodes
   765  - `ValidAndVerified` checks whether header is valid and checks if a
   766    new lightBlock should be trusted
   767    based on a previously verified lightBlock.
   768  - `Schedule` decides which height to try to verify next
   769  
   770  In the following description of `VerifyToTarget` we do not deal with error
   771  handling. If any of the above function returns an error, VerifyToTarget just
   772  passes the error on.
   773  
   774  #### **[LCV-FUNC-MAIN.2]**
   775  
   776  ```go
   777  func VerifyToTarget(primary PeerID, root LightBlock,
   778                      targetHeight Height) (LightStore, Result) {
   779  
   780      lightStore = new LightStore;
   781      lightStore.Update(root, StateVerified, root.verifiedBy);
   782      nextHeight := targetHeight;
   783  
   784      for lightStore.LatestVerified.height < targetHeight {
   785  
   786          // Get next LightBlock for verification
   787          current, found := lightStore.Get(nextHeight)
   788          if !found {
   789              current = FetchLightBlock(primary, nextHeight)
   790              lightStore.Update(current, StateUnverified, nil)
   791          }
   792  
   793          // Verify
   794          verdict = ValidAndVerified(lightStore.LatestVerified, current)
   795  
   796          // Decide whether/how to continue
   797          if verdict == SUCCESS {
   798              lightStore.Update(current, StateVerified, lightStore.LatestVerified.Height)
   799          }
   800          else if verdict == NOT_ENOUGH_TRUST {
   801              // do nothing
   802              // the light block current passed validation, but the validator
   803              // set is too different to verify it. We keep the state of
   804              // current at StateUnverified. For a later iteration, Schedule
   805              // might decide to try verification of that light block again.
   806          }
   807          else {
   808              // verdict is some error code
   809              lightStore.Update(current, StateFailed, nil)
   810              return (nil, ResultFailure)
   811          }
   812          nextHeight = Schedule(lightStore, nextHeight, targetHeight)
   813      }
   814      return (lightStore.FilterVerified, ResultSuccess)
   815  }
   816  ```
   817  
   818  - Expected precondition
   819      - *root* is within the *trustingPeriod*  **[LCV-PRE-TP.1]**
   820      - *targetHeight* is greater than the height of *root*
   821  - Expected postcondition:
   822      - returns *lightStore* that contains a LightBlock that corresponds to a block
   823       of the blockchain of height *targetHeight*
   824       (that is, the LightBlock has been added to *lightStore*) **[LCV-POST-LS.1]**
   825  - Error conditions
   826      - if the precondition is violated
   827      - if `ValidAndVerified` or `FetchLightBlock` report an error
   828      - if [**[LCV-INV-TP.1]**](#LCV-INV-TP.1) is violated
   829    
   830  ### Details of the Functions
   831  
   832  #### **[LCV-FUNC-VALID.2]**
   833  
   834  ```go
   835  func ValidAndVerified(trusted LightBlock, untrusted LightBlock) Result
   836  ```
   837  
   838  - Expected precondition:
   839      - *untrusted* is valid, that is, satisfies the soundness [checks][block]
   840      - *untrusted* is **well-formed**, that is,
   841          - *untrusted.Header.Time < now + clockDrift*
   842          - *untrusted.Validators = hash(untrusted.Header.Validators)*
   843          - *untrusted.NextValidators = hash(untrusted.Header.NextValidators)*
   844      - *trusted.Header.Time > now - trustingPeriod*
   845      - the `Height` and `Time` of `trusted` are smaller than the Height and
   846    `Time` of `untrusted`, respectively
   847      - the *untrusted.Header* is well-formed (passes the tests from
   848       [[block]]), and in particular
   849          - if the untrusted header `unstrusted.Header` is the immediate
   850     successor  of  `trusted.Header`, then it holds that
   851              - *trusted.Header.NextValidators =
   852      untrusted.Header.Validators*, and
   853      moreover,
   854              - *untrusted.Header.Commit*
   855                  - contains signatures by more than two-thirds of the validators
   856                  - contains no signature from nodes that are not in *trusted.Header.NextValidators*
   857  - Expected postcondition:
   858      - Returns `SUCCESS`:
   859          - if *untrusted* is the immediate successor of *trusted*, or otherwise,
   860          - if the signatures of a set of validators that have more than
   861               *max(1/3,trustThreshold)* of voting power in
   862               *trusted.Nextvalidators* is contained in
   863               *untrusted.Commit* (that is, header passes the tests
   864               [**[TMBC-VAL-CONTAINS-CORR.1]**][TMBC-VAL-CONTAINS-CORR-link]
   865               and [**[TMBC-VAL-COMMIT.1]**][TMBC-VAL-COMMIT-link])
   866      - Returns `NOT_ENOUGH_TRUST` if:
   867          - *untrusted* is *not* the immediate successor of
   868             *trusted*
   869       and the  *max(1/3,trustThreshold)* threshold is not reached
   870             (that is, if
   871        [**[TMBC-VAL-CONTAINS-CORR.1]**][TMBC-VAL-CONTAINS-CORR-link]
   872        fails and header is does not violate the soundness
   873           checks [[block]]).
   874  - Error condition:
   875      - if precondition violated
   876  
   877  ----;
   878  
   879  #### **[LCV-FUNC-SCHEDULE.1]**
   880  
   881  ```go
   882  func Schedule(lightStore, nextHeight, targetHeight) Height
   883  ```
   884  
   885  - Implementation remark: If picks the next height to be verified.
   886    We keep the precise choice of the next header under-specified. It is
   887    subject to performance optimizations that do not influence the correctness
   888  - Expected postcondition: **[LCV-SCHEDULE-POST.1]**
   889     Return *H* s.t.
   890     1. if *lightStore.LatestVerified.Height = nextHeight* and
   891        *lightStore.LatestVerified < targetHeight* then  
   892     *nextHeight < H <= targetHeight*
   893     2. if *lightStore.LatestVerified.Height < nextHeight* and
   894        *lightStore.LatestVerified.Height < targetHeight* then  
   895     *lightStore.LatestVerified.Height < H < nextHeight*
   896     3. if *lightStore.LatestVerified.Height = targetHeight* then  
   897       *H =  targetHeight*
   898  
   899  > Case i. captures the case where the light block at height *nextHeight*
   900  > has been verified, and we can choose a height closer to the *targetHeight*.
   901  > As we get the *lightStore* as parameter, the choice of the next height can
   902  > depend on the *lightStore*, e.g., we can pick a height for which we have
   903  > already downloaded a light block.
   904  > In Case ii. the header of *nextHeight* could not be verified, and we need to pick a smaller height.
   905  > In Case iii. is a special case when we have verified the *targetHeight*.
   906  
   907  ### Solving the distributed specification
   908  
   909  Analogous to [[001_published]](./verification_001_published.md#solving-the-distributed-specification)
   910  
   911  ## Liveness Scenarios
   912  
   913  Analogous to [[001_published]](./verification_001_published.md#liveness-scenarios)
   914  
   915  # Part V - Supporting the IBC Relayer
   916  
   917  The above specification focuses on the most common case, which also
   918  constitutes the most challenging task: using the Tendermint [security
   919  model][TMBC-FM-2THIRDS-link] to verify light blocks without
   920  downloading all intermediate blocks. To focus on this challenge, above
   921  we have restricted ourselves to the case where  *targetHeight* is
   922  greater than the height of any trusted header. This simplified
   923  presentation of the algorithm as initially
   924  `lightStore.LatestVerified()` is less than *targetHeight*, and in the
   925  process of verification `lightStore.LatestVerified()` increases until
   926  *targetHeight* is reached.
   927  
   928  For [IBC][ibc-rs] there are two additional challenges:
   929  
   930  1. it might be that some "older" header is needed, that is,
   931  *targetHeight < lightStore.LatestVerified()*.  The
   932  [supervisor](../supervisor/supervisor.md) checks whether it is in this
   933  case by calling `LatestPrevious` and `MinVerified` and if so it calls
   934  `Backwards`. All these functions are specified below.
   935  
   936  2. In order to submit proof of a light client attack, a relayer may
   937     need to submit a verification trace. This it is important to
   938     compute such a trace efficiently. That it can be done is based on
   939     the invariant [[LCV-INV-LS-ROOT.2]](#LCV-INV-LS-ROOT2) that needs
   940     to be maintained by the light client. In particular
   941     `VerifyToTarget` and `Backwards` need to take care of setting
   942     `verification-root`.
   943  
   944  #### **[LCV-FUNC-LATEST-PREV.2]**
   945  
   946  ```go
   947  func (ls LightStore) LatestPrevious(height Height) (LightBlock, bool)
   948  ```
   949  
   950  - Expected postcondition
   951      - returns a light block *lb* that satisfies:
   952          - *lb* is in lightStore
   953          - *lb* is in StateTrusted
   954          - *lb* is not expired
   955          - *lb.Header.Height < height*
   956          - for all *b* in lightStore s.t. *b* is trusted and not expired it
   957            holds *lb.Header.Height >= b.Header.Height*
   958      - *false* in the second argument if
   959        the LightStore does not contain such an *lb*.
   960  
   961  ----;
   962  
   963  #### **[LCV-FUNC-LOWEST.2]**
   964  
   965  ```go
   966  func (ls LightStore) Lowest() (LightBlock)
   967  ```
   968  
   969  - Expected postcondition
   970      - returns the lowest trusted light block within trusting period
   971  
   972  ----;
   973  
   974  #### **[LCV-FUNC-MIN.2]**
   975  
   976  ```go
   977  func (ls LightStore) MinVerified() (LightBlock, bool)
   978  ```
   979  
   980  - Expected postcondition
   981      - returns a light block *lb* that satisfies:
   982          - *lb* is in lightStore
   983          - *lb.Header.Height* is minimal in the lightStore
   984      - *false* in the second argument if
   985        the LightStore does not contain such an *lb*.
   986  
   987  If a height that is smaller than the smallest height in the lightstore
   988  is required, we check the hashes backwards. This is done with the
   989  following function:
   990  
   991  #### **[LCV-FUNC-BACKWARDS.2]**
   992  
   993  ```go
   994  func Backwards (primary PeerID, root LightBlock, targetHeight Height)
   995                 (LightStore, Result) {
   996    
   997      lb := root;
   998      lightStore := new LightStore;
   999      lightStore.Update(lb, StateTrusted, lb.verifiedBy)
  1000  
  1001      latest := lb.Header
  1002      for i := lb.Header.height - 1; i >= targetHeight; i-- {
  1003          // here we download height-by-height. We might first download all
  1004          // headers down to targetHeight and then check them.
  1005          current := FetchLightBlock(primary,i)
  1006          if (hash(current) != latest.Header.LastBlockId) {
  1007              return (nil, ResultFailure)
  1008          }
  1009          else {
  1010              // latest and current are linked together by LastBlockId
  1011              // therefore it is not relevant which we verified first
  1012              // for consistency, we store latest was veried using
  1013              // current so that the verifiedBy is always pointing down
  1014              // the chain
  1015              lightStore.Update(current, StateTrusted, nil)
  1016              lightStore.Update(latest, StateTrusted, current.Header.Height)
  1017          }
  1018          latest = current
  1019      }
  1020      return (lightStore, ResultSuccess)
  1021  }
  1022  ```
  1023  
  1024  # References
  1025  
  1026  [[block]] Specification of the block data structure.
  1027  
  1028  [[RPC]] RPC client for Tendermint
  1029  
  1030  [[attack-detector]] The specification of the light client attack detector.
  1031  
  1032  [[fullnode]] Specification of the full node API
  1033  
  1034  [[ibc-rs]] Rust implementation of IBC modules and relayer.
  1035  
  1036  [[lightclient]] The light client ADR [77d2651 on Dec 27, 2019].
  1037  
  1038  [RPC]: https://docs.tendermint.com/master/rpc/
  1039  
  1040  [block]: https://github.com/tendermint/spec/blob/d46cd7f573a2c6a2399fcab2cde981330aa63f37/spec/core/data_structures.md
  1041  
  1042  [TMBC-HEADER-link]: #tmbc-header1
  1043  [TMBC-SEQ-link]: #tmbc-seq1
  1044  [TMBC-CorrFull-link]: #tmbc-corr-full1
  1045  [TMBC-Auth-Byz-link]: #tmbc-auth-byz1
  1046  [TMBC-TIME_PARAMS-link]: #tmbc-time-params1
  1047  [TMBC-FM-2THIRDS-link]: #tmbc-fm-2thirds1
  1048  [TMBC-VAL-CONTAINS-CORR-link]: #tmbc-val-contains-corr1
  1049  [TMBC-VAL-COMMIT-link]: #tmbc-val-commit1
  1050  [TMBC-SOUND-DISTR-POSS-COMMIT-link]: #tmbc-sound-distr-poss-commit1
  1051  
  1052  [lightclient]: https://github.com/interchainio/tendermint-rs/blob/e2cb9aca0b95430fca2eac154edddc9588038982/docs/architecture/adr-002-lite-client.md
  1053  [attack-detector]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/detection/detection_001_reviewed.md
  1054  [fullnode]: https://github.com/tendermint/spec/blob/master/spec/blockchain/fullnode.md
  1055  
  1056  [ibc-rs]:https://github.com/informalsystems/ibc-rs
  1057  
  1058  [blockchain-validator-set]: https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md#data-structures
  1059  [fullnode-data-structures]: https://github.com/tendermint/spec/blob/master/spec/blockchain/fullnode.md#data-structures
  1060  
  1061  [FN-ManifestFaulty-link]: https://github.com/tendermint/spec/blob/master/spec/blockchain/fullnode.md#fn-manifestfaulty
  1062  
  1063  [arXiv]: https://arxiv.org/abs/1807.04938