mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-13 21:31:23 +00:00
state: send byzantine validators in BeginBlock
This commit is contained in:
@ -53,8 +53,8 @@ func TestEvidencePool(t *testing.T) {
|
||||
store := NewEvidenceStore(dbm.NewMemDB())
|
||||
pool := NewEvidencePool(stateDB, store)
|
||||
|
||||
goodEvidence := newMockGoodEvidence(height, 0, valAddr)
|
||||
badEvidence := MockBadEvidence{goodEvidence}
|
||||
goodEvidence := types.NewMockGoodEvidence(height, 0, valAddr)
|
||||
badEvidence := types.MockBadEvidence{goodEvidence}
|
||||
|
||||
err := pool.AddEvidence(badEvidence)
|
||||
assert.NotNil(err)
|
||||
|
@ -101,7 +101,7 @@ func _waitForEvidence(t *testing.T, wg *sync.WaitGroup, evs types.EvidenceList,
|
||||
func sendEvidence(t *testing.T, evpool *EvidencePool, valAddr []byte, n int) types.EvidenceList {
|
||||
evList := make([]types.Evidence, n)
|
||||
for i := 0; i < n; i++ {
|
||||
ev := newMockGoodEvidence(int64(i+1), 0, valAddr)
|
||||
ev := types.NewMockGoodEvidence(int64(i+1), 0, valAddr)
|
||||
err := evpool.AddEvidence(ev)
|
||||
assert.Nil(t, err)
|
||||
evList[i] = ev
|
||||
|
@ -1,8 +1,6 @@
|
||||
package evidence
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -20,7 +18,7 @@ func TestStoreAddDuplicate(t *testing.T) {
|
||||
store := NewEvidenceStore(db)
|
||||
|
||||
priority := int64(10)
|
||||
ev := newMockGoodEvidence(2, 1, []byte("val1"))
|
||||
ev := types.NewMockGoodEvidence(2, 1, []byte("val1"))
|
||||
|
||||
added := store.AddNewEvidence(ev, priority)
|
||||
assert.True(added)
|
||||
@ -43,7 +41,7 @@ func TestStoreMark(t *testing.T) {
|
||||
assert.Equal(0, len(pendingEv))
|
||||
|
||||
priority := int64(10)
|
||||
ev := newMockGoodEvidence(2, 1, []byte("val1"))
|
||||
ev := types.NewMockGoodEvidence(2, 1, []byte("val1"))
|
||||
|
||||
added := store.AddNewEvidence(ev, priority)
|
||||
assert.True(added)
|
||||
@ -89,15 +87,15 @@ func TestStorePriority(t *testing.T) {
|
||||
|
||||
// sorted by priority and then height
|
||||
cases := []struct {
|
||||
ev MockGoodEvidence
|
||||
ev types.MockGoodEvidence
|
||||
priority int64
|
||||
}{
|
||||
{newMockGoodEvidence(2, 1, []byte("val1")), 17},
|
||||
{newMockGoodEvidence(5, 2, []byte("val2")), 15},
|
||||
{newMockGoodEvidence(10, 2, []byte("val2")), 13},
|
||||
{newMockGoodEvidence(100, 2, []byte("val2")), 11},
|
||||
{newMockGoodEvidence(90, 2, []byte("val2")), 11},
|
||||
{newMockGoodEvidence(80, 2, []byte("val2")), 11},
|
||||
{types.NewMockGoodEvidence(2, 1, []byte("val1")), 17},
|
||||
{types.NewMockGoodEvidence(5, 2, []byte("val2")), 15},
|
||||
{types.NewMockGoodEvidence(10, 2, []byte("val2")), 13},
|
||||
{types.NewMockGoodEvidence(100, 2, []byte("val2")), 11},
|
||||
{types.NewMockGoodEvidence(90, 2, []byte("val2")), 11},
|
||||
{types.NewMockGoodEvidence(80, 2, []byte("val2")), 11},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@ -119,48 +117,6 @@ const (
|
||||
|
||||
var _ = wire.RegisterInterface(
|
||||
struct{ types.Evidence }{},
|
||||
wire.ConcreteType{MockGoodEvidence{}, evidenceTypeMockGood},
|
||||
wire.ConcreteType{MockBadEvidence{}, evidenceTypeMockBad},
|
||||
wire.ConcreteType{types.MockGoodEvidence{}, evidenceTypeMockGood},
|
||||
wire.ConcreteType{types.MockBadEvidence{}, evidenceTypeMockBad},
|
||||
)
|
||||
|
||||
type MockGoodEvidence struct {
|
||||
Height_ int64
|
||||
Address_ []byte
|
||||
Index_ int
|
||||
}
|
||||
|
||||
func newMockGoodEvidence(height int64, index int, address []byte) MockGoodEvidence {
|
||||
return MockGoodEvidence{height, address, index}
|
||||
}
|
||||
|
||||
func (e MockGoodEvidence) Height() int64 { return e.Height_ }
|
||||
func (e MockGoodEvidence) Address() []byte { return e.Address_ }
|
||||
func (e MockGoodEvidence) Index() int { return e.Index_ }
|
||||
func (e MockGoodEvidence) Hash() []byte {
|
||||
return []byte(fmt.Sprintf("%d-%d", e.Height_, e.Index_))
|
||||
}
|
||||
func (e MockGoodEvidence) Verify(chainID string) error { return nil }
|
||||
func (e MockGoodEvidence) Equal(ev types.Evidence) bool {
|
||||
e2 := ev.(MockGoodEvidence)
|
||||
return e.Height_ == e2.Height_ &&
|
||||
bytes.Equal(e.Address_, e2.Address_) &&
|
||||
e.Index_ == e2.Index_
|
||||
}
|
||||
func (e MockGoodEvidence) String() string {
|
||||
return fmt.Sprintf("GoodEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
|
||||
}
|
||||
|
||||
type MockBadEvidence struct {
|
||||
MockGoodEvidence
|
||||
}
|
||||
|
||||
func (e MockBadEvidence) Verify(chainID string) error { return fmt.Errorf("MockBadEvidence") }
|
||||
func (e MockBadEvidence) Equal(ev types.Evidence) bool {
|
||||
e2 := ev.(MockBadEvidence)
|
||||
return e.Height_ == e2.Height_ &&
|
||||
bytes.Equal(e.Address_, e2.Address_) &&
|
||||
e.Index_ == e2.Index_
|
||||
}
|
||||
func (e MockBadEvidence) String() string {
|
||||
return fmt.Sprintf("BadEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
|
||||
}
|
||||
|
@ -191,13 +191,20 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus,
|
||||
}
|
||||
|
||||
// TODO: determine which validators were byzantine
|
||||
byzantineVals := make([]*abci.Evidence, len(block.Evidence.Evidence))
|
||||
for i, ev := range block.Evidence.Evidence {
|
||||
byzantineVals[i] = &abci.Evidence{
|
||||
PubKey: ev.Address(), // XXX
|
||||
Height: ev.Height(),
|
||||
}
|
||||
}
|
||||
|
||||
// Begin block
|
||||
_, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
|
||||
Hash: block.Hash(),
|
||||
Header: types.TM2PB.Header(block.Header),
|
||||
AbsentValidators: absentVals,
|
||||
ByzantineValidators: nil,
|
||||
ByzantineValidators: byzantineVals,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("Error in proxyAppConn.BeginBlock", "err", err)
|
||||
|
@ -82,6 +82,51 @@ func TestBeginBlockAbsentValidators(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
expectedByzantineValidators []*abci.Evidence
|
||||
}{
|
||||
{"none byzantine", []types.Evidence{}, []*abci.Evidence{}},
|
||||
{"one byzantine", []types.Evidence{ev1}, []*abci.Evidence{{ev1.Address(), ev1.Height()}}},
|
||||
{"multiple byzantine", []types.Evidence{ev1, ev2}, []*abci.Evidence{
|
||||
{ev1.Address(), ev1.Height()},
|
||||
{ev2.Address(), ev2.Height()}}},
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// make some bogus txs
|
||||
@ -116,6 +161,7 @@ type testApp struct {
|
||||
abci.BaseApplication
|
||||
|
||||
AbsentValidators []int32
|
||||
ByzantineValidators []*abci.Evidence
|
||||
}
|
||||
|
||||
func NewDummyApplication() *testApp {
|
||||
@ -128,6 +174,7 @@ func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) {
|
||||
|
||||
func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
app.AbsentValidators = req.AbsentValidators
|
||||
app.ByzantineValidators = req.ByzantineValidators
|
||||
return abci.ResponseBeginBlock{}
|
||||
}
|
||||
|
||||
|
@ -167,3 +167,50 @@ func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
|
||||
// just check their hashes
|
||||
return bytes.Equal(merkle.SimpleHashFromBinary(dve), merkle.SimpleHashFromBinary(ev))
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
// UNSTABLE
|
||||
type MockGoodEvidence struct {
|
||||
Height_ int64
|
||||
Address_ []byte
|
||||
Index_ int
|
||||
}
|
||||
|
||||
// UNSTABLE
|
||||
func NewMockGoodEvidence(height int64, index int, address []byte) MockGoodEvidence {
|
||||
return MockGoodEvidence{height, address, index}
|
||||
}
|
||||
|
||||
func (e MockGoodEvidence) Height() int64 { return e.Height_ }
|
||||
func (e MockGoodEvidence) Address() []byte { return e.Address_ }
|
||||
func (e MockGoodEvidence) Index() int { return e.Index_ }
|
||||
func (e MockGoodEvidence) Hash() []byte {
|
||||
return []byte(fmt.Sprintf("%d-%d", e.Height_, e.Index_))
|
||||
}
|
||||
func (e MockGoodEvidence) Verify(chainID string) error { return nil }
|
||||
func (e MockGoodEvidence) Equal(ev Evidence) bool {
|
||||
e2 := ev.(MockGoodEvidence)
|
||||
return e.Height_ == e2.Height_ &&
|
||||
bytes.Equal(e.Address_, e2.Address_) &&
|
||||
e.Index_ == e2.Index_
|
||||
}
|
||||
func (e MockGoodEvidence) String() string {
|
||||
return fmt.Sprintf("GoodEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
|
||||
}
|
||||
|
||||
// UNSTABLE
|
||||
type MockBadEvidence struct {
|
||||
MockGoodEvidence
|
||||
}
|
||||
|
||||
func (e MockBadEvidence) Verify(chainID string) error { return fmt.Errorf("MockBadEvidence") }
|
||||
func (e MockBadEvidence) Equal(ev Evidence) bool {
|
||||
e2 := ev.(MockBadEvidence)
|
||||
return e.Height_ == e2.Height_ &&
|
||||
bytes.Equal(e.Address_, e2.Address_) &&
|
||||
e.Index_ == e2.Index_
|
||||
}
|
||||
func (e MockBadEvidence) String() string {
|
||||
return fmt.Sprintf("BadEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
|
||||
}
|
||||
|
Reference in New Issue
Block a user