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.

140 lines
6.0 KiB

  1. /*
  2. Package lite allows you to securely validate headers without a full node.
  3. This library pulls together all the crypto and algorithms, so given a
  4. relatively recent (< unbonding period) known validator set, one can get
  5. indisputable proof that data is in the chain (current state) or detect if the
  6. node is lying to the client.
  7. Tendermint RPC exposes a lot of info, but a malicious node could return any
  8. data it wants to queries, or even to block headers, even making up fake
  9. signatures from non-existent validators to justify it. This is a lot of logic
  10. to get right, to be contained in a small, easy to use library, that does this
  11. for you, so you can just build nice applications.
  12. We design for clients who have no strong trust relationship with any Tendermint
  13. node, just the blockchain and validator set as a whole.
  14. # Data structures
  15. ## SignedHeader
  16. SignedHeader is a block header along with a commit -- enough validator
  17. precommit-vote signatures to prove its validity (> 2/3 of the voting power)
  18. given the validator set responsible for signing that header. A FullCommit is a
  19. SignedHeader along with the current and next validator sets.
  20. The hash of the next validator set is included and signed in the SignedHeader.
  21. This lets the lite client keep track of arbitrary changes to the validator set,
  22. as every change to the validator set must be approved by inclusion in the
  23. header and signed in the commit.
  24. In the worst case, with every block changing the validators around completely,
  25. a lite client can sync up with every block header to verify each validator set
  26. change on the chain. In practice, most applications will not have frequent
  27. drastic updates to the validator set, so the logic defined in this package for
  28. lite client syncing is optimized to use intelligent bisection and
  29. block-skipping for efficient sourcing and verification of these data structures
  30. and updates to the validator set (see the DynamicVerifier for more
  31. information).
  32. The FullCommit is also declared in this package as a convenience structure,
  33. which includes the SignedHeader along with the full current and next
  34. ValidatorSets.
  35. ## Verifier
  36. A Verifier validates a new SignedHeader given the currently known state. There
  37. are two different types of Verifiers provided.
  38. BaseVerifier - given a validator set and a height, this Verifier verifies
  39. that > 2/3 of the voting power of the given validator set had signed the
  40. SignedHeader, and that the SignedHeader was to be signed by the exact given
  41. validator set, and that the height of the commit is at least height (or
  42. greater).
  43. SignedHeader.Commit may be signed by a different validator set, it can get
  44. certified with a BaseVerifier as long as sufficient signatures from the
  45. previous validator set are present in the commit.
  46. DynamicVerifier - this Verifier implements an auto-update and persistence
  47. strategy to certify any SignedHeader of the blockchain.
  48. ## Provider and PersistentProvider
  49. A Provider allows us to store and retrieve the FullCommits.
  50. ```go
  51. type Provider interface {
  52. // LatestFullCommit returns the latest commit with
  53. // minHeight <= height <= maxHeight.
  54. // If maxHeight is zero, returns the latest where
  55. // minHeight <= height.
  56. LatestFullCommit(chainID string, minHeight, maxHeight int64) (FullCommit, error)
  57. }
  58. ```
  59. * client.NewHTTPProvider - query Tendermint rpc.
  60. A PersistentProvider is a Provider that also allows for saving state. This is
  61. used by the DynamicVerifier for persistence.
  62. ```go
  63. type PersistentProvider interface {
  64. Provider
  65. // SaveFullCommit saves a FullCommit (without verification).
  66. SaveFullCommit(fc FullCommit) error
  67. }
  68. ```
  69. * DBProvider - persistence provider for use with any tmlibs/DB.
  70. * MultiProvider - combine multiple providers.
  71. The suggested use for local light clients is client.NewHTTPProvider(...) for
  72. getting new data (Source), and NewMultiProvider(NewDBProvider("label",
  73. dbm.NewMemDB()), NewDBProvider("label", db.NewFileDB(...))) to store confirmed
  74. full commits (Trusted)
  75. # How We Track Validators
  76. Unless you want to blindly trust the node you talk with, you need to trace
  77. every response back to a hash in a block header and validate the commit
  78. signatures of that block header match the proper validator set. If there is a
  79. static validator set, you store it locally upon initialization of the client,
  80. and check against that every time.
  81. If the validator set for the blockchain is dynamic, verifying block commits is
  82. a bit more involved -- if there is a block at height H with a known (trusted)
  83. validator set V, and another block at height H' (H' > H) with validator set V'
  84. != V, then we want a way to safely update it.
  85. First, we get the new (unconfirmed) validator set V' and verify that H' is
  86. internally consistent and properly signed by this V'. Assuming it is a valid
  87. block, we check that at least 2/3 of the validators in V also signed it,
  88. meaning it would also be valid under our old assumptions. Then, we accept H'
  89. and V' as valid and trusted and use that to validate for heights X > H' until a
  90. more recent and updated validator set is found.
  91. If we cannot update directly from H -> H' because there was too much change to
  92. the validator set, then we can look for some Hm (H < Hm < H') with a validator
  93. set Vm. Then we try to update H -> Hm and then Hm -> H' in two steps. If one
  94. of these steps doesn't work, then we continue bisecting, until we eventually
  95. have to externally validate the valdiator set changes at every block.
  96. Since we never trust any server in this protocol, only the signatures
  97. themselves, it doesn't matter if the seed comes from a (possibly malicious)
  98. node or a (possibly malicious) user. We can accept it or reject it based only
  99. on our trusted validator set and cryptographic proofs. This makes it extremely
  100. important to verify that you have the proper validator set when initializing
  101. the client, as that is the root of all trust.
  102. The software currently assumes that the unbonding period is infinite in
  103. duration. If the DynamicVerifier hasn't been updated in a while, you should
  104. manually verify the block headers using other sources.
  105. TODO: Update the software to handle cases around the unbonding period.
  106. */
  107. package lite