diff --git a/app/ante.go b/app/ante.go index 78a7dc215f..ffe6ec4807 100644 --- a/app/ante.go +++ b/app/ante.go @@ -8,6 +8,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/ante" ibcante "github.com/cosmos/ibc-go/v3/modules/core/ante" ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper" + "github.com/sei-protocol/sei-chain/x/oracle" + oraclekeeper "github.com/sei-protocol/sei-chain/x/oracle/keeper" ) // HandlerOptions extend the SDK's AnteHandler options by requiring the IBC @@ -17,6 +19,7 @@ type HandlerOptions struct { IBCKeeper *ibckeeper.Keeper WasmConfig *wasmTypes.WasmConfig + OracleKeeper *oraclekeeper.Keeper TXCounterStoreKey sdk.StoreKey } @@ -36,6 +39,9 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { if options.TXCounterStoreKey == nil { return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "tx counter key is required for ante builder") } + if options.OracleKeeper == nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "oracle keeper is required for ante builder") + } sigGasConsumer := options.SigGasConsumer if sigGasConsumer == nil { @@ -47,6 +53,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { wasmkeeper.NewLimitSimulationGasDecorator(options.WasmConfig.SimulationGasLimit), // after setup context to enforce limits early wasmkeeper.NewCountTXDecorator(options.TXCounterStoreKey), ante.NewRejectExtensionOptionsDecorator(), + oracle.NewSpammingPreventionDecorator(*options.OracleKeeper), ante.NewMempoolFeeDecorator(), ante.NewValidateBasicDecorator(), ante.NewTxTimeoutHeightDecorator(), diff --git a/app/app.go b/app/app.go index eac0fed470..3bc2942df9 100644 --- a/app/app.go +++ b/app/app.go @@ -101,6 +101,10 @@ import ( dexmodulekeeper "github.com/sei-protocol/sei-chain/x/dex/keeper" dexmoduletypes "github.com/sei-protocol/sei-chain/x/dex/types" + oraclemodule "github.com/sei-protocol/sei-chain/x/oracle" + oraclekeeper "github.com/sei-protocol/sei-chain/x/oracle/keeper" + oracletypes "github.com/sei-protocol/sei-chain/x/oracle/types" + epochmodule "github.com/sei-protocol/sei-chain/x/epoch" epochmodulekeeper "github.com/sei-protocol/sei-chain/x/epoch/keeper" epochmoduletypes "github.com/sei-protocol/sei-chain/x/epoch/types" @@ -159,6 +163,7 @@ var ( evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, vesting.AppModuleBasic{}, + oraclemodule.AppModuleBasic{}, wasm.AppModuleBasic{}, dexmodule.AppModuleBasic{}, epochmodule.AppModuleBasic{}, @@ -174,9 +179,15 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + oracletypes.ModuleName: nil, wasm.ModuleName: {authtypes.Burner}, + dexmoduletypes.ModuleName: nil, // this line is used by starport scaffolding # stargate/app/maccPerms } + + allowedReceivingModAcc = map[string]bool{ + oracletypes.ModuleName: true, + } ) var ( @@ -228,6 +239,7 @@ type App struct { TransferKeeper ibctransferkeeper.Keeper FeeGrantKeeper feegrantkeeper.Keeper WasmKeeper wasm.Keeper + OracleKeeper oraclekeeper.Keeper // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper @@ -276,7 +288,7 @@ func New( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, - evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, wasm.StoreKey, + evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, oracletypes.StoreKey, wasm.StoreKey, dexmoduletypes.StoreKey, epochmoduletypes.StoreKey, // this line is used by starport scaffolding # stargate/app/storeKey @@ -398,6 +410,11 @@ func New( &stakingKeeper, govRouter, ) + app.OracleKeeper = oraclekeeper.NewKeeper( + appCodec, keys[oracletypes.StoreKey], app.GetSubspace(oracletypes.ModuleName), + app.AccountKeeper, app.BankKeeper, app.DistrKeeper, &stakingKeeper, distrtypes.ModuleName, + ) + wasmDir := filepath.Join(homePath, "wasm") wasmConfig, err := wasm.ReadWasmConfig(appOpts) if err != nil { @@ -483,6 +500,7 @@ func New( evidence.NewAppModule(app.EvidenceKeeper), ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), + oraclemodule.NewAppModule(appCodec, app.OracleKeeper, app.AccountKeeper, app.BankKeeper), wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), transferModule, dexModule, @@ -512,6 +530,7 @@ func New( evidencetypes.ModuleName, ibctransfertypes.ModuleName, feegrant.ModuleName, + oracletypes.ModuleName, epochmoduletypes.ModuleName, dexmoduletypes.ModuleName, wasm.ModuleName, @@ -535,6 +554,7 @@ func New( evidencetypes.ModuleName, ibctransfertypes.ModuleName, feegrant.ModuleName, + oracletypes.ModuleName, epochmoduletypes.ModuleName, dexmoduletypes.ModuleName, wasm.ModuleName, @@ -563,6 +583,7 @@ func New( evidencetypes.ModuleName, ibctransfertypes.ModuleName, feegrant.ModuleName, + oracletypes.ModuleName, epochmoduletypes.ModuleName, dexmoduletypes.ModuleName, wasm.ModuleName, @@ -586,6 +607,7 @@ func New( slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), + oraclemodule.NewAppModule(appCodec, app.OracleKeeper, app.AccountKeeper, app.BankKeeper), wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), ibc.NewAppModule(app.IBCKeeper), transferModule, @@ -616,6 +638,7 @@ func New( IBCKeeper: app.IBCKeeper, TXCounterStoreKey: keys[wasm.StoreKey], WasmConfig: &wasmConfig, + OracleKeeper: &app.OracleKeeper, }, ) if err != nil { @@ -793,6 +816,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) + paramsKeeper.Subspace(oracletypes.ModuleName) paramsKeeper.Subspace(wasm.ModuleName) paramsKeeper.Subspace(dexmoduletypes.ModuleName) paramsKeeper.Subspace(epochmoduletypes.ModuleName) @@ -805,3 +829,12 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino func (app *App) SimulationManager() *module.SimulationManager { return app.sm } + +func (app *App) BlacklistedAccAddrs() map[string]bool { + blacklistedAddrs := make(map[string]bool) + for acc := range maccPerms { + blacklistedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc] + } + + return blacklistedAddrs +} diff --git a/go.mod b/go.mod index 161e74782d..669d7d4568 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( go.opentelemetry.io/otel/exporters/jaeger v1.6.3 go.opentelemetry.io/otel/sdk v1.6.3 go.opentelemetry.io/otel/trace v1.6.3 - google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac + google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd google.golang.org/grpc v1.46.2 google.golang.org/protobuf v1.28.0 gopkg.in/yaml.v2 v2.4.0 @@ -56,6 +56,7 @@ require ( github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.0 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect @@ -63,7 +64,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.3 // indirect github.com/google/btree v1.0.1 // indirect @@ -73,6 +74,7 @@ require ( github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.1 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect @@ -129,6 +131,7 @@ require ( gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect nhooyr.io/websocket v1.8.6 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) replace ( diff --git a/go.sum b/go.sum index ac22a60bc1..1111d61ffb 100644 --- a/go.sum +++ b/go.sum @@ -570,6 +570,7 @@ github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASx github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -686,6 +687,8 @@ github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -759,6 +762,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-github/v37 v37.0.0/go.mod h1:LM7in3NmXDrX58GbEHy7FtNLbI2JijX93RnMKvWG3m4= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -853,6 +857,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.1 h1:Y7pyy1viWfoKMUVxmjfI5X6fVLlen75kdYjeIwl9CKc= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.1/go.mod h1:chrfS3YoLAlKTRE5cFWvCbt8uGAjshktT4PveTUpsFQ= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -2267,6 +2273,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac h1:qSNTkEN+L2mvWcLgJOR+8bdHX9rN/IdU3A1Ghpfb1Rg= google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -2386,4 +2394,6 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/proto/oracle/genesis.proto b/proto/oracle/genesis.proto new file mode 100644 index 0000000000..8ca9dcb621 --- /dev/null +++ b/proto/oracle/genesis.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; +package seiprotocol.seichain.oracle; + +import "gogoproto/gogo.proto"; +import "oracle/oracle.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/sei-protocol/sei-chain/x/oracle/types"; + +message GenesisState { + Params params = 1 [(gogoproto.nullable) = false]; + repeated FeederDelegation feeder_delegations = 2 [(gogoproto.nullable) = false]; + repeated ExchangeRateTuple exchange_rates = 3 + [(gogoproto.castrepeated) = "ExchangeRateTuples", (gogoproto.nullable) = false]; + repeated MissCounter miss_counters = 4 [(gogoproto.nullable) = false]; + repeated AggregateExchangeRatePrevote aggregate_exchange_rate_prevotes = 5 [(gogoproto.nullable) = false]; + repeated AggregateExchangeRateVote aggregate_exchange_rate_votes = 6 [(gogoproto.nullable) = false]; +} + +message FeederDelegation { + string feeder_address = 1; + string validator_address = 2; +} + +message MissCounter { + string validator_address = 1; + uint64 miss_counter = 2; +} diff --git a/proto/oracle/oracle.proto b/proto/oracle/oracle.proto new file mode 100644 index 0000000000..16196b4f26 --- /dev/null +++ b/proto/oracle/oracle.proto @@ -0,0 +1,85 @@ +syntax = "proto3"; +package seiprotocol.seichain.oracle; + +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/sei-protocol/sei-chain/x/oracle/types"; + +message Params { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; + + uint64 vote_period = 1 [(gogoproto.moretags) = "yaml:\"vote_period\""]; + string vote_threshold = 2 [ + (gogoproto.moretags) = "yaml:\"vote_threshold\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string reward_band = 3 [ + (gogoproto.moretags) = "yaml:\"reward_band\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + repeated Denom whitelist = 4 [ + (gogoproto.moretags) = "yaml:\"whitelist\"", + (gogoproto.castrepeated) = "DenomList", + (gogoproto.nullable) = false + ]; + string slash_fraction = 5 [ + (gogoproto.moretags) = "yaml:\"slash_fraction\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + uint64 slash_window = 6 [(gogoproto.moretags) = "yaml:\"slash_window\""]; + string min_valid_per_window = 7 [ + (gogoproto.moretags) = "yaml:\"min_valid_per_window\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} + +message Denom { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string name = 1 [(gogoproto.moretags) = "yaml:\"name\""]; +} + +message AggregateExchangeRatePrevote { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string hash = 1 [(gogoproto.moretags) = "yaml:\"hash\""]; + string voter = 2 [(gogoproto.moretags) = "yaml:\"voter\""]; + uint64 submit_block = 3 [(gogoproto.moretags) = "yaml:\"submit_block\""]; +} + +message AggregateExchangeRateVote { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + repeated ExchangeRateTuple exchange_rate_tuples = 1 [ + (gogoproto.moretags) = "yaml:\"exchange_rate_tuples\"", + (gogoproto.castrepeated) = "ExchangeRateTuples", + (gogoproto.nullable) = false + ]; + + string voter = 2 [(gogoproto.moretags) = "yaml:\"voter\""]; +} + +message ExchangeRateTuple { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string denom = 1 [(gogoproto.moretags) = "yaml:\"denom\""]; + string exchange_rate = 2 [ + (gogoproto.moretags) = "yaml:\"exchange_rate\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} diff --git a/proto/oracle/query.proto b/proto/oracle/query.proto new file mode 100644 index 0000000000..4c51ed539b --- /dev/null +++ b/proto/oracle/query.proto @@ -0,0 +1,210 @@ +syntax = "proto3"; +package seiprotocol.seichain.oracle; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "oracle/oracle.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/sei-protocol/sei-chain/x/oracle/types"; + +// Query defines the gRPC querier service. +service Query { + // ExchangeRate returns exchange rate of a denom + rpc ExchangeRate(QueryExchangeRateRequest) returns (QueryExchangeRateResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/denoms/{denom}/exchange_rate"; + } + + // ExchangeRates returns exchange rates of all denoms + rpc ExchangeRates(QueryExchangeRatesRequest) returns (QueryExchangeRatesResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/denoms/exchange_rates"; + } + + // Actives returns all active denoms + rpc Actives(QueryActivesRequest) returns (QueryActivesResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/denoms/actives"; + } + + // VoteTargets returns all vote target denoms + rpc VoteTargets(QueryVoteTargetsRequest) returns (QueryVoteTargetsResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/enoms/vote_targets"; + } + + // FeederDelegation returns feeder delegation of a validator + rpc FeederDelegation(QueryFeederDelegationRequest) returns (QueryFeederDelegationResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/validators/{validator_addr}/feeder"; + } + + // MissCounter returns oracle miss counter of a validator + rpc MissCounter(QueryMissCounterRequest) returns (QueryMissCounterResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/validators/{validator_addr}/miss"; + } + + // AggregatePrevote returns an aggregate prevote of a validator + rpc AggregatePrevote(QueryAggregatePrevoteRequest) returns (QueryAggregatePrevoteResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/validators/{validator_addr}/aggregate_prevote"; + } + + // AggregatePrevotes returns aggregate prevotes of all validators + rpc AggregatePrevotes(QueryAggregatePrevotesRequest) returns (QueryAggregatePrevotesResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/validators/aggregate_prevotes"; + } + + // AggregateVote returns an aggregate vote of a validator + rpc AggregateVote(QueryAggregateVoteRequest) returns (QueryAggregateVoteResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/valdiators/{validator_addr}/aggregate_vote"; + } + + // AggregateVotes returns aggregate votes of all validators + rpc AggregateVotes(QueryAggregateVotesRequest) returns (QueryAggregateVotesResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/validators/aggregate_votes"; + } + + // Params queries all parameters. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/sei-protocol/sei-chain/oracle/params"; + } +} + +// QueryExchangeRateRequest is the request type for the Query/ExchangeRate RPC method. +message QueryExchangeRateRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // denom defines the denomination to query for. + string denom = 1; +} + +// QueryExchangeRateResponse is response type for the +// Query/ExchangeRate RPC method. +message QueryExchangeRateResponse { + // exchange_rate defines the exchange rate of Luna denominated in various Terra + string exchange_rate = 1 + [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; +} + +// QueryExchangeRatesRequest is the request type for the Query/ExchangeRates RPC method. +message QueryExchangeRatesRequest {} + +// QueryExchangeRatesResponse is response type for the +// Query/ExchangeRates RPC method. +message QueryExchangeRatesResponse { + // exchange_rates defines a list of the exchange rate for all whitelisted denoms. + repeated cosmos.base.v1beta1.DecCoin exchange_rates = 1 + [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins", (gogoproto.nullable) = false]; +} + +// QueryActivesRequest is the request type for the Query/Actives RPC method. +message QueryActivesRequest {} + +// QueryActivesResponse is response type for the +// Query/Actives RPC method. +message QueryActivesResponse { + // actives defines a list of the denomination which oracle prices aggreed upon. + repeated string actives = 1; +} + +// QueryVoteTargetsRequest is the request type for the Query/VoteTargets RPC method. +message QueryVoteTargetsRequest {} + +// QueryVoteTargetsResponse is response type for the +// Query/VoteTargets RPC method. +message QueryVoteTargetsResponse { + // vote_targets defines a list of the denomination in which everyone + // should vote in the current vote period. + repeated string vote_targets = 1; +} + +// QueryFeederDelegationRequest is the request type for the Query/FeederDelegation RPC method. +message QueryFeederDelegationRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // validator defines the validator address to query for. + string validator_addr = 1; +} + +// QueryFeederDelegationResponse is response type for the +// Query/FeederDelegation RPC method. +message QueryFeederDelegationResponse { + // feeder_addr defines the feeder delegation of a validator + string feeder_addr = 1; +} + +// QueryMissCounterRequest is the request type for the Query/MissCounter RPC method. +message QueryMissCounterRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // validator defines the validator address to query for. + string validator_addr = 1; +} + +// QueryMissCounterResponse is response type for the +// Query/MissCounter RPC method. +message QueryMissCounterResponse { + // miss_counter defines the oracle miss counter of a validator + uint64 miss_counter = 1; +} + +// QueryAggregatePrevoteRequest is the request type for the Query/AggregatePrevote RPC method. +message QueryAggregatePrevoteRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // validator defines the validator address to query for. + string validator_addr = 1; +} + +// QueryAggregatePrevoteResponse is response type for the +// Query/AggregatePrevote RPC method. +message QueryAggregatePrevoteResponse { + // aggregate_prevote defines oracle aggregate prevote submitted by a validator in the current vote period + AggregateExchangeRatePrevote aggregate_prevote = 1 [(gogoproto.nullable) = false]; + ; +} + +// QueryAggregatePrevotesRequest is the request type for the Query/AggregatePrevotes RPC method. +message QueryAggregatePrevotesRequest {} + +// QueryAggregatePrevotesResponse is response type for the +// Query/AggregatePrevotes RPC method. +message QueryAggregatePrevotesResponse { + // aggregate_prevotes defines all oracle aggregate prevotes submitted in the current vote period + repeated AggregateExchangeRatePrevote aggregate_prevotes = 1 [(gogoproto.nullable) = false]; +} + +// QueryAggregateVoteRequest is the request type for the Query/AggregateVote RPC method. +message QueryAggregateVoteRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // validator defines the validator address to query for. + string validator_addr = 1; +} + +// QueryAggregateVoteResponse is response type for the +// Query/AggregateVote RPC method. +message QueryAggregateVoteResponse { + // aggregate_vote defines oracle aggregate vote submitted by a validator in the current vote period + AggregateExchangeRateVote aggregate_vote = 1 [(gogoproto.nullable) = false]; +} + +// QueryAggregateVotesRequest is the request type for the Query/AggregateVotes RPC method. +message QueryAggregateVotesRequest {} + +// QueryAggregateVotesResponse is response type for the +// Query/AggregateVotes RPC method. +message QueryAggregateVotesResponse { + // aggregate_votes defines all oracle aggregate votes submitted in the current vote period + repeated AggregateExchangeRateVote aggregate_votes = 1 [(gogoproto.nullable) = false]; +} + +// QueryParamsRequest is the request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is the response type for the Query/Params RPC method. +message QueryParamsResponse { + // params defines the parameters of the module. + Params params = 1 [(gogoproto.nullable) = false]; +} \ No newline at end of file diff --git a/proto/oracle/tx.proto b/proto/oracle/tx.proto new file mode 100644 index 0000000000..9d3fb33d3d --- /dev/null +++ b/proto/oracle/tx.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package seiprotocol.seichain.oracle; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/sei-protocol/sei-chain/x/oracle/types"; + +// Msg defines the oracle Msg service. +service Msg { + // AggregateExchangeRatePrevote defines a method for submitting + // aggregate exchange rate prevote + rpc AggregateExchangeRatePrevote(MsgAggregateExchangeRatePrevote) returns (MsgAggregateExchangeRatePrevoteResponse); + + // AggregateExchangeRateVote defines a method for submitting + // aggregate exchange rate vote + rpc AggregateExchangeRateVote(MsgAggregateExchangeRateVote) returns (MsgAggregateExchangeRateVoteResponse); + + // DelegateFeedConsent defines a method for setting the feeder delegation + rpc DelegateFeedConsent(MsgDelegateFeedConsent) returns (MsgDelegateFeedConsentResponse); +} + +// MsgAggregateExchangeRatePrevote represents a message to submit +// aggregate exchange rate prevote. +message MsgAggregateExchangeRatePrevote { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string hash = 1 [(gogoproto.moretags) = "yaml:\"hash\""]; + string feeder = 2 [(gogoproto.moretags) = "yaml:\"feeder\""]; + string validator = 3 [(gogoproto.moretags) = "yaml:\"validator\""]; +} + +// MsgAggregateExchangeRatePrevoteResponse defines the Msg/AggregateExchangeRatePrevote response type. +message MsgAggregateExchangeRatePrevoteResponse {} + +// MsgAggregateExchangeRateVote represents a message to submit +// aggregate exchange rate vote. +message MsgAggregateExchangeRateVote { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string salt = 1 [(gogoproto.moretags) = "yaml:\"salt\""]; + string exchange_rates = 2 [(gogoproto.moretags) = "yaml:\"exchange_rates\""]; + string feeder = 3 [(gogoproto.moretags) = "yaml:\"feeder\""]; + string validator = 4 [(gogoproto.moretags) = "yaml:\"validator\""]; +} + +// MsgAggregateExchangeRateVoteResponse defines the Msg/AggregateExchangeRateVote response type. +message MsgAggregateExchangeRateVoteResponse {} + +// MsgDelegateFeedConsent represents a message to +// delegate oracle voting rights to another address. +message MsgDelegateFeedConsent { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string operator = 1 [(gogoproto.moretags) = "yaml:\"operator\""]; + string delegate = 2 [(gogoproto.moretags) = "yaml:\"delegate\""]; +} + +// MsgDelegateFeedConsentResponse defines the Msg/DelegateFeedConsent response type. +message MsgDelegateFeedConsentResponse {} \ No newline at end of file diff --git a/x/oracle/abci.go b/x/oracle/abci.go new file mode 100755 index 0000000000..349559ab45 --- /dev/null +++ b/x/oracle/abci.go @@ -0,0 +1,116 @@ +package oracle + +import ( + "time" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + + params := k.GetParams(ctx) + if utils.IsPeriodLastBlock(ctx, params.VotePeriod) { + + // Build claim map over all validators in active set + validatorClaimMap := make(map[string]types.Claim) + + maxValidators := k.StakingKeeper.MaxValidators(ctx) + iterator := k.StakingKeeper.ValidatorsPowerStoreIterator(ctx) + defer iterator.Close() + + powerReduction := k.StakingKeeper.PowerReduction(ctx) + + i := 0 + for ; iterator.Valid() && i < int(maxValidators); iterator.Next() { + validator := k.StakingKeeper.Validator(ctx, iterator.Value()) + + // Exclude not bonded validator + if validator.IsBonded() { + valAddr := validator.GetOperator() + validatorClaimMap[valAddr.String()] = types.NewClaim(validator.GetConsensusPower(powerReduction), 0, 0, valAddr) + i++ + } + } + + voteTargets := make(map[string]types.Denom) + k.IterateVoteTargets(ctx, func(denom string, denomInfo types.Denom) bool { + voteTargets[denom] = denomInfo + return false + }) + + // Clear all exchange rates + k.IterateBaseExchangeRates(ctx, func(denom string, _ sdk.Dec) (stop bool) { + k.DeleteBaseExchangeRate(ctx, denom) + return false + }) + + // Organize votes to ballot by denom + // NOTE: **Filter out inactive or jailed validators** + // NOTE: **Make abstain votes to have zero vote power** + voteMap := k.OrganizeBallotByDenom(ctx, validatorClaimMap) + + if referenceDenom := pickReferenceDenom(ctx, k, voteTargets, voteMap); referenceDenom != "" { + // make voteMap of Reference denom to calculate cross exchange rates + ballotRD := voteMap[referenceDenom] + voteMapRD := ballotRD.ToMap() + + var exchangeRateRD sdk.Dec + + exchangeRateRD = ballotRD.WeightedMedianWithAssertion() + + // Iterate through ballots and update exchange rates; drop if not enough votes have been achieved. + for denom, ballot := range voteMap { + + // Convert ballot to cross exchange rates + if denom != referenceDenom { + + ballot = ballot.ToCrossRateWithSort(voteMapRD) + } + + // Get weighted median of cross exchange rates + exchangeRate := Tally(ctx, ballot, params.RewardBand, validatorClaimMap) + + // Transform into the original form base/quote + if denom != referenceDenom { + exchangeRate = exchangeRateRD.Quo(exchangeRate) + } + + // Set the exchange rate, emit ABCI event + k.SetBaseExchangeRateWithEvent(ctx, denom, exchangeRate) + } + } + + //--------------------------- + // Do miss counting & slashing + voteTargetsLen := len(voteTargets) + for _, claim := range validatorClaimMap { + // Skip abstain & valid voters + if int(claim.WinCount) == voteTargetsLen { + continue + } + + // Increase miss counter + k.SetMissCounter(ctx, claim.Recipient, k.GetMissCounter(ctx, claim.Recipient)+1) + } + + // Clear the ballot + k.ClearBallots(ctx, params.VotePeriod) + + // Update vote targets + k.ApplyWhitelist(ctx, params.Whitelist, voteTargets) + } + + // Do slash who did miss voting over threshold and + // reset miss counters of all validators at the last block of slash window + if utils.IsPeriodLastBlock(ctx, params.SlashWindow) { + k.SlashAndResetMissCounters(ctx) + } + + return +} diff --git a/x/oracle/abci_test.go b/x/oracle/abci_test.go new file mode 100755 index 0000000000..6ca11d4b7f --- /dev/null +++ b/x/oracle/abci_test.go @@ -0,0 +1,455 @@ +package oracle_test + +import ( + "fmt" + "math" + "sort" + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/sei-protocol/sei-chain/x/oracle" + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +func TestOracleThreshold(t *testing.T) { + input, h := setup(t) + exchangeRateStr := randomExchangeRate.String() + utils.MicroAtomDenom + + // Case 1. + // Less than the threshold signs, exchange rate consensus fails + salt := "1" + hash := types.GetAggregateVoteHash(salt, exchangeRateStr, keeper.ValAddrs[0]) + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[0], keeper.ValAddrs[0]) + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, keeper.Addrs[0], keeper.ValAddrs[0]) + + _, err1 := h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 := h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + _, err := input.OracleKeeper.GetBaseExchangeRate(input.Ctx.WithBlockHeight(1), utils.MicroAtomDenom) + require.Error(t, err) + + // Case 2. + // More than the threshold signs, exchange rate consensus succeeds + salt = "1" + hash = types.GetAggregateVoteHash(salt, exchangeRateStr, keeper.ValAddrs[0]) + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[0], keeper.ValAddrs[0]) + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, keeper.Addrs[0], keeper.ValAddrs[0]) + + _, err1 = h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + salt = "2" + hash = types.GetAggregateVoteHash(salt, exchangeRateStr, keeper.ValAddrs[1]) + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[1], keeper.ValAddrs[1]) + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, keeper.Addrs[1], keeper.ValAddrs[1]) + + _, err1 = h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + salt = "3" + hash = types.GetAggregateVoteHash(salt, exchangeRateStr, keeper.ValAddrs[2]) + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[2], keeper.ValAddrs[2]) + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, keeper.Addrs[2], keeper.ValAddrs[2]) + + _, err1 = h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + rate, err := input.OracleKeeper.GetBaseExchangeRate(input.Ctx.WithBlockHeight(1), utils.MicroAtomDenom) + require.NoError(t, err) + require.Equal(t, randomExchangeRate, rate) + + // Case 3. + // Increase voting power of absent validator, exchange rate consensus fails + val, _ := input.StakingKeeper.GetValidator(input.Ctx, keeper.ValAddrs[2]) + input.StakingKeeper.Delegate(input.Ctx.WithBlockHeight(0), keeper.Addrs[2], stakingAmt.MulRaw(3), stakingtypes.Unbonded, val, false) + + salt = "1" + hash = types.GetAggregateVoteHash(salt, exchangeRateStr, keeper.ValAddrs[0]) + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[0], keeper.ValAddrs[0]) + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, keeper.Addrs[0], keeper.ValAddrs[0]) + + _, err1 = h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + salt = "2" + hash = types.GetAggregateVoteHash(salt, exchangeRateStr, keeper.ValAddrs[1]) + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[1], keeper.ValAddrs[1]) + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, keeper.Addrs[1], keeper.ValAddrs[1]) + + _, err1 = h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + _, err = input.OracleKeeper.GetBaseExchangeRate(input.Ctx.WithBlockHeight(1), utils.MicroAtomDenom) + require.Error(t, err) +} + +func TestOracleDrop(t *testing.T) { + input, h := setup(t) + + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom, randomExchangeRate) + + // Account 1, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + + // Immediately swap halt after an illiquid oracle vote + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + _, err := input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + require.Error(t, err) +} + +func TestOracleTally(t *testing.T) { + input, _ := setup(t) + + ballot := types.ExchangeRateBallot{} + rates, valAddrs, stakingKeeper := types.GenerateRandomTestCase() + input.OracleKeeper.StakingKeeper = stakingKeeper + h := oracle.NewHandler(input.OracleKeeper) + for i, rate := range rates { + + decExchangeRate := sdk.NewDecWithPrec(int64(rate*math.Pow10(keeper.OracleDecPrecision)), int64(keeper.OracleDecPrecision)) + exchangeRateStr := decExchangeRate.String() + utils.MicroAtomDenom + + salt := fmt.Sprintf("%d", i) + hash := types.GetAggregateVoteHash(salt, exchangeRateStr, valAddrs[i]) + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, sdk.AccAddress(valAddrs[i]), valAddrs[i]) + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, sdk.AccAddress(valAddrs[i]), valAddrs[i]) + + _, err1 := h(input.Ctx.WithBlockHeight(0), prevoteMsg) + _, err2 := h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + power := stakingAmt.QuoRaw(utils.MicroUnit).Int64() + if decExchangeRate.IsZero() { + power = int64(0) + } + + vote := types.NewVoteForTally( + decExchangeRate, utils.MicroAtomDenom, valAddrs[i], power) + ballot = append(ballot, vote) + + // change power of every three validator + if i%3 == 0 { + stakingKeeper.Validators()[i].SetConsensusPower(int64(i + 1)) + } + } + + validatorClaimMap := make(map[string]types.Claim) + for _, valAddr := range valAddrs { + validatorClaimMap[valAddr.String()] = types.Claim{ + Power: stakingKeeper.Validator(input.Ctx, valAddr).GetConsensusPower(sdk.DefaultPowerReduction), + Weight: int64(0), + WinCount: int64(0), + Recipient: valAddr, + } + } + sort.Sort(ballot) + weightedMedian := ballot.WeightedMedianWithAssertion() + standardDeviation := ballot.StandardDeviation(weightedMedian) + maxSpread := weightedMedian.Mul(input.OracleKeeper.RewardBand(input.Ctx).QuoInt64(2)) + + if standardDeviation.GT(maxSpread) { + maxSpread = standardDeviation + } + + expectedValidatorClaimMap := make(map[string]types.Claim) + for _, valAddr := range valAddrs { + expectedValidatorClaimMap[valAddr.String()] = types.Claim{ + Power: stakingKeeper.Validator(input.Ctx, valAddr).GetConsensusPower(sdk.DefaultPowerReduction), + Weight: int64(0), + WinCount: int64(0), + Recipient: valAddr, + } + } + + for _, vote := range ballot { + if (vote.ExchangeRate.GTE(weightedMedian.Sub(maxSpread)) && + vote.ExchangeRate.LTE(weightedMedian.Add(maxSpread))) || + !vote.ExchangeRate.IsPositive() { + key := vote.Voter.String() + claim := expectedValidatorClaimMap[key] + claim.Weight += vote.Power + claim.WinCount++ + expectedValidatorClaimMap[key] = claim + } + } + + tallyMedian := oracle.Tally(input.Ctx, ballot, input.OracleKeeper.RewardBand(input.Ctx), validatorClaimMap) + + require.Equal(t, validatorClaimMap, expectedValidatorClaimMap) + require.Equal(t, tallyMedian.MulInt64(100).TruncateInt(), weightedMedian.MulInt64(100).TruncateInt()) +} + +func TestOracleTallyTiming(t *testing.T) { + input, h := setup(t) + + // all the keeper.Addrs vote for the block ... not last period block yet, so tally fails + for i := range keeper.Addrs[:2] { + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, i) + } + + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 10 // set vote period to 10 for now, for convenience + input.OracleKeeper.SetParams(input.Ctx, params) + require.Equal(t, 0, int(input.Ctx.BlockHeight())) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + _, err := input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + require.Error(t, err) + + input.Ctx = input.Ctx.WithBlockHeight(int64(params.VotePeriod - 1)) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + _, err = input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + require.NoError(t, err) +} + +func TestInvalidVotesSlashing(t *testing.T) { + input, h := setup(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.Whitelist = types.DenomList{{Name: utils.MicroAtomDenom}} + input.OracleKeeper.SetParams(input.Ctx, params) + input.OracleKeeper.SetVoteTarget(input.Ctx, utils.MicroAtomDenom) + + votePeriodsPerWindow := sdk.NewDec(int64(input.OracleKeeper.SlashWindow(input.Ctx))).QuoInt64(int64(input.OracleKeeper.VotePeriod(input.Ctx))).TruncateInt64() + slashFraction := input.OracleKeeper.SlashFraction(input.Ctx) + minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx) + + for i := uint64(0); i < uint64(sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64()); i++ { + input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) + + // Account 1, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + + // Account 2, KRW, miss vote + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate.Add(sdk.NewDec(100000000000000))}}, 1) + + // Account 3, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + require.Equal(t, i+1, input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + } + + validator := input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[1]) + require.Equal(t, stakingAmt, validator.GetBondedTokens()) + + // one more miss vote will inccur keeper.ValAddrs[1] slashing + // Account 1, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + + // Account 2, KRW, miss vote + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate.Add(sdk.NewDec(100000000000000))}}, 1) + + // Account 3, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + input.Ctx = input.Ctx.WithBlockHeight(votePeriodsPerWindow - 1) + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + validator = input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[1]) + require.Equal(t, sdk.OneDec().Sub(slashFraction).MulInt(stakingAmt).TruncateInt(), validator.GetBondedTokens()) +} + +func TestWhitelistSlashing(t *testing.T) { + input, h := setup(t) + + votePeriodsPerWindow := sdk.NewDec(int64(input.OracleKeeper.SlashWindow(input.Ctx))).QuoInt64(int64(input.OracleKeeper.VotePeriod(input.Ctx))).TruncateInt64() + slashFraction := input.OracleKeeper.SlashFraction(input.Ctx) + minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx) + + for i := uint64(0); i < uint64(sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64()); i++ { + input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) + + // Account 2, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 1) + // Account 3, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + require.Equal(t, i+1, input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + } + + validator := input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[0]) + require.Equal(t, stakingAmt, validator.GetBondedTokens()) + + // one more miss vote will inccur Account 1 slashing + + // Account 2, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 1) + // Account 3, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + input.Ctx = input.Ctx.WithBlockHeight(votePeriodsPerWindow - 1) + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + validator = input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[0]) + require.Equal(t, sdk.OneDec().Sub(slashFraction).MulInt(stakingAmt).TruncateInt(), validator.GetBondedTokens()) +} + +func TestNotPassedBallotSlashing(t *testing.T) { + input, h := setup(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.Whitelist = types.DenomList{{Name: utils.MicroAtomDenom}} + input.OracleKeeper.SetParams(input.Ctx, params) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + input.OracleKeeper.SetVoteTarget(input.Ctx, utils.MicroAtomDenom) + + input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) + + // Account 1, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[2])) +} + +func TestAbstainSlashing(t *testing.T) { + input, h := setup(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.Whitelist = types.DenomList{{Name: utils.MicroAtomDenom}} + input.OracleKeeper.SetParams(input.Ctx, params) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + input.OracleKeeper.SetVoteTarget(input.Ctx, utils.MicroAtomDenom) + + votePeriodsPerWindow := sdk.NewDec(int64(input.OracleKeeper.SlashWindow(input.Ctx))).QuoInt64(int64(input.OracleKeeper.VotePeriod(input.Ctx))).TruncateInt64() + minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx) + + for i := uint64(0); i <= uint64(sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64()); i++ { + input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) + + // Account 1, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + + // Account 2, KRW, abstain vote + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: sdk.ZeroDec()}}, 1) + + // Account 3, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + } + + validator := input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[1]) + require.Equal(t, stakingAmt, validator.GetBondedTokens()) +} + +func TestVoteTargets(t *testing.T) { + input, h := setup(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.Whitelist = types.DenomList{{Name: utils.MicroAtomDenom}, {Name: utils.MicroAtomDenom}} + input.OracleKeeper.SetParams(input.Ctx, params) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + input.OracleKeeper.SetVoteTarget(input.Ctx, utils.MicroAtomDenom) + + // KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + // no missing current + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[2])) + + // vote targets are {KRW, SDR} + require.Equal(t, []string{utils.MicroAtomDenom}, input.OracleKeeper.GetVoteTargets(input.Ctx)) + + _, err := input.OracleKeeper.GetVoteTarget(input.Ctx, utils.MicroAtomDenom) + require.NoError(t, err) + + // delete SDR + params.Whitelist = types.DenomList{{Name: utils.MicroAtomDenom}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // KRW, missing + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[2])) + + // SDR must be deleted + require.Equal(t, []string{utils.MicroAtomDenom}, input.OracleKeeper.GetVoteTargets(input.Ctx)) + + _, err = input.OracleKeeper.GetVoteTarget(input.Ctx, "undefined") + require.Error(t, err) + + params.Whitelist = types.DenomList{{Name: utils.MicroAtomDenom}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // KRW, no missing + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + require.Equal(t, uint64(0), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[2])) + + _, err = input.OracleKeeper.GetVoteTarget(input.Ctx, utils.MicroAtomDenom) + require.NoError(t, err) +} + +func TestAbstainWithSmallStakingPower(t *testing.T) { + input, h := setupWithSmallVotingPower(t) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + input.OracleKeeper.SetVoteTarget(input.Ctx, utils.MicroAtomDenom) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: utils.MicroAtomDenom, Amount: sdk.ZeroDec()}}, 0) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + _, err := input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + require.Error(t, err) +} + +func makeAggregatePrevoteAndVote(t *testing.T, input keeper.TestInput, h sdk.Handler, height int64, rates sdk.DecCoins, idx int) { + // Account 1, SDR + salt := "1" + hash := types.GetAggregateVoteHash(salt, rates.String(), keeper.ValAddrs[idx]) + + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[idx], keeper.ValAddrs[idx]) + _, err := h(input.Ctx.WithBlockHeight(height), prevoteMsg) + require.NoError(t, err) + + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, rates.String(), keeper.Addrs[idx], keeper.ValAddrs[idx]) + _, err = h(input.Ctx.WithBlockHeight(height+1), voteMsg) + require.NoError(t, err) +} diff --git a/x/oracle/ante.go b/x/oracle/ante.go new file mode 100644 index 0000000000..e09d5b638e --- /dev/null +++ b/x/oracle/ante.go @@ -0,0 +1,108 @@ +package oracle + +import ( + "sync" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// SpammingPreventionDecorator will check if the transaction's gas is smaller than +// configured hard cap +type SpammingPreventionDecorator struct { + oracleKeeper keeper.Keeper + oraclePrevoteMap map[string]int64 + oracleVoteMap map[string]int64 + mu *sync.Mutex +} + +// NewSpammingPreventionDecorator returns new spamming prevention decorator instance +func NewSpammingPreventionDecorator(oracleKeeper keeper.Keeper) SpammingPreventionDecorator { + return SpammingPreventionDecorator{ + oracleKeeper: oracleKeeper, + oraclePrevoteMap: make(map[string]int64), + oracleVoteMap: make(map[string]int64), + mu: &sync.Mutex{}, + } +} + +// AnteHandle handles msg tax fee checking +func (spd SpammingPreventionDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + if ctx.IsReCheckTx() { + return next(ctx, tx, simulate) + } + + if !simulate { + if ctx.IsCheckTx() { + err := spd.CheckOracleSpamming(ctx, tx.GetMsgs()) + if err != nil { + return ctx, err + } + } + } + + return next(ctx, tx, simulate) +} + +// CheckOracleSpamming check whether the msgs are spamming purpose or not +func (spd SpammingPreventionDecorator) CheckOracleSpamming(ctx sdk.Context, msgs []sdk.Msg) error { + spd.mu.Lock() + defer spd.mu.Unlock() + + curHeight := ctx.BlockHeight() + for _, msg := range msgs { + switch msg := msg.(type) { + case *types.MsgAggregateExchangeRatePrevote: + feederAddr, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + return err + } + + valAddr, err := sdk.ValAddressFromBech32(msg.Validator) + if err != nil { + return err + } + + err = spd.oracleKeeper.ValidateFeeder(ctx, feederAddr, valAddr) + if err != nil { + return err + } + + if lastSubmittedHeight, ok := spd.oraclePrevoteMap[msg.Validator]; ok && lastSubmittedHeight == curHeight { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "the validator has already been submitted prevote at the current height") + } + + spd.oraclePrevoteMap[msg.Validator] = curHeight + continue + case *types.MsgAggregateExchangeRateVote: + feederAddr, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + return err + } + + valAddr, err := sdk.ValAddressFromBech32(msg.Validator) + if err != nil { + return err + } + + err = spd.oracleKeeper.ValidateFeeder(ctx, feederAddr, valAddr) + if err != nil { + return err + } + + if lastSubmittedHeight, ok := spd.oracleVoteMap[msg.Validator]; ok && lastSubmittedHeight == curHeight { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "the validator has already been submitted vote at the current height") + } + + spd.oracleVoteMap[msg.Validator] = curHeight + continue + default: + return nil + } + } + + return nil +} diff --git a/x/oracle/client/cli/query.go b/x/oracle/client/cli/query.go new file mode 100755 index 0000000000..b92201b2c9 --- /dev/null +++ b/x/oracle/client/cli/query.go @@ -0,0 +1,368 @@ +package cli + +import ( + "context" + "strings" + + "github.com/spf13/cobra" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + oracleQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the oracle module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + oracleQueryCmd.AddCommand( + GetCmdQueryExchangeRates(), + GetCmdQueryActives(), + GetCmdQueryParams(), + GetCmdQueryFeederDelegation(), + GetCmdQueryMissCounter(), + GetCmdQueryAggregatePrevote(), + GetCmdQueryAggregateVote(), + GetCmdQueryVoteTargets(), + ) + + return oracleQueryCmd + +} + +// GetCmdQueryExchangeRates implements the query rate command. +func GetCmdQueryExchangeRates() *cobra.Command { + cmd := &cobra.Command{ + Use: "exchange-rates [denom]", + Args: cobra.RangeArgs(0, 1), + Short: "Query the current Luna exchange rate w.r.t an asset", + Long: strings.TrimSpace(` +Query the current exchange rate of Luna with an asset. +You can find the current list of active denoms by running + +$ terrad query oracle exchange-rates + +Or, can filter with denom + +$ terrad query oracle exchange-rates ukrw +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + if len(args) == 0 { + res, err := queryClient.ExchangeRates(context.Background(), &types.QueryExchangeRatesRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + denom := args[0] + res, err := queryClient.ExchangeRate( + context.Background(), + &types.QueryExchangeRateRequest{Denom: denom}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryActives implements the query actives command. +func GetCmdQueryActives() *cobra.Command { + cmd := &cobra.Command{ + Use: "actives", + Args: cobra.NoArgs, + Short: "Query the active list of Terra assets recognized by the oracle", + Long: strings.TrimSpace(` +Query the active list of Terra assets recognized by the types. + +$ terrad query oracle actives +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Actives(context.Background(), &types.QueryActivesRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryParams implements the query params command. +func GetCmdQueryParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Args: cobra.NoArgs, + Short: "Query the current Oracle params", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryFeederDelegation implements the query feeder delegation command +func GetCmdQueryFeederDelegation() *cobra.Command { + cmd := &cobra.Command{ + Use: "feeder [validator]", + Args: cobra.ExactArgs(1), + Short: "Query the oracle feeder delegate account", + Long: strings.TrimSpace(` +Query the account the validator's oracle voting right is delegated to. + +$ terrad query oracle feeder terravaloper... +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + valString := args[0] + validator, err := sdk.ValAddressFromBech32(valString) + if err != nil { + return err + } + + res, err := queryClient.FeederDelegation( + context.Background(), + &types.QueryFeederDelegationRequest{ValidatorAddr: validator.String()}, + ) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryMissCounter implements the query miss counter of the validator command +func GetCmdQueryMissCounter() *cobra.Command { + cmd := &cobra.Command{ + Use: "miss [validator]", + Args: cobra.ExactArgs(1), + Short: "Query the # of the miss count", + Long: strings.TrimSpace(` +Query the # of vote periods missed in this oracle slash window. + +$ terrad query oracle miss terravaloper... +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + valString := args[0] + validator, err := sdk.ValAddressFromBech32(valString) + if err != nil { + return err + } + + res, err := queryClient.MissCounter( + context.Background(), + &types.QueryMissCounterRequest{ValidatorAddr: validator.String()}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryAggregatePrevote implements the query aggregate prevote of the validator command +func GetCmdQueryAggregatePrevote() *cobra.Command { + cmd := &cobra.Command{ + Use: "aggregate-prevotes [validator]", + Args: cobra.RangeArgs(0, 1), + Short: "Query outstanding oracle aggregate prevotes.", + Long: strings.TrimSpace(` +Query outstanding oracle aggregate prevotes. + +$ terrad query oracle aggregate-prevotes + +Or, can filter with voter address + +$ terrad query oracle aggregate-prevotes terravaloper... +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + if len(args) == 0 { + res, err := queryClient.AggregatePrevotes( + context.Background(), + &types.QueryAggregatePrevotesRequest{}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + valString := args[0] + validator, err := sdk.ValAddressFromBech32(valString) + if err != nil { + return err + } + + res, err := queryClient.AggregatePrevote( + context.Background(), + &types.QueryAggregatePrevoteRequest{ValidatorAddr: validator.String()}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryAggregateVote implements the query aggregate prevote of the validator command +func GetCmdQueryAggregateVote() *cobra.Command { + cmd := &cobra.Command{ + Use: "aggregate-votes [validator]", + Args: cobra.RangeArgs(0, 1), + Short: "Query outstanding oracle aggregate votes.", + Long: strings.TrimSpace(` +Query outstanding oracle aggregate vote. + +$ terrad query oracle aggregate-votes + +Or, can filter with voter address + +$ terrad query oracle aggregate-votes terravaloper... +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + if len(args) == 0 { + res, err := queryClient.AggregateVotes( + context.Background(), + &types.QueryAggregateVotesRequest{}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + valString := args[0] + validator, err := sdk.ValAddressFromBech32(valString) + if err != nil { + return err + } + + res, err := queryClient.AggregateVote( + context.Background(), + &types.QueryAggregateVoteRequest{ValidatorAddr: validator.String()}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryVoteTargets implements the query params command. +func GetCmdQueryVoteTargets() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-targets", + Args: cobra.NoArgs, + Short: "Query the current Oracle vote targets", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.VoteTargets( + context.Background(), + &types.QueryVoteTargetsRequest{}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/oracle/client/cli/tx.go b/x/oracle/client/cli/tx.go new file mode 100755 index 0000000000..2c9b3aa745 --- /dev/null +++ b/x/oracle/client/cli/tx.go @@ -0,0 +1,211 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/pkg/errors" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/spf13/cobra" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + oracleTxCmd := &cobra.Command{ + Use: "oracle", + Short: "Oracle transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + oracleTxCmd.AddCommand( + GetCmdDelegateFeederPermission(), + GetCmdAggregateExchangeRatePrevote(), + GetCmdAggregateExchangeRateVote(), + ) + + return oracleTxCmd +} + +// GetCmdDelegateFeederPermission will create a feeder permission delegation tx and sign it with the given key. +func GetCmdDelegateFeederPermission() *cobra.Command { + cmd := &cobra.Command{ + Use: "set-feeder [feeder]", + Args: cobra.ExactArgs(1), + Short: "Delegate the permission to vote for the oracle to an address", + Long: strings.TrimSpace(` +Delegate the permission to submit exchange rate votes for the oracle to an address. + +Delegation can keep your validator operator key offline and use a separate replaceable key online. + +$ terrad tx oracle set-feeder terra1... + +where "terra1..." is the address you want to delegate your voting rights to. +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + // Get from address + voter := clientCtx.GetFromAddress() + + // The address the right is being delegated from + validator := sdk.ValAddress(voter) + + feederStr := args[0] + feeder, err := sdk.AccAddressFromBech32(feederStr) + if err != nil { + return err + } + + msgs := []sdk.Msg{types.NewMsgDelegateFeedConsent(validator, feeder)} + for _, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return err + } + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdAggregateExchangeRatePrevote will create a aggregateExchangeRatePrevote tx and sign it with the given key. +func GetCmdAggregateExchangeRatePrevote() *cobra.Command { + cmd := &cobra.Command{ + Use: "aggregate-prevote [salt] [exchange-rates] [validator]", + Args: cobra.RangeArgs(2, 3), + Short: "Submit an oracle aggregate prevote for the exchange rates of Luna", + Long: strings.TrimSpace(` +Submit an oracle aggregate prevote for the exchange rates of Luna denominated in multiple denoms. +The purpose of aggregate prevote is to hide aggregate exchange rate vote with hash which is formatted +as hex string in SHA256("{salt}:{exchange_rate}{denom},...,{exchange_rate}{denom}:{voter}") + +# Aggregate Prevote +$ terrad tx oracle aggregate-prevote 1234 8888.0ukrw,1.243uusd,0.99usdr + +where "ukrw,uusd,usdr" is the denominating currencies, and "8888.0,1.243,0.99" is the exchange rates of micro Luna in micro denoms from the voter's point of view. + +If voting from a voting delegate, set "validator" to the address of the validator to vote on behalf of: +$ terrad tx oracle aggregate-prevote 1234 8888.0ukrw,1.243uusd,0.99usdr terravaloper1... +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + salt := args[0] + exchangeRatesStr := args[1] + _, err = types.ParseExchangeRateTuples(exchangeRatesStr) + if err != nil { + return fmt.Errorf("given exchange_rates {%s} is not a valid format; exchange_rate should be formatted as DecCoins; %s", exchangeRatesStr, err.Error()) + } + + // Get from address + voter := clientCtx.GetFromAddress() + + // By default the voter is voting on behalf of itself + validator := sdk.ValAddress(voter) + + // Override validator if validator is given + if len(args) == 3 { + parsedVal, err := sdk.ValAddressFromBech32(args[2]) + if err != nil { + return errors.Wrap(err, "validator address is invalid") + } + validator = parsedVal + } + + hash := types.GetAggregateVoteHash(salt, exchangeRatesStr, validator) + msgs := []sdk.Msg{types.NewMsgAggregateExchangeRatePrevote(hash, voter, validator)} + for _, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return err + } + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdAggregateExchangeRateVote will create a aggregateExchangeRateVote tx and sign it with the given key. +func GetCmdAggregateExchangeRateVote() *cobra.Command { + cmd := &cobra.Command{ + Use: "aggregate-vote [salt] [exchange-rates] [validator]", + Args: cobra.RangeArgs(2, 3), + Short: "Submit an oracle aggregate vote for the exchange_rates of Luna", + Long: strings.TrimSpace(` +Submit a aggregate vote for the exchange_rates of Luna w.r.t the input denom. Companion to a prevote submitted in the previous vote period. + +$ terrad tx oracle aggregate-vote 1234 8888.0ukrw,1.243uusd,0.99usdr + +where "ukrw,uusd,usdr" is the denominating currencies, and "8888.0,1.243,0.99" is the exchange rates of micro Luna in micro denoms from the voter's point of view. + +"salt" should match the salt used to generate the SHA256 hex in the aggregated pre-vote. + +If voting from a voting delegate, set "validator" to the address of the validator to vote on behalf of: +$ terrad tx oracle aggregate-vote 1234 8888.0ukrw,1.243uusd,0.99usdr terravaloper1.... +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + salt := args[0] + exchangeRatesStr := args[1] + _, err = types.ParseExchangeRateTuples(exchangeRatesStr) + if err != nil { + return fmt.Errorf("given exchange_rate {%s} is not a valid format; exchange rate should be formatted as DecCoin; %s", exchangeRatesStr, err.Error()) + } + + // Get from address + voter := clientCtx.GetFromAddress() + + // By default the voter is voting on behalf of itself + validator := sdk.ValAddress(voter) + + // Override validator if validator is given + if len(args) == 3 { + parsedVal, err := sdk.ValAddressFromBech32(args[2]) + if err != nil { + return errors.Wrap(err, "validator address is invalid") + } + validator = parsedVal + } + + msgs := []sdk.Msg{types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, voter, validator)} + for _, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return err + } + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/oracle/client/rest/query.go b/x/oracle/client/rest/query.go new file mode 100755 index 0000000000..4e6fa4555f --- /dev/null +++ b/x/oracle/client/rest/query.go @@ -0,0 +1,284 @@ +package rest + +import ( + "fmt" + "net/http" + + "github.com/gorilla/mux" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" +) + +func registerQueryRoutes(cliCtx client.Context, rtr *mux.Router) { + rtr.HandleFunc(fmt.Sprintf("/oracle/denoms/{%s}/exchange_rate", RestDenom), queryExchangeRateHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc("/oracle/denoms/actives", queryActivesHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc("/oracle/denoms/exchange_rates", queryExchangeRatesHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc("/oracle/denoms/vote_targets", queryVoteTargetsHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/feeder", RestVoter), queryFeederDelegationHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/miss", RestVoter), queryMissHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/aggregate_prevote", RestVoter), queryAggregatePrevoteHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/aggregate_vote", RestVoter), queryAggregateVoteHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc("/oracle/voters/aggregate_prevotes", queryAggregatePrevotesHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc("/oracle/voters/aggregate_votes", queryAggregateVotesHandlerFunction(cliCtx)).Methods("GET") + rtr.HandleFunc("/oracle/parameters", queryParamsHandlerFunction(cliCtx)).Methods("GET") +} + +func queryExchangeRateHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + denom, ok := checkDenomVar(w, r) + if !ok { + return + } + + params := types.NewQueryExchangeRateParams(denom) + bz, err := cliCtx.LegacyAmino.MarshalJSON(params) + if rest.CheckBadRequestError(w, err) { + return + } + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryExchangeRate), bz) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryExchangeRatesHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryExchangeRates), nil) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryActivesHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryActives), nil) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryParamsHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryParameters), nil) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryFeederDelegationHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + params := types.NewQueryFeederDelegationParams(voterAddr) + bz, err := cliCtx.LegacyAmino.MarshalJSON(params) + if rest.CheckBadRequestError(w, err) { + return + } + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryFeederDelegation), bz) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryMissHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + params := types.NewQueryMissCounterParams(voterAddr) + bz, err := cliCtx.LegacyAmino.MarshalJSON(params) + if rest.CheckBadRequestError(w, err) { + return + } + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryMissCounter), bz) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryAggregatePrevoteHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + params := types.NewQueryAggregatePrevoteParams(voterAddr) + bz, err := cliCtx.LegacyAmino.MarshalJSON(params) + if rest.CheckBadRequestError(w, err) { + return + } + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryAggregatePrevote), bz) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryAggregateVoteHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + params := types.NewQueryAggregateVoteParams(voterAddr) + bz, err := cliCtx.LegacyAmino.MarshalJSON(params) + if rest.CheckBadRequestError(w, err) { + return + } + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryAggregateVote), bz) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryAggregatePrevotesHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryAggregatePrevotes), nil) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryAggregateVotesHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryAggregateVotes), nil) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func queryVoteTargetsHandlerFunction(cliCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryVoteTargets), nil) + if rest.CheckInternalServerError(w, err) { + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func checkDenomVar(w http.ResponseWriter, r *http.Request) (string, bool) { + denom := mux.Vars(r)[RestDenom] + err := sdk.ValidateDenom(denom) + if rest.CheckBadRequestError(w, err) { + return "", false + } + + return denom, true +} + +func checkVoterAddressVar(w http.ResponseWriter, r *http.Request) (sdk.ValAddress, bool) { + addr, err := sdk.ValAddressFromBech32(mux.Vars(r)[RestVoter]) + if rest.CheckBadRequestError(w, err) { + return nil, false + } + + return addr, true +} diff --git a/x/oracle/client/rest/rest.go b/x/oracle/client/rest/rest.go new file mode 100755 index 0000000000..008dad1ca5 --- /dev/null +++ b/x/oracle/client/rest/rest.go @@ -0,0 +1,22 @@ +package rest + +import ( + "github.com/cosmos/cosmos-sdk/client" + clientrest "github.com/cosmos/cosmos-sdk/client/rest" + + "github.com/gorilla/mux" +) + +//nolint +const ( + RestDenom = "denom" + RestVoter = "voter" +) + +// RegisterRoutes registers oracle-related REST handlers to a router +func RegisterRoutes(clientCtx client.Context, rtr *mux.Router) { + r := clientrest.WithHTTPDeprecationHeaders(rtr) + + registerQueryRoutes(clientCtx, r) + registerTxHandlers(clientCtx, r) +} diff --git a/x/oracle/client/rest/tx.go b/x/oracle/client/rest/tx.go new file mode 100755 index 0000000000..535090bd1f --- /dev/null +++ b/x/oracle/client/rest/tx.go @@ -0,0 +1,163 @@ +package rest + +import ( + "fmt" + "net/http" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + + "github.com/gorilla/mux" +) + +func registerTxHandlers(cliCtx client.Context, rtr *mux.Router) { + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/feeder", RestVoter), newDelegateHandlerFunction(cliCtx)).Methods("POST") + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/aggregate_prevote", RestVoter), newAggregatePrevoteHandlerFunction(cliCtx)).Methods("POST") + rtr.HandleFunc(fmt.Sprintf("/oracle/voters/{%s}/aggregate_vote", RestVoter), newAggregateVoteHandlerFunction(cliCtx)).Methods("POST") +} + +type ( + delegateReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Feeder sdk.AccAddress `json:"feeder" yaml:"feeder"` + } + + aggregatePrevoteReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + + Hash string `json:"hash" yaml:"hash"` + ExchangeRates string `json:"exchange_rates" yaml:"exchange_rates"` + Salt string `json:"salt" yaml:"salt"` + } + + aggregateVoteReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + + ExchangeRates string `json:"exchange_rates" yaml:"exchange_rates"` + Salt string `json:"salt" yaml:"salt"` + } +) + +func newDelegateHandlerFunction(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req delegateReq + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + // create the message + msg := types.NewMsgDelegateFeedConsent(voterAddr, req.Feeder) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} + +func newAggregatePrevoteHandlerFunction(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req aggregatePrevoteReq + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + feederAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + var hash types.AggregateVoteHash + + // If hash is not given, then retrieve hash from exchange_rate and salt + if len(req.Hash) == 0 && (len(req.ExchangeRates) > 0 && len(req.Salt) > 0) { + _, err := types.ParseExchangeRateTuples(req.ExchangeRates) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + hash = types.GetAggregateVoteHash(req.Salt, req.ExchangeRates, voterAddr) + } else if len(req.Hash) > 0 { + hash, err = types.AggregateVoteHashFromHexString(req.Hash) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + } else { + rest.WriteErrorResponse(w, http.StatusBadRequest, "must provide Hash or (ExchangeRates & Salt)") + return + } + + // create the message + msg := types.NewMsgAggregateExchangeRatePrevote(hash, feederAddr, voterAddr) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} + +func newAggregateVoteHandlerFunction(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req aggregateVoteReq + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + feederAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + voterAddr, ok := checkVoterAddressVar(w, r) + if !ok { + return + } + + // Check validation of tuples + _, err = types.ParseExchangeRateTuples(req.ExchangeRates) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // create the message + msg := types.NewMsgAggregateExchangeRateVote(req.Salt, req.ExchangeRates, feederAddr, voterAddr) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} diff --git a/x/oracle/common_test.go b/x/oracle/common_test.go new file mode 100755 index 0000000000..cc22200445 --- /dev/null +++ b/x/oracle/common_test.go @@ -0,0 +1,87 @@ +package oracle_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/sei-protocol/sei-chain/x/oracle" + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/utils" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking" +) + +var ( + uSDRAmt = sdk.NewInt(1005 * utils.MicroUnit) + stakingAmt = sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + + randomExchangeRate = sdk.NewDec(1700) + anotherRandomExchangeRate = sdk.NewDecWithPrec(4882, 2) // swap rate +) + +func setupWithSmallVotingPower(t *testing.T) (keeper.TestInput, sdk.Handler) { + input := keeper.CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + h := oracle.NewHandler(input.OracleKeeper) + + sh := staking.NewHandler(input.StakingKeeper) + _, err := sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[0], keeper.ValPubKeys[0], sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction))) + require.NoError(t, err) + + staking.EndBlocker(input.Ctx, input.StakingKeeper) + + return input, h +} + +func setup(t *testing.T) (keeper.TestInput, sdk.Handler) { + input := keeper.CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + h := oracle.NewHandler(input.OracleKeeper) + + sh := staking.NewHandler(input.StakingKeeper) + + // Validator created + _, err := sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[0], keeper.ValPubKeys[0], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[1], keeper.ValPubKeys[1], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[2], keeper.ValPubKeys[2], stakingAmt)) + require.NoError(t, err) + staking.EndBlocker(input.Ctx, input.StakingKeeper) + + return input, h +} + +func setupVal5(t *testing.T) (keeper.TestInput, sdk.Handler) { + input := keeper.CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + h := oracle.NewHandler(input.OracleKeeper) + + sh := staking.NewHandler(input.StakingKeeper) + + // Validator created + _, err := sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[0], keeper.ValPubKeys[0], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[1], keeper.ValPubKeys[1], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[2], keeper.ValPubKeys[2], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[3], keeper.ValPubKeys[3], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, keeper.NewTestMsgCreateValidator(keeper.ValAddrs[4], keeper.ValPubKeys[4], stakingAmt)) + require.NoError(t, err) + staking.EndBlocker(input.Ctx, input.StakingKeeper) + + return input, h +} diff --git a/x/oracle/exported/alias.go b/x/oracle/exported/alias.go new file mode 100755 index 0000000000..4edfe50844 --- /dev/null +++ b/x/oracle/exported/alias.go @@ -0,0 +1,10 @@ +//nolint:deadcode,unused +//DONTCOVER +package exported + +import "github.com/sei-protocol/sei-chain/x/oracle/types" + +type ( + MsgAggregateExchangeRatePrevote = types.MsgAggregateExchangeRatePrevote + MsgAggregateExchangeRateVote = types.MsgAggregateExchangeRateVote +) diff --git a/x/oracle/genesis.go b/x/oracle/genesis.go new file mode 100755 index 0000000000..292d429224 --- /dev/null +++ b/x/oracle/genesis.go @@ -0,0 +1,116 @@ +package oracle + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// InitGenesis initialize default parameters +// and the keeper's address to pubkey map +func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState) { + for _, d := range data.FeederDelegations { + voter, err := sdk.ValAddressFromBech32(d.ValidatorAddress) + if err != nil { + panic(err) + } + + feeder, err := sdk.AccAddressFromBech32(d.FeederAddress) + if err != nil { + panic(err) + } + + keeper.SetFeederDelegation(ctx, voter, feeder) + } + + for _, ex := range data.ExchangeRates { + keeper.SetBaseExchangeRate(ctx, ex.Denom, ex.ExchangeRate) + } + + for _, mc := range data.MissCounters { + operator, err := sdk.ValAddressFromBech32(mc.ValidatorAddress) + if err != nil { + panic(err) + } + + keeper.SetMissCounter(ctx, operator, mc.MissCounter) + } + + for _, ap := range data.AggregateExchangeRatePrevotes { + valAddr, err := sdk.ValAddressFromBech32(ap.Voter) + if err != nil { + panic(err) + } + + keeper.SetAggregateExchangeRatePrevote(ctx, valAddr, ap) + } + + for _, av := range data.AggregateExchangeRateVotes { + valAddr, err := sdk.ValAddressFromBech32(av.Voter) + if err != nil { + panic(err) + } + + keeper.SetAggregateExchangeRateVote(ctx, valAddr, av) + } + + keeper.SetParams(ctx, data.Params) + + // check if the module account exists + moduleAcc := keeper.GetOracleAccount(ctx) + if moduleAcc == nil { + panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) + } +} + +// ExportGenesis writes the current store values +// to a genesis file, which can be imported again +// with InitGenesis +func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { + params := keeper.GetParams(ctx) + feederDelegations := []types.FeederDelegation{} + keeper.IterateFeederDelegations(ctx, func(valAddr sdk.ValAddress, feederAddr sdk.AccAddress) (stop bool) { + feederDelegations = append(feederDelegations, types.FeederDelegation{ + FeederAddress: feederAddr.String(), + ValidatorAddress: valAddr.String(), + }) + return false + }) + + exchangeRates := []types.ExchangeRateTuple{} + keeper.IterateBaseExchangeRates(ctx, func(denom string, rate sdk.Dec) (stop bool) { + exchangeRates = append(exchangeRates, types.ExchangeRateTuple{Denom: denom, ExchangeRate: rate}) + return false + }) + + missCounters := []types.MissCounter{} + keeper.IterateMissCounters(ctx, func(operator sdk.ValAddress, missCounter uint64) (stop bool) { + missCounters = append(missCounters, types.MissCounter{ + ValidatorAddress: operator.String(), + MissCounter: missCounter, + }) + return false + }) + + aggregateExchangeRatePrevotes := []types.AggregateExchangeRatePrevote{} + keeper.IterateAggregateExchangeRatePrevotes(ctx, func(_ sdk.ValAddress, aggregatePrevote types.AggregateExchangeRatePrevote) (stop bool) { + aggregateExchangeRatePrevotes = append(aggregateExchangeRatePrevotes, aggregatePrevote) + return false + }) + + aggregateExchangeRateVotes := []types.AggregateExchangeRateVote{} + keeper.IterateAggregateExchangeRateVotes(ctx, func(_ sdk.ValAddress, aggregateVote types.AggregateExchangeRateVote) bool { + aggregateExchangeRateVotes = append(aggregateExchangeRateVotes, aggregateVote) + return false + }) + + return types.NewGenesisState(params, + exchangeRates, + feederDelegations, + missCounters, + aggregateExchangeRatePrevotes, + aggregateExchangeRateVotes) +} diff --git a/x/oracle/genesis_test.go b/x/oracle/genesis_test.go new file mode 100755 index 0000000000..4d64487ad1 --- /dev/null +++ b/x/oracle/genesis_test.go @@ -0,0 +1,31 @@ +package oracle_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/sei-protocol/sei-chain/x/oracle" + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestExportInitGenesis(t *testing.T) { + input, _ := setup(t) + + input.OracleKeeper.SetFeederDelegation(input.Ctx, keeper.ValAddrs[0], keeper.Addrs[1]) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, "denom", sdk.NewDec(123)) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, keeper.ValAddrs[0], types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{123}, keeper.ValAddrs[0], uint64(2))) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, keeper.ValAddrs[0], types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "foo", ExchangeRate: sdk.NewDec(123)}}, keeper.ValAddrs[0])) + input.OracleKeeper.SetVoteTarget(input.Ctx, "denom") + input.OracleKeeper.SetVoteTarget(input.Ctx, "denom2") + genesis := oracle.ExportGenesis(input.Ctx, input.OracleKeeper) + + newInput := keeper.CreateTestInput(t) + oracle.InitGenesis(newInput.Ctx, newInput.OracleKeeper, genesis) + newGenesis := oracle.ExportGenesis(newInput.Ctx, newInput.OracleKeeper) + + require.Equal(t, genesis, newGenesis) +} diff --git a/x/oracle/handler.go b/x/oracle/handler.go new file mode 100755 index 0000000000..58c15f54cc --- /dev/null +++ b/x/oracle/handler.go @@ -0,0 +1,32 @@ +package oracle + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// NewHandler returns a handler for "oracle" type messages. +func NewHandler(k keeper.Keeper) sdk.Handler { + msgServer := keeper.NewMsgServerImpl(k) + + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + switch msg := msg.(type) { + case *types.MsgDelegateFeedConsent: + res, err := msgServer.DelegateFeedConsent(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgAggregateExchangeRatePrevote: + res, err := msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgAggregateExchangeRateVote: + res, err := msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + default: + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized oracle message type: %T", msg) + } + } +} diff --git a/x/oracle/handler_test.go b/x/oracle/handler_test.go new file mode 100755 index 0000000000..7c9c29a7ca --- /dev/null +++ b/x/oracle/handler_test.go @@ -0,0 +1,105 @@ +package oracle_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto/secp256k1" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +func TestOracleFilters(t *testing.T) { + input, h := setup(t) + + // Case 1: non-oracle message being sent fails + bankMsg := banktypes.MsgSend{} + _, err := h(input.Ctx, &bankMsg) + require.Error(t, err) + + // Case 2: Normal MsgAggregateExchangeRatePrevote submission goes through + salt := "1" + + hash := types.GetAggregateVoteHash(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.ValAddrs[0]) + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[0], keeper.ValAddrs[0]) + _, err = h(input.Ctx, prevoteMsg) + require.NoError(t, err) + + // // Case 3: Normal MsgAggregateExchangeRateVote submission goes through keeper.Addrs + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.Addrs[0], keeper.ValAddrs[0]) + _, err = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err) + + // Case 4: a non-validator sending an oracle message fails + nonValidatorPub := secp256k1.GenPrivKey().PubKey() + nonValidatorAddr := nonValidatorPub.Address() + salt = "2" + hash = types.GetAggregateVoteHash(salt, randomExchangeRate.String()+utils.MicroAtomDenom, sdk.ValAddress(nonValidatorAddr)) + + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, sdk.AccAddress(nonValidatorAddr), sdk.ValAddress(nonValidatorAddr)) + _, err = h(input.Ctx, prevoteMsg) + require.Error(t, err) +} + +func TestFeederDelegation(t *testing.T) { + input, h := setup(t) + + salt := "1" + hash := types.GetAggregateVoteHash(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.ValAddrs[0]) + + // Case 1: empty message + delegateFeedConsentMsg := types.MsgDelegateFeedConsent{} + _, err := h(input.Ctx, &delegateFeedConsentMsg) + require.Error(t, err) + + // Case 2: Normal Prevote - without delegation + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[0], keeper.ValAddrs[0]) + _, err = h(input.Ctx, prevoteMsg) + require.NoError(t, err) + + // Case 2.1: Normal Prevote - with delegation fails + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[1], keeper.ValAddrs[0]) + _, err = h(input.Ctx, prevoteMsg) + require.Error(t, err) + + // Case 2.2: Normal Vote - without delegation + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.Addrs[0], keeper.ValAddrs[0]) + _, err = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err) + + // Case 2.3: Normal Vote - with delegation fails + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.Addrs[1], keeper.ValAddrs[0]) + _, err = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.Error(t, err) + + // Case 3: Normal MsgDelegateFeedConsent succeeds + msg := types.NewMsgDelegateFeedConsent(keeper.ValAddrs[0], keeper.Addrs[1]) + _, err = h(input.Ctx, msg) + require.NoError(t, err) + + // Case 4.1: Normal Prevote - without delegation fails + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[2], keeper.ValAddrs[0]) + _, err = h(input.Ctx, prevoteMsg) + require.Error(t, err) + + // Case 4.2: Normal Prevote - with delegation succeeds + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[1], keeper.ValAddrs[0]) + _, err = h(input.Ctx, prevoteMsg) + require.NoError(t, err) + + // Case 4.3: Normal Vote - without delegation fails + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.Addrs[2], keeper.ValAddrs[0]) + _, err = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.Error(t, err) + + // Case 4.4: Normal Vote - with delegation succeeds + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+utils.MicroAtomDenom, keeper.Addrs[1], keeper.ValAddrs[0]) + _, err = h(input.Ctx.WithBlockHeight(1), voteMsg) + require.NoError(t, err) +} diff --git a/x/oracle/keeper/alias_functions.go b/x/oracle/keeper/alias_functions.go new file mode 100755 index 0000000000..a255edb2aa --- /dev/null +++ b/x/oracle/keeper/alias_functions.go @@ -0,0 +1,25 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// GetOracleAccount returns oracle ModuleAccount +func (k Keeper) GetOracleAccount(ctx sdk.Context) authtypes.ModuleAccountI { + return k.accountKeeper.GetModuleAccount(ctx, types.ModuleName) +} + +// GetRewardPool retrieves the balance of the oracle module account +func (k Keeper) GetRewardPool(ctx sdk.Context, denom string) sdk.Coin { + acc := k.accountKeeper.GetModuleAccount(ctx, types.ModuleName) + return k.bankKeeper.GetBalance(ctx, acc.GetAddress(), denom) +} + +// GetRewardPool retrieves the balance of the oracle module account +func (k Keeper) GetRewardPoolLegacy(ctx sdk.Context) sdk.Coins { + acc := k.accountKeeper.GetModuleAccount(ctx, types.ModuleName) + return k.bankKeeper.GetAllBalances(ctx, acc.GetAddress()) +} diff --git a/x/oracle/keeper/ballot.go b/x/oracle/keeper/ballot.go new file mode 100755 index 0000000000..d36a92989d --- /dev/null +++ b/x/oracle/keeper/ballot.go @@ -0,0 +1,118 @@ +package keeper + +import ( + "fmt" + "sort" + "strings" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// OrganizeBallotByDenom collects all oracle votes for the period, categorized by the votes' denom parameter +func (k Keeper) OrganizeBallotByDenom(ctx sdk.Context, validatorClaimMap map[string]types.Claim) (votes map[string]types.ExchangeRateBallot) { + votes = map[string]types.ExchangeRateBallot{} + + // Organize aggregate votes + aggregateHandler := func(voterAddr sdk.ValAddress, vote types.AggregateExchangeRateVote) (stop bool) { + // organize ballot only for the active validators + claim, ok := validatorClaimMap[vote.Voter] + + if ok { + power := claim.Power + for _, tuple := range vote.ExchangeRateTuples { + tmpPower := power + if !tuple.ExchangeRate.IsPositive() { + // Make the power of abstain vote zero + tmpPower = 0 + } + + votes[tuple.Denom] = append(votes[tuple.Denom], + types.NewVoteForTally( + tuple.ExchangeRate, + tuple.Denom, + voterAddr, + tmpPower, + ), + ) + } + + } + + return false + } + + k.IterateAggregateExchangeRateVotes(ctx, aggregateHandler) + + // sort created ballot + for denom, ballot := range votes { + sort.Sort(ballot) + votes[denom] = ballot + } + + return +} + +// ClearBallots clears all tallied prevotes and votes from the store +func (k Keeper) ClearBallots(ctx sdk.Context, votePeriod uint64) { + // Clear all aggregate prevotes + k.IterateAggregateExchangeRatePrevotes(ctx, func(voterAddr sdk.ValAddress, aggregatePrevote types.AggregateExchangeRatePrevote) (stop bool) { + if ctx.BlockHeight() > int64(aggregatePrevote.SubmitBlock+votePeriod) { + k.DeleteAggregateExchangeRatePrevote(ctx, voterAddr) + } + + return false + }) + + // Clear all aggregate votes + k.IterateAggregateExchangeRateVotes(ctx, func(voterAddr sdk.ValAddress, aggregateVote types.AggregateExchangeRateVote) (stop bool) { + k.DeleteAggregateExchangeRateVote(ctx, voterAddr) + return false + }) +} + +// ApplyWhitelist update vote target denom list with params whitelist +func (k Keeper) ApplyWhitelist(ctx sdk.Context, whitelist types.DenomList, voteTargets map[string]types.Denom) { + + // check is there any update in whitelist params + updateRequired := false + if len(voteTargets) != len(whitelist) { + updateRequired = true + } else { + for _, item := range whitelist { + if _, ok := voteTargets[item.Name]; !ok { + updateRequired = true + break + } + } + } + + if updateRequired { + k.ClearVoteTargets(ctx) + + for _, item := range whitelist { + k.SetVoteTarget(ctx, item.Name) + + // Register meta data to bank module + if _, ok := k.bankKeeper.GetDenomMetaData(ctx, item.Name); !ok { + base := item.Name + display := base[1:] + + k.bankKeeper.SetDenomMetaData(ctx, banktypes.Metadata{ + Description: display, + DenomUnits: []*banktypes.DenomUnit{ + {Denom: "u" + display, Exponent: uint32(0), Aliases: []string{"micro" + display}}, + {Denom: "m" + display, Exponent: uint32(3), Aliases: []string{"milli" + display}}, + {Denom: display, Exponent: uint32(6), Aliases: []string{}}, + }, + Base: base, + Display: display, + Name: fmt.Sprintf("%s TERRA", strings.ToUpper(display)), + Symbol: fmt.Sprintf("%sT", strings.ToUpper(display[:len(display)-1])), + }) + } + } + } +} diff --git a/x/oracle/keeper/ballot_test.go b/x/oracle/keeper/ballot_test.go new file mode 100755 index 0000000000..a093462b19 --- /dev/null +++ b/x/oracle/keeper/ballot_test.go @@ -0,0 +1,180 @@ +package keeper + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking" +) + +func TestOrganizeAggregate(t *testing.T) { + input := CreateTestInput(t) + + power := int64(100) + amt := sdk.TokensFromConsensusPower(power, sdk.DefaultPowerReduction) + sh := staking.NewHandler(input.StakingKeeper) + ctx := input.Ctx + + // Validator created + _, err := sh(ctx, NewTestMsgCreateValidator(ValAddrs[0], ValPubKeys[0], amt)) + require.NoError(t, err) + _, err = sh(ctx, NewTestMsgCreateValidator(ValAddrs[1], ValPubKeys[1], amt)) + require.NoError(t, err) + _, err = sh(ctx, NewTestMsgCreateValidator(ValAddrs[2], ValPubKeys[2], amt)) + require.NoError(t, err) + staking.EndBlocker(ctx, input.StakingKeeper) + + sdrBallot := types.ExchangeRateBallot{ + types.NewVoteForTally(sdk.NewDec(17), utils.MicroSeiDenom, ValAddrs[0], power), + types.NewVoteForTally(sdk.NewDec(10), utils.MicroSeiDenom, ValAddrs[1], power), + types.NewVoteForTally(sdk.NewDec(6), utils.MicroSeiDenom, ValAddrs[2], power), + } + krwBallot := types.ExchangeRateBallot{ + types.NewVoteForTally(sdk.NewDec(1000), utils.MicroAtomDenom, ValAddrs[0], power), + types.NewVoteForTally(sdk.NewDec(1300), utils.MicroAtomDenom, ValAddrs[1], power), + types.NewVoteForTally(sdk.NewDec(2000), utils.MicroAtomDenom, ValAddrs[2], power), + } + + for i := range sdrBallot { + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[i], + types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Denom: sdrBallot[i].Denom, ExchangeRate: sdrBallot[i].ExchangeRate}, + {Denom: krwBallot[i].Denom, ExchangeRate: krwBallot[i].ExchangeRate}, + }, ValAddrs[i])) + } + + // organize votes by denom + ballotMap := input.OracleKeeper.OrganizeBallotByDenom(input.Ctx, map[string]types.Claim{ + ValAddrs[0].String(): { + Power: power, + WinCount: 0, + Recipient: ValAddrs[0], + }, + ValAddrs[1].String(): { + Power: power, + WinCount: 0, + Recipient: ValAddrs[1], + }, + ValAddrs[2].String(): { + Power: power, + WinCount: 0, + Recipient: ValAddrs[2], + }, + }) + + // sort each ballot for comparison + sort.Sort(sdrBallot) + sort.Sort(krwBallot) + sort.Sort(ballotMap[utils.MicroSeiDenom]) + sort.Sort(ballotMap[utils.MicroAtomDenom]) + + require.Equal(t, sdrBallot, ballotMap[utils.MicroSeiDenom]) + require.Equal(t, krwBallot, ballotMap[utils.MicroAtomDenom]) +} + +func TestClearBallots(t *testing.T) { + input := CreateTestInput(t) + + power := int64(100) + amt := sdk.TokensFromConsensusPower(power, sdk.DefaultPowerReduction) + sh := staking.NewHandler(input.StakingKeeper) + ctx := input.Ctx + + // Validator created + _, err := sh(ctx, NewTestMsgCreateValidator(ValAddrs[0], ValPubKeys[0], amt)) + require.NoError(t, err) + _, err = sh(ctx, NewTestMsgCreateValidator(ValAddrs[1], ValPubKeys[1], amt)) + require.NoError(t, err) + _, err = sh(ctx, NewTestMsgCreateValidator(ValAddrs[2], ValPubKeys[2], amt)) + require.NoError(t, err) + staking.EndBlocker(ctx, input.StakingKeeper) + + sdrBallot := types.ExchangeRateBallot{ + types.NewVoteForTally(sdk.NewDec(17), utils.MicroSeiDenom, ValAddrs[0], power), + types.NewVoteForTally(sdk.NewDec(10), utils.MicroSeiDenom, ValAddrs[1], power), + types.NewVoteForTally(sdk.NewDec(6), utils.MicroSeiDenom, ValAddrs[2], power), + } + krwBallot := types.ExchangeRateBallot{ + types.NewVoteForTally(sdk.NewDec(1000), utils.MicroAtomDenom, ValAddrs[0], power), + types.NewVoteForTally(sdk.NewDec(1300), utils.MicroAtomDenom, ValAddrs[1], power), + types.NewVoteForTally(sdk.NewDec(2000), utils.MicroAtomDenom, ValAddrs[2], power), + } + + for i := range sdrBallot { + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, ValAddrs[i], types.AggregateExchangeRatePrevote{ + Hash: "", + Voter: ValAddrs[i].String(), + SubmitBlock: uint64(input.Ctx.BlockHeight()), + }) + + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[i], + types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Denom: sdrBallot[i].Denom, ExchangeRate: sdrBallot[i].ExchangeRate}, + {Denom: krwBallot[i].Denom, ExchangeRate: krwBallot[i].ExchangeRate}, + }, ValAddrs[i])) + } + + input.OracleKeeper.ClearBallots(input.Ctx, 5) + + prevoteCounter := 0 + voteCounter := 0 + input.OracleKeeper.IterateAggregateExchangeRatePrevotes(input.Ctx, func(_ sdk.ValAddress, _ types.AggregateExchangeRatePrevote) bool { + prevoteCounter++ + return false + }) + input.OracleKeeper.IterateAggregateExchangeRateVotes(input.Ctx, func(_ sdk.ValAddress, _ types.AggregateExchangeRateVote) bool { + voteCounter++ + return false + }) + + require.Equal(t, prevoteCounter, 3) + require.Equal(t, voteCounter, 0) + + input.OracleKeeper.ClearBallots(input.Ctx.WithBlockHeight(input.Ctx.BlockHeight()+6), 5) + + prevoteCounter = 0 + input.OracleKeeper.IterateAggregateExchangeRatePrevotes(input.Ctx, func(_ sdk.ValAddress, _ types.AggregateExchangeRatePrevote) bool { + prevoteCounter++ + return false + }) + require.Equal(t, prevoteCounter, 0) +} + +func TestApplyWhitelist(t *testing.T) { + input := CreateTestInput(t) + + input.OracleKeeper.ApplyWhitelist(input.Ctx, types.DenomList{ + types.Denom{ + Name: "uatom", + }, + types.Denom{ + Name: "uusdc", + }, + }, map[string]types.Denom{}) + + _, err := input.OracleKeeper.GetVoteTarget(input.Ctx, "uatom") + require.NoError(t, err) + + _, err = input.OracleKeeper.GetVoteTarget(input.Ctx, "uusdc") + require.NoError(t, err) + + metadata, ok := input.BankKeeper.GetDenomMetaData(input.Ctx, "uatom") + require.True(t, ok) + require.Equal(t, metadata.Base, "uatom") + require.Equal(t, metadata.Display, "atom") + require.Equal(t, len(metadata.DenomUnits), 3) + require.Equal(t, metadata.Description, "atom") + + metadata, ok = input.BankKeeper.GetDenomMetaData(input.Ctx, "uusdc") + require.True(t, ok) + require.Equal(t, metadata.Base, "uusdc") + require.Equal(t, metadata.Display, "usdc") + require.Equal(t, len(metadata.DenomUnits), 3) + require.Equal(t, metadata.Description, "usdc") +} diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go new file mode 100755 index 0000000000..71809bd308 --- /dev/null +++ b/x/oracle/keeper/keeper.go @@ -0,0 +1,356 @@ +package keeper + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + gogotypes "github.com/gogo/protobuf/types" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +// Keeper of the oracle store +type Keeper struct { + cdc codec.BinaryCodec + storeKey sdk.StoreKey + paramSpace paramstypes.Subspace + + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + distrKeeper types.DistributionKeeper + StakingKeeper types.StakingKeeper + + distrName string +} + +// NewKeeper constructs a new keeper for oracle +func NewKeeper(cdc codec.BinaryCodec, storeKey sdk.StoreKey, + paramspace paramstypes.Subspace, accountKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, distrKeeper types.DistributionKeeper, + stakingKeeper types.StakingKeeper, distrName string) Keeper { + + // ensure oracle module account is set + if addr := accountKeeper.GetModuleAddress(types.ModuleName); addr == nil { + panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) + } + + // set KeyTable if it has not already been set + if !paramspace.HasKeyTable() { + paramspace = paramspace.WithKeyTable(types.ParamKeyTable()) + } + + return Keeper{ + cdc: cdc, + storeKey: storeKey, + paramSpace: paramspace, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + distrKeeper: distrKeeper, + StakingKeeper: stakingKeeper, + distrName: distrName, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +//----------------------------------- +// ExchangeRate logic + +func (k Keeper) GetBaseExchangeRate(ctx sdk.Context, denom string) (sdk.Dec, error) { + if denom == utils.MicroBaseDenom { + return sdk.OneDec(), nil + } + + store := ctx.KVStore(k.storeKey) + b := store.Get(types.GetExchangeRateKey(denom)) + if b == nil { + return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrUnknownDenom, denom) + } + + dp := sdk.DecProto{} + k.cdc.MustUnmarshal(b, &dp) + return dp.Dec, nil +} + +func (k Keeper) SetBaseExchangeRate(ctx sdk.Context, denom string, exchangeRate sdk.Dec) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&sdk.DecProto{Dec: exchangeRate}) + store.Set(types.GetExchangeRateKey(denom), bz) +} + +func (k Keeper) SetBaseExchangeRateWithEvent(ctx sdk.Context, denom string, exchangeRate sdk.Dec) { + k.SetBaseExchangeRate(ctx, denom, exchangeRate) + ctx.EventManager().EmitEvent( + sdk.NewEvent(types.EventTypeExchangeRateUpdate, + sdk.NewAttribute(types.AttributeKeyDenom, denom), + sdk.NewAttribute(types.AttributeKeyExchangeRate, exchangeRate.String()), + ), + ) +} + +func (k Keeper) DeleteBaseExchangeRate(ctx sdk.Context, denom string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetExchangeRateKey(denom)) +} + +func (k Keeper) IterateBaseExchangeRates(ctx sdk.Context, handler func(denom string, exchangeRate sdk.Dec) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.ExchangeRateKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + denom := string(iter.Key()[len(types.ExchangeRateKey):]) + dp := sdk.DecProto{} + k.cdc.MustUnmarshal(iter.Value(), &dp) + if handler(denom, dp.Dec) { + break + } + } +} + +//----------------------------------- +// Oracle delegation logic + +// GetFeederDelegation gets the account address that the validator operator delegated oracle vote rights to +func (k Keeper) GetFeederDelegation(ctx sdk.Context, operator sdk.ValAddress) sdk.AccAddress { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.GetFeederDelegationKey(operator)) + if bz == nil { + // By default the right is delegated to the validator itself + return sdk.AccAddress(operator) + } + + return sdk.AccAddress(bz) +} + +// SetFeederDelegation sets the account address that the validator operator delegated oracle vote rights to +func (k Keeper) SetFeederDelegation(ctx sdk.Context, operator sdk.ValAddress, delegatedFeeder sdk.AccAddress) { + store := ctx.KVStore(k.storeKey) + store.Set(types.GetFeederDelegationKey(operator), delegatedFeeder.Bytes()) +} + +// IterateFeederDelegations iterates over the feed delegates and performs a callback function. +func (k Keeper) IterateFeederDelegations(ctx sdk.Context, + handler func(delegator sdk.ValAddress, delegate sdk.AccAddress) (stop bool)) { + + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.FeederDelegationKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + delegator := sdk.ValAddress(iter.Key()[2:]) + delegate := sdk.AccAddress(iter.Value()) + + if handler(delegator, delegate) { + break + } + } +} + +//----------------------------------- +// Miss counter logic + +// GetMissCounter retrieves the # of vote periods missed in this oracle slash window +func (k Keeper) GetMissCounter(ctx sdk.Context, operator sdk.ValAddress) uint64 { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.GetMissCounterKey(operator)) + if bz == nil { + // By default the counter is zero + return 0 + } + + var missCounter gogotypes.UInt64Value + k.cdc.MustUnmarshal(bz, &missCounter) + return missCounter.Value +} + +// SetMissCounter updates the # of vote periods missed in this oracle slash window +func (k Keeper) SetMissCounter(ctx sdk.Context, operator sdk.ValAddress, missCounter uint64) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&gogotypes.UInt64Value{Value: missCounter}) + store.Set(types.GetMissCounterKey(operator), bz) +} + +// DeleteMissCounter removes miss counter for the validator +func (k Keeper) DeleteMissCounter(ctx sdk.Context, operator sdk.ValAddress) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetMissCounterKey(operator)) +} + +// IterateMissCounters iterates over the miss counters and performs a callback function. +func (k Keeper) IterateMissCounters(ctx sdk.Context, + handler func(operator sdk.ValAddress, missCounter uint64) (stop bool)) { + + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.MissCounterKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + operator := sdk.ValAddress(iter.Key()[2:]) + + var missCounter gogotypes.UInt64Value + k.cdc.MustUnmarshal(iter.Value(), &missCounter) + + if handler(operator, missCounter.Value) { + break + } + } +} + +//----------------------------------- +// AggregateExchangeRatePrevote logic + +// GetAggregateExchangeRatePrevote retrieves an oracle prevote from the store +func (k Keeper) GetAggregateExchangeRatePrevote(ctx sdk.Context, voter sdk.ValAddress) (aggregatePrevote types.AggregateExchangeRatePrevote, err error) { + store := ctx.KVStore(k.storeKey) + b := store.Get(types.GetAggregateExchangeRatePrevoteKey(voter)) + if b == nil { + err = sdkerrors.Wrap(types.ErrNoAggregatePrevote, voter.String()) + return + } + k.cdc.MustUnmarshal(b, &aggregatePrevote) + return +} + +// SetAggregateExchangeRatePrevote set an oracle aggregate prevote to the store +func (k Keeper) SetAggregateExchangeRatePrevote(ctx sdk.Context, voter sdk.ValAddress, prevote types.AggregateExchangeRatePrevote) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&prevote) + + store.Set(types.GetAggregateExchangeRatePrevoteKey(voter), bz) +} + +// DeleteAggregateExchangeRatePrevote deletes an oracle prevote from the store +func (k Keeper) DeleteAggregateExchangeRatePrevote(ctx sdk.Context, voter sdk.ValAddress) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetAggregateExchangeRatePrevoteKey(voter)) +} + +// IterateAggregateExchangeRatePrevotes iterates rate over prevotes in the store +func (k Keeper) IterateAggregateExchangeRatePrevotes(ctx sdk.Context, handler func(voterAddr sdk.ValAddress, aggregatePrevote types.AggregateExchangeRatePrevote) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.AggregateExchangeRatePrevoteKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + voterAddr := sdk.ValAddress(iter.Key()[2:]) + + var aggregatePrevote types.AggregateExchangeRatePrevote + k.cdc.MustUnmarshal(iter.Value(), &aggregatePrevote) + if handler(voterAddr, aggregatePrevote) { + break + } + } +} + +//----------------------------------- +// AggregateExchangeRateVote logic + +// GetAggregateExchangeRateVote retrieves an oracle prevote from the store +func (k Keeper) GetAggregateExchangeRateVote(ctx sdk.Context, voter sdk.ValAddress) (aggregateVote types.AggregateExchangeRateVote, err error) { + store := ctx.KVStore(k.storeKey) + b := store.Get(types.GetAggregateExchangeRateVoteKey(voter)) + if b == nil { + err = sdkerrors.Wrap(types.ErrNoAggregateVote, voter.String()) + return + } + k.cdc.MustUnmarshal(b, &aggregateVote) + return +} + +// SetAggregateExchangeRateVote adds an oracle aggregate prevote to the store +func (k Keeper) SetAggregateExchangeRateVote(ctx sdk.Context, voter sdk.ValAddress, vote types.AggregateExchangeRateVote) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&vote) + store.Set(types.GetAggregateExchangeRateVoteKey(voter), bz) +} + +// DeleteAggregateExchangeRateVote deletes an oracle prevote from the store +func (k Keeper) DeleteAggregateExchangeRateVote(ctx sdk.Context, voter sdk.ValAddress) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetAggregateExchangeRateVoteKey(voter)) +} + +// IterateAggregateExchangeRateVotes iterates rate over prevotes in the store +func (k Keeper) IterateAggregateExchangeRateVotes(ctx sdk.Context, handler func(voterAddr sdk.ValAddress, aggregateVote types.AggregateExchangeRateVote) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.AggregateExchangeRateVoteKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + voterAddr := sdk.ValAddress(iter.Key()[2:]) + + var aggregateVote types.AggregateExchangeRateVote + k.cdc.MustUnmarshal(iter.Value(), &aggregateVote) + if handler(voterAddr, aggregateVote) { + break + } + } +} + +func (k Keeper) GetVoteTarget(ctx sdk.Context, denom string) (types.Denom, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.GetVoteTargetKey(denom)) + if bz == nil { + err := sdkerrors.Wrap(types.ErrNoVoteTarget, denom) + return types.Denom{}, err + } + + voteTarget := types.Denom{} + k.cdc.MustUnmarshal(bz, &voteTarget) + + return voteTarget, nil +} + +func (k Keeper) SetVoteTarget(ctx sdk.Context, denom string) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&types.Denom{Name: denom}) + store.Set(types.GetVoteTargetKey(denom), bz) +} + +func (k Keeper) IterateVoteTargets(ctx sdk.Context, handler func(denom string, denomInfo types.Denom) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.VoteTargetKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + denom := types.ExtractDenomFromVoteTargetKey(iter.Key()) + + var denomInfo types.Denom + k.cdc.MustUnmarshal(iter.Value(), &denomInfo) + if handler(denom, denomInfo) { + break + } + } +} + +func (k Keeper) ClearVoteTargets(ctx sdk.Context) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.VoteTargetKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + store.Delete(iter.Key()) + } +} + +// ValidateFeeder return the given feeder is allowed to feed the message or not +func (k Keeper) ValidateFeeder(ctx sdk.Context, feederAddr sdk.AccAddress, validatorAddr sdk.ValAddress) error { + if !feederAddr.Equals(validatorAddr) { + delegate := k.GetFeederDelegation(ctx, validatorAddr) + if !delegate.Equals(feederAddr) { + return sdkerrors.Wrap(types.ErrNoVotingPermission, feederAddr.String()) + } + } + + // Check that the given validator exists + if val := k.StakingKeeper.Validator(ctx, validatorAddr); val == nil || !val.IsBonded() { + return sdkerrors.Wrapf(stakingtypes.ErrNoValidatorFound, "validator %s is not active set", validatorAddr.String()) + } + + return nil +} diff --git a/x/oracle/keeper/keeper_test.go b/x/oracle/keeper/keeper_test.go new file mode 100755 index 0000000000..ea5ff6869c --- /dev/null +++ b/x/oracle/keeper/keeper_test.go @@ -0,0 +1,377 @@ +package keeper + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func TestExchangeRate(t *testing.T) { + input := CreateTestInput(t) + + cnyExchangeRate := sdk.NewDecWithPrec(839, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + gbpExchangeRate := sdk.NewDecWithPrec(4995, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + krwExchangeRate := sdk.NewDecWithPrec(2838, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + lunaExchangeRate := sdk.NewDecWithPrec(3282384, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + + // Set & get rates + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroSeiDenom, cnyExchangeRate) + rate, err := input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroSeiDenom) + require.NoError(t, err) + require.Equal(t, cnyExchangeRate, rate) + + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroEthDenom, gbpExchangeRate) + rate, err = input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroEthDenom) + require.NoError(t, err) + require.Equal(t, gbpExchangeRate, rate) + + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom, krwExchangeRate) + rate, err = input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + require.NoError(t, err) + require.Equal(t, krwExchangeRate, rate) + + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroBaseDenom, lunaExchangeRate) + rate, _ = input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroBaseDenom) + require.Equal(t, sdk.OneDec(), rate) + + input.OracleKeeper.DeleteBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + _, err = input.OracleKeeper.GetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom) + require.Error(t, err) + + numExchangeRates := 0 + handler := func(denom string, exchangeRate sdk.Dec) (stop bool) { + numExchangeRates = numExchangeRates + 1 + return false + } + input.OracleKeeper.IterateBaseExchangeRates(input.Ctx, handler) + + require.True(t, numExchangeRates == 3) +} + +func TestIterateLunaExchangeRates(t *testing.T) { + input := CreateTestInput(t) + + cnyExchangeRate := sdk.NewDecWithPrec(839, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + gbpExchangeRate := sdk.NewDecWithPrec(4995, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + krwExchangeRate := sdk.NewDecWithPrec(2838, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + lunaExchangeRate := sdk.NewDecWithPrec(3282384, int64(OracleDecPrecision)).MulInt64(utils.MicroUnit) + + // Set & get rates + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroSeiDenom, cnyExchangeRate) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroEthDenom, gbpExchangeRate) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom, krwExchangeRate) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroBaseDenom, lunaExchangeRate) + + input.OracleKeeper.IterateBaseExchangeRates(input.Ctx, func(denom string, rate sdk.Dec) (stop bool) { + switch denom { + case utils.MicroSeiDenom: + require.Equal(t, cnyExchangeRate, rate) + case utils.MicroEthDenom: + require.Equal(t, gbpExchangeRate, rate) + case utils.MicroAtomDenom: + require.Equal(t, krwExchangeRate, rate) + case utils.MicroBaseDenom: + require.Equal(t, lunaExchangeRate, rate) + } + return false + }) + +} + +func TestRewardPool(t *testing.T) { + input := CreateTestInput(t) + + fees := sdk.NewCoins(sdk.NewCoin(utils.MicroEthDenom, sdk.NewInt(1000))) + acc := input.AccountKeeper.GetModuleAccount(input.Ctx, types.ModuleName) + err := FundAccount(input, acc.GetAddress(), fees) + if err != nil { + panic(err) // never occurs + } + + KFees := input.OracleKeeper.GetRewardPool(input.Ctx, utils.MicroEthDenom) + require.Equal(t, fees[0], KFees) +} + +func TestParams(t *testing.T) { + input := CreateTestInput(t) + + // Test default params setting + input.OracleKeeper.SetParams(input.Ctx, types.DefaultParams()) + params := input.OracleKeeper.GetParams(input.Ctx) + require.NotNil(t, params) + + // Test custom params setting + votePeriod := uint64(10) + voteThreshold := sdk.NewDecWithPrec(33, 2) + oracleRewardBand := sdk.NewDecWithPrec(1, 2) + slashFraction := sdk.NewDecWithPrec(1, 2) + slashWindow := uint64(1000) + minValidPerWindow := sdk.NewDecWithPrec(1, 4) + whitelist := types.DenomList{ + {Name: utils.MicroEthDenom}, + {Name: utils.MicroAtomDenom}, + } + + // Should really test validateParams, but skipping because obvious + newParams := types.Params{ + VotePeriod: votePeriod, + VoteThreshold: voteThreshold, + RewardBand: oracleRewardBand, + Whitelist: whitelist, + SlashFraction: slashFraction, + SlashWindow: slashWindow, + MinValidPerWindow: minValidPerWindow, + } + input.OracleKeeper.SetParams(input.Ctx, newParams) + + storedParams := input.OracleKeeper.GetParams(input.Ctx) + require.NotNil(t, storedParams) + require.Equal(t, storedParams, newParams) +} + +func TestFeederDelegation(t *testing.T) { + input := CreateTestInput(t) + + // Test default getters and setters + delegate := input.OracleKeeper.GetFeederDelegation(input.Ctx, ValAddrs[0]) + require.Equal(t, Addrs[0], delegate) + + input.OracleKeeper.SetFeederDelegation(input.Ctx, ValAddrs[0], Addrs[1]) + delegate = input.OracleKeeper.GetFeederDelegation(input.Ctx, ValAddrs[0]) + require.Equal(t, Addrs[1], delegate) +} + +func TestIterateFeederDelegations(t *testing.T) { + input := CreateTestInput(t) + + // Test default getters and setters + delegate := input.OracleKeeper.GetFeederDelegation(input.Ctx, ValAddrs[0]) + require.Equal(t, Addrs[0], delegate) + + input.OracleKeeper.SetFeederDelegation(input.Ctx, ValAddrs[0], Addrs[1]) + + var delegators []sdk.ValAddress + var delegates []sdk.AccAddress + input.OracleKeeper.IterateFeederDelegations(input.Ctx, func(delegator sdk.ValAddress, delegate sdk.AccAddress) (stop bool) { + delegators = append(delegators, delegator) + delegates = append(delegates, delegate) + return false + }) + + require.Equal(t, 1, len(delegators)) + require.Equal(t, 1, len(delegates)) + require.Equal(t, ValAddrs[0], delegators[0]) + require.Equal(t, Addrs[1], delegates[0]) +} + +func TestMissCounter(t *testing.T) { + input := CreateTestInput(t) + + // Test default getters and setters + counter := input.OracleKeeper.GetMissCounter(input.Ctx, ValAddrs[0]) + require.Equal(t, uint64(0), counter) + + missCounter := uint64(10) + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], missCounter) + counter = input.OracleKeeper.GetMissCounter(input.Ctx, ValAddrs[0]) + require.Equal(t, missCounter, counter) + + input.OracleKeeper.DeleteMissCounter(input.Ctx, ValAddrs[0]) + counter = input.OracleKeeper.GetMissCounter(input.Ctx, ValAddrs[0]) + require.Equal(t, uint64(0), counter) +} + +func TestIterateMissCounters(t *testing.T) { + input := CreateTestInput(t) + + // Test default getters and setters + counter := input.OracleKeeper.GetMissCounter(input.Ctx, ValAddrs[0]) + require.Equal(t, uint64(0), counter) + + missCounter := uint64(10) + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[1], missCounter) + + var operators []sdk.ValAddress + var missCounters []uint64 + input.OracleKeeper.IterateMissCounters(input.Ctx, func(delegator sdk.ValAddress, missCounter uint64) (stop bool) { + operators = append(operators, delegator) + missCounters = append(missCounters, missCounter) + return false + }) + + require.Equal(t, 1, len(operators)) + require.Equal(t, 1, len(missCounters)) + require.Equal(t, ValAddrs[1], operators[0]) + require.Equal(t, missCounter, missCounters[0]) +} + +func TestAggregatePrevoteAddDelete(t *testing.T) { + input := CreateTestInput(t) + + hash := types.GetAggregateVoteHash("salt", "100ukrw,1000uusd", sdk.ValAddress(Addrs[0])) + aggregatePrevote := types.NewAggregateExchangeRatePrevote(hash, sdk.ValAddress(Addrs[0]), 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, sdk.ValAddress(Addrs[0]), aggregatePrevote) + + KPrevote, err := input.OracleKeeper.GetAggregateExchangeRatePrevote(input.Ctx, sdk.ValAddress(Addrs[0])) + require.NoError(t, err) + require.Equal(t, aggregatePrevote, KPrevote) + + input.OracleKeeper.DeleteAggregateExchangeRatePrevote(input.Ctx, sdk.ValAddress(Addrs[0])) + _, err = input.OracleKeeper.GetAggregateExchangeRatePrevote(input.Ctx, sdk.ValAddress(Addrs[0])) + require.Error(t, err) +} + +func TestAggregatePrevoteIterate(t *testing.T) { + input := CreateTestInput(t) + + hash := types.GetAggregateVoteHash("salt", "100ukrw,1000uusd", sdk.ValAddress(Addrs[0])) + aggregatePrevote1 := types.NewAggregateExchangeRatePrevote(hash, sdk.ValAddress(Addrs[0]), 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, sdk.ValAddress(Addrs[0]), aggregatePrevote1) + + hash2 := types.GetAggregateVoteHash("salt", "100ukrw,1000uusd", sdk.ValAddress(Addrs[1])) + aggregatePrevote2 := types.NewAggregateExchangeRatePrevote(hash2, sdk.ValAddress(Addrs[1]), 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, sdk.ValAddress(Addrs[1]), aggregatePrevote2) + + i := 0 + bigger := bytes.Compare(Addrs[0], Addrs[1]) + input.OracleKeeper.IterateAggregateExchangeRatePrevotes(input.Ctx, func(voter sdk.ValAddress, p types.AggregateExchangeRatePrevote) (stop bool) { + if (i == 0 && bigger == -1) || (i == 1 && bigger == 1) { + require.Equal(t, aggregatePrevote1, p) + require.Equal(t, voter.String(), p.Voter) + } else { + require.Equal(t, aggregatePrevote2, p) + require.Equal(t, voter.String(), p.Voter) + } + + i++ + return false + }) +} + +func TestAggregateVoteAddDelete(t *testing.T) { + input := CreateTestInput(t) + + aggregateVote := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Denom: "foo", ExchangeRate: sdk.NewDec(-1)}, + {Denom: "foo", ExchangeRate: sdk.NewDec(0)}, + {Denom: "foo", ExchangeRate: sdk.NewDec(1)}, + }, sdk.ValAddress(Addrs[0])) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[0]), aggregateVote) + + KVote, err := input.OracleKeeper.GetAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[0])) + require.NoError(t, err) + require.Equal(t, aggregateVote, KVote) + + input.OracleKeeper.DeleteAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[0])) + _, err = input.OracleKeeper.GetAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[0])) + require.Error(t, err) +} + +func TestAggregateVoteIterate(t *testing.T) { + input := CreateTestInput(t) + + aggregateVote1 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Denom: "foo", ExchangeRate: sdk.NewDec(-1)}, + {Denom: "foo", ExchangeRate: sdk.NewDec(0)}, + {Denom: "foo", ExchangeRate: sdk.NewDec(1)}, + }, sdk.ValAddress(Addrs[0])) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[0]), aggregateVote1) + + aggregateVote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Denom: "foo", ExchangeRate: sdk.NewDec(-1)}, + {Denom: "foo", ExchangeRate: sdk.NewDec(0)}, + {Denom: "foo", ExchangeRate: sdk.NewDec(1)}, + }, sdk.ValAddress(Addrs[1])) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[1]), aggregateVote2) + + i := 0 + bigger := bytes.Compare(address.MustLengthPrefix(Addrs[0]), address.MustLengthPrefix(Addrs[1])) + input.OracleKeeper.IterateAggregateExchangeRateVotes(input.Ctx, func(voter sdk.ValAddress, p types.AggregateExchangeRateVote) (stop bool) { + if (i == 0 && bigger == -1) || (i == 1 && bigger == 1) { + require.Equal(t, aggregateVote1, p) + require.Equal(t, voter.String(), p.Voter) + } else { + require.Equal(t, aggregateVote2, p) + require.Equal(t, voter.String(), p.Voter) + } + + i++ + return false + }) +} + +func TestVoteTargetGetSet(t *testing.T) { + input := CreateTestInput(t) + + voteTargets := map[string]types.Denom{ + utils.MicroEthDenom: types.Denom{utils.MicroEthDenom}, + utils.MicroUsdcDenom: types.Denom{utils.MicroUsdcDenom}, + utils.MicroAtomDenom: types.Denom{utils.MicroAtomDenom}, + utils.MicroSeiDenom: types.Denom{utils.MicroSeiDenom}, + } + + for denom := range voteTargets { + input.OracleKeeper.SetVoteTarget(input.Ctx, denom) + denomInfo, err := input.OracleKeeper.GetVoteTarget(input.Ctx, denom) + require.NoError(t, err) + require.Equal(t, voteTargets[denom], denomInfo) + } + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + for denom := range voteTargets { + _, err := input.OracleKeeper.GetVoteTarget(input.Ctx, denom) + require.Error(t, err) + } +} + +func TestValidateFeeder(t *testing.T) { + // initial setup + input := CreateTestInput(t) + addr, val := ValAddrs[0], ValPubKeys[0] + addr1, val1 := ValAddrs[1], ValPubKeys[1] + amt := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) + sh := staking.NewHandler(input.StakingKeeper) + ctx := input.Ctx + + // Validator created + _, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + require.NoError(t, err) + _, err = sh(ctx, NewTestMsgCreateValidator(addr1, val1, amt)) + require.NoError(t, err) + staking.EndBlocker(ctx, input.StakingKeeper) + + require.Equal( + t, input.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(input.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), + ) + require.Equal(t, amt, input.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) + require.Equal( + t, input.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr1)), + sdk.NewCoins(sdk.NewCoin(input.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), + ) + require.Equal(t, amt, input.StakingKeeper.Validator(ctx, addr1).GetBondedTokens()) + + require.NoError(t, input.OracleKeeper.ValidateFeeder(input.Ctx, sdk.AccAddress(addr), sdk.ValAddress(addr))) + require.NoError(t, input.OracleKeeper.ValidateFeeder(input.Ctx, sdk.AccAddress(addr1), sdk.ValAddress(addr1))) + + // delegate works + input.OracleKeeper.SetFeederDelegation(input.Ctx, sdk.ValAddress(addr), sdk.AccAddress(addr1)) + require.NoError(t, input.OracleKeeper.ValidateFeeder(input.Ctx, sdk.AccAddress(addr1), sdk.ValAddress(addr))) + require.Error(t, input.OracleKeeper.ValidateFeeder(input.Ctx, sdk.AccAddress(Addrs[2]), sdk.ValAddress(addr))) + + // only active validators can do oracle votes + validator, found := input.StakingKeeper.GetValidator(input.Ctx, sdk.ValAddress(addr)) + require.True(t, found) + validator.Status = stakingtypes.Unbonded + input.StakingKeeper.SetValidator(input.Ctx, validator) + require.Error(t, input.OracleKeeper.ValidateFeeder(input.Ctx, sdk.AccAddress(addr1), sdk.ValAddress(addr))) +} diff --git a/x/oracle/keeper/msg_server.go b/x/oracle/keeper/msg_server.go new file mode 100755 index 0000000000..7dfb190e8f --- /dev/null +++ b/x/oracle/keeper/msg_server.go @@ -0,0 +1,166 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the oracle MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +func (ms msgServer) AggregateExchangeRatePrevote(goCtx context.Context, msg *types.MsgAggregateExchangeRatePrevote) (*types.MsgAggregateExchangeRatePrevoteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + valAddr, err := sdk.ValAddressFromBech32(msg.Validator) + if err != nil { + return nil, err + } + + feederAddr, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + return nil, err + } + + if err := ms.ValidateFeeder(ctx, feederAddr, valAddr); err != nil { + return nil, err + } + + // Convert hex string to votehash + voteHash, err := types.AggregateVoteHashFromHexString(msg.Hash) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidHash, err.Error()) + } + + aggregatePrevote := types.NewAggregateExchangeRatePrevote(voteHash, valAddr, uint64(ctx.BlockHeight())) + ms.SetAggregateExchangeRatePrevote(ctx, valAddr, aggregatePrevote) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeAggregatePrevote, + sdk.NewAttribute(types.AttributeKeyVoter, msg.Validator), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Feeder), + ), + }) + + return &types.MsgAggregateExchangeRatePrevoteResponse{}, nil +} + +func (ms msgServer) AggregateExchangeRateVote(goCtx context.Context, msg *types.MsgAggregateExchangeRateVote) (*types.MsgAggregateExchangeRateVoteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + valAddr, err := sdk.ValAddressFromBech32(msg.Validator) + if err != nil { + return nil, err + } + + feederAddr, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + return nil, err + } + + if err := ms.ValidateFeeder(ctx, feederAddr, valAddr); err != nil { + return nil, err + } + + params := ms.GetParams(ctx) + + aggregatePrevote, err := ms.GetAggregateExchangeRatePrevote(ctx, valAddr) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrNoAggregatePrevote, msg.Validator) + } + + // Check a msg is submitted proper period + if (uint64(ctx.BlockHeight())/params.VotePeriod)-(aggregatePrevote.SubmitBlock/params.VotePeriod) != 1 { + return nil, types.ErrRevealPeriodMissMatch + } + + exchangeRateTuples, err := types.ParseExchangeRateTuples(msg.ExchangeRates) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error()) + } + + // check all denoms are in the vote target + for _, tuple := range exchangeRateTuples { + if !ms.IsVoteTarget(ctx, tuple.Denom) { + return nil, sdkerrors.Wrap(types.ErrUnknownDenom, tuple.Denom) + } + } + + // Verify a exchange rate with aggregate prevote hash + hash := types.GetAggregateVoteHash(msg.Salt, msg.ExchangeRates, valAddr) + if aggregatePrevote.Hash != hash.String() { + return nil, sdkerrors.Wrapf(types.ErrVerificationFailed, "must be given %s not %s", aggregatePrevote.Hash, hash) + } + + // Move aggregate prevote to aggregate vote with given exchange rates + ms.SetAggregateExchangeRateVote(ctx, valAddr, types.NewAggregateExchangeRateVote(exchangeRateTuples, valAddr)) + ms.DeleteAggregateExchangeRatePrevote(ctx, valAddr) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeAggregateVote, + sdk.NewAttribute(types.AttributeKeyVoter, msg.Validator), + sdk.NewAttribute(types.AttributeKeyExchangeRates, msg.ExchangeRates), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Feeder), + ), + }) + + return &types.MsgAggregateExchangeRateVoteResponse{}, nil +} + +func (ms msgServer) DelegateFeedConsent(goCtx context.Context, msg *types.MsgDelegateFeedConsent) (*types.MsgDelegateFeedConsentResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + operatorAddr, err := sdk.ValAddressFromBech32(msg.Operator) + if err != nil { + return nil, err + } + + delegateAddr, err := sdk.AccAddressFromBech32(msg.Delegate) + if err != nil { + return nil, err + } + + // Check the delegator is a validator + val := ms.StakingKeeper.Validator(ctx, operatorAddr) + if val == nil { + return nil, sdkerrors.Wrap(stakingtypes.ErrNoValidatorFound, msg.Operator) + } + + // Set the delegation + ms.SetFeederDelegation(ctx, operatorAddr, delegateAddr) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeFeedDelegate, + sdk.NewAttribute(types.AttributeKeyFeeder, msg.Delegate), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Operator), + ), + }) + + return &types.MsgDelegateFeedConsentResponse{}, nil +} diff --git a/x/oracle/keeper/params.go b/x/oracle/keeper/params.go new file mode 100755 index 0000000000..dd5939ed36 --- /dev/null +++ b/x/oracle/keeper/params.go @@ -0,0 +1,67 @@ +package keeper + +import ( + "github.com/sei-protocol/sei-chain/x/oracle/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// VotePeriod returns the number of blocks during which voting takes place. +func (k Keeper) VotePeriod(ctx sdk.Context) (res uint64) { + k.paramSpace.Get(ctx, types.KeyVotePeriod, &res) + return +} + +// VoteThreshold returns the minimum percentage of votes that must be received for a ballot to pass. +func (k Keeper) VoteThreshold(ctx sdk.Context) (res sdk.Dec) { + k.paramSpace.Get(ctx, types.KeyVoteThreshold, &res) + return +} + +// RewardBand returns the ratio of allowable exchange rate error that a validator can be rewared +func (k Keeper) RewardBand(ctx sdk.Context) (res sdk.Dec) { + k.paramSpace.Get(ctx, types.KeyRewardBand, &res) + return +} + +// Whitelist returns the denom list that can be activated +func (k Keeper) Whitelist(ctx sdk.Context) (res types.DenomList) { + k.paramSpace.Get(ctx, types.KeyWhitelist, &res) + return +} + +// SetWhitelist store new whitelist to param store +// this function is only for test purpose +func (k Keeper) SetWhitelist(ctx sdk.Context, whitelist types.DenomList) { + k.paramSpace.Set(ctx, types.KeyWhitelist, whitelist) + return +} + +// SlashFraction returns oracle voting penalty rate +func (k Keeper) SlashFraction(ctx sdk.Context) (res sdk.Dec) { + k.paramSpace.Get(ctx, types.KeySlashFraction, &res) + return +} + +// SlashWindow returns # of vote period for oracle slashing +func (k Keeper) SlashWindow(ctx sdk.Context) (res uint64) { + k.paramSpace.Get(ctx, types.KeySlashWindow, &res) + return +} + +// MinValidPerWindow returns oracle slashing threshold +func (k Keeper) MinValidPerWindow(ctx sdk.Context) (res sdk.Dec) { + k.paramSpace.Get(ctx, types.KeyMinValidPerWindow, &res) + return +} + +// GetParams returns the total set of oracle parameters. +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramSpace.GetParamSet(ctx, ¶ms) + return params +} + +// SetParams sets the total set of oracle parameters. +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSpace.SetParamSet(ctx, ¶ms) +} diff --git a/x/oracle/keeper/querier.go b/x/oracle/keeper/querier.go new file mode 100755 index 0000000000..53ca8f7f3a --- /dev/null +++ b/x/oracle/keeper/querier.go @@ -0,0 +1,193 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// querier is used as Keeper will have duplicate methods if used directly, and gRPC names take precedence over q +type querier struct { + Keeper +} + +// NewQuerier returns an implementation of the oracle QueryServer interface +// for the provided Keeper. +func NewQuerier(keeper Keeper) types.QueryServer { + return &querier{Keeper: keeper} +} + +var _ types.QueryServer = querier{} + +// Params queries params of distribution module +func (q querier) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + var params types.Params + q.paramSpace.GetParamSet(ctx, ¶ms) + + return &types.QueryParamsResponse{Params: params}, nil +} + +// ExchangeRate queries exchange rate of a denom +func (q querier) ExchangeRate(c context.Context, req *types.QueryExchangeRateRequest) (*types.QueryExchangeRateResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + if len(req.Denom) == 0 { + return nil, status.Error(codes.InvalidArgument, "empty denom") + } + + ctx := sdk.UnwrapSDKContext(c) + exchangeRate, err := q.GetBaseExchangeRate(ctx, req.Denom) + if err != nil { + return nil, err + } + + return &types.QueryExchangeRateResponse{ExchangeRate: exchangeRate}, nil +} + +// ExchangeRates queries exchange rates of all denoms +func (q querier) ExchangeRates(c context.Context, req *types.QueryExchangeRatesRequest) (*types.QueryExchangeRatesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var exchangeRates sdk.DecCoins + q.IterateBaseExchangeRates(ctx, func(denom string, rate sdk.Dec) (stop bool) { + exchangeRates = append(exchangeRates, sdk.NewDecCoinFromDec(denom, rate)) + return false + }) + + return &types.QueryExchangeRatesResponse{ExchangeRates: exchangeRates}, nil +} + +// Actives queries all denoms for which exchange rates exist +func (q querier) Actives(c context.Context, req *types.QueryActivesRequest) (*types.QueryActivesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + denoms := []string{} + q.IterateBaseExchangeRates(ctx, func(denom string, rate sdk.Dec) (stop bool) { + denoms = append(denoms, denom) + return false + }) + + return &types.QueryActivesResponse{Actives: denoms}, nil +} + +// VoteTargets queries the voting target list on current vote period +func (q querier) VoteTargets(c context.Context, req *types.QueryVoteTargetsRequest) (*types.QueryVoteTargetsResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + return &types.QueryVoteTargetsResponse{VoteTargets: q.GetVoteTargets(ctx)}, nil +} + +// FeederDelegation queries the account address that the validator operator delegated oracle vote rights to +func (q querier) FeederDelegation(c context.Context, req *types.QueryFeederDelegationRequest) (*types.QueryFeederDelegationResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + valAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddr) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + return &types.QueryFeederDelegationResponse{ + FeederAddr: q.GetFeederDelegation(ctx, valAddr).String(), + }, nil +} + +// MissCounter queries oracle miss counter of a validator +func (q querier) MissCounter(c context.Context, req *types.QueryMissCounterRequest) (*types.QueryMissCounterResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + valAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddr) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + return &types.QueryMissCounterResponse{ + MissCounter: q.GetMissCounter(ctx, valAddr), + }, nil +} + +// AggregatePrevote queries an aggregate prevote of a validator +func (q querier) AggregatePrevote(c context.Context, req *types.QueryAggregatePrevoteRequest) (*types.QueryAggregatePrevoteResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + valAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddr) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + prevote, err := q.GetAggregateExchangeRatePrevote(ctx, valAddr) + if err != nil { + return nil, err + } + + return &types.QueryAggregatePrevoteResponse{ + AggregatePrevote: prevote, + }, nil +} + +// AggregatePrevotes queries aggregate prevotes of all validators +func (q querier) AggregatePrevotes(c context.Context, req *types.QueryAggregatePrevotesRequest) (*types.QueryAggregatePrevotesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var prevotes []types.AggregateExchangeRatePrevote + q.IterateAggregateExchangeRatePrevotes(ctx, func(_ sdk.ValAddress, prevote types.AggregateExchangeRatePrevote) bool { + prevotes = append(prevotes, prevote) + return false + }) + + return &types.QueryAggregatePrevotesResponse{ + AggregatePrevotes: prevotes, + }, nil +} + +// AggregateVote queries an aggregate vote of a validator +func (q querier) AggregateVote(c context.Context, req *types.QueryAggregateVoteRequest) (*types.QueryAggregateVoteResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + valAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddr) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + vote, err := q.GetAggregateExchangeRateVote(ctx, valAddr) + if err != nil { + return nil, err + } + + return &types.QueryAggregateVoteResponse{ + AggregateVote: vote, + }, nil +} + +// AggregateVotes queries aggregate votes of all validators +func (q querier) AggregateVotes(c context.Context, req *types.QueryAggregateVotesRequest) (*types.QueryAggregateVotesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var votes []types.AggregateExchangeRateVote + q.IterateAggregateExchangeRateVotes(ctx, func(_ sdk.ValAddress, vote types.AggregateExchangeRateVote) bool { + votes = append(votes, vote) + return false + }) + + return &types.QueryAggregateVotesResponse{ + AggregateVotes: votes, + }, nil +} diff --git a/x/oracle/keeper/querier_test.go b/x/oracle/keeper/querier_test.go new file mode 100755 index 0000000000..36524d2e12 --- /dev/null +++ b/x/oracle/keeper/querier_test.go @@ -0,0 +1,189 @@ +package keeper + +import ( + "bytes" + "sort" + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +func TestQueryParams(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + + querier := NewQuerier(input.OracleKeeper) + res, err := querier.Params(ctx, &types.QueryParamsRequest{}) + require.NoError(t, err) + + require.Equal(t, input.OracleKeeper.GetParams(input.Ctx), res.Params) +} + +func TestQueryExchangeRate(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + rate := sdk.NewDec(1700) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom, rate) + + // Query to grpc + res, err := querier.ExchangeRate(ctx, &types.QueryExchangeRateRequest{ + Denom: utils.MicroAtomDenom, + }) + require.NoError(t, err) + require.Equal(t, rate, res.ExchangeRate) +} + +func TestQueryExchangeRates(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + rate := sdk.NewDec(1700) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroAtomDenom, rate) + input.OracleKeeper.SetBaseExchangeRate(input.Ctx, utils.MicroSeiDenom, rate) + + res, err := querier.ExchangeRates(ctx, &types.QueryExchangeRatesRequest{}) + require.NoError(t, err) + + require.Equal(t, sdk.DecCoins{ + sdk.NewDecCoinFromDec(utils.MicroAtomDenom, rate), + sdk.NewDecCoinFromDec(utils.MicroSeiDenom, rate), + }, res.ExchangeRates) +} + +func TestQueryFeederDelegation(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + input.OracleKeeper.SetFeederDelegation(input.Ctx, ValAddrs[0], Addrs[1]) + + res, err := querier.FeederDelegation(ctx, &types.QueryFeederDelegationRequest{ + ValidatorAddr: ValAddrs[0].String(), + }) + require.NoError(t, err) + + require.Equal(t, Addrs[1].String(), res.FeederAddr) +} + +func TestQueryAggregatePrevote(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + prevote1 := types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{}, ValAddrs[0], 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, ValAddrs[0], prevote1) + prevote2 := types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{}, ValAddrs[1], 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, ValAddrs[1], prevote2) + + // validator 0 address params + res, err := querier.AggregatePrevote(ctx, &types.QueryAggregatePrevoteRequest{ + ValidatorAddr: ValAddrs[0].String(), + }) + require.NoError(t, err) + require.Equal(t, prevote1, res.AggregatePrevote) + + // validator 1 address params + res, err = querier.AggregatePrevote(ctx, &types.QueryAggregatePrevoteRequest{ + ValidatorAddr: ValAddrs[1].String(), + }) + require.NoError(t, err) + require.Equal(t, prevote2, res.AggregatePrevote) +} + +func TestQueryAggregatePrevotes(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + prevote1 := types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{}, ValAddrs[0], 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, ValAddrs[0], prevote1) + prevote2 := types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{}, ValAddrs[1], 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, ValAddrs[1], prevote2) + prevote3 := types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{}, ValAddrs[2], 0) + input.OracleKeeper.SetAggregateExchangeRatePrevote(input.Ctx, ValAddrs[2], prevote3) + + expectedPrevotes := []types.AggregateExchangeRatePrevote{prevote1, prevote2, prevote3} + sort.SliceStable(expectedPrevotes, func(i, j int) bool { + addr1, _ := sdk.ValAddressFromBech32(expectedPrevotes[i].Voter) + addr2, _ := sdk.ValAddressFromBech32(expectedPrevotes[j].Voter) + return bytes.Compare(addr1, addr2) == -1 + }) + + res, err := querier.AggregatePrevotes(ctx, &types.QueryAggregatePrevotesRequest{}) + require.NoError(t, err) + require.Equal(t, expectedPrevotes, res.AggregatePrevotes) +} + +func TestQueryAggregateVote(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + vote1 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[0]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[0], vote1) + vote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[1]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[1], vote2) + + // validator 0 address params + res, err := querier.AggregateVote(ctx, &types.QueryAggregateVoteRequest{ + ValidatorAddr: ValAddrs[0].String(), + }) + require.NoError(t, err) + require.Equal(t, vote1, res.AggregateVote) + + // validator 1 address params + res, err = querier.AggregateVote(ctx, &types.QueryAggregateVoteRequest{ + ValidatorAddr: ValAddrs[1].String(), + }) + require.NoError(t, err) + require.Equal(t, vote2, res.AggregateVote) +} + +func TestQueryAggregateVotes(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + vote1 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[0]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[0], vote1) + vote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[1]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[1], vote2) + vote3 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[2]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[2], vote3) + + expectedVotes := []types.AggregateExchangeRateVote{vote1, vote2, vote3} + sort.SliceStable(expectedVotes, func(i, j int) bool { + addr1, _ := sdk.ValAddressFromBech32(expectedVotes[i].Voter) + addr2, _ := sdk.ValAddressFromBech32(expectedVotes[j].Voter) + return bytes.Compare(addr1, addr2) == -1 + }) + + res, err := querier.AggregateVotes(ctx, &types.QueryAggregateVotesRequest{}) + require.NoError(t, err) + require.Equal(t, expectedVotes, res.AggregateVotes) +} + +func TestQueryVoteTargets(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + + voteTargets := []string{"denom", "denom2", "denom3"} + for _, target := range voteTargets { + input.OracleKeeper.SetVoteTarget(input.Ctx, target) + } + + res, err := querier.VoteTargets(ctx, &types.QueryVoteTargetsRequest{}) + require.NoError(t, err) + require.Equal(t, voteTargets, res.VoteTargets) +} diff --git a/x/oracle/keeper/slash.go b/x/oracle/keeper/slash.go new file mode 100755 index 0000000000..7ff89712c3 --- /dev/null +++ b/x/oracle/keeper/slash.go @@ -0,0 +1,49 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SlashAndResetMissCounters do slash any operator who over criteria & clear all operators miss counter to zero +func (k Keeper) SlashAndResetMissCounters(ctx sdk.Context) { + height := ctx.BlockHeight() + distributionHeight := height - sdk.ValidatorUpdateDelay - 1 + + // slash_window / vote_period + votePeriodsPerWindow := uint64( + sdk.NewDec(int64(k.SlashWindow(ctx))). + QuoInt64(int64(k.VotePeriod(ctx))). + TruncateInt64(), + ) + minValidPerWindow := k.MinValidPerWindow(ctx) + slashFraction := k.SlashFraction(ctx) + powerReduction := k.StakingKeeper.PowerReduction(ctx) + + k.IterateMissCounters(ctx, func(operator sdk.ValAddress, missCounter uint64) bool { + + // Calculate valid vote rate; (SlashWindow - MissCounter)/SlashWindow + validVoteRate := sdk.NewDecFromInt( + sdk.NewInt(int64(votePeriodsPerWindow - missCounter))). + QuoInt64(int64(votePeriodsPerWindow)) + + // Penalize the validator whose the valid vote rate is smaller than min threshold + if validVoteRate.LT(minValidPerWindow) { + validator := k.StakingKeeper.Validator(ctx, operator) + if validator.IsBonded() && !validator.IsJailed() { + consAddr, err := validator.GetConsAddr() + if err != nil { + panic(err) + } + + k.StakingKeeper.Slash( + ctx, consAddr, + distributionHeight, validator.GetConsensusPower(powerReduction), slashFraction, + ) + k.StakingKeeper.Jail(ctx, consAddr) + } + } + + k.DeleteMissCounter(ctx, operator) + return false + }) +} diff --git a/x/oracle/keeper/slash_test.go b/x/oracle/keeper/slash_test.go new file mode 100755 index 0000000000..6bc8f640d5 --- /dev/null +++ b/x/oracle/keeper/slash_test.go @@ -0,0 +1,82 @@ +package keeper + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func TestSlashAndResetMissCounters(t *testing.T) { + // initial setup + input := CreateTestInput(t) + addr, val := ValAddrs[0], ValPubKeys[0] + addr1, val1 := ValAddrs[1], ValPubKeys[1] + amt := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) + sh := staking.NewHandler(input.StakingKeeper) + ctx := input.Ctx + + // Validator created + _, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + require.NoError(t, err) + _, err = sh(ctx, NewTestMsgCreateValidator(addr1, val1, amt)) + require.NoError(t, err) + staking.EndBlocker(ctx, input.StakingKeeper) + + require.Equal( + t, input.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(input.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), + ) + require.Equal(t, amt, input.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) + require.Equal( + t, input.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr1)), + sdk.NewCoins(sdk.NewCoin(input.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), + ) + require.Equal(t, amt, input.StakingKeeper.Validator(ctx, addr1).GetBondedTokens()) + + votePeriodsPerWindow := sdk.NewDec(int64(input.OracleKeeper.SlashWindow(input.Ctx))).QuoInt64(int64(input.OracleKeeper.VotePeriod(input.Ctx))).TruncateInt64() + slashFraction := input.OracleKeeper.SlashFraction(input.Ctx) + minValidVotes := input.OracleKeeper.MinValidPerWindow(input.Ctx).MulInt64(votePeriodsPerWindow).TruncateInt64() + // Case 1, no slash + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], uint64(votePeriodsPerWindow-minValidVotes)) + input.OracleKeeper.SlashAndResetMissCounters(input.Ctx) + staking.EndBlocker(input.Ctx, input.StakingKeeper) + + validator, _ := input.StakingKeeper.GetValidator(input.Ctx, ValAddrs[0]) + require.Equal(t, amt, validator.GetBondedTokens()) + + // Case 2, slash + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], uint64(votePeriodsPerWindow-minValidVotes+1)) + input.OracleKeeper.SlashAndResetMissCounters(input.Ctx) + validator, _ = input.StakingKeeper.GetValidator(input.Ctx, ValAddrs[0]) + require.Equal(t, amt.Sub(slashFraction.MulInt(amt).TruncateInt()), validator.GetBondedTokens()) + require.True(t, validator.IsJailed()) + + // Case 3, slash unbonded validator + validator, _ = input.StakingKeeper.GetValidator(input.Ctx, ValAddrs[0]) + validator.Status = stakingtypes.Unbonded + validator.Jailed = false + validator.Tokens = amt + input.StakingKeeper.SetValidator(input.Ctx, validator) + + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], uint64(votePeriodsPerWindow-minValidVotes+1)) + input.OracleKeeper.SlashAndResetMissCounters(input.Ctx) + validator, _ = input.StakingKeeper.GetValidator(input.Ctx, ValAddrs[0]) + require.Equal(t, amt, validator.Tokens) + require.False(t, validator.IsJailed()) + + // Case 4, slash jailed validator + validator, _ = input.StakingKeeper.GetValidator(input.Ctx, ValAddrs[0]) + validator.Status = stakingtypes.Bonded + validator.Jailed = true + validator.Tokens = amt + input.StakingKeeper.SetValidator(input.Ctx, validator) + + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], uint64(votePeriodsPerWindow-minValidVotes+1)) + input.OracleKeeper.SlashAndResetMissCounters(input.Ctx) + validator, _ = input.StakingKeeper.GetValidator(input.Ctx, ValAddrs[0]) + require.Equal(t, amt, validator.Tokens) +} diff --git a/x/oracle/keeper/test_utils.go b/x/oracle/keeper/test_utils.go new file mode 100755 index 0000000000..21292accb8 --- /dev/null +++ b/x/oracle/keeper/test_utils.go @@ -0,0 +1,266 @@ +//nolint +package keeper + +import ( + "testing" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" + "github.com/stretchr/testify/require" + + "time" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simapp" + simparams "github.com/cosmos/cosmos-sdk/simapp/params" + "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/distribution" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/params" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +const faucetAccountName = "faucet" + +// ModuleBasics nolint +var ModuleBasics = module.NewBasicManager( + auth.AppModuleBasic{}, + bank.AppModuleBasic{}, + distribution.AppModuleBasic{}, + staking.AppModuleBasic{}, + params.AppModuleBasic{}, +) + +// MakeTestCodec nolint +func MakeTestCodec(t *testing.T) codec.Codec { + return MakeEncodingConfig(t).Marshaler +} + +// MakeEncodingConfig nolint +func MakeEncodingConfig(_ *testing.T) simparams.EncodingConfig { + amino := codec.NewLegacyAmino() + interfaceRegistry := codectypes.NewInterfaceRegistry() + marshaler := codec.NewProtoCodec(interfaceRegistry) + txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes) + + std.RegisterInterfaces(interfaceRegistry) + std.RegisterLegacyAminoCodec(amino) + + ModuleBasics.RegisterLegacyAminoCodec(amino) + ModuleBasics.RegisterInterfaces(interfaceRegistry) + types.RegisterLegacyAminoCodec(amino) + types.RegisterInterfaces(interfaceRegistry) + return simparams.EncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Marshaler: marshaler, + TxConfig: txCfg, + Amino: amino, + } +} + +// Test addresses +var ( + ValPubKeys = simapp.CreateTestPubKeys(5) + + pubKeys = []crypto.PubKey{ + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + } + + Addrs = []sdk.AccAddress{ + sdk.AccAddress(pubKeys[0].Address()), + sdk.AccAddress(pubKeys[1].Address()), + sdk.AccAddress(pubKeys[2].Address()), + sdk.AccAddress(pubKeys[3].Address()), + sdk.AccAddress(pubKeys[4].Address()), + } + + ValAddrs = []sdk.ValAddress{ + sdk.ValAddress(pubKeys[0].Address()), + sdk.ValAddress(pubKeys[1].Address()), + sdk.ValAddress(pubKeys[2].Address()), + sdk.ValAddress(pubKeys[3].Address()), + sdk.ValAddress(pubKeys[4].Address()), + } + + InitTokens = sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) + InitCoins = sdk.NewCoins(sdk.NewCoin(utils.MicroSeiDenom, InitTokens)) + + OracleDecPrecision = 8 +) + +// TestInput nolint +type TestInput struct { + Ctx sdk.Context + Cdc *codec.LegacyAmino + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + OracleKeeper Keeper + StakingKeeper stakingkeeper.Keeper + DistrKeeper distrkeeper.Keeper +} + +// CreateTestInput nolint +func CreateTestInput(t *testing.T) TestInput { + keyAcc := sdk.NewKVStoreKey(authtypes.StoreKey) + keyBank := sdk.NewKVStoreKey(banktypes.StoreKey) + keyParams := sdk.NewKVStoreKey(paramstypes.StoreKey) + tKeyParams := sdk.NewTransientStoreKey(paramstypes.TStoreKey) + keyOracle := sdk.NewKVStoreKey(types.StoreKey) + keyStaking := sdk.NewKVStoreKey(stakingtypes.StoreKey) + keyDistr := sdk.NewKVStoreKey(distrtypes.StoreKey) + + db := dbm.NewMemDB() + ms := store.NewCommitMultiStore(db) + ctx := sdk.NewContext(ms, tmproto.Header{Time: time.Now().UTC()}, false, log.NewNopLogger()) + encodingConfig := MakeEncodingConfig(t) + appCodec, legacyAmino := encodingConfig.Marshaler, encodingConfig.Amino + + ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyBank, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(tKeyParams, sdk.StoreTypeTransient, db) + ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyOracle, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyStaking, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyDistr, sdk.StoreTypeIAVL, db) + + require.NoError(t, ms.LoadLatestVersion()) + + blackListAddrs := map[string]bool{ + authtypes.FeeCollectorName: true, + stakingtypes.NotBondedPoolName: true, + stakingtypes.BondedPoolName: true, + distrtypes.ModuleName: true, + faucetAccountName: true, + } + + maccPerms := map[string][]string{ + faucetAccountName: {authtypes.Minter}, + authtypes.FeeCollectorName: nil, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + distrtypes.ModuleName: nil, + types.ModuleName: nil, + } + + paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, keyParams, tKeyParams) + accountKeeper := authkeeper.NewAccountKeeper(appCodec, keyAcc, paramsKeeper.Subspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms) + bankKeeper := bankkeeper.NewBaseKeeper(appCodec, keyBank, accountKeeper, paramsKeeper.Subspace(banktypes.ModuleName), blackListAddrs) + + totalSupply := sdk.NewCoins(sdk.NewCoin(utils.MicroSeiDenom, InitTokens.MulRaw(int64(len(Addrs)*10)))) + bankKeeper.MintCoins(ctx, faucetAccountName, totalSupply) + + stakingKeeper := stakingkeeper.NewKeeper( + appCodec, + keyStaking, + accountKeeper, + bankKeeper, + paramsKeeper.Subspace(stakingtypes.ModuleName), + ) + + stakingParams := stakingtypes.DefaultParams() + stakingParams.BondDenom = utils.MicroSeiDenom + stakingKeeper.SetParams(ctx, stakingParams) + + distrKeeper := distrkeeper.NewKeeper( + appCodec, + keyDistr, paramsKeeper.Subspace(distrtypes.ModuleName), + accountKeeper, bankKeeper, stakingKeeper, + authtypes.FeeCollectorName, blackListAddrs) + + distrKeeper.SetFeePool(ctx, distrtypes.InitialFeePool()) + distrParams := distrtypes.DefaultParams() + distrParams.CommunityTax = sdk.NewDecWithPrec(2, 2) + distrParams.BaseProposerReward = sdk.NewDecWithPrec(1, 2) + distrParams.BonusProposerReward = sdk.NewDecWithPrec(4, 2) + distrKeeper.SetParams(ctx, distrParams) + stakingKeeper.SetHooks(stakingtypes.NewMultiStakingHooks(distrKeeper.Hooks())) + + feeCollectorAcc := authtypes.NewEmptyModuleAccount(authtypes.FeeCollectorName) + notBondedPool := authtypes.NewEmptyModuleAccount(stakingtypes.NotBondedPoolName, authtypes.Burner, authtypes.Staking) + bondPool := authtypes.NewEmptyModuleAccount(stakingtypes.BondedPoolName, authtypes.Burner, authtypes.Staking) + distrAcc := authtypes.NewEmptyModuleAccount(distrtypes.ModuleName) + oracleAcc := authtypes.NewEmptyModuleAccount(types.ModuleName, authtypes.Minter) + + bankKeeper.SendCoinsFromModuleToModule(ctx, faucetAccountName, stakingtypes.NotBondedPoolName, sdk.NewCoins(sdk.NewCoin(utils.MicroSeiDenom, InitTokens.MulRaw(int64(len(Addrs)))))) + + accountKeeper.SetModuleAccount(ctx, feeCollectorAcc) + accountKeeper.SetModuleAccount(ctx, bondPool) + accountKeeper.SetModuleAccount(ctx, notBondedPool) + accountKeeper.SetModuleAccount(ctx, distrAcc) + accountKeeper.SetModuleAccount(ctx, oracleAcc) + + for _, addr := range Addrs { + accountKeeper.SetAccount(ctx, authtypes.NewBaseAccountWithAddress(addr)) + err := bankKeeper.SendCoinsFromModuleToAccount(ctx, faucetAccountName, addr, InitCoins) + require.NoError(t, err) + } + + keeper := NewKeeper( + appCodec, + keyOracle, + paramsKeeper.Subspace(types.ModuleName), + accountKeeper, + bankKeeper, + distrKeeper, + stakingKeeper, + distrtypes.ModuleName, + ) + + defaults := types.DefaultParams() + keeper.SetParams(ctx, defaults) + + for _, denom := range defaults.Whitelist { + keeper.SetVoteTarget(ctx, denom.Name) + } + + return TestInput{ctx, legacyAmino, accountKeeper, bankKeeper, keeper, stakingKeeper, distrKeeper} +} + +// NewTestMsgCreateValidator test msg creator +func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey cryptotypes.PubKey, amt sdk.Int) *stakingtypes.MsgCreateValidator { + commission := stakingtypes.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) + msg, _ := stakingtypes.NewMsgCreateValidator( + address, pubKey, sdk.NewCoin(utils.MicroSeiDenom, amt), + stakingtypes.Description{}, commission, sdk.OneInt(), + ) + + return msg +} + +// FundAccount is a utility function that funds an account by minting and +// sending the coins to the address. This should be used for testing purposes +// only! +func FundAccount(input TestInput, addr sdk.AccAddress, amounts sdk.Coins) error { + if err := input.BankKeeper.MintCoins(input.Ctx, faucetAccountName, amounts); err != nil { + return err + } + + return input.BankKeeper.SendCoinsFromModuleToAccount(input.Ctx, faucetAccountName, addr, amounts) +} diff --git a/x/oracle/keeper/vote_target.go b/x/oracle/keeper/vote_target.go new file mode 100755 index 0000000000..1b928cd79c --- /dev/null +++ b/x/oracle/keeper/vote_target.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +func (k Keeper) IsVoteTarget(ctx sdk.Context, denom string) bool { + _, err := k.GetVoteTarget(ctx, denom) + return err == nil +} + +func (k Keeper) GetVoteTargets(ctx sdk.Context) (voteTargets []string) { + k.IterateVoteTargets(ctx, func(denom string, denomInfo types.Denom) bool { + voteTargets = append(voteTargets, denom) + return false + }) + + return voteTargets +} diff --git a/x/oracle/keeper/vote_target_test.go b/x/oracle/keeper/vote_target_test.go new file mode 100755 index 0000000000..6fb3ec0e4f --- /dev/null +++ b/x/oracle/keeper/vote_target_test.go @@ -0,0 +1,33 @@ +package keeper + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestKeeper_GetVoteTargets(t *testing.T) { + input := CreateTestInput(t) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + + expectedTargets := []string{"bar", "foo", "whoowhoo"} + for _, target := range expectedTargets { + input.OracleKeeper.SetVoteTarget(input.Ctx, target) + } + + targets := input.OracleKeeper.GetVoteTargets(input.Ctx) + require.Equal(t, expectedTargets, targets) +} + +func TestKeeper_IsVoteTarget(t *testing.T) { + input := CreateTestInput(t) + + input.OracleKeeper.ClearVoteTargets(input.Ctx) + + validTargets := []string{"bar", "foo", "whoowhoo"} + for _, target := range validTargets { + input.OracleKeeper.SetVoteTarget(input.Ctx, target) + require.True(t, input.OracleKeeper.IsVoteTarget(input.Ctx, target)) + } +} diff --git a/x/oracle/module.go b/x/oracle/module.go new file mode 100755 index 0000000000..2fa431728a --- /dev/null +++ b/x/oracle/module.go @@ -0,0 +1,202 @@ +package oracle + +import ( + "context" + "fmt" + + "encoding/json" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/sei-protocol/sei-chain/x/oracle/client/cli" + "github.com/sei-protocol/sei-chain/x/oracle/client/rest" + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/simulation" + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the oracle module. +type AppModuleBasic struct { + cdc codec.Codec +} + +// Name returns the module's name +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the module's types on the given LegacyAmino codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (b AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// DefaultGenesis returns default genesis state as raw bytes for the staking +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the oracle module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return types.ValidateGenesis(&data) +} + +// RegisterRESTRoutes registers the REST routes for the oracle module. +func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { + rest.RegisterRoutes(clientCtx, rtr) +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the oracle module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + _ = types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the root tx command for the oracle module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns no root query command for the oracle module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +//___________________________ + +// AppModule implements an application module for the oracle module. +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule( + cdc codec.Codec, + keeper keeper.Keeper, + accountKeeper types.AccountKeeper, + bankKeeper types.BankKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc}, + keeper: keeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + } +} + +// Name returns the oracle module's name. +func (AppModule) Name() string { return types.ModuleName } + +// RegisterInvariants performs a no-op. +func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// Route returns the message routing key for the oracle module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper)) +} + +// QuerierRoute returns the oracle module's querier route name. +func (AppModule) QuerierRoute() string { return types.QuerierRoute } + +// LegacyQuerierHandler returns the oracle module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return nil +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + querier := keeper.NewQuerier(am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), querier) +} + +// InitGenesis performs genesis initialization for the oracle module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + InitGenesis(ctx, am.keeper, &genesisState) + + return nil +} + +// ExportGenesis returns the exported genesis state as raw bytes for the oracle +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(gs) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// BeginBlock returns the begin blocker for the oracle module. +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock returns the end blocker for the oracle module. +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + EndBlocker(ctx, am.keeper) + return []abci.ValidatorUpdate{} +} + +//____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the distribution module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents returns all the oracle content functions used to +// simulate governance proposals. +func (am AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized oracle param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return simulation.ParamChanges(r) +} + +// RegisterStoreDecoder registers a decoder for oracle module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the oracle module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, + am.accountKeeper, am.bankKeeper, am.keeper, + ) +} diff --git a/x/oracle/simulation/decoder.go b/x/oracle/simulation/decoder.go new file mode 100755 index 0000000000..ef1495299c --- /dev/null +++ b/x/oracle/simulation/decoder.go @@ -0,0 +1,52 @@ +package simulation + +import ( + "bytes" + "fmt" + + gogotypes "github.com/gogo/protobuf/types" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's +// Value to the corresponding oracle type. +func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.Equal(kvA.Key[:1], types.ExchangeRateKey): + var exchangeRateA, exchangeRateB sdk.DecProto + cdc.MustUnmarshal(kvA.Value, &exchangeRateA) + cdc.MustUnmarshal(kvB.Value, &exchangeRateB) + return fmt.Sprintf("%v\n%v", exchangeRateA, exchangeRateB) + case bytes.Equal(kvA.Key[:1], types.FeederDelegationKey): + return fmt.Sprintf("%v\n%v", sdk.AccAddress(kvA.Value), sdk.AccAddress(kvB.Value)) + case bytes.Equal(kvA.Key[:1], types.MissCounterKey): + var counterA, counterB gogotypes.UInt64Value + cdc.MustUnmarshal(kvA.Value, &counterA) + cdc.MustUnmarshal(kvB.Value, &counterB) + return fmt.Sprintf("%v\n%v", counterA.Value, counterB.Value) + case bytes.Equal(kvA.Key[:1], types.AggregateExchangeRatePrevoteKey): + var prevoteA, prevoteB types.AggregateExchangeRatePrevote + cdc.MustUnmarshal(kvA.Value, &prevoteA) + cdc.MustUnmarshal(kvB.Value, &prevoteB) + return fmt.Sprintf("%v\n%v", prevoteA, prevoteB) + case bytes.Equal(kvA.Key[:1], types.AggregateExchangeRateVoteKey): + var voteA, voteB types.AggregateExchangeRateVote + cdc.MustUnmarshal(kvA.Value, &voteA) + cdc.MustUnmarshal(kvB.Value, &voteB) + return fmt.Sprintf("%v\n%v", voteA, voteB) + case bytes.Equal(kvA.Key[:1], types.VoteTargetKey): + var voteTargetA, voteTargetB types.Denom + cdc.MustUnmarshal(kvA.Value, &voteTargetA) + cdc.MustUnmarshal(kvB.Value, &voteTargetB) + return fmt.Sprintf("%v\n%v", voteTargetA, voteTargetB) + default: + panic(fmt.Sprintf("invalid oracle key prefix %X", kvA.Key[:1])) + } + } +} diff --git a/x/oracle/simulation/decoder_test.go b/x/oracle/simulation/decoder_test.go new file mode 100755 index 0000000000..951d9e9155 --- /dev/null +++ b/x/oracle/simulation/decoder_test.go @@ -0,0 +1,77 @@ +package simulation_test + +import ( + "fmt" + "testing" + + gogotypes "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto/ed25519" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + sim "github.com/sei-protocol/sei-chain/x/oracle/simulation" + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +var ( + delPk = ed25519.GenPrivKey().PubKey() + feederAddr = sdk.AccAddress(delPk.Address()) + valAddr = sdk.ValAddress(delPk.Address()) +) + +func TestDecodeDistributionStore(t *testing.T) { + cdc := keeper.MakeTestCodec(t) + dec := sim.NewDecodeStore(cdc) + + exchangeRate := sdk.NewDecWithPrec(1234, 1) + missCounter := uint64(23) + + aggregatePrevote := types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash([]byte("12345")), valAddr, 123) + aggregateVote := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Denom: utils.MicroAtomDenom, ExchangeRate: sdk.NewDecWithPrec(1234, 1)}, + }, valAddr) + + denom := "usei" + + kvPairs := kv.Pairs{ + Pairs: []kv.Pair{ + {Key: types.ExchangeRateKey, Value: cdc.MustMarshal(&sdk.DecProto{Dec: exchangeRate})}, + {Key: types.FeederDelegationKey, Value: feederAddr.Bytes()}, + {Key: types.MissCounterKey, Value: cdc.MustMarshal(&gogotypes.UInt64Value{Value: missCounter})}, + {Key: types.AggregateExchangeRatePrevoteKey, Value: cdc.MustMarshal(&aggregatePrevote)}, + {Key: types.AggregateExchangeRateVoteKey, Value: cdc.MustMarshal(&aggregateVote)}, + {Key: types.VoteTargetKey, Value: cdc.MustMarshal(&types.Denom{Name: denom})}, + {Key: []byte{0x99}, Value: []byte{0x99}}, + }, + } + + tests := []struct { + name string + expectedLog string + }{ + {"ExchangeRate", fmt.Sprintf("%v\n%v", exchangeRate, exchangeRate)}, + {"FeederDelegation", fmt.Sprintf("%v\n%v", feederAddr, feederAddr)}, + {"MissCounter", fmt.Sprintf("%v\n%v", missCounter, missCounter)}, + {"AggregatePrevote", fmt.Sprintf("%v\n%v", aggregatePrevote, aggregatePrevote)}, + {"AggregateVote", fmt.Sprintf("%v\n%v", aggregateVote, aggregateVote)}, + {"VoteTarget", fmt.Sprintf("name: %v\n\nname: %v\n", denom, denom)}, + {"other", ""}, + } + + for i, tt := range tests { + i, tt := i, tt + t.Run(tt.name, func(t *testing.T) { + switch i { + case len(tests) - 1: + require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) + default: + require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + } + }) + } +} diff --git a/x/oracle/simulation/genesis.go b/x/oracle/simulation/genesis.go new file mode 100755 index 0000000000..23a3d55791 --- /dev/null +++ b/x/oracle/simulation/genesis.go @@ -0,0 +1,123 @@ +package simulation + +//DONTCOVER + +import ( + "encoding/json" + "fmt" + "math/rand" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +// Simulation parameter constants +const ( + votePeriodKey = "vote_period" + voteThresholdKey = "vote_threshold" + rewardBandKey = "reward_band" + rewardDistributionWindowKey = "reward_distribution_window" + slashFractionKey = "slash_fraction" + slashWindowKey = "slash_window" + minValidPerWindowKey = "min_valid_per_window" +) + +// GenVotePeriod randomized VotePeriod +func GenVotePeriod(r *rand.Rand) uint64 { + return uint64(1 + r.Intn(100)) +} + +// GenVoteThreshold randomized VoteThreshold +func GenVoteThreshold(r *rand.Rand) sdk.Dec { + return sdk.NewDecWithPrec(333, 3).Add(sdk.NewDecWithPrec(int64(r.Intn(333)), 3)) +} + +// GenRewardBand randomized RewardBand +func GenRewardBand(r *rand.Rand) sdk.Dec { + return sdk.ZeroDec().Add(sdk.NewDecWithPrec(int64(r.Intn(100)), 3)) +} + +// GenSlashFraction randomized SlashFraction +func GenSlashFraction(r *rand.Rand) sdk.Dec { + return sdk.ZeroDec().Add(sdk.NewDecWithPrec(int64(r.Intn(100)), 3)) +} + +// GenSlashWindow randomized SlashWindow +func GenSlashWindow(r *rand.Rand) uint64 { + return uint64(100 + r.Intn(100000)) +} + +// GenMinValidPerWindow randomized MinValidPerWindow +func GenMinValidPerWindow(r *rand.Rand) sdk.Dec { + return sdk.ZeroDec().Add(sdk.NewDecWithPrec(int64(r.Intn(500)), 3)) +} + +// RandomizedGenState generates a random GenesisState for oracle +func RandomizedGenState(simState *module.SimulationState) { + + var votePeriod uint64 + simState.AppParams.GetOrGenerate( + simState.Cdc, votePeriodKey, &votePeriod, simState.Rand, + func(r *rand.Rand) { votePeriod = GenVotePeriod(r) }, + ) + + var voteThreshold sdk.Dec + simState.AppParams.GetOrGenerate( + simState.Cdc, voteThresholdKey, &voteThreshold, simState.Rand, + func(r *rand.Rand) { voteThreshold = GenVoteThreshold(r) }, + ) + + var rewardBand sdk.Dec + simState.AppParams.GetOrGenerate( + simState.Cdc, rewardBandKey, &rewardBand, simState.Rand, + func(r *rand.Rand) { rewardBand = GenRewardBand(r) }, + ) + + var slashFraction sdk.Dec + simState.AppParams.GetOrGenerate( + simState.Cdc, slashFractionKey, &slashFraction, simState.Rand, + func(r *rand.Rand) { slashFraction = GenSlashFraction(r) }, + ) + + var slashWindow uint64 + simState.AppParams.GetOrGenerate( + simState.Cdc, slashWindowKey, &slashWindow, simState.Rand, + func(r *rand.Rand) { slashWindow = GenSlashWindow(r) }, + ) + + var minValidPerWindow sdk.Dec + simState.AppParams.GetOrGenerate( + simState.Cdc, minValidPerWindowKey, &minValidPerWindow, simState.Rand, + func(r *rand.Rand) { minValidPerWindow = GenMinValidPerWindow(r) }, + ) + + oracleGenesis := types.NewGenesisState( + types.Params{ + VotePeriod: votePeriod, + VoteThreshold: voteThreshold, + RewardBand: rewardBand, + Whitelist: types.DenomList{ + {Name: utils.MicroSeiDenom}, + {Name: utils.MicroAtomDenom}, + }, + SlashFraction: slashFraction, + SlashWindow: slashWindow, + MinValidPerWindow: minValidPerWindow, + }, + []types.ExchangeRateTuple{}, + []types.FeederDelegation{}, + []types.MissCounter{}, + []types.AggregateExchangeRatePrevote{}, + []types.AggregateExchangeRateVote{}, + ) + + bz, err := json.MarshalIndent(&oracleGenesis.Params, "", " ") + if err != nil { + panic(err) + } + fmt.Printf("Selected randomly generated oracle parameters:\n%s\n", bz) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(oracleGenesis) +} diff --git a/x/oracle/simulation/operations.go b/x/oracle/simulation/operations.go new file mode 100755 index 0000000000..3eec38e6e1 --- /dev/null +++ b/x/oracle/simulation/operations.go @@ -0,0 +1,272 @@ +package simulation + +//DONTCOVER + +import ( + "math/rand" + "strings" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +// Simulation operation weights constants +const ( + OpWeightMsgAggregateExchangeRatePrevote = "op_weight_msg_exchange_rate_aggregate_prevote" + OpWeightMsgAggregateExchangeRateVote = "op_weight_msg_exchange_rate_aggregate_vote" + OpWeightMsgDelegateFeedConsent = "op_weight_msg_exchange_feed_consent" + + salt = "1234" +) + +var ( + whitelist = []string{utils.MicroAtomDenom} + voteHashMap map[string]string = make(map[string]string) +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, + cdc codec.JSONCodec, + ak types.AccountKeeper, + bk types.BankKeeper, + k keeper.Keeper) simulation.WeightedOperations { + var ( + weightMsgAggregateExchangeRatePrevote int + weightMsgAggregateExchangeRateVote int + weightMsgDelegateFeedConsent int + ) + appParams.GetOrGenerate(cdc, OpWeightMsgAggregateExchangeRatePrevote, &weightMsgAggregateExchangeRatePrevote, nil, + func(_ *rand.Rand) { + weightMsgAggregateExchangeRatePrevote = simappparams.DefaultWeightMsgSend * 2 + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgAggregateExchangeRateVote, &weightMsgAggregateExchangeRateVote, nil, + func(_ *rand.Rand) { + weightMsgAggregateExchangeRateVote = simappparams.DefaultWeightMsgSend * 2 + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgDelegateFeedConsent, &weightMsgDelegateFeedConsent, nil, + func(_ *rand.Rand) { + weightMsgDelegateFeedConsent = simappparams.DefaultWeightMsgSetWithdrawAddress + }, + ) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgAggregateExchangeRatePrevote, + SimulateMsgAggregateExchangeRatePrevote(ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgAggregateExchangeRateVote, + SimulateMsgAggregateExchangeRateVote(ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgDelegateFeedConsent, + SimulateMsgDelegateFeedConsent(ak, bk, k), + ), + } +} + +// SimulateMsgAggregateExchangeRatePrevote generates a MsgAggregateExchangeRatePrevote with random values. +// nolint: funlen +func SimulateMsgAggregateExchangeRatePrevote(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + address := sdk.ValAddress(simAccount.Address) + + // ensure the validator exists + val := k.StakingKeeper.Validator(ctx, address) + if val == nil || !val.IsBonded() { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRatePrevote, "unable to find validator"), nil, nil + } + + exchangeRatesStr := "" + for _, denom := range whitelist { + price := sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 10000)), int64(1)) + exchangeRatesStr += price.String() + denom + "," + } + + exchangeRatesStr = strings.TrimRight(exchangeRatesStr, ",") + voteHash := types.GetAggregateVoteHash(salt, exchangeRatesStr, address) + + feederAddr := k.GetFeederDelegation(ctx, address) + feederSimAccount, _ := simtypes.FindAccount(accs, feederAddr) + + feederAccount := ak.GetAccount(ctx, feederAddr) + spendable := bk.SpendableCoins(ctx, feederAccount.GetAddress()) + + fees, err := simtypes.RandomFees(r, ctx, spendable) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRatePrevote, "unable to generate fees"), nil, err + } + + msg := types.NewMsgAggregateExchangeRatePrevote(voteHash, feederAddr, address) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{feederAccount.GetAccountNumber()}, + []uint64{feederAccount.GetSequence()}, + feederSimAccount.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + voteHashMap[address.String()] = exchangeRatesStr + + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil + } +} + +// SimulateMsgAggregateExchangeRateVote generates a MsgAggregateExchangeRateVote with random values. +// nolint: funlen +func SimulateMsgAggregateExchangeRateVote(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + address := sdk.ValAddress(simAccount.Address) + + // ensure the validator exists + val := k.StakingKeeper.Validator(ctx, address) + if val == nil || !val.IsBonded() { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRateVote, "unable to find validator"), nil, nil + } + + // ensure vote hash exists + exchangeRatesStr, ok := voteHashMap[address.String()] + if !ok { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRateVote, "vote hash not exists"), nil, nil + } + + // get prevote + prevote, err := k.GetAggregateExchangeRatePrevote(ctx, address) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRateVote, "prevote not found"), nil, nil + } + + params := k.GetParams(ctx) + if (uint64(ctx.BlockHeight())/params.VotePeriod)-(prevote.SubmitBlock/params.VotePeriod) != 1 { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRateVote, "reveal period of submitted vote do not match with registered prevote"), nil, nil + } + + feederAddr := k.GetFeederDelegation(ctx, address) + feederSimAccount, _ := simtypes.FindAccount(accs, feederAddr) + feederAccount := ak.GetAccount(ctx, feederAddr) + spendableCoins := bk.SpendableCoins(ctx, feederAddr) + + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRateVote, "unable to generate fees"), nil, err + } + + msg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, feederAddr, address) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{feederAccount.GetAccountNumber()}, + []uint64{feederAccount.GetSequence()}, + feederSimAccount.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil + } +} + +// SimulateMsgDelegateFeedConsent generates a MsgDelegateFeedConsent with random values. +// nolint: funlen +func SimulateMsgDelegateFeedConsent(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + delegateAccount, _ := simtypes.RandomAcc(r, accs) + valAddress := sdk.ValAddress(simAccount.Address) + delegateValAddress := sdk.ValAddress(delegateAccount.Address) + account := ak.GetAccount(ctx, simAccount.Address) + + // ensure the validator exists + val := k.StakingKeeper.Validator(ctx, valAddress) + if val == nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDelegateFeedConsent, "unable to find validator"), nil, nil + } + + // ensure the target address is not a validator + val2 := k.StakingKeeper.Validator(ctx, delegateValAddress) + if val2 != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDelegateFeedConsent, "unable to delegate to validator"), nil, nil + } + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgAggregateExchangeRateVote, "unable to generate fees"), nil, err + } + + msg := types.NewMsgDelegateFeedConsent(valAddress, delegateAccount.Address) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + simAccount.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil + } +} diff --git a/x/oracle/simulation/params.go b/x/oracle/simulation/params.go new file mode 100755 index 0000000000..ca4acf73b8 --- /dev/null +++ b/x/oracle/simulation/params.go @@ -0,0 +1,45 @@ +package simulation + +//DONTCOVER + +import ( + "fmt" + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// ParamChanges defines the parameters that can be modified by param change proposals +// on the simulation +func ParamChanges(r *rand.Rand) []simtypes.ParamChange { + return []simtypes.ParamChange{ + simulation.NewSimParamChange(types.ModuleName, string(types.KeyVotePeriod), + func(r *rand.Rand) string { + return fmt.Sprintf("\"%d\"", GenVotePeriod(r)) + }, + ), + simulation.NewSimParamChange(types.ModuleName, string(types.KeyVoteThreshold), + func(r *rand.Rand) string { + return fmt.Sprintf("\"%s\"", GenVoteThreshold(r)) + }, + ), + simulation.NewSimParamChange(types.ModuleName, string(types.KeyRewardBand), + func(r *rand.Rand) string { + return fmt.Sprintf("\"%s\"", GenRewardBand(r)) + }, + ), + simulation.NewSimParamChange(types.ModuleName, string(types.KeySlashFraction), + func(r *rand.Rand) string { + return fmt.Sprintf("\"%s\"", GenSlashFraction(r)) + }, + ), + simulation.NewSimParamChange(types.ModuleName, string(types.KeySlashWindow), + func(r *rand.Rand) string { + return fmt.Sprintf("\"%d\"", GenSlashWindow(r)) + }, + ), + } +} diff --git a/x/oracle/spec/01_concepts.md b/x/oracle/spec/01_concepts.md new file mode 100755 index 0000000000..fe87e768a0 --- /dev/null +++ b/x/oracle/spec/01_concepts.md @@ -0,0 +1,60 @@ + + +# Concepts + +## Voting Procedure + +During each `VotePeriod`, the Oracle module obtains consensus on the exchange rate of Luna against denominations specified in `Whitelist` by requiring all members of the validator set to submit a vote for Luna exchange rate before the end of the interval. + +Validators must first pre-commit to a exchange rate, then in the subsequent `VotePeriod` submit and reveal their exchange rate alongside a proof that they had pre-commited at that price. This scheme forces the voter to commit to a submission before knowing the votes of others and thereby reduces centralization and free-rider risk in the Oracle. + +* Prevote and Vote + + Let `P_t` be the current time interval of duration defined by `VotePeriod` (currently set to 30 seconds) during which validators must submit two messages: + + * A `MsgAggregateExchangeRatePrevote`, containing the SHA256 hash of the exchange rates of Luna with respect to a Terra peg. A prevote must be submitted for all different denomination on which to report a Luna exchange rates. + * A `MsgAggregateExchangeRateVote`, containing the salt used to create the hash for the aggreagte prevote submitted in the previous interval `P_t-1`. + +* Vote Tally + + At the end of `P_t`, the submitted votes are tallied. + + The submitted salt of each vote is used to verify consistency with the prevote submitted by the validator in `P_t-1`. If the validator has not submitted a prevote, or the SHA256 resulting from the salt does not match the hash from the prevote, the vote is dropped. + + For each denomination, if the total voting power of submitted votes exceeds 50%, the weighted median of the votes is recorded on-chain as the effective exchange rate for Luna against that denomination for the following `VotePeriod` `P_t+1`. + + Denominations receiving fewer than `VoteThreshold` total voting power have their exchange rates deleted from the store, and no swaps can be made with it during the next VotePeriod `P_t+1`. + +* Ballot Rewards + + After the votes are tallied, the winners of the ballots are determined with `tally()`. + + Voters that have managed to vote within a narrow band around the weighted median, are rewarded with a portion of the collected seigniorage. See `k.RewardBallotWinners()` for more details. + + > Starting from Columbus-3, fees from [Market](../../market/spec/README.md) swaps are no longer are included in the oracle reward pool, and are immediately burned during the swap operation. + +## Reward Band + +Let `M` be the weighted median, `𝜎` be the standard deviation of the votes in the ballot, and be the RewardBand parameter. The band around the median is set to be `𝜀 = max(𝜎, R/2)`. All valid (i.e. bonded and non-jailed) validators that submitted an exchange rate vote in the interval `[M - 𝜀, M + 𝜀]` should be included in the set of winners, weighted by their relative vote power. + +## Slashing + +> Be sure to read this section carefully as it concerns potential loss of funds. + +A `VotePeriod` during which either of the following events occur is considered a "miss": + +* The validator fails to submits a vote for Luna exchange rate against **each and every** denomination specified in `Whitelist`. + +* The validator fails to vote within the `reward band` around the weighted median for one or more denominations. + +During every `SlashWindow`, participating validators must maintain a valid vote rate of at least `MinValidPerWindow` (5%), lest they get their stake slashed (currently set to 0.01%). The slashed validator is automatically temporarily "jailed" by the protocol (to protect the funds of delegators), and the operator is expected to fix the discrepancy promptly to resume validator participation. + +## Abstaining from Voting + +A validator may abstain from voting by submitting a non-positive integer for the `ExchangeRate` field in `MsgExchangeRateVote`. Doing so will absolve them of any penalties for missing `VotePeriod`s, but also disqualify them from receiving Oracle seigniorage rewards for faithful reporting. + +## Messages + +> The control flow for vote-tallying, Luna exchange rate updates, ballot rewards and slashing happens at the end of every `VotePeriod`, and is found at the [end-block ABCI](./03_end_block.md) function rather than inside message handlers. diff --git a/x/oracle/spec/02_state.md b/x/oracle/spec/02_state.md new file mode 100755 index 0000000000..a937979dd9 --- /dev/null +++ b/x/oracle/spec/02_state.md @@ -0,0 +1,95 @@ + + +# State + +## ExchangeRatePrevote + +`ExchangeRatePrevote` containing validator voter's prevote for a given denom for the current `VotePeriod`. + +- ExchangeRatePrevote: `0x01 -> amino(ExchangeRatePrevote)` + +```go +type ValAddress []byte +type VoteHash []byte + +type ExchangeRatePrevote struct { + Hash VoteHash // Vote hex hash to protect centralize data source problem + Denom string // Ticker name of target fiat currency + Voter sdk.ValAddress // Voter val address + SubmitBlock int64 +} +``` + +## ExchangeRateVote + +`ExchangeRateVote` containing validator voter's vote for a given denom for the current `VotePeriod`. + +- ExchangeRateVote: `0x02 -> amino(ExchangeRateVote)` + +```go +type ExchangeRateVote struct { + ExchangeRate sdk.Dec // ExchangeRate of Luna in target fiat currency + Denom string // Ticker name of target fiat currency + Voter sdk.ValAddress // voter val address of validator +} +``` + +## ExchangeRate + +An `sdk.Dec` that stores the current Luna exchange rate against a given denom, which is used by the [Market](../../market/spec/README.md) module for pricing swaps. + +You can get the active list of denoms trading against `Luna` (denominations with votes past `VoteThreshold`) with `k.GetActiveDenoms()`. + +- ExchangeRate: `0x03 -> amino(sdk.Dec)` + +## FeederDelegation + +An `sdk.AccAddress` (`terra-` account) address of `operator`'s delegated price feeder. + +- FeederDelegation: `0x04 -> amino(sdk.AccAddress)` + +## MissCounter + +An `int64` representing the number of `VotePeriods` that validator `operator` missed during the current `SlashWindow`. + +- MissCounter: `0x05 -> amino(int64)` + +## AggregateExchangeRatePrevote + +`AggregateExchangeRatePrevote` containing validator voter's aggregated prevote for all denoms for the current `VotePeriod`. + +- AggregateExchangeRatePrevote: `0x06 -> amino(AggregateExchangeRatePrevote)` + +```go +// AggregateVoteHash is hash value to hide vote exchange rates +// which is formatted as hex string in SHA256("{salt}:{exchange rate}{denom},...,{exchange rate}{denom}:{voter}") +type AggregateVoteHash []byte + +type AggregateExchangeRatePrevote struct { + Hash AggregateVoteHash // Vote hex hash to protect centralize data source problem + Voter sdk.ValAddress // Voter val address + SubmitBlock int64 +} +``` + +## AggregateExchangeRateVote + +`AggregateExchangeRateVote` containing validator voter's aggregate vote for all denoms for the current `VotePeriod`. + +- AggregateExchangeRateVote: `0x07 -> amino(AggregateExchangeRateVote)` + +```go +type ExchangeRateTuple struct { + Denom string `json:"denom"` + ExchangeRate sdk.Dec `json:"exchange_rate"` +} + +type ExchangeRateTuples []ExchangeRateTuple + +type AggregateExchangeRateVote struct { + ExchangeRateTuples ExchangeRateTuples // ExchangeRates of Luna in target fiat currencies + Voter sdk.ValAddress // voter val address of validator +} +``` diff --git a/x/oracle/spec/03_end_block.md b/x/oracle/spec/03_end_block.md new file mode 100755 index 0000000000..3484c02a71 --- /dev/null +++ b/x/oracle/spec/03_end_block.md @@ -0,0 +1,33 @@ + + +# End Block + +## Tally Exchange Rate Votes + +At the end of every block, the `Oracle` module checks whether it's the last block of the `VotePeriod`. If it is, it runs the [Voting Procedure](./01_concepts.md#Voting_Procedure): + +1. All current active Luna exchange rates are purged from the store + +2. Received votes are organized into ballots by denomination. Abstained votes, as well as votes by inactive or jailed validators are ignored + +3. Denominations not meeting the following requirements will be dropped: + + - Must appear in the permitted denominations in `Whitelist` + - Ballot for denomination must have at least `VoteThreshold` total vote power + +4. For each remaining `denom` with a passing ballot: + + - Tally up votes and find the weighted median exchange rate and winners with `tally()` + - Iterate through winners of the ballot and add their weight to their running total + - Set the Luna exchange rate on the blockchain for that Luna<>`denom` with `k.SetLunaExchangeRate()` + - Emit a `exchange_rate_update` event + +5. Count up the validators who [missed](./01_concepts.md#Slashing) the Oracle vote and increase the appropriate miss counters + +6. If at the end of a `SlashWindow`, penalize validators who have missed more than the penalty threshold (submitted fewer valid votes than `MinValidPerWindow`) + +7. Distribute rewards to ballot winners with `k.RewardBallotWinners()` + +8. Clear all prevotes (except ones for the next `VotePeriod`) and votes from the store diff --git a/x/oracle/spec/04_messages.md b/x/oracle/spec/04_messages.md new file mode 100755 index 0000000000..0c58057fbd --- /dev/null +++ b/x/oracle/spec/04_messages.md @@ -0,0 +1,94 @@ + + +# Messages + +## MsgExchangeRatePrevote (Deprecated) + +`Hash` is a hex string generated by the leading 20 bytes of the SHA256 hash (hex string) of a string of the format `{salt}:{exchange_rate}:{denom}:{voter}`, the metadata of the actual `MsgExchangeRateVote` to follow in the next `VotePeriod`. You can use the `GetVoteHash()` function to help encode this hash. Note that since in the subsequent `MsgExchangeRateVote`, the salt will have to be revealed, the salt used must be regenerated for each prevote submission. + +`Denom` is the denomination of the currency for which the vote is being cast. For example, if the voter wishes to submit a prevote for the usd, then the correct `Denom` is `uusd`. + +The exchange rate used in the hash must be the open market exchange rate of Luna, with respect to the denomination matching `Denom`. For example, if `Denom` is `uusd` and the going exchange rate for Luna is 1 USD, then "1" must be used as the exchange rate, as `1 uluna = 1 uusd`. + +`Feeder` (`terra-` address) is used if the validator wishes to delegate oracle vote signing to a separate key (who "feeds" the price in lieu of the operator) to de-risk exposing their validator signing key. + +`Validator` is the validator address (`terravaloper-` address) of the original validator. + + +```go +// Deprecated: normal prevote and vote will be deprecated after columbus-4 +// MsgExchangeRatePrevote - struct for prevoting on the ExchangeRateVote. +// The purpose of prevote is to hide vote exchange rate with hash +// which is formatted as hex string in SHA256("{salt}:{exchange_rate}:{denom}:{voter}") +type MsgExchangeRatePrevote struct { + Hash VoteHash + Denom string + Feeder sdk.AccAddress + Validator sdk.ValAddress +} +``` + +## MsgExchangeRateVote (Deprecated) + +The `MsgExchangeRateVote` contains the actual exchange rate vote. The `Salt` parameter must match the salt used to create the prevote, otherwise the voter cannot be rewarded. + +```go +// Deprecated: normal prevote and vote will be deprecated after columbus-4 +// MsgExchangeRateVote - struct for voting on the exchange rate of Luna denominated in various Terra assets. +// For example, if the validator believes that the effective exchange rate of Luna in USD is 10.39, that's +// what the exchange rate field would be, and if 1213.34 for KRW, same. +type MsgExchangeRateVote struct { + ExchangeRate sdk.Dec // the effective rate of Luna in {Denom} + Salt string + Denom string + Feeder sdk.AccAddress + Validator sdk.ValAddress +} +``` + +## MsgDelegateFeedConsent + +Validators may also elect to delegate voting rights to another key to prevent the block signing key from being kept online. To do so, they must submit a `MsgDelegateFeedConsent`, delegating their oracle voting rights to a `Delegate` that sign `MsgExchangeRatePrevote` and `MsgExchangeRateVote` on behalf of the validator. + +> Delegate validators will likely require you to deposit some funds (in Terra or Luna) which they can use to pay fees, sent in a separate MsgSend. This agreement is made off-chain and not enforced by the Terra protocol. + +The `Operator` field contains the operator address of the validator (prefixed `terravaloper-`). The `Delegate` field is the account address (prefixed `terra-`) of the delegate account that will be submitting exchange rate related votes and prevotes on behalf of the `Operator`. + +```go +// MsgDelegateFeedConsent - struct for delegating oracle voting rights to another address. +type MsgDelegateFeedConsent struct { + Operator sdk.ValAddress + Delegate sdk.AccAddress +} +``` + +## MsgAggregateExchangeRatePrevote + +`Hash` is a hex string generated by the leading 20 bytes of the SHA256 hash (hex string) of a string of the format `{salt}:{exchange rate}{denom},...,{exchange rate}{denom}:{voter}`, the metadata of the actual `MsgAggregateExchangeRateVote` to follow in the next `VotePeriod`. You can use the `GetAggregateVoteHash()` function to help encode this hash. Note that since in the subsequent `MsgAggregateExchangeRateVote`, the salt will have to be revealed, the salt used must be regenerated for each prevote submission. + +```go +// MsgAggregateExchangeRatePrevote - struct for aggregate prevoting on the ExchangeRateVote. +// The purpose of aggregate prevote is to hide vote exchange rates with hash +// which is formatted as hex string in SHA256("{salt}:{exchange rate}{denom},...,{exchange rate}{denom}:{voter}") +type MsgAggregateExchangeRatePrevote struct { + Hash AggregateVoteHash + Feeder sdk.AccAddress + Validator sdk.ValAddress +} +``` + +## MsgAggregateExchangeRateVote + +The `MsgAggregateExchangeRateVote` contains the actual exchange rates vote. The `Salt` parameter must match the salt used to create the prevote, otherwise the voter cannot be rewarded. + +```go +// MsgAggregateExchangeRateVote - struct for voting on the exchange rates of Luna denominated in various Terra assets. +type MsgAggregateExchangeRateVote struct { + Salt string + ExchangeRates string + Feeder sdk.AccAddress + Validator sdk.ValAddress +} +``` diff --git a/x/oracle/spec/05_events.md b/x/oracle/spec/05_events.md new file mode 100755 index 0000000000..654d5fdba6 --- /dev/null +++ b/x/oracle/spec/05_events.md @@ -0,0 +1,71 @@ + + +# Events + +The oracle module emits the following events: + +## EndBlocker + +| Type | Attribute Key | Attribute Value | +|----------------------|---------------|-----------------| +| exchange_rate_update | denom | {denom} | +| exchange_rate_update | exchange_rate | {exchangeRate} | + +## Handlers + +### MsgExchangeRatePrevote + +| Type | Attribute Key | Attribute Value | +|---------|---------------|---------------------| +| prevote | denom | {denom} | +| prevote | voter | {validatorAddress} | +| prevote | feeder | {feederAddress} | +| message | module | oracle | +| message | action | exchangerateprevote | +| message | sender | {senderAddress} | + +### MsgExchangeRateVote + +| Type | Attribute Key | Attribute Value | +|---------|---------------|--------------------| +| vote | denom | {denom} | +| vote | voter | {validatorAddress} | +| vote | exchange_rate | {exchangeRate} | +| vote | feeder | {feederAddress} | +| message | module | oracle | +| message | action | exchangeratevote | +| message | sender | {senderAddress} | + + +### MsgDelegateFeedConsent + +| Type | Attribute Key | Attribute Value | +|---------------|---------------|--------------------| +| feed_delegate | operator | {validatorAddress} | +| feed_delegate | feeder | {feederAddress} | +| message | module | oracle | +| message | action | delegatefeeder | +| message | sender | {senderAddress} | + +### MsgAggregateExchangeRatePrevote + +| Type | Attribute Key | Attribute Value | +|-------------------|---------------|------------------------------| +| aggregate_prevote | voter | {validatorAddress} | +| aggregate_prevote | feeder | {feederAddress} | +| message | module | oracle | +| message | action | aggregateexchangerateprevote | +| message | sender | {senderAddress} | + +### MsgAggregateExchangeRateVote + +| Type | Attribute Key | Attribute Value | +|----------------|----------------|---------------------------| +| aggregate_vote | voter | {validatorAddress} | +| aggregate_vote | exchange_rates | {exchangeRates} | +| aggregate_vote | feeder | {feederAddress} | +| message | module | oracle | +| message | action | aggregateexchangeratevote | +| message | sender | {senderAddress} | diff --git a/x/oracle/spec/06_params.md b/x/oracle/spec/06_params.md new file mode 100755 index 0000000000..4d631a8bfb --- /dev/null +++ b/x/oracle/spec/06_params.md @@ -0,0 +1,19 @@ + + + +# Parameters + +The market module contains the following parameters: + +| Key | Type | Example | +|--------------------------|--------------|------------------------| +| voteperiod | string (int) | "5" | +| votethreshold | string (dec) | "0.500000000000000000" | +| rewardband | string (dec) | "0.020000000000000000" | +| rewarddistributionwindow | string (int) | "5256000" | +| whitelist | []DenomList | [{"name": "ukrw"}] | +| slashfraction | string (dec) | "0.001000000000000000" | +| slashwindow | string (int) | "100800" | +| minvalidperwindow | string (int) | "0.050000000000000000" | \ No newline at end of file diff --git a/x/oracle/spec/README.md b/x/oracle/spec/README.md new file mode 100755 index 0000000000..b2c725ccfd --- /dev/null +++ b/x/oracle/spec/README.md @@ -0,0 +1,35 @@ +## Abstract + +The Oracle module provides the Terra blockchain with an up-to-date and accurate price feed of exchange rates of Luna against various Terra pegs so that the [Market](../../market/spec/README.md) may provide fair exchanges between Terra<>Terra currency pairs, as well as Terra<>Luna. + +As price information is extrinsic to the blockchain, the Terra network relies on validators to periodically vote on the current Luna exchange rate, with the protocol tallying up the results once per `VotePeriod` and updating the on-chain exchange rate as the weighted median of the ballot. + +> Since the Oracle service is powered by validators, you may find it interesting to look at the [Staking](https://github.com/cosmos/cosmos-sdk/tree/master/x/staking/spec/README.md) module, which covers the logic for staking and validators. + +## Contents + +1. **[Concepts](01_concepts.md)** + - [Voting Procedure](01_concepts.md#Voting-Procedure) + - [Reward Band](01_concepts.md#Reward-Band) + - [Slashing](01_concepts.md#Slashing) + - [Abstaining from Voting](01_concepts.md#Abstaining-from-Voting) +2. **[State](02_state.md)** + - [ExchangeRatePrevote](02_state.md#ExchangeRatePrevote) + - [ExchangeRateVote](02_state.md#ExchangeRateVote) + - [ExchangeRate](02_state.md#ExchangeRate) + - [FeederDelegation](02_state.md#FeederDelegation) + - [MissCounter](02_state.md#MissCounter) + - [AggregateExchangeRatePrevote](02_state.md#AggregateExchangeRatePrevote) + - [AggregateExchangeRateVote](02_state.md#AggregateExchangeRateVote) +3. **[EndBlock](03_end_block.md)** + - [Tally Exchange Rate Votes](03_end_block.md#Tally-Exchange-Rate-Votes) +4. **[Messages](04_messages.md)** + - [MsgExchangeRatePrevote](04_messages.md#MsgExchangeRatePrevote) + - [MsgExchangeRatePrevote](04_messages.md#MsgExchangeRatePrevote) + - [MsgDelegateFeedConsent](04_messages.md#MsgDelegateFeedConsent) + - [MsgAggregateExchangeRatePrevote](04_messages.md#MsgAggregateExchangeRatePrevote) + - [MsgAggregateExchangeRateVote](04_messages.md#MsgAggregateExchangeRateVote) +5. **[Events](05_events.md)** + - [EndBlocker](05_events.md#EndBlocker) + - [Handlers](05_events.md#Handlers) +6. **[Parameters](06_params.md)** \ No newline at end of file diff --git a/x/oracle/tally.go b/x/oracle/tally.go new file mode 100755 index 0000000000..da8bd8ef3b --- /dev/null +++ b/x/oracle/tally.go @@ -0,0 +1,86 @@ +package oracle + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/sei-protocol/sei-chain/x/oracle/keeper" + "github.com/sei-protocol/sei-chain/x/oracle/types" +) + +// Tally calculates the median and returns it. Sets the set of voters to be rewarded, i.e. voted within +// a reasonable spread from the weighted median to the store +// CONTRACT: pb must be sorted +func Tally(ctx sdk.Context, pb types.ExchangeRateBallot, rewardBand sdk.Dec, validatorClaimMap map[string]types.Claim) (weightedMedian sdk.Dec) { + weightedMedian = pb.WeightedMedianWithAssertion() + + standardDeviation := pb.StandardDeviation(weightedMedian) + rewardSpread := weightedMedian.Mul(rewardBand.QuoInt64(2)) + + if standardDeviation.GT(rewardSpread) { + rewardSpread = standardDeviation + } + + for _, vote := range pb { + // Filter ballot winners & abstain voters + if (vote.ExchangeRate.GTE(weightedMedian.Sub(rewardSpread)) && + vote.ExchangeRate.LTE(weightedMedian.Add(rewardSpread))) || + !vote.ExchangeRate.IsPositive() { + + key := vote.Voter.String() + claim := validatorClaimMap[key] + claim.Weight += vote.Power + claim.WinCount++ + validatorClaimMap[key] = claim + } + } + + return +} + +// ballot for the asset is passing the threshold amount of voting power +func ballotIsPassing(ballot types.ExchangeRateBallot, thresholdVotes sdk.Int) (sdk.Int, bool) { + ballotPower := sdk.NewInt(ballot.Power()) + return ballotPower, !ballotPower.IsZero() && ballotPower.GTE(thresholdVotes) +} + +// choose reference denom with the highest voter turnout +// If the voting power of the two denominations is the same, +// select reference denom in alphabetical order. +func pickReferenceDenom(ctx sdk.Context, k keeper.Keeper, voteTargets map[string]types.Denom, voteMap map[string]types.ExchangeRateBallot) string { + largestBallotPower := int64(0) + referenceDenom := "" + + totalBondedPower := sdk.TokensToConsensusPower(k.StakingKeeper.TotalBondedTokens(ctx), k.StakingKeeper.PowerReduction(ctx)) + voteThreshold := k.VoteThreshold(ctx) + thresholdVotes := voteThreshold.MulInt64(totalBondedPower).RoundInt() + + for denom, ballot := range voteMap { + // If denom is not in the voteTargets, or the ballot for it has failed, then skip + // and remove it from voteMap for iteration efficiency + if _, exists := voteTargets[denom]; !exists { + delete(voteMap, denom) + continue + } + + ballotPower := int64(0) + + // If the ballot is not passed, remove it from the voteTargets array + // to prevent slashing validators who did valid vote. + if power, ok := ballotIsPassing(ballot, thresholdVotes); ok { + ballotPower = power.Int64() + } else { + delete(voteTargets, denom) + delete(voteMap, denom) + continue + } + + if ballotPower > largestBallotPower || largestBallotPower == 0 { + referenceDenom = denom + largestBallotPower = ballotPower + } else if largestBallotPower == ballotPower && referenceDenom > denom { + referenceDenom = denom + } + } + + return referenceDenom +} diff --git a/x/oracle/types/ballot.go b/x/oracle/types/ballot.go new file mode 100755 index 0000000000..fc811cda82 --- /dev/null +++ b/x/oracle/types/ballot.go @@ -0,0 +1,196 @@ +package types + +import ( + "fmt" + "math" + "sort" + "strconv" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NOTE: we don't need to implement proto interface on this file +// these are not used in store or rpc response + +// VoteForTally is a convenience wrapper to reduce redundant lookup cost +type VoteForTally struct { + Denom string + ExchangeRate sdk.Dec + Voter sdk.ValAddress + Power int64 +} + +// NewVoteForTally returns a new VoteForTally instance +func NewVoteForTally(rate sdk.Dec, denom string, voter sdk.ValAddress, power int64) VoteForTally { + return VoteForTally{ + ExchangeRate: rate, + Denom: denom, + Voter: voter, + Power: power, + } +} + +// ExchangeRateBallot is a convenience wrapper around a ExchangeRateVote slice +type ExchangeRateBallot []VoteForTally + +// ToMap return organized exchange rate map by validator +func (pb ExchangeRateBallot) ToMap() map[string]sdk.Dec { + exchangeRateMap := make(map[string]sdk.Dec) + for _, vote := range pb { + if vote.ExchangeRate.IsPositive() { + exchangeRateMap[string(vote.Voter)] = vote.ExchangeRate + } + } + + return exchangeRateMap +} + +// ToCrossRate return cross_rate(base/exchange_rate) ballot +func (pb ExchangeRateBallot) ToCrossRate(bases map[string]sdk.Dec) (cb ExchangeRateBallot) { + for i := range pb { + vote := pb[i] + + if exchangeRateRT, ok := bases[string(vote.Voter)]; ok && vote.ExchangeRate.IsPositive() { + vote.ExchangeRate = exchangeRateRT.Quo(vote.ExchangeRate) + } else { + // If we can't get reference terra exchange rate, we just convert the vote as abstain vote + vote.ExchangeRate = sdk.ZeroDec() + vote.Power = 0 + } + + cb = append(cb, vote) + } + + return +} + +// ToCrossRateWithSort return cross_rate(base/exchange_rate) ballot +func (pb ExchangeRateBallot) ToCrossRateWithSort(bases map[string]sdk.Dec) (cb ExchangeRateBallot) { + for i := range pb { + vote := pb[i] + + if exchangeRateRD, ok := bases[string(vote.Voter)]; ok && vote.ExchangeRate.IsPositive() { + vote.ExchangeRate = exchangeRateRD.Quo(vote.ExchangeRate) + } else { + // If we can't get reference denom exchange rate, we just convert the vote as abstain vote + vote.ExchangeRate = sdk.ZeroDec() + vote.Power = 0 + } + + cb = append(cb, vote) + } + + sort.Sort(cb) + return +} + +// Power returns the total amount of voting power in the ballot +func (pb ExchangeRateBallot) Power() int64 { + totalPower := int64(0) + for _, vote := range pb { + totalPower += vote.Power + } + + return totalPower +} + +// WeightedMedian returns the median weighted by the power of the ExchangeRateVote. +// CONTRACT: ballot must be sorted +func (pb ExchangeRateBallot) WeightedMedian() sdk.Dec { + totalPower := pb.Power() + if pb.Len() > 0 { + pivot := int64(0) + for _, v := range pb { + votePower := v.Power + + pivot += votePower + if pivot >= (totalPower / 2) { + return v.ExchangeRate + } + } + } + return sdk.ZeroDec() +} + +// WeightedMedianWithAssertion returns the median weighted by the power of the ExchangeRateVote. +// CONTRACT: ballot must be sorted +func (pb ExchangeRateBallot) WeightedMedianWithAssertion() sdk.Dec { + if !sort.IsSorted(pb) { + panic("ballot must be sorted") + } + + totalPower := pb.Power() + if pb.Len() > 0 { + pivot := int64(0) + for _, v := range pb { + votePower := v.Power + + pivot += votePower + if pivot >= (totalPower / 2) { + return v.ExchangeRate + } + } + } + return sdk.ZeroDec() +} + +// StandardDeviation returns the standard deviation by the power of the ExchangeRateVote. +func (pb ExchangeRateBallot) StandardDeviation(median sdk.Dec) (standardDeviation sdk.Dec) { + if len(pb) == 0 { + return sdk.ZeroDec() + } + + defer func() { + if e := recover(); e != nil { + standardDeviation = sdk.ZeroDec() + } + }() + + sum := sdk.ZeroDec() + for _, v := range pb { + deviation := v.ExchangeRate.Sub(median) + sum = sum.Add(deviation.Mul(deviation)) + } + + variance := sum.QuoInt64(int64(len(pb))) + + floatNum, _ := strconv.ParseFloat(variance.String(), 64) + floatNum = math.Sqrt(floatNum) + standardDeviation, _ = sdk.NewDecFromStr(fmt.Sprintf("%f", floatNum)) + + return +} + +// Len implements sort.Interface +func (pb ExchangeRateBallot) Len() int { + return len(pb) +} + +// Less reports whether the element with +// index i should sort before the element with index j. +func (pb ExchangeRateBallot) Less(i, j int) bool { + return pb[i].ExchangeRate.LT(pb[j].ExchangeRate) +} + +// Swap implements sort.Interface. +func (pb ExchangeRateBallot) Swap(i, j int) { + pb[i], pb[j] = pb[j], pb[i] +} + +// Claim is an interface that directs its rewards to an attached bank account. +type Claim struct { + Power int64 + Weight int64 + WinCount int64 + Recipient sdk.ValAddress +} + +// NewClaim generates a Claim instance. +func NewClaim(power, weight, winCount int64, recipient sdk.ValAddress) Claim { + return Claim{ + Power: power, + Weight: weight, + WinCount: winCount, + Recipient: recipient, + } +} diff --git a/x/oracle/types/ballot_test.go b/x/oracle/types/ballot_test.go new file mode 100755 index 0000000000..2e638905f5 --- /dev/null +++ b/x/oracle/types/ballot_test.go @@ -0,0 +1,291 @@ +package types + +import ( + "fmt" + "math" + "sort" + "strconv" + + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto/secp256k1" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/sei-protocol/sei-chain/x/oracle/utils" +) + +func TestToMap(t *testing.T) { + tests := struct { + votes []VoteForTally + isValid []bool + }{ + + []VoteForTally{ + { + + Voter: sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()), + Denom: utils.MicroAtomDenom, + ExchangeRate: sdk.NewDec(1600), + Power: 100, + }, + }, + []bool{true}, + } + + pb := ExchangeRateBallot(tests.votes) + mapData := pb.ToMap() + for i, vote := range tests.votes { + exchangeRate, ok := mapData[string(vote.Voter)] + if tests.isValid[i] { + require.True(t, ok) + require.Equal(t, exchangeRate, vote.ExchangeRate) + } else { + require.False(t, ok) + } + } +} + +func TestToCrossRate(t *testing.T) { + data := []struct { + base sdk.Dec + quote sdk.Dec + expected sdk.Dec + }{ + { + base: sdk.NewDec(1600), + quote: sdk.NewDec(100), + expected: sdk.NewDec(16), + }, + { + base: sdk.NewDec(0), + quote: sdk.NewDec(100), + expected: sdk.NewDec(16), + }, + { + base: sdk.NewDec(1600), + quote: sdk.NewDec(0), + expected: sdk.NewDec(16), + }, + } + + pbBase := ExchangeRateBallot{} + pbQuote := ExchangeRateBallot{} + cb := ExchangeRateBallot{} + for _, data := range data { + valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()) + if !data.base.IsZero() { + pbBase = append(pbBase, NewVoteForTally(data.base, utils.MicroAtomDenom, valAddr, 100)) + } + + pbQuote = append(pbQuote, NewVoteForTally(data.quote, utils.MicroAtomDenom, valAddr, 100)) + + if !data.base.IsZero() && !data.quote.IsZero() { + cb = append(cb, NewVoteForTally(data.base.Quo(data.quote), utils.MicroAtomDenom, valAddr, 100)) + } else { + cb = append(cb, NewVoteForTally(sdk.ZeroDec(), utils.MicroAtomDenom, valAddr, 0)) + } + } + + sort.Sort(cb) + + baseMapBallot := pbBase.ToMap() + require.Equal(t, cb, pbQuote.ToCrossRateWithSort(baseMapBallot)) +} + +func TestSqrt(t *testing.T) { + num := sdk.NewDecWithPrec(144, 4) + floatNum, err := strconv.ParseFloat(num.String(), 64) + require.NoError(t, err) + + floatNum = math.Sqrt(floatNum) + num, err = sdk.NewDecFromStr(fmt.Sprintf("%f", floatNum)) + require.NoError(t, err) + + require.Equal(t, sdk.NewDecWithPrec(12, 2), num) +} + +func TestPBPower(t *testing.T) { + + ctx := sdk.NewContext(nil, tmproto.Header{}, false, nil) + _, valAccAddrs, sk := GenerateRandomTestCase() + pb := ExchangeRateBallot{} + ballotPower := int64(0) + + for i := 0; i < len(sk.Validators()); i++ { + power := sk.Validator(ctx, valAccAddrs[i]).GetConsensusPower(sdk.DefaultPowerReduction) + vote := NewVoteForTally( + sdk.ZeroDec(), + utils.MicroAtomDenom, + valAccAddrs[i], + power, + ) + + pb = append(pb, vote) + + require.NotEqual(t, int64(0), vote.Power) + + ballotPower += vote.Power + } + + require.Equal(t, ballotPower, pb.Power()) + + // Mix in a fake validator, the total power should not have changed. + pubKey := secp256k1.GenPrivKey().PubKey() + faceValAddr := sdk.ValAddress(pubKey.Address()) + fakeVote := NewVoteForTally( + sdk.OneDec(), + utils.MicroAtomDenom, + faceValAddr, + 0, + ) + + pb = append(pb, fakeVote) + require.Equal(t, ballotPower, pb.Power()) +} + +func TestPBWeightedMedian(t *testing.T) { + tests := []struct { + inputs []int64 + weights []int64 + isValidator []bool + median sdk.Dec + }{ + { + // Supermajority one number + []int64{1, 2, 10, 100000}, + []int64{1, 1, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDec(10), + }, + { + // Adding fake validator doesn't change outcome + []int64{1, 2, 10, 100000, 10000000000}, + []int64{1, 1, 100, 1, 10000}, + []bool{true, true, true, true, false}, + sdk.NewDec(10), + }, + { + // Tie votes + []int64{1, 2, 3, 4}, + []int64{1, 100, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDec(2), + }, + { + // No votes + []int64{}, + []int64{}, + []bool{true, true, true, true}, + sdk.NewDec(0), + }, + } + + for _, tc := range tests { + pb := ExchangeRateBallot{} + for i, input := range tc.inputs { + valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()) + + power := tc.weights[i] + if !tc.isValidator[i] { + power = 0 + } + + vote := NewVoteForTally( + sdk.NewDec(int64(input)), + utils.MicroAtomDenom, + valAddr, + power, + ) + + pb = append(pb, vote) + } + + require.Equal(t, tc.median, pb.WeightedMedianWithAssertion()) + } +} + +func TestPBStandardDeviation(t *testing.T) { + tests := []struct { + inputs []float64 + weights []int64 + isValidator []bool + standardDeviation sdk.Dec + }{ + { + // Supermajority one number + []float64{1.0, 2.0, 10.0, 100000.0}, + []int64{1, 1, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDecWithPrec(4999500036300, OracleDecPrecision), + }, + { + // Adding fake validator doesn't change outcome + []float64{1.0, 2.0, 10.0, 100000.0, 10000000000}, + []int64{1, 1, 100, 1, 10000}, + []bool{true, true, true, true, false}, + sdk.NewDecWithPrec(447213595075100600, OracleDecPrecision), + }, + { + // Tie votes + []float64{1.0, 2.0, 3.0, 4.0}, + []int64{1, 100, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDecWithPrec(122474500, OracleDecPrecision), + }, + { + // No votes + []float64{}, + []int64{}, + []bool{true, true, true, true}, + sdk.NewDecWithPrec(0, 0), + }, + } + + base := math.Pow10(OracleDecPrecision) + for _, tc := range tests { + pb := ExchangeRateBallot{} + for i, input := range tc.inputs { + valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()) + + power := tc.weights[i] + if !tc.isValidator[i] { + power = 0 + } + + vote := NewVoteForTally( + sdk.NewDecWithPrec(int64(input*base), int64(OracleDecPrecision)), + utils.MicroAtomDenom, + valAddr, + power, + ) + + pb = append(pb, vote) + } + + require.Equal(t, tc.standardDeviation, pb.StandardDeviation(pb.WeightedMedianWithAssertion())) + } +} + +func TestPBStandardDeviationOverflow(t *testing.T) { + valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()) + exchangeRate, err := sdk.NewDecFromStr("100000000000000000000000000000000000000000000000000000000.0") + require.NoError(t, err) + + pb := ExchangeRateBallot{NewVoteForTally( + sdk.ZeroDec(), + utils.MicroAtomDenom, + valAddr, + 2, + ), NewVoteForTally( + exchangeRate, + utils.MicroAtomDenom, + valAddr, + 1, + )} + + require.Equal(t, sdk.ZeroDec(), pb.StandardDeviation(pb.WeightedMedianWithAssertion())) +} diff --git a/x/oracle/types/codec.go b/x/oracle/types/codec.go new file mode 100755 index 0000000000..84fa88ef18 --- /dev/null +++ b/x/oracle/types/codec.go @@ -0,0 +1,33 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgAggregateExchangeRatePrevote{}, "oracle/MsgAggregateExchangeRatePrevote", nil) + cdc.RegisterConcrete(&MsgAggregateExchangeRateVote{}, "oracle/MsgAggregateExchangeRateVote", nil) + cdc.RegisterConcrete(&MsgDelegateFeedConsent{}, "oracle/MsgDelegateFeedConsent", nil) +} + +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgAggregateExchangeRatePrevote{}, + ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgAggregateExchangeRateVote{}, + ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgDelegateFeedConsent{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + Amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) +) diff --git a/x/oracle/types/denom.go b/x/oracle/types/denom.go new file mode 100755 index 0000000000..57e6de64e8 --- /dev/null +++ b/x/oracle/types/denom.go @@ -0,0 +1,29 @@ +package types + +import ( + "strings" + + "gopkg.in/yaml.v2" +) + +// String implements fmt.Stringer interface +func (d Denom) String() string { + out, _ := yaml.Marshal(d) + return string(out) +} + +// Equal implements equal interface +func (d Denom) Equal(d1 *Denom) bool { + return d.Name == d1.Name +} + +// DenomList is array of Denom +type DenomList []Denom + +// String implements fmt.Stringer interface +func (dl DenomList) String() (out string) { + for _, d := range dl { + out += d.String() + "\n" + } + return strings.TrimSpace(out) +} diff --git a/x/oracle/types/errors.go b/x/oracle/types/errors.go new file mode 100755 index 0000000000..738ce8d809 --- /dev/null +++ b/x/oracle/types/errors.go @@ -0,0 +1,26 @@ +package types + +import ( + "fmt" + + "github.com/tendermint/tendermint/crypto/tmhash" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Oracle Errors +var ( + ErrInvalidExchangeRate = sdkerrors.Register(ModuleName, 2, "invalid exchange rate") + ErrNoPrevote = sdkerrors.Register(ModuleName, 3, "no prevote") + ErrNoVote = sdkerrors.Register(ModuleName, 4, "no vote") + ErrNoVotingPermission = sdkerrors.Register(ModuleName, 5, "unauthorized voter") + ErrInvalidHash = sdkerrors.Register(ModuleName, 6, "invalid hash") + ErrInvalidHashLength = sdkerrors.Register(ModuleName, 7, fmt.Sprintf("invalid hash length; should equal %d", tmhash.TruncatedSize)) + ErrVerificationFailed = sdkerrors.Register(ModuleName, 8, "hash verification failed") + ErrRevealPeriodMissMatch = sdkerrors.Register(ModuleName, 9, "reveal period of submitted vote do not match with registered prevote") + ErrInvalidSaltLength = sdkerrors.Register(ModuleName, 10, "invalid salt length; should be 1~4") + ErrNoAggregatePrevote = sdkerrors.Register(ModuleName, 11, "no aggregate prevote") + ErrNoAggregateVote = sdkerrors.Register(ModuleName, 12, "no aggregate vote") + ErrNoVoteTarget = sdkerrors.Register(ModuleName, 13, "no vote target") + ErrUnknownDenom = sdkerrors.Register(ModuleName, 14, "unknown denom") +) diff --git a/x/oracle/types/events.go b/x/oracle/types/events.go new file mode 100755 index 0000000000..f1c147ca64 --- /dev/null +++ b/x/oracle/types/events.go @@ -0,0 +1,20 @@ +package types + +// Oracle module event types +const ( + EventTypeExchangeRateUpdate = "exchange_rate_update" + EventTypePrevote = "prevote" + EventTypeVote = "vote" + EventTypeFeedDelegate = "feed_delegate" + EventTypeAggregatePrevote = "aggregate_prevote" + EventTypeAggregateVote = "aggregate_vote" + + AttributeKeyDenom = "denom" + AttributeKeyVoter = "voter" + AttributeKeyExchangeRate = "exchange_rate" + AttributeKeyExchangeRates = "exchange_rates" + AttributeKeyOperator = "operator" + AttributeKeyFeeder = "feeder" + + AttributeValueCategory = ModuleName +) diff --git a/x/oracle/types/expected_keeper.go b/x/oracle/types/expected_keeper.go new file mode 100755 index 0000000000..feed39e429 --- /dev/null +++ b/x/oracle/types/expected_keeper.go @@ -0,0 +1,46 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// StakingKeeper is expected keeper for staking module +type StakingKeeper interface { + Validator(ctx sdk.Context, address sdk.ValAddress) stakingtypes.ValidatorI // get validator by operator address; nil when validator not found + TotalBondedTokens(sdk.Context) sdk.Int // total bonded tokens within the validator set + Slash(sdk.Context, sdk.ConsAddress, int64, int64, sdk.Dec) // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction + Jail(sdk.Context, sdk.ConsAddress) // jail a validator + ValidatorsPowerStoreIterator(ctx sdk.Context) sdk.Iterator // an iterator for the current validator power store + MaxValidators(sdk.Context) uint32 // MaxValidators returns the maximum amount of bonded validators + PowerReduction(ctx sdk.Context) (res sdk.Int) +} + +// DistributionKeeper is expected keeper for distribution module +type DistributionKeeper interface { + AllocateTokensToValidator(ctx sdk.Context, val stakingtypes.ValidatorI, tokens sdk.DecCoins) + + // only used for simulation + GetValidatorOutstandingRewardsCoins(ctx sdk.Context, val sdk.ValAddress) sdk.DecCoins +} + +// AccountKeeper is expected keeper for auth module +type AccountKeeper interface { + GetModuleAddress(name string) sdk.AccAddress + GetModuleAccount(ctx sdk.Context, moduleName string) authtypes.ModuleAccountI + GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI // only used for simulation +} + +// BankKeeper defines the expected interface needed to retrieve account balances. +type BankKeeper interface { + GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin + GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) error + GetDenomMetaData(ctx sdk.Context, denom string) (banktypes.Metadata, bool) + SetDenomMetaData(ctx sdk.Context, denomMetaData banktypes.Metadata) + + // only used for simulation + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins +} diff --git a/x/oracle/types/genesis.go b/x/oracle/types/genesis.go new file mode 100755 index 0000000000..2f2ba40b6d --- /dev/null +++ b/x/oracle/types/genesis.go @@ -0,0 +1,54 @@ +package types + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" +) + +// NewGenesisState creates a new GenesisState object +func NewGenesisState( + params Params, rates []ExchangeRateTuple, + feederDelegations []FeederDelegation, missCounters []MissCounter, + aggregateExchangeRatePrevotes []AggregateExchangeRatePrevote, + aggregateExchangeRateVotes []AggregateExchangeRateVote, +) *GenesisState { + + return &GenesisState{ + Params: params, + ExchangeRates: rates, + FeederDelegations: feederDelegations, + MissCounters: missCounters, + AggregateExchangeRatePrevotes: aggregateExchangeRatePrevotes, + AggregateExchangeRateVotes: aggregateExchangeRateVotes, + } +} + +// DefaultGenesisState - default GenesisState used by columbus-2 +func DefaultGenesisState() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + ExchangeRates: []ExchangeRateTuple{}, + FeederDelegations: []FeederDelegation{}, + MissCounters: []MissCounter{}, + AggregateExchangeRatePrevotes: []AggregateExchangeRatePrevote{}, + AggregateExchangeRateVotes: []AggregateExchangeRateVote{}, + } +} + +// ValidateGenesis validates the oracle genesis state +func ValidateGenesis(data *GenesisState) error { + return data.Params.Validate() +} + +// GetGenesisStateFromAppState returns x/oracle GenesisState given raw application +// genesis state. +func GetGenesisStateFromAppState(cdc codec.JSONCodec, appState map[string]json.RawMessage) *GenesisState { + var genesisState GenesisState + + if appState[ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) + } + + return &genesisState +} diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go new file mode 100644 index 0000000000..718ee51d85 --- /dev/null +++ b/x/oracle/types/genesis.pb.go @@ -0,0 +1,1075 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type GenesisState struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + FeederDelegations []FeederDelegation `protobuf:"bytes,2,rep,name=feeder_delegations,json=feederDelegations,proto3" json:"feeder_delegations"` + ExchangeRates ExchangeRateTuples `protobuf:"bytes,3,rep,name=exchange_rates,json=exchangeRates,proto3,castrepeated=ExchangeRateTuples" json:"exchange_rates"` + MissCounters []MissCounter `protobuf:"bytes,4,rep,name=miss_counters,json=missCounters,proto3" json:"miss_counters"` + AggregateExchangeRatePrevotes []AggregateExchangeRatePrevote `protobuf:"bytes,5,rep,name=aggregate_exchange_rate_prevotes,json=aggregateExchangeRatePrevotes,proto3" json:"aggregate_exchange_rate_prevotes"` + AggregateExchangeRateVotes []AggregateExchangeRateVote `protobuf:"bytes,6,rep,name=aggregate_exchange_rate_votes,json=aggregateExchangeRateVotes,proto3" json:"aggregate_exchange_rate_votes"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_ce0b3a2b4a184fc3, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func (m *GenesisState) GetFeederDelegations() []FeederDelegation { + if m != nil { + return m.FeederDelegations + } + return nil +} + +func (m *GenesisState) GetExchangeRates() ExchangeRateTuples { + if m != nil { + return m.ExchangeRates + } + return nil +} + +func (m *GenesisState) GetMissCounters() []MissCounter { + if m != nil { + return m.MissCounters + } + return nil +} + +func (m *GenesisState) GetAggregateExchangeRatePrevotes() []AggregateExchangeRatePrevote { + if m != nil { + return m.AggregateExchangeRatePrevotes + } + return nil +} + +func (m *GenesisState) GetAggregateExchangeRateVotes() []AggregateExchangeRateVote { + if m != nil { + return m.AggregateExchangeRateVotes + } + return nil +} + +type FeederDelegation struct { + FeederAddress string `protobuf:"bytes,1,opt,name=feeder_address,json=feederAddress,proto3" json:"feeder_address,omitempty"` + ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` +} + +func (m *FeederDelegation) Reset() { *m = FeederDelegation{} } +func (m *FeederDelegation) String() string { return proto.CompactTextString(m) } +func (*FeederDelegation) ProtoMessage() {} +func (*FeederDelegation) Descriptor() ([]byte, []int) { + return fileDescriptor_ce0b3a2b4a184fc3, []int{1} +} +func (m *FeederDelegation) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FeederDelegation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FeederDelegation.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *FeederDelegation) XXX_Merge(src proto.Message) { + xxx_messageInfo_FeederDelegation.Merge(m, src) +} +func (m *FeederDelegation) XXX_Size() int { + return m.Size() +} +func (m *FeederDelegation) XXX_DiscardUnknown() { + xxx_messageInfo_FeederDelegation.DiscardUnknown(m) +} + +var xxx_messageInfo_FeederDelegation proto.InternalMessageInfo + +func (m *FeederDelegation) GetFeederAddress() string { + if m != nil { + return m.FeederAddress + } + return "" +} + +func (m *FeederDelegation) GetValidatorAddress() string { + if m != nil { + return m.ValidatorAddress + } + return "" +} + +type MissCounter struct { + ValidatorAddress string `protobuf:"bytes,1,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` + MissCounter uint64 `protobuf:"varint,2,opt,name=miss_counter,json=missCounter,proto3" json:"miss_counter,omitempty"` +} + +func (m *MissCounter) Reset() { *m = MissCounter{} } +func (m *MissCounter) String() string { return proto.CompactTextString(m) } +func (*MissCounter) ProtoMessage() {} +func (*MissCounter) Descriptor() ([]byte, []int) { + return fileDescriptor_ce0b3a2b4a184fc3, []int{2} +} +func (m *MissCounter) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MissCounter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MissCounter.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MissCounter) XXX_Merge(src proto.Message) { + xxx_messageInfo_MissCounter.Merge(m, src) +} +func (m *MissCounter) XXX_Size() int { + return m.Size() +} +func (m *MissCounter) XXX_DiscardUnknown() { + xxx_messageInfo_MissCounter.DiscardUnknown(m) +} + +var xxx_messageInfo_MissCounter proto.InternalMessageInfo + +func (m *MissCounter) GetValidatorAddress() string { + if m != nil { + return m.ValidatorAddress + } + return "" +} + +func (m *MissCounter) GetMissCounter() uint64 { + if m != nil { + return m.MissCounter + } + return 0 +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "seiprotocol.seichain.oracle.GenesisState") + proto.RegisterType((*FeederDelegation)(nil), "seiprotocol.seichain.oracle.FeederDelegation") + proto.RegisterType((*MissCounter)(nil), "seiprotocol.seichain.oracle.MissCounter") +} + +func init() { proto.RegisterFile("oracle/genesis.proto", fileDescriptor_ce0b3a2b4a184fc3) } + +var fileDescriptor_ce0b3a2b4a184fc3 = []byte{ + // 491 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4f, 0x6b, 0x13, 0x41, + 0x14, 0xcf, 0xb6, 0x69, 0xc0, 0x49, 0x52, 0xda, 0xb1, 0x87, 0x10, 0xe9, 0x36, 0x46, 0x84, 0x80, + 0x74, 0xd7, 0x56, 0x10, 0x3c, 0x26, 0xfe, 0x03, 0x41, 0x28, 0x5b, 0xf1, 0x20, 0xc8, 0x32, 0xbb, + 0xfb, 0xb2, 0x19, 0xd8, 0xdd, 0x59, 0xf7, 0x4d, 0x42, 0x3d, 0x79, 0xd5, 0x9b, 0x9f, 0xc3, 0x4f, + 0xd2, 0x63, 0x8f, 0x9e, 0x54, 0x92, 0x2f, 0x22, 0x99, 0x99, 0x36, 0x6b, 0x6d, 0x16, 0x7a, 0xca, + 0xe4, 0xbd, 0xdf, 0xbf, 0x37, 0xf3, 0x96, 0xec, 0x89, 0x82, 0x85, 0x09, 0xb8, 0x31, 0x64, 0x80, + 0x1c, 0x9d, 0xbc, 0x10, 0x52, 0xd0, 0x7b, 0x08, 0x5c, 0x9d, 0x42, 0x91, 0x38, 0x08, 0x3c, 0x9c, + 0x30, 0x9e, 0x39, 0x1a, 0xda, 0xdd, 0x8b, 0x45, 0x2c, 0x54, 0xd7, 0x5d, 0x9e, 0x34, 0xa5, 0x7b, + 0xd7, 0x08, 0xe9, 0x1f, 0x53, 0xb4, 0x43, 0x81, 0xa9, 0x40, 0x37, 0x60, 0x08, 0xee, 0xec, 0x28, + 0x00, 0xc9, 0x8e, 0xdc, 0x50, 0xf0, 0x4c, 0xf7, 0xfb, 0xdf, 0xb6, 0x48, 0xeb, 0xb5, 0x76, 0x3e, + 0x95, 0x4c, 0x02, 0x1d, 0x92, 0x46, 0xce, 0x0a, 0x96, 0x62, 0xc7, 0xea, 0x59, 0x83, 0xe6, 0xf1, + 0x03, 0xa7, 0x22, 0x89, 0x73, 0xa2, 0xa0, 0xa3, 0xfa, 0xf9, 0xaf, 0x83, 0x9a, 0x67, 0x88, 0x34, + 0x20, 0x74, 0x0c, 0x10, 0x41, 0xe1, 0x47, 0x90, 0x40, 0xcc, 0x24, 0x17, 0x19, 0x76, 0x36, 0x7a, + 0x9b, 0x83, 0xe6, 0xf1, 0x61, 0xa5, 0xdc, 0x2b, 0x45, 0x7b, 0x71, 0xc5, 0x32, 0xc2, 0xbb, 0xe3, + 0x6b, 0x75, 0xa4, 0x9f, 0xc8, 0x36, 0x9c, 0x85, 0x13, 0x96, 0xc5, 0xe0, 0x17, 0x4c, 0x02, 0x76, + 0x36, 0x95, 0xbe, 0x53, 0xa9, 0xff, 0xd2, 0x50, 0x3c, 0x26, 0xe1, 0xdd, 0x34, 0x4f, 0x60, 0xd4, + 0x5d, 0x1a, 0xfc, 0xf8, 0x7d, 0x40, 0xff, 0x6b, 0xa1, 0xd7, 0x86, 0x52, 0x0d, 0xe9, 0x29, 0x69, + 0xa7, 0x1c, 0xd1, 0x0f, 0xc5, 0x34, 0x93, 0x50, 0x60, 0xa7, 0xae, 0x1c, 0x07, 0x95, 0x8e, 0x6f, + 0x39, 0xe2, 0x73, 0x4d, 0x30, 0xc3, 0xb4, 0xd2, 0x55, 0x09, 0xe9, 0x57, 0x8b, 0xf4, 0x58, 0x1c, + 0x17, 0xcb, 0xc1, 0xc0, 0xff, 0x67, 0x24, 0x3f, 0x2f, 0x60, 0x26, 0x96, 0xa3, 0x6d, 0x29, 0xa3, + 0x67, 0x95, 0x46, 0xc3, 0x4b, 0x91, 0xf2, 0x20, 0x27, 0x5a, 0xc1, 0x38, 0xef, 0xb3, 0x0a, 0x0c, + 0xd2, 0x2f, 0x64, 0x7f, 0x5d, 0x12, 0x1d, 0xa3, 0xa1, 0x62, 0x3c, 0xbd, 0x7d, 0x8c, 0xf7, 0xab, + 0x0c, 0x5d, 0xb6, 0x0e, 0x80, 0xfd, 0x31, 0xd9, 0xb9, 0xbe, 0x00, 0xf4, 0x21, 0xd9, 0x36, 0xbb, + 0xc4, 0xa2, 0xa8, 0x00, 0xd4, 0x6b, 0x79, 0xc7, 0x6b, 0xeb, 0xea, 0x50, 0x17, 0xe9, 0x23, 0xb2, + 0x3b, 0x63, 0x09, 0x8f, 0x98, 0x14, 0x2b, 0xe4, 0x86, 0x42, 0xee, 0x5c, 0x35, 0x0c, 0xb8, 0xff, + 0x91, 0x34, 0x4b, 0xcf, 0x72, 0x33, 0xd7, 0xba, 0x99, 0x4b, 0xef, 0x93, 0x56, 0x79, 0x09, 0x94, + 0x47, 0xdd, 0x6b, 0x96, 0xde, 0x74, 0xf4, 0xe6, 0x7c, 0x6e, 0x5b, 0x17, 0x73, 0xdb, 0xfa, 0x33, + 0xb7, 0xad, 0xef, 0x0b, 0xbb, 0x76, 0xb1, 0xb0, 0x6b, 0x3f, 0x17, 0x76, 0xed, 0xc3, 0xe3, 0x98, + 0xcb, 0xc9, 0x34, 0x70, 0x42, 0x91, 0xba, 0x08, 0xfc, 0xf0, 0xf2, 0x16, 0xd5, 0x1f, 0x75, 0x8d, + 0xee, 0x99, 0xf9, 0x7c, 0x5d, 0xf9, 0x39, 0x07, 0x0c, 0x1a, 0x0a, 0xf2, 0xe4, 0x6f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xe1, 0xc5, 0x36, 0x34, 0x25, 0x04, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AggregateExchangeRateVotes) > 0 { + for iNdEx := len(m.AggregateExchangeRateVotes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AggregateExchangeRateVotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } + if len(m.AggregateExchangeRatePrevotes) > 0 { + for iNdEx := len(m.AggregateExchangeRatePrevotes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AggregateExchangeRatePrevotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if len(m.MissCounters) > 0 { + for iNdEx := len(m.MissCounters) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MissCounters[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.ExchangeRates) > 0 { + for iNdEx := len(m.ExchangeRates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ExchangeRates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.FeederDelegations) > 0 { + for iNdEx := len(m.FeederDelegations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FeederDelegations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *FeederDelegation) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FeederDelegation) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FeederDelegation) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.FeederAddress) > 0 { + i -= len(m.FeederAddress) + copy(dAtA[i:], m.FeederAddress) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.FeederAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MissCounter) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MissCounter) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MissCounter) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MissCounter != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.MissCounter)) + i-- + dAtA[i] = 0x10 + } + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + if len(m.FeederDelegations) > 0 { + for _, e := range m.FeederDelegations { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.ExchangeRates) > 0 { + for _, e := range m.ExchangeRates { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.MissCounters) > 0 { + for _, e := range m.MissCounters { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.AggregateExchangeRatePrevotes) > 0 { + for _, e := range m.AggregateExchangeRatePrevotes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.AggregateExchangeRateVotes) > 0 { + for _, e := range m.AggregateExchangeRateVotes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *FeederDelegation) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FeederAddress) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + return n +} + +func (m *MissCounter) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if m.MissCounter != 0 { + n += 1 + sovGenesis(uint64(m.MissCounter)) + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeederDelegations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FeederDelegations = append(m.FeederDelegations, FeederDelegation{}) + if err := m.FeederDelegations[len(m.FeederDelegations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExchangeRates = append(m.ExchangeRates, ExchangeRateTuple{}) + if err := m.ExchangeRates[len(m.ExchangeRates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MissCounters", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MissCounters = append(m.MissCounters, MissCounter{}) + if err := m.MissCounters[len(m.MissCounters)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregateExchangeRatePrevotes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AggregateExchangeRatePrevotes = append(m.AggregateExchangeRatePrevotes, AggregateExchangeRatePrevote{}) + if err := m.AggregateExchangeRatePrevotes[len(m.AggregateExchangeRatePrevotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregateExchangeRateVotes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AggregateExchangeRateVotes = append(m.AggregateExchangeRateVotes, AggregateExchangeRateVote{}) + if err := m.AggregateExchangeRateVotes[len(m.AggregateExchangeRateVotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FeederDelegation) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FeederDelegation: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FeederDelegation: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeederAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FeederAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MissCounter) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MissCounter: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MissCounter: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MissCounter", wireType) + } + m.MissCounter = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MissCounter |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/oracle/types/genesis_test.go b/x/oracle/types/genesis_test.go new file mode 100755 index 0000000000..48a371d0a8 --- /dev/null +++ b/x/oracle/types/genesis_test.go @@ -0,0 +1,15 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGenesisValidation(t *testing.T) { + genState := DefaultGenesisState() + require.NoError(t, ValidateGenesis(genState)) + + genState.Params.VotePeriod = 0 + require.Error(t, ValidateGenesis(genState)) +} diff --git a/x/oracle/types/hash.go b/x/oracle/types/hash.go new file mode 100755 index 0000000000..ce5fc8cdc1 --- /dev/null +++ b/x/oracle/types/hash.go @@ -0,0 +1,120 @@ +package types + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + + "gopkg.in/yaml.v2" + + "github.com/tendermint/tendermint/crypto/tmhash" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ yaml.Marshaler = AggregateVoteHash{} + +// AggregateVoteHash is hash value to hide vote exchange rates +// which is formatted as hex string in SHA256("{salt}:{exchange rate}{denom},...,{exchange rate}{denom}:{voter}") +type AggregateVoteHash []byte + +// GetAggregateVoteHash computes hash value of ExchangeRateVote +// to avoid redundant DecCoins stringify operation, use string argument +func GetAggregateVoteHash(salt string, exchangeRatesStr string, voter sdk.ValAddress) AggregateVoteHash { + hash := tmhash.NewTruncated() + sourceStr := fmt.Sprintf("%s:%s:%s", salt, exchangeRatesStr, voter.String()) + _, err := hash.Write([]byte(sourceStr)) + if err != nil { + panic(err) + } + bz := hash.Sum(nil) + return bz +} + +// AggregateVoteHashFromHexString convert hex string to AggregateVoteHash +func AggregateVoteHashFromHexString(s string) (AggregateVoteHash, error) { + h, err := hex.DecodeString(s) + if err != nil { + return nil, err + } + + return h, nil +} + +// String implements fmt.Stringer interface +func (h AggregateVoteHash) String() string { + return hex.EncodeToString(h) +} + +// Equal does bytes equal check +func (h AggregateVoteHash) Equal(h2 AggregateVoteHash) bool { + return bytes.Equal(h, h2) +} + +// Empty check the name hash has zero length +func (h AggregateVoteHash) Empty() bool { + return len(h) == 0 +} + +// Bytes returns the raw address bytes. +func (h AggregateVoteHash) Bytes() []byte { + return h +} + +// Size returns the raw address bytes. +func (h AggregateVoteHash) Size() int { + return len(h) +} + +// Format implements the fmt.Formatter interface. +func (h AggregateVoteHash) Format(s fmt.State, verb rune) { + switch verb { + case 's': + _, _ = s.Write([]byte(h.String())) + case 'p': + _, _ = s.Write([]byte(fmt.Sprintf("%p", h))) + default: + _, _ = s.Write([]byte(fmt.Sprintf("%X", []byte(h)))) + } +} + +// Marshal returns the raw address bytes. It is needed for protobuf +// compatibility. +func (h AggregateVoteHash) Marshal() ([]byte, error) { + return h, nil +} + +// Unmarshal sets the address to the given data. It is needed for protobuf +// compatibility. +func (h *AggregateVoteHash) Unmarshal(data []byte) error { + *h = data + return nil +} + +// MarshalJSON marshals to JSON using Bech32. +func (h AggregateVoteHash) MarshalJSON() ([]byte, error) { + return json.Marshal(h.String()) +} + +// MarshalYAML marshals to YAML using Bech32. +func (h AggregateVoteHash) MarshalYAML() (interface{}, error) { + return h.String(), nil +} + +// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding. +func (h *AggregateVoteHash) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return err + } + + h2, err := AggregateVoteHashFromHexString(s) + if err != nil { + return err + } + + *h = h2 + return nil +} diff --git a/x/oracle/types/hash_test.go b/x/oracle/types/hash_test.go new file mode 100755 index 0000000000..8e3995d22c --- /dev/null +++ b/x/oracle/types/hash_test.go @@ -0,0 +1,41 @@ +package types + +import ( + "encoding/hex" + + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "testing" +) + +func TestAggregateVoteHash(t *testing.T) { + addrs := []sdk.AccAddress{ + sdk.AccAddress([]byte("addr1_______________")), + } + + aggregateVoteHash := GetAggregateVoteHash("salt", "100ukrw,200uusd", sdk.ValAddress(addrs[0])) + hexStr := hex.EncodeToString(aggregateVoteHash) + aggregateVoteHashRes, err := AggregateVoteHashFromHexString(hexStr) + require.NoError(t, err) + require.Equal(t, aggregateVoteHash, aggregateVoteHashRes) + require.True(t, aggregateVoteHash.Equal(aggregateVoteHash)) + require.True(t, AggregateVoteHash([]byte{}).Empty()) + + got, _ := yaml.Marshal(&aggregateVoteHash) + require.Equal(t, aggregateVoteHash.String()+"\n", string(got)) + + res := AggregateVoteHash{} + testMarshal(t, &aggregateVoteHash, &res, aggregateVoteHash.MarshalJSON, (&res).UnmarshalJSON) + testMarshal(t, &aggregateVoteHash, &res, aggregateVoteHash.Marshal, (&res).Unmarshal) +} + +func testMarshal(t *testing.T, original interface{}, res interface{}, marshal func() ([]byte, error), unmarshal func([]byte) error) { + bz, err := marshal() + require.Nil(t, err) + err = unmarshal(bz) + require.Nil(t, err) + require.Equal(t, original, res) +} diff --git a/x/oracle/types/keys.go b/x/oracle/types/keys.go new file mode 100755 index 0000000000..99c7ea5948 --- /dev/null +++ b/x/oracle/types/keys.go @@ -0,0 +1,78 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +const ( + // ModuleName is the name of the oracle module + ModuleName = "oracle" + + // StoreKey is the string store representation + StoreKey = ModuleName + + // RouterKey is the msg router key for the oracle module + RouterKey = ModuleName + + // QuerierRoute is the query router key for the oracle module + QuerierRoute = ModuleName +) + +// Keys for oracle store +// Items are stored with the following key: values +// +// - 0x01: sdk.Dec +// +// - 0x02: accAddress +// +// - 0x03: int64 +// +// - 0x04: AggregateExchangeRatePrevote +// +// - 0x05: AggregateExchangeRateVote +// +// - 0x06: sdk.Dec +var ( + // Keys for store prefixes + ExchangeRateKey = []byte{0x01} // prefix for each key to a rate + FeederDelegationKey = []byte{0x02} // prefix for each key to a feeder delegation + MissCounterKey = []byte{0x03} // prefix for each key to a miss counter + AggregateExchangeRatePrevoteKey = []byte{0x04} // prefix for each key to a aggregate prevote + AggregateExchangeRateVoteKey = []byte{0x05} // prefix for each key to a aggregate vote + VoteTargetKey = []byte{0x06} // prefix for each key to a vote target +) + +// GetExchangeRateKey - stored by *denom* +func GetExchangeRateKey(denom string) []byte { + return append(ExchangeRateKey, []byte(denom)...) +} + +// GetFeederDelegationKey - stored by *Validator* address +func GetFeederDelegationKey(v sdk.ValAddress) []byte { + return append(FeederDelegationKey, address.MustLengthPrefix(v)...) +} + +// GetMissCounterKey - stored by *Validator* address +func GetMissCounterKey(v sdk.ValAddress) []byte { + return append(MissCounterKey, address.MustLengthPrefix(v)...) +} + +// GetAggregateExchangeRatePrevoteKey - stored by *Validator* address +func GetAggregateExchangeRatePrevoteKey(v sdk.ValAddress) []byte { + return append(AggregateExchangeRatePrevoteKey, address.MustLengthPrefix(v)...) +} + +// GetAggregateExchangeRateVoteKey - stored by *Validator* address +func GetAggregateExchangeRateVoteKey(v sdk.ValAddress) []byte { + return append(AggregateExchangeRateVoteKey, address.MustLengthPrefix(v)...) +} + +func GetVoteTargetKey(d string) []byte { + return append(VoteTargetKey, []byte(d)...) +} + +func ExtractDenomFromVoteTargetKey(key []byte) (denom string) { + denom = string(key[1:]) + return +} diff --git a/x/oracle/types/msgs.go b/x/oracle/types/msgs.go new file mode 100755 index 0000000000..cb92bfb575 --- /dev/null +++ b/x/oracle/types/msgs.go @@ -0,0 +1,194 @@ +package types + +import ( + "github.com/tendermint/tendermint/crypto/tmhash" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// ensure Msg interface compliance at compile time +var ( + _ sdk.Msg = &MsgDelegateFeedConsent{} + _ sdk.Msg = &MsgAggregateExchangeRatePrevote{} + _ sdk.Msg = &MsgAggregateExchangeRateVote{} +) + +// oracle message types +const ( + TypeMsgDelegateFeedConsent = "delegate_feeder" + TypeMsgAggregateExchangeRatePrevote = "aggregate_exchange_rate_prevote" + TypeMsgAggregateExchangeRateVote = "aggregate_exchange_rate_vote" +) + +//------------------------------------------------- +//------------------------------------------------- + +// NewMsgAggregateExchangeRatePrevote returns MsgAggregateExchangeRatePrevote instance +func NewMsgAggregateExchangeRatePrevote(hash AggregateVoteHash, feeder sdk.AccAddress, validator sdk.ValAddress) *MsgAggregateExchangeRatePrevote { + return &MsgAggregateExchangeRatePrevote{ + Hash: hash.String(), + Feeder: feeder.String(), + Validator: validator.String(), + } +} + +// Route implements sdk.Msg +func (msg MsgAggregateExchangeRatePrevote) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgAggregateExchangeRatePrevote) Type() string { return TypeMsgAggregateExchangeRatePrevote } + +// GetSignBytes implements sdk.Msg +func (msg MsgAggregateExchangeRatePrevote) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgAggregateExchangeRatePrevote) GetSigners() []sdk.AccAddress { + feeder, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{feeder} +} + +// ValidateBasic Implements sdk.Msg +func (msg MsgAggregateExchangeRatePrevote) ValidateBasic() error { + + _, err := AggregateVoteHashFromHexString(msg.Hash) + if err != nil { + return sdkerrors.Wrapf(ErrInvalidHash, "Invalid vote hash (%s)", err) + } + + // HEX encoding doubles the hash length + if len(msg.Hash) != tmhash.TruncatedSize*2 { + return ErrInvalidHashLength + } + + _, err = sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid feeder address (%s)", err) + } + + _, err = sdk.ValAddressFromBech32(msg.Validator) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid operator address (%s)", err) + } + + return nil +} + +// NewMsgAggregateExchangeRateVote returns MsgAggregateExchangeRateVote instance +func NewMsgAggregateExchangeRateVote(salt string, exchangeRates string, feeder sdk.AccAddress, validator sdk.ValAddress) *MsgAggregateExchangeRateVote { + return &MsgAggregateExchangeRateVote{ + Salt: salt, + ExchangeRates: exchangeRates, + Feeder: feeder.String(), + Validator: validator.String(), + } +} + +// Route implements sdk.Msg +func (msg MsgAggregateExchangeRateVote) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgAggregateExchangeRateVote) Type() string { return TypeMsgAggregateExchangeRateVote } + +// GetSignBytes implements sdk.Msg +func (msg MsgAggregateExchangeRateVote) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgAggregateExchangeRateVote) GetSigners() []sdk.AccAddress { + feeder, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{feeder} +} + +// ValidateBasic implements sdk.Msg +func (msg MsgAggregateExchangeRateVote) ValidateBasic() error { + + _, err := sdk.AccAddressFromBech32(msg.Feeder) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid feeder address (%s)", err) + } + + _, err = sdk.ValAddressFromBech32(msg.Validator) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid operator address (%s)", err) + } + + if l := len(msg.ExchangeRates); l == 0 { + return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "must provide at least one oracle exchange rate") + } else if l > 4096 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "exchange rates string can not exceed 4096 characters") + } + + exchangeRates, err := ParseExchangeRateTuples(msg.ExchangeRates) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "failed to parse exchange rates string cause: "+err.Error()) + } + + for _, exchangeRate := range exchangeRates { + // Check overflow bit length + if exchangeRate.ExchangeRate.BigInt().BitLen() > 255+sdk.DecimalPrecisionBits { + return sdkerrors.Wrap(ErrInvalidExchangeRate, "overflow") + } + } + + if len(msg.Salt) > 4 || len(msg.Salt) < 1 { + return sdkerrors.Wrap(ErrInvalidSaltLength, "salt length must be [1, 4]") + } + + return nil +} + +// NewMsgDelegateFeedConsent creates a MsgDelegateFeedConsent instance +func NewMsgDelegateFeedConsent(operatorAddress sdk.ValAddress, feederAddress sdk.AccAddress) *MsgDelegateFeedConsent { + return &MsgDelegateFeedConsent{ + Operator: operatorAddress.String(), + Delegate: feederAddress.String(), + } +} + +// Route implements sdk.Msg +func (msg MsgDelegateFeedConsent) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgDelegateFeedConsent) Type() string { return TypeMsgDelegateFeedConsent } + +// GetSignBytes implements sdk.Msg +func (msg MsgDelegateFeedConsent) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgDelegateFeedConsent) GetSigners() []sdk.AccAddress { + operator, err := sdk.ValAddressFromBech32(msg.Operator) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{sdk.AccAddress(operator)} +} + +// ValidateBasic implements sdk.Msg +func (msg MsgDelegateFeedConsent) ValidateBasic() error { + _, err := sdk.ValAddressFromBech32(msg.Operator) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid operator address (%s)", err) + } + + _, err = sdk.AccAddressFromBech32(msg.Delegate) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid delegate address (%s)", err) + } + + return nil +} diff --git a/x/oracle/types/msgs_test.go b/x/oracle/types/msgs_test.go new file mode 100755 index 0000000000..6ba2c15436 --- /dev/null +++ b/x/oracle/types/msgs_test.go @@ -0,0 +1,101 @@ +package types + +import ( + "testing" + + "github.com/sei-protocol/sei-chain/x/oracle/utils" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestMsgFeederDelegation(t *testing.T) { + addrs := []sdk.AccAddress{ + sdk.AccAddress([]byte("addr1_______________")), + sdk.AccAddress([]byte("addr2_______________")), + } + + tests := []struct { + delegator sdk.ValAddress + delegate sdk.AccAddress + expectPass bool + }{ + {sdk.ValAddress(addrs[0]), addrs[1], true}, + {sdk.ValAddress{}, addrs[1], false}, + {sdk.ValAddress(addrs[0]), sdk.AccAddress{}, false}, + {nil, nil, false}, + } + + for i, tc := range tests { + msg := NewMsgDelegateFeedConsent(tc.delegator, tc.delegate) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", i) + } + } +} + +func TestMsgAggregateExchangeRatePrevote(t *testing.T) { + addrs := []sdk.AccAddress{ + sdk.AccAddress([]byte("addr1_______________")), + } + + exchangeRates := sdk.DecCoins{sdk.NewDecCoinFromDec(utils.MicroAtomDenom, sdk.OneDec())} + bz := GetAggregateVoteHash("1", exchangeRates.String(), sdk.ValAddress(addrs[0])) + + tests := []struct { + hash AggregateVoteHash + exchangeRates sdk.DecCoins + voter sdk.AccAddress + expectPass bool + }{ + {bz, exchangeRates, addrs[0], true}, + {bz[1:], exchangeRates, addrs[0], false}, + {bz, exchangeRates, sdk.AccAddress{}, false}, + {AggregateVoteHash{}, exchangeRates, addrs[0], false}, + } + + for i, tc := range tests { + msg := NewMsgAggregateExchangeRatePrevote(tc.hash, tc.voter, sdk.ValAddress(tc.voter)) + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} + +func TestMsgAggregateExchangeRateVote(t *testing.T) { + addrs := []sdk.AccAddress{ + sdk.AccAddress([]byte("addr1_______________")), + } + + invalidExchangeRates := "a,b" + exchangeRates := "1.0foo,1232.132bar" + abstainExchangeRates := "0.0foo,1232.132bar" + overFlowExchangeRates := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0foo,1232.132bar" + + tests := []struct { + voter sdk.AccAddress + salt string + exchangeRates string + expectPass bool + }{ + {addrs[0], "123", exchangeRates, true}, + {addrs[0], "123", invalidExchangeRates, false}, + {addrs[0], "123", abstainExchangeRates, true}, + {addrs[0], "123", overFlowExchangeRates, false}, + {sdk.AccAddress{}, "123", exchangeRates, false}, + {addrs[0], "", exchangeRates, false}, + } + + for i, tc := range tests { + msg := NewMsgAggregateExchangeRateVote(tc.salt, tc.exchangeRates, tc.voter, sdk.ValAddress(tc.voter)) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", i) + } + } +} diff --git a/x/oracle/types/oracle.pb.go b/x/oracle/types/oracle.pb.go new file mode 100644 index 0000000000..979c0eca03 --- /dev/null +++ b/x/oracle/types/oracle.pb.go @@ -0,0 +1,1488 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/oracle.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type Params struct { + VotePeriod uint64 `protobuf:"varint,1,opt,name=vote_period,json=votePeriod,proto3" json:"vote_period,omitempty" yaml:"vote_period"` + VoteThreshold github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=vote_threshold,json=voteThreshold,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"vote_threshold" yaml:"vote_threshold"` + RewardBand github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=reward_band,json=rewardBand,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"reward_band" yaml:"reward_band"` + Whitelist DenomList `protobuf:"bytes,4,rep,name=whitelist,proto3,castrepeated=DenomList" json:"whitelist" yaml:"whitelist"` + SlashFraction github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction,json=slashFraction,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction" yaml:"slash_fraction"` + SlashWindow uint64 `protobuf:"varint,6,opt,name=slash_window,json=slashWindow,proto3" json:"slash_window,omitempty" yaml:"slash_window"` + MinValidPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=min_valid_per_window,json=minValidPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_valid_per_window" yaml:"min_valid_per_window"` +} + +func (m *Params) Reset() { *m = Params{} } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_dc470b50b143d488, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetVotePeriod() uint64 { + if m != nil { + return m.VotePeriod + } + return 0 +} + +func (m *Params) GetWhitelist() DenomList { + if m != nil { + return m.Whitelist + } + return nil +} + +func (m *Params) GetSlashWindow() uint64 { + if m != nil { + return m.SlashWindow + } + return 0 +} + +type Denom struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` +} + +func (m *Denom) Reset() { *m = Denom{} } +func (*Denom) ProtoMessage() {} +func (*Denom) Descriptor() ([]byte, []int) { + return fileDescriptor_dc470b50b143d488, []int{1} +} +func (m *Denom) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Denom) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Denom.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Denom) XXX_Merge(src proto.Message) { + xxx_messageInfo_Denom.Merge(m, src) +} +func (m *Denom) XXX_Size() int { + return m.Size() +} +func (m *Denom) XXX_DiscardUnknown() { + xxx_messageInfo_Denom.DiscardUnknown(m) +} + +var xxx_messageInfo_Denom proto.InternalMessageInfo + +type AggregateExchangeRatePrevote struct { + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty" yaml:"hash"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty" yaml:"voter"` + SubmitBlock uint64 `protobuf:"varint,3,opt,name=submit_block,json=submitBlock,proto3" json:"submit_block,omitempty" yaml:"submit_block"` +} + +func (m *AggregateExchangeRatePrevote) Reset() { *m = AggregateExchangeRatePrevote{} } +func (*AggregateExchangeRatePrevote) ProtoMessage() {} +func (*AggregateExchangeRatePrevote) Descriptor() ([]byte, []int) { + return fileDescriptor_dc470b50b143d488, []int{2} +} +func (m *AggregateExchangeRatePrevote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AggregateExchangeRatePrevote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AggregateExchangeRatePrevote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AggregateExchangeRatePrevote) XXX_Merge(src proto.Message) { + xxx_messageInfo_AggregateExchangeRatePrevote.Merge(m, src) +} +func (m *AggregateExchangeRatePrevote) XXX_Size() int { + return m.Size() +} +func (m *AggregateExchangeRatePrevote) XXX_DiscardUnknown() { + xxx_messageInfo_AggregateExchangeRatePrevote.DiscardUnknown(m) +} + +var xxx_messageInfo_AggregateExchangeRatePrevote proto.InternalMessageInfo + +type AggregateExchangeRateVote struct { + ExchangeRateTuples ExchangeRateTuples `protobuf:"bytes,1,rep,name=exchange_rate_tuples,json=exchangeRateTuples,proto3,castrepeated=ExchangeRateTuples" json:"exchange_rate_tuples" yaml:"exchange_rate_tuples"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty" yaml:"voter"` +} + +func (m *AggregateExchangeRateVote) Reset() { *m = AggregateExchangeRateVote{} } +func (*AggregateExchangeRateVote) ProtoMessage() {} +func (*AggregateExchangeRateVote) Descriptor() ([]byte, []int) { + return fileDescriptor_dc470b50b143d488, []int{3} +} +func (m *AggregateExchangeRateVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AggregateExchangeRateVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AggregateExchangeRateVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AggregateExchangeRateVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_AggregateExchangeRateVote.Merge(m, src) +} +func (m *AggregateExchangeRateVote) XXX_Size() int { + return m.Size() +} +func (m *AggregateExchangeRateVote) XXX_DiscardUnknown() { + xxx_messageInfo_AggregateExchangeRateVote.DiscardUnknown(m) +} + +var xxx_messageInfo_AggregateExchangeRateVote proto.InternalMessageInfo + +type ExchangeRateTuple struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty" yaml:"denom"` + ExchangeRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=exchange_rate,json=exchangeRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"exchange_rate" yaml:"exchange_rate"` +} + +func (m *ExchangeRateTuple) Reset() { *m = ExchangeRateTuple{} } +func (*ExchangeRateTuple) ProtoMessage() {} +func (*ExchangeRateTuple) Descriptor() ([]byte, []int) { + return fileDescriptor_dc470b50b143d488, []int{4} +} +func (m *ExchangeRateTuple) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExchangeRateTuple) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExchangeRateTuple.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExchangeRateTuple) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExchangeRateTuple.Merge(m, src) +} +func (m *ExchangeRateTuple) XXX_Size() int { + return m.Size() +} +func (m *ExchangeRateTuple) XXX_DiscardUnknown() { + xxx_messageInfo_ExchangeRateTuple.DiscardUnknown(m) +} + +var xxx_messageInfo_ExchangeRateTuple proto.InternalMessageInfo + +func init() { + proto.RegisterType((*Params)(nil), "seiprotocol.seichain.oracle.Params") + proto.RegisterType((*Denom)(nil), "seiprotocol.seichain.oracle.Denom") + proto.RegisterType((*AggregateExchangeRatePrevote)(nil), "seiprotocol.seichain.oracle.AggregateExchangeRatePrevote") + proto.RegisterType((*AggregateExchangeRateVote)(nil), "seiprotocol.seichain.oracle.AggregateExchangeRateVote") + proto.RegisterType((*ExchangeRateTuple)(nil), "seiprotocol.seichain.oracle.ExchangeRateTuple") +} + +func init() { proto.RegisterFile("oracle/oracle.proto", fileDescriptor_dc470b50b143d488) } + +var fileDescriptor_dc470b50b143d488 = []byte{ + // 700 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x31, 0x6f, 0xd3, 0x40, + 0x18, 0x8d, 0x69, 0x53, 0xc8, 0x25, 0x85, 0xd6, 0x0d, 0x10, 0x5a, 0x14, 0x57, 0x87, 0xa8, 0xba, + 0xd4, 0xa6, 0x30, 0x20, 0xb2, 0x61, 0x95, 0x22, 0x21, 0x90, 0xa2, 0x53, 0x55, 0x24, 0x96, 0xe8, + 0x62, 0x1f, 0xf6, 0xa9, 0xb6, 0x2f, 0xba, 0x73, 0x9b, 0x76, 0x61, 0x66, 0x64, 0x44, 0x62, 0xe9, + 0xcc, 0x0e, 0xfc, 0x85, 0x8e, 0x1d, 0x11, 0x83, 0x41, 0xed, 0xc2, 0x86, 0x94, 0x5f, 0x80, 0xee, + 0xce, 0x6d, 0x9d, 0x26, 0xaa, 0xa8, 0x98, 0xec, 0xf7, 0xbd, 0xbb, 0xf7, 0x3d, 0x7f, 0xdf, 0x4b, + 0xc0, 0x1c, 0xe3, 0xd8, 0x8b, 0x88, 0xa3, 0x1f, 0x76, 0x8f, 0xb3, 0x94, 0x99, 0x0b, 0x82, 0x50, + 0xf5, 0xe6, 0xb1, 0xc8, 0x16, 0x84, 0x7a, 0x21, 0xa6, 0x89, 0xad, 0x8f, 0xcc, 0xd7, 0x03, 0x16, + 0x30, 0xc5, 0x3a, 0xf2, 0x4d, 0x5f, 0x99, 0x6f, 0x7a, 0x4c, 0xc4, 0x4c, 0x38, 0x5d, 0x2c, 0x88, + 0xb3, 0xb3, 0xda, 0x25, 0x29, 0x5e, 0x75, 0x3c, 0x46, 0x13, 0xcd, 0xc3, 0x6f, 0x65, 0x30, 0xd5, + 0xc6, 0x1c, 0xc7, 0xc2, 0x7c, 0x0c, 0xaa, 0x3b, 0x2c, 0x25, 0x9d, 0x1e, 0xe1, 0x94, 0xf9, 0x0d, + 0x63, 0xd1, 0x58, 0x9e, 0x74, 0x6f, 0x0d, 0x32, 0xcb, 0xdc, 0xc3, 0x71, 0xd4, 0x82, 0x05, 0x12, + 0x22, 0x20, 0x51, 0x5b, 0x01, 0x33, 0x01, 0xd7, 0x15, 0x97, 0x86, 0x9c, 0x88, 0x90, 0x45, 0x7e, + 0xe3, 0xca, 0xa2, 0xb1, 0x5c, 0x71, 0x9f, 0x1f, 0x64, 0x56, 0xe9, 0x47, 0x66, 0x2d, 0x05, 0x34, + 0x0d, 0xb7, 0xbb, 0xb6, 0xc7, 0x62, 0x27, 0xb7, 0xa3, 0x1f, 0x2b, 0xc2, 0xdf, 0x72, 0xd2, 0xbd, + 0x1e, 0x11, 0xf6, 0x1a, 0xf1, 0x06, 0x99, 0x75, 0xb3, 0xd0, 0xe9, 0x54, 0x0d, 0xa2, 0x69, 0x59, + 0xd8, 0x38, 0xc1, 0x26, 0x01, 0x55, 0x4e, 0xfa, 0x98, 0xfb, 0x9d, 0x2e, 0x4e, 0xfc, 0xc6, 0x84, + 0x6a, 0xb6, 0x76, 0xe9, 0x66, 0xf9, 0x67, 0x15, 0xa4, 0x20, 0x02, 0x1a, 0xb9, 0x38, 0xf1, 0xcd, + 0x00, 0x54, 0xfa, 0x21, 0x4d, 0x49, 0x44, 0x45, 0xda, 0x98, 0x5c, 0x9c, 0x58, 0xae, 0x3e, 0x84, + 0xf6, 0x05, 0x1b, 0xb0, 0xd7, 0x48, 0xc2, 0x62, 0xf7, 0xbe, 0x34, 0x32, 0xc8, 0xac, 0x19, 0x2d, + 0x7f, 0x2a, 0x01, 0x3f, 0xff, 0xb4, 0x2a, 0xea, 0xc8, 0x4b, 0x2a, 0x52, 0x74, 0xa6, 0x2d, 0xe7, + 0x27, 0x22, 0x2c, 0xc2, 0xce, 0x5b, 0x8e, 0xbd, 0x94, 0xb2, 0xa4, 0x51, 0xfe, 0xbf, 0xf9, 0x0d, + 0xab, 0x41, 0x34, 0xad, 0x0a, 0xeb, 0x39, 0x36, 0x5b, 0xa0, 0xa6, 0x4f, 0xf4, 0x69, 0xe2, 0xb3, + 0x7e, 0x63, 0x4a, 0x6d, 0xfa, 0xf6, 0x20, 0xb3, 0xe6, 0x8a, 0xf7, 0x35, 0x0b, 0x51, 0x55, 0xc1, + 0xd7, 0x0a, 0x99, 0xef, 0x40, 0x3d, 0xa6, 0x49, 0x67, 0x07, 0x47, 0xd4, 0x97, 0x61, 0x38, 0xd1, + 0xb8, 0xaa, 0x1c, 0xbf, 0xba, 0xb4, 0xe3, 0x05, 0xdd, 0x71, 0x9c, 0x26, 0x44, 0xb3, 0x31, 0x4d, + 0x36, 0x65, 0xb5, 0x4d, 0xb8, 0xee, 0xdf, 0xba, 0xf6, 0x71, 0xdf, 0x2a, 0xfd, 0xde, 0xb7, 0x0c, + 0xd8, 0x02, 0x65, 0x35, 0x4d, 0xf3, 0x1e, 0x98, 0x4c, 0x70, 0x4c, 0x54, 0x60, 0x2b, 0xee, 0x8d, + 0x41, 0x66, 0x55, 0xb5, 0xa8, 0xac, 0x42, 0xa4, 0xc8, 0x56, 0xed, 0xfd, 0xbe, 0x55, 0xca, 0xef, + 0x96, 0xe0, 0x17, 0x03, 0xdc, 0x7d, 0x1a, 0x04, 0x9c, 0x04, 0x38, 0x25, 0xcf, 0x76, 0xbd, 0x10, + 0x27, 0x01, 0x41, 0x38, 0x25, 0x6d, 0x4e, 0x64, 0xd6, 0xa4, 0x66, 0x88, 0x45, 0x38, 0xaa, 0x29, + 0xab, 0x10, 0x29, 0xd2, 0x5c, 0x02, 0x65, 0x79, 0x98, 0xe7, 0x71, 0x9f, 0x19, 0x64, 0x56, 0xed, + 0x2c, 0xc0, 0x1c, 0x22, 0x4d, 0xab, 0x79, 0x6f, 0x77, 0x63, 0x9a, 0x76, 0xba, 0x11, 0xf3, 0xb6, + 0x54, 0x60, 0x87, 0xe7, 0x5d, 0x60, 0xe5, 0xbc, 0x15, 0x74, 0x25, 0x3a, 0xe7, 0xfb, 0x8f, 0x01, + 0xee, 0x8c, 0xf5, 0xbd, 0x29, 0x4d, 0x7f, 0x32, 0x40, 0x9d, 0xe4, 0xc5, 0x0e, 0xc7, 0xf2, 0x37, + 0xb4, 0xdd, 0x8b, 0x88, 0x68, 0x18, 0x2a, 0xbc, 0xf6, 0x85, 0xe1, 0x2d, 0xaa, 0x6d, 0xc8, 0x6b, + 0xee, 0x93, 0x3c, 0xc8, 0xf9, 0x8a, 0xc6, 0x29, 0xcb, 0x4c, 0x9b, 0x23, 0x37, 0x05, 0x32, 0xc9, + 0x48, 0xed, 0x5f, 0xa7, 0x75, 0xee, 0x8b, 0xbf, 0x1a, 0x60, 0x76, 0xa4, 0x81, 0xd4, 0xf2, 0xe5, + 0xee, 0xf3, 0xfd, 0x14, 0xb4, 0x54, 0x19, 0x22, 0x4d, 0x9b, 0x5b, 0x60, 0x7a, 0xc8, 0x76, 0xde, + 0x7b, 0xfd, 0xd2, 0x31, 0xad, 0x8f, 0x99, 0x01, 0x44, 0xb5, 0xe2, 0x67, 0x0e, 0x1b, 0x77, 0x5f, + 0x1c, 0x1c, 0x35, 0x8d, 0xc3, 0xa3, 0xa6, 0xf1, 0xeb, 0xa8, 0x69, 0x7c, 0x38, 0x6e, 0x96, 0x0e, + 0x8f, 0x9b, 0xa5, 0xef, 0xc7, 0xcd, 0xd2, 0x9b, 0x07, 0x85, 0xae, 0x82, 0xd0, 0x95, 0x93, 0x95, + 0x28, 0xa0, 0x76, 0xe2, 0xec, 0xe6, 0xff, 0xfb, 0xda, 0x43, 0x77, 0x4a, 0x1d, 0x79, 0xf4, 0x37, + 0x00, 0x00, 0xff, 0xff, 0xc9, 0x7e, 0x83, 0xc5, 0x15, 0x06, 0x00, 0x00, +} + +func (this *Params) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Params) + if !ok { + that2, ok := that.(Params) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.VotePeriod != that1.VotePeriod { + return false + } + if !this.VoteThreshold.Equal(that1.VoteThreshold) { + return false + } + if !this.RewardBand.Equal(that1.RewardBand) { + return false + } + if len(this.Whitelist) != len(that1.Whitelist) { + return false + } + for i := range this.Whitelist { + if !this.Whitelist[i].Equal(&that1.Whitelist[i]) { + return false + } + } + if !this.SlashFraction.Equal(that1.SlashFraction) { + return false + } + if this.SlashWindow != that1.SlashWindow { + return false + } + if !this.MinValidPerWindow.Equal(that1.MinValidPerWindow) { + return false + } + return true +} +func (m *Params) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.MinValidPerWindow.Size() + i -= size + if _, err := m.MinValidPerWindow.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + if m.SlashWindow != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.SlashWindow)) + i-- + dAtA[i] = 0x30 + } + { + size := m.SlashFraction.Size() + i -= size + if _, err := m.SlashFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.Whitelist) > 0 { + for iNdEx := len(m.Whitelist) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Whitelist[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size := m.RewardBand.Size() + i -= size + if _, err := m.RewardBand.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size := m.VoteThreshold.Size() + i -= size + if _, err := m.VoteThreshold.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.VotePeriod != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.VotePeriod)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Denom) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Denom) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Denom) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AggregateExchangeRatePrevote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AggregateExchangeRatePrevote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AggregateExchangeRatePrevote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SubmitBlock != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.SubmitBlock)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AggregateExchangeRateVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AggregateExchangeRateVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AggregateExchangeRateVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if len(m.ExchangeRateTuples) > 0 { + for iNdEx := len(m.ExchangeRateTuples) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ExchangeRateTuples[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ExchangeRateTuple) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExchangeRateTuple) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExchangeRateTuple) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.ExchangeRate.Size() + i -= size + if _, err := m.ExchangeRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintOracle(dAtA []byte, offset int, v uint64) int { + offset -= sovOracle(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VotePeriod != 0 { + n += 1 + sovOracle(uint64(m.VotePeriod)) + } + l = m.VoteThreshold.Size() + n += 1 + l + sovOracle(uint64(l)) + l = m.RewardBand.Size() + n += 1 + l + sovOracle(uint64(l)) + if len(m.Whitelist) > 0 { + for _, e := range m.Whitelist { + l = e.Size() + n += 1 + l + sovOracle(uint64(l)) + } + } + l = m.SlashFraction.Size() + n += 1 + l + sovOracle(uint64(l)) + if m.SlashWindow != 0 { + n += 1 + sovOracle(uint64(m.SlashWindow)) + } + l = m.MinValidPerWindow.Size() + n += 1 + l + sovOracle(uint64(l)) + return n +} + +func (m *Denom) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + return n +} + +func (m *AggregateExchangeRatePrevote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + if m.SubmitBlock != 0 { + n += 1 + sovOracle(uint64(m.SubmitBlock)) + } + return n +} + +func (m *AggregateExchangeRateVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ExchangeRateTuples) > 0 { + for _, e := range m.ExchangeRateTuples { + l = e.Size() + n += 1 + l + sovOracle(uint64(l)) + } + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + return n +} + +func (m *ExchangeRateTuple) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + l = m.ExchangeRate.Size() + n += 1 + l + sovOracle(uint64(l)) + return n +} + +func sovOracle(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozOracle(x uint64) (n int) { + return sovOracle(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VotePeriod", wireType) + } + m.VotePeriod = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VotePeriod |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteThreshold", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VoteThreshold.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardBand", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.RewardBand.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Whitelist", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Whitelist = append(m.Whitelist, Denom{}) + if err := m.Whitelist[len(m.Whitelist)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SlashFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashWindow", wireType) + } + m.SlashWindow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SlashWindow |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinValidPerWindow", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinValidPerWindow.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Denom) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Denom: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Denom: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AggregateExchangeRatePrevote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AggregateExchangeRatePrevote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AggregateExchangeRatePrevote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubmitBlock", wireType) + } + m.SubmitBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubmitBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AggregateExchangeRateVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AggregateExchangeRateVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AggregateExchangeRateVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRateTuples", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExchangeRateTuples = append(m.ExchangeRateTuples, ExchangeRateTuple{}) + if err := m.ExchangeRateTuples[len(m.ExchangeRateTuples)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExchangeRateTuple) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExchangeRateTuple: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExchangeRateTuple: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExchangeRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipOracle(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowOracle + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowOracle + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowOracle + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthOracle + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupOracle + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthOracle + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthOracle = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowOracle = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupOracle = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go new file mode 100755 index 0000000000..7b59b84d69 --- /dev/null +++ b/x/oracle/types/params.go @@ -0,0 +1,223 @@ +package types + +import ( + "fmt" + + "gopkg.in/yaml.v2" + + "github.com/sei-protocol/sei-chain/x/oracle/utils" + + sdk "github.com/cosmos/cosmos-sdk/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +// Parameter keys +var ( + KeyVotePeriod = []byte("VotePeriod") + KeyVoteThreshold = []byte("VoteThreshold") + KeyRewardBand = []byte("RewardBand") + KeyWhitelist = []byte("Whitelist") + KeySlashFraction = []byte("SlashFraction") + KeySlashWindow = []byte("SlashWindow") + KeyMinValidPerWindow = []byte("MinValidPerWindow") +) + +// Default parameter values +const ( + DefaultVotePeriod = utils.BlocksPerMinute / 2 // 30 seconds + DefaultSlashWindow = utils.BlocksPerWeek // window for a week +) + +// Default parameter values +var ( + DefaultVoteThreshold = sdk.NewDecWithPrec(50, 2) // 50% + DefaultRewardBand = sdk.NewDecWithPrec(2, 2) // 2% (-1, 1) + DefaultWhitelist = DenomList{ + {Name: utils.MicroAtomDenom}, + {Name: utils.MicroUsdcDenom}, + } + DefaultSlashFraction = sdk.NewDecWithPrec(1, 4) // 0.01% + DefaultMinValidPerWindow = sdk.NewDecWithPrec(5, 2) // 5% +) + +var _ paramstypes.ParamSet = &Params{} + +// DefaultParams creates default oracle module parameters +func DefaultParams() Params { + return Params{ + VotePeriod: DefaultVotePeriod, + VoteThreshold: DefaultVoteThreshold, + RewardBand: DefaultRewardBand, + Whitelist: DefaultWhitelist, + SlashFraction: DefaultSlashFraction, + SlashWindow: DefaultSlashWindow, + MinValidPerWindow: DefaultMinValidPerWindow, + } +} + +// ParamKeyTable returns the parameter key table. +func ParamKeyTable() paramstypes.KeyTable { + return paramstypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// ParamSetPairs implements the ParamSet interface and returns all the key/value pairs +// pairs of oracle module's parameters. +func (p *Params) ParamSetPairs() paramstypes.ParamSetPairs { + return paramstypes.ParamSetPairs{ + paramstypes.NewParamSetPair(KeyVotePeriod, &p.VotePeriod, validateVotePeriod), + paramstypes.NewParamSetPair(KeyVoteThreshold, &p.VoteThreshold, validateVoteThreshold), + paramstypes.NewParamSetPair(KeyRewardBand, &p.RewardBand, validateRewardBand), + paramstypes.NewParamSetPair(KeyWhitelist, &p.Whitelist, validateWhitelist), + paramstypes.NewParamSetPair(KeySlashFraction, &p.SlashFraction, validateSlashFraction), + paramstypes.NewParamSetPair(KeySlashWindow, &p.SlashWindow, validateSlashWindow), + paramstypes.NewParamSetPair(KeyMinValidPerWindow, &p.MinValidPerWindow, validateMinValidPerWindow), + } +} + +// String implements fmt.Stringer interface +func (p Params) String() string { + out, _ := yaml.Marshal(p) + return string(out) +} + +// Validate performs basic validation on oracle parameters. +func (p Params) Validate() error { + if p.VotePeriod == 0 { + return fmt.Errorf("oracle parameter VotePeriod must be > 0, is %d", p.VotePeriod) + } + if p.VoteThreshold.LTE(sdk.NewDecWithPrec(33, 2)) { + return fmt.Errorf("oracle parameter VoteThreshold must be greater than 33 percent") + } + + if p.RewardBand.GT(sdk.OneDec()) || p.RewardBand.IsNegative() { + return fmt.Errorf("oracle parameter RewardBand must be between [0, 1]") + } + + if p.SlashFraction.GT(sdk.OneDec()) || p.SlashFraction.IsNegative() { + return fmt.Errorf("oracle parameter SlashFraction must be between [0, 1]") + } + + if p.SlashWindow < p.VotePeriod { + return fmt.Errorf("oracle parameter SlashWindow must be greater than or equal with VotePeriod") + } + + if p.MinValidPerWindow.GT(sdk.OneDec()) || p.MinValidPerWindow.IsNegative() { + return fmt.Errorf("oracle parameter MinValidPerWindow must be between [0, 1]") + } + + for _, denom := range p.Whitelist { + if len(denom.Name) == 0 { + return fmt.Errorf("oracle parameter Whitelist Denom must have name") + } + } + return nil +} + +func validateVotePeriod(i interface{}) error { + v, ok := i.(uint64) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v == 0 { + return fmt.Errorf("vote period must be positive: %d", v) + } + + return nil +} + +func validateVoteThreshold(i interface{}) error { + v, ok := i.(sdk.Dec) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v.LT(sdk.NewDecWithPrec(33, 2)) { + return fmt.Errorf("vote threshold must be bigger than 33%%: %s", v) + } + + if v.GT(sdk.OneDec()) { + return fmt.Errorf("vote threshold too large: %s", v) + } + + return nil +} + +func validateRewardBand(i interface{}) error { + v, ok := i.(sdk.Dec) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v.IsNegative() { + return fmt.Errorf("reward band must be positive: %s", v) + } + + if v.GT(sdk.OneDec()) { + return fmt.Errorf("reward band is too large: %s", v) + } + + return nil +} + +func validateWhitelist(i interface{}) error { + v, ok := i.(DenomList) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + for _, d := range v { + if len(d.Name) == 0 { + return fmt.Errorf("oracle parameter Whitelist Denom must have name") + } + } + + return nil +} + +func validateSlashFraction(i interface{}) error { + v, ok := i.(sdk.Dec) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v.IsNegative() { + return fmt.Errorf("slash fraction must be positive: %s", v) + } + + if v.GT(sdk.OneDec()) { + return fmt.Errorf("slash fraction is too large: %s", v) + } + + return nil +} + +func validateSlashWindow(i interface{}) error { + v, ok := i.(uint64) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v == 0 { + return fmt.Errorf("slash window must be positive: %d", v) + } + + return nil +} + +func validateMinValidPerWindow(i interface{}) error { + v, ok := i.(sdk.Dec) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v.IsNegative() { + return fmt.Errorf("min valid per window must be positive: %s", v) + } + + if v.GT(sdk.OneDec()) { + return fmt.Errorf("min valid per window is too large: %s", v) + } + + return nil +} diff --git a/x/oracle/types/params_test.go b/x/oracle/types/params_test.go new file mode 100755 index 0000000000..955a1bd2e1 --- /dev/null +++ b/x/oracle/types/params_test.go @@ -0,0 +1,60 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestParamsEqual(t *testing.T) { + p1 := DefaultParams() + err := p1.Validate() + require.NoError(t, err) + + // minus vote period + p1.VotePeriod = 0 + err = p1.Validate() + require.Error(t, err) + + // small vote threshold + p2 := DefaultParams() + p2.VoteThreshold = sdk.ZeroDec() + err = p2.Validate() + require.Error(t, err) + + // negative reward band + p3 := DefaultParams() + p3.RewardBand = sdk.NewDecWithPrec(-1, 2) + err = p3.Validate() + require.Error(t, err) + + // negative slash fraction + p4 := DefaultParams() + p4.SlashFraction = sdk.NewDec(-1) + err = p4.Validate() + require.Error(t, err) + + // negative min valid per window + p5 := DefaultParams() + p5.MinValidPerWindow = sdk.NewDec(-1) + err = p5.Validate() + require.Error(t, err) + + // small slash window + p6 := DefaultParams() + p6.SlashWindow = 0 + err = p6.Validate() + require.Error(t, err) + + // empty name + p7 := DefaultParams() + p7.Whitelist[0].Name = "" + err = p7.Validate() + require.Error(t, err) + + p8 := DefaultParams() + require.NotNil(t, p8.ParamSetPairs()) + require.NotNil(t, p8.String()) +} diff --git a/x/oracle/types/querier.go b/x/oracle/types/querier.go new file mode 100755 index 0000000000..e6d7914130 --- /dev/null +++ b/x/oracle/types/querier.go @@ -0,0 +1,99 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Defines the prefix of each query path +const ( + QueryParameters = "parameters" + QueryExchangeRate = "exchangeRate" + QueryExchangeRates = "exchangeRates" + QueryActives = "actives" + QueryFeederDelegation = "feederDelegation" + QueryMissCounter = "missCounter" + QueryAggregatePrevote = "aggregatePrevote" + QueryAggregatePrevotes = "aggregatePrevotes" + QueryAggregateVote = "aggregateVote" + QueryAggregateVotes = "aggregateVotes" + QueryVoteTargets = "voteTargets" +) + +// QueryExchangeRateParams defines the params for the following queries: +// - 'custom/oracle/exchange_rate' +type QueryExchangeRateParams struct { + Denom string +} + +// NewQueryExchangeRateParams returns params for exchange_rate query +func NewQueryExchangeRateParams(denom string) QueryExchangeRateParams { + return QueryExchangeRateParams{denom} +} + +// QueryPrevotesParams defines the params for the following queries: +// - 'custom/oracle/prevotes' +type QueryPrevotesParams struct { + Voter sdk.ValAddress + Denom string +} + +// NewQueryPrevotesParams returns params for exchange_rate prevotes query +func NewQueryPrevotesParams(voter sdk.ValAddress, denom string) QueryPrevotesParams { + return QueryPrevotesParams{voter, denom} +} + +// QueryVotesParams defines the params for the following queries: +// - 'custom/oracle/votes' +type QueryVotesParams struct { + Voter sdk.ValAddress + Denom string +} + +// NewQueryVotesParams returns params for exchange_rate votes query +func NewQueryVotesParams(voter sdk.ValAddress, denom string) QueryVotesParams { + return QueryVotesParams{voter, denom} +} + +// QueryFeederDelegationParams defeins the params for the following queries: +// - 'custom/oracle/feederDelegation' +type QueryFeederDelegationParams struct { + Validator sdk.ValAddress +} + +// NewQueryFeederDelegationParams returns params for feeder delegation query +func NewQueryFeederDelegationParams(validator sdk.ValAddress) QueryFeederDelegationParams { + return QueryFeederDelegationParams{validator} +} + +// QueryMissCounterParams defines the params for the following queries: +// - 'custom/oracle/missCounter' +type QueryMissCounterParams struct { + Validator sdk.ValAddress +} + +// NewQueryMissCounterParams returns params for feeder delegation query +func NewQueryMissCounterParams(validator sdk.ValAddress) QueryMissCounterParams { + return QueryMissCounterParams{validator} +} + +// QueryAggregatePrevoteParams defines the params for the following queries: +// - 'custom/oracle/aggregatePrevote' +type QueryAggregatePrevoteParams struct { + Validator sdk.ValAddress +} + +// NewQueryAggregatePrevoteParams returns params for feeder delegation query +func NewQueryAggregatePrevoteParams(validator sdk.ValAddress) QueryAggregatePrevoteParams { + return QueryAggregatePrevoteParams{validator} +} + +// QueryAggregateVoteParams defines the params for the following queries: +// - 'custom/oracle/aggregateVote' +type QueryAggregateVoteParams struct { + Validator sdk.ValAddress +} + +// NewQueryAggregateVoteParams returns params for feeder delegation query +func NewQueryAggregateVoteParams(validator sdk.ValAddress) QueryAggregateVoteParams { + return QueryAggregateVoteParams{validator} +} diff --git a/x/oracle/types/query.pb.go b/x/oracle/types/query.pb.go new file mode 100644 index 0000000000..f7f22f434d --- /dev/null +++ b/x/oracle/types/query.pb.go @@ -0,0 +1,4149 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/query.proto + +package types + +import ( + context "context" + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryExchangeRateRequest is the request type for the Query/ExchangeRate RPC method. +type QueryExchangeRateRequest struct { + // denom defines the denomination to query for. + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryExchangeRateRequest) Reset() { *m = QueryExchangeRateRequest{} } +func (m *QueryExchangeRateRequest) String() string { return proto.CompactTextString(m) } +func (*QueryExchangeRateRequest) ProtoMessage() {} +func (*QueryExchangeRateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{0} +} +func (m *QueryExchangeRateRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryExchangeRateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryExchangeRateRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryExchangeRateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryExchangeRateRequest.Merge(m, src) +} +func (m *QueryExchangeRateRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryExchangeRateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryExchangeRateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryExchangeRateRequest proto.InternalMessageInfo + +// QueryExchangeRateResponse is response type for the +// Query/ExchangeRate RPC method. +type QueryExchangeRateResponse struct { + // exchange_rate defines the exchange rate of Luna denominated in various Terra + ExchangeRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=exchange_rate,json=exchangeRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"exchange_rate"` +} + +func (m *QueryExchangeRateResponse) Reset() { *m = QueryExchangeRateResponse{} } +func (m *QueryExchangeRateResponse) String() string { return proto.CompactTextString(m) } +func (*QueryExchangeRateResponse) ProtoMessage() {} +func (*QueryExchangeRateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{1} +} +func (m *QueryExchangeRateResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryExchangeRateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryExchangeRateResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryExchangeRateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryExchangeRateResponse.Merge(m, src) +} +func (m *QueryExchangeRateResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryExchangeRateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryExchangeRateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryExchangeRateResponse proto.InternalMessageInfo + +// QueryExchangeRatesRequest is the request type for the Query/ExchangeRates RPC method. +type QueryExchangeRatesRequest struct { +} + +func (m *QueryExchangeRatesRequest) Reset() { *m = QueryExchangeRatesRequest{} } +func (m *QueryExchangeRatesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryExchangeRatesRequest) ProtoMessage() {} +func (*QueryExchangeRatesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{2} +} +func (m *QueryExchangeRatesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryExchangeRatesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryExchangeRatesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryExchangeRatesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryExchangeRatesRequest.Merge(m, src) +} +func (m *QueryExchangeRatesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryExchangeRatesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryExchangeRatesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryExchangeRatesRequest proto.InternalMessageInfo + +// QueryExchangeRatesResponse is response type for the +// Query/ExchangeRates RPC method. +type QueryExchangeRatesResponse struct { + // exchange_rates defines a list of the exchange rate for all whitelisted denoms. + ExchangeRates github_com_cosmos_cosmos_sdk_types.DecCoins `protobuf:"bytes,1,rep,name=exchange_rates,json=exchangeRates,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.DecCoins" json:"exchange_rates"` +} + +func (m *QueryExchangeRatesResponse) Reset() { *m = QueryExchangeRatesResponse{} } +func (m *QueryExchangeRatesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryExchangeRatesResponse) ProtoMessage() {} +func (*QueryExchangeRatesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{3} +} +func (m *QueryExchangeRatesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryExchangeRatesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryExchangeRatesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryExchangeRatesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryExchangeRatesResponse.Merge(m, src) +} +func (m *QueryExchangeRatesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryExchangeRatesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryExchangeRatesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryExchangeRatesResponse proto.InternalMessageInfo + +func (m *QueryExchangeRatesResponse) GetExchangeRates() github_com_cosmos_cosmos_sdk_types.DecCoins { + if m != nil { + return m.ExchangeRates + } + return nil +} + +// QueryActivesRequest is the request type for the Query/Actives RPC method. +type QueryActivesRequest struct { +} + +func (m *QueryActivesRequest) Reset() { *m = QueryActivesRequest{} } +func (m *QueryActivesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryActivesRequest) ProtoMessage() {} +func (*QueryActivesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{4} +} +func (m *QueryActivesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryActivesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryActivesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryActivesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryActivesRequest.Merge(m, src) +} +func (m *QueryActivesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryActivesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryActivesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryActivesRequest proto.InternalMessageInfo + +// QueryActivesResponse is response type for the +// Query/Actives RPC method. +type QueryActivesResponse struct { + // actives defines a list of the denomination which oracle prices aggreed upon. + Actives []string `protobuf:"bytes,1,rep,name=actives,proto3" json:"actives,omitempty"` +} + +func (m *QueryActivesResponse) Reset() { *m = QueryActivesResponse{} } +func (m *QueryActivesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryActivesResponse) ProtoMessage() {} +func (*QueryActivesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{5} +} +func (m *QueryActivesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryActivesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryActivesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryActivesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryActivesResponse.Merge(m, src) +} +func (m *QueryActivesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryActivesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryActivesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryActivesResponse proto.InternalMessageInfo + +func (m *QueryActivesResponse) GetActives() []string { + if m != nil { + return m.Actives + } + return nil +} + +// QueryVoteTargetsRequest is the request type for the Query/VoteTargets RPC method. +type QueryVoteTargetsRequest struct { +} + +func (m *QueryVoteTargetsRequest) Reset() { *m = QueryVoteTargetsRequest{} } +func (m *QueryVoteTargetsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVoteTargetsRequest) ProtoMessage() {} +func (*QueryVoteTargetsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{6} +} +func (m *QueryVoteTargetsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteTargetsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteTargetsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryVoteTargetsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteTargetsRequest.Merge(m, src) +} +func (m *QueryVoteTargetsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteTargetsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteTargetsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteTargetsRequest proto.InternalMessageInfo + +// QueryVoteTargetsResponse is response type for the +// Query/VoteTargets RPC method. +type QueryVoteTargetsResponse struct { + // vote_targets defines a list of the denomination in which everyone + // should vote in the current vote period. + VoteTargets []string `protobuf:"bytes,1,rep,name=vote_targets,json=voteTargets,proto3" json:"vote_targets,omitempty"` +} + +func (m *QueryVoteTargetsResponse) Reset() { *m = QueryVoteTargetsResponse{} } +func (m *QueryVoteTargetsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVoteTargetsResponse) ProtoMessage() {} +func (*QueryVoteTargetsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{7} +} +func (m *QueryVoteTargetsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteTargetsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteTargetsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryVoteTargetsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteTargetsResponse.Merge(m, src) +} +func (m *QueryVoteTargetsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteTargetsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteTargetsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteTargetsResponse proto.InternalMessageInfo + +func (m *QueryVoteTargetsResponse) GetVoteTargets() []string { + if m != nil { + return m.VoteTargets + } + return nil +} + +// QueryFeederDelegationRequest is the request type for the Query/FeederDelegation RPC method. +type QueryFeederDelegationRequest struct { + // validator defines the validator address to query for. + ValidatorAddr string `protobuf:"bytes,1,opt,name=validator_addr,json=validatorAddr,proto3" json:"validator_addr,omitempty"` +} + +func (m *QueryFeederDelegationRequest) Reset() { *m = QueryFeederDelegationRequest{} } +func (m *QueryFeederDelegationRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFeederDelegationRequest) ProtoMessage() {} +func (*QueryFeederDelegationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{8} +} +func (m *QueryFeederDelegationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeederDelegationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeederDelegationRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryFeederDelegationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeederDelegationRequest.Merge(m, src) +} +func (m *QueryFeederDelegationRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFeederDelegationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeederDelegationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeederDelegationRequest proto.InternalMessageInfo + +// QueryFeederDelegationResponse is response type for the +// Query/FeederDelegation RPC method. +type QueryFeederDelegationResponse struct { + // feeder_addr defines the feeder delegation of a validator + FeederAddr string `protobuf:"bytes,1,opt,name=feeder_addr,json=feederAddr,proto3" json:"feeder_addr,omitempty"` +} + +func (m *QueryFeederDelegationResponse) Reset() { *m = QueryFeederDelegationResponse{} } +func (m *QueryFeederDelegationResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFeederDelegationResponse) ProtoMessage() {} +func (*QueryFeederDelegationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{9} +} +func (m *QueryFeederDelegationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeederDelegationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeederDelegationResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryFeederDelegationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeederDelegationResponse.Merge(m, src) +} +func (m *QueryFeederDelegationResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFeederDelegationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeederDelegationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeederDelegationResponse proto.InternalMessageInfo + +func (m *QueryFeederDelegationResponse) GetFeederAddr() string { + if m != nil { + return m.FeederAddr + } + return "" +} + +// QueryMissCounterRequest is the request type for the Query/MissCounter RPC method. +type QueryMissCounterRequest struct { + // validator defines the validator address to query for. + ValidatorAddr string `protobuf:"bytes,1,opt,name=validator_addr,json=validatorAddr,proto3" json:"validator_addr,omitempty"` +} + +func (m *QueryMissCounterRequest) Reset() { *m = QueryMissCounterRequest{} } +func (m *QueryMissCounterRequest) String() string { return proto.CompactTextString(m) } +func (*QueryMissCounterRequest) ProtoMessage() {} +func (*QueryMissCounterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{10} +} +func (m *QueryMissCounterRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMissCounterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMissCounterRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryMissCounterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMissCounterRequest.Merge(m, src) +} +func (m *QueryMissCounterRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryMissCounterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMissCounterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMissCounterRequest proto.InternalMessageInfo + +// QueryMissCounterResponse is response type for the +// Query/MissCounter RPC method. +type QueryMissCounterResponse struct { + // miss_counter defines the oracle miss counter of a validator + MissCounter uint64 `protobuf:"varint,1,opt,name=miss_counter,json=missCounter,proto3" json:"miss_counter,omitempty"` +} + +func (m *QueryMissCounterResponse) Reset() { *m = QueryMissCounterResponse{} } +func (m *QueryMissCounterResponse) String() string { return proto.CompactTextString(m) } +func (*QueryMissCounterResponse) ProtoMessage() {} +func (*QueryMissCounterResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{11} +} +func (m *QueryMissCounterResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMissCounterResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMissCounterResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryMissCounterResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMissCounterResponse.Merge(m, src) +} +func (m *QueryMissCounterResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryMissCounterResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMissCounterResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMissCounterResponse proto.InternalMessageInfo + +func (m *QueryMissCounterResponse) GetMissCounter() uint64 { + if m != nil { + return m.MissCounter + } + return 0 +} + +// QueryAggregatePrevoteRequest is the request type for the Query/AggregatePrevote RPC method. +type QueryAggregatePrevoteRequest struct { + // validator defines the validator address to query for. + ValidatorAddr string `protobuf:"bytes,1,opt,name=validator_addr,json=validatorAddr,proto3" json:"validator_addr,omitempty"` +} + +func (m *QueryAggregatePrevoteRequest) Reset() { *m = QueryAggregatePrevoteRequest{} } +func (m *QueryAggregatePrevoteRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAggregatePrevoteRequest) ProtoMessage() {} +func (*QueryAggregatePrevoteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{12} +} +func (m *QueryAggregatePrevoteRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregatePrevoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregatePrevoteRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregatePrevoteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregatePrevoteRequest.Merge(m, src) +} +func (m *QueryAggregatePrevoteRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregatePrevoteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregatePrevoteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregatePrevoteRequest proto.InternalMessageInfo + +// QueryAggregatePrevoteResponse is response type for the +// Query/AggregatePrevote RPC method. +type QueryAggregatePrevoteResponse struct { + // aggregate_prevote defines oracle aggregate prevote submitted by a validator in the current vote period + AggregatePrevote AggregateExchangeRatePrevote `protobuf:"bytes,1,opt,name=aggregate_prevote,json=aggregatePrevote,proto3" json:"aggregate_prevote"` +} + +func (m *QueryAggregatePrevoteResponse) Reset() { *m = QueryAggregatePrevoteResponse{} } +func (m *QueryAggregatePrevoteResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAggregatePrevoteResponse) ProtoMessage() {} +func (*QueryAggregatePrevoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{13} +} +func (m *QueryAggregatePrevoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregatePrevoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregatePrevoteResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregatePrevoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregatePrevoteResponse.Merge(m, src) +} +func (m *QueryAggregatePrevoteResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregatePrevoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregatePrevoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregatePrevoteResponse proto.InternalMessageInfo + +func (m *QueryAggregatePrevoteResponse) GetAggregatePrevote() AggregateExchangeRatePrevote { + if m != nil { + return m.AggregatePrevote + } + return AggregateExchangeRatePrevote{} +} + +// QueryAggregatePrevotesRequest is the request type for the Query/AggregatePrevotes RPC method. +type QueryAggregatePrevotesRequest struct { +} + +func (m *QueryAggregatePrevotesRequest) Reset() { *m = QueryAggregatePrevotesRequest{} } +func (m *QueryAggregatePrevotesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAggregatePrevotesRequest) ProtoMessage() {} +func (*QueryAggregatePrevotesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{14} +} +func (m *QueryAggregatePrevotesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregatePrevotesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregatePrevotesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregatePrevotesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregatePrevotesRequest.Merge(m, src) +} +func (m *QueryAggregatePrevotesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregatePrevotesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregatePrevotesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregatePrevotesRequest proto.InternalMessageInfo + +// QueryAggregatePrevotesResponse is response type for the +// Query/AggregatePrevotes RPC method. +type QueryAggregatePrevotesResponse struct { + // aggregate_prevotes defines all oracle aggregate prevotes submitted in the current vote period + AggregatePrevotes []AggregateExchangeRatePrevote `protobuf:"bytes,1,rep,name=aggregate_prevotes,json=aggregatePrevotes,proto3" json:"aggregate_prevotes"` +} + +func (m *QueryAggregatePrevotesResponse) Reset() { *m = QueryAggregatePrevotesResponse{} } +func (m *QueryAggregatePrevotesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAggregatePrevotesResponse) ProtoMessage() {} +func (*QueryAggregatePrevotesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{15} +} +func (m *QueryAggregatePrevotesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregatePrevotesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregatePrevotesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregatePrevotesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregatePrevotesResponse.Merge(m, src) +} +func (m *QueryAggregatePrevotesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregatePrevotesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregatePrevotesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregatePrevotesResponse proto.InternalMessageInfo + +func (m *QueryAggregatePrevotesResponse) GetAggregatePrevotes() []AggregateExchangeRatePrevote { + if m != nil { + return m.AggregatePrevotes + } + return nil +} + +// QueryAggregateVoteRequest is the request type for the Query/AggregateVote RPC method. +type QueryAggregateVoteRequest struct { + // validator defines the validator address to query for. + ValidatorAddr string `protobuf:"bytes,1,opt,name=validator_addr,json=validatorAddr,proto3" json:"validator_addr,omitempty"` +} + +func (m *QueryAggregateVoteRequest) Reset() { *m = QueryAggregateVoteRequest{} } +func (m *QueryAggregateVoteRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAggregateVoteRequest) ProtoMessage() {} +func (*QueryAggregateVoteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{16} +} +func (m *QueryAggregateVoteRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregateVoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregateVoteRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregateVoteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregateVoteRequest.Merge(m, src) +} +func (m *QueryAggregateVoteRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregateVoteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregateVoteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregateVoteRequest proto.InternalMessageInfo + +// QueryAggregateVoteResponse is response type for the +// Query/AggregateVote RPC method. +type QueryAggregateVoteResponse struct { + // aggregate_vote defines oracle aggregate vote submitted by a validator in the current vote period + AggregateVote AggregateExchangeRateVote `protobuf:"bytes,1,opt,name=aggregate_vote,json=aggregateVote,proto3" json:"aggregate_vote"` +} + +func (m *QueryAggregateVoteResponse) Reset() { *m = QueryAggregateVoteResponse{} } +func (m *QueryAggregateVoteResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAggregateVoteResponse) ProtoMessage() {} +func (*QueryAggregateVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{17} +} +func (m *QueryAggregateVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregateVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregateVoteResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregateVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregateVoteResponse.Merge(m, src) +} +func (m *QueryAggregateVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregateVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregateVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregateVoteResponse proto.InternalMessageInfo + +func (m *QueryAggregateVoteResponse) GetAggregateVote() AggregateExchangeRateVote { + if m != nil { + return m.AggregateVote + } + return AggregateExchangeRateVote{} +} + +// QueryAggregateVotesRequest is the request type for the Query/AggregateVotes RPC method. +type QueryAggregateVotesRequest struct { +} + +func (m *QueryAggregateVotesRequest) Reset() { *m = QueryAggregateVotesRequest{} } +func (m *QueryAggregateVotesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAggregateVotesRequest) ProtoMessage() {} +func (*QueryAggregateVotesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{18} +} +func (m *QueryAggregateVotesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregateVotesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregateVotesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregateVotesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregateVotesRequest.Merge(m, src) +} +func (m *QueryAggregateVotesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregateVotesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregateVotesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregateVotesRequest proto.InternalMessageInfo + +// QueryAggregateVotesResponse is response type for the +// Query/AggregateVotes RPC method. +type QueryAggregateVotesResponse struct { + // aggregate_votes defines all oracle aggregate votes submitted in the current vote period + AggregateVotes []AggregateExchangeRateVote `protobuf:"bytes,1,rep,name=aggregate_votes,json=aggregateVotes,proto3" json:"aggregate_votes"` +} + +func (m *QueryAggregateVotesResponse) Reset() { *m = QueryAggregateVotesResponse{} } +func (m *QueryAggregateVotesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAggregateVotesResponse) ProtoMessage() {} +func (*QueryAggregateVotesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{19} +} +func (m *QueryAggregateVotesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAggregateVotesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAggregateVotesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryAggregateVotesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAggregateVotesResponse.Merge(m, src) +} +func (m *QueryAggregateVotesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAggregateVotesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAggregateVotesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAggregateVotesResponse proto.InternalMessageInfo + +func (m *QueryAggregateVotesResponse) GetAggregateVotes() []AggregateExchangeRateVote { + if m != nil { + return m.AggregateVotes + } + return nil +} + +// QueryParamsRequest is the request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{20} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is the response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params defines the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_562b782cb9ac197e, []int{21} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*QueryExchangeRateRequest)(nil), "seiprotocol.seichain.oracle.QueryExchangeRateRequest") + proto.RegisterType((*QueryExchangeRateResponse)(nil), "seiprotocol.seichain.oracle.QueryExchangeRateResponse") + proto.RegisterType((*QueryExchangeRatesRequest)(nil), "seiprotocol.seichain.oracle.QueryExchangeRatesRequest") + proto.RegisterType((*QueryExchangeRatesResponse)(nil), "seiprotocol.seichain.oracle.QueryExchangeRatesResponse") + proto.RegisterType((*QueryActivesRequest)(nil), "seiprotocol.seichain.oracle.QueryActivesRequest") + proto.RegisterType((*QueryActivesResponse)(nil), "seiprotocol.seichain.oracle.QueryActivesResponse") + proto.RegisterType((*QueryVoteTargetsRequest)(nil), "seiprotocol.seichain.oracle.QueryVoteTargetsRequest") + proto.RegisterType((*QueryVoteTargetsResponse)(nil), "seiprotocol.seichain.oracle.QueryVoteTargetsResponse") + proto.RegisterType((*QueryFeederDelegationRequest)(nil), "seiprotocol.seichain.oracle.QueryFeederDelegationRequest") + proto.RegisterType((*QueryFeederDelegationResponse)(nil), "seiprotocol.seichain.oracle.QueryFeederDelegationResponse") + proto.RegisterType((*QueryMissCounterRequest)(nil), "seiprotocol.seichain.oracle.QueryMissCounterRequest") + proto.RegisterType((*QueryMissCounterResponse)(nil), "seiprotocol.seichain.oracle.QueryMissCounterResponse") + proto.RegisterType((*QueryAggregatePrevoteRequest)(nil), "seiprotocol.seichain.oracle.QueryAggregatePrevoteRequest") + proto.RegisterType((*QueryAggregatePrevoteResponse)(nil), "seiprotocol.seichain.oracle.QueryAggregatePrevoteResponse") + proto.RegisterType((*QueryAggregatePrevotesRequest)(nil), "seiprotocol.seichain.oracle.QueryAggregatePrevotesRequest") + proto.RegisterType((*QueryAggregatePrevotesResponse)(nil), "seiprotocol.seichain.oracle.QueryAggregatePrevotesResponse") + proto.RegisterType((*QueryAggregateVoteRequest)(nil), "seiprotocol.seichain.oracle.QueryAggregateVoteRequest") + proto.RegisterType((*QueryAggregateVoteResponse)(nil), "seiprotocol.seichain.oracle.QueryAggregateVoteResponse") + proto.RegisterType((*QueryAggregateVotesRequest)(nil), "seiprotocol.seichain.oracle.QueryAggregateVotesRequest") + proto.RegisterType((*QueryAggregateVotesResponse)(nil), "seiprotocol.seichain.oracle.QueryAggregateVotesResponse") + proto.RegisterType((*QueryParamsRequest)(nil), "seiprotocol.seichain.oracle.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "seiprotocol.seichain.oracle.QueryParamsResponse") +} + +func init() { proto.RegisterFile("oracle/query.proto", fileDescriptor_562b782cb9ac197e) } + +var fileDescriptor_562b782cb9ac197e = []byte{ + // 1103 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x97, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xc7, 0x3d, 0xd0, 0xa6, 0x74, 0x1c, 0x87, 0x64, 0x1a, 0x44, 0xea, 0x04, 0xbb, 0x2c, 0x2a, + 0x54, 0x42, 0xd9, 0xcd, 0x8f, 0x26, 0x90, 0xa4, 0x05, 0x9c, 0x04, 0x50, 0x4b, 0x81, 0xd6, 0x54, + 0x11, 0xe2, 0x62, 0x4d, 0x76, 0x87, 0xcd, 0x0a, 0x7b, 0xc7, 0xdd, 0xd9, 0x58, 0xa9, 0xaa, 0x1e, + 0x40, 0x1c, 0xb8, 0x20, 0x55, 0x42, 0xe2, 0xc0, 0xa9, 0x17, 0x2e, 0xdc, 0xb9, 0x72, 0x00, 0x09, + 0xf5, 0x58, 0x51, 0x0e, 0x88, 0x43, 0x8b, 0x12, 0x0e, 0xfc, 0x13, 0x48, 0xd5, 0xce, 0xbc, 0x5d, + 0xef, 0xfa, 0x47, 0x76, 0x6d, 0x9f, 0xd6, 0x3b, 0x33, 0xef, 0xcd, 0xe7, 0x3b, 0x6f, 0x76, 0xbe, + 0x63, 0x4c, 0xb8, 0x47, 0xcd, 0x3a, 0x33, 0x6e, 0xed, 0x33, 0xef, 0xb6, 0xde, 0xf4, 0xb8, 0xcf, + 0xc9, 0xac, 0x60, 0x8e, 0xfc, 0x65, 0xf2, 0xba, 0x2e, 0x98, 0x63, 0xee, 0x51, 0xc7, 0xd5, 0xd5, + 0xc0, 0xe2, 0xb4, 0xcd, 0x6d, 0x2e, 0x7b, 0x8d, 0xe0, 0x97, 0x0a, 0x29, 0xce, 0xd9, 0x9c, 0xdb, + 0x75, 0x66, 0xd0, 0xa6, 0x63, 0x50, 0xd7, 0xe5, 0x3e, 0xf5, 0x1d, 0xee, 0x0a, 0xe8, 0x3d, 0x03, + 0x93, 0xa8, 0x07, 0x34, 0x96, 0x4c, 0x2e, 0x1a, 0x5c, 0x18, 0xbb, 0x54, 0x30, 0xa3, 0xb5, 0xb8, + 0xcb, 0x7c, 0xba, 0x68, 0x98, 0xdc, 0x71, 0x55, 0xbf, 0xb6, 0x8e, 0x67, 0x6e, 0x04, 0x50, 0xef, + 0x1e, 0x98, 0x7b, 0xd4, 0xb5, 0x59, 0x95, 0xfa, 0xac, 0xca, 0x6e, 0xed, 0x33, 0xe1, 0x93, 0x69, + 0x7c, 0xd2, 0x62, 0x2e, 0x6f, 0xcc, 0xa0, 0x73, 0xe8, 0xc2, 0xe9, 0xaa, 0x7a, 0x59, 0x7f, 0xee, + 0x9b, 0xfb, 0xe5, 0xdc, 0x7f, 0xf7, 0xcb, 0x39, 0xad, 0x89, 0xcf, 0xf6, 0x88, 0x15, 0x4d, 0xee, + 0x0a, 0x46, 0x3e, 0xc1, 0x05, 0x06, 0xed, 0x35, 0x8f, 0xfa, 0x4c, 0x25, 0xd9, 0xd4, 0x1f, 0x3c, + 0x2e, 0xe7, 0xfe, 0x7e, 0x5c, 0x7e, 0xd5, 0x76, 0xfc, 0xbd, 0xfd, 0x5d, 0xdd, 0xe4, 0x0d, 0x03, + 0x10, 0xd5, 0x63, 0x5e, 0x58, 0x5f, 0x18, 0xfe, 0xed, 0x26, 0x13, 0xfa, 0x36, 0x33, 0xab, 0xe3, + 0x2c, 0x96, 0x5c, 0x9b, 0xed, 0x31, 0xa3, 0x00, 0x5c, 0xed, 0x7b, 0x84, 0x8b, 0xbd, 0x7a, 0x01, + 0xe8, 0x00, 0x4f, 0x24, 0x80, 0xc4, 0x0c, 0x3a, 0xf7, 0xec, 0x85, 0xfc, 0xd2, 0x9c, 0xae, 0x26, + 0xd6, 0x83, 0x25, 0xd2, 0x61, 0x89, 0x82, 0xb9, 0xb7, 0xb8, 0xe3, 0x6e, 0x2e, 0x07, 0xbc, 0x3f, + 0x3d, 0x29, 0xbf, 0x9e, 0x8d, 0x37, 0x88, 0x11, 0xd5, 0x42, 0x1c, 0x5a, 0x68, 0x2f, 0xe0, 0x33, + 0x92, 0xab, 0x62, 0xfa, 0x4e, 0xab, 0xcd, 0xbb, 0x80, 0xa7, 0x93, 0xcd, 0x00, 0x3a, 0x83, 0x4f, + 0x51, 0xd5, 0x24, 0x09, 0x4f, 0x57, 0xc3, 0x57, 0xed, 0x2c, 0x7e, 0x51, 0x46, 0xec, 0x70, 0x9f, + 0xdd, 0xa4, 0x9e, 0xcd, 0xfc, 0x28, 0xd9, 0x65, 0xa8, 0x63, 0xa2, 0x0b, 0x12, 0xbe, 0x8c, 0xc7, + 0x5b, 0xdc, 0x67, 0x35, 0x5f, 0xb5, 0x43, 0xd6, 0x7c, 0xab, 0x3d, 0x54, 0xfb, 0x18, 0xcf, 0xc9, + 0xf0, 0xf7, 0x18, 0xb3, 0x98, 0xb7, 0xcd, 0xea, 0xcc, 0x96, 0x7b, 0x2b, 0xdc, 0x0a, 0xe7, 0xf1, + 0x44, 0x8b, 0xd6, 0x1d, 0x8b, 0xfa, 0xdc, 0xab, 0x51, 0xcb, 0xf2, 0x60, 0x4f, 0x14, 0xa2, 0xd6, + 0x8a, 0x65, 0x79, 0xb1, 0xbd, 0xf1, 0x0e, 0x7e, 0xa9, 0x4f, 0x42, 0x80, 0x2a, 0xe3, 0xfc, 0xe7, + 0xb2, 0x2f, 0x9e, 0x0e, 0xab, 0xa6, 0x20, 0x97, 0x76, 0x15, 0xc4, 0x7e, 0xe8, 0x08, 0xb1, 0xc5, + 0xf7, 0x5d, 0x9f, 0x79, 0x43, 0xd3, 0x84, 0xab, 0x93, 0xc8, 0xd5, 0x5e, 0x9d, 0x86, 0x23, 0x44, + 0xcd, 0x54, 0xed, 0x32, 0xd5, 0x89, 0x6a, 0xbe, 0xd1, 0x1e, 0x1a, 0xad, 0x4e, 0xc5, 0xb6, 0xbd, + 0x40, 0x07, 0xbb, 0xee, 0xb1, 0x60, 0xf5, 0x86, 0xe6, 0xf9, 0x16, 0xc1, 0xf2, 0x74, 0x67, 0x04, + 0xaa, 0x3a, 0x9e, 0xa2, 0x61, 0x5f, 0xad, 0xa9, 0x3a, 0x65, 0xd6, 0xfc, 0xd2, 0x9a, 0x7e, 0xcc, + 0xc9, 0xa1, 0x47, 0x19, 0xe3, 0x5f, 0x01, 0x64, 0xdf, 0x3c, 0x11, 0xec, 0xe6, 0xea, 0x24, 0xed, + 0x98, 0x55, 0x2b, 0xf7, 0xc1, 0x89, 0xb6, 0xd7, 0x3d, 0x84, 0x4b, 0xfd, 0x46, 0x00, 0xb1, 0x8b, + 0x49, 0x17, 0x71, 0xf8, 0x8d, 0x8d, 0x8c, 0x3c, 0xd5, 0x89, 0x2c, 0xb4, 0x6b, 0x70, 0x16, 0x44, + 0xd1, 0x3b, 0xa3, 0x54, 0xe4, 0xcb, 0xf0, 0xf0, 0xe8, 0x48, 0x07, 0xe2, 0x4c, 0x3c, 0xd1, 0x16, + 0x17, 0xab, 0xc5, 0xea, 0xe0, 0xc2, 0x76, 0xda, 0xaa, 0x0a, 0x34, 0x3e, 0x99, 0x36, 0xd7, 0x0b, + 0x21, 0x2a, 0xc1, 0xd7, 0x08, 0xcf, 0xf6, 0xec, 0x06, 0x44, 0x86, 0x9f, 0x4f, 0x22, 0x86, 0x8b, + 0x3f, 0x1a, 0xe3, 0x44, 0x82, 0x51, 0x68, 0xd3, 0x98, 0x48, 0x8a, 0xeb, 0xd4, 0xa3, 0x8d, 0x08, + 0xee, 0x53, 0x38, 0xe2, 0xc2, 0x56, 0x60, 0xaa, 0xe0, 0xb1, 0xa6, 0x6c, 0x81, 0xe5, 0x7a, 0xe5, + 0x58, 0x14, 0x15, 0x0c, 0xf3, 0x42, 0xe0, 0xd2, 0xff, 0x93, 0xf8, 0xa4, 0x4c, 0x4d, 0x7e, 0x45, + 0x78, 0x3c, 0x0e, 0x49, 0x56, 0x8e, 0xcd, 0xd6, 0xcf, 0xd6, 0x8a, 0xab, 0x83, 0x86, 0x29, 0x31, + 0xda, 0xd6, 0x57, 0x8f, 0xfe, 0xfd, 0xee, 0x99, 0xcb, 0x64, 0xc3, 0x10, 0xcc, 0x99, 0x0f, 0x13, + 0xc8, 0x17, 0x99, 0x01, 0x8c, 0xd7, 0x90, 0x36, 0x29, 0x8c, 0x3b, 0xf2, 0x79, 0xd7, 0x48, 0x98, + 0x0e, 0xf9, 0x05, 0xe1, 0x42, 0xc2, 0x9f, 0xc8, 0x80, 0x38, 0xe1, 0x92, 0x17, 0xdf, 0x18, 0x38, + 0x0e, 0x74, 0x5c, 0x92, 0x3a, 0x56, 0xc9, 0xc5, 0x6c, 0x3a, 0x92, 0xa6, 0x49, 0x7e, 0x44, 0xf8, + 0x14, 0x38, 0x16, 0x59, 0x48, 0x47, 0x48, 0x7a, 0x5e, 0x71, 0x71, 0x80, 0x08, 0xc0, 0x5d, 0x91, + 0xb8, 0x06, 0x99, 0xcf, 0x86, 0x0b, 0x5e, 0x49, 0x7e, 0x46, 0x38, 0x1f, 0x33, 0x43, 0x72, 0x31, + 0x7d, 0xe6, 0x6e, 0x5b, 0x2d, 0xae, 0x0c, 0x18, 0x05, 0xcc, 0x6b, 0x92, 0x79, 0x99, 0x2c, 0xa6, + 0x30, 0x2b, 0xe4, 0xb8, 0x39, 0x93, 0x3f, 0x11, 0x9e, 0xec, 0x34, 0x4d, 0xb2, 0x96, 0x8e, 0xd1, + 0xc7, 0xb9, 0x8b, 0xeb, 0xc3, 0x84, 0x82, 0x8c, 0x2b, 0x52, 0xc6, 0x16, 0xa9, 0xa4, 0xc8, 0x88, + 0x0e, 0x55, 0x61, 0xdc, 0x49, 0x1e, 0xbb, 0x77, 0x0d, 0xe5, 0xe8, 0xe4, 0x37, 0x84, 0xf3, 0x31, + 0xf7, 0xcd, 0x52, 0x8e, 0x6e, 0xe3, 0xcf, 0x52, 0x8e, 0x1e, 0x16, 0xaf, 0xbd, 0x2f, 0x75, 0x54, + 0xc8, 0xdb, 0x23, 0xe8, 0x08, 0xee, 0x03, 0xe4, 0x09, 0xc2, 0x93, 0x9d, 0x0e, 0x98, 0xa5, 0x38, + 0x7d, 0x2e, 0x0e, 0x59, 0x8a, 0xd3, 0xef, 0x86, 0xa0, 0xdd, 0x94, 0xa2, 0x3e, 0x22, 0xd7, 0x46, + 0x10, 0xd5, 0x65, 0xd8, 0xe4, 0x0f, 0x84, 0xa7, 0xba, 0x3c, 0x9e, 0x0c, 0xc1, 0x19, 0x7d, 0x42, + 0x1b, 0x43, 0xc5, 0x82, 0xc8, 0x6d, 0x29, 0xf2, 0x2d, 0x72, 0x29, 0xbb, 0xc8, 0xee, 0x4b, 0x08, + 0x79, 0x84, 0x70, 0x21, 0xe1, 0x9a, 0x59, 0x0e, 0xdd, 0x5e, 0xf7, 0x8a, 0x2c, 0x87, 0x6e, 0xcf, + 0x0b, 0x84, 0x76, 0x43, 0x0a, 0xf9, 0x80, 0x5c, 0x49, 0x17, 0x62, 0x39, 0xa9, 0xd5, 0x92, 0xa5, + 0xfa, 0x1d, 0xe1, 0x89, 0xe4, 0x5d, 0x80, 0x0c, 0x8a, 0x17, 0x15, 0xe9, 0xcd, 0xc1, 0x03, 0x41, + 0x58, 0x45, 0x0a, 0xdb, 0x20, 0x6b, 0xc3, 0x54, 0x48, 0x95, 0xe7, 0x07, 0x84, 0xc7, 0x94, 0xf7, + 0x13, 0x23, 0x9d, 0x23, 0x71, 0xf1, 0x28, 0x2e, 0x64, 0x0f, 0x00, 0xe0, 0x79, 0x09, 0xfc, 0x1a, + 0x39, 0x9f, 0x02, 0xac, 0xee, 0x1f, 0x9b, 0x57, 0x1f, 0x1c, 0x96, 0xd0, 0xc3, 0xc3, 0x12, 0xfa, + 0xe7, 0xb0, 0x84, 0xee, 0x1d, 0x95, 0x72, 0x0f, 0x8f, 0x4a, 0xb9, 0xbf, 0x8e, 0x4a, 0xb9, 0xcf, + 0x16, 0x62, 0x7f, 0x09, 0xfb, 0xa4, 0x3a, 0x08, 0x93, 0xc9, 0x3f, 0x88, 0xbb, 0x63, 0x72, 0xc8, + 0xf2, 0xd3, 0x00, 0x00, 0x00, 0xff, 0xff, 0x11, 0x5b, 0xc0, 0xda, 0x0f, 0x10, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // ExchangeRate returns exchange rate of a denom + ExchangeRate(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryExchangeRateResponse, error) + // ExchangeRates returns exchange rates of all denoms + ExchangeRates(ctx context.Context, in *QueryExchangeRatesRequest, opts ...grpc.CallOption) (*QueryExchangeRatesResponse, error) + // Actives returns all active denoms + Actives(ctx context.Context, in *QueryActivesRequest, opts ...grpc.CallOption) (*QueryActivesResponse, error) + // VoteTargets returns all vote target denoms + VoteTargets(ctx context.Context, in *QueryVoteTargetsRequest, opts ...grpc.CallOption) (*QueryVoteTargetsResponse, error) + // FeederDelegation returns feeder delegation of a validator + FeederDelegation(ctx context.Context, in *QueryFeederDelegationRequest, opts ...grpc.CallOption) (*QueryFeederDelegationResponse, error) + // MissCounter returns oracle miss counter of a validator + MissCounter(ctx context.Context, in *QueryMissCounterRequest, opts ...grpc.CallOption) (*QueryMissCounterResponse, error) + // AggregatePrevote returns an aggregate prevote of a validator + AggregatePrevote(ctx context.Context, in *QueryAggregatePrevoteRequest, opts ...grpc.CallOption) (*QueryAggregatePrevoteResponse, error) + // AggregatePrevotes returns aggregate prevotes of all validators + AggregatePrevotes(ctx context.Context, in *QueryAggregatePrevotesRequest, opts ...grpc.CallOption) (*QueryAggregatePrevotesResponse, error) + // AggregateVote returns an aggregate vote of a validator + AggregateVote(ctx context.Context, in *QueryAggregateVoteRequest, opts ...grpc.CallOption) (*QueryAggregateVoteResponse, error) + // AggregateVotes returns aggregate votes of all validators + AggregateVotes(ctx context.Context, in *QueryAggregateVotesRequest, opts ...grpc.CallOption) (*QueryAggregateVotesResponse, error) + // Params queries all parameters. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) ExchangeRate(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryExchangeRateResponse, error) { + out := new(QueryExchangeRateResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/ExchangeRate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ExchangeRates(ctx context.Context, in *QueryExchangeRatesRequest, opts ...grpc.CallOption) (*QueryExchangeRatesResponse, error) { + out := new(QueryExchangeRatesResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/ExchangeRates", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Actives(ctx context.Context, in *QueryActivesRequest, opts ...grpc.CallOption) (*QueryActivesResponse, error) { + out := new(QueryActivesResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/Actives", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VoteTargets(ctx context.Context, in *QueryVoteTargetsRequest, opts ...grpc.CallOption) (*QueryVoteTargetsResponse, error) { + out := new(QueryVoteTargetsResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/VoteTargets", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) FeederDelegation(ctx context.Context, in *QueryFeederDelegationRequest, opts ...grpc.CallOption) (*QueryFeederDelegationResponse, error) { + out := new(QueryFeederDelegationResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/FeederDelegation", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) MissCounter(ctx context.Context, in *QueryMissCounterRequest, opts ...grpc.CallOption) (*QueryMissCounterResponse, error) { + out := new(QueryMissCounterResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/MissCounter", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AggregatePrevote(ctx context.Context, in *QueryAggregatePrevoteRequest, opts ...grpc.CallOption) (*QueryAggregatePrevoteResponse, error) { + out := new(QueryAggregatePrevoteResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/AggregatePrevote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AggregatePrevotes(ctx context.Context, in *QueryAggregatePrevotesRequest, opts ...grpc.CallOption) (*QueryAggregatePrevotesResponse, error) { + out := new(QueryAggregatePrevotesResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/AggregatePrevotes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AggregateVote(ctx context.Context, in *QueryAggregateVoteRequest, opts ...grpc.CallOption) (*QueryAggregateVoteResponse, error) { + out := new(QueryAggregateVoteResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/AggregateVote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AggregateVotes(ctx context.Context, in *QueryAggregateVotesRequest, opts ...grpc.CallOption) (*QueryAggregateVotesResponse, error) { + out := new(QueryAggregateVotesResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/AggregateVotes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // ExchangeRate returns exchange rate of a denom + ExchangeRate(context.Context, *QueryExchangeRateRequest) (*QueryExchangeRateResponse, error) + // ExchangeRates returns exchange rates of all denoms + ExchangeRates(context.Context, *QueryExchangeRatesRequest) (*QueryExchangeRatesResponse, error) + // Actives returns all active denoms + Actives(context.Context, *QueryActivesRequest) (*QueryActivesResponse, error) + // VoteTargets returns all vote target denoms + VoteTargets(context.Context, *QueryVoteTargetsRequest) (*QueryVoteTargetsResponse, error) + // FeederDelegation returns feeder delegation of a validator + FeederDelegation(context.Context, *QueryFeederDelegationRequest) (*QueryFeederDelegationResponse, error) + // MissCounter returns oracle miss counter of a validator + MissCounter(context.Context, *QueryMissCounterRequest) (*QueryMissCounterResponse, error) + // AggregatePrevote returns an aggregate prevote of a validator + AggregatePrevote(context.Context, *QueryAggregatePrevoteRequest) (*QueryAggregatePrevoteResponse, error) + // AggregatePrevotes returns aggregate prevotes of all validators + AggregatePrevotes(context.Context, *QueryAggregatePrevotesRequest) (*QueryAggregatePrevotesResponse, error) + // AggregateVote returns an aggregate vote of a validator + AggregateVote(context.Context, *QueryAggregateVoteRequest) (*QueryAggregateVoteResponse, error) + // AggregateVotes returns aggregate votes of all validators + AggregateVotes(context.Context, *QueryAggregateVotesRequest) (*QueryAggregateVotesResponse, error) + // Params queries all parameters. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) ExchangeRate(ctx context.Context, req *QueryExchangeRateRequest) (*QueryExchangeRateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExchangeRate not implemented") +} +func (*UnimplementedQueryServer) ExchangeRates(ctx context.Context, req *QueryExchangeRatesRequest) (*QueryExchangeRatesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExchangeRates not implemented") +} +func (*UnimplementedQueryServer) Actives(ctx context.Context, req *QueryActivesRequest) (*QueryActivesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Actives not implemented") +} +func (*UnimplementedQueryServer) VoteTargets(ctx context.Context, req *QueryVoteTargetsRequest) (*QueryVoteTargetsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteTargets not implemented") +} +func (*UnimplementedQueryServer) FeederDelegation(ctx context.Context, req *QueryFeederDelegationRequest) (*QueryFeederDelegationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeederDelegation not implemented") +} +func (*UnimplementedQueryServer) MissCounter(ctx context.Context, req *QueryMissCounterRequest) (*QueryMissCounterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MissCounter not implemented") +} +func (*UnimplementedQueryServer) AggregatePrevote(ctx context.Context, req *QueryAggregatePrevoteRequest) (*QueryAggregatePrevoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AggregatePrevote not implemented") +} +func (*UnimplementedQueryServer) AggregatePrevotes(ctx context.Context, req *QueryAggregatePrevotesRequest) (*QueryAggregatePrevotesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AggregatePrevotes not implemented") +} +func (*UnimplementedQueryServer) AggregateVote(ctx context.Context, req *QueryAggregateVoteRequest) (*QueryAggregateVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AggregateVote not implemented") +} +func (*UnimplementedQueryServer) AggregateVotes(ctx context.Context, req *QueryAggregateVotesRequest) (*QueryAggregateVotesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AggregateVotes not implemented") +} +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_ExchangeRate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryExchangeRateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ExchangeRate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/ExchangeRate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ExchangeRate(ctx, req.(*QueryExchangeRateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ExchangeRates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryExchangeRatesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ExchangeRates(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/ExchangeRates", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ExchangeRates(ctx, req.(*QueryExchangeRatesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Actives_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryActivesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Actives(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/Actives", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Actives(ctx, req.(*QueryActivesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VoteTargets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVoteTargetsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VoteTargets(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/VoteTargets", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VoteTargets(ctx, req.(*QueryVoteTargetsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_FeederDelegation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFeederDelegationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FeederDelegation(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/FeederDelegation", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FeederDelegation(ctx, req.(*QueryFeederDelegationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_MissCounter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryMissCounterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).MissCounter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/MissCounter", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).MissCounter(ctx, req.(*QueryMissCounterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AggregatePrevote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAggregatePrevoteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AggregatePrevote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/AggregatePrevote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AggregatePrevote(ctx, req.(*QueryAggregatePrevoteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AggregatePrevotes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAggregatePrevotesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AggregatePrevotes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/AggregatePrevotes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AggregatePrevotes(ctx, req.(*QueryAggregatePrevotesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AggregateVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAggregateVoteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AggregateVote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/AggregateVote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AggregateVote(ctx, req.(*QueryAggregateVoteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AggregateVotes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAggregateVotesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AggregateVotes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/AggregateVotes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AggregateVotes(ctx, req.(*QueryAggregateVotesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "seiprotocol.seichain.oracle.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ExchangeRate", + Handler: _Query_ExchangeRate_Handler, + }, + { + MethodName: "ExchangeRates", + Handler: _Query_ExchangeRates_Handler, + }, + { + MethodName: "Actives", + Handler: _Query_Actives_Handler, + }, + { + MethodName: "VoteTargets", + Handler: _Query_VoteTargets_Handler, + }, + { + MethodName: "FeederDelegation", + Handler: _Query_FeederDelegation_Handler, + }, + { + MethodName: "MissCounter", + Handler: _Query_MissCounter_Handler, + }, + { + MethodName: "AggregatePrevote", + Handler: _Query_AggregatePrevote_Handler, + }, + { + MethodName: "AggregatePrevotes", + Handler: _Query_AggregatePrevotes_Handler, + }, + { + MethodName: "AggregateVote", + Handler: _Query_AggregateVote_Handler, + }, + { + MethodName: "AggregateVotes", + Handler: _Query_AggregateVotes_Handler, + }, + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "oracle/query.proto", +} + +func (m *QueryExchangeRateRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryExchangeRateRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryExchangeRateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryExchangeRateResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryExchangeRateResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryExchangeRateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.ExchangeRate.Size() + i -= size + if _, err := m.ExchangeRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryExchangeRatesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryExchangeRatesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryExchangeRatesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryExchangeRatesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryExchangeRatesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryExchangeRatesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ExchangeRates) > 0 { + for iNdEx := len(m.ExchangeRates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ExchangeRates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryActivesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryActivesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryActivesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryActivesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryActivesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryActivesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Actives) > 0 { + for iNdEx := len(m.Actives) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Actives[iNdEx]) + copy(dAtA[i:], m.Actives[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Actives[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteTargetsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryVoteTargetsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteTargetsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryVoteTargetsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryVoteTargetsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteTargetsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteTargets) > 0 { + for iNdEx := len(m.VoteTargets) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.VoteTargets[iNdEx]) + copy(dAtA[i:], m.VoteTargets[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.VoteTargets[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryFeederDelegationRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryFeederDelegationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeederDelegationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ValidatorAddr) > 0 { + i -= len(m.ValidatorAddr) + copy(dAtA[i:], m.ValidatorAddr) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ValidatorAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryFeederDelegationResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryFeederDelegationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeederDelegationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.FeederAddr) > 0 { + i -= len(m.FeederAddr) + copy(dAtA[i:], m.FeederAddr) + i = encodeVarintQuery(dAtA, i, uint64(len(m.FeederAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryMissCounterRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryMissCounterRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMissCounterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ValidatorAddr) > 0 { + i -= len(m.ValidatorAddr) + copy(dAtA[i:], m.ValidatorAddr) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ValidatorAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryMissCounterResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryMissCounterResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMissCounterResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MissCounter != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.MissCounter)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryAggregatePrevoteRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregatePrevoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregatePrevoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ValidatorAddr) > 0 { + i -= len(m.ValidatorAddr) + copy(dAtA[i:], m.ValidatorAddr) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ValidatorAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAggregatePrevoteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregatePrevoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregatePrevoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.AggregatePrevote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryAggregatePrevotesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregatePrevotesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregatePrevotesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryAggregatePrevotesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregatePrevotesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregatePrevotesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AggregatePrevotes) > 0 { + for iNdEx := len(m.AggregatePrevotes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AggregatePrevotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryAggregateVoteRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregateVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregateVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ValidatorAddr) > 0 { + i -= len(m.ValidatorAddr) + copy(dAtA[i:], m.ValidatorAddr) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ValidatorAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAggregateVoteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregateVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregateVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.AggregateVote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryAggregateVotesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregateVotesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregateVotesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryAggregateVotesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryAggregateVotesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAggregateVotesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AggregateVotes) > 0 { + for iNdEx := len(m.AggregateVotes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AggregateVotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryExchangeRateRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryExchangeRateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ExchangeRate.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryExchangeRatesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryExchangeRatesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ExchangeRates) > 0 { + for _, e := range m.ExchangeRates { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryActivesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryActivesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Actives) > 0 { + for _, s := range m.Actives { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryVoteTargetsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryVoteTargetsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.VoteTargets) > 0 { + for _, s := range m.VoteTargets { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryFeederDelegationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ValidatorAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeederDelegationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FeederAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryMissCounterRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ValidatorAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryMissCounterResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MissCounter != 0 { + n += 1 + sovQuery(uint64(m.MissCounter)) + } + return n +} + +func (m *QueryAggregatePrevoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ValidatorAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAggregatePrevoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.AggregatePrevote.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryAggregatePrevotesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryAggregatePrevotesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AggregatePrevotes) > 0 { + for _, e := range m.AggregatePrevotes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryAggregateVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ValidatorAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAggregateVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.AggregateVote.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryAggregateVotesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryAggregateVotesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AggregateVotes) > 0 { + for _, e := range m.AggregateVotes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryExchangeRateRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryExchangeRateRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryExchangeRateRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryExchangeRateResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryExchangeRateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryExchangeRateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExchangeRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryExchangeRatesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryExchangeRatesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryExchangeRatesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryExchangeRatesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryExchangeRatesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryExchangeRatesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExchangeRates = append(m.ExchangeRates, types.DecCoin{}) + if err := m.ExchangeRates[len(m.ExchangeRates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryActivesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryActivesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryActivesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryActivesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryActivesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryActivesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Actives", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Actives = append(m.Actives, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteTargetsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryVoteTargetsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteTargetsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteTargetsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryVoteTargetsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteTargetsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteTargets", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteTargets = append(m.VoteTargets, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeederDelegationRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryFeederDelegationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeederDelegationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeederDelegationResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryFeederDelegationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeederDelegationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeederAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FeederAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryMissCounterRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryMissCounterRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMissCounterRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryMissCounterResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryMissCounterResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMissCounterResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MissCounter", wireType) + } + m.MissCounter = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MissCounter |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregatePrevoteRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregatePrevoteRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregatePrevoteRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregatePrevoteResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregatePrevoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregatePrevoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregatePrevote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.AggregatePrevote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregatePrevotesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregatePrevotesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregatePrevotesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregatePrevotesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregatePrevotesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregatePrevotesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregatePrevotes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AggregatePrevotes = append(m.AggregatePrevotes, AggregateExchangeRatePrevote{}) + if err := m.AggregatePrevotes[len(m.AggregatePrevotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregateVoteRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregateVoteRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregateVoteRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregateVoteResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregateVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregateVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregateVote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.AggregateVote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregateVotesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregateVotesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregateVotesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAggregateVotesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAggregateVotesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAggregateVotesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregateVotes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AggregateVotes = append(m.AggregateVotes, AggregateExchangeRateVote{}) + if err := m.AggregateVotes[len(m.AggregateVotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/oracle/types/query.pb.gw.go b/x/oracle/types/query.pb.gw.go new file mode 100644 index 0000000000..fe1975a6f8 --- /dev/null +++ b/x/oracle/types/query.pb.gw.go @@ -0,0 +1,983 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: oracle/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_ExchangeRate_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryExchangeRateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := client.ExchangeRate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ExchangeRate_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryExchangeRateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.ExchangeRate(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_ExchangeRates_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryExchangeRatesRequest + var metadata runtime.ServerMetadata + + msg, err := client.ExchangeRates(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ExchangeRates_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryExchangeRatesRequest + var metadata runtime.ServerMetadata + + msg, err := server.ExchangeRates(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Actives_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryActivesRequest + var metadata runtime.ServerMetadata + + msg, err := client.Actives(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Actives_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryActivesRequest + var metadata runtime.ServerMetadata + + msg, err := server.Actives(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_VoteTargets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteTargetsRequest + var metadata runtime.ServerMetadata + + msg, err := client.VoteTargets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VoteTargets_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteTargetsRequest + var metadata runtime.ServerMetadata + + msg, err := server.VoteTargets(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_FeederDelegation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeederDelegationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := client.FeederDelegation(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FeederDelegation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeederDelegationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.FeederDelegation(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_MissCounter_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMissCounterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := client.MissCounter(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_MissCounter_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMissCounterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.MissCounter(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AggregatePrevote_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregatePrevoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := client.AggregatePrevote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AggregatePrevote_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregatePrevoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.AggregatePrevote(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AggregatePrevotes_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregatePrevotesRequest + var metadata runtime.ServerMetadata + + msg, err := client.AggregatePrevotes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AggregatePrevotes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregatePrevotesRequest + var metadata runtime.ServerMetadata + + msg, err := server.AggregatePrevotes(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AggregateVote_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregateVoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := client.AggregateVote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AggregateVote_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregateVoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.AggregateVote(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AggregateVotes_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregateVotesRequest + var metadata runtime.ServerMetadata + + msg, err := client.AggregateVotes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AggregateVotes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAggregateVotesRequest + var metadata runtime.ServerMetadata + + msg, err := server.AggregateVotes(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_ExchangeRate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ExchangeRate_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ExchangeRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ExchangeRates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ExchangeRates_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ExchangeRates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Actives_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Actives_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Actives_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VoteTargets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VoteTargets_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteTargets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FeederDelegation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FeederDelegation_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeederDelegation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_MissCounter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_MissCounter_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_MissCounter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregatePrevote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AggregatePrevote_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregatePrevote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregatePrevotes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AggregatePrevotes_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregatePrevotes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregateVote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AggregateVote_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregateVote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregateVotes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AggregateVotes_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregateVotes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_ExchangeRate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ExchangeRate_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ExchangeRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ExchangeRates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ExchangeRates_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ExchangeRates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Actives_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Actives_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Actives_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VoteTargets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VoteTargets_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteTargets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FeederDelegation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_FeederDelegation_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeederDelegation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_MissCounter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_MissCounter_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_MissCounter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregatePrevote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AggregatePrevote_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregatePrevote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregatePrevotes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AggregatePrevotes_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregatePrevotes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregateVote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AggregateVote_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregateVote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AggregateVotes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AggregateVotes_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AggregateVotes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_ExchangeRate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"sei-protocol", "sei-chain", "oracle", "denoms", "denom", "exchange_rate"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_ExchangeRates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"sei-protocol", "sei-chain", "oracle", "denoms", "exchange_rates"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Actives_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"sei-protocol", "sei-chain", "oracle", "denoms", "actives"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VoteTargets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"sei-protocol", "sei-chain", "oracle", "enoms", "vote_targets"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_FeederDelegation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"sei-protocol", "sei-chain", "oracle", "validators", "validator_addr", "feeder"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_MissCounter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"sei-protocol", "sei-chain", "oracle", "validators", "validator_addr", "miss"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_AggregatePrevote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"sei-protocol", "sei-chain", "oracle", "validators", "validator_addr", "aggregate_prevote"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_AggregatePrevotes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"sei-protocol", "sei-chain", "oracle", "validators", "aggregate_prevotes"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_AggregateVote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"sei-protocol", "sei-chain", "oracle", "valdiators", "validator_addr", "aggregate_vote"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_AggregateVotes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"sei-protocol", "sei-chain", "oracle", "validators", "aggregate_votes"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"sei-protocol", "sei-chain", "oracle", "params"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_ExchangeRate_0 = runtime.ForwardResponseMessage + + forward_Query_ExchangeRates_0 = runtime.ForwardResponseMessage + + forward_Query_Actives_0 = runtime.ForwardResponseMessage + + forward_Query_VoteTargets_0 = runtime.ForwardResponseMessage + + forward_Query_FeederDelegation_0 = runtime.ForwardResponseMessage + + forward_Query_MissCounter_0 = runtime.ForwardResponseMessage + + forward_Query_AggregatePrevote_0 = runtime.ForwardResponseMessage + + forward_Query_AggregatePrevotes_0 = runtime.ForwardResponseMessage + + forward_Query_AggregateVote_0 = runtime.ForwardResponseMessage + + forward_Query_AggregateVotes_0 = runtime.ForwardResponseMessage + + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/oracle/types/test_utils.go b/x/oracle/types/test_utils.go new file mode 100755 index 0000000000..b5692bf130 --- /dev/null +++ b/x/oracle/types/test_utils.go @@ -0,0 +1,154 @@ +//nolint +package types + +import ( + "math" + "math/rand" + "time" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/tendermint/tendermint/crypto/secp256k1" + tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" +) + +// OracleDecPrecision nolint +const OracleDecPrecision = 8 + +// GenerateRandomTestCase nolint +func GenerateRandomTestCase() (rates []float64, valValAddrs []sdk.ValAddress, stakingKeeper DummyStakingKeeper) { + valValAddrs = []sdk.ValAddress{} + mockValidators := []MockValidator{} + + base := math.Pow10(OracleDecPrecision) + + rand.Seed(int64(time.Now().Nanosecond())) + numInputs := 10 + (rand.Int() % 100) + for i := 0; i < numInputs; i++ { + rate := float64(int64(rand.Float64()*base)) / base + rates = append(rates, rate) + + pubKey := secp256k1.GenPrivKey().PubKey() + valValAddr := sdk.ValAddress(pubKey.Address()) + valValAddrs = append(valValAddrs, valValAddr) + + power := rand.Int63()%1000 + 1 + mockValidator := NewMockValidator(valValAddr, power) + mockValidators = append(mockValidators, mockValidator) + } + + stakingKeeper = NewDummyStakingKeeper(mockValidators) + + return +} + +var _ StakingKeeper = DummyStakingKeeper{} + +// DummyStakingKeeper dummy staking keeper to test ballot +type DummyStakingKeeper struct { + validators []MockValidator +} + +// NewDummyStakingKeeper returns new DummyStakingKeeper instance +func NewDummyStakingKeeper(validators []MockValidator) DummyStakingKeeper { + return DummyStakingKeeper{ + validators: validators, + } +} + +// Validators nolint +func (sk DummyStakingKeeper) Validators() []MockValidator { + return sk.validators +} + +// Validator nolint +func (sk DummyStakingKeeper) Validator(ctx sdk.Context, address sdk.ValAddress) stakingtypes.ValidatorI { + for _, validator := range sk.validators { + if validator.GetOperator().Equals(address) { + return validator + } + } + + return nil +} + +// TotalBondedTokens nolint +func (DummyStakingKeeper) TotalBondedTokens(_ sdk.Context) sdk.Int { + return sdk.ZeroInt() +} + +// Slash nolint +func (DummyStakingKeeper) Slash(sdk.Context, sdk.ConsAddress, int64, int64, sdk.Dec) {} + +// ValidatorsPowerStoreIterator nolint +func (DummyStakingKeeper) ValidatorsPowerStoreIterator(ctx sdk.Context) sdk.Iterator { + return sdk.KVStoreReversePrefixIterator(nil, nil) +} + +// Jail nolint +func (DummyStakingKeeper) Jail(sdk.Context, sdk.ConsAddress) { +} + +// GetLastValidatorPower nolint +func (sk DummyStakingKeeper) GetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) (power int64) { + return sk.Validator(ctx, operator).GetConsensusPower(sdk.DefaultPowerReduction) +} + +// MaxValidators returns the maximum amount of bonded validators +func (DummyStakingKeeper) MaxValidators(sdk.Context) uint32 { + return 100 +} + +// PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power +func (DummyStakingKeeper) PowerReduction(ctx sdk.Context) (res sdk.Int) { + res = sdk.DefaultPowerReduction + return +} + +// MockValidator nolint +type MockValidator struct { + power int64 + operator sdk.ValAddress +} + +var _ stakingtypes.ValidatorI = MockValidator{} + +func (MockValidator) IsJailed() bool { return false } +func (MockValidator) GetMoniker() string { return "" } +func (MockValidator) GetStatus() stakingtypes.BondStatus { return stakingtypes.Bonded } +func (MockValidator) IsBonded() bool { return true } +func (MockValidator) IsUnbonded() bool { return false } +func (MockValidator) IsUnbonding() bool { return false } +func (v MockValidator) GetOperator() sdk.ValAddress { return v.operator } +func (MockValidator) ConsPubKey() (cryptotypes.PubKey, error) { return nil, nil } +func (MockValidator) TmConsPublicKey() (tmprotocrypto.PublicKey, error) { + return tmprotocrypto.PublicKey{}, nil +} +func (MockValidator) GetConsAddr() (sdk.ConsAddress, error) { return nil, nil } +func (v MockValidator) GetTokens() sdk.Int { + return sdk.TokensFromConsensusPower(v.power, sdk.DefaultPowerReduction) +} +func (v MockValidator) GetBondedTokens() sdk.Int { + return sdk.TokensFromConsensusPower(v.power, sdk.DefaultPowerReduction) +} +func (v MockValidator) GetConsensusPower(powerReduction sdk.Int) int64 { return v.power } +func (v *MockValidator) SetConsensusPower(power int64) { v.power = power } +func (v MockValidator) GetCommission() sdk.Dec { return sdk.ZeroDec() } +func (v MockValidator) GetMinSelfDelegation() sdk.Int { return sdk.OneInt() } +func (v MockValidator) GetDelegatorShares() sdk.Dec { return sdk.NewDec(v.power) } +func (v MockValidator) TokensFromShares(sdk.Dec) sdk.Dec { return sdk.ZeroDec() } +func (v MockValidator) TokensFromSharesTruncated(sdk.Dec) sdk.Dec { return sdk.ZeroDec() } +func (v MockValidator) TokensFromSharesRoundUp(sdk.Dec) sdk.Dec { return sdk.ZeroDec() } +func (v MockValidator) SharesFromTokens(amt sdk.Int) (sdk.Dec, error) { return sdk.ZeroDec(), nil } +func (v MockValidator) SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, error) { + return sdk.ZeroDec(), nil +} + +func NewMockValidator(valAddr sdk.ValAddress, power int64) MockValidator { + return MockValidator{ + power: power, + operator: valAddr, + } +} diff --git a/x/oracle/types/tx.pb.go b/x/oracle/types/tx.pb.go new file mode 100644 index 0000000000..b657d6a98d --- /dev/null +++ b/x/oracle/types/tx.pb.go @@ -0,0 +1,1455 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgAggregateExchangeRatePrevote represents a message to submit +// aggregate exchange rate prevote. +type MsgAggregateExchangeRatePrevote struct { + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty" yaml:"hash"` + Feeder string `protobuf:"bytes,2,opt,name=feeder,proto3" json:"feeder,omitempty" yaml:"feeder"` + Validator string `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty" yaml:"validator"` +} + +func (m *MsgAggregateExchangeRatePrevote) Reset() { *m = MsgAggregateExchangeRatePrevote{} } +func (m *MsgAggregateExchangeRatePrevote) String() string { return proto.CompactTextString(m) } +func (*MsgAggregateExchangeRatePrevote) ProtoMessage() {} +func (*MsgAggregateExchangeRatePrevote) Descriptor() ([]byte, []int) { + return fileDescriptor_cb5390096518ffda, []int{0} +} +func (m *MsgAggregateExchangeRatePrevote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAggregateExchangeRatePrevote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAggregateExchangeRatePrevote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAggregateExchangeRatePrevote) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAggregateExchangeRatePrevote.Merge(m, src) +} +func (m *MsgAggregateExchangeRatePrevote) XXX_Size() int { + return m.Size() +} +func (m *MsgAggregateExchangeRatePrevote) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAggregateExchangeRatePrevote.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAggregateExchangeRatePrevote proto.InternalMessageInfo + +// MsgAggregateExchangeRatePrevoteResponse defines the Msg/AggregateExchangeRatePrevote response type. +type MsgAggregateExchangeRatePrevoteResponse struct { +} + +func (m *MsgAggregateExchangeRatePrevoteResponse) Reset() { + *m = MsgAggregateExchangeRatePrevoteResponse{} +} +func (m *MsgAggregateExchangeRatePrevoteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAggregateExchangeRatePrevoteResponse) ProtoMessage() {} +func (*MsgAggregateExchangeRatePrevoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_cb5390096518ffda, []int{1} +} +func (m *MsgAggregateExchangeRatePrevoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAggregateExchangeRatePrevoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAggregateExchangeRatePrevoteResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAggregateExchangeRatePrevoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAggregateExchangeRatePrevoteResponse.Merge(m, src) +} +func (m *MsgAggregateExchangeRatePrevoteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgAggregateExchangeRatePrevoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAggregateExchangeRatePrevoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAggregateExchangeRatePrevoteResponse proto.InternalMessageInfo + +// MsgAggregateExchangeRateVote represents a message to submit +// aggregate exchange rate vote. +type MsgAggregateExchangeRateVote struct { + Salt string `protobuf:"bytes,1,opt,name=salt,proto3" json:"salt,omitempty" yaml:"salt"` + ExchangeRates string `protobuf:"bytes,2,opt,name=exchange_rates,json=exchangeRates,proto3" json:"exchange_rates,omitempty" yaml:"exchange_rates"` + Feeder string `protobuf:"bytes,3,opt,name=feeder,proto3" json:"feeder,omitempty" yaml:"feeder"` + Validator string `protobuf:"bytes,4,opt,name=validator,proto3" json:"validator,omitempty" yaml:"validator"` +} + +func (m *MsgAggregateExchangeRateVote) Reset() { *m = MsgAggregateExchangeRateVote{} } +func (m *MsgAggregateExchangeRateVote) String() string { return proto.CompactTextString(m) } +func (*MsgAggregateExchangeRateVote) ProtoMessage() {} +func (*MsgAggregateExchangeRateVote) Descriptor() ([]byte, []int) { + return fileDescriptor_cb5390096518ffda, []int{2} +} +func (m *MsgAggregateExchangeRateVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAggregateExchangeRateVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAggregateExchangeRateVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAggregateExchangeRateVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAggregateExchangeRateVote.Merge(m, src) +} +func (m *MsgAggregateExchangeRateVote) XXX_Size() int { + return m.Size() +} +func (m *MsgAggregateExchangeRateVote) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAggregateExchangeRateVote.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAggregateExchangeRateVote proto.InternalMessageInfo + +// MsgAggregateExchangeRateVoteResponse defines the Msg/AggregateExchangeRateVote response type. +type MsgAggregateExchangeRateVoteResponse struct { +} + +func (m *MsgAggregateExchangeRateVoteResponse) Reset() { *m = MsgAggregateExchangeRateVoteResponse{} } +func (m *MsgAggregateExchangeRateVoteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAggregateExchangeRateVoteResponse) ProtoMessage() {} +func (*MsgAggregateExchangeRateVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_cb5390096518ffda, []int{3} +} +func (m *MsgAggregateExchangeRateVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAggregateExchangeRateVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAggregateExchangeRateVoteResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAggregateExchangeRateVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAggregateExchangeRateVoteResponse.Merge(m, src) +} +func (m *MsgAggregateExchangeRateVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgAggregateExchangeRateVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAggregateExchangeRateVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAggregateExchangeRateVoteResponse proto.InternalMessageInfo + +// MsgDelegateFeedConsent represents a message to +// delegate oracle voting rights to another address. +type MsgDelegateFeedConsent struct { + Operator string `protobuf:"bytes,1,opt,name=operator,proto3" json:"operator,omitempty" yaml:"operator"` + Delegate string `protobuf:"bytes,2,opt,name=delegate,proto3" json:"delegate,omitempty" yaml:"delegate"` +} + +func (m *MsgDelegateFeedConsent) Reset() { *m = MsgDelegateFeedConsent{} } +func (m *MsgDelegateFeedConsent) String() string { return proto.CompactTextString(m) } +func (*MsgDelegateFeedConsent) ProtoMessage() {} +func (*MsgDelegateFeedConsent) Descriptor() ([]byte, []int) { + return fileDescriptor_cb5390096518ffda, []int{4} +} +func (m *MsgDelegateFeedConsent) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDelegateFeedConsent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDelegateFeedConsent.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgDelegateFeedConsent) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDelegateFeedConsent.Merge(m, src) +} +func (m *MsgDelegateFeedConsent) XXX_Size() int { + return m.Size() +} +func (m *MsgDelegateFeedConsent) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDelegateFeedConsent.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDelegateFeedConsent proto.InternalMessageInfo + +// MsgDelegateFeedConsentResponse defines the Msg/DelegateFeedConsent response type. +type MsgDelegateFeedConsentResponse struct { +} + +func (m *MsgDelegateFeedConsentResponse) Reset() { *m = MsgDelegateFeedConsentResponse{} } +func (m *MsgDelegateFeedConsentResponse) String() string { return proto.CompactTextString(m) } +func (*MsgDelegateFeedConsentResponse) ProtoMessage() {} +func (*MsgDelegateFeedConsentResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_cb5390096518ffda, []int{5} +} +func (m *MsgDelegateFeedConsentResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDelegateFeedConsentResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDelegateFeedConsentResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgDelegateFeedConsentResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDelegateFeedConsentResponse.Merge(m, src) +} +func (m *MsgDelegateFeedConsentResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgDelegateFeedConsentResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDelegateFeedConsentResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDelegateFeedConsentResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgAggregateExchangeRatePrevote)(nil), "seiprotocol.seichain.oracle.MsgAggregateExchangeRatePrevote") + proto.RegisterType((*MsgAggregateExchangeRatePrevoteResponse)(nil), "seiprotocol.seichain.oracle.MsgAggregateExchangeRatePrevoteResponse") + proto.RegisterType((*MsgAggregateExchangeRateVote)(nil), "seiprotocol.seichain.oracle.MsgAggregateExchangeRateVote") + proto.RegisterType((*MsgAggregateExchangeRateVoteResponse)(nil), "seiprotocol.seichain.oracle.MsgAggregateExchangeRateVoteResponse") + proto.RegisterType((*MsgDelegateFeedConsent)(nil), "seiprotocol.seichain.oracle.MsgDelegateFeedConsent") + proto.RegisterType((*MsgDelegateFeedConsentResponse)(nil), "seiprotocol.seichain.oracle.MsgDelegateFeedConsentResponse") +} + +func init() { proto.RegisterFile("oracle/tx.proto", fileDescriptor_cb5390096518ffda) } + +var fileDescriptor_cb5390096518ffda = []byte{ + // 497 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x31, 0x6f, 0xd3, 0x40, + 0x14, 0xc7, 0x7d, 0xa4, 0xaa, 0xda, 0x43, 0x25, 0xe0, 0x16, 0x94, 0x86, 0xca, 0xae, 0x0e, 0x04, + 0x74, 0xc0, 0x46, 0xed, 0x44, 0x61, 0xa0, 0xa5, 0x30, 0x20, 0x45, 0x42, 0x37, 0x30, 0xb0, 0xa0, + 0xab, 0xf3, 0x38, 0x5b, 0x72, 0x73, 0x91, 0xef, 0xa8, 0xd2, 0x1d, 0x09, 0x46, 0x56, 0xb6, 0x8a, + 0x2f, 0xc0, 0xd7, 0x60, 0xcc, 0xc8, 0x64, 0xa1, 0x64, 0x61, 0x62, 0xf0, 0x27, 0x40, 0xbe, 0xb3, + 0x8d, 0x11, 0x69, 0xa2, 0x84, 0xed, 0x72, 0xff, 0xdf, 0xff, 0xde, 0xff, 0xbd, 0x3c, 0x19, 0x37, + 0x45, 0xc2, 0x82, 0x18, 0x7c, 0x35, 0xf0, 0xfa, 0x89, 0x50, 0xc2, 0xbe, 0x29, 0x21, 0xd2, 0xa7, + 0x40, 0xc4, 0x9e, 0x84, 0x28, 0x08, 0x59, 0xd4, 0xf3, 0x0c, 0xd5, 0xde, 0xe0, 0x82, 0x0b, 0xad, + 0xfa, 0xf9, 0xc9, 0x58, 0xc8, 0x57, 0x84, 0xdd, 0x8e, 0xe4, 0x07, 0x9c, 0x27, 0xc0, 0x99, 0x82, + 0x67, 0x83, 0x20, 0x64, 0x3d, 0x0e, 0x94, 0x29, 0x78, 0x99, 0xc0, 0xa9, 0x50, 0x60, 0xdf, 0xc2, + 0x4b, 0x21, 0x93, 0x61, 0x0b, 0x6d, 0xa3, 0x7b, 0xab, 0x87, 0xcd, 0x2c, 0x75, 0x2f, 0x9f, 0xb1, + 0x93, 0x78, 0x9f, 0xe4, 0xb7, 0x84, 0x6a, 0xd1, 0xde, 0xc1, 0xcb, 0x6f, 0x01, 0xba, 0x90, 0xb4, + 0x2e, 0x69, 0xec, 0x5a, 0x96, 0xba, 0x6b, 0x06, 0x33, 0xf7, 0x84, 0x16, 0x80, 0xbd, 0x8b, 0x57, + 0x4f, 0x59, 0x1c, 0x75, 0x99, 0x12, 0x49, 0xab, 0xa1, 0xe9, 0x8d, 0x2c, 0x75, 0xaf, 0x1a, 0xba, + 0x92, 0x08, 0xfd, 0x83, 0xed, 0xaf, 0x7c, 0x3c, 0x77, 0xad, 0x9f, 0xe7, 0xae, 0x45, 0x76, 0xf0, + 0xdd, 0x19, 0x81, 0x29, 0xc8, 0xbe, 0xe8, 0x49, 0x20, 0xbf, 0x10, 0xde, 0xba, 0x88, 0x7d, 0x55, + 0x74, 0x26, 0x59, 0xac, 0xfe, 0xed, 0x2c, 0xbf, 0x25, 0x54, 0x8b, 0xf6, 0x13, 0x7c, 0x05, 0x0a, + 0xe3, 0x9b, 0x84, 0x29, 0x90, 0x45, 0x87, 0x9b, 0x59, 0xea, 0x5e, 0x37, 0xf8, 0xdf, 0x3a, 0xa1, + 0x6b, 0x50, 0xab, 0x24, 0x6b, 0xb3, 0x69, 0xcc, 0x35, 0x9b, 0xa5, 0x79, 0x67, 0x73, 0x07, 0xdf, + 0x9e, 0xd6, 0x6f, 0x35, 0x98, 0xf7, 0x08, 0xdf, 0xe8, 0x48, 0x7e, 0x04, 0xb1, 0xe6, 0x9e, 0x03, + 0x74, 0x9f, 0xe6, 0x42, 0x4f, 0xd9, 0x3e, 0x5e, 0x11, 0x7d, 0x48, 0x74, 0x7d, 0x33, 0x96, 0xf5, + 0x2c, 0x75, 0x9b, 0xa6, 0x7e, 0xa9, 0x10, 0x5a, 0x41, 0xb9, 0xa1, 0x5b, 0xbc, 0x53, 0x0c, 0xa6, + 0x66, 0x28, 0x15, 0x42, 0x2b, 0xa8, 0x16, 0x77, 0x1b, 0x3b, 0x93, 0x53, 0x94, 0x41, 0x77, 0x87, + 0x0d, 0xdc, 0xe8, 0x48, 0x6e, 0x7f, 0x41, 0x78, 0x6b, 0xea, 0x8e, 0x3e, 0xf6, 0xa6, 0xec, 0xbe, + 0x37, 0x63, 0x61, 0xda, 0x47, 0xff, 0xe3, 0x2e, 0xc3, 0xda, 0x9f, 0x11, 0xde, 0xbc, 0x78, 0xd7, + 0x1e, 0x2e, 0x54, 0x23, 0xb7, 0xb6, 0x0f, 0x16, 0xb6, 0x56, 0xd9, 0x3e, 0x20, 0xbc, 0x3e, 0xe9, + 0xef, 0xde, 0x9b, 0xf5, 0xf4, 0x04, 0x53, 0xfb, 0xd1, 0x02, 0xa6, 0x32, 0xc9, 0xe1, 0x8b, 0x6f, + 0x23, 0x07, 0x0d, 0x47, 0x0e, 0xfa, 0x31, 0x72, 0xd0, 0xa7, 0xb1, 0x63, 0x0d, 0xc7, 0x8e, 0xf5, + 0x7d, 0xec, 0x58, 0xaf, 0x1f, 0xf0, 0x48, 0x85, 0xef, 0x8e, 0xbd, 0x40, 0x9c, 0xf8, 0x12, 0xa2, + 0xfb, 0x65, 0x05, 0xfd, 0x43, 0x97, 0xf0, 0x07, 0x7e, 0xf9, 0xcd, 0x3b, 0xeb, 0x83, 0x3c, 0x5e, + 0xd6, 0xc8, 0xde, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5e, 0xce, 0x17, 0xb4, 0x0a, 0x05, 0x00, + 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // AggregateExchangeRatePrevote defines a method for submitting + // aggregate exchange rate prevote + AggregateExchangeRatePrevote(ctx context.Context, in *MsgAggregateExchangeRatePrevote, opts ...grpc.CallOption) (*MsgAggregateExchangeRatePrevoteResponse, error) + // AggregateExchangeRateVote defines a method for submitting + // aggregate exchange rate vote + AggregateExchangeRateVote(ctx context.Context, in *MsgAggregateExchangeRateVote, opts ...grpc.CallOption) (*MsgAggregateExchangeRateVoteResponse, error) + // DelegateFeedConsent defines a method for setting the feeder delegation + DelegateFeedConsent(ctx context.Context, in *MsgDelegateFeedConsent, opts ...grpc.CallOption) (*MsgDelegateFeedConsentResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) AggregateExchangeRatePrevote(ctx context.Context, in *MsgAggregateExchangeRatePrevote, opts ...grpc.CallOption) (*MsgAggregateExchangeRatePrevoteResponse, error) { + out := new(MsgAggregateExchangeRatePrevoteResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Msg/AggregateExchangeRatePrevote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) AggregateExchangeRateVote(ctx context.Context, in *MsgAggregateExchangeRateVote, opts ...grpc.CallOption) (*MsgAggregateExchangeRateVoteResponse, error) { + out := new(MsgAggregateExchangeRateVoteResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Msg/AggregateExchangeRateVote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) DelegateFeedConsent(ctx context.Context, in *MsgDelegateFeedConsent, opts ...grpc.CallOption) (*MsgDelegateFeedConsentResponse, error) { + out := new(MsgDelegateFeedConsentResponse) + err := c.cc.Invoke(ctx, "/seiprotocol.seichain.oracle.Msg/DelegateFeedConsent", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // AggregateExchangeRatePrevote defines a method for submitting + // aggregate exchange rate prevote + AggregateExchangeRatePrevote(context.Context, *MsgAggregateExchangeRatePrevote) (*MsgAggregateExchangeRatePrevoteResponse, error) + // AggregateExchangeRateVote defines a method for submitting + // aggregate exchange rate vote + AggregateExchangeRateVote(context.Context, *MsgAggregateExchangeRateVote) (*MsgAggregateExchangeRateVoteResponse, error) + // DelegateFeedConsent defines a method for setting the feeder delegation + DelegateFeedConsent(context.Context, *MsgDelegateFeedConsent) (*MsgDelegateFeedConsentResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) AggregateExchangeRatePrevote(ctx context.Context, req *MsgAggregateExchangeRatePrevote) (*MsgAggregateExchangeRatePrevoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AggregateExchangeRatePrevote not implemented") +} +func (*UnimplementedMsgServer) AggregateExchangeRateVote(ctx context.Context, req *MsgAggregateExchangeRateVote) (*MsgAggregateExchangeRateVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AggregateExchangeRateVote not implemented") +} +func (*UnimplementedMsgServer) DelegateFeedConsent(ctx context.Context, req *MsgDelegateFeedConsent) (*MsgDelegateFeedConsentResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DelegateFeedConsent not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_AggregateExchangeRatePrevote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAggregateExchangeRatePrevote) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).AggregateExchangeRatePrevote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Msg/AggregateExchangeRatePrevote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).AggregateExchangeRatePrevote(ctx, req.(*MsgAggregateExchangeRatePrevote)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_AggregateExchangeRateVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAggregateExchangeRateVote) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).AggregateExchangeRateVote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Msg/AggregateExchangeRateVote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).AggregateExchangeRateVote(ctx, req.(*MsgAggregateExchangeRateVote)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_DelegateFeedConsent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgDelegateFeedConsent) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).DelegateFeedConsent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/seiprotocol.seichain.oracle.Msg/DelegateFeedConsent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).DelegateFeedConsent(ctx, req.(*MsgDelegateFeedConsent)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "seiprotocol.seichain.oracle.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AggregateExchangeRatePrevote", + Handler: _Msg_AggregateExchangeRatePrevote_Handler, + }, + { + MethodName: "AggregateExchangeRateVote", + Handler: _Msg_AggregateExchangeRateVote_Handler, + }, + { + MethodName: "DelegateFeedConsent", + Handler: _Msg_DelegateFeedConsent_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "oracle/tx.proto", +} + +func (m *MsgAggregateExchangeRatePrevote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAggregateExchangeRatePrevote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAggregateExchangeRatePrevote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Validator) > 0 { + i -= len(m.Validator) + copy(dAtA[i:], m.Validator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Validator))) + i-- + dAtA[i] = 0x1a + } + if len(m.Feeder) > 0 { + i -= len(m.Feeder) + copy(dAtA[i:], m.Feeder) + i = encodeVarintTx(dAtA, i, uint64(len(m.Feeder))) + i-- + dAtA[i] = 0x12 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTx(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgAggregateExchangeRatePrevoteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAggregateExchangeRatePrevoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAggregateExchangeRatePrevoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgAggregateExchangeRateVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAggregateExchangeRateVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAggregateExchangeRateVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Validator) > 0 { + i -= len(m.Validator) + copy(dAtA[i:], m.Validator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Validator))) + i-- + dAtA[i] = 0x22 + } + if len(m.Feeder) > 0 { + i -= len(m.Feeder) + copy(dAtA[i:], m.Feeder) + i = encodeVarintTx(dAtA, i, uint64(len(m.Feeder))) + i-- + dAtA[i] = 0x1a + } + if len(m.ExchangeRates) > 0 { + i -= len(m.ExchangeRates) + copy(dAtA[i:], m.ExchangeRates) + i = encodeVarintTx(dAtA, i, uint64(len(m.ExchangeRates))) + i-- + dAtA[i] = 0x12 + } + if len(m.Salt) > 0 { + i -= len(m.Salt) + copy(dAtA[i:], m.Salt) + i = encodeVarintTx(dAtA, i, uint64(len(m.Salt))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgAggregateExchangeRateVoteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAggregateExchangeRateVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAggregateExchangeRateVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgDelegateFeedConsent) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgDelegateFeedConsent) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDelegateFeedConsent) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Delegate) > 0 { + i -= len(m.Delegate) + copy(dAtA[i:], m.Delegate) + i = encodeVarintTx(dAtA, i, uint64(len(m.Delegate))) + i-- + dAtA[i] = 0x12 + } + if len(m.Operator) > 0 { + i -= len(m.Operator) + copy(dAtA[i:], m.Operator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Operator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgDelegateFeedConsentResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgDelegateFeedConsentResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDelegateFeedConsentResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgAggregateExchangeRatePrevote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Feeder) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Validator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgAggregateExchangeRatePrevoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgAggregateExchangeRateVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Salt) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ExchangeRates) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Feeder) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Validator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgAggregateExchangeRateVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgDelegateFeedConsent) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Operator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Delegate) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgDelegateFeedConsentResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgAggregateExchangeRatePrevote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAggregateExchangeRatePrevote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAggregateExchangeRatePrevote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Feeder", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Feeder = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgAggregateExchangeRatePrevoteResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAggregateExchangeRatePrevoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAggregateExchangeRatePrevoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgAggregateExchangeRateVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAggregateExchangeRateVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAggregateExchangeRateVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Salt = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRates", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExchangeRates = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Feeder", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Feeder = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgAggregateExchangeRateVoteResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAggregateExchangeRateVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAggregateExchangeRateVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDelegateFeedConsent) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDelegateFeedConsent: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDelegateFeedConsent: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Operator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Delegate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Delegate = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDelegateFeedConsentResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDelegateFeedConsentResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDelegateFeedConsentResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/oracle/types/vote.go b/x/oracle/types/vote.go new file mode 100755 index 0000000000..6e4bdf36aa --- /dev/null +++ b/x/oracle/types/vote.go @@ -0,0 +1,93 @@ +package types + +import ( + "fmt" + "strings" + + "gopkg.in/yaml.v2" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NewAggregateExchangeRatePrevote returns AggregateExchangeRatePrevote object +func NewAggregateExchangeRatePrevote(hash AggregateVoteHash, voter sdk.ValAddress, submitBlock uint64) AggregateExchangeRatePrevote { + return AggregateExchangeRatePrevote{ + Hash: hash.String(), + Voter: voter.String(), + SubmitBlock: submitBlock, + } +} + +// String implement stringify +func (v AggregateExchangeRatePrevote) String() string { + out, _ := yaml.Marshal(v) + return string(out) +} + +// NewAggregateExchangeRateVote creates a AggregateExchangeRateVote instance +func NewAggregateExchangeRateVote(exchangeRateTuples ExchangeRateTuples, voter sdk.ValAddress) AggregateExchangeRateVote { + return AggregateExchangeRateVote{ + ExchangeRateTuples: exchangeRateTuples, + Voter: voter.String(), + } +} + +// String implement stringify +func (v AggregateExchangeRateVote) String() string { + out, _ := yaml.Marshal(v) + return string(out) +} + +// NewExchangeRateTuple creates a ExchangeRateTuple instance +func NewExchangeRateTuple(denom string, exchangeRate sdk.Dec) ExchangeRateTuple { + return ExchangeRateTuple{ + denom, + exchangeRate, + } +} + +// String implement stringify +func (v ExchangeRateTuple) String() string { + out, _ := yaml.Marshal(v) + return string(out) +} + +// ExchangeRateTuples - array of ExchangeRateTuple +type ExchangeRateTuples []ExchangeRateTuple + +// String implements fmt.Stringer interface +func (tuples ExchangeRateTuples) String() string { + out, _ := yaml.Marshal(tuples) + return string(out) +} + +// ParseExchangeRateTuples ExchangeRateTuple parser +func ParseExchangeRateTuples(tuplesStr string) (ExchangeRateTuples, error) { + tuplesStr = strings.TrimSpace(tuplesStr) + if len(tuplesStr) == 0 { + return nil, nil + } + + tupleStrs := strings.Split(tuplesStr, ",") + tuples := make(ExchangeRateTuples, len(tupleStrs)) + duplicateCheckMap := make(map[string]bool) + for i, tupleStr := range tupleStrs { + decCoin, err := sdk.ParseDecCoin(tupleStr) + if err != nil { + return nil, err + } + + tuples[i] = ExchangeRateTuple{ + Denom: decCoin.Denom, + ExchangeRate: decCoin.Amount, + } + + if _, ok := duplicateCheckMap[decCoin.Denom]; ok { + return nil, fmt.Errorf("duplicated denom %s", decCoin.Denom) + } + + duplicateCheckMap[decCoin.Denom] = true + } + + return tuples, nil +} diff --git a/x/oracle/types/vote_test.go b/x/oracle/types/vote_test.go new file mode 100755 index 0000000000..df50bb2180 --- /dev/null +++ b/x/oracle/types/vote_test.go @@ -0,0 +1,29 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseExchangeRateTuples(t *testing.T) { + valid := "123.0uluna,123.123ukrw" + _, err := ParseExchangeRateTuples(valid) + require.NoError(t, err) + + duplicatedDenom := "100.0uluna,123.123ukrw,121233.123ukrw" + _, err = ParseExchangeRateTuples(duplicatedDenom) + require.Error(t, err) + + invalidCoins := "123.123" + _, err = ParseExchangeRateTuples(invalidCoins) + require.Error(t, err) + + invalidCoinsWithValid := "123.0uluna,123.1" + _, err = ParseExchangeRateTuples(invalidCoinsWithValid) + require.Error(t, err) + + abstainCoinsWithValid := "0.0uluna,123.1ukrw" + _, err = ParseExchangeRateTuples(abstainCoinsWithValid) + require.NoError(t, err) +} diff --git a/x/oracle/utils/assets.go b/x/oracle/utils/assets.go new file mode 100644 index 0000000000..d07b21a38b --- /dev/null +++ b/x/oracle/utils/assets.go @@ -0,0 +1,12 @@ +package utils + +const ( + MicroUsdcDenom = "uusdc" + MicroSeiDenom = "usei" + MicroAtomDenom = "uatom" + MicroEthDenom = "ueth" + + MicroBaseDenom = MicroUsdcDenom // use usdc until sei's market stablizes + + MicroUnit = int64(1e6) +) diff --git a/x/oracle/utils/period.go b/x/oracle/utils/period.go new file mode 100644 index 0000000000..ea870af2e9 --- /dev/null +++ b/x/oracle/utils/period.go @@ -0,0 +1,18 @@ +package utils + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + BlocksPerMinute = uint64(20) + BlocksPerHour = BlocksPerMinute * 60 + BlocksPerDay = BlocksPerHour * 24 + BlocksPerWeek = BlocksPerDay * 7 + BlocksPerMonth = BlocksPerDay * 30 + BlocksPerYear = BlocksPerDay * 365 +) + +func IsPeriodLastBlock(ctx sdk.Context, blocksPerPeriod uint64) bool { + return ((uint64)(ctx.BlockHeight())+1)%blocksPerPeriod == 0 +}