Skip to content
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

Main patch from tm-v0.34.17 #389

Merged
merged 10 commits into from
Apr 6, 2022
92 changes: 82 additions & 10 deletions cmd/ostracon/commands/reset_priv_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package commands

import (
"os"
"path/filepath"

"github.com/spf13/cobra"

Expand All @@ -16,12 +17,22 @@ var ResetAllCmd = &cobra.Command{
Use: "unsafe-reset-all",
Aliases: []string{"unsafe_reset_all"},
Short: "(unsafe) Remove all the data and WAL, reset this node's validator to genesis state",
Run: resetAll,
RunE: resetAllCmd,
PreRun: deprecateSnakeCase,
}

var keepAddrBook bool

// ResetStateCmd removes the database of the specified Tendermint core instance.
var ResetStateCmd = &cobra.Command{
Use: "reset-state",
Short: "Remove all the data and WAL",
RunE: func(cmd *cobra.Command, args []string) error {
return resetState(config.DBDir(), logger)
},
PreRun: deprecateSnakeCase,
}

func init() {
ResetAllCmd.Flags().BoolVar(&keepAddrBook, "keep-addr-book", false, "keep the address book intact")
ResetAllCmd.Flags().String("priv_key_type", config.PrivKeyType,
Expand All @@ -41,12 +52,9 @@ var ResetPrivValidatorCmd = &cobra.Command{

// XXX: this is totally unsafe.
// it's only suitable for testnets.
func resetAll(cmd *cobra.Command, args []string) {
err := ResetAll(config.DBDir(), config.P2P.AddrBookFile(), config.PrivValidatorKeyFile(),
func resetAllCmd(cmd *cobra.Command, args []string) error {
return resetAll(config.DBDir(), config.P2P.AddrBookFile(), config.PrivValidatorKeyFile(),
config.PrivValidatorStateFile(), config.PrivValidatorKeyType(), logger)
if err != nil {
panic(err)
}
}

// XXX: this is totally unsafe.
Expand All @@ -59,9 +67,8 @@ func resetPrivValidator(cmd *cobra.Command, args []string) {
}
}

// ResetAll removes address book files plus all data, and resets the privValdiator data.
// Exported so other CLI tools can use it.
func ResetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile, privKeyType string, logger log.Logger) error {
// resetAll removes address book files plus all data, and resets the privValdiator data.
func resetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile, privKeyType string, logger log.Logger) error {
if keepAddrBook {
logger.Info("The address book remains intact")
} else {
Expand All @@ -72,13 +79,76 @@ func ResetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile, privKeyType
} else {
logger.Error("Error removing all blockchain history", "dir", dbDir, "err", err)
}

// recreate the dbDir since the privVal state needs to live there
if err := tmos.EnsureDir(dbDir, 0700); err != nil {
logger.Error("unable to recreate dbDir", "err", err)
}
return resetFilePV(privValKeyFile, privValStateFile, privKeyType, logger)
}

// resetState removes address book files plus all databases.
func resetState(dbDir string, logger log.Logger) error {
blockdb := filepath.Join(dbDir, "blockstore.db")
state := filepath.Join(dbDir, "state.db")
wal := filepath.Join(dbDir, "cs.wal")
evidence := filepath.Join(dbDir, "evidence.db")
txIndex := filepath.Join(dbDir, "tx_index.db")
peerstore := filepath.Join(dbDir, "peerstore.db")

if tmos.FileExists(blockdb) {
if err := os.RemoveAll(blockdb); err == nil {
logger.Info("Removed all blockstore.db", "dir", blockdb)
} else {
logger.Error("error removing all blockstore.db", "dir", blockdb, "err", err)
}
}

if tmos.FileExists(state) {
if err := os.RemoveAll(state); err == nil {
logger.Info("Removed all state.db", "dir", state)
} else {
logger.Error("error removing all state.db", "dir", state, "err", err)
}
}

if tmos.FileExists(wal) {
if err := os.RemoveAll(wal); err == nil {
logger.Info("Removed all cs.wal", "dir", wal)
} else {
logger.Error("error removing all cs.wal", "dir", wal, "err", err)
}
}

if tmos.FileExists(evidence) {
if err := os.RemoveAll(evidence); err == nil {
logger.Info("Removed all evidence.db", "dir", evidence)
} else {
logger.Error("error removing all evidence.db", "dir", evidence, "err", err)
}
}

if tmos.FileExists(txIndex) {
if err := os.RemoveAll(txIndex); err == nil {
logger.Info("Removed tx_index.db", "dir", txIndex)
} else {
logger.Error("error removing tx_index.db", "dir", txIndex, "err", err)
}
}

if tmos.FileExists(peerstore) {
if err := os.RemoveAll(peerstore); err == nil {
logger.Info("Removed peerstore.db", "dir", peerstore)
} else {
logger.Error("error removing peerstore.db", "dir", peerstore, "err", err)
}
}
if err := tmos.EnsureDir(dbDir, 0700); err != nil {
logger.Error("unable to recreate dbDir", "err", err)
}
return nil
}

func resetFilePV(privValKeyFile, privValStateFile, privKeyType string, logger log.Logger) error {
if _, err := os.Stat(privValKeyFile); err == nil {
pv := privval.LoadFilePVEmptyState(privValKeyFile, privValStateFile)
Expand All @@ -90,7 +160,9 @@ func resetFilePV(privValKeyFile, privValStateFile, privKeyType string, logger lo
if err != nil {
return err
}
pv.Save()
if pv != nil {
pv.Save()
}
logger.Info("Generated private validator file", "keyFile", privValKeyFile,
"stateFile", privValStateFile)
}
Expand Down
33 changes: 33 additions & 0 deletions cmd/ostracon/commands/reset_priv_validator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package commands

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func setupResetCmd(t *testing.T) {
clearConfig(defaultRoot)
config.SetRoot(defaultRoot)
require.NoError(t, os.MkdirAll(filepath.Dir(config.PrivValidatorKeyFile()), 0755))
require.NoError(t, os.MkdirAll(filepath.Dir(config.PrivValidatorStateFile()), 0755))
}

func TestResetAllCmd(t *testing.T) {
setupResetCmd(t)
err := ResetAllCmd.RunE(ResetAllCmd, nil)
require.NoError(t, err)
}

func TestResetStateCmd(t *testing.T) {
setupResetCmd(t)
err := ResetStateCmd.RunE(ResetStateCmd, nil)
require.NoError(t, err)
}

func TestResetPrivValidatorCmd(t *testing.T) {
setupResetCmd(t)
ResetPrivValidatorCmd.Run(ResetPrivValidatorCmd, nil)
}
1 change: 1 addition & 0 deletions cmd/ostracon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func main() {
cmd.ReplayConsoleCmd,
cmd.ResetAllCmd,
cmd.ResetPrivValidatorCmd,
cmd.ResetStateCmd,
cmd.ShowValidatorCmd,
cmd.TestnetFilesCmd,
cmd.ShowNodeIDCmd,
Expand Down
35 changes: 29 additions & 6 deletions consensus/reactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Reactor struct {
mtx tmsync.RWMutex
waitSync bool
eventBus *types.EventBus
rs *cstypes.RoundState

Metrics *Metrics
}
Expand All @@ -58,6 +59,7 @@ func NewReactor(consensusState *State, waitSync bool, async bool, recvBufSize in
conR := &Reactor{
conS: consensusState,
waitSync: waitSync,
rs: consensusState.GetRoundState(),
Metrics: NopMetrics(),
}
conR.BaseReactor = *p2p.NewBaseReactor("Consensus", conR, async, recvBufSize)
Expand All @@ -84,6 +86,7 @@ func (conR *Reactor) OnStart() error {
go conR.peerStatsRoutine()

conR.subscribeToBroadcastEvents()
go conR.updateRoundStateRoutine()

if !conR.WaitSync() {
err := conR.conS.Start()
Expand Down Expand Up @@ -488,11 +491,31 @@ func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage)
}

func (conR *Reactor) sendNewRoundStepMessage(peer p2p.Peer) {
rs := conR.conS.GetRoundState()
rs := conR.getRoundState()
nrsMsg := makeRoundStepMessage(rs)
peer.Send(StateChannel, MustEncode(nrsMsg))
}

func (conR *Reactor) updateRoundStateRoutine() {
t := time.NewTicker(100 * time.Microsecond)
defer t.Stop()
for range t.C {
if !conR.IsRunning() {
return
}
rs := conR.conS.GetRoundState()
conR.mtx.Lock()
conR.rs = rs
conR.mtx.Unlock()
}
}

func (conR *Reactor) getRoundState() *cstypes.RoundState {
conR.mtx.RLock()
defer conR.mtx.RUnlock()
return conR.rs
}

func (conR *Reactor) gossipDataRoutine(peer p2p.Peer, ps *PeerState) {
logger := conR.Logger.With("peer", peer)

Expand All @@ -502,7 +525,7 @@ OUTER_LOOP:
if !peer.IsRunning() || !conR.IsRunning() {
return
}
rs := conR.conS.GetRoundState()
rs := conR.getRoundState()
prs := ps.GetRoundState()

// Send proposal Block parts?
Expand Down Expand Up @@ -645,7 +668,7 @@ OUTER_LOOP:
if !peer.IsRunning() || !conR.IsRunning() {
return
}
rs := conR.conS.GetRoundState()
rs := conR.getRoundState()
prs := ps.GetRoundState()

switch sleeping {
Expand Down Expand Up @@ -779,7 +802,7 @@ OUTER_LOOP:

// Maybe send Height/Round/Prevotes
{
rs := conR.conS.GetRoundState()
rs := conR.getRoundState()
prs := ps.GetRoundState()
if rs.Height == prs.Height {
if maj23, ok := rs.Votes.Prevotes(prs.Round).TwoThirdsMajority(); ok {
Expand All @@ -796,7 +819,7 @@ OUTER_LOOP:

// Maybe send Height/Round/Precommits
{
rs := conR.conS.GetRoundState()
rs := conR.getRoundState()
prs := ps.GetRoundState()
if rs.Height == prs.Height {
if maj23, ok := rs.Votes.Precommits(prs.Round).TwoThirdsMajority(); ok {
Expand All @@ -813,7 +836,7 @@ OUTER_LOOP:

// Maybe send Height/Round/ProposalPOL
{
rs := conR.conS.GetRoundState()
rs := conR.getRoundState()
prs := ps.GetRoundState()
if rs.Height == prs.Height && prs.ProposalPOLRound >= 0 {
if maj23, ok := rs.Votes.Prevotes(prs.ProposalPOLRound).TwoThirdsMajority(); ok {
Expand Down
Loading