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

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