github.com/MagHErmit/tendermint@v0.282.1/spec/light-client/supervisor/supervisor_002_draft.md (about)

     1  # Draft of Light Client Supervisor for discussion
     2  
     3  ## Modification to the initialization
     4  
     5  The lightclient is initialized with LCInitData
     6  
     7  ### **[LC-DATA-INIT.2]**
     8  
     9  ```go
    10  type LCInitData struct {
    11      TrustedBlock   LightBlock
    12      Genesis        GenesisDoc
    13      TrustedHash    []byte
    14      TrustedHeight  int64
    15  }
    16  ```
    17  
    18  where only one of the components must be provided. `GenesisDoc` is
    19  defined in the [Tendermint
    20  Types](https://github.com/MagHErmit/tendermint/blob/v0.34.x/types/genesis.go).
    21  
    22  
    23  ### Initialization
    24  
    25  The light client is based on subjective initialization. It has to
    26  trust the initial data given to it by the user. It cannot perform any
    27  detection of an attack yet instead requires an initial point of trust.
    28  There are three forms of initial data which are used to obtain the
    29  first trusted block:
    30  
    31  - A trusted block from a prior initialization
    32  - A trusted height and hash
    33  - A genesis file
    34  
    35  The golang light client implementation checks this initial data in that
    36  order; first attempting to find a trusted block from the trusted store,
    37  then acquiring a light block from the primary at the trusted height and matching
    38  the hash, or finally checking for a genesis file to verify the initial header.
    39  
    40  The light client doesn't need to check if the trusted block is within the
    41  trusted period because it already trusts it, however, if the light block is
    42  outside the trust period, there is a higher chance the light client won't be
    43  able to verify anything.
    44  
    45  Cross-checking this trusted block with providers upon initialization is helpful
    46  for ensuring that the node is responsive and correctly configured but does not
    47  increase trust since proving a conflicting block is a
    48  [light client attack](https://github.com/MagHErmit/tendermint/blob/v0.34.x/spec/light-client/detection/detection_003_reviewed.md#tmbc-lc-attack1)
    49  and not just a [bogus](https://github.com/MagHErmit/tendermint/blob/v0.34.x/spec/light-client/detection/detection_003_reviewed.md#tmbc-bogus1) block could result in
    50  performing backwards verification beyond the trusted period, thus a fruitless
    51  endeavour.
    52  
    53  However, with the notion of it's better to fail earlier than later, the golang
    54  light client implementation will perform a consistency check on all providers
    55  and will error if one returns a different header, allowing the user
    56  the opportunity to reinitialize.
    57  
    58  #### **[LC-FUNC-INIT.2]:**
    59  
    60  ```go
    61  func InitLightClient(initData LCInitData) (LightStore, Error) {
    62      var initialBlock LightBlock
    63  
    64      switch {
    65      case LCInitData.TrustedBlock != nil:
    66          // we trust the block from a prior initialization
    67          initialBlock = LCInitData.TrustedBlock
    68  
    69      case LCInitData.TrustedHash != nil:
    70          untrustedBlock := FetchLightBlock(PeerList.Primary(), LCInitData.TrustedHeight)
    71  
    72  
    73          // verify that the hashes match
    74          if untrustedBlock.Hash() != LCInitData.TrustedHash {
    75              return nil, Error("Primary returned block with different hash")
    76          }
    77          // after checking the hash we now trust the block
    78          initialBlock = untrustedBlock
    79      }
    80      case LCInitData.Genesis != nil:
    81          untrustedBlock := FetchLightBlock(PeerList.Primary(), LCInitData.Genesis.InitialHeight)
    82  
    83          // verify that 2/3+ of the validator set signed the untrustedBlock
    84          if err := VerifyCommitFull(untrustedBlock.Commit, LCInitData.Genesis.Validators); err != nil {
    85              return nil, err
    86          }
    87  
    88          // we can now trust the block
    89          initialBlock = untrustedBlock
    90      default:
    91          return nil, Error("No initial data was provided")
    92  
    93      // This is done in the golang version but is optional and not strictly part of the protocol
    94      if err := CrossCheck(initialBlock, PeerList.Witnesses()); err != nil {
    95          return nil, err
    96      }
    97  
    98      // initialize light store
    99      lightStore := new LightStore;
   100      lightStore.Add(newBlock);
   101      return (lightStore, OK);
   102  }
   103  
   104  func CrossCheck(lb LightBlock, witnesses []Provider) error {
   105      for _, witness := range witnesses {
   106          witnessBlock := FetchLightBlock(witness, lb.Height)
   107  
   108          if witnessBlock.Hash() != lb.Hash() {
   109              return Error("Witness has different block")
   110          }
   111      }
   112      return OK
   113  }
   114  
   115  ```
   116  
   117  - Implementation remark
   118      - none
   119  - Expected precondition
   120      - *LCInitData* contains either a genesis file of a lightblock
   121      - if genesis it passes `ValidateAndComplete()` see [Tendermint](https://informal.systems)
   122  - Expected postcondition
   123      - *lightStore* initialized with trusted lightblock. It has either been
   124        cross-checked (from genesis) or it has initial trust from the
   125        user.
   126  - Error condition
   127      - if precondition is violated
   128      - empty peerList
   129  
   130  ----
   131