diff --git a/block/manager.go b/block/manager.go index 0a5fd87a8..afce8e161 100644 --- a/block/manager.go +++ b/block/manager.go @@ -9,9 +9,9 @@ import ( "code.cloudfoundry.org/go-diodes" + "cosmossdk.io/errors" "github.com/avast/retry-go" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/types/errors" abciconv "github.com/dymensionxyz/dymint/conv/abci" "github.com/dymensionxyz/dymint/node/events" "github.com/dymensionxyz/dymint/p2p" @@ -565,24 +565,30 @@ func (m *Manager) alignStoreWithApp(ctx context.Context, block *types.Block) (bo // Validate incosistency in height wasn't caused by a crash and if so handle it. proxyAppInfo, err := m.executor.GetAppInfo() if err != nil { - m.logger.Error("Failed to get app info", "error", err) - return isRequired, err - } - if uint64(proxyAppInfo.LastBlockHeight) == block.Header.Height { - isRequired = true - m.logger.Info("Skipping block application and only updating store height and state hash", "height", block.Header.Height) - // update the state with the hash, last store height and last validators. - m.lastState.AppHash = *(*[32]byte)(proxyAppInfo.LastBlockAppHash) - m.lastState.LastStoreHeight = block.Header.Height - m.lastState.LastValidators = m.lastState.Validators.Copy() - _, err := m.store.UpdateState(m.lastState, nil) - if err != nil { - m.logger.Error("Failed to update state", "error", err) - return isRequired, err - } - m.store.SetHeight(block.Header.Height) + return isRequired, errors.Wrap(err, "failed to get app info") + } + if uint64(proxyAppInfo.LastBlockHeight) != block.Header.Height { return isRequired, nil } + + isRequired = true + m.logger.Info("Skipping block application and only updating store height and state hash", "height", block.Header.Height) + // update the state with the hash, last store height and last validators. + m.lastState.AppHash = *(*[32]byte)(proxyAppInfo.LastBlockAppHash) + m.lastState.LastStoreHeight = block.Header.Height + m.lastState.LastValidators = m.lastState.Validators.Copy() + + resp, err := m.store.LoadBlockResponses(block.Header.Height) + if err != nil { + return isRequired, errors.Wrap(err, "failed to load block responses") + } + copy(m.lastState.LastResultsHash[:], tmtypes.NewResults(resp.DeliverTxs).Hash()) + + _, err = m.store.UpdateState(m.lastState, nil) + if err != nil { + return isRequired, errors.Wrap(err, "failed to update state") + } + m.store.SetHeight(block.Header.Height) return isRequired, nil } diff --git a/state/executor.go b/state/executor.go index 3d9a2819d..e40eedc73 100644 --- a/state/executor.go +++ b/state/executor.go @@ -175,6 +175,7 @@ func (e *BlockExecutor) Commit(ctx context.Context, state *types.State, block *t } copy(state.AppHash[:], appHash[:]) + copy(state.LastResultsHash[:], tmtypes.NewResults(resp.DeliverTxs).Hash()) err = e.publishEvents(resp, block, *state) if err != nil { @@ -203,6 +204,7 @@ func (e *BlockExecutor) updateState(state types.State, block *types.Block, abciR } hash := block.Header.Hash() + //TODO: we can probably pass the state as a pointer and update it directly s := types.State{ Version: state.Version, ChainID: state.ChainID, @@ -223,8 +225,10 @@ func (e *BlockExecutor) updateState(state types.State, block *types.Block, abciR AppHash: state.AppHash, LastValidators: state.LastValidators.Copy(), LastStoreHeight: state.LastStoreHeight, + + LastResultsHash: state.LastResultsHash, + BaseHeight: state.BaseHeight, } - copy(s.LastResultsHash[:], tmtypes.NewResults(abciResponses.DeliverTxs).Hash()) return s, nil } @@ -276,7 +280,6 @@ func (e *BlockExecutor) validateBlock(state types.State, block *types.Block) err if !bytes.Equal(block.Header.AppHash[:], state.AppHash[:]) { return errors.New("AppHash mismatch") } - if !bytes.Equal(block.Header.LastResultsHash[:], state.LastResultsHash[:]) { return errors.New("LastResultsHash mismatch") } diff --git a/testutil/types.go b/testutil/types.go index 8d900540f..c4b9a3578 100644 --- a/testutil/types.go +++ b/testutil/types.go @@ -39,40 +39,76 @@ func createRandomHashes() [][32]byte { } // GenerateBlocks generates random blocks. -func GenerateBlocks(startHeight uint64, num uint64, proposerKey crypto.PrivKey) ([]*types.Block, error) { +func generateBlock(height uint64) *types.Block { + h := createRandomHashes() + block := &types.Block{ + Header: types.Header{ + Version: types.Version{ + Block: BlockVersion, + App: AppVersion, + }, + NamespaceID: [8]byte{0, 1, 2, 3, 4, 5, 6, 7}, + Height: height, + Time: 4567, + LastHeaderHash: h[0], + LastCommitHash: h[1], + DataHash: h[2], + ConsensusHash: h[3], + // AppHash: h[4], + AppHash: [32]byte{}, + LastResultsHash: getEmptyLastResultsHash(), + ProposerAddress: []byte{4, 3, 2, 1}, + AggregatorsHash: h[6], + }, + Data: types.Data{ + Txs: nil, + IntermediateStateRoots: types.IntermediateStateRoots{RawRootsList: [][]byte{{0x1}}}, + Evidence: types.EvidenceData{Evidence: nil}, + }, + LastCommit: types.Commit{ + Height: 8, + HeaderHash: h[7], + Signatures: []types.Signature{}, + }, + } + + return block +} + +func GenerateBlocksWithTxs(startHeight uint64, num uint64, proposerKey crypto.PrivKey, nTxs int) ([]*types.Block, error) { blocks := make([]*types.Block, num) for i := uint64(0); i < num; i++ { - h := createRandomHashes() - block := &types.Block{ - Header: types.Header{ - Version: types.Version{ - Block: BlockVersion, - App: AppVersion, - }, - NamespaceID: [8]byte{0, 1, 2, 3, 4, 5, 6, 7}, - Height: i + startHeight, - Time: 4567, - LastHeaderHash: h[0], - LastCommitHash: h[1], - DataHash: h[2], - ConsensusHash: h[3], - // AppHash: h[4], - AppHash: [32]byte{}, - LastResultsHash: getEmptyLastResultsHash(), - ProposerAddress: []byte{4, 3, 2, 1}, - AggregatorsHash: h[6], - }, - Data: types.Data{ - Txs: nil, - IntermediateStateRoots: types.IntermediateStateRoots{RawRootsList: [][]byte{{0x1}}}, - Evidence: types.EvidenceData{Evidence: nil}, - }, - LastCommit: types.Commit{ - Height: 8, - HeaderHash: h[7], - Signatures: []types.Signature{}, + + block := generateBlock(i + startHeight) + + block.Data = types.Data{ + Txs: make(types.Txs, nTxs), + IntermediateStateRoots: types.IntermediateStateRoots{ + RawRootsList: make([][]byte, nTxs), }, } + + for i := 0; i < nTxs; i++ { + block.Data.Txs[i] = GetRandomTx() + block.Data.IntermediateStateRoots.RawRootsList[i] = GetRandomBytes(32) + } + + signature, err := generateSignature(proposerKey, &block.Header) + if err != nil { + return nil, err + } + block.LastCommit.Signatures = []types.Signature{signature} + blocks[i] = block + } + return blocks, nil +} + +// GenerateBlocks generates random blocks. +func GenerateBlocks(startHeight uint64, num uint64, proposerKey crypto.PrivKey) ([]*types.Block, error) { + blocks := make([]*types.Block, num) + for i := uint64(0); i < num; i++ { + block := generateBlock(i + startHeight) + signature, err := generateSignature(proposerKey, &block.Header) if err != nil { return nil, err