checkpoint

This commit is contained in:
Callum Waters
2022-07-11 13:59:37 +02:00
parent 2dbc76d79f
commit c0eb5da04c
8 changed files with 51 additions and 26 deletions

View File

@@ -557,7 +557,7 @@ type RPCConfig struct {
// Set to true to enable the /BlockResults query. Saving ABCI Responses is also necessary
// to reindex events used in the command line
PersistABCIResponses bool `mapstructure:"persist-abci-responses"`
DiscardABCIResponses bool `mapstructure:"persist-abci-responses"`
}
// DefaultRPCConfig returns a default configuration for the RPC server
@@ -584,7 +584,7 @@ func DefaultRPCConfig() *RPCConfig {
TLSCertFile: "",
TLSKeyFile: "",
PersistABCIResponses: false,
DiscardABCIResponses: true,
}
}

View File

@@ -1,6 +1,9 @@
package state
import "fmt"
import (
"errors"
"fmt"
)
type (
ErrInvalidBlock error
@@ -99,3 +102,5 @@ func (e ErrNoConsensusParamsForHeight) Error() string {
func (e ErrNoABCIResponsesForHeight) Error() string {
return fmt.Sprintf("could not find results for height #%d", e.Height)
}
var ErrABCIResponsesNotPersisted = errors.New("node is not persisting abci responses")

View File

@@ -111,7 +111,7 @@ func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValida
})
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, false)
if err := stateStore.Save(s); err != nil {
panic(err)
}

View File

@@ -110,16 +110,16 @@ type Store interface {
type dbStore struct {
db dbm.DB
// persistABCIResponses determines if all
// discardABCIResponses determines if all
// ABCI responses are persisted or just the last
persistABCIResponses bool
discardABCIResponses bool
}
var _ Store = (*dbStore)(nil)
// NewStore creates the dbStore of the state pkg.
func NewStore(db dbm.DB, persistABCIResponses bool) Store {
return dbStore{db, persistABCIResponses}
func NewStore(db dbm.DB, discardABCIResponses bool) Store {
return dbStore{db, discardABCIResponses}
}
// LoadState loads the State from the database.
@@ -420,22 +420,19 @@ func ABCIResponsesResultsHash(ar *tmstate.ABCIResponses) []byte {
}
// LoadABCIResponses loads the ABCIResponses for the given height from the
// database. If not found, ErrNoABCIResponsesForHeight is returned.
//
// 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.
// database. If the node has DiscardABCIResponses set to true, ErrABCIResponsesNotPersisted
// is persisted. If not found, ErrNoABCIResponsesForHeight is returned.
func (store dbStore) LoadABCIResponses(height int64) (*tmstate.ABCIResponses, error) {
if !store.persistABCIResponses {
return nil, errors.New("this is not supported")
if !store.discardABCIResponses {
return nil, ErrABCIResponsesNotPersisted
}
buf, err := store.db.Get(abciResponsesKey(height))
if err != nil {
return nil, err
}
if len(buf) == 0 {
if len(buf) == 0 {
return nil, ErrNoABCIResponsesForHeight{height}
}
abciResponses := new(tmstate.ABCIResponses)
@@ -450,6 +447,21 @@ func (store dbStore) LoadABCIResponses(height int64) (*tmstate.ABCIResponses, er
return abciResponses, nil
}
// LoadLastABCIResponses loads the last ABCI response specifically after a crash
// We conduct a sanity check here which compares the height from the last ABICResponse to the
// height that is given
//
// This is used 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 (store dbStore) LoadLastABCIResponse(height int64) (*tmstate.ABCIResponses, error) {
bz, err := store.db.Get(lastABCIResponseKey())
abciResponse := new(tmstate.ABCIResponses)
err = abciResponses.Unmarshal(bz)
return abciResponse, nil
}
// SaveABCIResponses persists the ABCIResponses to the database.
// This is useful in case we crash after app.Commit and before s.Save().
// Responses are indexed by height so they can also be loaded later to produce
@@ -472,9 +484,9 @@ func (store dbStore) SaveABCIResponses(height int64, abciResponses *tmstate.ABCI
return err
}
// If the flag is true then we save the ABCIResponse. This can be used for the /BlockResults
// If the flag is false then we save the ABCIResponse. This can be used for the /BlockResults
// query or to reindex an event using the command line.
if store.persistABCIResponses {
if !store.discardABCIResponses {
if err := store.db.Set(abciResponsesKey(height), bz); err != nil {
return err
}
@@ -485,6 +497,10 @@ func (store dbStore) SaveABCIResponses(height int64, abciResponses *tmstate.ABCI
return store.db.SetSync(lastABCIResponseKey(), bz)
}
type ResponsesInfo struct {
abcu
}
// SaveValidatorSets is used to save the validator set over multiple heights.
// It is exposed so that a backfill operation during state sync can populate
// the store with the necessary amount of validator sets to verify any evidence

View File

@@ -139,7 +139,7 @@ func makeNode(cfg *config.Config,
}
closers = append(closers, dbCloser)
stateStore := sm.NewStore(stateDB, cfg.RPC.PersistABCIResponses)
stateStore := sm.NewStore(stateDB, cfg.RPC.DiscardABCIResponses)
genDoc, err := genesisDocProvider()
if err != nil {

View File

@@ -232,7 +232,7 @@ func TestCreateProposalBlock(t *testing.T) {
const height int64 = 1
state, stateDB, privVals := state(1, height)
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, false)
maxBytes := 16384
const partSize uint32 = 256
maxEvidenceBytes := int64(maxBytes / 2)
@@ -325,7 +325,7 @@ func TestMaxTxsProposalBlockSize(t *testing.T) {
const height int64 = 1
state, stateDB, _ := state(1, height)
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, false)
blockStore := store.NewBlockStore(dbm.NewMemDB())
const maxBytes int64 = 16384
const partSize uint32 = 256
@@ -387,7 +387,7 @@ func TestMaxProposalBlockSize(t *testing.T) {
logger := log.TestingLogger()
state, stateDB, _ := state(types.MaxVotesCount, int64(1))
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, false)
blockStore := store.NewBlockStore(dbm.NewMemDB())
const maxBytes int64 = 1024 * 1024 * 2
state.ConsensusParams.Block.MaxBytes = maxBytes
@@ -625,7 +625,7 @@ func state(nVals int, height int64) (sm.State, dbm.DB, []types.PrivValidator) {
// save validators to db for 2 heights
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, false)
if err := stateStore.Save(s); err != nil {
panic(err)
}
@@ -648,7 +648,7 @@ func loadStatefromGenesis(t *testing.T) sm.State {
t.Helper()
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, false)
cfg, err := config.ResetTestRoot("load_state_from_genesis")
require.NoError(t, err)

View File

@@ -298,7 +298,7 @@ func createEvidenceReactor(
logger = logger.With("module", "evidence")
reactorShim := p2p.NewReactorShim(logger, "EvidenceShim", evidence.ChannelShims)
evidencePool, err := evidence.NewPool(logger, evidenceDB, sm.NewStore(stateDB), blockStore)
evidencePool, err := evidence.NewPool(logger, evidenceDB, sm.NewStore(stateDB, cfg.RPC.DiscardABCIResponses), blockStore)
if err != nil {
return nil, nil, nil, fmt.Errorf("creating evidence pool: %w", err)
}

View File

@@ -32,6 +32,10 @@ message ConsensusParamsInfo {
int64 last_height_changed = 2;
}
message ResponsesInfo {
ABCIResponses abc
}
message Version {
tendermint.version.Consensus consensus = 1 [(gogoproto.nullable) = false];
string software = 2;