|
package state
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
|
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
// TODO(#2589):
|
|
// - generalize this past the first height
|
|
// - add txs and build up full State properly
|
|
// - test block.Time (see #2587 - there are no conditions on time for the first height)
|
|
func TestValidateBlockHeader(t *testing.T) {
|
|
var height int64 = 1 // TODO(#2589): generalize
|
|
state, stateDB := state(1, int(height))
|
|
|
|
blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), nil, nil, nil)
|
|
|
|
// A good block passes.
|
|
block := makeBlock(state, height)
|
|
err := blockExec.ValidateBlock(state, block)
|
|
require.NoError(t, err)
|
|
|
|
// some bad values
|
|
wrongHash := tmhash.Sum([]byte("this hash is wrong"))
|
|
wrongVersion1 := state.Version.Consensus
|
|
wrongVersion1.Block += 1
|
|
wrongVersion2 := state.Version.Consensus
|
|
wrongVersion2.App += 1
|
|
|
|
// Manipulation of any header field causes failure.
|
|
testCases := []struct {
|
|
name string
|
|
malleateBlock func(block *types.Block)
|
|
}{
|
|
{"Version wrong1", func(block *types.Block) { block.Version = wrongVersion1 }},
|
|
{"Version wrong2", func(block *types.Block) { block.Version = wrongVersion2 }},
|
|
{"ChainID wrong", func(block *types.Block) { block.ChainID = "not-the-real-one" }},
|
|
{"Height wrong", func(block *types.Block) { block.Height += 10 }},
|
|
{"Time wrong", func(block *types.Block) { block.Time = block.Time.Add(-time.Second * 3600 * 24) }},
|
|
{"NumTxs wrong", func(block *types.Block) { block.NumTxs += 10 }},
|
|
{"TotalTxs wrong", func(block *types.Block) { block.TotalTxs += 10 }},
|
|
|
|
{"LastBlockID wrong", func(block *types.Block) { block.LastBlockID.PartsHeader.Total += 10 }},
|
|
{"LastCommitHash wrong", func(block *types.Block) { block.LastCommitHash = wrongHash }},
|
|
{"DataHash wrong", func(block *types.Block) { block.DataHash = wrongHash }},
|
|
|
|
{"ValidatorsHash wrong", func(block *types.Block) { block.ValidatorsHash = wrongHash }},
|
|
{"NextValidatorsHash wrong", func(block *types.Block) { block.NextValidatorsHash = wrongHash }},
|
|
{"ConsensusHash wrong", func(block *types.Block) { block.ConsensusHash = wrongHash }},
|
|
{"AppHash wrong", func(block *types.Block) { block.AppHash = wrongHash }},
|
|
{"LastResultsHash wrong", func(block *types.Block) { block.LastResultsHash = wrongHash }},
|
|
|
|
{"EvidenceHash wrong", func(block *types.Block) { block.EvidenceHash = wrongHash }},
|
|
{"Proposer wrong", func(block *types.Block) { block.ProposerAddress = ed25519.GenPrivKey().PubKey().Address() }},
|
|
{"Proposer invalid", func(block *types.Block) { block.ProposerAddress = []byte("wrong size") }},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
block := makeBlock(state, height)
|
|
tc.malleateBlock(block)
|
|
err := blockExec.ValidateBlock(state, block)
|
|
require.Error(t, err, tc.name)
|
|
}
|
|
}
|
|
|
|
/*
|
|
TODO(#2589):
|
|
- test Block.Data.Hash() == Block.DataHash
|
|
- test len(Block.Data.Txs) == Block.NumTxs
|
|
*/
|
|
func TestValidateBlockData(t *testing.T) {
|
|
}
|
|
|
|
/*
|
|
TODO(#2589):
|
|
- test len(block.LastCommit.Precommits) == state.LastValidators.Size()
|
|
- test state.LastValidators.VerifyCommit
|
|
*/
|
|
func TestValidateBlockCommit(t *testing.T) {
|
|
}
|
|
|
|
/*
|
|
TODO(#2589):
|
|
- test good/bad evidence in block
|
|
*/
|
|
func TestValidateBlockEvidence(t *testing.T) {
|
|
var height int64 = 1 // TODO(#2589): generalize
|
|
state, stateDB := state(1, int(height))
|
|
|
|
blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), nil, nil, nil)
|
|
|
|
// make some evidence
|
|
addr, _ := state.Validators.GetByIndex(0)
|
|
goodEvidence := types.NewMockGoodEvidence(height, 0, addr)
|
|
|
|
// A block with a couple pieces of evidence passes.
|
|
block := makeBlock(state, height)
|
|
block.Evidence.Evidence = []types.Evidence{goodEvidence, goodEvidence}
|
|
block.EvidenceHash = block.Evidence.Hash()
|
|
err := blockExec.ValidateBlock(state, block)
|
|
require.NoError(t, err)
|
|
|
|
// A block with too much evidence fails.
|
|
maxBlockSize := state.ConsensusParams.BlockSize.MaxBytes
|
|
maxNumEvidence, _ := types.MaxEvidencePerBlock(maxBlockSize)
|
|
require.True(t, maxNumEvidence > 2)
|
|
for i := int64(0); i < maxNumEvidence; i++ {
|
|
block.Evidence.Evidence = append(block.Evidence.Evidence, goodEvidence)
|
|
}
|
|
block.EvidenceHash = block.Evidence.Hash()
|
|
err = blockExec.ValidateBlock(state, block)
|
|
require.Error(t, err)
|
|
_, ok := err.(*types.ErrEvidenceOverflow)
|
|
require.True(t, ok)
|
|
}
|
|
|
|
// always returns true if asked if any evidence was already committed.
|
|
type mockEvPoolAlwaysCommitted struct{}
|
|
|
|
func (m mockEvPoolAlwaysCommitted) PendingEvidence(int64) []types.Evidence { return nil }
|
|
func (m mockEvPoolAlwaysCommitted) AddEvidence(types.Evidence) error { return nil }
|
|
func (m mockEvPoolAlwaysCommitted) Update(*types.Block, State) {}
|
|
func (m mockEvPoolAlwaysCommitted) IsCommitted(types.Evidence) bool { return true }
|
|
|
|
func TestValidateFailBlockOnCommittedEvidence(t *testing.T) {
|
|
var height int64 = 1
|
|
state, stateDB := state(1, int(height))
|
|
|
|
blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), nil, nil, mockEvPoolAlwaysCommitted{})
|
|
// A block with a couple pieces of evidence passes.
|
|
block := makeBlock(state, height)
|
|
addr, _ := state.Validators.GetByIndex(0)
|
|
alreadyCommittedEvidence := types.NewMockGoodEvidence(height, 0, addr)
|
|
block.Evidence.Evidence = []types.Evidence{alreadyCommittedEvidence}
|
|
block.EvidenceHash = block.Evidence.Hash()
|
|
err := blockExec.ValidateBlock(state, block)
|
|
|
|
require.Error(t, err)
|
|
require.IsType(t, err, &types.ErrEvidenceInvalid{})
|
|
}
|
|
|
|
/*
|
|
TODO(#2589):
|
|
- test unmarshalling BlockParts that are too big into a Block that
|
|
(note this logic happens in the consensus, not in the validation here).
|
|
- test making blocks from the types.MaxXXX functions works/fails as expected
|
|
*/
|
|
func TestValidateBlockSize(t *testing.T) {
|
|
}
|