Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add downtime detector module #3688

Merged
merged 21 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ func (s *KeeperTestHelper) BuildTx(
// StateNotAltered validates that app state is not altered. Fails if it is.
func (s *KeeperTestHelper) StateNotAltered() {
oldState := s.App.ExportState(s.Ctx)
s.Commit()
s.App.Commit()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed to fix "QueryStateAltered" tests, because Commit would start a new block, which would cause a state write from downtime detector.

newState := s.App.ExportState(s.Ctx)
s.Require().Equal(oldState, newState)
}
Expand Down
8 changes: 8 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import (
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

downtimedetector "github.com/osmosis-labs/osmosis/v13/x/downtime-detector"
downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"
ibchooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks"
ibcratelimit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit"
ibcratelimittypes "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types"
Expand Down Expand Up @@ -104,6 +106,7 @@ type AppKeepers struct {
AuthzKeeper *authzkeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
DistrKeeper *distrkeeper.Keeper
DowntimeKeeper *downtimedetector.Keeper
SlashingKeeper *slashingkeeper.Keeper
IBCKeeper *ibckeeper.Keeper
ICAHostKeeper *icahostkeeper.Keeper
Expand Down Expand Up @@ -197,6 +200,10 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
)
appKeepers.DistrKeeper = &distrKeeper

appKeepers.DowntimeKeeper = downtimedetector.NewKeeper(
appKeepers.keys[downtimetypes.StoreKey],
)

slashingKeeper := slashingkeeper.NewKeeper(
appCodec,
appKeepers.keys[slashingtypes.StoreKey],
Expand Down Expand Up @@ -595,6 +602,7 @@ func KVStoreKeys() []string {
stakingtypes.StoreKey,
minttypes.StoreKey,
distrtypes.StoreKey,
downtimetypes.StoreKey,
slashingtypes.StoreKey,
govtypes.StoreKey,
paramstypes.StoreKey,
Expand Down
2 changes: 2 additions & 0 deletions app/keepers/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts"

_ "github.com/osmosis-labs/osmosis/v13/client/docs/statik"
downtimemodule "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/module"
"github.com/osmosis-labs/osmosis/v13/x/epochs"
"github.com/osmosis-labs/osmosis/v13/x/gamm"
ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks"
Expand All @@ -54,6 +55,7 @@ var AppModuleBasics = []module.AppModuleBasic{
capability.AppModuleBasic{},
staking.AppModuleBasic{},
mint.AppModuleBasic{},
downtimemodule.AppModuleBasic{},
distr.AppModuleBasic{},
gov.NewAppModuleBasic(
append(
Expand Down
6 changes: 6 additions & 0 deletions app/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (
ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts"
icatypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types"

downtimemodule "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/module"
downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"

ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks"

"github.com/cosmos/cosmos-sdk/types/module"
Expand Down Expand Up @@ -125,6 +128,7 @@ func appModules(
mint.NewAppModule(appCodec, *app.MintKeeper, app.AccountKeeper, app.BankKeeper),
slashing.NewAppModule(appCodec, *app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper),
distr.NewAppModule(appCodec, *app.DistrKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper),
downtimemodule.NewAppModule(*app.DowntimeKeeper),
staking.NewAppModule(appCodec, *app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
upgrade.NewAppModule(*app.UpgradeKeeper),
wasm.NewAppModule(appCodec, app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
Expand Down Expand Up @@ -175,6 +179,7 @@ func orderBeginBlockers(allModuleNames []string) []string {
// IBChost came after staking, before superfluid.
// TODO: Come back and delete this line after testing the base change.
ord.Sequence(stakingtypes.ModuleName, ibchost.ModuleName, superfluidtypes.ModuleName)
// We leave downtime-detector un-constrained.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we mean by un-constrained here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can go anywhere in the sequence of begin block runs

// every remaining module's begin block is a no-op.
return ord.TotalOrdering()
}
Expand Down Expand Up @@ -204,6 +209,7 @@ func OrderInitGenesis(allModuleNames []string) []string {
authtypes.ModuleName,
banktypes.ModuleName,
distrtypes.ModuleName,
downtimetypes.ModuleName,
stakingtypes.ModuleName,
slashingtypes.ModuleName,
govtypes.ModuleName,
Expand Down
3 changes: 2 additions & 1 deletion app/upgrades/v14/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
store "github.com/cosmos/cosmos-sdk/store/types"

"github.com/osmosis-labs/osmosis/v13/app/upgrades"
downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"
protorevtypes "github.com/osmosis-labs/osmosis/v13/x/protorev/types"
valsetpreftypes "github.com/osmosis-labs/osmosis/v13/x/valset-pref/types"
)
Expand All @@ -15,7 +16,7 @@ var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: store.StoreUpgrades{
Added: []string{valsetpreftypes.StoreKey, protorevtypes.StoreKey},
Added: []string{valsetpreftypes.StoreKey, protorevtypes.StoreKey, downtimetypes.StoreKey},
Deleted: []string{},
},
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.18
require (
github.com/CosmWasm/wasmd v0.29.2-osmo-v13
github.com/cosmos/cosmos-proto v1.0.0-alpha8
github.com/cosmos/cosmos-sdk v0.45.11
github.com/cosmos/cosmos-sdk v0.46.6
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/iavl v0.19.4
github.com/cosmos/ibc-go/v3 v3.4.0
Expand All @@ -27,6 +27,7 @@ require (
github.com/stretchr/testify v1.8.1
github.com/tendermint/tendermint v0.34.24
github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b
github.com/tidwall/btree v1.6.0
go.uber.org/multierr v1.8.0
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,8 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpR
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw=
github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8=
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
Expand Down
38 changes: 38 additions & 0 deletions proto/osmosis/downtime-detector/v1beta1/downtime_duration.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
syntax = "proto3";
package osmosis.downtimedetector.v1beta1;

import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types";

enum Downtime {
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
DURATION_30S = 0;
DURATION_1M = 1;
DURATION_2M = 2;
DURATION_3M = 3;
DURATION_4M = 4;
DURATION_5M = 5;
DURATION_10M = 6;
DURATION_20M = 7;
DURATION_30M = 8;
DURATION_40M = 9;
DURATION_50M = 10;
DURATION_1H = 11;
DURATION_1_5H = 12;
DURATION_2H = 13;
DURATION_2_5H = 14;
DURATION_3H = 15;
DURATION_4H = 16;
DURATION_5H = 17;
DURATION_6H = 18;
DURATION_9H = 19;
DURATION_12H = 20;
DURATION_18H = 21;
DURATION_24H = 22;
DURATION_36H = 23;
DURATION_48H = 24;
}
13 changes: 2 additions & 11 deletions proto/osmosis/downtime-detector/v1beta1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,12 @@ import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "osmosis/downtime-detector/v1beta1/downtime_duration.proto";

option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types";

// Params holds parameters for the downtime-detector module
message Params {}

message GenesisDowntimeEntry {
google.protobuf.Duration downtime_duration = 1 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.moretags) = "yaml:\"downtime_duration\""
];
Downtime duration = 1 [ (gogoproto.moretags) = "yaml:\"duration\"" ];
google.protobuf.Timestamp last_downtime = 2 [
(gogoproto.nullable) = false,
(gogoproto.stdtime) = true,
Expand All @@ -34,7 +28,4 @@ message GenesisState {
(gogoproto.stdtime) = true,
(gogoproto.moretags) = "yaml:\"last_block_time\""
];

// params is the container of twap parameters.
Params params = 3 [ (gogoproto.nullable) = false ];
}
14 changes: 2 additions & 12 deletions proto/osmosis/downtime-detector/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package osmosis.downtimedetector.v1beta1;

import "gogoproto/gogo.proto";
import "osmosis/downtime-detector/v1beta1/genesis.proto";
import "osmosis/downtime-detector/v1beta1/downtime_duration.proto";

import "cosmos/base/v1beta1/coin.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
Expand All @@ -15,9 +16,6 @@ import "google/protobuf/timestamp.proto";
option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto";

service Query {
rpc Params(ParamsRequest) returns (ParamsResponse) {
option (google.api.http).get = "/osmosis/downtime-detector/v1beta1/Params";
}
rpc RecoveredSinceDowntimeOfLength(RecoveredSinceDowntimeOfLengthRequest)
returns (RecoveredSinceDowntimeOfLengthResponse) {
option (google.api.http).get =
Expand All @@ -27,13 +25,8 @@ service Query {

// Query for has it been at least $RECOVERY_DURATION units of time,
// since the chain has been down for $DOWNTIME_DURATION.
// Note: $DOWNTIME_DURATION must be in set {SPECIFY_SET}
message RecoveredSinceDowntimeOfLengthRequest {
google.protobuf.Duration downtime = 1 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.moretags) = "yaml:\"downtime_duration\""
];
Downtime downtime = 1 [ (gogoproto.moretags) = "yaml:\"downtime\"" ];
google.protobuf.Duration recovery = 2 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
Expand All @@ -44,6 +37,3 @@ message RecoveredSinceDowntimeOfLengthRequest {
message RecoveredSinceDowntimeOfLengthResponse {
bool succesfully_recovered = 1;
}

message ParamsRequest {}
message ParamsResponse { Params params = 1 [ (gogoproto.nullable) = false ]; }
8 changes: 8 additions & 0 deletions proto/osmosis/downtime-detector/v1beta1/query.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
keeper:
path: "github.com/osmosis-labs/osmosis/v13/x/downtime-detector"
struct: "Keeper"
client_path: "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client"
queries:
RecoveredSinceDowntimeOfLength:
proto_wrapper:
query_func: "k.RecoveredSinceDowntimeOfLength"
4 changes: 4 additions & 0 deletions wasmbinding/stargate_whitelist.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

downtimequerytypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto"
epochtypes "github.com/osmosis-labs/osmosis/v13/x/epochs/types"
gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types"
gammv2types "github.com/osmosis-labs/osmosis/v13/x/gamm/v2types"
Expand Down Expand Up @@ -124,6 +125,9 @@ func init() {
setWhitelistedQuery("/osmosis.twap.v1beta1.Query/ArithmeticTwap", &twapquerytypes.ArithmeticTwapResponse{})
setWhitelistedQuery("/osmosis.twap.v1beta1.Query/ArithmeticTwapToNow", &twapquerytypes.ArithmeticTwapToNowResponse{})
setWhitelistedQuery("/osmosis.twap.v1beta1.Query/Params", &twapquerytypes.ParamsResponse{})

// downtime-detector
setWhitelistedQuery("/osmosis.downtimedetector.v1beta1.Query/RecoveredSinceDowntimeOfLength", &downtimequerytypes.RecoveredSinceDowntimeOfLengthResponse{})
}

// GetWhitelistedQuery returns the whitelisted query at the provided path.
Expand Down
37 changes: 37 additions & 0 deletions x/downtime-detector/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package downtimedetector

import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"
)

func (k *Keeper) BeginBlock(ctx sdk.Context) {
curTime := ctx.BlockTime()
lastBlockTime, err := k.GetLastBlockTime(ctx)
if err != nil {
ctx.Logger().Error("Downtime-detector, could not get last block time, did initialization happen correctly. " + err.Error())
}
downtime := curTime.Sub(lastBlockTime)
k.saveDowntimeUpdates(ctx, downtime)
k.StoreLastBlockTime(ctx, curTime)
}

// saveDowntimeUpdates saves the current block time as the
// last time the chain was down for all downtime lengths that are LTE the provided downtime.
func (k *Keeper) saveDowntimeUpdates(ctx sdk.Context, downtime time.Duration) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we get a gdoc here?

// minimum stored downtime is 30S, so if downtime is less than that, don't update anything.
if downtime < 30*time.Second {
return
}
types.DowntimeToDuration.Ascend(0, func(downType types.Downtime, duration time.Duration) bool {
// if downtime < duration of this entry, stop iterating further, don't update this entry.
if downtime < duration {
return false
}
k.StoreLastDowntimeOfLength(ctx, downType, ctx.BlockTime())
return true
})
}
40 changes: 40 additions & 0 deletions x/downtime-detector/client/cli/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cli

import (
"time"

"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli"
"github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto"
"github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"
)

func GetQueryCmd() *cobra.Command {
cmd := osmocli.QueryIndexCmd(types.ModuleName)
osmocli.AddQueryCmd(cmd, queryproto.NewQueryClient, RecoveredSinceQueryCmd)

return cmd
}

func RecoveredSinceQueryCmd() (*osmocli.QueryDescriptor, *queryproto.RecoveredSinceDowntimeOfLengthRequest) {
return &osmocli.QueryDescriptor{
Use: "recovered-since downtime-duration recovery-duration",
Short: "Queries if it has been at least <recovery-duration> since the chain was down for <downtime-duration>",
Long: `{{.Short}}
downtime-duration is a duration, but is restricted to a smaller set. Heres a few from the set: 30s, 1m, 5m, 10m, 30m, 1h, 3 h, 6h, 12h, 24h, 36h, 48h]
{{.ExampleHeader}}
{{.CommandPrefix}} recovered-since 24h 30m`,
CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{"Downtime": parseDowntimeDuration},
}, &queryproto.RecoveredSinceDowntimeOfLengthRequest{}
}

func parseDowntimeDuration(arg string, _ *pflag.FlagSet) (any, osmocli.FieldReadLocation, error) {
dur, err := time.ParseDuration(arg)
if err != nil {
return nil, osmocli.UsedArg, err
}
downtime, err := types.DowntimeByDuration(dur)
return downtime, osmocli.UsedArg, err
}
Loading