8000 genesis:revert removing the genesis file out of the DB by jmalicevic · Pull Request #1294 · cometbft/cometbft · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

genesis:revert removing the genesis file out of the DB #1294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

8 changes: 6 additions & 2 deletions blocksync/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,13 @@ func newReactor(
}

blockDB := dbm.NewMemDB()
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(blockDB)

state, err := sm.MakeGenesisState(genDoc)
state, err := stateStore.LoadFromDBOrGenesisDoc(genDoc)
if err != nil {
panic(fmt.Errorf("error constructing state from genesis file: %w", err))
}
Expand All @@ -101,7 +105,7 @@ func newReactor(
// pool.height is determined from the store.
fastSync := true
db := dbm.NewMemDB()
stateStore := sm.NewStore(db, sm.StoreOptions{
stateStore = sm.NewStore(db, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
Expand Down
6 changes: 2 additions & 4 deletions consensus/byzantine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,13 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, err := sm.MakeGenesisState(genDoc)
require.NoError(t, err)
require.NoError(t, stateStore.Save(state))
state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc)
thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i))
defer os.RemoveAll(thisConfig.RootDir)
ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal
app := appFunc()
vals := types.TM2PB.ValidatorUpdates(state.Validators)
_, err = app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals})
_, err := app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals})
require.NoError(t, err)

blockDB := dbm.NewMemDB()
Expand Down
7 changes: 5 additions & 2 deletions consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,10 @@ func randConsensusNet(t *testing.T, nValidators int, testName string, tickerFunc
configRootDirs := make([]string, 0, nValidators)
for i := 0; i < nValidators; i++ {
stateDB := dbm.NewMemDB() // each state needs its own db
state, _ := sm.MakeGenesisState(genDoc)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc)
thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i))
configRootDirs = append(configRootDirs, thisConfig.RootDir)
for _, opt := range configOpts {
Expand Down Expand Up @@ -815,7 +818,7 @@ func randConsensusNetWithPeers(
DiscardABCIResponses: false,
})
t.Cleanup(func() { _ = stateStore.Close() })
state, _ := sm.MakeGenesisState(genDoc)
state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc)
thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i))
configRootDirs = append(configRootDirs, thisConfig.RootDir)
ensureDir(filepath.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal
Expand Down
5 changes: 2 additions & 3 deletions consensus/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,13 @@ func TestReactorWithEvidence(t *testing.T) {
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, err := sm.MakeGenesisState(genDoc)
require.NoError(t, err)
state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc)
thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i))
defer os.RemoveAll(thisConfig.RootDir)
ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal
app := appFunc()
vals := types.TM2PB.ValidatorUpdates(state.Validators)
_, err = app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals})
_, err := app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals})
require.NoError(t, err)

