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.

111 lines
4.1 KiB

lite2: light client with weak subjectivity (#3989) Refs #1771 ADR: https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md ## Commits: * add Verifier and VerifyCommitTrusting * add two more checks make trustLevel an option * float32 for trustLevel * check newHeader time * started writing lite Client * unify Verify methods * ensure h2.Header.bfttime < h1.Header.bfttime + tp * move trust checks into Verify function * add more comments * more docs * started writing tests * unbonding period failures * tests are green * export ErrNewHeaderTooFarIntoFuture * make golangci happy * test for non-adjusted headers * more precision * providers and stores * VerifyHeader and VerifyHeaderAtHeight funcs * fix compile errors * remove lastVerifiedHeight, persist new trusted header * sequential verification * remove TrustedStore option * started writing tests for light client * cover basic cases for linear verification * bisection tests PASS * rename BisectingVerification to SkippingVerification * refactor the code * add TrustedHeader method * consolidate sequential verification tests * consolidate skipping verification tests * rename trustedVals to trustedNextVals * start writing docs * ValidateTrustLevel func and ErrOldHeaderExpired error * AutoClient and example tests * fix errors * update doc * remove ErrNewHeaderTooFarIntoFuture This check is unnecessary given existing a) ErrOldHeaderExpired b) h2.Time > now checks. * return an error if we're at more recent height * add comments * add LastSignedHeaderHeight method to Store I think it's fine if Store tracks last height * copy over proxy from old lite package * make TrustedHeader return latest if height=0 * modify LastSignedHeaderHeight to return an error if no headers exist * copy over proxy impl * refactor proxy and start http lite client * Tx and BlockchainInfo methods * Block method * commit method * code compiles again * lite client compiles * extract updateLiteClientIfNeededTo func * move final parts * add placeholder for tests * force usage of lite http client in proxy * comment out query tests for now * explicitly mention tp: trusting period * verify nextVals in VerifyHeader * refactor bisection * move the NextValidatorsHash check into updateTrustedHeaderAndVals + update the comment * add ConsensusParams method to RPC client * add ConsensusParams to rpc/mock/client * change trustLevel type to a new cmn.Fraction type + update SkippingVerification comment * stress out trustLevel is only used for non-adjusted headers * fixes after Fede's review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * compare newHeader with a header from an alternative provider * save pivot header Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r349122824 * check header can still be trusted in TrustedHeader Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r349101424 * lite: update Validators and Block endpoints - Block no longer contains BlockMeta - Validators now accept two additional params: page and perPage * make linter happy
5 years ago
lite: follow up from #3989 (#4209) * rename adjusted to adjacent Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r352140829 * rename ErrTooMuchChange to ErrNotEnoughVotingPowerSigned Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r352142785 * verify commit is properly signed * remove no longer trusted headers * restore trustedHeader and trustedNextVals * check trustedHeader using options Refs https://github.com/tendermint/tendermint/pull/4209#issuecomment-562462165 * use correct var when checking if headers are adjacent in bisection func + replace TODO with a comment https://github.com/tendermint/tendermint/pull/3989#discussion_r352125455 * return header in VerifyHeaderAtHeight because that way we avoid DB call + add godoc comments + check if there are no headers yet in AutoClient https://github.com/tendermint/tendermint/pull/3989#pullrequestreview-315454506 * TestVerifyAdjacentHeaders: add 2 more test-cases + add TestVerifyReturnsErrorIfTrustLevelIsInvalid * lite: avoid overflow when parsing key in db store! * lite: rename AutoClient#Err to Errs * lite: add a test for AutoClient * lite: fix keyPattern and call itr.Next in db store * lite: add two tests for db store * lite: add TestClientRemovesNoLongerTrustedHeaders * lite: test Client#Cleanup * lite: test restoring trustedHeader https://github.com/tendermint/tendermint/pull/4209#issuecomment-562462165 * lite: comment out unused code in test_helpers * fix TestVerifyReturnsErrorIfTrustLevelIsInvalid after merge * change defaultRemoveNoLongerTrustedHeadersPeriod and add docs * write more doc * lite: uncomment testable examples * use stdlog.Fatal to stop AutoClient tests * make lll linter happy * separate errors for 2 cases - the validator set of a skipped header cannot be trusted, i.e. <1/3rd of h1 validator set has signed (new error, something like ErrNewValSetCantBeTrusted) - the validator set is trusted but < 2/3rds has signed (ErrNewHeaderCantBeTrusted) https://github.com/tendermint/tendermint/pull/4209#discussion_r360331253 * remove all headers (even the last one) that are outside of the trusting period. By doing this, we avoid checking the trustedHeader's hash in checkTrustedHeaderUsingOptions (case #1). https://github.com/tendermint/tendermint/pull/4209#discussion_r360332460 * explain restoreTrustedHeaderAndNextVals better https://github.com/tendermint/tendermint/pull/4209#discussion_r360602328 * add ConfirmationFunction option for optionally prompting for user input Y/n before removing headers Refs https://github.com/tendermint/tendermint/pull/4209#discussion_r360602945 * make cleaning optional https://github.com/tendermint/tendermint/pull/4209#discussion_r364838189 * return error when user refused to remove headers * check for double votes in VerifyCommitTrusting * leave only ErrNewValSetCantBeTrusted error to differenciate between h2Vals.VerifyCommit and h1NextVals.VerifyCommitTrusting * fix example tests * remove unnecessary if condition https://github.com/tendermint/tendermint/pull/4209#discussion_r365171847 It will be handled by the above switch. * verifyCommitBasic does not depend on vals Co-authored-by: Marko <marbar3778@yahoo.com>
5 years ago
lite2: light client with weak subjectivity (#3989) Refs #1771 ADR: https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md ## Commits: * add Verifier and VerifyCommitTrusting * add two more checks make trustLevel an option * float32 for trustLevel * check newHeader time * started writing lite Client * unify Verify methods * ensure h2.Header.bfttime < h1.Header.bfttime + tp * move trust checks into Verify function * add more comments * more docs * started writing tests * unbonding period failures * tests are green * export ErrNewHeaderTooFarIntoFuture * make golangci happy * test for non-adjusted headers * more precision * providers and stores * VerifyHeader and VerifyHeaderAtHeight funcs * fix compile errors * remove lastVerifiedHeight, persist new trusted header * sequential verification * remove TrustedStore option * started writing tests for light client * cover basic cases for linear verification * bisection tests PASS * rename BisectingVerification to SkippingVerification * refactor the code * add TrustedHeader method * consolidate sequential verification tests * consolidate skipping verification tests * rename trustedVals to trustedNextVals * start writing docs * ValidateTrustLevel func and ErrOldHeaderExpired error * AutoClient and example tests * fix errors * update doc * remove ErrNewHeaderTooFarIntoFuture This check is unnecessary given existing a) ErrOldHeaderExpired b) h2.Time > now checks. * return an error if we're at more recent height * add comments * add LastSignedHeaderHeight method to Store I think it's fine if Store tracks last height * copy over proxy from old lite package * make TrustedHeader return latest if height=0 * modify LastSignedHeaderHeight to return an error if no headers exist * copy over proxy impl * refactor proxy and start http lite client * Tx and BlockchainInfo methods * Block method * commit method * code compiles again * lite client compiles * extract updateLiteClientIfNeededTo func * move final parts * add placeholder for tests * force usage of lite http client in proxy * comment out query tests for now * explicitly mention tp: trusting period * verify nextVals in VerifyHeader * refactor bisection * move the NextValidatorsHash check into updateTrustedHeaderAndVals + update the comment * add ConsensusParams method to RPC client * add ConsensusParams to rpc/mock/client * change trustLevel type to a new cmn.Fraction type + update SkippingVerification comment * stress out trustLevel is only used for non-adjusted headers * fixes after Fede's review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * compare newHeader with a header from an alternative provider * save pivot header Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r349122824 * check header can still be trusted in TrustedHeader Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r349101424 * lite: update Validators and Block endpoints - Block no longer contains BlockMeta - Validators now accept two additional params: page and perPage * make linter happy
5 years ago
  1. /*
  2. Package lite provides a light client implementation.
  3. The concept of light clients was introduced in the Bitcoin white paper. It
  4. describes a watcher of distributed consensus process that only validates the
  5. consensus algorithm and not the state machine transactions within.
  6. Tendermint light clients allow bandwidth & compute-constrained devices, such as
  7. smartphones, low-power embedded chips, or other blockchains to efficiently
  8. verify the consensus of a Tendermint blockchain. This forms the basis of safe
  9. and efficient state synchronization for new network nodes and inter-blockchain
  10. communication (where a light client of one Tendermint instance runs in another
  11. chain's state machine).
  12. In a network that is expected to reliably punish validators for misbehavior by
  13. slashing bonded stake and where the validator set changes infrequently, clients
  14. can take advantage of this assumption to safely synchronize a lite client
  15. without downloading the intervening headers.
  16. Light clients (and full nodes) operating in the Proof Of Stake context need a
  17. trusted block height from a trusted source that is no older than 1 unbonding
  18. window plus a configurable evidence submission synchrony bound. This is called
  19. weak subjectivity.
  20. Weak subjectivity is required in Proof of Stake blockchains because it is
  21. costless for an attacker to buy up voting keys that are no longer bonded and
  22. fork the network at some point in its prior history. See Vitalik's post at
  23. [Proof of Stake: How I Learned to Love Weak
  24. Subjectivity](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/).
  25. NOTE: Tendermint provides a somewhat different (stronger) light client model
  26. than Bitcoin under eclipse, since the eclipsing node(s) can only fool the light
  27. client if they have two-thirds of the private keys from the last root-of-trust.
  28. # Common structures
  29. * SignedHeader
  30. SignedHeader is a block header along with a commit -- enough validator
  31. precommit-vote signatures to prove its validity (> 2/3 of the voting power)
  32. given the validator set responsible for signing that header.
  33. The hash of the next validator set is included and signed in the SignedHeader.
  34. This lets the lite client keep track of arbitrary changes to the validator set,
  35. as every change to the validator set must be approved by inclusion in the
  36. header and signed in the commit.
  37. In the worst case, with every block changing the validators around completely,
  38. a lite client can sync up with every block header to verify each validator set
  39. change on the chain. In practice, most applications will not have frequent
  40. drastic updates to the validator set, so the logic defined in this package for
  41. lite client syncing is optimized to use intelligent bisection.
  42. # What this package provides
  43. This package provides three major things:
  44. 1. Client implementation (see client.go)
  45. 2. Pure functions to verify a new header (see verifier.go)
  46. 3. Secure RPC proxy
  47. ## 1. Client implementation (see client.go)
  48. Example usage:
  49. db, err := dbm.NewGoLevelDB("lite-client-db", dbDir)
  50. if err != nil {
  51. // return err
  52. t.Fatal(err)
  53. }
  54. c, err := NewClient(
  55. chainID,
  56. TrustOptions{
  57. Period: 504 * time.Hour, // 21 days
  58. Height: 100,
  59. Hash: header.Hash(),
  60. },
  61. httpp.New(chainID, "tcp://localhost:26657"),
  62. dbs.New(db, chainID),
  63. )
  64. err = c.VerifyHeaderAtHeight(101, time.Now())
  65. if err != nil {
  66. fmt.Println("retry?")
  67. }
  68. h, err := c.TrustedHeader(101)
  69. if err != nil {
  70. fmt.Println("retry?")
  71. }
  72. fmt.Println("got header", h)
  73. ## 2. Pure functions to verify a new header (see verifier.go)
  74. Verify function verifies a new header against some trusted header. See
  75. https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md
  76. for details.
  77. ## 3. Secure RPC proxy
  78. Tendermint RPC exposes a lot of info, but a malicious node could return any
  79. data it wants to queries, or even to block headers, even making up fake
  80. signatures from non-existent validators to justify it. Secure RPC proxy serves
  81. as a wrapper, which verifies all the headers, using a light client connected to
  82. some other node.
  83. See
  84. https://github.com/tendermint/tendermint/blob/master/cmd/tendermint/commands/lite.go
  85. for usage example.
  86. */
  87. package lite