You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
4.6 KiB

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