diff --git a/Makefile b/Makefile index 5d40c0721..0b8bc4f5c 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ devnet-clean: ## Deletes devnet1 containers .PHONY: e2e-ci e2e-ci: ## Runs all e2e CI tests @go install github.com/omni-network/omni/e2e - @cd e2e && ./run-multiple.sh manifests/devnet1.toml manifests/fuzzyhead.toml manifests/ci.toml manifests/backwards.toml + @cd e2e && ./run-multiple.sh manifests/devnet1.toml manifests/devnet2.toml manifests/fuzzyhead.toml manifests/ci.toml manifests/backwards.toml .PHONY: e2e-run e2e-run: ## Run specific e2e manifest (MANIFEST=single, MANIFEST=devnet1, etc). Note container remain running after the test. diff --git a/halo/app/start.go b/halo/app/start.go index 81d9c768d..18c5e1895 100644 --- a/halo/app/start.go +++ b/halo/app/start.go @@ -103,6 +103,7 @@ func Start(ctx context.Context, cfg Config) (<-chan error, func(context.Context) buildinfo.Instrument(ctx) + feature.SetGlobals(cfg.FeatureFlags) ctx = feature.WithFlags(ctx, cfg.FeatureFlags) tracerIDs := tracer.Identifiers{Network: cfg.Network, Service: "halo", Instance: cfg.Comet.Moniker} diff --git a/halo/evmstaking/evmstaking.go b/halo/evmstaking/evmstaking.go index e1aad4906..527ba4b55 100644 --- a/halo/evmstaking/evmstaking.go +++ b/halo/evmstaking/evmstaking.go @@ -11,6 +11,7 @@ import ( "github.com/omni-network/omni/halo/genutil/evm/predeploys" "github.com/omni-network/omni/lib/errors" "github.com/omni-network/omni/lib/ethclient" + "github.com/omni-network/omni/lib/feature" "github.com/omni-network/omni/lib/k1util" "github.com/omni-network/omni/lib/log" evmenginetypes "github.com/omni-network/omni/octane/evmengine/types" @@ -73,6 +74,9 @@ func New( // Prepare returns all omni stake contract EVM event logs from the provided block hash. func (p EventProcessor) Prepare(ctx context.Context, blockHash common.Hash) ([]evmenginetypes.EVMEvent, error) { + if feature.FlagEVMStakingModule.Enabled(ctx) { + return nil, errors.New("unexpected code path [BUG]") + } logs, err := p.ethCl.FilterLogs(ctx, ethereum.FilterQuery{ BlockHash: &blockHash, Addresses: p.Addresses(), @@ -110,6 +114,9 @@ func (p EventProcessor) Addresses() []common.Address { // - CreateValidator // - Delegate. func (p EventProcessor) Deliver(ctx context.Context, _ common.Hash, elog evmenginetypes.EVMEvent) error { + if feature.FlagEVMStakingModule.Enabled(ctx) { + return errors.New("unexpected code path [BUG]") + } ethlog, err := elog.ToEthLog() if err != nil { return err diff --git a/halo/evmstaking2/keeper/keeper.go b/halo/evmstaking2/keeper/keeper.go index 22ce4eedc..099b67ecd 100644 --- a/halo/evmstaking2/keeper/keeper.go +++ b/halo/evmstaking2/keeper/keeper.go @@ -8,6 +8,7 @@ import ( "github.com/omni-network/omni/halo/genutil/evm/predeploys" "github.com/omni-network/omni/lib/errors" "github.com/omni-network/omni/lib/ethclient" + "github.com/omni-network/omni/lib/feature" "github.com/omni-network/omni/lib/k1util" "github.com/omni-network/omni/lib/log" evmenginetypes "github.com/omni-network/omni/octane/evmengine/types" @@ -86,6 +87,10 @@ func NewKeeper( // EndBlock delivers all pending EVM events on every `k.deliverInterval`'th block. func (k *Keeper) EndBlock(ctx context.Context) error { + if !feature.FlagEVMStakingModule.Enabled(ctx) { + return errors.New("unexpected code path [BUG]") + } + blockHeight := sdk.UnwrapSDKContext(ctx).BlockHeight() if blockHeight%k.deliverInterval != 0 { @@ -122,6 +127,9 @@ func (k *Keeper) EndBlock(ctx context.Context) error { // Prepare returns all omni stake contract EVM event logs from the provided block hash. func (k Keeper) Prepare(ctx context.Context, blockHash common.Hash) ([]evmenginetypes.EVMEvent, error) { + if !feature.FlagEVMStakingModule.Enabled(ctx) { + return nil, errors.New("unexpected code path [BUG]") + } logs, err := k.ethCl.FilterLogs(ctx, ethereum.FilterQuery{ BlockHash: &blockHash, Addresses: k.Addresses(), @@ -162,6 +170,9 @@ func (k Keeper) Addresses() []common.Address { // first stored in keeper's state. Then all stored events are periodically delivered // from `EndBlock` at once. func (k Keeper) Deliver(ctx context.Context, _ common.Hash, elog evmenginetypes.EVMEvent) error { + if !feature.FlagEVMStakingModule.Enabled(ctx) { + return errors.New("unexpected code path [BUG]") + } err := k.eventsTable.Insert(ctx, &EVMEvent{ Event: &elog, }) diff --git a/halo/evmstaking2/keeper/keeper_internal_test.go b/halo/evmstaking2/keeper/keeper_internal_test.go index d36c8f859..8855145a9 100644 --- a/halo/evmstaking2/keeper/keeper_internal_test.go +++ b/halo/evmstaking2/keeper/keeper_internal_test.go @@ -9,6 +9,7 @@ import ( "github.com/omni-network/omni/halo/evmstaking2/testutil" "github.com/omni-network/omni/halo/evmstaking2/types" "github.com/omni-network/omni/lib/ethclient" + "github.com/omni-network/omni/lib/feature" "github.com/omni-network/omni/lib/netconf" etypes "github.com/omni-network/omni/octane/evmengine/types" @@ -302,7 +303,8 @@ func setupKeeper( key := storetypes.NewKVStoreKey(types.ModuleName) storeSvc := runtime.NewKVStoreService(key) - ctx := sdktestutil.DefaultContext(key, storetypes.NewTransientStoreKey("test_key")) + ctx := sdktestutil.DefaultContext(key, storetypes.NewTransientStoreKey("test_key")). + WithContext(feature.WithFlag(context.Background(), feature.FlagEVMStakingModule)) ctx = ctx.WithBlockHeight(1) ctx = ctx.WithChainID(netconf.Simnet.Static().OmniConsensusChainIDStr()) diff --git a/lib/feature/feature.go b/lib/feature/feature.go index d95cc6a91..3f8aee331 100644 --- a/lib/feature/feature.go +++ b/lib/feature/feature.go @@ -2,6 +2,7 @@ package feature import ( "context" + "sync" "github.com/omni-network/omni/lib/log" ) @@ -11,6 +12,12 @@ const ( FlagEVMStakingModule Flag = "evm-staking-module" ) +// enabledFlags holds all globally enabled feature flags. The reason for having it is that +// we want to use feature flags across the entire code base. However, CometBFT doesn't allow +// specifying a root context, and the Cosmos SDK doesn't actually use the context provided in ABCI, +// so that feature flags cannot be shared with modules via context. +var enabledFlags sync.Map + var allFlags = map[Flag]bool{ FlagEVMStakingModule: true, } @@ -18,7 +25,7 @@ var allFlags = map[Flag]bool{ // Flag is a feature flag. type Flag string -// Enabled returns true if the flag is enabled in the context. +// Enabled returns true if the flag is enabled in the context or globally. func (f Flag) Enabled(ctx context.Context) bool { return enabled(ctx, f) } @@ -53,8 +60,19 @@ func WithFlag(ctx context.Context, flag Flag) context.Context { return WithFlags(ctx, Flags{string(flag)}) } -// enabled returns true if the given flag is enabled in the context. +// SetGlobals enables all given flags globally. +func SetGlobals(flags Flags) { + for _, flag := range flags { + enabledFlags.Store(Flag(flag), true) + } +} + +// enabled returns true if the given flag is enabled globally or in the context. func enabled(ctx context.Context, flag Flag) bool { + if _, ok := enabledFlags.Load(flag); ok { + return true + } + flags, ok := ctx.Value(key{}).([]Flag) if !ok { return false