pv := privVals[i]
Expand Down
11 changes: 7 additions & 4 deletions consensus/replay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ func startNewStateAndWaitForBlock(
t *testing.T,
consensusReplayConfig *cfg.Config,
blockDB dbm.DB,
stateStore sm.Store,
) {
logger := log.TestingLogger()
state, err := sm.MakeGenesisStateFromFile(consensusReplayConfig.GenesisFile())
require.NoError(t, err)
state, _ := stateStore.LoadFromDBOrGenesisFile(consensusReplayConfig.GenesisFile())
privValidator := loadPrivValidator(consensusReplayConfig)
cs := newStateWithConfigAndBlockStore(
consensusReplayConfig,
Expand All @@ -87,7 +87,7 @@ func startNewStateAndWaitForBlock(
bytes, _ := os.ReadFile(cs.config.WalFile())
t.Logf("====== WAL: \n\r%X\n", bytes)

err = cs.Start()
err := cs.Start()
require.NoError(t, err)
defer func() {
if err := cs.Stop(); err != nil {
Expand Down Expand Up @@ -175,6 +175,9 @@ LOOP:
logger := log.NewNopLogger()
blockDB := dbm.NewMemDB()
stateDB := blockDB
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, err := sm.MakeGenesisStateFromFile(consensusReplayConfig.GenesisFile())
require.NoError(t, err)
privValidator := loadPrivValidator(consensusReplayConfig)
Expand Down Expand Up @@ -215,7 +218,7 @@ LOOP:
t.Logf("WAL panicked: %v", err)

// make sure we can make blocks after a crash
startNewStateAndWaitForBlock(t, consensusReplayConfig, blockDB)
startNewStateAndWaitForBlock(t, consensusReplayConfig, blockDB, stateStore)

// stop consensus state and transactions sender (initFn)
cs.Stop() //nolint:errcheck // Logging this error causes failure
Expand Down
12 changes: 1 addition & 11 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,7 @@ func NewNode(ctx context.Context,
DiscardABCIResponses: config.Storage.DiscardABCIResponses,
})

genDoc, err := genesisDocProvider()
if err != nil {
return nil, err
}

err = genDoc.ValidateAndComplete()
if err != nil {
return nil, fmt.Errorf("error in genesis doc: %w", err)
}

state, err := loadStateFromDBOrGenesisDoc(stateStore, stateDB, genDoc)
state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider)
if err != nil {
return nil, err
}
Expand Down
70 changes: 0 additions & 70 deletions node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@ import (
"github.com/cometbft/cometbft/abci/example/kvstore"
cfg "github.com/cometbft/cometbft/config"
"github.com/cometbft/cometbft/crypto/ed25519"
"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/cometbft/cometbft/evidence"
"github.com/cometbft/cometbft/internal/test"
cmtjson "github.com/cometbft/cometbft/libs/json"
"github.com/cometbft/cometbft/libs/log"
cmtos "github.com/cometbft/cometbft/libs/os"
cmtrand "github.com/cometbft/cometbft/libs/rand"
mempl "github.com/cometbft/cometbft/mempool"
"github.com/cometbft/cometbft/p2p"
Expand Down Expand Up @@ -468,73 +465,6 @@ func TestNodeNewNodeCustomReactors(t *testing.T) {
assert.Contains(t, channels, cr.Channels[0].ID)
}

func TestNodeNewNodeGenesisHashMismatch(t *testing.T) {
config := test.ResetTestRoot("node_new_node_genesis_hash")
defer os.RemoveAll(config.RootDir)

// Use goleveldb so we can reuse the same db for the second NewNode()
config.DBBackend = string(dbm.GoLevelDBBackend)

nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
require.NoError(t, err)

n, err := NewNode(
context.Background(),
config,
privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()),
nodeKey,
proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
DefaultGenesisDocProviderFunc(config),
cfg.DefaultDBProvider,
DefaultMetricsProvider(config.Instrumentation),
log.TestingLogger(),
)
require.NoError(t, err)

// Start and stop to close the db for later reading
err = n.Start()
require.NoError(t, err)

err = n.Stop()
require.NoError(t, err)

// Ensure the genesis doc hash is saved to db
stateDB, err := cfg.DefaultDBProvider(&cfg.DBContext{ID: "state", Config: config})
require.NoError(t, err)

genDocHash, err := stateDB.Get(genesisDocHashKey)
require.NoError(t, err)
require.NotNil(t, genDocHash, "genesis doc hash should be saved in db")
require.Len(t, genDocHash, tmhash.Size)

err = stateDB.Close()
require.NoError(t, err)

// Modify the genesis file chain ID to get a different hash
genBytes := cmtos.MustReadFile(config.GenesisFile())
var genesisDoc types.GenesisDoc
err = cmtjson.Unmarshal(genBytes, &genesisDoc)
require.NoError(t, err)

genesisDoc.ChainID = "different-chain-id"
err = genesisDoc.SaveAs(config.GenesisFile())
require.NoError(t, err)

_, err = NewNode(
context.Background(),
config,
privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()),
nodeKey,
proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
DefaultGenesisDocProviderFunc(config),
cfg.DefaultDBProvider,
DefaultMetricsProvider(config.Instrumentation),
log.TestingLogger(),
)
require.Error(t, err, "NewNode should error when genesisDoc is changed")
require.Equal(t, "genesis doc hash in db does not match loaded genesis doc", err.Error())
}

func state(nVals int, height int64) (sm.State, dbm.DB, []types.PrivValidator) {
privVals := make([]types.PrivValidator, nVals)
vals := make([]types.GenesisValidator, nVals)
Expand Down
89 changes: 48 additions & 41 deletions node/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package node
import (
"bytes"
"context"
"errors"
"fmt"
"net"
"strings"
Expand All @@ -17,7 +18,6 @@ import (
cfg "github.com/cometbft/cometbft/config"
cs "github.com/cometbft/cometbft/consensus"
"github.com/cometbft/cometbft/crypto"
"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/cometbft/cometbft/evidence"
"github.com/cometbft/cometbft/statesync"

Expand Down Expand Up @@ -529,60 +529,67 @@ func startStateSync(

//------------------------------------------------------------------------------

var genesisDocHashKey = []byte("genesisDocHash")
var genesisDocKey = []byte("genesisDoc")

// loadStateFromDBOrGenesisDoc attempts to load the state from the
// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the
// database, or creates one using the given genesisDocProvider. On success this also
// returns the genesis doc loaded through the given provider.
func loadStateFromDBOrGenesisDoc(
stateStore sm.Store,
func LoadStateFromDBOrGenesisDocProvider(
stateDB dbm.DB,
genDoc *types.GenesisDoc,
) (sm.State, error) {
// 1. Verify genesisDoc hash in db if exists
genDocHash, err := stateDB.Get(genesisDocHashKey)
genesisDocProvider GenesisDocProvider,
) (sm.State, *types.GenesisDoc, error) {
// Get genesis doc
genDoc, err := loadGenesisDoc(stateDB)
if err != nil {
return sm.State{}, err
}
genDoc, err = genesisDocProvider()
if err != nil {
return sm.State{}, nil, err
}

genDocBytes, err := cmtjson.Marshal(genDoc)
err = genDoc.ValidateAndComplete()
if err != nil {
return sm.State{}, nil, fmt.Errorf("error in genesis doc: %w", err)
}
// save genesis doc to prevent a certain class of user errors (e.g. when it
// was changed, accidentally or not). Also good for audit trail.
if err := saveGenesisDoc(stateDB, genDoc); err != nil {
return sm.State{}, nil, err
}
}
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, err := stateStore.LoadFromDBOrGenesisDoc(genDoc)
if err != nil {
return sm.State{}, fmt.Errorf("failed to save genesis doc hash due to marshaling error: %w", err)
return sm.State{}, nil, err
}
return state, genDoc, nil
}

incomingGenDocHash := tmhash.Sum(genDocBytes)
if len(genDocHash) != 0 && !bytes.Equal(genDocHash, incomingGenDocHash) {
return sm.State{}, fmt.Errorf("genesis doc hash in db does not match loaded genesis doc")
// panics if failed to unmarshal bytes
func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) {
b, err := db.Get(genesisDocKey)
if err != nil {
panic(err)
}

// 2. Attempt to load state form the database
state, err := stateStore.Load()
if len(b) == 0 {
return nil, errors.New("genesis doc not found")
}
var genDoc *types.GenesisDoc
err = cmtjson.Unmarshal(b, &genDoc)
if err != nil {
return sm.State{}, err
panic(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, b))
}
return genDoc, nil
}

if state.IsEmpty() {
// 3. If it's not there, derive it from the genesis doc
state, err = sm.MakeGenesisState(genDoc)
if err != nil {
return sm.State{}, err
}

// 4. save the gensis document to the state store so
// its fetchable by other callers.
if err := stateStore.Save(state); err != nil {
return sm.State{}, err
}

// 5. Save the genDoc hash in the store if it doesn't already exist for future verification
if len(genDocHash) == 0 {
if err := stateDB.SetSync(genesisDocHashKey, incomingGenDocHash); err != nil {
return sm.State{}, fmt.Errorf("failed to save genesis doc hash to db: %w", err)
}
}
// panics if failed to marshal the given genesis document
func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) error {
b, err := cmtjson.Marshal(genDoc)
if err != nil {
return fmt.Errorf("failed to save genesis doc due to marshaling error: %w", err)
}

return state, nil
return db.SetSync(genesisDocKey, b)
}

func createAndStartPrivValidatorSocketClient(
Expand Down
Loading
0