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.

639 lines
19 KiB

7 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
add support for block pruning via ABCI Commit response (#4588) * Added BlockStore.DeleteBlock() * Added initial block pruner prototype * wip * Added BlockStore.PruneBlocks() * Added consensus setting for block pruning * Added BlockStore base * Error on replay if base does not have blocks * Handle missing blocks when sending VoteSetMaj23Message * Error message tweak * Properly update blockstore state * Error message fix again * blockchain: ignore peer missing blocks * Added FIXME * Added test for block replay with truncated history * Handle peer base in blockchain reactor * Improved replay error handling * Added tests for Store.PruneBlocks() * Fix non-RPC handling of truncated block history * Panic on missing block meta in needProofBlock() * Updated changelog * Handle truncated block history in RPC layer * Added info about earliest block in /status RPC * Reorder height and base in blockchain reactor messages * Updated changelog * Fix tests * Appease linter * Minor review fixes * Non-empty BlockStores should always have base > 0 * Update code to assume base > 0 invariant * Added blockstore tests for pruning to 0 * Make sure we don't prune below the current base * Added BlockStore.Size() * config: added retain_blocks recommendations * Update v1 blockchain reactor to handle blockstore base * Added state database pruning * Propagate errors on missing validator sets * Comment tweaks * Improved error message Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * use ABCI field ResponseCommit.retain_height instead of retain-blocks config option * remove State.RetainHeight, return value instead * fix minor issues * rename pruneHeights() to pruneBlocks() * noop to fix GitHub borkage Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "github.com/gogo/protobuf/proto"
  7. "github.com/google/orderedcode"
  8. dbm "github.com/tendermint/tm-db"
  9. abci "github.com/tendermint/tendermint/abci/types"
  10. tmmath "github.com/tendermint/tendermint/libs/math"
  11. tmos "github.com/tendermint/tendermint/libs/os"
  12. tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
  13. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  14. "github.com/tendermint/tendermint/types"
  15. )
  16. const (
  17. // persist validators every valSetCheckpointInterval blocks to avoid
  18. // LoadValidators taking too much time.
  19. // https://github.com/tendermint/tendermint/pull/3438
  20. // 100000 results in ~ 100ms to get 100 validators (see BenchmarkLoadValidators)
  21. valSetCheckpointInterval = 100000
  22. )
  23. //------------------------------------------------------------------------
  24. const (
  25. // prefixes are unique across all tm db's
  26. prefixValidators = int64(5)
  27. prefixConsensusParams = int64(6)
  28. prefixABCIResponses = int64(7)
  29. )
  30. func encodeKey(prefix int64, height int64) []byte {
  31. res, err := orderedcode.Append(nil, prefix, height)
  32. if err != nil {
  33. panic(err)
  34. }
  35. return res
  36. }
  37. func validatorsKey(height int64) []byte {
  38. return encodeKey(prefixValidators, height)
  39. }
  40. func consensusParamsKey(height int64) []byte {
  41. return encodeKey(prefixConsensusParams, height)
  42. }
  43. func abciResponsesKey(height int64) []byte {
  44. return encodeKey(prefixABCIResponses, height)
  45. }
  46. //----------------------
  47. //go:generate mockery --case underscore --name Store
  48. // Store defines the state store interface
  49. //
  50. // It is used to retrieve current state and save and load ABCI responses,
  51. // validators and consensus parameters
  52. type Store interface {
  53. // LoadFromDBOrGenesisFile loads the most recent state.
  54. // If the chain is new it will use the genesis file from the provided genesis file path as the current state.
  55. LoadFromDBOrGenesisFile(string) (State, error)
  56. // LoadFromDBOrGenesisDoc loads the most recent state.
  57. // If the chain is new it will use the genesis doc as the current state.
  58. LoadFromDBOrGenesisDoc(*types.GenesisDoc) (State, error)
  59. // Load loads the current state of the blockchain
  60. Load() (State, error)
  61. // LoadValidators loads the validator set at a given height
  62. LoadValidators(int64) (*types.ValidatorSet, error)
  63. // LoadABCIResponses loads the abciResponse for a given height
  64. LoadABCIResponses(int64) (*tmstate.ABCIResponses, error)
  65. // LoadConsensusParams loads the consensus params for a given height
  66. LoadConsensusParams(int64) (tmproto.ConsensusParams, error)
  67. // Save overwrites the previous state with the updated one
  68. Save(State) error
  69. // SaveABCIResponses saves ABCIResponses for a given height
  70. SaveABCIResponses(int64, *tmstate.ABCIResponses) error
  71. // Bootstrap is used for bootstrapping state when not starting from a initial height.
  72. Bootstrap(State) error
  73. // PruneStates takes the height from which to prune up to (exclusive)
  74. PruneStates(int64) error
  75. }
  76. // dbStore wraps a db (github.com/tendermint/tm-db)
  77. type dbStore struct {
  78. db dbm.DB
  79. }
  80. var _ Store = (*dbStore)(nil)
  81. // NewStore creates the dbStore of the state pkg.
  82. func NewStore(db dbm.DB) Store {
  83. return dbStore{db}
  84. }
  85. // LoadStateFromDBOrGenesisFile loads the most recent state from the database,
  86. // or creates a new one from the given genesisFilePath.
  87. func (store dbStore) LoadFromDBOrGenesisFile(genesisFilePath string) (State, error) {
  88. state, err := store.Load()
  89. if err != nil {
  90. return State{}, err
  91. }
  92. if state.IsEmpty() {
  93. var err error
  94. state, err = MakeGenesisStateFromFile(genesisFilePath)
  95. if err != nil {
  96. return state, err
  97. }
  98. }
  99. return state, nil
  100. }
  101. // LoadStateFromDBOrGenesisDoc loads the most recent state from the database,
  102. // or creates a new one from the given genesisDoc.
  103. func (store dbStore) LoadFromDBOrGenesisDoc(genesisDoc *types.GenesisDoc) (State, error) {
  104. state, err := store.Load()
  105. if err != nil {
  106. return State{}, err
  107. }
  108. if state.IsEmpty() {
  109. var err error
  110. state, err = MakeGenesisState(genesisDoc)
  111. if err != nil {
  112. return state, err
  113. }
  114. }
  115. return state, nil
  116. }
  117. // LoadState loads the State from the database.
  118. func (store dbStore) Load() (State, error) {
  119. return store.loadState(stateKey)
  120. }
  121. func (store dbStore) loadState(key []byte) (state State, err error) {
  122. buf, err := store.db.Get(key)
  123. if err != nil {
  124. return state, err
  125. }
  126. if len(buf) == 0 {
  127. return state, nil
  128. }
  129. sp := new(tmstate.State)
  130. err = proto.Unmarshal(buf, sp)
  131. if err != nil {
  132. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  133. tmos.Exit(fmt.Sprintf(`LoadState: Data has been corrupted or its spec has changed:
  134. %v\n`, err))
  135. }
  136. sm, err := StateFromProto(sp)
  137. if err != nil {
  138. return state, err
  139. }
  140. return *sm, nil
  141. }
  142. // Save persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database.
  143. // This flushes the writes (e.g. calls SetSync).
  144. func (store dbStore) Save(state State) error {
  145. return store.save(state, stateKey)
  146. }
  147. func (store dbStore) save(state State, key []byte) error {
  148. nextHeight := state.LastBlockHeight + 1
  149. // If first block, save validators for the block.
  150. if nextHeight == 1 {
  151. nextHeight = state.InitialHeight
  152. // This extra logic due to Tendermint validator set changes being delayed 1 block.
  153. // It may get overwritten due to InitChain validator updates.
  154. if err := store.saveValidatorsInfo(nextHeight, nextHeight, state.Validators); err != nil {
  155. return err
  156. }
  157. }
  158. // Save next validators.
  159. if err := store.saveValidatorsInfo(nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators); err != nil {
  160. return err
  161. }
  162. // Save next consensus params.
  163. if err := store.saveConsensusParamsInfo(nextHeight,
  164. state.LastHeightConsensusParamsChanged, state.ConsensusParams); err != nil {
  165. return err
  166. }
  167. err := store.db.SetSync(key, state.Bytes())
  168. if err != nil {
  169. return err
  170. }
  171. return nil
  172. }
  173. // BootstrapState saves a new state, used e.g. by state sync when starting from non-zero height.
  174. func (store dbStore) Bootstrap(state State) error {
  175. height := state.LastBlockHeight + 1
  176. if height == 1 {
  177. height = state.InitialHeight
  178. }
  179. if height > 1 && !state.LastValidators.IsNilOrEmpty() {
  180. if err := store.saveValidatorsInfo(height-1, height-1, state.LastValidators); err != nil {
  181. return err
  182. }
  183. }
  184. if err := store.saveValidatorsInfo(height, height, state.Validators); err != nil {
  185. return err
  186. }
  187. if err := store.saveValidatorsInfo(height+1, height+1, state.NextValidators); err != nil {
  188. return err
  189. }
  190. if err := store.saveConsensusParamsInfo(height,
  191. state.LastHeightConsensusParamsChanged, state.ConsensusParams); err != nil {
  192. return err
  193. }
  194. return store.db.SetSync(stateKey, state.Bytes())
  195. }
  196. // PruneStates deletes states up to the height specified (exclusive). It is not
  197. // guaranteed to delete all states, since the last checkpointed state and states being pointed to by
  198. // e.g. `LastHeightChanged` must remain. The state at retain height must also exist.
  199. // Pruning is done in descending order.
  200. func (store dbStore) PruneStates(retainHeight int64) error {
  201. if retainHeight <= 0 {
  202. return fmt.Errorf("height %v must be greater than 0", retainHeight)
  203. }
  204. if err := store.pruneValidatorSets(retainHeight); err != nil {
  205. return err
  206. }
  207. if err := store.pruneConsensusParams(retainHeight); err != nil {
  208. return err
  209. }
  210. if err := store.pruneABCIResponses(retainHeight); err != nil {
  211. return err
  212. }
  213. return nil
  214. }
  215. // pruneValidatorSets calls a reverse iterator from base height to retain height (exclusive), deleting
  216. // all validator sets in between. Due to the fact that most validator sets stored reference an earlier
  217. // validator set, it is likely that there will remain one validator set left after pruning.
  218. func (store dbStore) pruneValidatorSets(height int64) error {
  219. valInfo, err := loadValidatorsInfo(store.db, height)
  220. if err != nil {
  221. return fmt.Errorf("validators at height %v not found: %w", height, err)
  222. }
  223. // We will prune up to the validator set at the given "height". As we don't save validator sets every
  224. // height but only when they change or at a check point, it is likely that the validator set at the height
  225. // we prune to is empty and thus dependent on the validator set saved at a previous height. We must find
  226. // that validator set and make sure it is not pruned.
  227. lastRecordedValSetHeight := lastStoredHeightFor(height, valInfo.LastHeightChanged)
  228. lastRecordedValSet, err := loadValidatorsInfo(store.db, lastRecordedValSetHeight)
  229. if err != nil || lastRecordedValSet.ValidatorSet == nil {
  230. return fmt.Errorf("couldn't find validators at height %d (height %d was originally requested): %w",
  231. lastStoredHeightFor(height, valInfo.LastHeightChanged),
  232. height,
  233. err,
  234. )
  235. }
  236. // batch delete all the validators sets up to height
  237. return store.batchDelete(
  238. validatorsKey(1),
  239. validatorsKey(height),
  240. validatorsKey(lastRecordedValSetHeight),
  241. )
  242. }
  243. // pruneConsensusParams calls a reverse iterator from base height to retain height batch deleting
  244. // all consensus params in between. If the consensus params at the new base height is dependent
  245. // on a prior height then this will keep that lower height to.
  246. func (store dbStore) pruneConsensusParams(retainHeight int64) error {
  247. paramsInfo, err := store.loadConsensusParamsInfo(retainHeight)
  248. if err != nil {
  249. return fmt.Errorf("consensus params at height %v not found: %w", retainHeight, err)
  250. }
  251. // As we don't save the consensus params at every height, only when there is a consensus params change,
  252. // we must not prune (or save) the last consensus params that the consensus params info at height
  253. // is dependent on.
  254. if paramsInfo.ConsensusParams.Equal(&tmproto.ConsensusParams{}) {
  255. lastRecordedConsensusParams, err := store.loadConsensusParamsInfo(paramsInfo.LastHeightChanged)
  256. if err != nil || lastRecordedConsensusParams.ConsensusParams.Equal(&tmproto.ConsensusParams{}) {
  257. return fmt.Errorf(
  258. "couldn't find consensus params at height %d as last changed from height %d: %w",
  259. paramsInfo.LastHeightChanged,
  260. retainHeight,
  261. err,
  262. )
  263. }
  264. }
  265. // batch delete all the consensus params up to the retain height
  266. return store.batchDelete(
  267. consensusParamsKey(1),
  268. consensusParamsKey(retainHeight),
  269. consensusParamsKey(paramsInfo.LastHeightChanged),
  270. )
  271. }
  272. // pruneABCIResponses calls a reverse iterator from base height to retain height batch deleting
  273. // all abci responses in between
  274. func (store dbStore) pruneABCIResponses(height int64) error {
  275. return store.batchDelete(abciResponsesKey(1), abciResponsesKey(height), nil)
  276. }
  277. // batchDelete is a generic function for deleting a range of keys in reverse order. It will
  278. // skip keys that have been
  279. func (store dbStore) batchDelete(start []byte, end []byte, exception []byte) error {
  280. iter, err := store.db.ReverseIterator(start, end)
  281. if err != nil {
  282. return fmt.Errorf("iterator error: %w", err)
  283. }
  284. defer iter.Close()
  285. batch := store.db.NewBatch()
  286. defer batch.Close()
  287. pruned := 0
  288. for iter.Valid() {
  289. key := iter.Key()
  290. if bytes.Equal(key, exception) {
  291. iter.Next()
  292. continue
  293. }
  294. if err := batch.Delete(key); err != nil {
  295. return fmt.Errorf("pruning error at key %X: %w", key, err)
  296. }
  297. pruned++
  298. // avoid batches growing too large by flushing to disk regularly
  299. if pruned%1000 == 0 {
  300. if err := iter.Error(); err != nil {
  301. return err
  302. }
  303. if err := iter.Close(); err != nil {
  304. return err
  305. }
  306. if err := batch.Write(); err != nil {
  307. return fmt.Errorf("pruning error at key %X: %w", key, err)
  308. }
  309. if err := batch.Close(); err != nil {
  310. return err
  311. }
  312. iter, err = store.db.ReverseIterator(start, end)
  313. if err != nil {
  314. return fmt.Errorf("iterator error: %w", err)
  315. }
  316. defer iter.Close()
  317. batch = store.db.NewBatch()
  318. defer batch.Close()
  319. } else {
  320. iter.Next()
  321. }
  322. }
  323. if err := iter.Error(); err != nil {
  324. return fmt.Errorf("iterator error: %w", err)
  325. }
  326. if err := batch.WriteSync(); err != nil {
  327. return err
  328. }
  329. return nil
  330. }
  331. //------------------------------------------------------------------------
  332. // ABCIResponsesResultsHash returns the root hash of a Merkle tree of
  333. // ResponseDeliverTx responses (see ABCIResults.Hash)
  334. //
  335. // See merkle.SimpleHashFromByteSlices
  336. func ABCIResponsesResultsHash(ar *tmstate.ABCIResponses) []byte {
  337. return types.NewResults(ar.DeliverTxs).Hash()
  338. }
  339. // LoadABCIResponses loads the ABCIResponses for the given height from the
  340. // database. If not found, ErrNoABCIResponsesForHeight is returned.
  341. //
  342. // This is useful for recovering from crashes where we called app.Commit and
  343. // before we called s.Save(). It can also be used to produce Merkle proofs of
  344. // the result of txs.
  345. func (store dbStore) LoadABCIResponses(height int64) (*tmstate.ABCIResponses, error) {
  346. buf, err := store.db.Get(abciResponsesKey(height))
  347. if err != nil {
  348. return nil, err
  349. }
  350. if len(buf) == 0 {
  351. return nil, ErrNoABCIResponsesForHeight{height}
  352. }
  353. abciResponses := new(tmstate.ABCIResponses)
  354. err = abciResponses.Unmarshal(buf)
  355. if err != nil {
  356. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  357. tmos.Exit(fmt.Sprintf(`LoadABCIResponses: Data has been corrupted or its spec has
  358. changed: %v\n`, err))
  359. }
  360. // TODO: ensure that buf is completely read.
  361. return abciResponses, nil
  362. }
  363. // SaveABCIResponses persists the ABCIResponses to the database.
  364. // This is useful in case we crash after app.Commit and before s.Save().
  365. // Responses are indexed by height so they can also be loaded later to produce
  366. // Merkle proofs.
  367. //
  368. // Exposed for testing.
  369. func (store dbStore) SaveABCIResponses(height int64, abciResponses *tmstate.ABCIResponses) error {
  370. var dtxs []*abci.ResponseDeliverTx
  371. // strip nil values,
  372. for _, tx := range abciResponses.DeliverTxs {
  373. if tx != nil {
  374. dtxs = append(dtxs, tx)
  375. }
  376. }
  377. abciResponses.DeliverTxs = dtxs
  378. bz, err := abciResponses.Marshal()
  379. if err != nil {
  380. return err
  381. }
  382. err = store.db.SetSync(abciResponsesKey(height), bz)
  383. if err != nil {
  384. return err
  385. }
  386. return nil
  387. }
  388. //-----------------------------------------------------------------------------
  389. // LoadValidators loads the ValidatorSet for a given height.
  390. // Returns ErrNoValSetForHeight if the validator set can't be found for this height.
  391. func (store dbStore) LoadValidators(height int64) (*types.ValidatorSet, error) {
  392. valInfo, err := loadValidatorsInfo(store.db, height)
  393. if err != nil {
  394. return nil, ErrNoValSetForHeight{height}
  395. }
  396. if valInfo.ValidatorSet == nil {
  397. lastStoredHeight := lastStoredHeightFor(height, valInfo.LastHeightChanged)
  398. valInfo2, err := loadValidatorsInfo(store.db, lastStoredHeight)
  399. if err != nil || valInfo2.ValidatorSet == nil {
  400. return nil,
  401. fmt.Errorf("couldn't find validators at height %d (height %d was originally requested): %w",
  402. lastStoredHeight,
  403. height,
  404. err,
  405. )
  406. }
  407. vs, err := types.ValidatorSetFromProto(valInfo2.ValidatorSet)
  408. if err != nil {
  409. return nil, err
  410. }
  411. vs.IncrementProposerPriority(tmmath.SafeConvertInt32(height - lastStoredHeight)) // mutate
  412. vi2, err := vs.ToProto()
  413. if err != nil {
  414. return nil, err
  415. }
  416. valInfo2.ValidatorSet = vi2
  417. valInfo = valInfo2
  418. }
  419. vip, err := types.ValidatorSetFromProto(valInfo.ValidatorSet)
  420. if err != nil {
  421. return nil, err
  422. }
  423. return vip, nil
  424. }
  425. func lastStoredHeightFor(height, lastHeightChanged int64) int64 {
  426. checkpointHeight := height - height%valSetCheckpointInterval
  427. return tmmath.MaxInt64(checkpointHeight, lastHeightChanged)
  428. }
  429. // CONTRACT: Returned ValidatorsInfo can be mutated.
  430. func loadValidatorsInfo(db dbm.DB, height int64) (*tmstate.ValidatorsInfo, error) {
  431. buf, err := db.Get(validatorsKey(height))
  432. if err != nil {
  433. return nil, err
  434. }
  435. if len(buf) == 0 {
  436. return nil, errors.New("value retrieved from db is empty")
  437. }
  438. v := new(tmstate.ValidatorsInfo)
  439. err = v.Unmarshal(buf)
  440. if err != nil {
  441. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  442. tmos.Exit(fmt.Sprintf(`LoadValidators: Data has been corrupted or its spec has changed:
  443. %v\n`, err))
  444. }
  445. // TODO: ensure that buf is completely read.
  446. return v, nil
  447. }
  448. // saveValidatorsInfo persists the validator set.
  449. //
  450. // `height` is the effective height for which the validator is responsible for
  451. // signing. It should be called from s.Save(), right before the state itself is
  452. // persisted.
  453. func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet *types.ValidatorSet) error {
  454. if lastHeightChanged > height {
  455. return errors.New("lastHeightChanged cannot be greater than ValidatorsInfo height")
  456. }
  457. valInfo := &tmstate.ValidatorsInfo{
  458. LastHeightChanged: lastHeightChanged,
  459. }
  460. // Only persist validator set if it was updated or checkpoint height (see
  461. // valSetCheckpointInterval) is reached.
  462. if height == lastHeightChanged || height%valSetCheckpointInterval == 0 {
  463. pv, err := valSet.ToProto()
  464. if err != nil {
  465. return err
  466. }
  467. valInfo.ValidatorSet = pv
  468. }
  469. bz, err := valInfo.Marshal()
  470. if err != nil {
  471. return err
  472. }
  473. err = store.db.Set(validatorsKey(height), bz)
  474. if err != nil {
  475. return err
  476. }
  477. return nil
  478. }
  479. //-----------------------------------------------------------------------------
  480. // ConsensusParamsInfo represents the latest consensus params, or the last height it changed
  481. // LoadConsensusParams loads the ConsensusParams for a given height.
  482. func (store dbStore) LoadConsensusParams(height int64) (tmproto.ConsensusParams, error) {
  483. empty := tmproto.ConsensusParams{}
  484. paramsInfo, err := store.loadConsensusParamsInfo(height)
  485. if err != nil {
  486. return empty, fmt.Errorf("could not find consensus params for height #%d: %w", height, err)
  487. }
  488. if paramsInfo.ConsensusParams.Equal(&empty) {
  489. paramsInfo2, err := store.loadConsensusParamsInfo(paramsInfo.LastHeightChanged)
  490. if err != nil {
  491. return empty, fmt.Errorf(
  492. "couldn't find consensus params at height %d as last changed from height %d: %w",
  493. paramsInfo.LastHeightChanged,
  494. height,
  495. err,
  496. )
  497. }
  498. paramsInfo = paramsInfo2
  499. }
  500. return paramsInfo.ConsensusParams, nil
  501. }
  502. func (store dbStore) loadConsensusParamsInfo(height int64) (*tmstate.ConsensusParamsInfo, error) {
  503. buf, err := store.db.Get(consensusParamsKey(height))
  504. if err != nil {
  505. return nil, err
  506. }
  507. if len(buf) == 0 {
  508. return nil, errors.New("value retrieved from db is empty")
  509. }
  510. paramsInfo := new(tmstate.ConsensusParamsInfo)
  511. if err = paramsInfo.Unmarshal(buf); err != nil {
  512. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  513. tmos.Exit(fmt.Sprintf(`LoadConsensusParams: Data has been corrupted or its spec has changed:
  514. %v\n`, err))
  515. }
  516. // TODO: ensure that buf is completely read.
  517. return paramsInfo, nil
  518. }
  519. // saveConsensusParamsInfo persists the consensus params for the next block to disk.
  520. // It should be called from s.Save(), right before the state itself is persisted.
  521. // If the consensus params did not change after processing the latest block,
  522. // only the last height for which they changed is persisted.
  523. func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params tmproto.ConsensusParams) error {
  524. paramsInfo := &tmstate.ConsensusParamsInfo{
  525. LastHeightChanged: changeHeight,
  526. }
  527. if changeHeight == nextHeight {
  528. paramsInfo.ConsensusParams = params
  529. }
  530. bz, err := paramsInfo.Marshal()
  531. if err != nil {
  532. return err
  533. }
  534. err = store.db.Set(consensusParamsKey(nextHeight), bz)
  535. if err != nil {
  536. return err
  537. }
  538. return nil
  539. }