diff --git a/state/execution.go b/state/execution.go index 86da99c5a..052510e87 100644 --- a/state/execution.go +++ b/state/execution.go @@ -73,7 +73,7 @@ func (blockExec *BlockExecutor) ApplyBlock(state State, blockID types.BlockID, b return state, ErrInvalidBlock(err) } - abciResponses, err := execBlockOnProxyApp(blockExec.logger, blockExec.proxyApp, block) + abciResponses, err := execBlockOnProxyApp(blockExec.logger, blockExec.proxyApp, block, s.LastValidators) if err != nil { return state, ErrProxyAppConn(err) } @@ -157,7 +157,8 @@ func (blockExec *BlockExecutor) Commit(block *types.Block) ([]byte, error) { // Executes block's transactions on proxyAppConn. // Returns a list of transaction results and updates to the validator set -func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus, block *types.Block) (*ABCIResponses, error) { +func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus, + block *types.Block, valSet *types.ValidatorSet) (*ABCIResponses, error) { var validTxs, invalidTxs = 0, 0 txIndex := 0 @@ -184,26 +185,26 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus, proxyAppConn.SetResponseCallback(proxyCb) // determine which validators did not sign last block - absentVals := make([]int32, 0) - for valI, vote := range block.LastCommit.Precommits { - if vote == nil { - absentVals = append(absentVals, int32(valI)) + signVals := make([]abci.SigningValidator, len(block.LastCommit.Precommits)) + for i, val := range valSet.Validators { + vote := block.LastCommit.Precommits[i] + val := abci.SigningValidator{ + Validator: types.TM2PB.Validator(val), + SignedLastBlock: vote != nil, } + signVals[i] = val } byzantineVals := make([]abci.Evidence, len(block.Evidence.Evidence)) for i, ev := range block.Evidence.Evidence { - byzantineVals[i] = abci.Evidence{ - // TODO: fill this in - Height: ev.Height(), - } + byzantineVals[i] = types.TM2PB.Evidence(ev) } // Begin block _, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{ - Hash: block.Hash(), - Header: types.TM2PB.Header(block.Header), - // TODO: fill this in + Hash: block.Hash(), + Header: types.TM2PB.Header(block.Header), + Validators: signVals, ByzantineValidators: byzantineVals, }) if err != nil { @@ -355,8 +356,9 @@ func fireEvents(logger log.Logger, eventBus types.BlockEventPublisher, block *ty // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state. // It returns the application root hash (result of abci.Commit). -func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block, logger log.Logger) ([]byte, error) { - _, err := execBlockOnProxyApp(logger, appConnConsensus, block) +func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block, + logger log.Logger, valSet *types.ValidatorSet) ([]byte, error) { + _, err := execBlockOnProxyApp(logger, appConnConsensus, block, valSet) if err != nil { logger.Error("Error executing block on proxy app", "height", block.Height, "err", err) return nil, err diff --git a/state/execution_test.go b/state/execution_test.go index 2d14f35f4..e31a0fd13 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -1,6 +1,7 @@ package state import ( + "fmt" "testing" "time" @@ -19,7 +20,6 @@ import ( ) var ( - privKey = crypto.GenPrivKeyEd25519FromSecret([]byte("execution_test")) chainID = "execution_chain" testPartSize = 65536 nTxsPerBlock = 10 @@ -32,7 +32,7 @@ func TestApplyBlock(t *testing.T) { require.Nil(t, err) defer proxyApp.Stop() - state, stateDB := state(), dbm.NewMemDB() + state, stateDB := state(1), dbm.NewMemDB() blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), MockMempool{}, MockEvidencePool{}) @@ -46,8 +46,8 @@ func TestApplyBlock(t *testing.T) { // TODO check state and mempool } -// TestBeginBlockAbsentValidators ensures we send absent validators list. -func TestBeginBlockAbsentValidators(t *testing.T) { +// TestBeginBlockValidators ensures we send absent validators list. +func TestBeginBlockValidators(t *testing.T) { app := &testApp{} cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc, nil) @@ -55,32 +55,45 @@ func TestBeginBlockAbsentValidators(t *testing.T) { require.Nil(t, err) defer proxyApp.Stop() - state := state() + state := state(2) prevHash := state.LastBlockID.Hash prevParts := types.PartSetHeader{} prevBlockID := types.BlockID{prevHash, prevParts} now := time.Now().UTC() + vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit} + vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now} + testCases := []struct { desc string lastCommitPrecommits []*types.Vote - expectedAbsentValidators []int32 + expectedAbsentValidators []int }{ - {"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}}, - {"multiple absent", []*types.Vote{nil, nil}, []int32{0, 1}}, + {"none absent", []*types.Vote{vote0, vote1}, []int{}}, + {"one absent", []*types.Vote{vote0, nil}, []int{1}}, + {"multiple absent", []*types.Vote{nil, nil}, []int{0, 1}}, } for _, tc := range testCases { lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: tc.lastCommitPrecommits} block, _ := state.MakeBlock(2, makeTxs(2), lastCommit) - _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger()) + _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators) require.Nil(t, err, tc.desc) - // -> app must receive an index of the absent validator - assert.Equal(t, tc.expectedAbsentValidators, app.Validators, tc.desc) + // -> 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) + } + } } } @@ -93,7 +106,7 @@ func TestBeginBlockByzantineValidators(t *testing.T) { require.Nil(t, err) defer proxyApp.Stop() - state := state() + state := state(2) prevHash := state.LastBlockID.Hash prevParts := types.PartSetHeader{} @@ -113,15 +126,19 @@ func TestBeginBlockByzantineValidators(t *testing.T) { {"one byzantine", []types.Evidence{ev1}, []abci.Evidence{types.TM2PB.Evidence(ev1)}}, {"multiple byzantine", []types.Evidence{ev1, ev2}, []abci.Evidence{ types.TM2PB.Evidence(ev1), - types.TM2PB.Evidence(ev1)}}, + types.TM2PB.Evidence(ev2)}}, } + 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 { - lastCommit := &types.Commit{BlockID: prevBlockID} block, _ := state.MakeBlock(10, makeTxs(2), lastCommit) block.Evidence.Evidence = tc.evidence - _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger()) + _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators) require.Nil(t, err, tc.desc) // -> app must receive an index of the byzantine validator @@ -139,13 +156,19 @@ func makeTxs(height int64) (txs []types.Tx) { return txs } -func state() State { +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), + } + } s, _ := MakeGenesisState(&types.GenesisDoc{ - ChainID: chainID, - Validators: []types.GenesisValidator{ - {privKey.PubKey(), 10000, "test"}, - }, - AppHash: nil, + ChainID: chainID, + Validators: vals, + AppHash: nil, }) return s } diff --git a/state/validation_test.go b/state/validation_test.go index e0b7fe9ee..f72021975 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -9,7 +9,7 @@ import ( ) func TestValidateBlock(t *testing.T) { - state := state() + state := state(1) blockExec := NewBlockExecutor(dbm.NewMemDB(), log.TestingLogger(), nil, nil, nil) diff --git a/types/protobuf.go b/types/protobuf.go index a0347450e..20cf8a561 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -88,6 +88,17 @@ func (tm2pb) Evidence(ev_ Evidence) abci.Evidence { // Time: ev.Time(), // TotalVotingPower: 10, } + case *MockGoodEvidence, MockGoodEvidence: + return abci.Evidence{ + Type: "mock/good", + Validator: abci.Validator{ + Address: ev.Address(), + // TODO + }, + Height: ev.Height(), + // Time: ev.Time(), + // TotalVotingPower: 10, + } default: panic(fmt.Sprintf("Unknown evidence type: %v %v", ev_, reflect.TypeOf(ev_))) }