2017-02-21 23:40:26 +04:00
|
|
|
package state
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
2017-12-15 12:12:45 -06:00
|
|
|
"time"
|
2017-02-21 23:40:26 +04:00
|
|
|
|
2017-12-11 12:26:19 -06:00
|
|
|
"github.com/stretchr/testify/assert"
|
2017-02-21 23:40:26 +04:00
|
|
|
"github.com/stretchr/testify/require"
|
2017-10-04 16:40:45 -04:00
|
|
|
|
2018-02-27 14:01:10 +00:00
|
|
|
"github.com/tendermint/abci/example/kvstore"
|
2017-12-11 12:26:19 -06:00
|
|
|
abci "github.com/tendermint/abci/types"
|
2017-02-21 23:40:26 +04:00
|
|
|
crypto "github.com/tendermint/go-crypto"
|
2018-01-06 01:26:51 -05:00
|
|
|
cmn "github.com/tendermint/tmlibs/common"
|
2017-05-01 21:25:10 -04:00
|
|
|
dbm "github.com/tendermint/tmlibs/db"
|
2017-05-02 11:53:32 +04: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 23:40:26 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
privKey = crypto.GenPrivKeyEd25519FromSecret([]byte("execution_test"))
|
|
|
|
chainID = "execution_chain"
|
|
|
|
testPartSize = 65536
|
|
|
|
nTxsPerBlock = 10
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestApplyBlock(t *testing.T) {
|
2018-02-27 14:01:10 +00:00
|
|
|
cc := proxy.NewLocalClientCreator(kvstore.NewKVStoreApplication())
|
2017-05-01 21:25:10 -04:00
|
|
|
proxyApp := proxy.NewAppConns(cc, nil)
|
2017-11-06 13:20:39 -05:00
|
|
|
err := proxyApp.Start()
|
2017-02-21 23:40:26 +04:00
|
|
|
require.Nil(t, err)
|
|
|
|
defer proxyApp.Stop()
|
|
|
|
|
2017-12-27 20:03:48 -05:00
|
|
|
state, stateDB := state(), dbm.NewMemDB()
|
2017-02-21 23:40:26 +04:00
|
|
|
|
2017-12-28 18:26:13 -05:00
|
|
|
blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(),
|
2018-06-04 14:13:39 -07:00
|
|
|
MockMempool{}, MockEvidencePool{})
|
2017-11-19 22:44:46 +00:00
|
|
|
|
2017-12-27 20:03:48 -05:00
|
|
|
block := makeBlock(state, 1)
|
|
|
|
blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
|
|
|
|
|
|
|
|
state, err = blockExec.ApplyBlock(state, blockID, block)
|
2017-02-21 23:40:26 +04:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
// TODO check state and mempool
|
|
|
|
}
|
|
|
|
|
2017-12-11 12:26:19 -06:00
|
|
|
// TestBeginBlockAbsentValidators ensures we send absent validators list.
|
|
|
|
func TestBeginBlockAbsentValidators(t *testing.T) {
|
|
|
|
app := &testApp{}
|
|
|
|
cc := proxy.NewLocalClientCreator(app)
|
|
|
|
proxyApp := proxy.NewAppConns(cc, nil)
|
|
|
|
err := proxyApp.Start()
|
|
|
|
require.Nil(t, err)
|
|
|
|
defer proxyApp.Stop()
|
|
|
|
|
|
|
|
state := state()
|
|
|
|
|
|
|
|
prevHash := state.LastBlockID.Hash
|
|
|
|
prevParts := types.PartSetHeader{}
|
|
|
|
prevBlockID := types.BlockID{prevHash, prevParts}
|
|
|
|
|
2017-12-15 12:12:45 -06:00
|
|
|
now := time.Now().UTC()
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
lastCommitPrecommits []*types.Vote
|
|
|
|
expectedAbsentValidators []int32
|
|
|
|
}{
|
2018-04-03 06:50:53 -07:00
|
|
|
{"none absent", []*types.Vote{{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}, {ValidatorIndex: 1, Timestamp: now}}, []int32{}},
|
|
|
|
{"one absent", []*types.Vote{{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}, nil}, []int32{1}},
|
2017-12-15 12:12:45 -06:00
|
|
|
{"multiple absent", []*types.Vote{nil, nil}, []int32{0, 1}},
|
|
|
|
}
|
2017-12-11 12:26:19 -06:00
|
|
|
|
2017-12-15 12:12:45 -06:00
|
|
|
for _, tc := range testCases {
|
|
|
|
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: tc.lastCommitPrecommits}
|
2017-12-11 12:26:19 -06:00
|
|
|
|
2017-12-20 23:53:15 -05:00
|
|
|
block, _ := state.MakeBlock(2, makeTxs(2), lastCommit)
|
2017-12-27 20:03:48 -05:00
|
|
|
_, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger())
|
2017-12-15 12:12:45 -06:00
|
|
|
require.Nil(t, err, tc.desc)
|
|
|
|
|
|
|
|
// -> app must receive an index of the absent validator
|
2018-05-31 22:46:19 -04:00
|
|
|
assert.Equal(t, tc.expectedAbsentValidators, app.Validators, tc.desc)
|
2017-12-15 12:12:45 -06:00
|
|
|
}
|
2017-12-11 12:26:19 -06:00
|
|
|
}
|
|
|
|
|
2017-12-29 11:26:55 -05: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()
|
|
|
|
|
|
|
|
state := state()
|
|
|
|
|
|
|
|
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
|
2018-01-06 01:26:51 -05:00
|
|
|
expectedByzantineValidators []abci.Evidence
|
2017-12-29 11:26:55 -05:00
|
|
|
}{
|
2018-01-06 01:26:51 -05:00
|
|
|
{"none byzantine", []types.Evidence{}, []abci.Evidence{}},
|
2018-05-31 22:46:19 -04:00
|
|
|
{"one byzantine", []types.Evidence{ev1}, []abci.Evidence{types.TM2PB.Evidence(ev1)}},
|
2018-01-06 01:26:51 -05:00
|
|
|
{"multiple byzantine", []types.Evidence{ev1, ev2}, []abci.Evidence{
|
2018-05-31 22:46:19 -04:00
|
|
|
types.TM2PB.Evidence(ev1),
|
|
|
|
types.TM2PB.Evidence(ev1)}},
|
2017-12-29 11:26:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
lastCommit := &types.Commit{BlockID: prevBlockID}
|
|
|
|
|
|
|
|
block, _ := state.MakeBlock(10, makeTxs(2), lastCommit)
|
|
|
|
block.Evidence.Evidence = tc.evidence
|
|
|
|
_, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger())
|
|
|
|
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 23:40:26 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// make some bogus txs
|
2017-12-01 19:04:53 -06:00
|
|
|
func makeTxs(height int64) (txs []types.Tx) {
|
2017-02-21 23:40:26 +04:00
|
|
|
for i := 0; i < nTxsPerBlock; i++ {
|
2017-11-30 13:08:38 -06:00
|
|
|
txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
|
2017-02-21 23:40:26 +04:00
|
|
|
}
|
|
|
|
return txs
|
|
|
|
}
|
|
|
|
|
2017-12-27 20:03:48 -05:00
|
|
|
func state() State {
|
|
|
|
s, _ := MakeGenesisState(&types.GenesisDoc{
|
2017-02-21 23:40:26 +04:00
|
|
|
ChainID: chainID,
|
|
|
|
Validators: []types.GenesisValidator{
|
2017-09-05 16:37:20 -04:00
|
|
|
{privKey.PubKey(), 10000, "test"},
|
2017-02-21 23:40:26 +04:00
|
|
|
},
|
|
|
|
AppHash: nil,
|
|
|
|
})
|
2017-09-20 18:29:36 -04:00
|
|
|
return s
|
2017-02-21 23:40:26 +04:00
|
|
|
}
|
|
|
|
|
2017-12-27 20:03:48 -05:00
|
|
|
func makeBlock(state State, height int64) *types.Block {
|
2017-12-20 23:53:15 -05:00
|
|
|
block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit))
|
2017-02-21 23:40:26 +04:00
|
|
|
return block
|
|
|
|
}
|
2017-12-11 12:26:19 -06:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
var _ abci.Application = (*testApp)(nil)
|
|
|
|
|
|
|
|
type testApp struct {
|
|
|
|
abci.BaseApplication
|
|
|
|
|
2018-05-31 22:46:19 -04:00
|
|
|
Validators []abci.SigningValidator
|
2018-01-06 01:26:51 -05:00
|
|
|
ByzantineValidators []abci.Evidence
|
2017-12-11 12:26:19 -06:00
|
|
|
}
|
|
|
|
|
2018-02-27 14:01:10 +00:00
|
|
|
func NewKVStoreApplication() *testApp {
|
2017-12-11 12:26:19 -06: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 22:46:19 -04:00
|
|
|
app.Validators = req.Validators
|
2017-12-29 11:26:55 -05:00
|
|
|
app.ByzantineValidators = req.ByzantineValidators
|
2017-12-11 12:26:19 -06:00
|
|
|
return abci.ResponseBeginBlock{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *testApp) DeliverTx(tx []byte) abci.ResponseDeliverTx {
|
2018-01-06 01:26:51 -05:00
|
|
|
return abci.ResponseDeliverTx{Tags: []cmn.KVPair{}}
|
2017-12-11 12:26:19 -06: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
|
|
|
|
}
|