From 0261e6f5ce4bce1b9fc1b5de72b22c8cd0760ab0 Mon Sep 17 00:00:00 2001 From: BananaLF <864685021@qq.com> Date: Thu, 10 Mar 2022 14:07:44 +0800 Subject: [PATCH] Merge PR: op for params and blockedcontract Cache (#1661) * op ante account verify * add err log * solve gasmeter bug * solve a log bug * solve a log bug * solve a log bug * add txhash to log * add txhash to log * add txhash to log * solve a bug for ante * restructure ante * add seq * restructure seq * restructure ante for gas consume * restructure ante log * change gas meter * restructure ante gasmeter * add pin AccountAggregateValidationDecorator * op params * op params solve bug * temp cache blockcontract * op other chain deecorator * solve params bug * solve a bug * solve a bug * op params and blockedmethod cache * solve blocked contract cache bug for update in delive or AyncDeliver * solve a params cache bug * change get contract blocked list gasmeter * add deliver into context * complete cache for params * op ante * make unit test passing * add height control for params cache * add milestone ante height * remove useless code * dynamic analyzer config * solve bug for analyzer dynamic config * add some log * resolve conflict * revert AccountAggregateValidateDecorator logic * use AccountAggregateValidateDecorator logic * remove ante dufee logic * remove useless code * remove height quarantine * unUse async * change code name * change WithDeliver to SetDeliver. remove gasmeter for GetContractMethodBlockedList. * change EvmParamsCache to evmParamsCache Co-authored-by: xiangjianmeng <805442788@qq.com> --- app/ante/GasLimitDecorator.go | 1 - app/app.go | 1 + app/config/config.go | 25 +++++- app/innertx_test.go | 1 + app/rpc/namespaces/eth/simulation/impl.go | 5 ++ cmd/client/flags.go | 2 +- cmd/exchaind/repair_data.go | 2 +- libs/cosmos-sdk/baseapp/baseapp.go | 4 + libs/cosmos-sdk/baseapp/baseapp_runtx.go | 3 - libs/cosmos-sdk/types/context.go | 30 ++++--- libs/cosmos-sdk/x/auth/ante/basic.go | 2 +- libs/tendermint/state/execution.go | 2 +- x/common/analyzer/analyzer.go | 41 ++++++---- x/evm/alias.go | 7 +- x/evm/handler_test.go | 2 + x/evm/keeper/keeper.go | 6 +- x/evm/keeper/params.go | 13 ++- x/evm/types/address_list_test.go | 1 - x/evm/types/cache.go | 96 +++++++++++++++++++++++ x/evm/types/statedb.go | 24 +++++- x/evm/types/statedb_test.go | 1 + x/evm/watcher/watcher_test.go | 1 + x/params/keeper.go | 6 +- x/params/proposal_handler.go | 10 +++ 24 files changed, 239 insertions(+), 47 deletions(-) create mode 100644 x/evm/types/cache.go diff --git a/app/ante/GasLimitDecorator.go b/app/ante/GasLimitDecorator.go index 345f23b845..80cf4bf99c 100644 --- a/app/ante/GasLimitDecorator.go +++ b/app/ante/GasLimitDecorator.go @@ -37,4 +37,3 @@ func (g GasLimitDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, return next(ctx, tx, simulate) } - diff --git a/app/app.go b/app/app.go index 251d0c2ea5..efee42ddd7 100644 --- a/app/app.go +++ b/app/app.go @@ -289,6 +289,7 @@ func NewOKExChainApp( app.subspaces[crisis.ModuleName], invCheckPeriod, app.SupplyKeeper, auth.FeeCollectorName, ) app.UpgradeKeeper = upgrade.NewKeeper(skipUpgradeHeights, keys[upgrade.StoreKey], app.cdc) + app.ParamsKeeper.RegisterSignal(evmtypes.SetEvmParamsNeedUpdate) app.EvmKeeper = evm.NewKeeper( app.cdc, keys[evm.StoreKey], app.subspaces[evm.ModuleName], &app.AccountKeeper, app.SupplyKeeper, app.BankKeeper, logger) (&bankKeeper).SetInnerTxKeeper(app.EvmKeeper) diff --git a/app/config/config.go b/app/config/config.go index 7e483c4c99..9321b78ccb 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -11,6 +11,7 @@ import ( iavlconfig "github.com/okex/exchain/libs/iavl/config" tmconfig "github.com/okex/exchain/libs/tendermint/config" "github.com/okex/exchain/libs/tendermint/libs/log" + "github.com/okex/exchain/x/common/analyzer" "github.com/spf13/viper" ) @@ -59,6 +60,9 @@ type OecConfig struct { // enable-wtx enableWtx bool + + // enable-analyzer + enableAnalyzer bool } const ( @@ -74,7 +78,7 @@ const ( FlagGasLimitBuffer = "gas-limit-buffer" FlagEnableDynamicGp = "enable-dynamic-gp" FlagDynamicGpWeight = "dynamic-gp-weight" - FlagEnableWrappedTx = "enable-wtx" + FlagEnableWrappedTx = "enable-wtx" FlagCsTimeoutPropose = "consensus.timeout_propose" FlagCsTimeoutProposeDelta = "consensus.timeout_propose_delta" @@ -165,6 +169,7 @@ func RegisterDynamicConfig(logger log.Logger) { oecConfig := GetOecConfig() tmconfig.SetDynamicConfig(oecConfig) iavlconfig.SetDynamicConfig(oecConfig) + analyzer.SetDynamicConfig(oecConfig) } func (c *OecConfig) loadFromConfig() { @@ -186,6 +191,7 @@ func (c *OecConfig) loadFromConfig() { c.SetIavlCacheSize(viper.GetInt(iavl.FlagIavlCacheSize)) c.SetNodeKeyWhitelist(viper.GetString(FlagNodeKeyWhitelist)) c.SetEnableWtx(viper.GetBool(FlagEnableWrappedTx)) + c.SetEnableAnalyzer(viper.GetBool(analyzer.FlagEnableAnalyzer)) } func resolveNodeKeyWhitelist(plain string) []string { @@ -220,7 +226,8 @@ func (c *OecConfig) format() string { consensus.timeout_precommit: %s consensus.timeout_precommit_delta: %s - iavl-cache-size: %d`, + iavl-cache-size: %d + enable-analyzer: %v`, c.GetMempoolRecheck(), c.GetMempoolForceRecheckGap(), c.GetMempoolSize(), @@ -237,6 +244,7 @@ func (c *OecConfig) format() string { c.GetCsTimeoutPrecommit(), c.GetCsTimeoutPrecommitDelta(), c.GetIavlCacheSize(), + c.GetEnableAnalyzer(), ) } @@ -345,9 +353,22 @@ func (c *OecConfig) update(key, value interface{}) { return } c.SetIavlCacheSize(r) + case analyzer.FlagEnableAnalyzer: + r, err := strconv.ParseBool(v) + if err != nil { + return + } + c.SetEnableAnalyzer(r) } } +func (c *OecConfig) GetEnableAnalyzer() bool { + return c.enableAnalyzer +} +func (c *OecConfig) SetEnableAnalyzer(value bool) { + c.enableAnalyzer = value +} + func (c *OecConfig) GetMempoolRecheck() bool { return c.mempoolRecheck } diff --git a/app/innertx_test.go b/app/innertx_test.go index e1845c5ef9..1ce52d36bb 100644 --- a/app/innertx_test.go +++ b/app/innertx_test.go @@ -58,6 +58,7 @@ func (suite *InnerTxTestSuite) SetupTest() { suite.app = Setup(checkTx) suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: chain_id, Time: time.Now().UTC()}) + suite.ctx.SetDeliver() suite.stateDB = evm_types.CreateEmptyCommitStateDB(suite.app.EvmKeeper.GenerateCSDBParams(), suite.ctx) suite.codec = codec.New() diff --git a/app/rpc/namespaces/eth/simulation/impl.go b/app/rpc/namespaces/eth/simulation/impl.go index c4d901d523..944246aa1f 100644 --- a/app/rpc/namespaces/eth/simulation/impl.go +++ b/app/rpc/namespaces/eth/simulation/impl.go @@ -127,6 +127,11 @@ func (p SubspaceProxy) GetParamSet(ctx sdk.Context, ps params.ParamSet) { } } + +func (p SubspaceProxy) RegisterSignal(handler func()) { + +} + func (p SubspaceProxy) SetParamSet(ctx sdk.Context, ps params.ParamSet) { } diff --git a/cmd/client/flags.go b/cmd/client/flags.go index 7ab87fd093..5616a675e5 100644 --- a/cmd/client/flags.go +++ b/cmd/client/flags.go @@ -108,7 +108,7 @@ func RegisterAppFlag(cmd *cobra.Command) { cmd.Flags().Bool(app.FlagEnableRepairState, false, "Enable auto repair state on start") - cmd.Flags().Bool(analyzer.FlagEnableAnalyzer, true, "Enable auto open log analyzer") + cmd.Flags().Bool(analyzer.FlagEnableAnalyzer, false, "Enable auto open log analyzer") cmd.Flags().Bool(sanity.FlagDisableSanity, false, "Disable sanity check") cmd.Flags().Int(tmtypes.FlagSigCacheSize, 200000, "Maximum number of signatures in the cache") } diff --git a/cmd/exchaind/repair_data.go b/cmd/exchaind/repair_data.go index 8b92b9e13b..8ff4b6894a 100644 --- a/cmd/exchaind/repair_data.go +++ b/cmd/exchaind/repair_data.go @@ -27,6 +27,6 @@ func repairStateCmd(ctx *server.Context) *cobra.Command { cmd.Flags().Int64(app.FlagStartHeight, 0, "Set the start block height for repair") cmd.Flags().Bool(flatkv.FlagEnable, false, "Enable flat kv storage for read performance") cmd.Flags().String(app.Elapsed, app.DefaultElapsedSchemas, "schemaName=1|0,,,") - cmd.Flags().Bool(analyzer.FlagEnableAnalyzer, true, "Enable auto open log analyzer") + cmd.Flags().Bool(analyzer.FlagEnableAnalyzer, false, "Enable auto open log analyzer") return cmd } diff --git a/libs/cosmos-sdk/baseapp/baseapp.go b/libs/cosmos-sdk/baseapp/baseapp.go index f08403ac15..76ea3694ed 100644 --- a/libs/cosmos-sdk/baseapp/baseapp.go +++ b/libs/cosmos-sdk/baseapp/baseapp.go @@ -631,6 +631,10 @@ func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) sdk.Context ctx = ctx.WithTxBytes(getRealTxByte(txBytes)) } + if mode == runTxModeDeliver { + ctx.SetDeliver() + } + return ctx } diff --git a/libs/cosmos-sdk/baseapp/baseapp_runtx.go b/libs/cosmos-sdk/baseapp/baseapp_runtx.go index 41c29029b1..ecefe5dcd8 100644 --- a/libs/cosmos-sdk/baseapp/baseapp_runtx.go +++ b/libs/cosmos-sdk/baseapp/baseapp_runtx.go @@ -135,7 +135,6 @@ func (app *BaseApp) runAnte(info *runTxInfo, mode runTxMode) error { newCtx, err := app.anteHandler(anteCtx, info.tx, mode == runTxModeSimulate) // NewAnteHandler app.pin(AnteChain, false, mode) - // 3. AnteOther app.pin(AnteOther, true, mode) ms := info.ctx.MultiStore() @@ -164,7 +163,6 @@ func (app *BaseApp) runAnte(info *runTxInfo, mode runTxMode) error { } app.pin(AnteOther, false, mode) - // 4. CacheStoreWrite if mode != runTxModeDeliverInAsync { app.pin(CacheStoreWrite, true, mode) @@ -176,7 +174,6 @@ func (app *BaseApp) runAnte(info *runTxInfo, mode runTxMode) error { return nil } - func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { tx, err := app.txDecoder(req.Tx) diff --git a/libs/cosmos-sdk/types/context.go b/libs/cosmos-sdk/types/context.go index 75195322bb..a23d8a6af8 100644 --- a/libs/cosmos-sdk/types/context.go +++ b/libs/cosmos-sdk/types/context.go @@ -33,6 +33,7 @@ type Context struct { voteInfo []abci.VoteInfo gasMeter GasMeter blockGasMeter GasMeter + isDeliver bool checkTx bool recheckTx bool // if recheckTx == true, then checkTx must also be true wrappedCheckTx bool // if wrappedCheckTx == true, then checkTx must also be true @@ -53,17 +54,20 @@ type Context struct { type Request = Context // Read-only accessors -func (c Context) Context() context.Context { return c.ctx } -func (c Context) MultiStore() MultiStore { return c.ms } -func (c Context) BlockHeight() int64 { return c.header.Height } -func (c Context) BlockTime() time.Time { return c.header.Time } -func (c Context) ChainID() string { return c.chainID } -func (c Context) From() string { return c.from } -func (c Context) TxBytes() []byte { return c.txBytes } -func (c Context) Logger() log.Logger { return c.logger } -func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } -func (c Context) GasMeter() GasMeter { return c.gasMeter } -func (c Context) BlockGasMeter() GasMeter { return c.blockGasMeter } +func (c Context) Context() context.Context { return c.ctx } +func (c Context) MultiStore() MultiStore { return c.ms } +func (c Context) BlockHeight() int64 { return c.header.Height } +func (c Context) BlockTime() time.Time { return c.header.Time } +func (c Context) ChainID() string { return c.chainID } +func (c Context) From() string { return c.from } +func (c Context) TxBytes() []byte { return c.txBytes } +func (c Context) Logger() log.Logger { return c.logger } +func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } +func (c Context) GasMeter() GasMeter { return c.gasMeter } +func (c Context) BlockGasMeter() GasMeter { return c.blockGasMeter } +func (c Context) IsDeliver() bool { + return c.isDeliver +} func (c Context) IsCheckTx() bool { return c.checkTx } func (c Context) IsReCheckTx() bool { return c.recheckTx } func (c Context) IsTraceTx() bool { return c.traceTx } @@ -175,6 +179,10 @@ func (c Context) WithAsync() Context { return c } +func (c *Context) SetDeliver() { + c.isDeliver = true +} + func (c Context) WithBlockHeader(header abci.Header) Context { // https://github.com/gogo/protobuf/issues/519 header.Time = header.Time.UTC() diff --git a/libs/cosmos-sdk/x/auth/ante/basic.go b/libs/cosmos-sdk/x/auth/ante/basic.go index c7f6d3a618..f0fded1daf 100644 --- a/libs/cosmos-sdk/x/auth/ante/basic.go +++ b/libs/cosmos-sdk/x/auth/ante/basic.go @@ -23,7 +23,7 @@ func NewValidateBasicDecorator() ValidateBasicDecorator { return ValidateBasicDecorator{} } -func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { +func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { // simulate means 'eth_call' or 'eth_estimateGas', when it means 'eth_estimateGas' we can not 'VerifySig'.so skip here if simulate { return next(ctx, tx, simulate) diff --git a/libs/tendermint/state/execution.go b/libs/tendermint/state/execution.go index 9f9629c598..ac8fb520aa 100644 --- a/libs/tendermint/state/execution.go +++ b/libs/tendermint/state/execution.go @@ -408,7 +408,7 @@ func execBlockOnProxyApp(context *executionTask) (*ABCIResponses, error) { if txRes.Code == abci.CodeTypeOK { validTxs++ } else { - logger.Debug("Invalid tx", "code", txRes.Code, "log", txRes.Log) + logger.Debug("Invalid tx", "code", txRes.Code, "log", txRes.Log, "index", txIndex) invalidTxs++ } abciResponses.DeliverTxs[txIndex] = txRes diff --git a/x/common/analyzer/analyzer.go b/x/common/analyzer/analyzer.go index 53f7af8b1b..c15c0e4f7c 100644 --- a/x/common/analyzer/analyzer.go +++ b/x/common/analyzer/analyzer.go @@ -13,11 +13,27 @@ import ( const FlagEnableAnalyzer string = "enable-analyzer" var ( - singleAnalys *analyer - openAnalyzer bool - once sync.Once + singleAnalys *analyer + openAnalyzer bool + once sync.Once + dynamicConfig IDynamicConfig = MockDynamicConfig{} ) +func SetDynamicConfig(c IDynamicConfig) { + dynamicConfig = c +} + +type IDynamicConfig interface { + GetEnableAnalyzer() bool +} + +type MockDynamicConfig struct { +} + +func (c MockDynamicConfig) GetEnableAnalyzer() bool { + return viper.GetBool(FlagEnableAnalyzer) +} + type analyer struct { status bool currentTxIndex int64 @@ -41,13 +57,6 @@ func init() { } } -func getOpen() bool { - once.Do(func() { - openAnalyzer = viper.GetBool(FlagEnableAnalyzer) - }) - return openAnalyzer -} - func newAnalys(height int64) { if singleAnalys == nil { singleAnalys = &analyer{ @@ -58,7 +67,7 @@ func newAnalys(height int64) { } func OnAppBeginBlockEnter(height int64) { - if !getOpen() { + if !dynamicConfig.GetEnableAnalyzer() { return } newAnalys(height) @@ -137,7 +146,7 @@ func (s *analyer) format() { trace.GetElapsedInfo().AddInfo(trace.Evm, fmt.Sprintf(EVM_FORMAT, s.dbRead, s.dbWrite, evmcore-s.dbRead-s.dbWrite)) } -func addInfo(name string, keys []string, record map[string]int64) { +func addInfo(name string, keys []string, record map[string]int64) { var comma, format string for _, v := range keys { format += fmt.Sprintf("%s%s<%dms>", comma, v, record[v]) @@ -146,7 +155,6 @@ func addInfo(name string, keys []string, record map[string]int64) { trace.GetElapsedInfo().AddInfo(name, format) } - func (s *analyer) genRecord() (int64, map[string]int64) { var evmcore int64 var record = make(map[string]int64) @@ -173,7 +181,7 @@ func (s *analyer) genRecord() (int64, map[string]int64) { return evmcore, record } -func formatDeliverTx(record map[string]int64) { +func formatDeliverTx(record map[string]int64) { // deliver txs var deliverTxsKeys = []string{ @@ -192,8 +200,7 @@ func formatDeliverTx(record map[string]int64) { addInfo(trace.DeliverTxs, deliverTxsKeys, record) } - -func formatEvmHandlerDetail(record map[string]int64) { +func formatEvmHandlerDetail(record map[string]int64) { // run msg var evmHandlerKeys = []string{ @@ -214,7 +221,7 @@ func formatEvmHandlerDetail(record map[string]int64) { addInfo(trace.EvmHandlerDetail, evmHandlerKeys, record) } -func formatRunAnteDetail(record map[string]int64) { +func formatRunAnteDetail(record map[string]int64) { // ante var anteKeys = []string{ diff --git a/x/evm/alias.go b/x/evm/alias.go index f8877617a1..d958d51803 100644 --- a/x/evm/alias.go +++ b/x/evm/alias.go @@ -15,9 +15,10 @@ const ( // nolint var ( - NewKeeper = keeper.NewKeeper - TxDecoder = types.TxDecoder - NewSimulateKeeper = keeper.NewSimulateKeeper + NewKeeper = keeper.NewKeeper + TxDecoder = types.TxDecoder + NewSimulateKeeper = keeper.NewSimulateKeeper + SetEvmParamsNeedUpdate = types.SetEvmParamsNeedUpdate ) //nolint diff --git a/x/evm/handler_test.go b/x/evm/handler_test.go index 684b3b08c1..5854bca489 100644 --- a/x/evm/handler_test.go +++ b/x/evm/handler_test.go @@ -50,6 +50,7 @@ func (suite *EvmTestSuite) SetupTest() { suite.app = app.Setup(checkTx) suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: chain_id, Time: time.Now().UTC()}) + suite.ctx.SetDeliver() suite.stateDB = types.CreateEmptyCommitStateDB(suite.app.EvmKeeper.GenerateCSDBParams(), suite.ctx) suite.handler = evm.NewHandler(suite.app.EvmKeeper) suite.querier = keeper.NewQuerier(*suite.app.EvmKeeper) @@ -801,6 +802,7 @@ func (suite *EvmContractBlockedListTestSuite) SetupTest() { suite.app = app.Setup(checkTx) suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()}) + suite.ctx.SetDeliver() suite.stateDB = types.CreateEmptyCommitStateDB(suite.app.EvmKeeper.GenerateCSDBParams(), suite.ctx) suite.handler = evm.NewHandler(suite.app.EvmKeeper) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 057ce6a6e0..c61db178b3 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -84,7 +84,6 @@ func NewKeeper( db := types.BloomDb() types.InitIndexer(db) } - // NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations k := &Keeper{ cdc: cdc, @@ -310,3 +309,8 @@ func (k *Keeper) IsAddressBlocked(ctx sdk.Context, addr sdk.AccAddress) bool { csdb := types.CreateEmptyCommitStateDB(k.GenerateCSDBParams(), ctx) return csdb.GetParams().EnableContractBlockedList && csdb.IsContractInBlockedList(addr.Bytes()) } + +func (k *Keeper) IsContractInBlockedList(ctx sdk.Context, addr sdk.AccAddress) bool { + csdb := types.CreateEmptyCommitStateDB(k.GenerateCSDBParams(), ctx) + return csdb.IsContractInBlockedList(addr.Bytes()) +} diff --git a/x/evm/keeper/params.go b/x/evm/keeper/params.go index a88212a0c7..981f3680f7 100644 --- a/x/evm/keeper/params.go +++ b/x/evm/keeper/params.go @@ -7,11 +7,22 @@ import ( // GetParams returns the total set of evm parameters. func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { - k.paramSpace.GetParamSet(ctx, ¶ms) + if ctx.IsDeliver() { + if types.GetEvmParamsCache().IsNeedParamsUpdate() { + k.paramSpace.GetParamSet(ctx, ¶ms) + types.GetEvmParamsCache().UpdateParams(params) + } else { + params = types.GetEvmParamsCache().GetParams() + } + } else { + k.paramSpace.GetParamSet(ctx, ¶ms) + } + return } // SetParams sets the evm parameters to the param space. func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) + types.GetEvmParamsCache().SetNeedParamsUpdate() } diff --git a/x/evm/types/address_list_test.go b/x/evm/types/address_list_test.go index f2624a7a9d..7ca6bfff94 100644 --- a/x/evm/types/address_list_test.go +++ b/x/evm/types/address_list_test.go @@ -43,7 +43,6 @@ func TestBlockMethod(t *testing.T) { //test decode and encode buff := ModuleCdc.MustMarshalJSON(bcl) - t.Log(string(buff)) nbcl := BlockedContractList{} ModuleCdc.MustUnmarshalJSON(buff, &nbcl) } diff --git a/x/evm/types/cache.go b/x/evm/types/cache.go new file mode 100644 index 0000000000..2811293bc3 --- /dev/null +++ b/x/evm/types/cache.go @@ -0,0 +1,96 @@ +package types + +import ( + "sync" +) + +var evmParamsCache = NewCache() + +type Cache struct { + paramsCache Params + needParamsUpdate bool + paramsMutex sync.RWMutex + + blockedContractMethodsCache map[string]BlockedContract + needBlockedUpdate bool + blockedMutex sync.RWMutex +} + +func NewCache() *Cache { + return &Cache{ + paramsCache: DefaultParams(), + blockedContractMethodsCache: make(map[string]BlockedContract, 0), + needParamsUpdate: true, + needBlockedUpdate: true, + } +} + +func (c *Cache) UpdateParams(params Params) { + c.paramsMutex.Lock() + defer c.paramsMutex.Unlock() + c.paramsCache = params + c.needParamsUpdate = false +} + +func (c *Cache) SetNeedParamsUpdate() { + c.paramsMutex.Lock() + defer c.paramsMutex.Unlock() + c.needParamsUpdate = true +} + +func (c *Cache) IsNeedParamsUpdate() bool { + c.paramsMutex.RLock() + defer c.paramsMutex.RUnlock() + return c.needParamsUpdate +} + +func (c Cache) GetParams() Params { + c.paramsMutex.RLock() + defer c.paramsMutex.RUnlock() + return NewParams(c.paramsCache.EnableCreate, + c.paramsCache.EnableCall, + c.paramsCache.EnableContractDeploymentWhitelist, + c.paramsCache.EnableContractBlockedList, + c.paramsCache.MaxGasLimitPerTx, + c.paramsCache.ExtraEIPs...) +} + +func (c *Cache) SetNeedBlockedUpdate() { + c.blockedMutex.Lock() + defer c.blockedMutex.Unlock() + c.needBlockedUpdate = true +} + +func (c *Cache) IsNeedBlockedUpdate() bool { + c.blockedMutex.RLock() + defer c.blockedMutex.RUnlock() + return c.needBlockedUpdate +} + +func (c *Cache) GetBlockedContractMethod(addr string) (contract *BlockedContract) { + c.blockedMutex.RLock() + bc, ok := c.blockedContractMethodsCache[addr] + c.blockedMutex.RUnlock() + if ok { + return NewBlockContract(bc.Address, bc.BlockMethods) + } + return nil +} + +func (c *Cache) UpdateBlockedContractMethod(bcl BlockedContractList) { + c.blockedMutex.Lock() + c.blockedContractMethodsCache = make(map[string]BlockedContract, 0) + for i, _ := range bcl { + c.blockedContractMethodsCache[bcl[i].Address.String()] = bcl[i] + } + c.blockedMutex.Unlock() + c.needBlockedUpdate = false +} + +func SetEvmParamsNeedUpdate() { + GetEvmParamsCache().SetNeedParamsUpdate() +} + +func GetEvmParamsCache() *Cache { + return evmParamsCache +} diff --git a/x/evm/types/statedb.go b/x/evm/types/statedb.go index c746543bcb..82fd94e51b 100644 --- a/x/evm/types/statedb.go +++ b/x/evm/types/statedb.go @@ -257,6 +257,7 @@ func (csdb *CommitStateDB) SetHeightHash(height uint64, hash ethcmn.Hash) { func (csdb *CommitStateDB) SetParams(params Params) { csdb.params = ¶ms csdb.paramSpace.SetParamSet(csdb.ctx, ¶ms) + GetEvmParamsCache().SetNeedParamsUpdate() } // SetBalance sets the balance of an account. @@ -528,7 +529,16 @@ func (csdb *CommitStateDB) GetHeightHash(height uint64) ethcmn.Hash { func (csdb *CommitStateDB) GetParams() Params { if csdb.params == nil { var params Params - csdb.paramSpace.GetParamSet(csdb.ctx, ¶ms) + if csdb.ctx.IsDeliver() { + if GetEvmParamsCache().IsNeedParamsUpdate() { + csdb.paramSpace.GetParamSet(csdb.ctx, ¶ms) + GetEvmParamsCache().UpdateParams(params) + } else { + params = GetEvmParamsCache().GetParams() + } + } else { + csdb.paramSpace.GetParamSet(csdb.ctx, ¶ms) + } csdb.params = ¶ms } return *csdb.params @@ -1272,6 +1282,7 @@ func (csdb *CommitStateDB) IsDeployerInWhitelist(deployerAddr sdk.AccAddress) bo // SetContractBlockedList sets the target address list into blocked list store func (csdb *CommitStateDB) SetContractBlockedList(addrList AddressList) { + defer GetEvmParamsCache().SetNeedBlockedUpdate() if csdb.Watcher.Enabled() { for i := 0; i < len(addrList); i++ { csdb.Watcher.SaveContractBlockedListItem(addrList[i]) @@ -1285,6 +1296,7 @@ func (csdb *CommitStateDB) SetContractBlockedList(addrList AddressList) { // DeleteContractBlockedList deletes the target address list from blocked list store func (csdb *CommitStateDB) DeleteContractBlockedList(addrList AddressList) { + defer GetEvmParamsCache().SetNeedBlockedUpdate() if csdb.Watcher.Enabled() { for i := 0; i < len(addrList); i++ { csdb.Watcher.DeleteContractBlockedList(addrList[i]) @@ -1324,6 +1336,14 @@ func (csdb *CommitStateDB) IsContractInBlockedList(contractAddr sdk.AccAddress) // GetContractMethodBlockedByAddress gets contract methods blocked by address func (csdb CommitStateDB) GetContractMethodBlockedByAddress(contractAddr sdk.AccAddress) *BlockedContract { + if csdb.ctx.IsDeliver() { + if GetEvmParamsCache().IsNeedBlockedUpdate() { + bcl := csdb.GetContractMethodBlockedList() + GetEvmParamsCache().UpdateBlockedContractMethod(bcl) + } + return GetEvmParamsCache().GetBlockedContractMethod(contractAddr.String()) + } + //use dbAdapter for watchdb or prefixdb bs := csdb.dbAdapter.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixContractBlockedList) vaule := bs.Get(contractAddr) @@ -1358,6 +1378,7 @@ func (csdb CommitStateDB) GetContractMethodBlockedByAddress(contractAddr sdk.Acc // InsertContractMethodBlockedList sets the list of contract method blocked into blocked list store func (csdb *CommitStateDB) InsertContractMethodBlockedList(contractList BlockedContractList) sdk.Error { + defer GetEvmParamsCache().SetNeedBlockedUpdate() for i := 0; i < len(contractList); i++ { bc := csdb.GetContractMethodBlockedByAddress(contractList[i].Address) if bc != nil { @@ -1377,6 +1398,7 @@ func (csdb *CommitStateDB) InsertContractMethodBlockedList(contractList BlockedC // DeleteContractMethodBlockedList delete the list of contract method blocked from blocked list store func (csdb *CommitStateDB) DeleteContractMethodBlockedList(contractList BlockedContractList) sdk.Error { + defer GetEvmParamsCache().SetNeedBlockedUpdate() for i := 0; i < len(contractList); i++ { bc := csdb.GetContractMethodBlockedByAddress(contractList[i].Address) if bc != nil { diff --git a/x/evm/types/statedb_test.go b/x/evm/types/statedb_test.go index 4bd7b568e3..af0a045b9b 100644 --- a/x/evm/types/statedb_test.go +++ b/x/evm/types/statedb_test.go @@ -37,6 +37,7 @@ func (suite *StateDBTestSuite) SetupTest() { suite.app = app.Setup(checkTx) suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-1"}) + suite.ctx.SetDeliver() suite.stateDB = types.CreateEmptyCommitStateDB(suite.app.EvmKeeper.GenerateCSDBParams(), suite.ctx) privkey, err := ethsecp256k1.GenerateKey() diff --git a/x/evm/watcher/watcher_test.go b/x/evm/watcher/watcher_test.go index 5aded67712..ca8f18998b 100644 --- a/x/evm/watcher/watcher_test.go +++ b/x/evm/watcher/watcher_test.go @@ -63,6 +63,7 @@ func setupTest() *WatcherTestSt { w.app = app.Setup(checkTx) w.ctx = w.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: chain_id, Time: time.Now().UTC()}) + w.ctx.SetDeliver() w.handler = evm.NewHandler(w.app.EvmKeeper) ethermint.SetChainId(chain_id) diff --git a/x/params/keeper.go b/x/params/keeper.go index 447619108f..600f09a2ed 100644 --- a/x/params/keeper.go +++ b/x/params/keeper.go @@ -19,14 +19,16 @@ type Keeper struct { // the reference to the CoinKeeper to modify balances ck BankKeeper // the reference to the GovKeeper to insert waiting queue - gk GovKeeper + gk GovKeeper + signals []func() } // NewKeeper creates a new instance of params keeper func NewKeeper(cdc *codec.Codec, key *sdk.KVStoreKey, tkey *sdk.TransientStoreKey) ( k Keeper) { k = Keeper{ - Keeper: sdkparams.NewKeeper(cdc, key, tkey), + Keeper: sdkparams.NewKeeper(cdc, key, tkey), + signals: make([]func(), 0), } k.cdc = cdc k.paramSpace = k.Subspace(DefaultParamspace).WithKeyTable(types.ParamKeyTable()) diff --git a/x/params/proposal_handler.go b/x/params/proposal_handler.go index aee938ea04..fca03baebb 100644 --- a/x/params/proposal_handler.go +++ b/x/params/proposal_handler.go @@ -41,6 +41,7 @@ func handleParameterChangeProposal(ctx sdk.Context, k *Keeper, proposal *govtype } func changeParams(ctx sdk.Context, k *Keeper, paramProposal types.ParameterChangeProposal) sdk.Error { + defer k.signalUpdate() for _, c := range paramProposal.Changes { ss, ok := k.GetSubspace(c.Subspace) if !ok { @@ -55,6 +56,15 @@ func changeParams(ctx sdk.Context, k *Keeper, paramProposal types.ParameterChang return nil } +func (k *Keeper) RegisterSignal(handler func()) { + k.signals = append(k.signals, handler) +} +func (k *Keeper) signalUpdate() { + for i, _ := range k.signals { + k.signals[i]() + } +} + func checkDenom(paramProposal types.ParameterChangeProposal) sdk.Error { for _, c := range paramProposal.Changes { if c.Subspace == "evm" && c.Key == "EVMDenom" {