diff --git a/consensus/state.go b/consensus/state.go index 683612496..84488731f 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1015,7 +1015,8 @@ func (cs *ConsensusState) stageBlock(block *types.Block, blockParts *types.PartS } // Already staged? - if cs.stagedBlock == block { + blockHash := block.Hash() + if cs.stagedBlock != nil && len(blockHash) != 0 && bytes.Equal(cs.stagedBlock.Hash(), blockHash) { return nil } diff --git a/state/state.go b/state/state.go index a3f3586eb..0fcd64f7b 100644 --- a/state/state.go +++ b/state/state.go @@ -633,6 +633,7 @@ func (s *State) AppendBlock(block *types.Block, blockPartsHeader types.PartSetHe return nil } +// Mutates the block in place and updates it with new state hash. func (s *State) SetBlockStateHash(block *types.Block) error { sCopy := s.Copy() err := sCopy.appendBlock(block, types.PartSetHeader{}) diff --git a/types/block.go b/types/block.go index 176ce4385..c00e90ccb 100644 --- a/types/block.go +++ b/types/block.go @@ -55,16 +55,24 @@ func (b *Block) ValidateBasic(lastBlockHeight uint, lastBlockHash []byte, return nil } +// Computes and returns the block hash. +// If the block is incomplete (e.g. missing Header.StateHash) +// then the hash is nil, to prevent the usage of that hash. func (b *Block) Hash() []byte { if b.Header == nil || b.Validation == nil || b.Data == nil { return nil } - hashes := [][]byte{ - b.Header.Hash(), - b.Validation.Hash(), - b.Data.Hash(), + hashHeader := b.Header.Hash() + hashValidation := b.Validation.Hash() + hashData := b.Data.Hash() + + // If hashHeader is nil, required fields are missing. + if len(hashHeader) == 0 { + return nil } - // Merkle hash from sub-hashes. + + // Merkle hash from subhashes. + hashes := [][]byte{hashHeader, hashValidation, hashData} return merkle.HashFromHashes(hashes) } @@ -125,7 +133,12 @@ type Header struct { StateHash []byte } +// NOTE: hash is nil if required fields are missing. func (h *Header) Hash() []byte { + if len(h.StateHash) == 0 { + return nil + } + buf := new(bytes.Buffer) hasher, n, err := sha256.New(), new(int64), new(error) binary.WriteBinary(h, buf, n, err) diff --git a/vm/test/fake_app_state.go b/vm/test/fake_app_state.go index f31ed80e9..be11467ea 100644 --- a/vm/test/fake_app_state.go +++ b/vm/test/fake_app_state.go @@ -1,4 +1,4 @@ -package main +package vm import ( "fmt"