From 78dbb1a9ac05343087262a7b69c343efcd02646b Mon Sep 17 00:00:00 2001 From: wangzhiyong Date: Tue, 19 Mar 2019 17:24:24 +0800 Subject: [PATCH] =?UTF-8?q?qbase=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81valida?= =?UTF-8?q?tor=E5=8F=98=E6=9B=B4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- baseabci/baseapp.go | 10 ++++ validator/key.go | 16 ++++++ validator/validator_mapper.go | 67 +++++++++++++++++++++++++ validator/validator_mapper_test.go | 80 ++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 validator/key.go create mode 100644 validator/validator_mapper.go create mode 100644 validator/validator_mapper_test.go diff --git a/baseabci/baseapp.go b/baseabci/baseapp.go index 15cb795..a6e671d 100644 --- a/baseabci/baseapp.go +++ b/baseabci/baseapp.go @@ -18,6 +18,7 @@ import ( "github.com/QOSGroup/qbase/store" "github.com/QOSGroup/qbase/txs" "github.com/QOSGroup/qbase/types" + "github.com/QOSGroup/qbase/validator" go_amino "github.com/tendermint/go-amino" abci "github.com/tendermint/tendermint/abci/types" @@ -92,6 +93,7 @@ func NewBaseApp(name string, logger log.Logger, db dbm.DB, registerCodecFunc fun app.registerQcpMapper() app.RegisterMapper(consensus.NewConsensusMapper(cdc)) + app.RegisterMapper(validator.NewValidatorMapper()) return app } @@ -367,6 +369,9 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg res = app.beginBlocker(app.deliverState.ctx, req) } + valMapper := validator.GetValidatorMapper(app.deliverState.ctx) + valMapper.SetLastBlockProposer(req.Header.GetProposerAddress()) + valMapper.ClearValidatorUpdateSet() // set the signed validators for addition to context in deliverTx app.voteInfos = req.LastCommitInfo.GetVotes() @@ -841,6 +846,11 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc res = app.endBlocker(app.deliverState.ctx, req) } + valMapper := validator.GetValidatorMapper(app.deliverState.ctx) + if b := valMapper.IsEnableValidatorUpdated(); b { + res.ValidatorUpdates = valMapper.GetValidatorUpdateSet() + } + return } diff --git a/validator/key.go b/validator/key.go new file mode 100644 index 0000000..8a95ce8 --- /dev/null +++ b/validator/key.go @@ -0,0 +1,16 @@ +package validator + +const ( + ValidatorMapperName = "_base_validator_" +) + +var ( + //EnableValidatorUpdatedKey 是否启用更新validator特性,默认关闭 + EnableValidatorUpdatedKey = []byte("_enable_validator_updated_") + + //ValidatorUpdateSetKey 保存本块中validator变化结果 + ValidatorUpdateSetKey = []byte("_validator_update_set_") + + //LastBlockProposerKey 上一块验证人 + LastBlockProposerKey = []byte("_last_block_proposer_") +) diff --git a/validator/validator_mapper.go b/validator/validator_mapper.go new file mode 100644 index 0000000..00d8cd8 --- /dev/null +++ b/validator/validator_mapper.go @@ -0,0 +1,67 @@ +package validator + +import ( + "github.com/QOSGroup/qbase/context" + "github.com/QOSGroup/qbase/mapper" + "github.com/QOSGroup/qbase/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +type ValidatorMapper struct { + *mapper.BaseMapper +} + +func (mapper *ValidatorMapper) ClearValidatorUpdateSet() { + mapper.Del(ValidatorUpdateSetKey) +} + +func (mapper *ValidatorMapper) GetValidatorUpdateSet() (update []abci.ValidatorUpdate) { + mapper.Get(ValidatorUpdateSetKey, &update) + return +} + +func (mapper *ValidatorMapper) SetValidatorUpdateSet(update []abci.ValidatorUpdate) { + mapper.Set(ValidatorUpdateSetKey, update) +} + +func (mapper *ValidatorMapper) SetLastBlockProposer(address types.Address) { + mapper.Set(LastBlockProposerKey, address) +} + +func (mapper *ValidatorMapper) GetLastBlockProposer() (address types.Address, exsits bool) { + exsits = mapper.Get(LastBlockProposerKey, &address) + return +} + +func (mapper *ValidatorMapper) IsEnableValidatorUpdated() bool { + if v, exsits := mapper.GetBool(EnableValidatorUpdatedKey); exsits { + return v + } + return false +} + +func (mapper *ValidatorMapper) EnableValidatorUpdated() { + mapper.Set(EnableValidatorUpdatedKey, true) +} + +func (mapper *ValidatorMapper) DisableValidatorUpdated() { + mapper.Set(EnableValidatorUpdatedKey, false) +} + +var _ mapper.IMapper = (*ValidatorMapper)(nil) + +func NewValidatorMapper() *ValidatorMapper { + var validatorMapper = ValidatorMapper{} + validatorMapper.BaseMapper = mapper.NewBaseMapper(nil, ValidatorMapperName) + return &validatorMapper +} + +func GetValidatorMapper(ctx context.Context) *ValidatorMapper { + return ctx.Mapper(ValidatorMapperName).(*ValidatorMapper) +} + +func (mapper *ValidatorMapper) Copy() mapper.IMapper { + validatorMapper := &ValidatorMapper{} + validatorMapper.BaseMapper = mapper.BaseMapper.Copy() + return validatorMapper +} diff --git a/validator/validator_mapper_test.go b/validator/validator_mapper_test.go new file mode 100644 index 0000000..41222b9 --- /dev/null +++ b/validator/validator_mapper_test.go @@ -0,0 +1,80 @@ +package validator + +import ( + "testing" + + "github.com/QOSGroup/qbase/context" + "github.com/QOSGroup/qbase/mapper" + "github.com/QOSGroup/qbase/store" + "github.com/QOSGroup/qbase/types" + "github.com/stretchr/testify/require" + go_amino "github.com/tendermint/go-amino" + abci "github.com/tendermint/tendermint/abci/types" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" +) + +func defaultContext(key store.StoreKey, mapperMap map[string]mapper.IMapper) context.Context { + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, store.StoreTypeIAVL, db) + cms.LoadLatestVersion() + ctx := context.NewContext(cms, abci.Header{}, false, log.NewNopLogger(), mapperMap) + return ctx +} + +func getValidatorMapper() *ValidatorMapper { + cdc := go_amino.NewCodec() + + seedMapper := NewValidatorMapper() + seedMapper.SetCodec(cdc) + + mapperMap := make(map[string]mapper.IMapper) + mapperMap[seedMapper.MapperName()] = seedMapper + + ctx := defaultContext(seedMapper.GetStoreKey(), mapperMap) + return GetValidatorMapper(ctx) +} + +func TestValidatorMapper(t *testing.T) { + + valMapper := getValidatorMapper() + b := valMapper.IsEnableValidatorUpdated() + require.Equal(t, false, b) + + valMapper.EnableValidatorUpdated() + + b = valMapper.IsEnableValidatorUpdated() + require.Equal(t, true, b) + + valMapper.DisableValidatorUpdated() + + b = valMapper.IsEnableValidatorUpdated() + require.Equal(t, false, b) + + s := valMapper.GetValidatorUpdateSet() + require.Equal(t, 0, len(s)) + + s = []abci.ValidatorUpdate{ + {}, {}, + } + + valMapper.SetValidatorUpdateSet(s) + s = valMapper.GetValidatorUpdateSet() + require.Equal(t, 2, len(s)) + + valMapper.ClearValidatorUpdateSet() + + s = valMapper.GetValidatorUpdateSet() + require.Equal(t, 0, len(s)) + + addr, _ := valMapper.GetLastBlockProposer() + require.Equal(t, true, addr.Empty()) + + addr = types.Address{12, 20, 32} + valMapper.SetLastBlockProposer(addr) + + addr, _ = valMapper.GetLastBlockProposer() + require.Equal(t, false, addr.Empty()) + +}