mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-26 18:04:22 +00:00
state: proto migration (#4972)
## Description the second part of state proto migration Closes: #XXX
This commit is contained in:
+104
-74
@@ -3,11 +3,13 @@ package state
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmmath "github.com/tendermint/tendermint/libs/math"
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
tmstate "github.com/tendermint/tendermint/proto/state"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -56,6 +58,7 @@ func LoadStateFromDBOrGenesisFile(stateDB dbm.DB, genesisFilePath string) (State
|
||||
// to the database.
|
||||
func LoadStateFromDBOrGenesisDoc(stateDB dbm.DB, genesisDoc *types.GenesisDoc) (State, error) {
|
||||
state := LoadState(stateDB)
|
||||
|
||||
if state.IsEmpty() {
|
||||
var err error
|
||||
state, err = MakeGenesisState(genesisDoc)
|
||||
@@ -82,15 +85,21 @@ func loadState(db dbm.DB, key []byte) (state State) {
|
||||
return state
|
||||
}
|
||||
|
||||
err = cdc.UnmarshalBinaryBare(buf, &state)
|
||||
sp := new(tmstate.State)
|
||||
|
||||
err = proto.Unmarshal(buf, sp)
|
||||
if err != nil {
|
||||
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
|
||||
tmos.Exit(fmt.Sprintf(`LoadState: Data has been corrupted or its spec has changed:
|
||||
%v\n`, err))
|
||||
%v\n`, err))
|
||||
}
|
||||
// TODO: ensure that buf is completely read.
|
||||
|
||||
return state
|
||||
sm, err := StateFromProto(sp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return *sm
|
||||
}
|
||||
|
||||
// SaveState persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database.
|
||||
@@ -110,6 +119,7 @@ func saveState(db dbm.DB, state State, key []byte) {
|
||||
}
|
||||
// Save next validators.
|
||||
saveValidatorsInfo(db, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators)
|
||||
|
||||
// Save next consensus params.
|
||||
saveConsensusParamsInfo(db, nextHeight, state.LastHeightConsensusParamsChanged, state.ConsensusParams)
|
||||
err := db.SetSync(key, state.Bytes())
|
||||
@@ -130,15 +140,6 @@ func BootstrapState(db dbm.DB, state State) error {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// ABCIResponses retains the responses
|
||||
// of the various ABCI calls during block processing.
|
||||
// It is persisted to disk for each height before calling Commit.
|
||||
type ABCIResponses struct {
|
||||
DeliverTxs []*abci.ResponseDeliverTx `json:"deliver_txs"`
|
||||
EndBlock *abci.ResponseEndBlock `json:"end_block"`
|
||||
BeginBlock *abci.ResponseBeginBlock `json:"begin_block"`
|
||||
}
|
||||
|
||||
// PruneStates deletes states between the given heights (including from, excluding to). It is not
|
||||
// guaranteed to delete all states, since the last checkpointed state and states being pointed to by
|
||||
// e.g. `LastHeightChanged` must remain. The state at to must also exist.
|
||||
@@ -187,12 +188,25 @@ func PruneStates(db dbm.DB, from int64, to int64) error {
|
||||
if keepVals[h] {
|
||||
v := loadValidatorsInfo(db, h)
|
||||
if v.ValidatorSet == nil {
|
||||
v.ValidatorSet, err = LoadValidators(db, h)
|
||||
|
||||
vip, err := LoadValidators(db, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pvi, err := vip.ToProto()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.ValidatorSet = pvi
|
||||
v.LastHeightChanged = h
|
||||
batch.Set(calcValidatorsKey(h), v.Bytes())
|
||||
|
||||
bz, err := v.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
batch.Set(calcValidatorsKey(h), bz)
|
||||
}
|
||||
} else {
|
||||
batch.Delete(calcValidatorsKey(h))
|
||||
@@ -206,7 +220,11 @@ func PruneStates(db dbm.DB, from int64, to int64) error {
|
||||
return err
|
||||
}
|
||||
p.LastHeightChanged = h
|
||||
batch.Set(calcConsensusParamsKey(h), p.Bytes())
|
||||
bz, err := p.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
batch.Set(calcConsensusParamsKey(h), bz)
|
||||
}
|
||||
} else {
|
||||
batch.Delete(calcConsensusParamsKey(h))
|
||||
@@ -235,42 +253,27 @@ func PruneStates(db dbm.DB, from int64, to int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewABCIResponses returns a new ABCIResponses
|
||||
func NewABCIResponses(block *types.Block) *ABCIResponses {
|
||||
resDeliverTxs := make([]*abci.ResponseDeliverTx, len(block.Data.Txs))
|
||||
if len(block.Data.Txs) == 0 {
|
||||
// This makes Amino encoding/decoding consistent.
|
||||
resDeliverTxs = nil
|
||||
}
|
||||
return &ABCIResponses{
|
||||
DeliverTxs: resDeliverTxs,
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes serializes the ABCIResponse using go-amino.
|
||||
func (arz *ABCIResponses) Bytes() []byte {
|
||||
return cdc.MustMarshalBinaryBare(arz)
|
||||
}
|
||||
|
||||
func (arz *ABCIResponses) ResultsHash() []byte {
|
||||
results := types.NewResults(arz.DeliverTxs)
|
||||
// ABCIResponsesResultsHash returns the merkle hash of the deliverTxs within ABCIResponses
|
||||
func ABCIResponsesResultsHash(ar tmstate.ABCIResponses) []byte {
|
||||
results := types.NewResults(ar.DeliverTxs)
|
||||
return results.Hash()
|
||||
}
|
||||
|
||||
// LoadABCIResponses loads the ABCIResponses for the given height from the database.
|
||||
// This is useful for recovering from crashes where we called app.Commit and before we called
|
||||
// s.Save(). It can also be used to produce Merkle proofs of the result of txs.
|
||||
func LoadABCIResponses(db dbm.DB, height int64) (*ABCIResponses, error) {
|
||||
func LoadABCIResponses(db dbm.DB, height int64) (*tmstate.ABCIResponses, error) {
|
||||
buf, err := db.Get(calcABCIResponsesKey(height))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(buf) == 0 {
|
||||
|
||||
return nil, ErrNoABCIResponsesForHeight{height}
|
||||
}
|
||||
|
||||
abciResponses := new(ABCIResponses)
|
||||
err = cdc.UnmarshalBinaryBare(buf, abciResponses)
|
||||
abciResponses := new(tmstate.ABCIResponses)
|
||||
err = abciResponses.Unmarshal(buf)
|
||||
if err != nil {
|
||||
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
|
||||
tmos.Exit(fmt.Sprintf(`LoadABCIResponses: Data has been corrupted or its spec has
|
||||
@@ -287,23 +290,25 @@ func LoadABCIResponses(db dbm.DB, height int64) (*ABCIResponses, error) {
|
||||
// Merkle proofs.
|
||||
//
|
||||
// Exposed for testing.
|
||||
func SaveABCIResponses(db dbm.DB, height int64, abciResponses *ABCIResponses) {
|
||||
db.SetSync(calcABCIResponsesKey(height), abciResponses.Bytes())
|
||||
func SaveABCIResponses(db dbm.DB, height int64, abciResponses *tmstate.ABCIResponses) {
|
||||
var dtxs []*abci.ResponseDeliverTx
|
||||
//strip nil values,
|
||||
for _, tx := range abciResponses.DeliverTxs {
|
||||
if tx != nil {
|
||||
dtxs = append(dtxs, tx)
|
||||
}
|
||||
}
|
||||
abciResponses.DeliverTxs = dtxs
|
||||
|
||||
bz, err := abciResponses.Marshal()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.SetSync(calcABCIResponsesKey(height), bz)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ValidatorsInfo represents the latest validator set, or the last height it changed
|
||||
type ValidatorsInfo struct {
|
||||
ValidatorSet *types.ValidatorSet
|
||||
LastHeightChanged int64
|
||||
}
|
||||
|
||||
// Bytes serializes the ValidatorsInfo using go-amino.
|
||||
func (valInfo *ValidatorsInfo) Bytes() []byte {
|
||||
return cdc.MustMarshalBinaryBare(valInfo)
|
||||
}
|
||||
|
||||
// LoadValidators loads the ValidatorSet for a given height.
|
||||
// Returns ErrNoValSetForHeight if the validator set can't be found for this height.
|
||||
func LoadValidators(db dbm.DB, height int64) (*types.ValidatorSet, error) {
|
||||
@@ -322,11 +327,28 @@ func LoadValidators(db dbm.DB, height int64) (*types.ValidatorSet, error) {
|
||||
),
|
||||
)
|
||||
}
|
||||
valInfo2.ValidatorSet.IncrementProposerPriority(tmmath.SafeConvertInt32(height - lastStoredHeight)) // mutate
|
||||
|
||||
vs, err := types.ValidatorSetFromProto(valInfo2.ValidatorSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vs.IncrementProposerPriority(tmmath.SafeConvertInt32(height - lastStoredHeight)) // mutate
|
||||
vi2, err := vs.ToProto()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
valInfo2.ValidatorSet = vi2
|
||||
valInfo = valInfo2
|
||||
}
|
||||
|
||||
return valInfo.ValidatorSet, nil
|
||||
vip, err := types.ValidatorSetFromProto(valInfo.ValidatorSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vip, nil
|
||||
}
|
||||
|
||||
func lastStoredHeightFor(height, lastHeightChanged int64) int64 {
|
||||
@@ -335,17 +357,18 @@ func lastStoredHeightFor(height, lastHeightChanged int64) int64 {
|
||||
}
|
||||
|
||||
// CONTRACT: Returned ValidatorsInfo can be mutated.
|
||||
func loadValidatorsInfo(db dbm.DB, height int64) *ValidatorsInfo {
|
||||
func loadValidatorsInfo(db dbm.DB, height int64) *tmstate.ValidatorsInfo {
|
||||
buf, err := db.Get(calcValidatorsKey(height))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if len(buf) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := new(ValidatorsInfo)
|
||||
err = cdc.UnmarshalBinaryBare(buf, v)
|
||||
v := new(tmstate.ValidatorsInfo)
|
||||
err = v.Unmarshal(buf)
|
||||
if err != nil {
|
||||
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
|
||||
tmos.Exit(fmt.Sprintf(`LoadValidators: Data has been corrupted or its spec has changed:
|
||||
@@ -365,29 +388,30 @@ func saveValidatorsInfo(db dbm.DB, height, lastHeightChanged int64, valSet *type
|
||||
if lastHeightChanged > height {
|
||||
panic("LastHeightChanged cannot be greater than ValidatorsInfo height")
|
||||
}
|
||||
valInfo := &ValidatorsInfo{
|
||||
valInfo := &tmstate.ValidatorsInfo{
|
||||
LastHeightChanged: lastHeightChanged,
|
||||
}
|
||||
// Only persist validator set if it was updated or checkpoint height (see
|
||||
// valSetCheckpointInterval) is reached.
|
||||
if height == lastHeightChanged || height%valSetCheckpointInterval == 0 {
|
||||
valInfo.ValidatorSet = valSet
|
||||
pv, err := valSet.ToProto()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
valInfo.ValidatorSet = pv
|
||||
}
|
||||
db.Set(calcValidatorsKey(height), valInfo.Bytes())
|
||||
|
||||
bz, err := valInfo.Marshal()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.Set(calcValidatorsKey(height), bz)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ConsensusParamsInfo represents the latest consensus params, or the last height it changed
|
||||
type ConsensusParamsInfo struct {
|
||||
ConsensusParams tmproto.ConsensusParams
|
||||
LastHeightChanged int64
|
||||
}
|
||||
|
||||
// Bytes serializes the ConsensusParamsInfo using go-amino.
|
||||
func (params ConsensusParamsInfo) Bytes() []byte {
|
||||
return cdc.MustMarshalBinaryBare(params)
|
||||
}
|
||||
|
||||
// LoadConsensusParams loads the ConsensusParams for a given height.
|
||||
func LoadConsensusParams(db dbm.DB, height int64) (tmproto.ConsensusParams, error) {
|
||||
@@ -409,13 +433,14 @@ func LoadConsensusParams(db dbm.DB, height int64) (tmproto.ConsensusParams, erro
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
paramsInfo = paramsInfo2
|
||||
}
|
||||
|
||||
return paramsInfo.ConsensusParams, nil
|
||||
}
|
||||
|
||||
func loadConsensusParamsInfo(db dbm.DB, height int64) *ConsensusParamsInfo {
|
||||
func loadConsensusParamsInfo(db dbm.DB, height int64) *tmstate.ConsensusParamsInfo {
|
||||
buf, err := db.Get(calcConsensusParamsKey(height))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -424,9 +449,8 @@ func loadConsensusParamsInfo(db dbm.DB, height int64) *ConsensusParamsInfo {
|
||||
return nil
|
||||
}
|
||||
|
||||
paramsInfo := new(ConsensusParamsInfo)
|
||||
err = cdc.UnmarshalBinaryBare(buf, paramsInfo)
|
||||
if err != nil {
|
||||
paramsInfo := new(tmstate.ConsensusParamsInfo)
|
||||
if err = paramsInfo.Unmarshal(buf); err != nil {
|
||||
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
|
||||
tmos.Exit(fmt.Sprintf(`LoadConsensusParams: Data has been corrupted or its spec has changed:
|
||||
%v\n`, err))
|
||||
@@ -441,11 +465,17 @@ func loadConsensusParamsInfo(db dbm.DB, height int64) *ConsensusParamsInfo {
|
||||
// If the consensus params did not change after processing the latest block,
|
||||
// only the last height for which they changed is persisted.
|
||||
func saveConsensusParamsInfo(db dbm.DB, nextHeight, changeHeight int64, params tmproto.ConsensusParams) {
|
||||
paramsInfo := &ConsensusParamsInfo{
|
||||
paramsInfo := &tmstate.ConsensusParamsInfo{
|
||||
LastHeightChanged: changeHeight,
|
||||
}
|
||||
|
||||
if changeHeight == nextHeight {
|
||||
paramsInfo.ConsensusParams = params
|
||||
}
|
||||
db.Set(calcConsensusParamsKey(nextHeight), paramsInfo.Bytes())
|
||||
bz, err := paramsInfo.Marshal()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.Set(calcConsensusParamsKey(nextHeight), bz)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user