tendermint/state/execution_test.go

221 lines
6.2 KiB
Go
Raw Normal View History

2017-02-21 11:40:26 -08:00
package state
import (
2018-05-31 20:29:46 -07:00
"fmt"
2017-02-21 11:40:26 -08:00
"testing"
2017-12-15 10:12:45 -08:00
"time"
2017-02-21 11:40:26 -08:00
2017-12-11 10:26:19 -08:00
"github.com/stretchr/testify/assert"
2017-02-21 11:40:26 -08:00
"github.com/stretchr/testify/require"
2017-10-04 13:40:45 -07:00
"github.com/tendermint/abci/example/kvstore"
2017-12-11 10:26:19 -08:00
abci "github.com/tendermint/abci/types"
2017-02-21 11:40:26 -08:00
crypto "github.com/tendermint/go-crypto"
cmn "github.com/tendermint/tmlibs/common"
2017-05-01 18:25:10 -07:00
dbm "github.com/tendermint/tmlibs/db"
2017-05-02 00:53:32 -07:00
"github.com/tendermint/tmlibs/log"
2018-06-04 14:13:39 -07:00
"github.com/tendermint/tendermint/proxy"
"github.com/tendermint/tendermint/types"
2017-02-21 11:40:26 -08:00
)
var (
chainID = "execution_chain"
testPartSize = 65536
nTxsPerBlock = 10
)
func TestApplyBlock(t *testing.T) {
cc := proxy.NewLocalClientCreator(kvstore.NewKVStoreApplication())
2017-05-01 18:25:10 -07:00
proxyApp := proxy.NewAppConns(cc, nil)
err := proxyApp.Start()
2017-02-21 11:40:26 -08:00
require.Nil(t, err)
defer proxyApp.Stop()
2018-05-31 20:29:46 -07:00
state, stateDB := state(1), dbm.NewMemDB()
2017-02-21 11:40:26 -08:00
2017-12-28 15:26:13 -08:00
blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(),
2018-06-04 14:13:39 -07:00
MockMempool{}, MockEvidencePool{})
2017-12-27 17:03:48 -08:00
block := makeBlock(state, 1)
blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
state, err = blockExec.ApplyBlock(state, blockID, block)
2017-02-21 11:40:26 -08:00
require.Nil(t, err)
// TODO check state and mempool
}
2018-05-31 20:29:46 -07:00
// TestBeginBlockValidators ensures we send absent validators list.
func TestBeginBlockValidators(t *testing.T) {
2017-12-11 10:26:19 -08:00
app := &testApp{}
cc := proxy.NewLocalClientCreator(app)
proxyApp := proxy.NewAppConns(cc, nil)
err := proxyApp.Start()
require.Nil(t, err)
defer proxyApp.Stop()
2018-05-31 20:29:46 -07:00
state := state(2)
2017-12-11 10:26:19 -08:00
prevHash := state.LastBlockID.Hash
prevParts := types.PartSetHeader{}
prevBlockID := types.BlockID{prevHash, prevParts}
2017-12-15 10:12:45 -08:00
now := time.Now().UTC()
2018-05-31 20:29:46 -07:00
vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
2017-12-15 10:12:45 -08:00
testCases := []struct {
desc string
lastCommitPrecommits []*types.Vote
2018-05-31 20:29:46 -07:00
expectedAbsentValidators []int
2017-12-15 10:12:45 -08:00
}{
2018-05-31 20:29:46 -07:00
{"none absent", []*types.Vote{vote0, vote1}, []int{}},
{"one absent", []*types.Vote{vote0, nil}, []int{1}},
{"multiple absent", []*types.Vote{nil, nil}, []int{0, 1}},
2017-12-15 10:12:45 -08:00
}
2017-12-11 10:26:19 -08:00
2017-12-15 10:12:45 -08:00
for _, tc := range testCases {
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: tc.lastCommitPrecommits}
2017-12-11 10:26:19 -08:00
block, _ := state.MakeBlock(2, makeTxs(2), lastCommit)
2018-05-31 20:29:46 -07:00
_, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators)
2017-12-15 10:12:45 -08:00
require.Nil(t, err, tc.desc)
2018-05-31 20:29:46 -07:00
// -> app receives a list of validators with a bool indicating if they signed
ctr := 0
for i, v := range app.Validators {
if ctr < len(tc.expectedAbsentValidators) &&
tc.expectedAbsentValidators[ctr] == i {
assert.False(t, v.SignedLastBlock)
ctr++
} else {
assert.True(t, v.SignedLastBlock)
}
}
2017-12-15 10:12:45 -08:00
}
2017-12-11 10:26:19 -08:00
}
// TestBeginBlockByzantineValidators ensures we send byzantine validators list.
func TestBeginBlockByzantineValidators(t *testing.T) {
app := &testApp{}
cc := proxy.NewLocalClientCreator(app)
proxyApp := proxy.NewAppConns(cc, nil)
err := proxyApp.Start()
require.Nil(t, err)
defer proxyApp.Stop()
2018-05-31 20:29:46 -07:00
state := state(2)
prevHash := state.LastBlockID.Hash
prevParts := types.PartSetHeader{}
prevBlockID := types.BlockID{prevHash, prevParts}
height1, idx1, val1 := int64(8), 0, []byte("val1")
height2, idx2, val2 := int64(3), 1, []byte("val2")
ev1 := types.NewMockGoodEvidence(height1, idx1, val1)
ev2 := types.NewMockGoodEvidence(height2, idx2, val2)
testCases := []struct {
desc string
evidence []types.Evidence
expectedByzantineValidators []abci.Evidence
}{
{"none byzantine", []types.Evidence{}, []abci.Evidence{}},
2018-05-31 19:46:19 -07:00
{"one byzantine", []types.Evidence{ev1}, []abci.Evidence{types.TM2PB.Evidence(ev1)}},
{"multiple byzantine", []types.Evidence{ev1, ev2}, []abci.Evidence{
2018-05-31 19:46:19 -07:00
types.TM2PB.Evidence(ev1),
2018-05-31 20:29:46 -07:00
types.TM2PB.Evidence(ev2)}},
}
2018-05-31 20:29:46 -07:00
now := time.Now().UTC()
vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
votes := []*types.Vote{vote0, vote1}
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes}
for _, tc := range testCases {
block, _ := state.MakeBlock(10, makeTxs(2), lastCommit)
block.Evidence.Evidence = tc.evidence
2018-05-31 20:29:46 -07:00
_, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators)
require.Nil(t, err, tc.desc)
// -> app must receive an index of the byzantine validator
assert.Equal(t, tc.expectedByzantineValidators, app.ByzantineValidators, tc.desc)
}
}
2017-02-21 11:40:26 -08:00
//----------------------------------------------------------------------------
// make some bogus txs
func makeTxs(height int64) (txs []types.Tx) {
2017-02-21 11:40:26 -08:00
for i := 0; i < nTxsPerBlock; i++ {
2017-11-30 11:08:38 -08:00
txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
2017-02-21 11:40:26 -08:00
}
return txs
}
2018-05-31 20:29:46 -07:00
func state(nVals int) State {
vals := make([]types.GenesisValidator, nVals)
for i := 0; i < nVals; i++ {
secret := []byte(fmt.Sprintf("test%d", i))
pk := crypto.GenPrivKeyEd25519FromSecret(secret)
vals[i] = types.GenesisValidator{
pk.PubKey(), 1000, fmt.Sprintf("test%d", i),
}
}
2017-12-27 17:03:48 -08:00
s, _ := MakeGenesisState(&types.GenesisDoc{
2018-05-31 20:29:46 -07:00
ChainID: chainID,
Validators: vals,
AppHash: nil,
2017-02-21 11:40:26 -08:00
})
return s
2017-02-21 11:40:26 -08:00
}
2017-12-27 17:03:48 -08:00
func makeBlock(state State, height int64) *types.Block {
block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit))
2017-02-21 11:40:26 -08:00
return block
}
2017-12-11 10:26:19 -08:00
//----------------------------------------------------------------------------
var _ abci.Application = (*testApp)(nil)
type testApp struct {
abci.BaseApplication
2018-05-31 19:46:19 -07:00
Validators []abci.SigningValidator
ByzantineValidators []abci.Evidence
2017-12-11 10:26:19 -08:00
}
func NewKVStoreApplication() *testApp {
2017-12-11 10:26:19 -08:00
return &testApp{}
}
func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) {
return abci.ResponseInfo{}
}
func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
2018-05-31 19:46:19 -07:00
app.Validators = req.Validators
app.ByzantineValidators = req.ByzantineValidators
2017-12-11 10:26:19 -08:00
return abci.ResponseBeginBlock{}
}
func (app *testApp) DeliverTx(tx []byte) abci.ResponseDeliverTx {
return abci.ResponseDeliverTx{Tags: []cmn.KVPair{}}
2017-12-11 10:26:19 -08:00
}
func (app *testApp) CheckTx(tx []byte) abci.ResponseCheckTx {
return abci.ResponseCheckTx{}
}
func (app *testApp) Commit() abci.ResponseCommit {
return abci.ResponseCommit{}
}
func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) {
return
}