diff --git a/internal/consensus/replay.go b/internal/consensus/replay.go index 5d097df21..10df0cd10 100644 --- a/internal/consensus/replay.go +++ b/internal/consensus/replay.go @@ -246,14 +246,14 @@ func (h *Handshaker) Handshake(ctx context.Context, appClient abciclient.Client) return fmt.Errorf("error calling Info: %w", err) } - blockHeight := res.LastBlockHeight - if blockHeight < 0 { - return fmt.Errorf("got a negative last block height (%d) from the app", blockHeight) + appBlockHeight := res.LastBlockHeight + if appBlockHeight < 0 { + return fmt.Errorf("got a negative last block height (%d) from the app", appBlockHeight) } appHash := res.LastBlockAppHash h.logger.Info("ABCI Handshake App Info", - "height", blockHeight, + "height", appBlockHeight, "hash", appHash, "software-version", res.Version, "protocol-version", res.AppVersion, @@ -262,16 +262,17 @@ func (h *Handshaker) Handshake(ctx context.Context, appClient abciclient.Client) // Only set the version if there is no existing state. if h.initialState.LastBlockHeight == 0 { h.initialState.Version.Consensus.App = res.AppVersion + h.initialState.ConsensusParams.Version.AppVersion = res.AppVersion } // Replay blocks up to the latest in the blockstore. - _, err = h.ReplayBlocks(ctx, h.initialState, appHash, blockHeight, appClient) + _, err = h.ReplayBlocks(ctx, h.initialState, appHash, appBlockHeight, appClient) if err != nil { return fmt.Errorf("error on replay: %w", err) } h.logger.Info("Completed ABCI Handshake - Tendermint and App are synced", - "appHeight", blockHeight, "appHash", appHash) + "appHeight", appBlockHeight, "appHash", appHash) // TODO: (on restart) replay mempool diff --git a/internal/consensus/replay_test.go b/internal/consensus/replay_test.go index d24e55d67..6f45e34bf 100644 --- a/internal/consensus/replay_test.go +++ b/internal/consensus/replay_test.go @@ -1288,3 +1288,48 @@ func (ica *initChainApp) InitChain(req abci.RequestInitChain) abci.ResponseInitC Validators: ica.vals, } } + +func TestReplayUpdateAppVerion(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := log.NewNopLogger() + + app := kvstore.NewApplication() + client := abciclient.NewLocalClient(logger, app) + + cfg, err := ResetConfig(t.TempDir(), "replay_test_") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(cfg.RootDir) }) + + privVal, err := privval.LoadFilePV(cfg.PrivValidator.KeyFile(), cfg.PrivValidator.StateFile()) + require.NoError(t, err) + pubKey, err := privVal.GetPubKey(ctx) + require.NoError(t, err) + + stateDB, state, store := stateAndStore(t, cfg, pubKey, 0x0) + stateStore := sm.NewStore(stateDB) + + // we modify the app version to the initial state for simulating the appversion update in the genesis file. + testGenesusAppVer := kvstore.ProtocolVersion + 1 + state.Version.Consensus.App = testGenesusAppVer + state.ConsensusParams.Version.AppVersion = testGenesusAppVer + require.NoError(t, stateStore.Save(state)) + + // the genDoc has the default genesis app version which it's fine because it's be used in the app InitChain request. + genDoc, err := sm.MakeGenesisDocFromFile(cfg.GenesisFile()) + require.NoError(t, err) + + handshaker := NewHandshaker(logger, stateStore, state, store, nil, genDoc) + proxyApp := proxy.New(client, logger, proxy.NopMetrics()) + require.NoError(t, proxyApp.Start(ctx), "Error starting proxy app connections") + + require.NoError(t, handshaker.Handshake(ctx, proxyApp), "error on abci handshake") + + // reload the state, check the app version was updated. + state, err = stateStore.Load() + require.NoError(t, err) + + require.Equal(t, kvstore.ProtocolVersion, state.Version.Consensus.App) + require.Equal(t, kvstore.ProtocolVersion, state.ConsensusParams.Version.AppVersion) +}