diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d118449..231351e3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#801](https://github.com/NibiruChain/nibiru/pull/801) - remove unused pair constants * [#788](https://github.com/NibiruChain/nibiru/pull/788) - add --overwrite flag to the nibid init call of localnet.sh +### Features +* [#791](https://github.com/NibiruChain/nibiru/pull/791) Add the x/oracle module + ## [v0.12.1](https://github.com/NibiruChain/nibiru/releases/tag/v0.12.1) - 2022-08-04 * [#796](https://github.com/NibiruChain/nibiru/pull/796) - fix bug that caused that epochKeeper was nil when running epoch hook from Perp module diff --git a/app/ante.go b/app/ante.go index c149854e6..c16cb8b23 100644 --- a/app/ante.go +++ b/app/ante.go @@ -13,7 +13,9 @@ type AnteHandlerOptions struct { IBCKeeper *ibckeeper.Keeper } -/* NewAnteHandler returns and AnteHandler that checks and increments sequence +/* + NewAnteHandler returns and AnteHandler that checks and increments sequence + numbers, checks signatures and account numbers, and deducts fees from the first signer. */ func NewAnteHandler(options AnteHandlerOptions) (sdk.AnteHandler, error) { diff --git a/app/export.go b/app/export.go index 13e884eb2..051be9b97 100644 --- a/app/export.go +++ b/app/export.go @@ -46,7 +46,8 @@ func (app *NibiruApp) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// in favor of export at a block height +// +// in favor of export at a block height func (app *NibiruApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { applyAllowedAddrs := false diff --git a/app/ibc_test.go b/app/ibc_test.go index 03db29c2d..2dc335f02 100644 --- a/app/ibc_test.go +++ b/app/ibc_test.go @@ -23,8 +23,11 @@ import ( "github.com/NibiruChain/nibiru/x/testutil/testapp" ) -/* SetupTestingApp returns the TestingApp and default genesis state used to - initialize the testing app. */ +/* +SetupTestingApp returns the TestingApp and default genesis state used to + + initialize the testing app. +*/ func SetupNibiruTestingApp() ( testingApp ibctesting.TestingApp, defaultGenesis map[string]json.RawMessage, @@ -86,11 +89,13 @@ func TestIBCTestSuite(t *testing.T) { suite.Run(t, new(IBCTestSuite)) } -/* NewIBCTestingTransferPath returns a "path" for testing. - A path contains two endpoints, 'EndpointA' and 'EndpointB' that correspond - to the order of the chains passed into the ibctesting.NewPath function. - A path is a pointer, and its values will be filled in as necessary during - the setup portion of testing. +/* +NewIBCTestingTransferPath returns a "path" for testing. + + A path contains two endpoints, 'EndpointA' and 'EndpointB' that correspond + to the order of the chains passed into the ibctesting.NewPath function. + A path is a pointer, and its values will be filled in as necessary during + the setup portion of testing. */ func NewIBCTestingTransferPath( chainA, chainB *ibctesting.TestChain, diff --git a/cmd/nibid/cmd/root.go b/cmd/nibid/cmd/root.go index 2d36c88da..112c2b79b 100644 --- a/cmd/nibid/cmd/root.go +++ b/cmd/nibid/cmd/root.go @@ -147,10 +147,11 @@ commands, then builds the rosetta root command given a protocol buffers serializer/deserializer. Args: - rootCmd: The root command called once in the 'main.go' of 'nibid'. - encodingConfig: EncodingConfig specifies the concrete encoding types to use - for a given app. This is provided for compatibility between protobuf and - amino implementations. + + rootCmd: The root command called once in the 'main.go' of 'nibid'. + encodingConfig: EncodingConfig specifies the concrete encoding types to use + for a given app. This is provided for compatibility between protobuf and + amino implementations. */ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { cfg := sdk.GetConfig() diff --git a/proto/oracle/v1beta1/genesis.proto b/proto/oracle/v1beta1/genesis.proto new file mode 100644 index 000000000..50005fe2e --- /dev/null +++ b/proto/oracle/v1beta1/genesis.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package nibiru.oracle.v1beta1; + +import "gogoproto/gogo.proto"; +import "oracle/v1beta1/oracle.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/NibiruChain/nibiru/x/oracle/types"; + +// GenesisState defines the oracle module's genesis state. +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]; + repeated TobinTax tobin_taxes = 7 [(gogoproto.nullable) = false]; +} + +// FeederDelegation is the address for where oracle feeder authority are +// delegated to. By default this struct is only used at genesis to feed in +// default feeder addresses. +message FeederDelegation { + string feeder_address = 1; + string validator_address = 2; +} + +// MissCounter defines an miss counter and validator address pair used in +// oracle module's genesis state +message MissCounter { + string validator_address = 1; + uint64 miss_counter = 2; +} + +// TobinTax defines a pair and tobin_tax pair used in +// oracle module's genesis state +message TobinTax { + string pair = 1; + string tobin_tax = 2 + [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; +} \ No newline at end of file diff --git a/proto/oracle/v1beta1/oracle.proto b/proto/oracle/v1beta1/oracle.proto new file mode 100644 index 000000000..80debcc06 --- /dev/null +++ b/proto/oracle/v1beta1/oracle.proto @@ -0,0 +1,99 @@ +syntax = "proto3"; +package nibiru.oracle.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/NibiruChain/nibiru/x/oracle/types"; + +// Params defines the parameters for the oracle module. +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 + ]; + uint64 reward_distribution_window = 4 [(gogoproto.moretags) = "yaml:\"reward_distribution_window\""]; + repeated Pair whitelist = 5 [ + (gogoproto.moretags) = "yaml:\"whitelist\"", + (gogoproto.castrepeated) = "PairList", + (gogoproto.nullable) = false + ]; + string slash_fraction = 6 [ + (gogoproto.moretags) = "yaml:\"slash_fraction\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + uint64 slash_window = 7 [(gogoproto.moretags) = "yaml:\"slash_window\""]; + string min_valid_per_window = 8 [ + (gogoproto.moretags) = "yaml:\"min_valid_per_window\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} + +// Pair is the object that holds configuration of each pair. +message Pair { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string name = 1 [(gogoproto.moretags) = "yaml:\"name\""]; + string tobin_tax = 2 [ + (gogoproto.moretags) = "yaml:\"tobin_tax\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} + +// 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}:({pair},{exchange_rate})|...,({pair},{exchange_rate}):{voter}") +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\""]; +} + +// MsgAggregateExchangeRateVote - struct for voting on +// the exchange rates different assets. +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\""]; +} + +// ExchangeRateTuple - struct to store interpreted exchange rates data to store +message ExchangeRateTuple { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string pair = 1 [(gogoproto.moretags) = "yaml:\"pair\""]; + 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/v1beta1/query.proto b/proto/oracle/v1beta1/query.proto new file mode 100644 index 000000000..3e4b263f2 --- /dev/null +++ b/proto/oracle/v1beta1/query.proto @@ -0,0 +1,253 @@ +syntax = "proto3"; +package nibiru.oracle.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "oracle/v1beta1/oracle.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/NibiruChain/nibiru/x/oracle/types"; + +// Query defines the gRPC querier service. +service Query { + // ExchangeRate returns exchange rate of a pair + rpc ExchangeRate(QueryExchangeRateRequest) returns (QueryExchangeRateResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/pairs/{pair}/exchange_rate"; + } + + // ExchangeRates returns exchange rates of all pairs + rpc ExchangeRates(QueryExchangeRatesRequest) returns (QueryExchangeRatesResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/pairs/exchange_rates"; + } + + // TobinTax returns tobin tax of a pair + rpc TobinTax(QueryTobinTaxRequest) returns (QueryTobinTaxResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/pairs/{pair}/tobin_tax"; + } + + // TobinTaxes returns tobin taxes of all pairs + rpc TobinTaxes(QueryTobinTaxesRequest) returns (QueryTobinTaxesResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/pairs/tobin_taxes"; + } + + // Actives returns all active pairs + rpc Actives(QueryActivesRequest) returns (QueryActivesResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/pairs/actives"; + } + + // VoteTargets returns all vote target for pairs + rpc VoteTargets(QueryVoteTargetsRequest) returns (QueryVoteTargetsResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/pairs/vote_targets"; + } + + // FeederDelegation returns feeder delegation of a validator + rpc FeederDelegation(QueryFeederDelegationRequest) returns (QueryFeederDelegationResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/validators/{validator_addr}/feeder"; + } + + // MissCounter returns oracle miss counter of a validator + rpc MissCounter(QueryMissCounterRequest) returns (QueryMissCounterResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/validators/{validator_addr}/miss"; + } + + // AggregatePrevote returns an aggregate prevote of a validator + rpc AggregatePrevote(QueryAggregatePrevoteRequest) returns (QueryAggregatePrevoteResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/validators/{validator_addr}/aggregate_prevote"; + } + + // AggregatePrevotes returns aggregate prevotes of all validators + rpc AggregatePrevotes(QueryAggregatePrevotesRequest) returns (QueryAggregatePrevotesResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/validators/aggregate_prevotes"; + } + + // AggregateVote returns an aggregate vote of a validator + rpc AggregateVote(QueryAggregateVoteRequest) returns (QueryAggregateVoteResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/valdiators/{validator_addr}/aggregate_vote"; + } + + // AggregateVotes returns aggregate votes of all validators + rpc AggregateVotes(QueryAggregateVotesRequest) returns (QueryAggregateVotesResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/validators/aggregate_votes"; + } + + // Params queries all parameters. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/params"; + } +} + +// QueryExchangeRateRequest is the request type for the Query/ExchangeRate RPC method. +message QueryExchangeRateRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // pair defines the pair to query for. + string pair = 1; +} + +// QueryExchangeRateResponse is response type for the +// Query/ExchangeRate RPC method. +message QueryExchangeRateResponse { + // exchange_rate defines the exchange rate of assets voted by validators + 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 pairs. + repeated ExchangeRateTuple exchange_rates = 1 [ + (gogoproto.castrepeated) = "ExchangeRateTuples", + (gogoproto.nullable) = false + ]; +} + +// QueryTobinTaxRequest is the request type for the Query/TobinTax RPC method. +message QueryTobinTaxRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // pair defines the asset to query for. + string pair = 1; +} + +// QueryTobinTaxResponse is response type for the +// Query/TobinTax RPC method. +message QueryTobinTaxResponse { + // tobin_taxe defines the tobin tax of a pair + string tobin_tax = 1 + [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; +} + +// QueryTobinTaxesRequest is the request type for the Query/TobinTaxes RPC method. +message QueryTobinTaxesRequest {} + +// QueryTobinTaxesResponse is response type for the +// Query/TobinTaxes RPC method. +message QueryTobinTaxesResponse { + // tobin_taxes defines a list of the tobin tax of all whitelisted pairs + repeated Pair tobin_taxes = 1 [ + (gogoproto.moretags) = "yaml:\"tobin_taxes\"", + (gogoproto.castrepeated) = "PairList", + (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 pair which oracle prices agreed 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 pairs 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/v1beta1/tx.proto b/proto/oracle/v1beta1/tx.proto new file mode 100644 index 000000000..cc74400fa --- /dev/null +++ b/proto/oracle/v1beta1/tx.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package nibiru.oracle.v1beta1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/NibiruChain/nibiru/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/common/common.go b/x/common/common.go index c9920ac16..863ded3a8 100644 --- a/x/common/common.go +++ b/x/common/common.go @@ -76,7 +76,9 @@ func (pair AssetPair) SortedName() string { return SortedPairNameFromDenoms([]string{pair.Token0, pair.Token1}) } -/* String returns the string representation of the asset pair. +/* + String returns the string representation of the asset pair. + Note that this differs from the output of the proto-generated 'String' method. */ func (pair AssetPair) String() string { diff --git a/x/dex/keeper/grpc_query.go b/x/dex/keeper/grpc_query.go index 2111c6459..d75ca4ec0 100644 --- a/x/dex/keeper/grpc_query.go +++ b/x/dex/keeper/grpc_query.go @@ -28,12 +28,14 @@ var _ types.QueryServer = queryServer{} Handler for the QueryParamsRequest query. args - ctx: the cosmos-sdk context - req: a QueryParamsRequest proto object + + ctx: the cosmos-sdk context + req: a QueryParamsRequest proto object ret - QueryParamsResponse: the QueryParamsResponse proto object response, containing the params - error: an error if any occurred + + QueryParamsResponse: the QueryParamsResponse proto object response, containing the params + error: an error if any occurred */ func (k queryServer) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { if req == nil { @@ -48,12 +50,14 @@ func (k queryServer) Params(c context.Context, req *types.QueryParamsRequest) (* Handler for the QueryPoolRequest query. args - ctx: the cosmos-sdk context - req: a QueryPoolRequest proto object + + ctx: the cosmos-sdk context + req: a QueryPoolRequest proto object ret - QueryPoolResponse: the QueryPoolResponse proto object response, containing the pool - error: an error if any occurred + + QueryPoolResponse: the QueryPoolResponse proto object response, containing the pool + error: an error if any occurred */ func (k queryServer) Pool(goCtx context.Context, req *types.QueryPoolRequest) (*types.QueryPoolResponse, error) { if req == nil { @@ -74,12 +78,14 @@ func (k queryServer) Pool(goCtx context.Context, req *types.QueryPoolRequest) (* Handler for the QueryPoolNumberRequest query. args - ctx: the cosmos-sdk context - req: a QueryPoolNumberRequest proto object + + ctx: the cosmos-sdk context + req: a QueryPoolNumberRequest proto object ret - QueryPoolNumberResponse: the QueryPoolNumberResponse proto object response, containing the next pool id number - error: an error if any occurred + + QueryPoolNumberResponse: the QueryPoolNumberResponse proto object response, containing the next pool id number + error: an error if any occurred */ func (k queryServer) PoolNumber(goCtx context.Context, req *types.QueryPoolNumberRequest) (*types.QueryPoolNumberResponse, error) { if req == nil { diff --git a/x/dex/keeper/keeper.go b/x/dex/keeper/keeper.go index 7d388fff5..92795d186 100644 --- a/x/dex/keeper/keeper.go +++ b/x/dex/keeper/keeper.go @@ -31,14 +31,16 @@ type ( Creates a new keeper for the dex module. args - cdc: a codec - storeKey: the key-value store key that this keeper uses - ps: the param subspace for this keeper - accountKeeper: the auth module\'s keeper for accounts - bankKeeper: the bank module\'s keeper for bank transfers + + cdc: a codec + storeKey: the key-value store key that this keeper uses + ps: the param subspace for this keeper + accountKeeper: the auth module\'s keeper for accounts + bankKeeper: the bank module\'s keeper for bank transfers ret - Keeper: a keeper for the dex module + + Keeper: a keeper for the dex module */ func NewKeeper( cdc codec.BinaryCodec, @@ -72,8 +74,9 @@ Sets the next pool id that should be chosen when a new pool is created. This function changes the state. args - ctx: the cosmos-sdk context - poolNumber: the numeric id of the next pool number to use + + ctx: the cosmos-sdk context + poolNumber: the numeric id of the next pool number to use */ func (k Keeper) SetNextPoolNumber(ctx sdk.Context, poolNumber uint64) { store := ctx.KVStore(k.storeKey) @@ -86,10 +89,12 @@ Retrieves the next pool id number to use when creating a new pool. This function is idempotent (does not change state). args - ctx: the cosmos-sdk context + + ctx: the cosmos-sdk context ret - uint64: a pool id number + + uint64: a pool id number */ func (k Keeper) GetNextPoolNumber(ctx sdk.Context) (poolNumber uint64) { bz := ctx.KVStore(k.storeKey).Get(types.KeyNextGlobalPoolNumber) @@ -106,10 +111,12 @@ Returns the next pool id number, and increments the state's next pool id number so that the next pool creation uses an autoincremented id number. args - ctx: the cosmos-sdk context + + ctx: the cosmos-sdk context ret - uint64: a pool id number + + uint64: a pool id number */ func (k Keeper) GetNextPoolNumberAndIncrement(ctx sdk.Context) uint64 { poolNumber := k.GetNextPoolNumber(ctx) @@ -123,11 +130,13 @@ Does not modify state. Panics if the bytes could not be unmarshalled to a Pool proto object. args - ctx: the cosmos-sdk context - poolId: the pool id number + + ctx: the cosmos-sdk context + poolId: the pool id number ret - pool: a Pool proto object + + pool: a Pool proto object */ func (k Keeper) FetchPool(ctx sdk.Context, poolId uint64) (pool types.Pool, err error) { store := ctx.KVStore(k.storeKey) @@ -218,13 +227,15 @@ func (k Keeper) SetPoolIdByDenom(ctx sdk.Context, pool types.Pool) { Mints new pool share tokens and sends them to an account. args: - ctx: the cosmos-sdk context - poolId: the pool id number - recipientAddr: the address of the recipient - amountPoolShares: the amount of pool shares to mint to the recipient + + ctx: the cosmos-sdk context + poolId: the pool id number + recipientAddr: the address of the recipient + amountPoolShares: the amount of pool shares to mint to the recipient ret: - err: returns an error if something errored out + + err: returns an error if something errored out */ func (k Keeper) mintPoolShareToAccount(ctx sdk.Context, poolId uint64, recipientAddr sdk.AccAddress, amountPoolShares sdk.Int) (err error) { newCoins := sdk.Coins{ @@ -249,13 +260,15 @@ Burns takes an amount of pool shares from an account and burns them. It's the inverse of mintPoolShareToAccount. args: - ctx: the cosmos-sdk context - poolId: the pool id number - recipientAddr: the address of the recipient - amountPoolShares: the amount of pool shares to mint to the recipient + + ctx: the cosmos-sdk context + poolId: the pool id number + recipientAddr: the address of the recipient + amountPoolShares: the amount of pool shares to mint to the recipient ret: - err: returns an error if something errored out + + err: returns an error if something errored out */ func (k Keeper) burnPoolShareFromAccount( ctx sdk.Context, @@ -286,14 +299,16 @@ func (k Keeper) burnPoolShareFromAccount( Creates a brand new pool and writes it to the state. args - ctx: the cosmos-sdk context - sender: the pool creator's address - poolParams: parameters of the pool, represented by a PoolParams proto object - poolAssets: initial assets in the pool, represented by a PoolAssets proto object array + + ctx: the cosmos-sdk context + sender: the pool creator's address + poolParams: parameters of the pool, represented by a PoolParams proto object + poolAssets: initial assets in the pool, represented by a PoolAssets proto object array ret - poolId: the pool id number - err: an error if any occurred + + poolId: the pool id number + err: an error if any occurred */ func (k Keeper) NewPool( ctx sdk.Context, diff --git a/x/dex/keeper/liquidity.go b/x/dex/keeper/liquidity.go index b7515af1c..ffe6dd1ea 100644 --- a/x/dex/keeper/liquidity.go +++ b/x/dex/keeper/liquidity.go @@ -13,11 +13,13 @@ import ( Fetches the liquidity for a specific coin denom. args: - ctx: the cosmos-sdk context - denom: the coin denom + + ctx: the cosmos-sdk context + denom: the coin denom ret: - amount: the amount of liquidity for the provided coin. Returns 0 if not found. + + amount: the amount of liquidity for the provided coin. Returns 0 if not found. */ func (k Keeper) GetDenomLiquidity(ctx sdk.Context, denom string) (amount sdk.Int) { store := ctx.KVStore(k.storeKey) @@ -37,9 +39,10 @@ func (k Keeper) GetDenomLiquidity(ctx sdk.Context, denom string) (amount sdk.Int Sets the liquidity for a specific coin denom. args: - ctx: the cosmos-sdk context - denom: the coin denom - amount: the amount of liquidity for the coin + + ctx: the cosmos-sdk context + denom: the coin denom + amount: the amount of liquidity for the coin */ func (k Keeper) SetDenomLiquidity(ctx sdk.Context, denom string, amount sdk.Int) { store := ctx.KVStore(k.storeKey) @@ -54,10 +57,12 @@ func (k Keeper) SetDenomLiquidity(ctx sdk.Context, denom string, amount sdk.Int) Fetches the liquidity for all tokens in the dex. args: - ctx: the cosmos-sdk context + + ctx: the cosmos-sdk context ret: - coins: an array of liquidities in the dex + + coins: an array of liquidities in the dex */ func (k Keeper) GetTotalLiquidity(ctx sdk.Context) (coins sdk.Coins) { store := ctx.KVStore(k.storeKey) @@ -79,8 +84,9 @@ func (k Keeper) GetTotalLiquidity(ctx sdk.Context) (coins sdk.Coins) { Sets the total liquidity for each coin. args: - ctx: the cosmos-sdk context - coins: the array of liquidities to update with + + ctx: the cosmos-sdk context + coins: the array of liquidities to update with */ func (k Keeper) SetTotalLiquidity(ctx sdk.Context, coins sdk.Coins) { for _, coin := range coins { @@ -92,8 +98,9 @@ func (k Keeper) SetTotalLiquidity(ctx sdk.Context, coins sdk.Coins) { Increases the total liquidity of the provided coins by the coin amount. args: - ctx: the cosmos-sdk context - coins: the coins added to the dex + + ctx: the cosmos-sdk context + coins: the coins added to the dex */ func (k Keeper) RecordTotalLiquidityIncrease(ctx sdk.Context, coins sdk.Coins) { for _, coin := range coins { @@ -107,8 +114,9 @@ func (k Keeper) RecordTotalLiquidityIncrease(ctx sdk.Context, coins sdk.Coins) { Increases the total liquidity of the provided coins by the coin amount. args: - ctx: the cosmos-sdk context - coins: the coins removed from the dex + + ctx: the cosmos-sdk context + coins: the coins removed from the dex */ func (k Keeper) RecordTotalLiquidityDecrease(ctx sdk.Context, coins sdk.Coins) { for _, coin := range coins { diff --git a/x/dex/keeper/msg_server.go b/x/dex/keeper/msg_server.go index a69be00e5..ac275f2ba 100644 --- a/x/dex/keeper/msg_server.go +++ b/x/dex/keeper/msg_server.go @@ -24,12 +24,14 @@ var _ types.MsgServer = msgServer{} Handler for the MsgCreatePool transaction. args - ctx: the cosmos-sdk context - msg: a MsgCreatePool proto object + + ctx: the cosmos-sdk context + msg: a MsgCreatePool proto object ret - MsgCreatePoolResponse: the MsgCreatePoolResponse proto object response, containing the pool id number - error: an error if any occurred + + MsgCreatePoolResponse: the MsgCreatePoolResponse proto object response, containing the pool id number + error: an error if any occurred */ func (k msgServer) CreatePool(goCtx context.Context, msg *types.MsgCreatePool) (*types.MsgCreatePoolResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) @@ -53,12 +55,14 @@ func (k msgServer) CreatePool(goCtx context.Context, msg *types.MsgCreatePool) ( Handler for the MsgJoinPool transaction. args - ctx: the cosmos-sdk context - msg: a MsgJoinPool proto object + + ctx: the cosmos-sdk context + msg: a MsgJoinPool proto object ret - MsgJoinPoolResponse: the MsgJoinPoolResponse proto object response, containing the pool id number - error: an error if any occurred + + MsgJoinPoolResponse: the MsgJoinPoolResponse proto object response, containing the pool id number + error: an error if any occurred */ func (k msgServer) JoinPool(ctx context.Context, msg *types.MsgJoinPool) (*types.MsgJoinPoolResponse, error) { sdkContext := sdk.UnwrapSDKContext(ctx) @@ -89,12 +93,14 @@ func (k msgServer) JoinPool(ctx context.Context, msg *types.MsgJoinPool) (*types Handler for the MsgExitPool transaction. args - ctx: the cosmos-sdk context - msg: a MsgExitPool proto object + + ctx: the cosmos-sdk context + msg: a MsgExitPool proto object ret - MsgExitPoolResponse: the MsgExitPoolResponse proto object response, containing the amount of tokens returned to the user - error: an error if any occurred + + MsgExitPoolResponse: the MsgExitPoolResponse proto object response, containing the amount of tokens returned to the user + error: an error if any occurred */ func (k msgServer) ExitPool(ctx context.Context, msg *types.MsgExitPool) (*types.MsgExitPoolResponse, error) { sdkContext := sdk.UnwrapSDKContext(ctx) @@ -123,12 +129,14 @@ func (k msgServer) ExitPool(ctx context.Context, msg *types.MsgExitPool) (*types Handler for the MsgJoinPool transaction. args - ctx: the cosmos-sdk context - msg: a MsgJoinPool proto object + + ctx: the cosmos-sdk context + msg: a MsgJoinPool proto object ret - MsgJoinPoolResponse: the MsgJoinPoolResponse proto object response, containing the pool id number - error: an error if any occurred + + MsgJoinPoolResponse: the MsgJoinPoolResponse proto object response, containing the pool id number + error: an error if any occurred */ func (k msgServer) SwapAssets(ctx context.Context, msg *types.MsgSwapAssets) ( *types.MsgSwapAssetsResponse, error, diff --git a/x/dex/math/constant_function.go b/x/dex/math/constant_function.go index d2409eb77..f4393aa7d 100644 --- a/x/dex/math/constant_function.go +++ b/x/dex/math/constant_function.go @@ -17,7 +17,6 @@ import ( // TODO(https://github.com/NibiruChain/nibiru/issues/141): Currently always calculates the invariant assuming constant weight (xy=k). // Once we figure out the floating point arithmetic conversions for exponentiation, we can // add unequal weights. -// func SolveConstantProductInvariant( xPrior, xAfter, diff --git a/x/dex/simulation/operations.go b/x/dex/simulation/operations.go index 48412896e..e009bfa6a 100644 --- a/x/dex/simulation/operations.go +++ b/x/dex/simulation/operations.go @@ -66,8 +66,8 @@ func SimulateMsgCreatePool(ak types.AccountKeeper, bk types.BankKeeper, k keeper } /* - SimulateMsgSwap generates a MsgSwap with random values - This function has a 33% chance of swapping a random fraction of the balance of a random token +SimulateMsgSwap generates a MsgSwap with random values +This function has a 33% chance of swapping a random fraction of the balance of a random token */ func SimulateMsgSwap(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( @@ -137,8 +137,8 @@ func SimulateMsgSwap(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keepe } /* - SimulateJoinPool generates a MsgJoinPool with random values - This function has a 33% chance of swapping a random fraction of the balance of a random token +SimulateJoinPool generates a MsgJoinPool with random values +This function has a 33% chance of swapping a random fraction of the balance of a random token */ func SimulateJoinPool(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( @@ -203,8 +203,8 @@ func SimulateJoinPool(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keep } /* - SimulateExitPool generates a MsgExitPool with random values - This function has a 33% chance of swapping a random fraction of the balance of a random token +SimulateExitPool generates a MsgExitPool with random values +This function has a 33% chance of swapping a random fraction of the balance of a random token */ func SimulateExitPool(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( diff --git a/x/dex/types/pool.go b/x/dex/types/pool.go index e324ef5b9..b85b50959 100644 --- a/x/dex/types/pool.go +++ b/x/dex/types/pool.go @@ -11,10 +11,12 @@ import ( Returns the *base* denomination of a pool share token for a given poolId. args: - poolId: the pool id number + + poolId: the pool id number ret: - poolDenom: the pool denomination name of the poolId + + poolDenom: the pool denomination name of the poolId */ func GetPoolShareBaseDenom(poolId uint64) (poolDenom string) { return fmt.Sprintf("nibiru/pool/%d", poolId) @@ -28,10 +30,12 @@ e.g. 1 atom is the display denom, but 10^6 uatom is the base denom. In Nibiru, a display denom is 10^18 base denoms. args: - poolId: the pool id number + + poolId: the pool id number ret: - poolDenom: the pool denomination name of the poolId + + poolDenom: the pool denomination name of the poolId */ func GetPoolShareDisplayDenom(poolId uint64) (poolDenom string) { return fmt.Sprintf("NIBIRU-POOL-%d", poolId) @@ -41,14 +45,16 @@ func GetPoolShareDisplayDenom(poolId uint64) (poolDenom string) { Creates a new pool and sets the initial assets. args: - poolId: the pool numeric id - poolAccountAddr: the pool's account address for holding funds - poolParams: pool configuration options - poolAssets: the initial pool assets and weights + + poolId: the pool numeric id + poolAccountAddr: the pool's account address for holding funds + poolParams: pool configuration options + poolAssets: the initial pool assets and weights ret: - pool: a new pool - err: error if any + + pool: a new pool + err: error if any */ func NewPool( poolId uint64, @@ -158,7 +164,6 @@ args: ret: - err: error if any - */ func (pool *Pool) updatePoolAssetBalances(tokens sdk.Coins) (err error) { // Ensures that there are no duplicate denoms, all denom's are valid, diff --git a/x/dex/types/pool_asset.go b/x/dex/types/pool_asset.go index f2bdcf647..3d40d0f3a 100644 --- a/x/dex/types/pool_asset.go +++ b/x/dex/types/pool_asset.go @@ -27,8 +27,6 @@ func (poolAsset PoolAsset) Validate() error { /* Subtracts an amount of coins from a pool's assets. Throws an error if the final amount is less than zero. - - */ func (pool *Pool) SubtractPoolAssetBalance(assetDenom string, subAmt sdk.Int) (err error) { if subAmt.LT(sdk.ZeroInt()) { diff --git a/x/oracle/abci.go b/x/oracle/abci.go new file mode 100644 index 000000000..28fdf8b0d --- /dev/null +++ b/x/oracle/abci.go @@ -0,0 +1,118 @@ +package oracle + +import ( + "time" + + "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/x/oracle/types" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// EndBlocker is called at the end of every block +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + + params := k.GetParams(ctx) + if types.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++ + } + } + + // Pair-TobinTax map + pairTobinTaxMap := make(map[string]sdk.Dec) + k.IterateTobinTaxes(ctx, func(pair string, tobinTax sdk.Dec) bool { + pairTobinTaxMap[pair] = tobinTax + return false + }) + + // Clear all exchange rates + k.IterateExchangeRates(ctx, func(pair string, _ sdk.Dec) (stop bool) { + k.DeleteExchangeRate(ctx, pair) + return false + }) + + // Organize votes to ballot by pair + // NOTE: **Filter out inactive or jailed validators** + // NOTE: **Make abstain votes to have zero vote power** + pairBallotMap := k.OrganizeBallotByPair(ctx, validatorClaimMap) + + if referencePair := PickReferencePair(ctx, k, pairTobinTaxMap, pairBallotMap); referencePair != "" { + // make voteMap of reference pair to calculate cross exchange rates + referenceBallot := pairBallotMap[referencePair] + referenceValidatorExchangeRateMap := referenceBallot.ToMap() + referenceExchangeRate := referenceBallot.WeightedMedianWithAssertion() + + // Iterate through ballots and update exchange rates; drop if not enough votes have been achieved. + for pair, ballot := range pairBallotMap { + // Convert ballot to cross exchange rates + if pair != referencePair { + ballot = ballot.ToCrossRateWithSort(referenceValidatorExchangeRateMap) + } + + // Get weighted median of cross exchange rates + exchangeRate := Tally(ctx, ballot, params.RewardBand, validatorClaimMap) + + // Transform into the original exchange rate + if pair != referencePair { + exchangeRate = referenceExchangeRate.Quo(exchangeRate) + } + + // Set the exchange rate, emit ABCI event + k.SetExchangeRateWithEvent(ctx, pair, exchangeRate) + } + } + + //--------------------------- + // Do miss counting & slashing + voteTargetsLen := len(pairTobinTaxMap) + 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) + } + + // Distribute rewards to ballot winners + k.RewardBallotWinners( + ctx, + (int64)(params.VotePeriod), + (int64)(params.RewardDistributionWindow), + pairTobinTaxMap, + validatorClaimMap, + ) + + // Clear the ballot + k.ClearBallots(ctx, params.VotePeriod) + + // Update vote targets and tobin tax + k.ApplyWhitelist(ctx, params.Whitelist, pairTobinTaxMap) + } + + // Do slash who did miss voting over threshold and + // reset miss counters of all validators at the last block of slash window + if types.IsPeriodLastBlock(ctx, params.SlashWindow) { + k.SlashAndResetMissCounters(ctx) + } +} diff --git a/x/oracle/abci_test.go b/x/oracle/abci_test.go new file mode 100644 index 000000000..a0eac9c3b --- /dev/null +++ b/x/oracle/abci_test.go @@ -0,0 +1,694 @@ +package oracle_test + +import ( + "fmt" + "math" + "sort" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/rand" + + "github.com/NibiruChain/nibiru/x/common" + "github.com/NibiruChain/nibiru/x/oracle" + "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +func TestOracleThreshold(t *testing.T) { + exchangeRates := types.ExchangeRateTuples{ + { + Pair: common.PairBTCStable.String(), + ExchangeRate: randomExchangeRate, + }, + } + input, h := setup(t) + exchangeRateStr, err := exchangeRates.ToString() + require.NoError(t, err) + + // 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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 := h.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + _, err = input.OracleKeeper.GetExchangeRate(input.Ctx.WithBlockHeight(1), exchangeRates[0].Pair) + 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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 = h.AggregateExchangeRateVote(sdk.WrapSDKContext(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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 = h.AggregateExchangeRateVote(sdk.WrapSDKContext(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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 = h.AggregateExchangeRateVote(sdk.WrapSDKContext(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.GetExchangeRate(input.Ctx.WithBlockHeight(1), exchangeRates[0].Pair) + 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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 = h.AggregateExchangeRateVote(sdk.WrapSDKContext(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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 = h.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + _, err = input.OracleKeeper.GetExchangeRate(input.Ctx.WithBlockHeight(1), exchangeRates[0].Pair) + require.Error(t, err) +} + +func TestOracleDrop(t *testing.T) { + input, h := setup(t) + + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairGovStable.String(), randomExchangeRate) + + // Account 1, pair gov stable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + + // Immediately swap halt after an illiquid oracle vote + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + _, err := input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairGovStable.String()) + 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 := keeper.NewMsgServerImpl(input.OracleKeeper) + for i, rate := range rates { + decExchangeRate := sdk.NewDecWithPrec(int64(rate*math.Pow10(keeper.OracleDecPrecision)), int64(keeper.OracleDecPrecision)) + exchangeRateStr, err := types.ExchangeRateTuples{ + {ExchangeRate: decExchangeRate, Pair: common.PairBTCStable.String()}}.ToString() + require.NoError(t, err) + + 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.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(0)), prevoteMsg) + _, err2 := h.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.NoError(t, err1) + require.NoError(t, err2) + + power := stakingAmt.QuoRaw(int64(6)).Int64() + if decExchangeRate.IsZero() { + power = int64(0) + } + + vote := types.NewBallotVoteForTally( + decExchangeRate, common.PairBTCStable.String(), 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, types.ExchangeRateTuples{{Pair: common.PairBTCStable.String(), ExchangeRate: 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.GetExchangeRate(input.Ctx, common.PairBTCStable.String()) + require.Error(t, err) + + input.Ctx = input.Ctx.WithBlockHeight(int64(params.VotePeriod - 1)) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + _, err = input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairBTCStable.String()) + require.NoError(t, err) +} + +func TestOracleRewardDistribution(t *testing.T) { + input, h := setup(t) + + // Account 1, btcstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairBTCStable.String(), ExchangeRate: randomExchangeRate}}, 0) + + // Account 2, btcstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairBTCStable.String(), ExchangeRate: randomExchangeRate}}, 1) + + rewardsAmt := sdk.NewInt(100000000) + err := input.BankKeeper.MintCoins(input.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(common.DenomGov, rewardsAmt))) + require.NoError(t, err) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + votePeriodsPerWindow := uint64(sdk.NewDec(int64(input.OracleKeeper.RewardDistributionWindow(input.Ctx))).QuoInt64(int64(input.OracleKeeper.VotePeriod(input.Ctx))).TruncateInt64()) + expectedRewardAmt := sdk.NewDecFromInt(rewardsAmt.QuoRaw(2)).QuoInt64(int64(votePeriodsPerWindow)).TruncateInt() + rewards := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[0]) + require.Equalf(t, expectedRewardAmt, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt(), "%s<=>%s", expectedRewardAmt.String(), rewards.String()) + rewards = input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[1]) + require.Equal(t, expectedRewardAmt, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) +} + +func TestOracleRewardBand(t *testing.T) { + input, h := setup(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.Whitelist = types.PairList{{Name: common.PairGovStable.String(), TobinTax: types.DefaultTobinTax}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // clear tobin tax to reset vote targets + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + input.OracleKeeper.SetTobinTax(input.Ctx, common.PairGovStable.String(), types.DefaultTobinTax) + + rewardSpread := randomExchangeRate.Mul(input.OracleKeeper.RewardBand(input.Ctx).QuoInt64(2)) + + // no one will miss the vote + // Account 1, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate.Sub(rewardSpread)}}, 0) + + // Account 2, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate.Add(rewardSpread)}}, 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])) + + // Account 1 will miss the vote due to raward band condition + // Account 1, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate.Sub(rewardSpread.Add(sdk.OneDec()))}}, 0) + + // Account 2, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate.Add(rewardSpread)}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + require.Equal(t, uint64(1), 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])) +} + +/* TODO(Mercilex): not appliable right now: https://github.com/NibiruChain/nibiru/issues/805 +func TestOracleMultiRewardDistribution(t *testing.T) { + input, h := setup(t) + + // SDR and KRW have the same voting power, but KRW has been chosen as referencepair by alphabetical order. + // Account 1, SDR, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairBTCStable.String(), ExchangeRate: randomExchangeRate}, {Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + + // Account 2, SDR + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairBTCStable.String(), ExchangeRate: randomExchangeRate}}, 1) + + // Account 3, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairBTCStable.String(), ExchangeRate: randomExchangeRate}}, 2) + + rewardAmt := sdk.NewInt(100000000) + err := input.BankKeeper.MintCoins(input.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(common.DenomGov, rewardAmt))) + require.NoError(t, err) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + rewardDistributedWindow := input.OracleKeeper.RewardDistributionWindow(input.Ctx) + + expectedRewardAmt := sdk.NewDecFromInt(rewardAmt.QuoRaw(3).MulRaw(2)).QuoInt64(int64(rewardDistributedWindow)).TruncateInt() + expectedRewardAmt2 := sdk.ZeroInt() // even vote power is same KRW with SDR, KRW chosen referenceTerra because alphabetical order + expectedRewardAmt3 := sdk.NewDecFromInt(rewardAmt.QuoRaw(3)).QuoInt64(int64(rewardDistributedWindow)).TruncateInt() + + rewards := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[0]) + require.Equal(t, expectedRewardAmt, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards = input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[1]) + require.Equal(t, expectedRewardAmt2, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards = input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[2]) + require.Equal(t, expectedRewardAmt3, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) +} +*/ + +func TestOracleExchangeRate(t *testing.T) { + input, h := setup(t) + + govStableExchangeRate := sdk.NewDec(1000000000) + ethStableExchangeRate := sdk.NewDec(1000000) + + // govstable has been chosen as referenceExchangeRate by highest voting power + // Account 1, ethstable, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairETHStable.String(), ExchangeRate: ethStableExchangeRate}, {Pair: common.PairGovStable.String(), ExchangeRate: govStableExchangeRate}}, 0) + + // Account 2, ethstable, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairETHStable.String(), ExchangeRate: ethStableExchangeRate}, {Pair: common.PairGovStable.String(), ExchangeRate: govStableExchangeRate}}, 1) + + // Account 3, govstable, btcstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: govStableExchangeRate}, {Pair: common.PairBTCStable.String(), ExchangeRate: randomExchangeRate}}, 2) + + rewardAmt := sdk.NewInt(100000000) + err := input.BankKeeper.MintCoins(input.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(common.DenomGov, rewardAmt))) + require.NoError(t, err) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + rewardDistributedWindow := input.OracleKeeper.RewardDistributionWindow(input.Ctx) + expectedRewardAmt := sdk.NewDecFromInt(rewardAmt.QuoRaw(5).MulRaw(2)).QuoInt64(int64(rewardDistributedWindow)).TruncateInt() + expectedRewardAmt2 := sdk.NewDecFromInt(rewardAmt.QuoRaw(5).MulRaw(1)).QuoInt64(int64(rewardDistributedWindow)).TruncateInt() + rewards := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[0]) + require.Equal(t, expectedRewardAmt, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards = input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[1]) + require.Equal(t, expectedRewardAmt, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards = input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[2]) + require.Equal(t, expectedRewardAmt2, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) +} + +func TestOracleEnsureSorted(t *testing.T) { + input, h := setup(t) + + for i := 0; i < 100; i++ { + govStableRate1 := sdk.NewDec(int64(rand.Uint64() % 100000000)) + ethStableRate1 := sdk.NewDec(int64(rand.Uint64() % 100000000)) + + govStableRate2 := sdk.NewDec(int64(rand.Uint64() % 100000000)) + ethStableRate2 := sdk.NewDec(int64(rand.Uint64() % 100000000)) + + govStableRate3 := sdk.NewDec(int64(rand.Uint64() % 100000000)) + ethStableRate3 := sdk.NewDec(int64(rand.Uint64() % 100000000)) + + // Account 1, ethstable, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairETHStable.String(), ExchangeRate: ethStableRate1}, {Pair: common.PairGovStable.String(), ExchangeRate: govStableRate1}}, 0) + + // Account 2, ethstable, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairETHStable.String(), ExchangeRate: ethStableRate2}, {Pair: common.PairGovStable.String(), ExchangeRate: govStableRate2}}, 1) + + // Account 3, ethstable, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairETHStable.String(), ExchangeRate: govStableRate3}, {Pair: common.PairGovStable.String(), ExchangeRate: ethStableRate3}}, 2) + + require.NotPanics(t, func() { + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + }) + } +} + +func TestOracleExchangeRateVal5(t *testing.T) { + input, h := setupVal5(t) + + govStableRate := sdk.NewDec(505000) + govStableRateErr := sdk.NewDec(500000) + ethStableRate := sdk.NewDec(505) + ethStableRateErr := sdk.NewDec(500) + + // govstable has been chosen as reference pair by highest voting power + // Account 1, govstable, ethstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: govStableRate}, {Pair: common.PairETHStable.String(), ExchangeRate: ethStableRate}}, 0) + + // Account 2, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: govStableRate}}, 1) + + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: govStableRate}}, 2) + + // Account 4, govstable, ethstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: govStableRateErr}, {Pair: common.PairETHStable.String(), ExchangeRate: ethStableRateErr}}, 3) + + // Account 5, govstable, ethstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: govStableRateErr}, {Pair: common.PairETHStable.String(), ExchangeRate: ethStableRateErr}}, 4) + + rewardAmt := sdk.NewInt(100000000) + err := input.BankKeeper.MintCoins(input.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(common.DenomGov, rewardAmt))) + require.NoError(t, err) + + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + + gotGovStableRate, err := input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairGovStable.String()) + require.NoError(t, err) + gotEthStableRate, err := input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairETHStable.String()) + require.NoError(t, err) + + // legacy version case + require.NotEqual(t, ethStableRateErr, gotEthStableRate) + + // new version case + require.Equal(t, govStableRate, gotGovStableRate) + require.Equal(t, ethStableRate, gotEthStableRate) + + rewardDistributedWindow := input.OracleKeeper.RewardDistributionWindow(input.Ctx) + expectedRewardAmt := sdk.NewDecFromInt(rewardAmt.QuoRaw(8).MulRaw(2)).QuoInt64(int64(rewardDistributedWindow)).TruncateInt() + expectedRewardAmt2 := sdk.NewDecFromInt(rewardAmt.QuoRaw(8).MulRaw(1)).QuoInt64(int64(rewardDistributedWindow)).TruncateInt() + rewards := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[0]) + require.Equal(t, expectedRewardAmt, rewards.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards1 := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[1]) + require.Equal(t, expectedRewardAmt2, rewards1.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards2 := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[2]) + require.Equal(t, expectedRewardAmt2, rewards2.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards3 := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[3]) + require.Equal(t, expectedRewardAmt, rewards3.Rewards.AmountOf(common.DenomGov).TruncateInt()) + rewards4 := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[4]) + require.Equal(t, expectedRewardAmt, rewards4.Rewards.AmountOf(common.DenomGov).TruncateInt()) +} + +func TestInvalidVotesSlashing(t *testing.T) { + input, h := setup(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.Whitelist = types.PairList{{Name: common.PairGovStable.String(), TobinTax: types.DefaultTobinTax}} + input.OracleKeeper.SetParams(input.Ctx, params) + input.OracleKeeper.SetTobinTax(input.Ctx, common.PairGovStable.String(), types.DefaultTobinTax) + + 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, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + + // Account 2, govstable, miss vote + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate.Add(sdk.NewDec(100000000000000))}}, 1) + + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + + // Account 2, govstable, miss vote + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate.Add(sdk.NewDec(100000000000000))}}, 1) + + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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.PairList{{Name: common.PairGovStable.String(), TobinTax: types.DefaultTobinTax}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // clear tobin tax to reset vote targets + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + input.OracleKeeper.SetTobinTax(input.Ctx, common.PairGovStable.String(), types.DefaultTobinTax) + + input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) + + // Account 1, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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.PairList{{Name: common.PairGovStable.String(), TobinTax: types.DefaultTobinTax}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // clear tobin tax to reset vote targets + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + input.OracleKeeper.SetTobinTax(input.Ctx, common.PairGovStable.String(), types.DefaultTobinTax) + + 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, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + + // Account 2, govstable, abstain vote + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: sdk.ZeroDec()}}, 1) + + // Account 3, govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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.PairList{{Name: common.PairGovStable.String(), TobinTax: types.DefaultTobinTax}, {Name: common.PairBTCStable.String(), TobinTax: types.DefaultTobinTax}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // clear tobin tax to reset vote targets + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + input.OracleKeeper.SetTobinTax(input.Ctx, common.PairGovStable.String(), types.DefaultTobinTax) + + // govstable + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: 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 {govstable, btcstable} + require.Equal(t, []string{common.PairBTCStable.String(), common.PairGovStable.String()}, input.OracleKeeper.GetVoteTargets(input.Ctx)) + + // tobin tax must be exists for btcstable + btcStableTax, err := input.OracleKeeper.GetTobinTax(input.Ctx, common.PairBTCStable.String()) + require.NoError(t, err) + require.Equal(t, types.DefaultTobinTax, btcStableTax) + + // delete btcstable + params.Whitelist = types.PairList{{Name: common.PairGovStable.String(), TobinTax: types.DefaultTobinTax}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // govstable, missing + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + require.Equal(t, uint64(1), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + require.Equal(t, uint64(1), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + require.Equal(t, uint64(1), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[2])) + + // btcstable must be deleted + require.Equal(t, []string{common.PairGovStable.String()}, input.OracleKeeper.GetVoteTargets(input.Ctx)) + + _, err = input.OracleKeeper.GetTobinTax(input.Ctx, common.PairBTCStable.String()) + require.Error(t, err) + + // change govstable tobin tax + params.Whitelist = types.PairList{{Name: common.PairGovStable.String(), TobinTax: sdk.ZeroDec()}} + input.OracleKeeper.SetParams(input.Ctx, params) + + // govstable, no missing + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: randomExchangeRate}}, 2) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + + require.Equal(t, uint64(1), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[0])) + require.Equal(t, uint64(1), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[1])) + require.Equal(t, uint64(1), input.OracleKeeper.GetMissCounter(input.Ctx, keeper.ValAddrs[2])) + + // govstable tobin tax must be 0 + tobinTax, err := input.OracleKeeper.GetTobinTax(input.Ctx, common.PairGovStable.String()) + require.NoError(t, err) + require.True(t, sdk.ZeroDec().Equal(tobinTax)) +} + +func TestAbstainWithSmallStakingPower(t *testing.T) { + input, h := setupWithSmallVotingPower(t) + + // clear tobin tax to reset vote targets + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + input.OracleKeeper.SetTobinTax(input.Ctx, common.PairGovStable.String(), types.DefaultTobinTax) + makeAggregatePrevoteAndVote(t, input, h, 0, types.ExchangeRateTuples{{Pair: common.PairGovStable.String(), ExchangeRate: sdk.ZeroDec()}}, 0) + + oracle.EndBlocker(input.Ctx, input.OracleKeeper) + _, err := input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairGovStable.String()) + require.Error(t, err) +} + +func makeAggregatePrevoteAndVote(t *testing.T, input keeper.TestInput, h types.MsgServer, height int64, rates types.ExchangeRateTuples, idx int) { + salt := "1" + ratesStr, err := rates.ToString() + require.NoError(t, err) + hash := types.GetAggregateVoteHash(salt, ratesStr, keeper.ValAddrs[idx]) + + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, keeper.Addrs[idx], keeper.ValAddrs[idx]) + _, err = h.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(height)), prevoteMsg) + require.NoError(t, err) + + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, ratesStr, keeper.Addrs[idx], keeper.ValAddrs[idx]) + _, err = h.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(height+1)), voteMsg) + require.NoError(t, err) +} diff --git a/x/oracle/client/cli/query.go b/x/oracle/client/cli/query.go new file mode 100644 index 000000000..15bf14cc7 --- /dev/null +++ b/x/oracle/client/cli/query.go @@ -0,0 +1,420 @@ +package cli + +import ( + "context" + "strings" + + "github.com/spf13/cobra" + + "github.com/NibiruChain/nibiru/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(), + GetCmdQueryTobinTaxes(), + ) + + return oracleQueryCmd +} + +// GetCmdQueryExchangeRates implements the query rate command. +func GetCmdQueryExchangeRates() *cobra.Command { + cmd := &cobra.Command{ + Use: "exchange-rates [pair]", + Args: cobra.RangeArgs(0, 1), + Short: "Query the current exchange rate w.r.t a pair", + Long: strings.TrimSpace(` +Query the current exchange rate of a pair. +You can find the current list of active pairs by running + +$ nibid query oracle exchange-rates + +Or, can filter with pair + +$ nibid query oracle exchange-rates nibi:usd +`), + 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) + } + + pair := args[0] + res, err := queryClient.ExchangeRate( + context.Background(), + &types.QueryExchangeRateRequest{Pair: pair}, + ) + 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 pairs recognized by the oracle", + Long: strings.TrimSpace(` +Query the active list of pairs recognized by the oracles. + +$ nibid 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. + +$ nibid query oracle feeder nibivaloper... +`), + 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. + +$ nibid query oracle miss nibivaloper... +`), + 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. + +$ nibid query oracle aggregate-prevotes + +Or, can filter with voter address + +$ nibid query oracle aggregate-prevotes nibivaloper... +`), + 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. + +$ nibid query oracle aggregate-votes + +Or, can filter with voter address + +$ nibid query oracle aggregate-votes nibivaloper... +`), + 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 +} + +// GetCmdQueryTobinTaxes implements the query params command. +func GetCmdQueryTobinTaxes() *cobra.Command { + cmd := &cobra.Command{ + Use: "tobin-taxes [pair]", + Args: cobra.RangeArgs(0, 1), + Short: "Query the current Oracle tobin taxes.", + Long: strings.TrimSpace(` +Query the current Oracle tobin taxes. + +$ nibid query oracle tobin-taxes + +Or, can filter with pair + +$ nibid query oracle tobin-taxes nibi:usd + +Or, can +`), + 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.TobinTaxes( + context.Background(), + &types.QueryTobinTaxesRequest{}, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + pair := args[0] + res, err := queryClient.TobinTax( + context.Background(), + &types.QueryTobinTaxRequest{Pair: pair}, + ) + 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 100644 index 000000000..f52e195dd --- /dev/null +++ b/x/oracle/client/cli/tx.go @@ -0,0 +1,207 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/pkg/errors" + + "github.com/NibiruChain/nibiru/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. + +$ nibid tx oracle set-feeder nibi1... + +where "nibi1..." 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 + } + + msg := types.NewMsgDelegateFeedConsent(validator, feeder) + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + 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 Nibiru", + Long: strings.TrimSpace(` +Submit an oracle aggregate prevote for the exchange rates of a pair. +The purpose of aggregate prevote is to hide aggregate exchange rate vote with hash which is formatted +as hex string in SHA256("{salt}:({pair},{exchange_rate})|...|({pair},{exchange_rate}):{voter}") + +# Aggregate Prevote +$ nibid tx oracle aggregate-prevote 1234 (40000.0,BTC:USD)|(1.243,NIBI:USD) + +where "BTC:USD,NIBI:USD" is the pair, and "40000.0, 1.243" is the exchange rates expressed in decimal value. + +If voting from a voting delegate, set "validator" to the address of the validator to vote on behalf of: +$ nibid tx oracle aggregate-prevote 1234 1234 (40000.0,BTC:USD)|(1.243,NIBI:USD) nibivaloper1... +`), + 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 + feeder := clientCtx.GetFromAddress() + + // By default, the feeder is voting on behalf of itself + validator := sdk.ValAddress(feeder) + + // 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) + + msg := types.NewMsgAggregateExchangeRatePrevote(hash, feeder, validator) + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + 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 Nibiru", + Long: strings.TrimSpace(` +Submit an aggregate vote for the exchange_rates of the proposed pairs. Companion to a prevote submitted in the previous vote period. + +$ nibid tx oracle aggregate-vote 1234 (40000.0,BTC:USD)|(1.243,NIBI:USD) + +where "BTC:USD, NIBI:USD" is the pairs, and "40000.0,1.243" is the exchange rates as decimal string. + +"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: +$ nibid tx oracle aggregate-vote 1234 (40000.0,BTC:USD)|(1.243,NIBI:USD) nibivaloper1.... +`), + 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 + feeder := clientCtx.GetFromAddress() + + // By default, the feeder is voting on behalf of itself + validator := sdk.ValAddress(feeder) + + // 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 + } + + msg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, feeder, validator) + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/oracle/common_test.go b/x/oracle/common_test.go new file mode 100644 index 000000000..26db6d270 --- /dev/null +++ b/x/oracle/common_test.go @@ -0,0 +1,88 @@ +package oracle_test + +import ( + "testing" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/x/oracle/keeper" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking" +) + +var ( + stakingAmt = sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + + randomExchangeRate = sdk.NewDec(1700) +) + +func setupWithSmallVotingPower(t *testing.T) (keeper.TestInput, types.MsgServer) { + input := keeper.CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + params.RewardDistributionWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + h := keeper.NewMsgServerImpl(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, types.MsgServer) { + input := keeper.CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + params.RewardDistributionWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + h := keeper.NewMsgServerImpl(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, types.MsgServer) { + input := keeper.CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + params.RewardDistributionWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + h := keeper.NewMsgServerImpl(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/genesis.go b/x/oracle/genesis.go new file mode 100644 index 000000000..374654815 --- /dev/null +++ b/x/oracle/genesis.go @@ -0,0 +1,133 @@ +package oracle + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/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.SetExchangeRate(ctx, ex.Pair, 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) + } + + if len(data.TobinTaxes) > 0 { + for _, tt := range data.TobinTaxes { + keeper.SetTobinTax(ctx, tt.Pair, tt.TobinTax) + } + } else { + for _, item := range data.Params.Whitelist { + keeper.SetTobinTax(ctx, item.Name, item.TobinTax) + } + } + + 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.IterateExchangeRates(ctx, func(pair string, rate sdk.Dec) (stop bool) { + exchangeRates = append(exchangeRates, types.ExchangeRateTuple{Pair: pair, 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 + }) + + tobinTaxes := []types.TobinTax{} + keeper.IterateTobinTaxes(ctx, func(pair string, tobinTax sdk.Dec) (stop bool) { + tobinTaxes = append(tobinTaxes, types.TobinTax{Pair: pair, TobinTax: tobinTax}) + return false + }) + + return types.NewGenesisState(params, + exchangeRates, + feederDelegations, + missCounters, + aggregateExchangeRatePrevotes, + aggregateExchangeRateVotes, + tobinTaxes) +} diff --git a/x/oracle/genesis_test.go b/x/oracle/genesis_test.go new file mode 100644 index 000000000..ed7c51039 --- /dev/null +++ b/x/oracle/genesis_test.go @@ -0,0 +1,133 @@ +package oracle_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/x/oracle" + "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/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.SetExchangeRate(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{{Pair: "foo", ExchangeRate: sdk.NewDec(123)}}, keeper.ValAddrs[0])) + input.OracleKeeper.SetTobinTax(input.Ctx, "denom", sdk.NewDecWithPrec(123, 3)) + input.OracleKeeper.SetTobinTax(input.Ctx, "denom2", sdk.NewDecWithPrec(123, 3)) + input.OracleKeeper.SetMissCounter(input.Ctx, keeper.ValAddrs[0], 10) + 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) +} + +func TestInitGenesis(t *testing.T) { + input, _ := setup(t) + genesis := types.DefaultGenesisState() + require.NotPanics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) + + genesis.FeederDelegations = []types.FeederDelegation{{ + FeederAddress: keeper.Addrs[0].String(), + ValidatorAddress: "invalid", + }} + + require.Panics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) + + genesis.FeederDelegations = []types.FeederDelegation{{ + FeederAddress: "invalid", + ValidatorAddress: keeper.ValAddrs[0].String(), + }} + + require.Panics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) + + genesis.FeederDelegations = []types.FeederDelegation{{ + FeederAddress: keeper.Addrs[0].String(), + ValidatorAddress: keeper.ValAddrs[0].String(), + }} + + genesis.MissCounters = []types.MissCounter{ + { + ValidatorAddress: "invalid", + MissCounter: 10, + }, + } + + require.Panics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) + + genesis.MissCounters = []types.MissCounter{ + { + ValidatorAddress: keeper.ValAddrs[0].String(), + MissCounter: 10, + }, + } + + genesis.AggregateExchangeRatePrevotes = []types.AggregateExchangeRatePrevote{ + { + Hash: "hash", + Voter: "invalid", + SubmitBlock: 100, + }, + } + + require.Panics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) + + genesis.AggregateExchangeRatePrevotes = []types.AggregateExchangeRatePrevote{ + { + Hash: "hash", + Voter: keeper.ValAddrs[0].String(), + SubmitBlock: 100, + }, + } + + genesis.AggregateExchangeRateVotes = []types.AggregateExchangeRateVote{ + { + ExchangeRateTuples: []types.ExchangeRateTuple{ + { + Pair: "nibi:usd", + ExchangeRate: sdk.NewDec(10), + }, + }, + Voter: "invalid", + }, + } + + require.Panics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) + + genesis.AggregateExchangeRateVotes = []types.AggregateExchangeRateVote{ + { + ExchangeRateTuples: []types.ExchangeRateTuple{ + { + Pair: "nibi:usd", + ExchangeRate: sdk.NewDec(10), + }, + }, + Voter: keeper.ValAddrs[0].String(), + }, + } + + require.NotPanics(t, func() { + oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis) + }) +} diff --git a/x/oracle/keeper/alias_functions.go b/x/oracle/keeper/alias_functions.go new file mode 100644 index 000000000..bc3fcbfae --- /dev/null +++ b/x/oracle/keeper/alias_functions.go @@ -0,0 +1,31 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/NibiruChain/nibiru/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 { + // TODO(mercilex): this logic needs to be redefined. https://github.com/NibiruChain/nibiru/issues/805 + if denom != common.DenomGov { + return sdk.NewCoin("zero", sdk.ZeroInt()) + } + 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 100644 index 000000000..d2d977a75 --- /dev/null +++ b/x/oracle/keeper/ballot.go @@ -0,0 +1,91 @@ +package keeper + +import ( + "sort" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// OrganizeBallotByPair collects all oracle votes for the period, categorized by the votes' pair parameter +func (k Keeper) OrganizeBallotByPair(ctx sdk.Context, validatorClaimMap map[string]types.Claim) (ballots map[string]types.ExchangeRateBallot) { + ballots = map[string]types.ExchangeRateBallot{} + + // Organize aggregate votes + aggregateHandler := func(voterAddr sdk.ValAddress, vote types.AggregateExchangeRateVote) (stop bool) { + // organize ballot only for the active validators + if claim, ok := validatorClaimMap[vote.Voter]; ok { + for _, tuple := range vote.ExchangeRateTuples { + power := claim.Power + if !tuple.ExchangeRate.IsPositive() { + // Make the power of abstain vote zero + power = 0 + } + + ballots[tuple.Pair] = append(ballots[tuple.Pair], + types.NewBallotVoteForTally( + tuple.ExchangeRate, + tuple.Pair, + voterAddr, + power, + ), + ) + } + } + + return false + } + + k.IterateAggregateExchangeRateVotes(ctx, aggregateHandler) + + // sort created ballot + for pair, ballot := range ballots { + sort.Sort(ballot) + ballots[pair] = 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 pair list and set tobin tax with params whitelist +func (k Keeper) ApplyWhitelist(ctx sdk.Context, whitelist types.PairList, voteTargets map[string]sdk.Dec) { + // check is there any update in whitelist params + updateRequired := false + if len(voteTargets) != len(whitelist) { + updateRequired = true + } else { + for _, item := range whitelist { + if tobinTax, ok := voteTargets[item.Name]; !ok || !tobinTax.Equal(item.TobinTax) { + updateRequired = true + break + } + } + } + + if updateRequired { + k.ClearTobinTaxes(ctx) + + for _, item := range whitelist { + k.SetTobinTax(ctx, item.Name, item.TobinTax) + } + } +} diff --git a/x/oracle/keeper/ballot_test.go b/x/oracle/keeper/ballot_test.go new file mode 100644 index 000000000..5f4a33c54 --- /dev/null +++ b/x/oracle/keeper/ballot_test.go @@ -0,0 +1,181 @@ +package keeper + +import ( + "sort" + "testing" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + 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) + + btcBallot := types.ExchangeRateBallot{ + types.NewBallotVoteForTally(sdk.NewDec(17), common.PairBTCStable.String(), ValAddrs[0], power), + types.NewBallotVoteForTally(sdk.NewDec(10), common.PairBTCStable.String(), ValAddrs[1], power), + types.NewBallotVoteForTally(sdk.NewDec(6), common.PairBTCStable.String(), ValAddrs[2], power), + } + ethBallot := types.ExchangeRateBallot{ + types.NewBallotVoteForTally(sdk.NewDec(1000), common.PairETHStable.String(), ValAddrs[0], power), + types.NewBallotVoteForTally(sdk.NewDec(1300), common.PairETHStable.String(), ValAddrs[1], power), + types.NewBallotVoteForTally(sdk.NewDec(2000), common.PairETHStable.String(), ValAddrs[2], power), + } + + for i := range btcBallot { + input.OracleKeeper.SetAggregateExchangeRateVote( + input.Ctx, + ValAddrs[i], + types.NewAggregateExchangeRateVote( + types.ExchangeRateTuples{ + {Pair: btcBallot[i].Pair, ExchangeRate: btcBallot[i].ExchangeRate}, + {Pair: ethBallot[i].Pair, ExchangeRate: ethBallot[i].ExchangeRate}, + }, + ValAddrs[i], + ), + ) + } + + // organize votes by denom + ballotMap := input.OracleKeeper.OrganizeBallotByPair(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(btcBallot) + sort.Sort(ethBallot) + sort.Sort(ballotMap[common.PairBTCStable.String()]) + sort.Sort(ballotMap[common.PairETHStable.String()]) + + require.Equal(t, btcBallot, ballotMap[common.PairBTCStable.String()]) + require.Equal(t, ethBallot, ballotMap[common.PairETHStable.String()]) +} + +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) + + btcBallot := types.ExchangeRateBallot{ + types.NewBallotVoteForTally(sdk.NewDec(17), common.PairBTCStable.String(), ValAddrs[0], power), + types.NewBallotVoteForTally(sdk.NewDec(10), common.PairBTCStable.String(), ValAddrs[1], power), + types.NewBallotVoteForTally(sdk.NewDec(6), common.PairBTCStable.String(), ValAddrs[2], power), + } + ethBallot := types.ExchangeRateBallot{ + types.NewBallotVoteForTally(sdk.NewDec(1000), common.PairETHStable.String(), ValAddrs[0], power), + types.NewBallotVoteForTally(sdk.NewDec(1300), common.PairETHStable.String(), ValAddrs[1], power), + types.NewBallotVoteForTally(sdk.NewDec(2000), common.PairETHStable.String(), ValAddrs[2], power), + } + + for i := range btcBallot { + 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{ + {Pair: btcBallot[i].Pair, ExchangeRate: btcBallot[i].ExchangeRate}, + {Pair: ethBallot[i].Pair, ExchangeRate: ethBallot[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) + + // no update + input.OracleKeeper.ApplyWhitelist(input.Ctx, types.PairList{ + types.Pair{ + Name: "nibi:usd", + TobinTax: sdk.OneDec(), + }, + types.Pair{ + Name: "btc:usd", + TobinTax: sdk.OneDec(), + }, + }, map[string]sdk.Dec{ + "nibi:usd": sdk.ZeroDec(), + "btc:usd": sdk.ZeroDec(), + }) + + price, err := input.OracleKeeper.GetTobinTax(input.Ctx, "nibi:usd") + require.NoError(t, err) + require.Equal(t, price, sdk.OneDec()) + + price, err = input.OracleKeeper.GetTobinTax(input.Ctx, "btc:usd") + require.NoError(t, err) + require.Equal(t, price, sdk.OneDec()) +} diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go new file mode 100644 index 000000000..82bbe9d54 --- /dev/null +++ b/x/oracle/keeper/keeper.go @@ -0,0 +1,360 @@ +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/NibiruChain/nibiru/x/oracle/types" +) + +// 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 + +// GetExchangeRate gets the consensus exchange rate of the given pair from the store. +func (k Keeper) GetExchangeRate(ctx sdk.Context, pair string) (sdk.Dec, error) { + store := ctx.KVStore(k.storeKey) + b := store.Get(types.GetExchangeRateKey(pair)) + if b == nil { + return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrUnknownPair, pair) + } + + dp := sdk.DecProto{} + k.cdc.MustUnmarshal(b, &dp) + return dp.Dec, nil +} + +// SetExchangeRate sets the consensus exchange rate of the given pair. +func (k Keeper) SetExchangeRate(ctx sdk.Context, pair string, exchangeRate sdk.Dec) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&sdk.DecProto{Dec: exchangeRate}) + store.Set(types.GetExchangeRateKey(pair), bz) +} + +// SetExchangeRateWithEvent calls SetExchangeRate and emits an event. +func (k Keeper) SetExchangeRateWithEvent(ctx sdk.Context, pair string, exchangeRate sdk.Dec) { + k.SetExchangeRate(ctx, pair, exchangeRate) + ctx.EventManager().EmitEvent( + sdk.NewEvent(types.EventTypeExchangeRateUpdate, + sdk.NewAttribute(types.AttributeKeyPair, pair), + sdk.NewAttribute(types.AttributeKeyExchangeRate, exchangeRate.String()), + ), + ) +} + +// DeleteExchangeRate deletes the consensus exchange rate of the provided pair from the store. +func (k Keeper) DeleteExchangeRate(ctx sdk.Context, pair string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetExchangeRateKey(pair)) +} + +// IterateExchangeRates iterates over pair's exchange rates +func (k Keeper) IterateExchangeRates(ctx sdk.Context, handler func(pair 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() { + rawKey := iter.Key() + pair := string(rawKey[len(types.ExchangeRateKey) : len(rawKey)-1]) + dp := sdk.DecProto{} + k.cdc.MustUnmarshal(iter.Value(), &dp) + if handler(pair, 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 + } + } +} + +// GetTobinTax return tobin tax for the pair +// TODO(mercilex): use AssetPair +func (k Keeper) GetTobinTax(ctx sdk.Context, pair string) (sdk.Dec, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.GetTobinTaxKey(pair)) + if bz == nil { + err := sdkerrors.Wrap(types.ErrNoTobinTax, pair) + return sdk.Dec{}, err + } + + tobinTax := sdk.DecProto{} + k.cdc.MustUnmarshal(bz, &tobinTax) + + return tobinTax.Dec, nil +} + +// SetTobinTax updates tobin tax for the pair +// TODO(mercilex): use AssetPair +func (k Keeper) SetTobinTax(ctx sdk.Context, pair string, tobinTax sdk.Dec) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&sdk.DecProto{Dec: tobinTax}) + store.Set(types.GetTobinTaxKey(pair), bz) +} + +// IterateTobinTaxes iterates rate over tobin taxes in the store +func (k Keeper) IterateTobinTaxes(ctx sdk.Context, handler func(pair string, tobinTax sdk.Dec) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.TobinTaxKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + pair := types.ExtractPairFromTobinTaxKey(iter.Key()) + + var tobinTax sdk.DecProto + k.cdc.MustUnmarshal(iter.Value(), &tobinTax) + if handler(pair, tobinTax.Dec) { + break + } + } +} + +// ClearTobinTaxes clears tobin taxes +func (k Keeper) ClearTobinTaxes(ctx sdk.Context) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.TobinTaxKey) + 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 100644 index 000000000..ccf1e0699 --- /dev/null +++ b/x/oracle/keeper/keeper_test.go @@ -0,0 +1,372 @@ +package keeper + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + 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) + + pairCollRate := sdk.NewDecWithPrec(839, int64(OracleDecPrecision)).MulInt64(int64(6)) + btcStableRate := sdk.NewDecWithPrec(2838, int64(OracleDecPrecision)).MulInt64(int64(6)) + + // Set & get rates + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairCollStable.String(), pairCollRate) + rate, err := input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairCollStable.String()) + require.NoError(t, err) + require.Equal(t, pairCollRate, rate) + + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairBTCStable.String(), btcStableRate) + rate, err = input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairBTCStable.String()) + require.NoError(t, err) + require.Equal(t, btcStableRate, rate) + + input.OracleKeeper.DeleteExchangeRate(input.Ctx, common.PairBTCStable.String()) + _, err = input.OracleKeeper.GetExchangeRate(input.Ctx, common.PairBTCStable.String()) + require.Error(t, err) + + numExchangeRates := 0 + handler := func(denom string, exchangeRate sdk.Dec) (stop bool) { + numExchangeRates = numExchangeRates + 1 + return false + } + input.OracleKeeper.IterateExchangeRates(input.Ctx, handler) + + require.True(t, numExchangeRates == 1) +} + +func TestIterateExchangeRates(t *testing.T) { + input := CreateTestInput(t) + + collStablePrice := sdk.NewDecWithPrec(839, int64(OracleDecPrecision)).MulInt64(int64(6)) + ethStablePrice := sdk.NewDecWithPrec(4995, int64(OracleDecPrecision)).MulInt64(int64(6)) + btcStablePrice := sdk.NewDecWithPrec(2838, int64(OracleDecPrecision)).MulInt64(int64(6)) + + // Set & get rates + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairCollStable.String(), collStablePrice) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairETHStable.String(), ethStablePrice) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairBTCStable.String(), btcStablePrice) + + input.OracleKeeper.IterateExchangeRates(input.Ctx, func(denom string, rate sdk.Dec) (stop bool) { + switch denom { + case common.PairCollStable.String(): + require.Equal(t, collStablePrice, rate) + case common.PairETHStable.String(): + require.Equal(t, ethStablePrice, rate) + case common.PairBTCStable.String(): + require.Equal(t, btcStablePrice, rate) + } + return false + }) +} + +/* TODO(mercilex): this test is currently not valid. https://github.com/NibiruChain/nibiru/issues/805 +func TestRewardPool(t *testing.T) { + input := CreateTestInput(t) + + fees := sdk.NewCoins(sdk.NewCoin(common.DenomColl, 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, common.DenomColl) + 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) + rewardDistributionWindow := uint64(10000000000000) + slashFraction := sdk.NewDecWithPrec(1, 2) + slashWindow := uint64(1000) + minValidPerWindow := sdk.NewDecWithPrec(1, 4) + whitelist := types.PairList{ + {Name: common.PairETHStable.String(), TobinTax: types.DefaultTobinTax}, + {Name: common.PairBTCStable.String(), TobinTax: types.DefaultTobinTax}, + } + + // Should really test validateParams, but skipping because obvious + newParams := types.Params{ + VotePeriod: votePeriod, + VoteThreshold: voteThreshold, + RewardBand: oracleRewardBand, + RewardDistributionWindow: rewardDistributionWindow, + 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", "(1000.0,nibi:usd)|(1000.0,btc:usd)", 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", "(1000.0,nibi:usd)|(1000.0,btc:usd)", 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", "(1000.0,nibi:usd)|(1000.0,btc:usd)", 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{ + {Pair: "foo", ExchangeRate: sdk.NewDec(-1)}, + {Pair: "foo", ExchangeRate: sdk.NewDec(0)}, + {Pair: "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{ + {Pair: "foo", ExchangeRate: sdk.NewDec(-1)}, + {Pair: "foo", ExchangeRate: sdk.NewDec(0)}, + {Pair: "foo", ExchangeRate: sdk.NewDec(1)}, + }, sdk.ValAddress(Addrs[0])) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, sdk.ValAddress(Addrs[0]), aggregateVote1) + + aggregateVote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{ + {Pair: "foo", ExchangeRate: sdk.NewDec(-1)}, + {Pair: "foo", ExchangeRate: sdk.NewDec(0)}, + {Pair: "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 TestTobinTaxGetSet(t *testing.T) { + input := CreateTestInput(t) + + tobinTaxes := map[string]sdk.Dec{ + common.PairBTCStable.String(): sdk.NewDec(1), + common.PairGovStable.String(): sdk.NewDecWithPrec(123, 3), + common.PairCollStable.String(): sdk.NewDecWithPrec(1423, 4), + common.PairETHStable.String(): sdk.NewDecWithPrec(15956, 5), + } + + for denom, tobinTax := range tobinTaxes { + input.OracleKeeper.SetTobinTax(input.Ctx, denom, tobinTax) + factor, err := input.OracleKeeper.GetTobinTax(input.Ctx, denom) + require.NoError(t, err) + require.Equal(t, tobinTaxes[denom], factor) + } + + input.OracleKeeper.IterateTobinTaxes(input.Ctx, func(denom string, tobinTax sdk.Dec) (stop bool) { + require.Equal(t, tobinTaxes[denom], tobinTax) + return false + }) + + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + for denom := range tobinTaxes { + _, err := input.OracleKeeper.GetTobinTax(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 + + // Create 2 validators. + _, 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, addr, sdk.AccAddress(addr1)) + require.NoError(t, input.OracleKeeper.ValidateFeeder(input.Ctx, sdk.AccAddress(addr1), addr)) + require.Error(t, input.OracleKeeper.ValidateFeeder(input.Ctx, Addrs[2], addr)) + + // only active validators can do oracle votes + validator, found := input.StakingKeeper.GetValidator(input.Ctx, 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), addr)) +} diff --git a/x/oracle/keeper/msg_server.go b/x/oracle/keeper/msg_server.go new file mode 100644 index 000000000..95a118bc1 --- /dev/null +++ b/x/oracle/keeper/msg_server.go @@ -0,0 +1,169 @@ +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/NibiruChain/nibiru/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 pairs are in the vote target + for _, tuple := range exchangeRateTuples { + if !ms.IsVoteTarget(ctx, tuple.Pair) { + return nil, sdkerrors.Wrap(types.ErrUnknownPair, tuple.Pair) + } + } + + // Verify an 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/msg_server_test.go b/x/oracle/keeper/msg_server_test.go new file mode 100644 index 000000000..8915420eb --- /dev/null +++ b/x/oracle/keeper/msg_server_test.go @@ -0,0 +1,227 @@ +package keeper + +import ( + "testing" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + "github.com/cosmos/cosmos-sdk/x/staking" +) + +func TestMsgServer_FeederDelegation(t *testing.T) { + input, msgServer := setup(t) + + exchangeRates := types.ExchangeRateTuples{ + { + Pair: common.PairBTCStable.String(), + ExchangeRate: randomExchangeRate, + }, + } + + exchangeRateStr, err := exchangeRates.ToString() + require.NoError(t, err) + salt := "1" + hash := types.GetAggregateVoteHash(salt, exchangeRateStr, ValAddrs[0]) + + // Case 1: empty message + delegateFeedConsentMsg := types.MsgDelegateFeedConsent{} + _, err = msgServer.DelegateFeedConsent(sdk.WrapSDKContext(input.Ctx), &delegateFeedConsentMsg) + require.Error(t, err) + + // Case 2: Normal Prevote - without delegation + prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg) + require.NoError(t, err) + + // Case 2.1: Normal Prevote - with delegation fails + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[1], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg) + require.Error(t, err) + + // Case 2.2: Normal Vote - without delegation + voteMsg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.NoError(t, err) + + // Case 2.3: Normal Vote - with delegation fails + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, Addrs[1], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.Error(t, err) + + // Case 3: Normal MsgDelegateFeedConsent succeeds + msg := types.NewMsgDelegateFeedConsent(ValAddrs[0], Addrs[1]) + _, err = msgServer.DelegateFeedConsent(sdk.WrapSDKContext(input.Ctx), msg) + require.NoError(t, err) + + // Case 4.1: Normal Prevote - without delegation fails + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[2], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg) + require.Error(t, err) + + // Case 4.2: Normal Prevote - with delegation succeeds + prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[1], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg) + require.NoError(t, err) + + // Case 4.3: Normal Vote - without delegation fails + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, Addrs[2], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.Error(t, err) + + // Case 4.4: Normal Vote - with delegation succeeds + voteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRateStr, Addrs[1], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg) + require.NoError(t, err) +} + +func TestMsgServer_AggregatePrevoteVote(t *testing.T) { + input, msgServer := setup(t) + + salt := "1" + exchangeRates := types.ExchangeRateTuples{ + { + Pair: common.PairGovStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("1000.23"), + }, + { + Pair: common.PairETHStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("0.29"), + }, + + { + Pair: common.PairBTCStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("0.27"), + }, + } + + otherExchangeRate := types.ExchangeRateTuples{ + { + Pair: common.PairGovStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("1000.23"), + }, + { + Pair: common.PairETHStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("0.29"), + }, + + { + Pair: common.PairETHStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("0.27"), + }, + } + + unintendedExchangeRateStr := types.ExchangeRateTuples{ + { + Pair: common.PairGovStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("1000.23"), + }, + { + Pair: common.PairETHStable.String(), + ExchangeRate: sdk.MustNewDecFromStr("0.29"), + }, + + { + Pair: common.AssetPair{ + Token0: "BTC", + Token1: "CNY", + }.String(), + ExchangeRate: sdk.MustNewDecFromStr("0.27"), + }, + } + exchangeRatesStr, err := exchangeRates.ToString() + require.NoError(t, err) + + otherExchangeRateStr, err := otherExchangeRate.ToString() + require.NoError(t, err) + + unintendedExchageRateStr, err := unintendedExchangeRateStr.ToString() + require.NoError(t, err) + + hash := types.GetAggregateVoteHash(salt, exchangeRatesStr, ValAddrs[0]) + + aggregateExchangeRatePrevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg) + require.NoError(t, err) + + // Unauthorized feeder + aggregateExchangeRatePrevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[1], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg) + require.Error(t, err) + + // Invalid addr + aggregateExchangeRatePrevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, sdk.AccAddress{}, ValAddrs[0]) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg) + require.Error(t, err) + + // Invalid validator addr + aggregateExchangeRatePrevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[0], sdk.ValAddress{}) + _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg) + require.Error(t, err) + + // Invalid reveal period + aggregateExchangeRateVoteMsg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg) + require.Error(t, err) + + // Invalid reveal period + input.Ctx = input.Ctx.WithBlockHeight(2) + aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg) + require.Error(t, err) + + // Other exchange rate with valid real period + input.Ctx = input.Ctx.WithBlockHeight(1) + aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, otherExchangeRateStr, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg) + require.Error(t, err) + + // Unauthorized feeder + aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[1], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg) + require.Error(t, err) + + // Unintended denom vote + aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, unintendedExchageRateStr, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg) + require.Error(t, err) + + // Valid exchange rate reveal submission + input.Ctx = input.Ctx.WithBlockHeight(1) + aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[0], ValAddrs[0]) + _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg) + require.NoError(t, err) +} + +var ( + stakingAmt = sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + randomExchangeRate = sdk.NewDec(1700) +) + +func setup(t *testing.T) (TestInput, types.MsgServer) { + input := CreateTestInput(t) + params := input.OracleKeeper.GetParams(input.Ctx) + params.VotePeriod = 1 + params.SlashWindow = 100 + params.RewardDistributionWindow = 100 + input.OracleKeeper.SetParams(input.Ctx, params) + msgServer := NewMsgServerImpl(input.OracleKeeper) + + sh := staking.NewHandler(input.StakingKeeper) + + // Validator created + _, err := sh(input.Ctx, NewTestMsgCreateValidator(ValAddrs[0], ValPubKeys[0], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, NewTestMsgCreateValidator(ValAddrs[1], ValPubKeys[1], stakingAmt)) + require.NoError(t, err) + _, err = sh(input.Ctx, NewTestMsgCreateValidator(ValAddrs[2], ValPubKeys[2], stakingAmt)) + require.NoError(t, err) + staking.EndBlocker(input.Ctx, input.StakingKeeper) + + return input, msgServer +} diff --git a/x/oracle/keeper/params.go b/x/oracle/keeper/params.go new file mode 100644 index 000000000..3f94b5750 --- /dev/null +++ b/x/oracle/keeper/params.go @@ -0,0 +1,72 @@ +package keeper + +import ( + "github.com/NibiruChain/nibiru/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 +} + +// RewardDistributionWindow returns the number of vote periods during which seigiornage reward comes in and then is distributed. +func (k Keeper) RewardDistributionWindow(ctx sdk.Context) (res uint64) { + k.paramSpace.Get(ctx, types.KeyRewardDistributionWindow, &res) + return +} + +// Whitelist returns the pair list that can be activated +func (k Keeper) Whitelist(ctx sdk.Context) (res types.PairList) { + 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.PairList) { + k.paramSpace.Set(ctx, types.KeyWhitelist, whitelist) +} + +// 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 100644 index 000000000..67fa267e9 --- /dev/null +++ b/x/oracle/keeper/querier.go @@ -0,0 +1,231 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/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, _ *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 pair +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.Pair) == 0 { + return nil, status.Error(codes.InvalidArgument, "empty pair") + } + + ctx := sdk.UnwrapSDKContext(c) + exchangeRate, err := q.GetExchangeRate(ctx, req.Pair) + if err != nil { + return nil, err + } + + return &types.QueryExchangeRateResponse{ExchangeRate: exchangeRate}, nil +} + +// ExchangeRates queries exchange rates of all pairs +func (q querier) ExchangeRates(c context.Context, _ *types.QueryExchangeRatesRequest) (*types.QueryExchangeRatesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var exchangeRates types.ExchangeRateTuples + q.IterateExchangeRates(ctx, func(pair string, rate sdk.Dec) (stop bool) { + exchangeRates = append(exchangeRates, types.ExchangeRateTuple{ + Pair: pair, + ExchangeRate: rate, + }) + return false + }) + + return &types.QueryExchangeRatesResponse{ExchangeRates: exchangeRates}, nil +} + +// TobinTax queries tobin tax of a pair +func (q querier) TobinTax(c context.Context, req *types.QueryTobinTaxRequest) (*types.QueryTobinTaxResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + if len(req.Pair) == 0 { + return nil, status.Error(codes.InvalidArgument, "empty pair") + } + + ctx := sdk.UnwrapSDKContext(c) + tobinTax, err := q.GetTobinTax(ctx, req.Pair) + if err != nil { + return nil, err + } + + return &types.QueryTobinTaxResponse{TobinTax: tobinTax}, nil +} + +// TobinTaxes queries tobin taxes of all pairs +func (q querier) TobinTaxes(c context.Context, _ *types.QueryTobinTaxesRequest) (*types.QueryTobinTaxesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var tobinTaxes types.PairList + q.IterateTobinTaxes(ctx, func(pair string, rate sdk.Dec) (stop bool) { + tobinTaxes = append(tobinTaxes, types.Pair{ + Name: pair, + TobinTax: rate, + }) + return false + }) + + return &types.QueryTobinTaxesResponse{TobinTaxes: tobinTaxes}, nil +} + +// Actives queries all pairs for which exchange rates exist +func (q querier) Actives(c context.Context, _ *types.QueryActivesRequest) (*types.QueryActivesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var pairs []string + q.IterateExchangeRates(ctx, func(pair string, rate sdk.Dec) (stop bool) { + pairs = append(pairs, pair) + return false + }) + + return &types.QueryActivesResponse{Actives: pairs}, nil +} + +// VoteTargets queries the voting target list on current vote period +func (q querier) VoteTargets(c context.Context, _ *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, _ *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, _ *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 100644 index 000000000..844611443 --- /dev/null +++ b/x/oracle/keeper/querier_test.go @@ -0,0 +1,293 @@ +package keeper + +import ( + "bytes" + "sort" + "testing" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +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.SetExchangeRate(input.Ctx, common.PairETHStable.String(), rate) + + // empty request + _, err := querier.ExchangeRate(ctx, nil) + require.Error(t, err) + + // Query to grpc + res, err := querier.ExchangeRate(ctx, &types.QueryExchangeRateRequest{ + Pair: common.PairETHStable.String(), + }) + require.NoError(t, err) + require.Equal(t, rate, res.ExchangeRate) +} + +func TestQueryMissCounter(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + missCounter := uint64(1) + input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], missCounter) + + // empty request + _, err := querier.MissCounter(ctx, nil) + require.Error(t, err) + + // Query to grpc + res, err := querier.MissCounter(ctx, &types.QueryMissCounterRequest{ + ValidatorAddr: ValAddrs[0].String(), + }) + require.NoError(t, err) + require.Equal(t, missCounter, res.MissCounter) +} + +func TestQueryExchangeRates(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + rate := sdk.NewDec(1700) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairBTCStable.String(), rate) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairETHStable.String(), rate) + + res, err := querier.ExchangeRates(ctx, &types.QueryExchangeRatesRequest{}) + require.NoError(t, err) + + require.Equal(t, types.ExchangeRateTuples{ + {Pair: common.PairBTCStable.String(), ExchangeRate: rate}, + {Pair: common.PairETHStable.String(), ExchangeRate: rate}, + }, res.ExchangeRates) +} + +func TestQueryActives(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + rate := sdk.NewDec(1700) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairBTCStable.String(), rate) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairGovStable.String(), rate) + input.OracleKeeper.SetExchangeRate(input.Ctx, common.PairETHStable.String(), rate) + + res, err := querier.Actives(ctx, &types.QueryActivesRequest{}) + require.NoError(t, err) + + targetDenoms := []string{ + common.PairBTCStable.String(), + common.PairETHStable.String(), + common.PairGovStable.String(), + } + + require.Equal(t, targetDenoms, res.Actives) +} + +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]) + + // empty request + _, err := querier.FeederDelegation(ctx, nil) + require.Error(t, err) + + 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) + + // empty request + _, err = querier.AggregatePrevote(ctx, nil) + require.Error(t, err) + + // 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{{Pair: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[0]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[0], vote1) + vote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Pair: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[1]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[1], vote2) + + // empty request + _, err := querier.AggregateVote(ctx, nil) + require.Error(t, err) + + // 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{{Pair: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[0]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[0], vote1) + vote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Pair: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[1]) + input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[1], vote2) + vote3 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Pair: "", 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) + + // clear tobin taxes + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + + voteTargets := []string{"denom", "denom2", "denom3"} + for _, target := range voteTargets { + input.OracleKeeper.SetTobinTax(input.Ctx, target, sdk.OneDec()) + } + + res, err := querier.VoteTargets(ctx, &types.QueryVoteTargetsRequest{}) + require.NoError(t, err) + require.Equal(t, voteTargets, res.VoteTargets) +} + +func TestQueryTobinTaxes(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + // clear tobin taxes + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + + tobinTaxes := types.PairList{{ + Name: common.PairBTCStable.String(), + TobinTax: sdk.OneDec(), + }, { + Name: common.PairETHStable.String(), + TobinTax: sdk.NewDecWithPrec(123, 2), + }} + for _, item := range tobinTaxes { + input.OracleKeeper.SetTobinTax(input.Ctx, item.Name, item.TobinTax) + } + + res, err := querier.TobinTaxes(ctx, &types.QueryTobinTaxesRequest{}) + require.NoError(t, err) + require.Equal(t, tobinTaxes, res.TobinTaxes) +} + +func TestQueryTobinTax(t *testing.T) { + input := CreateTestInput(t) + ctx := sdk.WrapSDKContext(input.Ctx) + querier := NewQuerier(input.OracleKeeper) + + denom := types.Pair{Name: common.PairBTCStable.String(), TobinTax: sdk.OneDec()} + input.OracleKeeper.SetTobinTax(input.Ctx, denom.Name, denom.TobinTax) + + // empty request + _, err := querier.TobinTax(ctx, nil) + require.Error(t, err) + + res, err := querier.TobinTax(ctx, &types.QueryTobinTaxRequest{ + Pair: common.PairBTCStable.String(), + }) + require.NoError(t, err) + + require.Equal(t, denom.TobinTax, res.TobinTax) +} diff --git a/x/oracle/keeper/reward.go b/x/oracle/keeper/reward.go new file mode 100644 index 000000000..a4117a4b7 --- /dev/null +++ b/x/oracle/keeper/reward.go @@ -0,0 +1,82 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +// RewardBallotWinners implements +// at the end of every VotePeriod, give out a portion of spread fees collected in the oracle reward pool +// +// to the oracle voters that voted faithfully. +func (k Keeper) RewardBallotWinners( + ctx sdk.Context, + votePeriod int64, + rewardDistributionWindow int64, + voteTargets map[string]sdk.Dec, + ballotWinners map[string]types.Claim, +) { + rewardDenoms := make([]string, len(voteTargets)+1) + rewardDenoms[0] = common.DenomGov + + i := 1 + for denom := range voteTargets { + rewardDenoms[i] = denom + i++ + } + + // Sum weight of the claims + ballotPowerSum := int64(0) + for _, winner := range ballotWinners { + ballotPowerSum += winner.Weight + } + + // Exit if the ballot is empty + if ballotPowerSum == 0 { + return + } + + // The Reward distributionRatio = votePeriod/rewardDistributionWindow + distributionRatio := sdk.NewDec(votePeriod).QuoInt64(rewardDistributionWindow) + + var periodRewards sdk.DecCoins + for _, denom := range rewardDenoms { + rewardPool := k.GetRewardPool(ctx, denom) + + // return if there's no rewards to give out + if rewardPool.IsZero() { + continue + } + + periodRewards = periodRewards.Add(sdk.NewDecCoinFromDec( + denom, + sdk.NewDecFromInt(rewardPool.Amount).Mul(distributionRatio), + )) + } + + // Dole out rewards + var distributedReward sdk.Coins + for _, winner := range ballotWinners { + receiverVal := k.StakingKeeper.Validator(ctx, winner.Recipient) + + // Reflects contribution + rewardCoins, _ := periodRewards.MulDec(sdk.NewDec(winner.Weight).QuoInt64(ballotPowerSum)).TruncateDecimal() + + // In case absence of the validator, we just skip distribution + if receiverVal != nil && !rewardCoins.IsZero() { + k.distrKeeper.AllocateTokensToValidator(ctx, receiverVal, sdk.NewDecCoinsFromCoins(rewardCoins...)) + distributedReward = distributedReward.Add(rewardCoins...) + } + } + + // Move distributed reward to distribution module + err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.distrName, distributedReward) + if err != nil { + panic(fmt.Sprintf("[oracle] Failed to send coins to distribution module %s", err.Error())) + } +} diff --git a/x/oracle/keeper/reward_test.go b/x/oracle/keeper/reward_test.go new file mode 100644 index 000000000..a71845ec7 --- /dev/null +++ b/x/oracle/keeper/reward_test.go @@ -0,0 +1,70 @@ +package keeper + +// Test a reward giving mechanism +/* TODO(mercilex): currently not appliable https://github.com/NibiruChain/nibiru/issues/805 +func TestRewardBallotWinners(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()) + + // Add claim pools + claim := types.NewClaim(10, 10, 0, addr) + claim2 := types.NewClaim(20, 20, 0, addr1) + claims := map[string]types.Claim{ + addr.String(): claim, + addr1.String(): claim2, + } + + // Prepare reward pool + givingAmt := sdk.NewCoins(sdk.NewInt64Coin(common.DenomGov, 30000000), sdk.NewInt64Coin(core.MicroUSDDenom, 40000000)) + acc := input.AccountKeeper.GetModuleAccount(ctx, types.ModuleName) + err = FundAccount(input, acc.GetAddress(), givingAmt) + require.NoError(t, err) + + voteTargets := make(map[string]sdk.Dec) + input.OracleKeeper.IterateTobinTaxes(ctx, func(denom string, tobinTax sdk.Dec) bool { + voteTargets[denom] = tobinTax + return false + }) + + votePeriodsPerWindow := sdk.NewDec((int64)(input.OracleKeeper.RewardDistributionWindow(input.Ctx))). + QuoInt64((int64)(input.OracleKeeper.VotePeriod(input.Ctx))). + TruncateInt64() + input.OracleKeeper.RewardBallotWinners(ctx, (int64)(input.OracleKeeper.VotePeriod(input.Ctx)), (int64)(input.OracleKeeper.RewardDistributionWindow(input.Ctx)), voteTargets, claims) + outstandingRewardsDec := input.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, addr) + outstandingRewards, _ := outstandingRewardsDec.TruncateDecimal() + require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(common.DenomGov)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).TruncateInt(), + outstandingRewards.AmountOf(common.DenomGov)) + require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroUSDDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).TruncateInt(), + outstandingRewards.AmountOf(core.MicroUSDDenom)) + + outstandingRewardsDec1 := input.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, addr1) + outstandingRewards1, _ := outstandingRewardsDec1.TruncateDecimal() + require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(common.DenomGov)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).MulInt64(2).TruncateInt(), + outstandingRewards1.AmountOf(common.DenomGov)) + require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroUSDDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).MulInt64(2).TruncateInt(), + outstandingRewards1.AmountOf(core.MicroUSDDenom)) +} +*/ diff --git a/x/oracle/keeper/slash.go b/x/oracle/keeper/slash.go new file mode 100644 index 000000000..55ea85796 --- /dev/null +++ b/x/oracle/keeper/slash.go @@ -0,0 +1,48 @@ +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 100644 index 000000000..6bc8f640d --- /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 100644 index 000000000..edeef016e --- /dev/null +++ b/x/oracle/keeper/test_utils.go @@ -0,0 +1,267 @@ +//nolint +package keeper + +import ( + "github.com/NibiruChain/nibiru/x/common" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + distr "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/staking" + "testing" + + "github.com/NibiruChain/nibiru/x/oracle/types" + "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" + 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" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + 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{}, + distr.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(common.DenomGov, 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 +// Creates a base app, with 5 accounts, +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(common.DenomGov, 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 = common.DenomGov + 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(common.DenomGov, 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.SetTobinTax(ctx, denom.Name, denom.TobinTax) + } + + 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(common.DenomGov, 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 100644 index 000000000..96930ed80 --- /dev/null +++ b/x/oracle/keeper/vote_target.go @@ -0,0 +1,19 @@ +package keeper + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// IsVoteTarget returns existence of a pair in the voting target list +func (k Keeper) IsVoteTarget(ctx sdk.Context, pair string) bool { + _, err := k.GetTobinTax(ctx, pair) + return err == nil +} + +// GetVoteTargets returns the voting target list on current vote period +func (k Keeper) GetVoteTargets(ctx sdk.Context) (voteTargets []string) { + k.IterateTobinTaxes(ctx, func(pair string, _ sdk.Dec) bool { + voteTargets = append(voteTargets, pair) + 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 100644 index 000000000..252323c09 --- /dev/null +++ b/x/oracle/keeper/vote_target_test.go @@ -0,0 +1,35 @@ +package keeper + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestKeeper_GetVoteTargets(t *testing.T) { + input := CreateTestInput(t) + + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + + expectedTargets := []string{"bar", "foo", "whoowhoo"} + for _, target := range expectedTargets { + input.OracleKeeper.SetTobinTax(input.Ctx, target, sdk.OneDec()) + } + + targets := input.OracleKeeper.GetVoteTargets(input.Ctx) + require.Equal(t, expectedTargets, targets) +} + +func TestKeeper_IsVoteTarget(t *testing.T) { + input := CreateTestInput(t) + + input.OracleKeeper.ClearTobinTaxes(input.Ctx) + + validTargets := []string{"bar", "foo", "whoowhoo"} + for _, target := range validTargets { + input.OracleKeeper.SetTobinTax(input.Ctx, target, sdk.OneDec()) + require.True(t, input.OracleKeeper.IsVoteTarget(input.Ctx, target)) + } +} diff --git a/x/oracle/module.go b/x/oracle/module.go new file mode 100644 index 000000000..35043f7fd --- /dev/null +++ b/x/oracle/module.go @@ -0,0 +1,204 @@ +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/NibiruChain/nibiru/x/oracle/client/cli" + "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/x/oracle/simulation" + "github.com/NibiruChain/nibiru/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(_ client.Context, _ *mux.Router) { +} + +// 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, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + return nil, fmt.Errorf("not supported") + }) +} + +// 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 func(_ sdk.Context, _ []string, _ abci.RequestQuery) ([]byte, error) { + return nil, fmt.Errorf("deprecated, use gRPC web") + } +} + +// 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 100644 index 000000000..b90d8bea7 --- /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/NibiruChain/nibiru/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.TobinTaxKey): + var tobinTaxA, tobinTaxB sdk.DecProto + cdc.MustUnmarshal(kvA.Value, &tobinTaxA) + cdc.MustUnmarshal(kvB.Value, &tobinTaxB) + return fmt.Sprintf("%v\n%v", tobinTaxA, tobinTaxB) + 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 100644 index 000000000..b6b8dc724 --- /dev/null +++ b/x/oracle/simulation/decoder_test.go @@ -0,0 +1,79 @@ +package simulation_test + +import ( + "fmt" + "testing" + + "github.com/NibiruChain/nibiru/x/common" + + 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/NibiruChain/nibiru/x/oracle/keeper" + sim "github.com/NibiruChain/nibiru/x/oracle/simulation" + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +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{ + {Pair: common.DenomStable, ExchangeRate: sdk.NewDecWithPrec(1234, 1)}, + {Pair: common.DenomStable, ExchangeRate: sdk.NewDecWithPrec(4321, 1)}, + }, valAddr) + + tobinTax := sdk.NewDecWithPrec(2, 2) + + 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.TobinTaxKey, Value: cdc.MustMarshal(&sdk.DecProto{Dec: tobinTax})}, + {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)}, + {"TobinTax", fmt.Sprintf("%v\n%v", tobinTax, tobinTax)}, + {"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 100644 index 000000000..0bd2a0f81 --- /dev/null +++ b/x/oracle/simulation/genesis.go @@ -0,0 +1,137 @@ +package simulation + +//DONTCOVER + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/NibiruChain/nibiru/x/common" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +// 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)) +} + +// GenRewardDistributionWindow randomized RewardDistributionWindow +func GenRewardDistributionWindow(r *rand.Rand) uint64 { + return uint64(100 + r.Intn(100000)) +} + +// 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 rewardDistributionWindow uint64 + simState.AppParams.GetOrGenerate( + simState.Cdc, rewardDistributionWindowKey, &rewardDistributionWindow, simState.Rand, + func(r *rand.Rand) { rewardDistributionWindow = GenRewardDistributionWindow(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, + RewardDistributionWindow: rewardDistributionWindow, + Whitelist: types.PairList{ + {Name: common.PairETHStable.String(), TobinTax: types.DefaultTobinTax}, + {Name: common.PairCollStable.String(), TobinTax: types.DefaultTobinTax}, + {Name: common.PairBTCStable.String(), TobinTax: types.DefaultTobinTax}, + {Name: common.PairGovStable.String(), TobinTax: sdk.NewDecWithPrec(2, 2)}}, + SlashFraction: slashFraction, + SlashWindow: slashWindow, + MinValidPerWindow: minValidPerWindow, + }, + []types.ExchangeRateTuple{}, + []types.FeederDelegation{}, + []types.MissCounter{}, + []types.AggregateExchangeRatePrevote{}, + []types.AggregateExchangeRateVote{}, + []types.TobinTax{}, + ) + + 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 100644 index 000000000..d3d7f0a16 --- /dev/null +++ b/x/oracle/simulation/operations.go @@ -0,0 +1,270 @@ +package simulation + +//DONTCOVER + +import ( + "math/rand" + "strings" + + "github.com/NibiruChain/nibiru/x/common" + + "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/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +// 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{common.PairBTCStable.String(), common.PairETHStable.String(), common.PairGovStable.String()} + 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 100644 index 000000000..31a03ee01 --- /dev/null +++ b/x/oracle/simulation/params.go @@ -0,0 +1,50 @@ +package simulation + +//DONTCOVER + +import ( + "fmt" + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/NibiruChain/nibiru/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.KeyRewardDistributionWindow), + func(r *rand.Rand) string { + return fmt.Sprintf("\"%d\"", GenRewardDistributionWindow(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 100644 index 000000000..2130568ca --- /dev/null +++ b/x/oracle/spec/01_concepts.md @@ -0,0 +1,58 @@ + + +# Concepts + +## Voting Procedure + +During each `VotePeriod`, the Oracle module obtains consensus on the exchange rate of pairs specified in `Whitelist` by requiring all members of the validator set to submit a vote for exchange rates 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 pairs. A prevote must be submitted for all pairs. + * A `MsgAggregateExchangeRateVote`, containing the salt used to create the hash for the aggregate 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 pair, 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 the following `VotePeriod` `P_t+1`. + + Exchange rates receiving fewer than `VoteThreshold` total voting power have their exchange rates deleted from the store, and no exchange rate will exist for 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. + +## 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 an exchange rate against **each and every** pair specified in `Whitelist`. + +* The validator fails to vote within the `reward band` around the weighted median for one or more pairs. + +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 `MsgAggregateExchangeRateVote`. 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, 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 100644 index 000000000..385b37f3e --- /dev/null +++ b/x/oracle/spec/02_state.md @@ -0,0 +1,63 @@ + + +# State + +## ExchangeRate + +An `sdk.Dec` that stores the current exchange rate against a given pair. + +You can get the active list of pairs (exchange rates with votes past `VoteThreshold`) with `k.GetActivePairs()`. + +- ExchangeRate: `0x03 -> amino(sdk.Dec)` + +## FeederDelegation + +An `sdk.AccAddress` (`nibi-` 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 pairs 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}:({pair},{exchange_rate})|...|({pair},{exchange_rate}):{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 pairs for the current `VotePeriod`. + +- AggregateExchangeRateVote: `0x07 -> amino(AggregateExchangeRateVote)` + +```go +type ExchangeRateTuple struct { + Pair string `json:"pair"` + ExchangeRate sdk.Dec `json:"exchange_rate"` +} + +type ExchangeRateTuples []ExchangeRateTuple + +type AggregateExchangeRateVote struct { + ExchangeRateTuples ExchangeRateTuples // ExchangeRates of pairs + 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 100644 index 000000000..fb46382af --- /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 exchange rates are purged from the store + +2. Received votes are organized into ballots by pair. Abstained votes, as well as votes by inactive or jailed validators are ignored + +3. Pairs not meeting the following requirements will be dropped: + + - Must appear in the permitted pairs in `Whitelist` + - Ballot for pair must have at least `VoteThreshold` total vote power + +4. For each remaining `pair` 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 exchange rate on the blockchain for that pair with `k.SetExchangeRate()` + - Emit an `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 100644 index 000000000..98596031a --- /dev/null +++ b/x/oracle/spec/04_messages.md @@ -0,0 +1,54 @@ + + +# Messages + +## 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}:({pair},{exchange_rate})|...|({pair},{exchange_rate}):{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}:({pair},{exchange_rate})|...|({pair},{exchange_rate}):{voter}") +type MsgAggregateExchangeRatePrevote struct { + Hash AggregateVoteHash + Feeder sdk.AccAddress + Validator sdk.ValAddress +} +``` + +`Feeder` (`nibi-` 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 (`nibivaloper-` address) of the original validator. + +## 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 pairs. +type MsgAggregateExchangeRateVote struct { + Salt string + ExchangeRates 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 `MsgAggregateExchangeRatePrevote` and `MsgAggregateExchangeRateVote` on behalf of the validator. + +> Delegate validators will likely require you to deposit some funds (in NIBI) which they can use to pay fees, sent in a separate MsgSend. This agreement is made off-chain and not enforced by the Nibiru protocol. + +The `Operator` field contains the operator address of the validator (prefixed `nibivaloper-`). The `Delegate` field is the account address (prefixed `nibi-`) 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 +} +``` diff --git a/x/oracle/spec/05_events.md b/x/oracle/spec/05_events.md new file mode 100644 index 000000000..f056875d9 --- /dev/null +++ b/x/oracle/spec/05_events.md @@ -0,0 +1,70 @@ + + +# Events + +The oracle module emits the following events: + +## EndBlocker + +| Type | Attribute Key | Attribute Value | +|----------------------|---------------|-----------------| +| exchange_rate_update | pair | {pair} | +| exchange_rate_update | exchange_rate | {exchangeRate} | + +## Handlers + +### MsgExchangeRatePrevote + +| Type | Attribute Key | Attribute Value | +|---------|---------------|---------------------| +| prevote | pair | {pair} | +| prevote | voter | {validatorAddress} | +| prevote | feeder | {feederAddress} | +| message | module | oracle | +| message | action | exchangerateprevote | +| message | sender | {senderAddress} | + +### MsgExchangeRateVote + +| Type | Attribute Key | Attribute Value | +|---------|---------------|--------------------| +| vote | pair | {pair} | +| 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 100644 index 000000000..a95d3dbe5 --- /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 | []PairList | [{"name": "unibi:unusd", tobin_tax": "0.002000000000000000"}] | +| slashfraction | string (dec) | "0.001000000000000000" | +| slashwindow | string (int) | "100800" | +| minvalidperwindow | string (int) | "0.050000000000000000" | diff --git a/x/oracle/spec/README.md b/x/oracle/spec/README.md new file mode 100644 index 000000000..8f89a2faa --- /dev/null +++ b/x/oracle/spec/README.md @@ -0,0 +1,36 @@ +# Abstract + +The Oracle module provides the Nibiru blockchain with an up-to-date and accurate price feed of exchange rates of trading pairs. + +As price information is extrinsic to the blockchain, the Nibiru network relies on validators to periodically vote on the current exchange rates, 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) + - [TobinTax](02_state.md#TobinTax) +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)** diff --git a/x/oracle/tally.go b/x/oracle/tally.go new file mode 100644 index 000000000..19be12db1 --- /dev/null +++ b/x/oracle/tally.go @@ -0,0 +1,85 @@ +package oracle + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/NibiruChain/nibiru/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(_ 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) +} + +// PickReferencePair choose Reference pair with the highest voter turnout +// If the voting power of the two denominations is the same, +// select reference pair in alphabetical order. +func PickReferencePair(ctx sdk.Context, k keeper.Keeper, voteTargets map[string]sdk.Dec, voteMap map[string]types.ExchangeRateBallot) string { + largestBallotPower := int64(0) + referencePair := "" + + totalBondedPower := sdk.TokensToConsensusPower(k.StakingKeeper.TotalBondedTokens(ctx), k.StakingKeeper.PowerReduction(ctx)) + voteThreshold := k.VoteThreshold(ctx) + thresholdVotes := voteThreshold.MulInt64(totalBondedPower).RoundInt() + + for pair, ballot := range voteMap { + // If pair 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[pair]; !exists { + delete(voteMap, pair) + 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, pair) + delete(voteMap, pair) + continue + } + + if ballotPower > largestBallotPower || largestBallotPower == 0 { + referencePair = pair + largestBallotPower = ballotPower + } else if largestBallotPower == ballotPower && referencePair > pair { + referencePair = pair + } + } + + return referencePair +} diff --git a/x/oracle/tally_fuzz_test.go b/x/oracle/tally_fuzz_test.go new file mode 100644 index 000000000..f33296c41 --- /dev/null +++ b/x/oracle/tally_fuzz_test.go @@ -0,0 +1,138 @@ +package oracle_test + +import ( + "sort" + "testing" + + fuzz "github.com/google/gofuzz" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/x/oracle" + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +func TestFuzz_Tally(t *testing.T) { + validators := map[string]int64{} + + f := fuzz.New().NilChance(0).Funcs( + func(e *sdk.Dec, c fuzz.Continue) { + *e = sdk.NewDec(c.Int63()) + }, + func(e *map[string]int64, c fuzz.Continue) { + numValidators := c.Intn(100) + 5 + + for i := 0; i < numValidators; i++ { + (*e)[sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()).String()] = c.Int63n(100) + } + }, + func(e *map[string]types.Claim, c fuzz.Continue) { + for validator, power := range validators { + addr, err := sdk.ValAddressFromBech32(validator) + require.NoError(t, err) + (*e)[validator] = types.NewClaim(power, 0, 0, addr) + } + }, + func(e *types.ExchangeRateBallot, c fuzz.Continue) { + ballot := types.ExchangeRateBallot{} + for addr, power := range validators { + addr, _ := sdk.ValAddressFromBech32(addr) + + var rate sdk.Dec + c.Fuzz(&rate) + + ballot = append(ballot, types.NewBallotVoteForTally(rate, c.RandString(), addr, power)) + } + + sort.Sort(ballot) + + *e = ballot + }, + ) + + // set random denoms and validators + f.Fuzz(&validators) + + input, _ := setup(t) + + claimMap := map[string]types.Claim{} + f.Fuzz(&claimMap) + + ballot := types.ExchangeRateBallot{} + f.Fuzz(&ballot) + + var rewardBand sdk.Dec + f.Fuzz(&rewardBand) + + require.NotPanics(t, func() { + oracle.Tally(input.Ctx, ballot, rewardBand, claimMap) + }) +} + +func TestFuzz_PickReferencePair(t *testing.T) { + var denoms []string + + f := fuzz.New().NilChance(0).Funcs( + func(e *[]string, c fuzz.Continue) { + numDenoms := c.Intn(100) + 5 + + for i := 0; i < numDenoms; i++ { + *e = append(*e, c.RandString()) + } + }, + func(e *sdk.Dec, c fuzz.Continue) { + *e = sdk.NewDec(c.Int63()) + }, + func(e *map[string]sdk.Dec, c fuzz.Continue) { + for _, denom := range denoms { + var rate sdk.Dec + c.Fuzz(&rate) + + (*e)[denom] = rate + } + }, + func(e *map[string]int64, c fuzz.Continue) { + numValidator := c.Intn(100) + 5 + for i := 0; i < numValidator; i++ { + (*e)[sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()).String()] = int64(c.Intn(100) + 1) + } + }, + func(e *map[string]types.ExchangeRateBallot, c fuzz.Continue) { + validators := map[string]int64{} + c.Fuzz(&validators) + + for _, denom := range denoms { + ballot := types.ExchangeRateBallot{} + + for addr, power := range validators { + addr, _ := sdk.ValAddressFromBech32(addr) + + var rate sdk.Dec + c.Fuzz(&rate) + + ballot = append(ballot, types.NewBallotVoteForTally(rate, denom, addr, power)) + } + + sort.Sort(ballot) + (*e)[denom] = ballot + } + }, + ) + + // set random denoms + f.Fuzz(&denoms) + + input, _ := setup(t) + + voteTargets := map[string]sdk.Dec{} + f.Fuzz(&voteTargets) + + voteMap := map[string]types.ExchangeRateBallot{} + f.Fuzz(&voteMap) + + require.NotPanics(t, func() { + oracle.PickReferencePair(input.Ctx, input.OracleKeeper, voteTargets, voteMap) + }) +} diff --git a/x/oracle/types/ballot.go b/x/oracle/types/ballot.go new file mode 100644 index 000000000..d7282a96b --- /dev/null +++ b/x/oracle/types/ballot.go @@ -0,0 +1,194 @@ +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 + +// BallotVoteForTally is a convenience wrapper to reduce redundant lookup cost +type BallotVoteForTally struct { + Pair string + ExchangeRate sdk.Dec + Voter sdk.ValAddress + Power int64 +} + +// NewBallotVoteForTally returns a new VoteForTally instance +func NewBallotVoteForTally(rate sdk.Dec, pair string, voter sdk.ValAddress, power int64) BallotVoteForTally { + return BallotVoteForTally{ + ExchangeRate: rate, + Pair: pair, + Voter: voter, + Power: power, + } +} + +// ExchangeRateBallot is a convenience wrapper around a ExchangeRateVote slice +type ExchangeRateBallot []BallotVoteForTally + +// 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 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(referenceExchangeRates map[string]sdk.Dec) (cb ExchangeRateBallot) { + for _, vote := range pb { + if referenceExchangeRate, ok := referenceExchangeRates[string(vote.Voter)]; ok && vote.ExchangeRate.IsPositive() { + vote.ExchangeRate = referenceExchangeRate.Quo(vote.ExchangeRate) + } else { + // If we can't get reference pair 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 100644 index 000000000..9a820da7a --- /dev/null +++ b/x/oracle/types/ballot_test.go @@ -0,0 +1,340 @@ +package types_test + +import ( + "fmt" + "math" + "sort" + "strconv" + + "github.com/NibiruChain/nibiru/x/common" + + "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/NibiruChain/nibiru/x/oracle/types" +) + +func TestToMap(t *testing.T) { + tests := struct { + votes []types.BallotVoteForTally + isValid []bool + }{ + + []types.BallotVoteForTally{ + { + + Voter: sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()), + Pair: common.PairBTCStable.String(), + ExchangeRate: sdk.NewDec(1600), + Power: 100, + }, + { + + Voter: sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()), + Pair: common.PairBTCStable.String(), + ExchangeRate: sdk.ZeroDec(), + Power: 100, + }, + { + + Voter: sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()), + Pair: common.PairBTCStable.String(), + ExchangeRate: sdk.NewDec(1500), + Power: 100, + }, + }, + []bool{true, false, true}, + } + + pb := types.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 := types.ExchangeRateBallot{} + pbQuote := types.ExchangeRateBallot{} + cb := types.ExchangeRateBallot{} + for _, data := range data { + valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()) + if !data.base.IsZero() { + pbBase = append(pbBase, types.NewBallotVoteForTally(data.base, common.PairBTCStable.String(), valAddr, 100)) + } + + pbQuote = append(pbQuote, types.NewBallotVoteForTally(data.quote, common.PairBTCStable.String(), valAddr, 100)) + + if !data.base.IsZero() && !data.quote.IsZero() { + cb = append(cb, types.NewBallotVoteForTally(data.base.Quo(data.quote), common.PairBTCStable.String(), valAddr, 100)) + } else { + cb = append(cb, types.NewBallotVoteForTally(sdk.ZeroDec(), common.PairBTCStable.String(), valAddr, 0)) + } + } + + baseMapBallot := pbBase.ToMap() + require.Equal(t, cb, pbQuote.ToCrossRate(baseMapBallot)) + + sort.Sort(cb) + + 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 := types.GenerateRandomTestCase() + pb := types.ExchangeRateBallot{} + ballotPower := int64(0) + + for i := 0; i < len(sk.Validators()); i++ { + power := sk.Validator(ctx, valAccAddrs[i]).GetConsensusPower(sdk.DefaultPowerReduction) + vote := types.NewBallotVoteForTally( + sdk.ZeroDec(), + common.PairETHStable.String(), + 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 := types.NewBallotVoteForTally( + sdk.OneDec(), + common.PairETHStable.String(), + 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 + panic bool + }{ + { + // Supermajority one number + []int64{1, 2, 10, 100000}, + []int64{1, 1, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDec(10), + false, + }, + { + // 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), + false, + }, + { + // Tie votes + []int64{1, 2, 3, 4}, + []int64{1, 100, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDec(2), + false, + }, + { + // No votes + []int64{}, + []int64{}, + []bool{true, true, true, true}, + sdk.NewDec(0), + false, + }, + { + // not sorted panic + []int64{2, 1, 10, 100000}, + []int64{1, 1, 100, 1}, + []bool{true, true, true, true}, + sdk.NewDec(10), + true, + }, + } + + for _, tc := range tests { + pb := types.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 := types.NewBallotVoteForTally( + sdk.NewDec(int64(input)), + common.PairETHStable.String(), + valAddr, + power, + ) + + pb = append(pb, vote) + } + + if tc.panic { + require.Panics(t, func() { pb.WeightedMedianWithAssertion() }) + } else { + require.Equal(t, tc.median, pb.WeightedMedian()) + 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, types.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, types.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, types.OracleDecPrecision), + }, + { + // No votes + []float64{}, + []int64{}, + []bool{true, true, true, true}, + sdk.NewDecWithPrec(0, 0), + }, + } + + base := math.Pow10(types.OracleDecPrecision) + for _, tc := range tests { + pb := types.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 := types.NewBallotVoteForTally( + sdk.NewDecWithPrec(int64(input*base), int64(types.OracleDecPrecision)), + common.PairETHStable.String(), + 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 := types.ExchangeRateBallot{types.NewBallotVoteForTally( + sdk.ZeroDec(), + common.PairETHStable.String(), + valAddr, + 2, + ), types.NewBallotVoteForTally( + exchangeRate, + common.PairETHStable.String(), + valAddr, + 1, + )} + + require.Equal(t, sdk.ZeroDec(), pb.StandardDeviation(pb.WeightedMedianWithAssertion())) +} + +func TestNewClaim(t *testing.T) { + power := int64(10) + weight := int64(11) + winCount := int64(1) + addr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address().Bytes()) + claim := types.NewClaim(power, weight, winCount, addr) + require.Equal(t, types.Claim{ + Power: power, + Weight: weight, + WinCount: winCount, + Recipient: addr, + }, claim) +} diff --git a/x/oracle/types/codec.go b/x/oracle/types/codec.go new file mode 100644 index 000000000..efe53d14e --- /dev/null +++ b/x/oracle/types/codec.go @@ -0,0 +1,46 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterLegacyAminoCodec registers the necessary x/oracle interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgAggregateExchangeRatePrevote{}, "oracle/MsgAggregateExchangeRatePrevote", nil) + cdc.RegisterConcrete(&MsgAggregateExchangeRateVote{}, "oracle/MsgAggregateExchangeRateVote", nil) + cdc.RegisterConcrete(&MsgDelegateFeedConsent{}, "oracle/MsgDelegateFeedConsent", nil) +} + +// RegisterInterfaces registers the x/oracle interfaces types with the interface registry +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgDelegateFeedConsent{}, + &MsgAggregateExchangeRatePrevote{}, + &MsgAggregateExchangeRateVote{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + amino = codec.NewLegacyAmino() + + // ModuleCdc references the global x/oracle module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding as Amino is + // still used for that purpose. + // + // The actual codec used for serialization should be provided to x/staking and + // defined at the application level. + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + amino.Seal() +} diff --git a/x/oracle/types/core.go b/x/oracle/types/core.go new file mode 100644 index 000000000..774c44850 --- /dev/null +++ b/x/oracle/types/core.go @@ -0,0 +1,8 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// IsPeriodLastBlock returns true if we are at the last block of the period +func IsPeriodLastBlock(ctx sdk.Context, blocksPerPeriod uint64) bool { + return ((uint64)(ctx.BlockHeight())+1)%blocksPerPeriod == 0 +} diff --git a/x/oracle/types/errors.go b/x/oracle/types/errors.go new file mode 100644 index 000000000..0fa3fe99e --- /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") + ErrNoTobinTax = sdkerrors.Register(ModuleName, 13, "no tobin tax") + ErrUnknownPair = sdkerrors.Register(ModuleName, 14, "unknown pair") +) diff --git a/x/oracle/types/events.go b/x/oracle/types/events.go new file mode 100644 index 000000000..91be4c9ab --- /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" + + AttributeKeyPair = "pair" + 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 100644 index 000000000..b91dfd8bb --- /dev/null +++ b/x/oracle/types/expected_keeper.go @@ -0,0 +1,42 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/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 offense height, offense 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 + // 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 100644 index 000000000..c6b959033 --- /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, + TobinTaxes []TobinTax, +) *GenesisState { + return &GenesisState{ + Params: params, + ExchangeRates: rates, + FeederDelegations: feederDelegations, + MissCounters: missCounters, + AggregateExchangeRatePrevotes: aggregateExchangeRatePrevotes, + AggregateExchangeRateVotes: aggregateExchangeRateVotes, + TobinTaxes: TobinTaxes, + } +} + +// DefaultGenesisState - default GenesisState used by columbus-2 +func DefaultGenesisState() *GenesisState { + return NewGenesisState(DefaultParams(), + []ExchangeRateTuple{}, + []FeederDelegation{}, + []MissCounter{}, + []AggregateExchangeRatePrevote{}, + []AggregateExchangeRateVote{}, + []TobinTax{}) +} + +// 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 000000000..874696aef --- /dev/null +++ b/x/oracle/types/genesis.pb.go @@ -0,0 +1,1368 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/v1beta1/genesis.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 + +// GenesisState defines the oracle module's genesis state. +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"` + TobinTaxes []TobinTax `protobuf:"bytes,7,rep,name=tobin_taxes,json=tobinTaxes,proto3" json:"tobin_taxes"` +} + +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_6d8ee91da7d45482, []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 +} + +func (m *GenesisState) GetTobinTaxes() []TobinTax { + if m != nil { + return m.TobinTaxes + } + return nil +} + +// FeederDelegation is the address for where oracle feeder authority are +// delegated to. By default this struct is only used at genesis to feed in +// default feeder addresses. +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_6d8ee91da7d45482, []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 "" +} + +// MissCounter defines an miss counter and validator address pair used in +// oracle module's genesis state +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_6d8ee91da7d45482, []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 +} + +// TobinTax defines a pair and tobin_tax pair used in +// oracle module's genesis state +type TobinTax struct { + Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"` + TobinTax github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=tobin_tax,json=tobinTax,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"tobin_tax"` +} + +func (m *TobinTax) Reset() { *m = TobinTax{} } +func (m *TobinTax) String() string { return proto.CompactTextString(m) } +func (*TobinTax) ProtoMessage() {} +func (*TobinTax) Descriptor() ([]byte, []int) { + return fileDescriptor_6d8ee91da7d45482, []int{3} +} +func (m *TobinTax) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TobinTax) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TobinTax.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 *TobinTax) XXX_Merge(src proto.Message) { + xxx_messageInfo_TobinTax.Merge(m, src) +} +func (m *TobinTax) XXX_Size() int { + return m.Size() +} +func (m *TobinTax) XXX_DiscardUnknown() { + xxx_messageInfo_TobinTax.DiscardUnknown(m) +} + +var xxx_messageInfo_TobinTax proto.InternalMessageInfo + +func (m *TobinTax) GetPair() string { + if m != nil { + return m.Pair + } + return "" +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "nibiru.oracle.v1beta1.GenesisState") + proto.RegisterType((*FeederDelegation)(nil), "nibiru.oracle.v1beta1.FeederDelegation") + proto.RegisterType((*MissCounter)(nil), "nibiru.oracle.v1beta1.MissCounter") + proto.RegisterType((*TobinTax)(nil), "nibiru.oracle.v1beta1.TobinTax") +} + +func init() { proto.RegisterFile("oracle/v1beta1/genesis.proto", fileDescriptor_6d8ee91da7d45482) } + +var fileDescriptor_6d8ee91da7d45482 = []byte{ + // 569 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xe3, 0x36, 0x2d, 0xed, 0xa6, 0xad, 0xda, 0x15, 0x48, 0x51, 0xa0, 0x4e, 0x89, 0x04, + 0x54, 0x02, 0x6c, 0xda, 0x1e, 0x39, 0x35, 0x2d, 0xe5, 0x80, 0x8a, 0x2a, 0x53, 0x71, 0x40, 0x20, + 0x6b, 0x6d, 0x4f, 0xdd, 0x55, 0x13, 0xaf, 0xe5, 0xd9, 0x54, 0xe9, 0x95, 0x27, 0xe0, 0x39, 0x90, + 0x78, 0x8f, 0x1e, 0x7b, 0x44, 0x1c, 0x0a, 0x4a, 0x5e, 0x04, 0x79, 0x77, 0x93, 0x98, 0x10, 0x23, + 0x71, 0x8a, 0x33, 0xf3, 0xcd, 0xff, 0xcf, 0xec, 0x8e, 0x4d, 0x1e, 0x88, 0x8c, 0x85, 0x1d, 0x70, + 0x2f, 0x77, 0x02, 0x90, 0x6c, 0xc7, 0x8d, 0x21, 0x01, 0xe4, 0xe8, 0xa4, 0x99, 0x90, 0x82, 0xde, + 0x4b, 0x78, 0xc0, 0xb3, 0x9e, 0xa3, 0x21, 0xc7, 0x40, 0x8d, 0xbb, 0xb1, 0x88, 0x85, 0x22, 0xdc, + 0xfc, 0x49, 0xc3, 0x8d, 0xfb, 0x53, 0x52, 0xa6, 0x48, 0x27, 0xed, 0x50, 0x60, 0x57, 0xa0, 0x1b, + 0x30, 0x9c, 0x10, 0xa1, 0xe0, 0x89, 0xce, 0xb7, 0xbe, 0x2d, 0x90, 0x95, 0xd7, 0xda, 0xfb, 0x9d, + 0x64, 0x12, 0xe8, 0x4b, 0xb2, 0x98, 0xb2, 0x8c, 0x75, 0xb1, 0x6e, 0x6d, 0x59, 0xdb, 0xb5, 0xdd, + 0x4d, 0x67, 0x66, 0x2f, 0xce, 0x89, 0x82, 0xda, 0xd5, 0xeb, 0xdb, 0x66, 0xc5, 0x33, 0x25, 0xf4, + 0x23, 0xa1, 0x67, 0x00, 0x11, 0x64, 0x7e, 0x04, 0x1d, 0x88, 0x99, 0xe4, 0x22, 0xc1, 0xfa, 0xdc, + 0xd6, 0xfc, 0x76, 0x6d, 0xf7, 0x49, 0x89, 0xd0, 0x91, 0x2a, 0x38, 0x1c, 0xf3, 0x46, 0x72, 0xe3, + 0x6c, 0x2a, 0x8e, 0xf4, 0x82, 0xac, 0x41, 0x3f, 0x3c, 0x67, 0x49, 0x0c, 0x7e, 0xc6, 0x24, 0x60, + 0x7d, 0x5e, 0x29, 0x6f, 0x97, 0x28, 0xbf, 0x32, 0xb0, 0xc7, 0x24, 0x9c, 0xf6, 0xd2, 0x0e, 0xb4, + 0x1b, 0xb9, 0xf4, 0xd7, 0x9f, 0x4d, 0xfa, 0x57, 0x0a, 0xbd, 0x55, 0x28, 0xc4, 0x90, 0x1e, 0x93, + 0xd5, 0x2e, 0x47, 0xf4, 0x43, 0xd1, 0x4b, 0x24, 0x64, 0x58, 0xaf, 0x2a, 0xaf, 0x56, 0x89, 0xd7, + 0x31, 0x47, 0x3c, 0xd0, 0xa8, 0x19, 0x60, 0xa5, 0x3b, 0x09, 0x21, 0xfd, 0x6c, 0x91, 0x2d, 0x16, + 0xc7, 0x59, 0x3e, 0x0c, 0xf8, 0x7f, 0x8c, 0xe1, 0xa7, 0x19, 0x5c, 0x8a, 0x7c, 0x9c, 0x05, 0x65, + 0xb1, 0x57, 0x62, 0xb1, 0x3f, 0x2a, 0x2f, 0x36, 0x7f, 0xa2, 0x6b, 0x8d, 0xe7, 0x26, 0xfb, 0x07, + 0x83, 0xf4, 0x8a, 0x6c, 0x96, 0xf5, 0xa0, 0x1b, 0x58, 0x54, 0x0d, 0xbc, 0xf8, 0x9f, 0x06, 0xde, + 0x4f, 0xdc, 0x1b, 0xac, 0x0c, 0x40, 0x7a, 0x44, 0x6a, 0x52, 0x04, 0x3c, 0xf1, 0x25, 0xeb, 0x03, + 0xd6, 0xef, 0x28, 0xa3, 0x66, 0x89, 0xd1, 0x69, 0x4e, 0x9e, 0xb2, 0xbe, 0xd1, 0x25, 0xd2, 0xfc, + 0x07, 0x6c, 0x9d, 0x91, 0xf5, 0xe9, 0x85, 0xa1, 0x8f, 0xc8, 0x9a, 0xd9, 0x3a, 0x16, 0x45, 0x19, + 0xa0, 0x5e, 0xdd, 0x65, 0x6f, 0x55, 0x47, 0xf7, 0x75, 0x90, 0x3e, 0x25, 0x1b, 0x97, 0xac, 0xc3, + 0x23, 0x26, 0xc5, 0x84, 0x9c, 0x53, 0xe4, 0xfa, 0x38, 0x61, 0xe0, 0xd6, 0x27, 0x52, 0x2b, 0x5c, + 0xe9, 0xec, 0x5a, 0x6b, 0x76, 0x2d, 0x7d, 0x48, 0x56, 0x8a, 0xab, 0xa3, 0x3c, 0xaa, 0x5e, 0xad, + 0xb0, 0x0f, 0xad, 0x0b, 0xb2, 0x34, 0x1a, 0x92, 0x52, 0x52, 0x4d, 0x19, 0xcf, 0x8c, 0x9c, 0x7a, + 0xa6, 0x6f, 0xc8, 0xf2, 0xf8, 0xb8, 0x74, 0x8f, 0x6d, 0x27, 0x3f, 0x8b, 0x1f, 0xb7, 0xcd, 0xc7, + 0x31, 0x97, 0xe7, 0xbd, 0xc0, 0x09, 0x45, 0xd7, 0x35, 0x2f, 0xb7, 0xfe, 0x79, 0x8e, 0xd1, 0x85, + 0x2b, 0xaf, 0x52, 0x40, 0xe7, 0x10, 0x42, 0x6f, 0x69, 0x74, 0x6a, 0xed, 0xa3, 0xeb, 0x81, 0x6d, + 0xdd, 0x0c, 0x6c, 0xeb, 0xd7, 0xc0, 0xb6, 0xbe, 0x0c, 0xed, 0xca, 0xcd, 0xd0, 0xae, 0x7c, 0x1f, + 0xda, 0x95, 0x0f, 0xcf, 0x0a, 0x5a, 0x6f, 0xd5, 0x55, 0x1c, 0x9c, 0x33, 0x9e, 0xb8, 0xfa, 0x5a, + 0xdc, 0xbe, 0xf9, 0x96, 0x68, 0xd5, 0x60, 0x51, 0x7d, 0x32, 0xf6, 0x7e, 0x07, 0x00, 0x00, 0xff, + 0xff, 0x7c, 0x61, 0x66, 0xd3, 0xbc, 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.TobinTaxes) > 0 { + for iNdEx := len(m.TobinTaxes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TobinTaxes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + 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 (m *TobinTax) 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 *TobinTax) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TobinTax) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.TobinTax.Size() + i -= size + if _, err := m.TobinTax.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Pair) > 0 { + i -= len(m.Pair) + copy(dAtA[i:], m.Pair) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Pair))) + 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)) + } + } + if len(m.TobinTaxes) > 0 { + for _, e := range m.TobinTaxes { + 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 (m *TobinTax) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Pair) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = m.TobinTax.Size() + n += 1 + l + sovGenesis(uint64(l)) + 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 + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TobinTaxes", 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.TobinTaxes = append(m.TobinTaxes, TobinTax{}) + if err := m.TobinTaxes[len(m.TobinTaxes)-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 (m *TobinTax) 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: TobinTax: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TobinTax: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pair", 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.Pair = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TobinTax", 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 + } + if err := m.TobinTax.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 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 100644 index 000000000..ed5bf47b7 --- /dev/null +++ b/x/oracle/types/genesis_test.go @@ -0,0 +1,28 @@ +package types_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +func TestGenesisValidation(t *testing.T) { + genState := types.DefaultGenesisState() + require.NoError(t, types.ValidateGenesis(genState)) + + genState.Params.VotePeriod = 0 + require.Error(t, types.ValidateGenesis(genState)) +} + +func TestGetGenesisStateFromAppState(t *testing.T) { + cdc := app.MakeTestEncodingConfig().Marshaler + appState := make(map[string]json.RawMessage) + + defaultGenesisState := types.DefaultGenesisState() + appState[types.ModuleName] = cdc.MustMarshalJSON(defaultGenesisState) + require.Equal(t, *defaultGenesisState, *types.GetGenesisStateFromAppState(cdc, appState)) +} diff --git a/x/oracle/types/hash.go b/x/oracle/types/hash.go new file mode 100644 index 000000000..0cbc76ffd --- /dev/null +++ b/x/oracle/types/hash.go @@ -0,0 +1,121 @@ +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}:({pair},{exchange_rate})|...|({pair},{exchange_rate}):{voter}") +type AggregateVoteHash []byte + +// GetAggregateVoteHash computes hash value of ExchangeRateVote +// to avoid redundant DecCoins stringify operation, use string argument +// TODO(mercilex): use ExchangeRateTuples +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 100644 index 000000000..e24389ac1 --- /dev/null +++ b/x/oracle/types/hash_test.go @@ -0,0 +1,43 @@ +package types_test + +import ( + "encoding/hex" + + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "testing" +) + +func TestAggregateVoteHash(t *testing.T) { + addrs := []sdk.AccAddress{ + sdk.AccAddress([]byte("addr1_______________")), + } + + aggregateVoteHash := types.GetAggregateVoteHash("salt", "(100,nibi:usd)|(200000,btc:usd)", sdk.ValAddress(addrs[0])) + hexStr := hex.EncodeToString(aggregateVoteHash) + aggregateVoteHashRes, err := types.AggregateVoteHashFromHexString(hexStr) + require.NoError(t, err) + require.Equal(t, aggregateVoteHash, aggregateVoteHashRes) + require.True(t, aggregateVoteHash.Equal(aggregateVoteHash)) + require.True(t, types.AggregateVoteHash([]byte{}).Empty()) + + got, _ := yaml.Marshal(&aggregateVoteHash) + require.Equal(t, aggregateVoteHash.String()+"\n", string(got)) + + res := types.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 100644 index 000000000..6094646f1 --- /dev/null +++ b/x/oracle/types/keys.go @@ -0,0 +1,80 @@ +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 + TobinTaxKey = []byte{0x06} // prefix for each key to a tobin tax +) + +// GetExchangeRateKey - stored by *pair* +func GetExchangeRateKey(pair string) []byte { + return append(ExchangeRateKey, append([]byte(pair), 0x00)...) +} + +// 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)...) +} + +// GetTobinTaxKey - stored by *pair* bytes +func GetTobinTaxKey(d string) []byte { + return append(TobinTaxKey, append([]byte(d), 0x00)...) +} + +// ExtractPairFromTobinTaxKey - split pair from the tobin tax key +func ExtractPairFromTobinTaxKey(key []byte) (pair string) { + pair = string(key[1 : len(key)-1]) + return +} diff --git a/x/oracle/types/msgs.go b/x/oracle/types/msgs.go new file mode 100644 index 000000000..958c12aa1 --- /dev/null +++ b/x/oracle/types/msgs.go @@ -0,0 +1,193 @@ +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 +// TODO(mercilex): accept ExchangeRatesTuples +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 100644 index 000000000..bed546fa6 --- /dev/null +++ b/x/oracle/types/msgs_test.go @@ -0,0 +1,124 @@ +package types_test + +import ( + "testing" + + "github.com/NibiruChain/nibiru/x/common" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + "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 := types.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(common.DenomColl, sdk.OneDec()), sdk.NewDecCoinFromDec(common.DenomStable, sdk.NewDecWithPrec(32121, 1))} + bz := types.GetAggregateVoteHash("1", exchangeRates.String(), sdk.ValAddress(addrs[0])) + + tests := []struct { + hash types.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}, + {types.AggregateVoteHash{}, exchangeRates, addrs[0], false}, + } + + for i, tc := range tests { + msg := types.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("addr1_______________"), + } + + exchangeRates := types.ExchangeRateTuples{ + { + Pair: "FOO:USD", + ExchangeRate: sdk.MustNewDecFromStr("1.0"), + }, + { + Pair: "BAR:USD", + ExchangeRate: sdk.MustNewDecFromStr("1232.132"), + }, + } + + abstainExchangeRates := types.ExchangeRateTuples{ + { + Pair: "FOO:USD", + ExchangeRate: sdk.ZeroDec(), + }, + { + Pair: "BAR:USD", + ExchangeRate: sdk.MustNewDecFromStr("1232.132"), + }, + } + + tests := []struct { + voter sdk.AccAddress + validator sdk.ValAddress + salt string + exchangeRates types.ExchangeRateTuples + expectPass bool + }{ + {addrs[0], sdk.ValAddress(addrs[0]), "123", exchangeRates, true}, + {addrs[0], sdk.ValAddress(addrs[0]), "123", abstainExchangeRates, true}, + {sdk.AccAddress{}, sdk.ValAddress(addrs[0]), "123", exchangeRates, false}, + {addrs[0], sdk.ValAddress(addrs[0]), "123", types.ExchangeRateTuples{}, false}, + {addrs[0], sdk.ValAddress{}, "123", abstainExchangeRates, false}, + {addrs[0], sdk.ValAddress(addrs[0]), "", abstainExchangeRates, false}, + } + + for i, tc := range tests { + exchangeRates, err := tc.exchangeRates.ToString() + require.NoError(t, err) + msg := types.NewMsgAggregateExchangeRateVote(tc.salt, exchangeRates, tc.voter, tc.validator) + 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 000000000..3a38a56b1 --- /dev/null +++ b/x/oracle/types/oracle.pb.go @@ -0,0 +1,1585 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/v1beta1/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 + +// Params defines the parameters for the oracle module. +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"` + RewardDistributionWindow uint64 `protobuf:"varint,4,opt,name=reward_distribution_window,json=rewardDistributionWindow,proto3" json:"reward_distribution_window,omitempty" yaml:"reward_distribution_window"` + Whitelist PairList `protobuf:"bytes,5,rep,name=whitelist,proto3,castrepeated=PairList" json:"whitelist" yaml:"whitelist"` + SlashFraction github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,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,7,opt,name=slash_window,json=slashWindow,proto3" json:"slash_window,omitempty" yaml:"slash_window"` + MinValidPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,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_2784fd4b0e83b02f, []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) GetRewardDistributionWindow() uint64 { + if m != nil { + return m.RewardDistributionWindow + } + return 0 +} + +func (m *Params) GetWhitelist() PairList { + if m != nil { + return m.Whitelist + } + return nil +} + +func (m *Params) GetSlashWindow() uint64 { + if m != nil { + return m.SlashWindow + } + return 0 +} + +// Pair is the object that holds configuration of each pair. +type Pair struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + TobinTax github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=tobin_tax,json=tobinTax,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"tobin_tax" yaml:"tobin_tax"` +} + +func (m *Pair) Reset() { *m = Pair{} } +func (*Pair) ProtoMessage() {} +func (*Pair) Descriptor() ([]byte, []int) { + return fileDescriptor_2784fd4b0e83b02f, []int{1} +} +func (m *Pair) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Pair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Pair.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 *Pair) XXX_Merge(src proto.Message) { + xxx_messageInfo_Pair.Merge(m, src) +} +func (m *Pair) XXX_Size() int { + return m.Size() +} +func (m *Pair) XXX_DiscardUnknown() { + xxx_messageInfo_Pair.DiscardUnknown(m) +} + +var xxx_messageInfo_Pair proto.InternalMessageInfo + +// 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}:({pair},{exchange_rate})|...|({pair},{exchange_rate}):{voter}") +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_2784fd4b0e83b02f, []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 + +// MsgAggregateExchangeRateVote - struct for voting on +// the exchange rates different assets. +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_2784fd4b0e83b02f, []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 + +// ExchangeRateTuple - struct to store interpreted exchange rates data to store +type ExchangeRateTuple struct { + Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty" yaml:"pair"` + 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_2784fd4b0e83b02f, []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), "nibiru.oracle.v1beta1.Params") + proto.RegisterType((*Pair)(nil), "nibiru.oracle.v1beta1.Pair") + proto.RegisterType((*AggregateExchangeRatePrevote)(nil), "nibiru.oracle.v1beta1.AggregateExchangeRatePrevote") + proto.RegisterType((*AggregateExchangeRateVote)(nil), "nibiru.oracle.v1beta1.AggregateExchangeRateVote") + proto.RegisterType((*ExchangeRateTuple)(nil), "nibiru.oracle.v1beta1.ExchangeRateTuple") +} + +func init() { proto.RegisterFile("oracle/v1beta1/oracle.proto", fileDescriptor_2784fd4b0e83b02f) } + +var fileDescriptor_2784fd4b0e83b02f = []byte{ + // 763 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x31, 0x6f, 0xdb, 0x46, + 0x14, 0x16, 0x6b, 0x59, 0x95, 0x4f, 0x72, 0x6b, 0xb3, 0x72, 0xcb, 0xda, 0x85, 0xe8, 0x5e, 0x5b, + 0x43, 0x43, 0x2b, 0xc2, 0xed, 0x50, 0x44, 0x5b, 0x18, 0xc7, 0x59, 0x92, 0x40, 0x20, 0x0c, 0x07, + 0xc8, 0x42, 0x1c, 0xc9, 0x8b, 0x78, 0x30, 0xc9, 0x13, 0x8e, 0x27, 0x4b, 0x5e, 0x32, 0x67, 0xcc, + 0x90, 0x00, 0x41, 0x26, 0xcf, 0x59, 0x83, 0xfc, 0x07, 0x8f, 0x1e, 0x83, 0x0c, 0x4c, 0x60, 0x2f, + 0xc9, 0xaa, 0x5f, 0x10, 0xdc, 0xf1, 0x6c, 0x53, 0x96, 0x02, 0x44, 0xc8, 0x24, 0xbe, 0xf7, 0xbd, + 0xfb, 0xde, 0x77, 0xef, 0xe3, 0x13, 0xc1, 0x06, 0x65, 0xc8, 0x8f, 0xb0, 0x75, 0xb8, 0xed, 0x61, + 0x8e, 0xb6, 0xad, 0x3c, 0x6c, 0xf7, 0x19, 0xe5, 0x54, 0x5f, 0x4b, 0x88, 0x47, 0xd8, 0xa0, 0xad, + 0x92, 0xaa, 0x66, 0xbd, 0xd1, 0xa3, 0x3d, 0x2a, 0x2b, 0x2c, 0xf1, 0x94, 0x17, 0xaf, 0x37, 0x7d, + 0x9a, 0xc6, 0x34, 0xb5, 0x3c, 0x94, 0x5e, 0xd1, 0xf9, 0x94, 0x24, 0x39, 0x0e, 0x9f, 0x55, 0x40, + 0xa5, 0x8b, 0x18, 0x8a, 0x53, 0xfd, 0x7f, 0x50, 0x3b, 0xa4, 0x1c, 0xbb, 0x7d, 0xcc, 0x08, 0x0d, + 0x0c, 0x6d, 0x53, 0x6b, 0x95, 0xed, 0x9f, 0xc7, 0x99, 0xa9, 0x1f, 0xa1, 0x38, 0xea, 0xc0, 0x02, + 0x08, 0x1d, 0x20, 0xa2, 0xae, 0x0c, 0xf4, 0x04, 0xfc, 0x20, 0x31, 0x1e, 0x32, 0x9c, 0x86, 0x34, + 0x0a, 0x8c, 0xef, 0x36, 0xb5, 0xd6, 0x92, 0x7d, 0xe7, 0x24, 0x33, 0x4b, 0xef, 0x32, 0x73, 0xab, + 0x47, 0x78, 0x38, 0xf0, 0xda, 0x3e, 0x8d, 0x2d, 0x25, 0x27, 0xff, 0xf9, 0x27, 0x0d, 0x0e, 0x2c, + 0x7e, 0xd4, 0xc7, 0x69, 0x7b, 0x07, 0xfb, 0xe3, 0xcc, 0x5c, 0x2b, 0x74, 0xba, 0x64, 0x83, 0xce, + 0xb2, 0x48, 0xec, 0x5d, 0xc4, 0x3a, 0x06, 0x35, 0x86, 0x87, 0x88, 0x05, 0xae, 0x87, 0x92, 0xc0, + 0x58, 0x90, 0xcd, 0x76, 0xe6, 0x6e, 0xa6, 0xae, 0x55, 0xa0, 0x82, 0x0e, 0xc8, 0x23, 0x1b, 0x25, + 0x81, 0xee, 0x83, 0x75, 0x85, 0x05, 0x24, 0xe5, 0x8c, 0x78, 0x03, 0x4e, 0x68, 0xe2, 0x0e, 0x49, + 0x12, 0xd0, 0xa1, 0x51, 0x96, 0xe3, 0xf9, 0x6b, 0x9c, 0x99, 0xbf, 0x4f, 0xf0, 0xcc, 0xa8, 0x85, + 0x8e, 0x91, 0x83, 0x3b, 0x05, 0xec, 0x81, 0x84, 0x74, 0x17, 0x2c, 0x0d, 0x43, 0xc2, 0x71, 0x44, + 0x52, 0x6e, 0x2c, 0x6e, 0x2e, 0xb4, 0x6a, 0xff, 0x6e, 0xb4, 0x67, 0x1a, 0xdc, 0xee, 0x22, 0xc2, + 0xec, 0x3f, 0xc5, 0x35, 0xc7, 0x99, 0xb9, 0x92, 0x37, 0xbd, 0x3c, 0x0b, 0x5f, 0xbd, 0x37, 0xab, + 0xa2, 0xe2, 0x2e, 0x49, 0xb9, 0x73, 0xc5, 0x29, 0xcc, 0x49, 0x23, 0x94, 0x86, 0xee, 0x23, 0x86, + 0x7c, 0xd1, 0xd8, 0xa8, 0x7c, 0x9b, 0x39, 0x93, 0x6c, 0xd0, 0x59, 0x96, 0x89, 0x5d, 0x15, 0xeb, + 0x1d, 0x50, 0xcf, 0x2b, 0xd4, 0x9c, 0xbe, 0x97, 0x73, 0xfa, 0x65, 0x9c, 0x99, 0x3f, 0x15, 0xcf, + 0x5f, 0x4c, 0xa6, 0x26, 0x43, 0x35, 0x8c, 0xc7, 0xa0, 0x11, 0x93, 0xc4, 0x3d, 0x44, 0x11, 0x09, + 0xc4, 0x9b, 0x76, 0xc1, 0x51, 0x95, 0x8a, 0xef, 0xcd, 0xad, 0x78, 0x23, 0xef, 0x38, 0x8b, 0x13, + 0x3a, 0xab, 0x31, 0x49, 0xf6, 0x45, 0xb6, 0x8b, 0x59, 0xde, 0xbf, 0x53, 0x7d, 0x71, 0x6c, 0x96, + 0x3e, 0x1e, 0x9b, 0x1a, 0x7c, 0xa9, 0x81, 0xb2, 0x98, 0xa6, 0xfe, 0x07, 0x28, 0x27, 0x28, 0xc6, + 0x72, 0x1b, 0x96, 0xec, 0x1f, 0xc7, 0x99, 0x59, 0xcb, 0x49, 0x45, 0x16, 0x3a, 0x12, 0x14, 0x26, + 0x72, 0xea, 0x91, 0xc4, 0xe5, 0x68, 0xa4, 0xde, 0x7d, 0x7b, 0x6e, 0xb1, 0xca, 0xd1, 0x4b, 0x22, + 0xe8, 0x54, 0xe5, 0xf3, 0x1e, 0x1a, 0x75, 0xea, 0x4f, 0x8e, 0xcd, 0x92, 0x12, 0x57, 0x82, 0x6f, + 0x34, 0xf0, 0xdb, 0xcd, 0x5e, 0x8f, 0xe1, 0x1e, 0xe2, 0xf8, 0xf6, 0xc8, 0x0f, 0x51, 0xd2, 0xc3, + 0x0e, 0xe2, 0xb8, 0xcb, 0xb0, 0xd8, 0x14, 0x21, 0x3a, 0x44, 0x69, 0x38, 0x2d, 0x5a, 0x64, 0xa1, + 0x23, 0x41, 0x7d, 0x0b, 0x2c, 0x8a, 0x62, 0xa6, 0x04, 0xaf, 0x8c, 0x33, 0xb3, 0x7e, 0xb5, 0x7e, + 0x0c, 0x3a, 0x39, 0x2c, 0x0d, 0x1d, 0x78, 0x31, 0xe1, 0xae, 0x17, 0x51, 0xff, 0x40, 0xae, 0xdb, + 0xa4, 0xa1, 0x05, 0x54, 0x18, 0x2a, 0x43, 0x5b, 0x44, 0xd7, 0x74, 0x7f, 0xd2, 0xc0, 0xaf, 0x33, + 0x75, 0xef, 0x0b, 0xd1, 0xcf, 0x35, 0xd0, 0xc0, 0x2a, 0xe9, 0x32, 0x24, 0xfe, 0x01, 0x06, 0xfd, + 0x08, 0xa7, 0x86, 0x26, 0xb7, 0xa2, 0xf5, 0x85, 0xad, 0x28, 0xf2, 0xec, 0x89, 0x03, 0xf6, 0x0d, + 0xb5, 0x22, 0xca, 0xfd, 0x59, 0x9c, 0x62, 0x5b, 0xf4, 0xa9, 0x93, 0xa9, 0xa3, 0xe3, 0xa9, 0xdc, + 0xd7, 0xce, 0xe9, 0xda, 0x5d, 0x5f, 0x6b, 0x60, 0x75, 0xaa, 0x81, 0x30, 0xa6, 0x8f, 0x08, 0x9b, + 0x36, 0x46, 0x64, 0xa1, 0x23, 0x41, 0xfd, 0x00, 0x2c, 0x4f, 0x68, 0x56, 0x8d, 0x77, 0xe7, 0x7e, + 0xa3, 0x1a, 0x33, 0x06, 0x00, 0x9d, 0x7a, 0xf1, 0x8e, 0x93, 0xaa, 0xed, 0xdd, 0x93, 0xb3, 0xa6, + 0x76, 0x7a, 0xd6, 0xd4, 0x3e, 0x9c, 0x35, 0xb5, 0xa7, 0xe7, 0xcd, 0xd2, 0xe9, 0x79, 0xb3, 0xf4, + 0xf6, 0xbc, 0x59, 0x7a, 0xf8, 0x77, 0xa1, 0xeb, 0x7d, 0x69, 0xc4, 0xad, 0x10, 0x91, 0xc4, 0xca, + 0x4d, 0xb1, 0x46, 0xea, 0x13, 0x95, 0xf7, 0xf7, 0x2a, 0xf2, 0xe3, 0xf2, 0xdf, 0xe7, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x16, 0xe3, 0xae, 0xaa, 0xc8, 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 this.RewardDistributionWindow != that1.RewardDistributionWindow { + 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] = 0x42 + if m.SlashWindow != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.SlashWindow)) + i-- + dAtA[i] = 0x38 + } + { + 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] = 0x32 + 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] = 0x2a + } + } + if m.RewardDistributionWindow != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.RewardDistributionWindow)) + i-- + dAtA[i] = 0x20 + } + { + 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 *Pair) 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 *Pair) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Pair) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.TobinTax.Size() + i -= size + if _, err := m.TobinTax.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + 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.Pair) > 0 { + i -= len(m.Pair) + copy(dAtA[i:], m.Pair) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Pair))) + 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 m.RewardDistributionWindow != 0 { + n += 1 + sovOracle(uint64(m.RewardDistributionWindow)) + } + 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 *Pair) 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)) + } + l = m.TobinTax.Size() + 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.Pair) + 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 != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDistributionWindow", wireType) + } + m.RewardDistributionWindow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RewardDistributionWindow |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + 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, Pair{}) + if err := m.Whitelist[len(m.Whitelist)-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 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 7: + 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 8: + 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 *Pair) 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: Pair: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Pair: 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 + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TobinTax", 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.TobinTax.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 *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 Pair", 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.Pair = 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/pair_list.go b/x/oracle/types/pair_list.go new file mode 100644 index 000000000..7b7a26f4f --- /dev/null +++ b/x/oracle/types/pair_list.go @@ -0,0 +1,29 @@ +package types + +import ( + "strings" + + "gopkg.in/yaml.v2" +) + +// String implements fmt.Stringer interface +func (m Pair) String() string { + out, _ := yaml.Marshal(m) + return string(out) +} + +// Equal implements equal interface +func (m Pair) Equal(pair *Pair) bool { + return m.Name == pair.Name && m.TobinTax.Equal(pair.TobinTax) +} + +// PairList is array of Pair +type PairList []Pair + +// String implements fmt.Stringer interface +func (dl PairList) String() (out string) { + for _, d := range dl { + out += d.String() + "\n" + } + return strings.TrimSpace(out) +} diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go new file mode 100644 index 000000000..6a4be1271 --- /dev/null +++ b/x/oracle/types/params.go @@ -0,0 +1,269 @@ +package types + +import ( + "fmt" + + "gopkg.in/yaml.v2" + + "github.com/NibiruChain/nibiru/x/common" + + 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") + KeyRewardDistributionWindow = []byte("RewardDistributionWindow") + KeyWhitelist = []byte("Whitelist") + KeySlashFraction = []byte("SlashFraction") + KeySlashWindow = []byte("SlashWindow") + KeyMinValidPerWindow = []byte("MinValidPerWindow") +) + +// Default parameter values +// TODO(mercilex): need to adjust this based on expected genesis parameters, this assumes block times are 1s +// DefaultVotePeriod: 10s +// DefaultSlashWindow: 1 Week +// DefaultRewardDistributionWindow: 1 year +const ( + DefaultVotePeriod = 10 // vote every 10s + DefaultSlashWindow = 604800 // 1 week + DefaultRewardDistributionWindow = DefaultSlashWindow * 54 // 1 week * 54 weeks (weeks in a year) +) + +// Default parameter values +var ( + DefaultVoteThreshold = sdk.NewDecWithPrec(50, 2) // 50% + DefaultRewardBand = sdk.NewDecWithPrec(2, 2) // 2% (-1, 1) + DefaultTobinTax = sdk.NewDecWithPrec(25, 4) // 0.25% + DefaultWhitelist = PairList{ + { + Name: common.PairBTCStable.String(), + TobinTax: DefaultTobinTax, + }, + { + Name: common.PairCollStable.String(), + TobinTax: DefaultTobinTax, + }, + { + Name: common.PairETHStable.String(), + TobinTax: DefaultTobinTax, + }, + { + Name: common.PairGovStable.String(), + TobinTax: DefaultTobinTax, + }, + } + 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, + RewardDistributionWindow: DefaultRewardDistributionWindow, + 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(KeyRewardDistributionWindow, &p.RewardDistributionWindow, validateRewardDistributionWindow), + 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.RewardDistributionWindow < p.VotePeriod { + return fmt.Errorf("oracle parameter RewardDistributionWindow must be greater than or equal with VotePeriod") + } + + 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 _, pair := range p.Whitelist { + if pair.TobinTax.GT(sdk.OneDec()) || pair.TobinTax.IsNegative() { + return fmt.Errorf("oracle parameter Whitelist Pair must have TobinTax between [0, 1]") + } + if len(pair.Name) == 0 { + return fmt.Errorf("oracle parameter Whitelist Pair 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 validateRewardDistributionWindow(i interface{}) error { + v, ok := i.(uint64) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v == 0 { + return fmt.Errorf("reward distribution window must be positive: %d", v) + } + + return nil +} + +func validateWhitelist(i interface{}) error { + v, ok := i.(PairList) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + for _, d := range v { + if d.TobinTax.GT(sdk.OneDec()) || d.TobinTax.IsNegative() { + return fmt.Errorf("oracle parameter Whitelist Pair must have TobinTax between [0, 1]") + } + if len(d.Name) == 0 { + return fmt.Errorf("oracle parameter Whitelist Pair 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 100644 index 000000000..8f72daf0f --- /dev/null +++ b/x/oracle/types/params_test.go @@ -0,0 +1,134 @@ +package types_test + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/x/oracle/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestParamsEqual(t *testing.T) { + p1 := types.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 := types.DefaultParams() + p2.VoteThreshold = sdk.ZeroDec() + err = p2.Validate() + require.Error(t, err) + + // negative reward band + p3 := types.DefaultParams() + p3.RewardBand = sdk.NewDecWithPrec(-1, 2) + err = p3.Validate() + require.Error(t, err) + + // negative slash fraction + p4 := types.DefaultParams() + p4.SlashFraction = sdk.NewDec(-1) + err = p4.Validate() + require.Error(t, err) + + // negative min valid per window + p5 := types.DefaultParams() + p5.MinValidPerWindow = sdk.NewDec(-1) + err = p5.Validate() + require.Error(t, err) + + // small slash window + p6 := types.DefaultParams() + p6.SlashWindow = 0 + err = p6.Validate() + require.Error(t, err) + + // small distribution window + p7 := types.DefaultParams() + p7.RewardDistributionWindow = 0 + err = p7.Validate() + require.Error(t, err) + + // non-positive tobin tax + p8 := types.DefaultParams() + p8.Whitelist[0].Name = "" + err = p8.Validate() + require.Error(t, err) + + // invalid name tobin tax + p9 := types.DefaultParams() + p9.Whitelist[0].TobinTax = sdk.NewDec(-1) + err = p9.Validate() + require.Error(t, err) + + // empty name + p10 := types.DefaultParams() + p10.Whitelist[0].Name = "" + err = p10.Validate() + require.Error(t, err) + + p11 := types.DefaultParams() + require.NotNil(t, p11.ParamSetPairs()) + require.NotNil(t, p11.String()) +} + +func TestValidate(t *testing.T) { + p1 := types.DefaultParams() + pairs := p1.ParamSetPairs() + for _, pair := range pairs { + switch { + case bytes.Equal(types.KeyVotePeriod, pair.Key) || + bytes.Equal(types.KeyRewardDistributionWindow, pair.Key) || + bytes.Equal(types.KeySlashWindow, pair.Key): + require.NoError(t, pair.ValidatorFn(uint64(1))) + require.Error(t, pair.ValidatorFn("invalid")) + require.Error(t, pair.ValidatorFn(uint64(0))) + case bytes.Equal(types.KeyVoteThreshold, pair.Key): + require.NoError(t, pair.ValidatorFn(sdk.NewDecWithPrec(33, 2))) + require.Error(t, pair.ValidatorFn("invalid")) + require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(32, 2))) + require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(101, 2))) + case bytes.Equal(types.KeyRewardBand, pair.Key) || + bytes.Equal(types.KeySlashFraction, pair.Key) || + bytes.Equal(types.KeyMinValidPerWindow, pair.Key): + require.NoError(t, pair.ValidatorFn(sdk.NewDecWithPrec(7, 2))) + require.Error(t, pair.ValidatorFn("invalid")) + require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(-1, 2))) + require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(101, 2))) + case bytes.Equal(types.KeyWhitelist, pair.Key): + require.NoError(t, pair.ValidatorFn(types.PairList{ + { + Name: "BTC:USDT", + TobinTax: sdk.NewDecWithPrec(10, 2), + }, + })) + require.Error(t, pair.ValidatorFn("invalid")) + require.Error(t, pair.ValidatorFn(types.PairList{ + { + Name: "", + TobinTax: sdk.NewDecWithPrec(10, 2), + }, + })) + require.Error(t, pair.ValidatorFn(types.PairList{ + { + Name: "BTC:USD", + TobinTax: sdk.NewDecWithPrec(101, 2), + }, + })) + require.Error(t, pair.ValidatorFn(types.PairList{ + { + Name: "BTC:BTC", + TobinTax: sdk.NewDecWithPrec(-1, 2), + }, + })) + } + } +} diff --git a/x/oracle/types/query.pb.go b/x/oracle/types/query.pb.go new file mode 100644 index 000000000..2f249e698 --- /dev/null +++ b/x/oracle/types/query.pb.go @@ -0,0 +1,4871 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/v1beta1/query.proto + +package types + +import ( + context "context" + 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" + 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 { + // pair defines the pair to query for. + Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,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_812803c014dfa45a, []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 assets voted by validators + 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_812803c014dfa45a, []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_812803c014dfa45a, []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 pairs. + ExchangeRates ExchangeRateTuples `protobuf:"bytes,1,rep,name=exchange_rates,json=exchangeRates,proto3,castrepeated=ExchangeRateTuples" 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_812803c014dfa45a, []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() ExchangeRateTuples { + if m != nil { + return m.ExchangeRates + } + return nil +} + +// QueryTobinTaxRequest is the request type for the Query/TobinTax RPC method. +type QueryTobinTaxRequest struct { + // pair defines the asset to query for. + Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"` +} + +func (m *QueryTobinTaxRequest) Reset() { *m = QueryTobinTaxRequest{} } +func (m *QueryTobinTaxRequest) String() string { return proto.CompactTextString(m) } +func (*QueryTobinTaxRequest) ProtoMessage() {} +func (*QueryTobinTaxRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_812803c014dfa45a, []int{4} +} +func (m *QueryTobinTaxRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTobinTaxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTobinTaxRequest.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 *QueryTobinTaxRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTobinTaxRequest.Merge(m, src) +} +func (m *QueryTobinTaxRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryTobinTaxRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTobinTaxRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTobinTaxRequest proto.InternalMessageInfo + +// QueryTobinTaxResponse is response type for the +// Query/TobinTax RPC method. +type QueryTobinTaxResponse struct { + // tobin_taxe defines the tobin tax of a pair + TobinTax github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=tobin_tax,json=tobinTax,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"tobin_tax"` +} + +func (m *QueryTobinTaxResponse) Reset() { *m = QueryTobinTaxResponse{} } +func (m *QueryTobinTaxResponse) String() string { return proto.CompactTextString(m) } +func (*QueryTobinTaxResponse) ProtoMessage() {} +func (*QueryTobinTaxResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_812803c014dfa45a, []int{5} +} +func (m *QueryTobinTaxResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTobinTaxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTobinTaxResponse.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 *QueryTobinTaxResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTobinTaxResponse.Merge(m, src) +} +func (m *QueryTobinTaxResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryTobinTaxResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTobinTaxResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTobinTaxResponse proto.InternalMessageInfo + +// QueryTobinTaxesRequest is the request type for the Query/TobinTaxes RPC method. +type QueryTobinTaxesRequest struct { +} + +func (m *QueryTobinTaxesRequest) Reset() { *m = QueryTobinTaxesRequest{} } +func (m *QueryTobinTaxesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryTobinTaxesRequest) ProtoMessage() {} +func (*QueryTobinTaxesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_812803c014dfa45a, []int{6} +} +func (m *QueryTobinTaxesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTobinTaxesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTobinTaxesRequest.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 *QueryTobinTaxesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTobinTaxesRequest.Merge(m, src) +} +func (m *QueryTobinTaxesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryTobinTaxesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTobinTaxesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTobinTaxesRequest proto.InternalMessageInfo + +// QueryTobinTaxesResponse is response type for the +// Query/TobinTaxes RPC method. +type QueryTobinTaxesResponse struct { + // tobin_taxes defines a list of the tobin tax of all whitelisted pairs + TobinTaxes PairList `protobuf:"bytes,1,rep,name=tobin_taxes,json=tobinTaxes,proto3,castrepeated=PairList" json:"tobin_taxes" yaml:"tobin_taxes"` +} + +func (m *QueryTobinTaxesResponse) Reset() { *m = QueryTobinTaxesResponse{} } +func (m *QueryTobinTaxesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryTobinTaxesResponse) ProtoMessage() {} +func (*QueryTobinTaxesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_812803c014dfa45a, []int{7} +} +func (m *QueryTobinTaxesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTobinTaxesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTobinTaxesResponse.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 *QueryTobinTaxesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTobinTaxesResponse.Merge(m, src) +} +func (m *QueryTobinTaxesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryTobinTaxesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTobinTaxesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTobinTaxesResponse proto.InternalMessageInfo + +func (m *QueryTobinTaxesResponse) GetTobinTaxes() PairList { + if m != nil { + return m.TobinTaxes + } + 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_812803c014dfa45a, []int{8} +} +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 pair which oracle prices agreed 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_812803c014dfa45a, []int{9} +} +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_812803c014dfa45a, []int{10} +} +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 pairs 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_812803c014dfa45a, []int{11} +} +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_812803c014dfa45a, []int{12} +} +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_812803c014dfa45a, []int{13} +} +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_812803c014dfa45a, []int{14} +} +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_812803c014dfa45a, []int{15} +} +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_812803c014dfa45a, []int{16} +} +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_812803c014dfa45a, []int{17} +} +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_812803c014dfa45a, []int{18} +} +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_812803c014dfa45a, []int{19} +} +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_812803c014dfa45a, []int{20} +} +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_812803c014dfa45a, []int{21} +} +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_812803c014dfa45a, []int{22} +} +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_812803c014dfa45a, []int{23} +} +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_812803c014dfa45a, []int{24} +} +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_812803c014dfa45a, []int{25} +} +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), "nibiru.oracle.v1beta1.QueryExchangeRateRequest") + proto.RegisterType((*QueryExchangeRateResponse)(nil), "nibiru.oracle.v1beta1.QueryExchangeRateResponse") + proto.RegisterType((*QueryExchangeRatesRequest)(nil), "nibiru.oracle.v1beta1.QueryExchangeRatesRequest") + proto.RegisterType((*QueryExchangeRatesResponse)(nil), "nibiru.oracle.v1beta1.QueryExchangeRatesResponse") + proto.RegisterType((*QueryTobinTaxRequest)(nil), "nibiru.oracle.v1beta1.QueryTobinTaxRequest") + proto.RegisterType((*QueryTobinTaxResponse)(nil), "nibiru.oracle.v1beta1.QueryTobinTaxResponse") + proto.RegisterType((*QueryTobinTaxesRequest)(nil), "nibiru.oracle.v1beta1.QueryTobinTaxesRequest") + proto.RegisterType((*QueryTobinTaxesResponse)(nil), "nibiru.oracle.v1beta1.QueryTobinTaxesResponse") + proto.RegisterType((*QueryActivesRequest)(nil), "nibiru.oracle.v1beta1.QueryActivesRequest") + proto.RegisterType((*QueryActivesResponse)(nil), "nibiru.oracle.v1beta1.QueryActivesResponse") + proto.RegisterType((*QueryVoteTargetsRequest)(nil), "nibiru.oracle.v1beta1.QueryVoteTargetsRequest") + proto.RegisterType((*QueryVoteTargetsResponse)(nil), "nibiru.oracle.v1beta1.QueryVoteTargetsResponse") + proto.RegisterType((*QueryFeederDelegationRequest)(nil), "nibiru.oracle.v1beta1.QueryFeederDelegationRequest") + proto.RegisterType((*QueryFeederDelegationResponse)(nil), "nibiru.oracle.v1beta1.QueryFeederDelegationResponse") + proto.RegisterType((*QueryMissCounterRequest)(nil), "nibiru.oracle.v1beta1.QueryMissCounterRequest") + proto.RegisterType((*QueryMissCounterResponse)(nil), "nibiru.oracle.v1beta1.QueryMissCounterResponse") + proto.RegisterType((*QueryAggregatePrevoteRequest)(nil), "nibiru.oracle.v1beta1.QueryAggregatePrevoteRequest") + proto.RegisterType((*QueryAggregatePrevoteResponse)(nil), "nibiru.oracle.v1beta1.QueryAggregatePrevoteResponse") + proto.RegisterType((*QueryAggregatePrevotesRequest)(nil), "nibiru.oracle.v1beta1.QueryAggregatePrevotesRequest") + proto.RegisterType((*QueryAggregatePrevotesResponse)(nil), "nibiru.oracle.v1beta1.QueryAggregatePrevotesResponse") + proto.RegisterType((*QueryAggregateVoteRequest)(nil), "nibiru.oracle.v1beta1.QueryAggregateVoteRequest") + proto.RegisterType((*QueryAggregateVoteResponse)(nil), "nibiru.oracle.v1beta1.QueryAggregateVoteResponse") + proto.RegisterType((*QueryAggregateVotesRequest)(nil), "nibiru.oracle.v1beta1.QueryAggregateVotesRequest") + proto.RegisterType((*QueryAggregateVotesResponse)(nil), "nibiru.oracle.v1beta1.QueryAggregateVotesResponse") + proto.RegisterType((*QueryParamsRequest)(nil), "nibiru.oracle.v1beta1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "nibiru.oracle.v1beta1.QueryParamsResponse") +} + +func init() { proto.RegisterFile("oracle/v1beta1/query.proto", fileDescriptor_812803c014dfa45a) } + +var fileDescriptor_812803c014dfa45a = []byte{ + // 1225 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x98, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xc7, 0x3d, 0x10, 0xd2, 0xe4, 0x71, 0x1c, 0x92, 0x21, 0x81, 0x74, 0x93, 0xd8, 0x65, 0x45, + 0xa3, 0x34, 0x2f, 0xde, 0xbc, 0x15, 0x48, 0x0b, 0x82, 0xbc, 0x10, 0x09, 0x08, 0x10, 0x4c, 0x94, + 0x03, 0x12, 0xb2, 0xc6, 0xf6, 0xd4, 0x59, 0xd5, 0xf6, 0xba, 0x3b, 0x63, 0x2b, 0x51, 0x54, 0x90, + 0x38, 0xf0, 0x76, 0xaa, 0xc4, 0x15, 0xa4, 0x72, 0xa4, 0x42, 0x42, 0xe2, 0x03, 0x00, 0xc7, 0x4a, + 0x5c, 0x2a, 0x71, 0x41, 0x08, 0xa5, 0x28, 0xe1, 0xc0, 0x99, 0x4f, 0x80, 0x76, 0x76, 0x76, 0xbd, + 0x6b, 0xef, 0x6e, 0xd7, 0xee, 0xc9, 0xce, 0xcc, 0xf3, 0xf2, 0x7b, 0xfe, 0xb3, 0x3b, 0xcf, 0xe3, + 0x80, 0x62, 0x98, 0xa4, 0x58, 0xa1, 0x5a, 0x73, 0xb9, 0x40, 0x39, 0x59, 0xd6, 0x6e, 0x35, 0xa8, + 0x79, 0x9c, 0xad, 0x9b, 0x06, 0x37, 0xf0, 0x78, 0x4d, 0x2f, 0xe8, 0x66, 0x23, 0x6b, 0x9b, 0x64, + 0xa5, 0x89, 0x32, 0x56, 0x36, 0xca, 0x86, 0xb0, 0xd0, 0xac, 0x6f, 0xb6, 0xb1, 0x32, 0x55, 0x36, + 0x8c, 0x72, 0x85, 0x6a, 0xa4, 0xae, 0x6b, 0xa4, 0x56, 0x33, 0x38, 0xe1, 0xba, 0x51, 0x63, 0x72, + 0x77, 0xb2, 0x2d, 0x8d, 0x0c, 0x69, 0x6f, 0xa6, 0x8b, 0x06, 0xab, 0x1a, 0x4c, 0x2b, 0x10, 0xd6, + 0xb2, 0x28, 0x1a, 0x7a, 0xcd, 0xde, 0x57, 0x5f, 0x86, 0x89, 0xf7, 0x2d, 0xac, 0x37, 0x8e, 0x8a, + 0x87, 0xa4, 0x56, 0xa6, 0x39, 0xc2, 0x69, 0x8e, 0xde, 0x6a, 0x50, 0xc6, 0x31, 0x86, 0xbe, 0x3a, + 0xd1, 0xcd, 0x09, 0x74, 0x09, 0xcd, 0x0e, 0xe6, 0xc4, 0xf7, 0x6b, 0x03, 0x5f, 0xdc, 0xcd, 0x24, + 0xfe, 0xbd, 0x9b, 0x49, 0xa8, 0x75, 0xb8, 0x18, 0xe0, 0xc9, 0xea, 0x46, 0x8d, 0x51, 0xfc, 0x01, + 0xa4, 0xa8, 0x5c, 0xcf, 0x9b, 0x84, 0x53, 0x3b, 0xc6, 0x66, 0xf6, 0xfe, 0x69, 0x26, 0xf1, 0xe7, + 0x69, 0x66, 0xa6, 0xac, 0xf3, 0xc3, 0x46, 0x21, 0x5b, 0x34, 0xaa, 0x9a, 0x04, 0xb4, 0x3f, 0x16, + 0x59, 0xe9, 0xa6, 0xc6, 0x8f, 0xeb, 0x94, 0x65, 0xb7, 0x69, 0x31, 0x37, 0x44, 0x3d, 0xc1, 0xd5, + 0xc9, 0x80, 0x8c, 0x4c, 0xc2, 0xaa, 0x5f, 0x22, 0x50, 0x82, 0x76, 0x25, 0xd0, 0x4d, 0x18, 0xf6, + 0x01, 0xb1, 0x09, 0x74, 0xe9, 0xc9, 0xd9, 0xe4, 0xca, 0x6c, 0x36, 0xf0, 0x20, 0xb2, 0xde, 0x28, + 0xfb, 0x8d, 0x7a, 0x85, 0x6e, 0x2a, 0x16, 0xfb, 0xbd, 0x87, 0x19, 0xdc, 0xb1, 0xc5, 0x72, 0x29, + 0x2f, 0x27, 0x53, 0xd7, 0x60, 0x4c, 0xa0, 0xec, 0x1b, 0x05, 0xbd, 0xb6, 0x4f, 0x8e, 0xe2, 0x09, + 0x5a, 0x82, 0xf1, 0x36, 0x2f, 0xc9, 0xfe, 0x36, 0x0c, 0x72, 0x6b, 0x2d, 0xcf, 0xc9, 0x51, 0x8f, + 0x42, 0x0e, 0x70, 0x19, 0x54, 0x9d, 0x80, 0x67, 0x7d, 0x59, 0x5a, 0x0a, 0x7e, 0x02, 0xcf, 0x75, + 0xec, 0x48, 0x82, 0x12, 0x24, 0x5d, 0x02, 0x57, 0xba, 0xc9, 0x10, 0xe9, 0xf6, 0x88, 0x6e, 0x6e, + 0xce, 0x58, 0x80, 0xff, 0x9d, 0x66, 0xf0, 0x31, 0xa9, 0x56, 0xae, 0xa9, 0x1e, 0x6f, 0xf5, 0xde, + 0xc3, 0xcc, 0x80, 0x65, 0xb3, 0xab, 0x33, 0x9e, 0x03, 0xee, 0x66, 0x53, 0xc7, 0xe1, 0x19, 0x01, + 0xb0, 0x51, 0xe4, 0x7a, 0xb3, 0xc5, 0xb5, 0x24, 0xd5, 0x74, 0x97, 0x25, 0xd4, 0x04, 0x5c, 0x20, + 0xf6, 0x92, 0x00, 0x1a, 0xcc, 0x39, 0x7f, 0xaa, 0x17, 0x65, 0x25, 0x07, 0x06, 0xa7, 0xfb, 0xc4, + 0x2c, 0x53, 0xee, 0x06, 0x7b, 0x55, 0x3e, 0xef, 0xbe, 0x2d, 0x19, 0xf0, 0x79, 0x18, 0x6a, 0x1a, + 0x9c, 0xe6, 0xb9, 0xbd, 0x2e, 0xa3, 0x26, 0x9b, 0x2d, 0x53, 0xf5, 0x3d, 0x98, 0x12, 0xee, 0x3b, + 0x94, 0x96, 0xa8, 0xb9, 0x4d, 0x2b, 0xb4, 0x2c, 0xde, 0x45, 0xe7, 0x84, 0x2f, 0xc3, 0x70, 0x93, + 0x54, 0xf4, 0x12, 0xe1, 0x86, 0x99, 0x27, 0xa5, 0x92, 0x73, 0xd6, 0x29, 0x77, 0x75, 0xa3, 0x54, + 0xf2, 0x1e, 0xfa, 0xeb, 0x30, 0x1d, 0x12, 0x50, 0x42, 0x65, 0x20, 0x79, 0x43, 0xec, 0x79, 0xc3, + 0x81, 0xbd, 0x64, 0xc5, 0x52, 0xdf, 0x92, 0xc5, 0xbe, 0xa3, 0x33, 0xb6, 0x65, 0x34, 0x6a, 0x9c, + 0x9a, 0x3d, 0xd3, 0x38, 0xea, 0xf8, 0x62, 0xb5, 0xd4, 0xa9, 0xea, 0x8c, 0xe5, 0x8b, 0xf6, 0xba, + 0x08, 0xd5, 0x97, 0x4b, 0x56, 0x5b, 0xa6, 0xae, 0x3a, 0x1b, 0xe5, 0xb2, 0x69, 0xd5, 0x41, 0xf7, + 0x4c, 0x6a, 0xa9, 0xd7, 0x33, 0xcf, 0xe7, 0x48, 0xca, 0xd3, 0x19, 0x51, 0x52, 0xdd, 0x80, 0x51, + 0xe2, 0xec, 0xe5, 0xeb, 0xf6, 0xa6, 0x88, 0x9a, 0x5c, 0x59, 0x0d, 0x79, 0x3e, 0xdd, 0x58, 0xde, + 0x17, 0x59, 0xc6, 0xdd, 0xec, 0xb3, 0x9e, 0xdb, 0xdc, 0x08, 0x69, 0xcb, 0xa7, 0x66, 0x42, 0x40, + 0xdc, 0x07, 0xeb, 0x2b, 0x04, 0xe9, 0x30, 0x0b, 0xc9, 0x7a, 0x08, 0xb8, 0x83, 0xd5, 0x79, 0x99, + 0x1e, 0x03, 0x76, 0xb4, 0x1d, 0x96, 0xa9, 0xbb, 0xf2, 0xa6, 0x74, 0xbd, 0x0f, 0x1e, 0xe7, 0x14, + 0x4e, 0xe4, 0xcd, 0xda, 0x16, 0x4d, 0x56, 0xf5, 0x11, 0x0c, 0xb7, 0xaa, 0xf2, 0xc8, 0xbf, 0xd4, + 0x4d, 0x45, 0x07, 0xad, 0x72, 0x52, 0xc4, 0x9b, 0x46, 0x9d, 0x0a, 0x4a, 0xee, 0xaa, 0xfe, 0x31, + 0x4c, 0x06, 0xee, 0x4a, 0xb6, 0x3c, 0x3c, 0xed, 0x67, 0x73, 0xe4, 0xee, 0x15, 0x6e, 0xd8, 0x07, + 0xc7, 0xd4, 0x31, 0xc0, 0x22, 0xff, 0x1e, 0x31, 0x49, 0xd5, 0xa5, 0xca, 0xc9, 0x8b, 0xcc, 0x59, + 0x95, 0x34, 0xd7, 0xa1, 0xbf, 0x2e, 0x56, 0xa4, 0x42, 0xd3, 0xa1, 0x17, 0xa8, 0x65, 0x24, 0x33, + 0x4a, 0x97, 0x95, 0xbf, 0x46, 0xe1, 0x29, 0x11, 0x14, 0xff, 0x80, 0x60, 0xc8, 0x8b, 0x87, 0xb5, + 0x90, 0x38, 0x61, 0x8d, 0x5d, 0x59, 0x8a, 0xef, 0x60, 0xa3, 0xab, 0xeb, 0x9f, 0xfe, 0xfe, 0xcf, + 0xd7, 0x4f, 0xac, 0xe2, 0x65, 0xcd, 0xf6, 0xd4, 0xda, 0x66, 0x0e, 0xab, 0x95, 0x31, 0xed, 0xc4, + 0xfa, 0xb8, 0xad, 0xf9, 0x1a, 0x2d, 0xfe, 0x1e, 0x41, 0xca, 0xd7, 0x93, 0x71, 0xec, 0xf4, 0x8e, + 0xa0, 0xca, 0x72, 0x17, 0x1e, 0x92, 0x78, 0x55, 0x10, 0x2f, 0xe2, 0xf9, 0x48, 0x62, 0xff, 0x4c, + 0x80, 0xbf, 0x41, 0x30, 0xe0, 0xb4, 0x3f, 0x3c, 0x1f, 0x95, 0xb4, 0xad, 0xb5, 0x2b, 0x0b, 0xf1, + 0x8c, 0x25, 0xdc, 0x55, 0x01, 0xa7, 0xe1, 0xc5, 0x38, 0x72, 0xba, 0xbd, 0x13, 0x7f, 0x8b, 0x00, + 0x5a, 0xdd, 0x19, 0x2f, 0xc6, 0xc9, 0xd9, 0x12, 0x31, 0x1b, 0xd7, 0x5c, 0x42, 0x2e, 0x09, 0xc8, + 0x39, 0x3c, 0x1b, 0x09, 0xe9, 0xe9, 0xec, 0xf8, 0x0e, 0x82, 0x0b, 0xb2, 0x4b, 0xe3, 0xb9, 0xa8, + 0x6c, 0xfe, 0x0e, 0xaf, 0xcc, 0xc7, 0xb2, 0x95, 0x58, 0x0b, 0x02, 0x6b, 0x06, 0xbf, 0x10, 0x89, + 0x25, 0x47, 0x01, 0xfc, 0x1d, 0x82, 0xa4, 0xa7, 0xd7, 0xe3, 0x48, 0x11, 0x3a, 0xe7, 0x05, 0x45, + 0x8b, 0x6d, 0x2f, 0xf1, 0x96, 0x05, 0xde, 0x3c, 0xbe, 0x12, 0x89, 0xe7, 0x9d, 0x33, 0xf0, 0xaf, + 0x08, 0x46, 0xda, 0xfb, 0x3f, 0x5e, 0x8d, 0x4a, 0x1c, 0x32, 0x7e, 0x28, 0x6b, 0xdd, 0x39, 0x49, + 0xe4, 0x0d, 0x81, 0x7c, 0x1d, 0xaf, 0x87, 0x20, 0xbb, 0x7d, 0x81, 0x69, 0x27, 0xfe, 0xce, 0x71, + 0x5b, 0xb3, 0x07, 0x11, 0xfc, 0x23, 0x82, 0xa4, 0x67, 0x68, 0x88, 0x96, 0xb9, 0x73, 0x52, 0x89, + 0x96, 0x39, 0x60, 0x1a, 0x51, 0x5f, 0x13, 0xcc, 0xeb, 0xf8, 0xa5, 0x1e, 0x98, 0xad, 0x91, 0x05, + 0xff, 0x86, 0x60, 0xa4, 0xbd, 0x55, 0x47, 0x8b, 0x1e, 0x32, 0xd5, 0x44, 0x8b, 0x1e, 0x36, 0xb8, + 0xa8, 0xbb, 0xa2, 0x80, 0x1d, 0xbc, 0xdd, 0x43, 0x01, 0x1d, 0x53, 0x04, 0xfe, 0x19, 0xc1, 0x68, + 0xc7, 0xe0, 0x81, 0xbb, 0x22, 0x73, 0x1f, 0xf9, 0xab, 0x5d, 0x7a, 0xc9, 0x82, 0x5e, 0x11, 0x05, + 0xbd, 0x88, 0xd7, 0x1e, 0x5d, 0x50, 0xe7, 0x14, 0x84, 0x7f, 0x41, 0x90, 0xf2, 0x35, 0xf1, 0xe8, + 0x2e, 0x11, 0x34, 0xd8, 0x44, 0x77, 0x89, 0xc0, 0xe1, 0x45, 0x7d, 0x53, 0x40, 0x6f, 0xe1, 0x8d, + 0x70, 0xe8, 0x92, 0xfe, 0xc8, 0x53, 0x10, 0x47, 0xf0, 0x13, 0x82, 0x61, 0xff, 0x18, 0x82, 0xe3, + 0x03, 0xb9, 0xe2, 0xaf, 0x74, 0xe3, 0x12, 0xb3, 0x39, 0x07, 0x2a, 0x6f, 0xcb, 0xfe, 0x19, 0x82, + 0x7e, 0x7b, 0xdc, 0xc0, 0x57, 0xa2, 0x32, 0xfb, 0xe6, 0x1b, 0x65, 0x2e, 0x8e, 0xa9, 0x84, 0xbb, + 0x2c, 0xe0, 0x32, 0x78, 0x3a, 0xf4, 0x3e, 0x14, 0xc3, 0xce, 0xce, 0xfd, 0xb3, 0x34, 0x7a, 0x70, + 0x96, 0x46, 0x7f, 0x9f, 0xa5, 0xd1, 0x9d, 0xf3, 0x74, 0xe2, 0xc1, 0x79, 0x3a, 0xf1, 0xc7, 0x79, + 0x3a, 0xf1, 0xe1, 0x82, 0xe7, 0x27, 0xee, 0xbb, 0x22, 0xc4, 0xd6, 0x21, 0xd1, 0x6b, 0x4e, 0xb8, + 0x23, 0x27, 0xa0, 0xf8, 0xb1, 0x5b, 0xe8, 0x17, 0xff, 0xd6, 0x58, 0xfd, 0x3f, 0x00, 0x00, 0xff, + 0xff, 0xb7, 0x31, 0x4f, 0x5b, 0x7c, 0x11, 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 pair + ExchangeRate(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryExchangeRateResponse, error) + // ExchangeRates returns exchange rates of all pairs + ExchangeRates(ctx context.Context, in *QueryExchangeRatesRequest, opts ...grpc.CallOption) (*QueryExchangeRatesResponse, error) + // TobinTax returns tobin tax of a pair + TobinTax(ctx context.Context, in *QueryTobinTaxRequest, opts ...grpc.CallOption) (*QueryTobinTaxResponse, error) + // TobinTaxes returns tobin taxes of all pairs + TobinTaxes(ctx context.Context, in *QueryTobinTaxesRequest, opts ...grpc.CallOption) (*QueryTobinTaxesResponse, error) + // Actives returns all active pairs + Actives(ctx context.Context, in *QueryActivesRequest, opts ...grpc.CallOption) (*QueryActivesResponse, error) + // VoteTargets returns all vote target for pairs + 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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.Query/ExchangeRates", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) TobinTax(ctx context.Context, in *QueryTobinTaxRequest, opts ...grpc.CallOption) (*QueryTobinTaxResponse, error) { + out := new(QueryTobinTaxResponse) + err := c.cc.Invoke(ctx, "/nibiru.oracle.v1beta1.Query/TobinTax", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) TobinTaxes(ctx context.Context, in *QueryTobinTaxesRequest, opts ...grpc.CallOption) (*QueryTobinTaxesResponse, error) { + out := new(QueryTobinTaxesResponse) + err := c.cc.Invoke(ctx, "/nibiru.oracle.v1beta1.Query/TobinTaxes", 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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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 pair + ExchangeRate(context.Context, *QueryExchangeRateRequest) (*QueryExchangeRateResponse, error) + // ExchangeRates returns exchange rates of all pairs + ExchangeRates(context.Context, *QueryExchangeRatesRequest) (*QueryExchangeRatesResponse, error) + // TobinTax returns tobin tax of a pair + TobinTax(context.Context, *QueryTobinTaxRequest) (*QueryTobinTaxResponse, error) + // TobinTaxes returns tobin taxes of all pairs + TobinTaxes(context.Context, *QueryTobinTaxesRequest) (*QueryTobinTaxesResponse, error) + // Actives returns all active pairs + Actives(context.Context, *QueryActivesRequest) (*QueryActivesResponse, error) + // VoteTargets returns all vote target for pairs + 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) TobinTax(ctx context.Context, req *QueryTobinTaxRequest) (*QueryTobinTaxResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TobinTax not implemented") +} +func (*UnimplementedQueryServer) TobinTaxes(ctx context.Context, req *QueryTobinTaxesRequest) (*QueryTobinTaxesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TobinTaxes 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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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_TobinTax_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryTobinTaxRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).TobinTax(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/nibiru.oracle.v1beta1.Query/TobinTax", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).TobinTax(ctx, req.(*QueryTobinTaxRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_TobinTaxes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryTobinTaxesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).TobinTaxes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/nibiru.oracle.v1beta1.Query/TobinTaxes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).TobinTaxes(ctx, req.(*QueryTobinTaxesRequest)) + } + 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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "nibiru.oracle.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ExchangeRate", + Handler: _Query_ExchangeRate_Handler, + }, + { + MethodName: "ExchangeRates", + Handler: _Query_ExchangeRates_Handler, + }, + { + MethodName: "TobinTax", + Handler: _Query_TobinTax_Handler, + }, + { + MethodName: "TobinTaxes", + Handler: _Query_TobinTaxes_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/v1beta1/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.Pair) > 0 { + i -= len(m.Pair) + copy(dAtA[i:], m.Pair) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Pair))) + 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 *QueryTobinTaxRequest) 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 *QueryTobinTaxRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTobinTaxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Pair) > 0 { + i -= len(m.Pair) + copy(dAtA[i:], m.Pair) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Pair))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryTobinTaxResponse) 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 *QueryTobinTaxResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTobinTaxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.TobinTax.Size() + i -= size + if _, err := m.TobinTax.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 *QueryTobinTaxesRequest) 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 *QueryTobinTaxesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTobinTaxesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryTobinTaxesResponse) 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 *QueryTobinTaxesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTobinTaxesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TobinTaxes) > 0 { + for iNdEx := len(m.TobinTaxes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TobinTaxes[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.Pair) + 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 *QueryTobinTaxRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Pair) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryTobinTaxResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.TobinTax.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryTobinTaxesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryTobinTaxesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.TobinTaxes) > 0 { + for _, e := range m.TobinTaxes { + 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 Pair", 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.Pair = 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, ExchangeRateTuple{}) + 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 *QueryTobinTaxRequest) 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: QueryTobinTaxRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTobinTaxRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pair", 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.Pair = 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 *QueryTobinTaxResponse) 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: QueryTobinTaxResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTobinTaxResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TobinTax", 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.TobinTax.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 *QueryTobinTaxesRequest) 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: QueryTobinTaxesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTobinTaxesRequest: 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 *QueryTobinTaxesResponse) 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: QueryTobinTaxesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTobinTaxesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TobinTaxes", 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.TobinTaxes = append(m.TobinTaxes, Pair{}) + if err := m.TobinTaxes[len(m.TobinTaxes)-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 000000000..8d6dc99b9 --- /dev/null +++ b/x/oracle/types/query.pb.gw.go @@ -0,0 +1,1108 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: oracle/v1beta1/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/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 + +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["pair"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pair") + } + + protoReq.Pair, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pair", 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["pair"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pair") + } + + protoReq.Pair, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pair", 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_TobinTax_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTobinTaxRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["pair"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pair") + } + + protoReq.Pair, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pair", err) + } + + msg, err := client.TobinTax(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_TobinTax_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTobinTaxRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["pair"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pair") + } + + protoReq.Pair, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pair", err) + } + + msg, err := server.TobinTax(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_TobinTaxes_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTobinTaxesRequest + var metadata runtime.ServerMetadata + + msg, err := client.TobinTaxes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_TobinTaxes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTobinTaxesRequest + var metadata runtime.ServerMetadata + + msg, err := server.TobinTaxes(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 (such as grpc.SendHeader, etc) 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() + 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) + 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.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) + 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_TobinTax_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_TobinTax_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_TobinTax_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_TobinTaxes_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_TobinTaxes_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_TobinTaxes_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.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) + 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.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) + 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.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) + 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.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) + 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.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) + 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.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) + 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.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) + 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.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) + 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.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) + 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_TobinTax_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_TobinTax_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_TobinTax_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_TobinTaxes_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_TobinTaxes_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_TobinTaxes_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{"nibiru", "oracle", "v1beta1", "pairs", "pair", "exchange_rate"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_ExchangeRates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "pairs", "exchange_rates"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_TobinTax_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"nibiru", "oracle", "v1beta1", "pairs", "pair", "tobin_tax"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_TobinTaxes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "pairs", "tobin_taxes"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Actives_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "pairs", "actives"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_VoteTargets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "pairs", "vote_targets"}, "", runtime.AssumeColonVerbOpt(false))) + + 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{"nibiru", "oracle", "v1beta1", "validators", "validator_addr", "feeder"}, "", runtime.AssumeColonVerbOpt(false))) + + 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{"nibiru", "oracle", "v1beta1", "validators", "validator_addr", "miss"}, "", runtime.AssumeColonVerbOpt(false))) + + 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{"nibiru", "oracle", "v1beta1", "validators", "validator_addr", "aggregate_prevote"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AggregatePrevotes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "validators", "aggregate_prevotes"}, "", runtime.AssumeColonVerbOpt(false))) + + 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{"nibiru", "oracle", "v1beta1", "valdiators", "validator_addr", "aggregate_vote"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AggregateVotes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "validators", "aggregate_votes"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"nibiru", "oracle", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_ExchangeRate_0 = runtime.ForwardResponseMessage + + forward_Query_ExchangeRates_0 = runtime.ForwardResponseMessage + + forward_Query_TobinTax_0 = runtime.ForwardResponseMessage + + forward_Query_TobinTaxes_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 100644 index 000000000..b5692bf13 --- /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 000000000..492110cd5 --- /dev/null +++ b/x/oracle/types/tx.pb.go @@ -0,0 +1,1455 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: oracle/v1beta1/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_8f0903e1642d8c8a, []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_8f0903e1642d8c8a, []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_8f0903e1642d8c8a, []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_8f0903e1642d8c8a, []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_8f0903e1642d8c8a, []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_8f0903e1642d8c8a, []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), "nibiru.oracle.v1beta1.MsgAggregateExchangeRatePrevote") + proto.RegisterType((*MsgAggregateExchangeRatePrevoteResponse)(nil), "nibiru.oracle.v1beta1.MsgAggregateExchangeRatePrevoteResponse") + proto.RegisterType((*MsgAggregateExchangeRateVote)(nil), "nibiru.oracle.v1beta1.MsgAggregateExchangeRateVote") + proto.RegisterType((*MsgAggregateExchangeRateVoteResponse)(nil), "nibiru.oracle.v1beta1.MsgAggregateExchangeRateVoteResponse") + proto.RegisterType((*MsgDelegateFeedConsent)(nil), "nibiru.oracle.v1beta1.MsgDelegateFeedConsent") + proto.RegisterType((*MsgDelegateFeedConsentResponse)(nil), "nibiru.oracle.v1beta1.MsgDelegateFeedConsentResponse") +} + +func init() { proto.RegisterFile("oracle/v1beta1/tx.proto", fileDescriptor_8f0903e1642d8c8a) } + +var fileDescriptor_8f0903e1642d8c8a = []byte{ + // 500 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xbf, 0x6f, 0xd3, 0x40, + 0x14, 0xc7, 0x7d, 0xa4, 0xaa, 0xda, 0x43, 0xa5, 0xe0, 0xb6, 0x90, 0x46, 0x95, 0x5d, 0x1d, 0x08, + 0xa8, 0x04, 0xb6, 0xda, 0x0a, 0x86, 0x22, 0x21, 0x68, 0xa1, 0x5b, 0x10, 0xf2, 0xc0, 0xc0, 0x82, + 0x2e, 0xc9, 0xe3, 0x6c, 0xc9, 0xf5, 0x45, 0x77, 0xd7, 0x28, 0x15, 0x2b, 0x03, 0x0b, 0x12, 0x13, + 0x73, 0x77, 0x06, 0xfe, 0x0d, 0xc6, 0x8e, 0x4c, 0x16, 0x4a, 0x16, 0x26, 0x06, 0xff, 0x05, 0xc8, + 0x77, 0xb6, 0x09, 0x6a, 0xd2, 0x2a, 0xd9, 0xac, 0xf7, 0xfd, 0xbc, 0x5f, 0x5f, 0x3f, 0x1d, 0xbe, + 0xc5, 0x05, 0x6d, 0xc7, 0xe0, 0xf7, 0xb6, 0x5b, 0xa0, 0xe8, 0xb6, 0xaf, 0xfa, 0x5e, 0x57, 0x70, + 0xc5, 0xed, 0xb5, 0x24, 0x6a, 0x45, 0xe2, 0xd8, 0x33, 0xba, 0x57, 0xe8, 0x8d, 0x55, 0xc6, 0x19, + 0xd7, 0x84, 0x9f, 0x7f, 0x19, 0x98, 0x7c, 0x47, 0xd8, 0x6d, 0x4a, 0xf6, 0x9c, 0x31, 0x01, 0x8c, + 0x2a, 0x78, 0xd9, 0x6f, 0x87, 0x34, 0x61, 0x10, 0x50, 0x05, 0xaf, 0x05, 0xf4, 0xb8, 0x02, 0xfb, + 0x36, 0x9e, 0x0b, 0xa9, 0x0c, 0xeb, 0x68, 0x13, 0xdd, 0x5f, 0xdc, 0x5f, 0xce, 0x52, 0xf7, 0xea, + 0x09, 0x3d, 0x8a, 0xf7, 0x48, 0x1e, 0x25, 0x81, 0x16, 0xed, 0x2d, 0x3c, 0xff, 0x1e, 0xa0, 0x03, + 0xa2, 0x7e, 0x45, 0x63, 0x37, 0xb2, 0xd4, 0x5d, 0x32, 0x98, 0x89, 0x93, 0xa0, 0x00, 0xec, 0x1d, + 0xbc, 0xd8, 0xa3, 0x71, 0xd4, 0xa1, 0x8a, 0x8b, 0x7a, 0x4d, 0xd3, 0xab, 0x59, 0xea, 0x5e, 0x37, + 0x74, 0x25, 0x91, 0xe0, 0x1f, 0xb6, 0xb7, 0xf0, 0xe9, 0xd4, 0xb5, 0x7e, 0x9f, 0xba, 0x16, 0xd9, + 0xc2, 0xf7, 0x2e, 0x19, 0x38, 0x00, 0xd9, 0xe5, 0x89, 0x04, 0xf2, 0x07, 0xe1, 0x8d, 0x49, 0xec, + 0x9b, 0x62, 0x33, 0x49, 0x63, 0x75, 0x7e, 0xb3, 0x3c, 0x4a, 0x02, 0x2d, 0xda, 0xcf, 0xf0, 0x35, + 0x28, 0x12, 0xdf, 0x09, 0xaa, 0x40, 0x16, 0x1b, 0xae, 0x67, 0xa9, 0xbb, 0x66, 0xf0, 0xff, 0x75, + 0x12, 0x2c, 0xc1, 0x48, 0x27, 0x39, 0xe2, 0x4d, 0x6d, 0x2a, 0x6f, 0xe6, 0xa6, 0xf5, 0xe6, 0x2e, + 0xbe, 0x73, 0xd1, 0xbe, 0x95, 0x31, 0x1f, 0x11, 0xbe, 0xd9, 0x94, 0xec, 0x05, 0xc4, 0x9a, 0x3b, + 0x04, 0xe8, 0x1c, 0xe4, 0x42, 0xa2, 0x6c, 0x1f, 0x2f, 0xf0, 0x2e, 0x08, 0xdd, 0xdf, 0xd8, 0xb2, + 0x92, 0xa5, 0xee, 0xb2, 0xe9, 0x5f, 0x2a, 0x24, 0xa8, 0xa0, 0x3c, 0xa1, 0x53, 0xd4, 0x29, 0x8c, + 0x19, 0x49, 0x28, 0x15, 0x12, 0x54, 0xd0, 0xc8, 0xb8, 0x9b, 0xd8, 0x19, 0x3f, 0x45, 0x39, 0xe8, + 0xce, 0xb7, 0x1a, 0xae, 0x35, 0x25, 0xb3, 0xbf, 0x22, 0xbc, 0x71, 0xe1, 0x8d, 0x3e, 0xf6, 0xc6, + 0x5e, 0xbd, 0x77, 0xc9, 0xa9, 0x34, 0x9e, 0xce, 0x96, 0x57, 0x0e, 0x68, 0x7f, 0x46, 0x78, 0x7d, + 0xf2, 0x7d, 0xed, 0x4e, 0x59, 0x3d, 0x4f, 0x6a, 0x3c, 0x99, 0x21, 0xa9, 0x9a, 0xe7, 0x03, 0x5e, + 0x19, 0xf7, 0x57, 0x1f, 0x4e, 0xae, 0x39, 0x06, 0x6f, 0x3c, 0x9a, 0x0a, 0x2f, 0x9b, 0xef, 0x1f, + 0xfe, 0x18, 0x38, 0xe8, 0x6c, 0xe0, 0xa0, 0x5f, 0x03, 0x07, 0x7d, 0x19, 0x3a, 0xd6, 0xd9, 0xd0, + 0xb1, 0x7e, 0x0e, 0x1d, 0xeb, 0xed, 0x03, 0x16, 0xa9, 0xf0, 0xb8, 0xe5, 0xb5, 0xf9, 0x91, 0xff, + 0x4a, 0x97, 0x3e, 0x08, 0x69, 0x94, 0xf8, 0xa6, 0x8d, 0xdf, 0xf7, 0x8b, 0xc7, 0x4c, 0x9d, 0x74, + 0x41, 0xb6, 0xe6, 0xf5, 0xdb, 0xb4, 0xfb, 0x37, 0x00, 0x00, 0xff, 0xff, 0x56, 0x02, 0x1b, 0x6d, + 0xe3, 0x04, 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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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, "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "/nibiru.oracle.v1beta1.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: "nibiru.oracle.v1beta1.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/v1beta1/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 100644 index 000000000..4dcf03a61 --- /dev/null +++ b/x/oracle/types/vote.go @@ -0,0 +1,172 @@ +package types + +import ( + "fmt" + "strings" + + "github.com/NibiruChain/nibiru/x/common" + + "gopkg.in/yaml.v2" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ExchangeRateTuplesSeparator = "|" + ExchangeRateTupleStringPrefix = '(' + ExchangeRateTupleStringSuffix = ')' + ExchangeRateTuplePairRateSeparator = "," +) + +// 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(pair string, exchangeRate sdk.Dec) ExchangeRateTuple { + return ExchangeRateTuple{ + pair, + exchangeRate, + } +} + +// String implement stringify +func (m ExchangeRateTuple) String() string { + out, _ := yaml.Marshal(m) + return string(out) +} + +// ToString converts the ExchangeRateTuple to the vote string. +func (m ExchangeRateTuple) ToString() (string, error) { + _, err := common.NewAssetPair(m.Pair) + if err != nil { + return "", err + } + + return fmt.Sprintf( + "%c%s%s%s%c", + ExchangeRateTupleStringPrefix, + m.Pair, + ExchangeRateTuplePairRateSeparator, + m.ExchangeRate.String(), + ExchangeRateTupleStringSuffix, + ), nil +} + +// NewExchangeRateTupleFromString populates ExchangeRateTuple from a string, fails if the string is of invalid format. +func NewExchangeRateTupleFromString(s string) (ExchangeRateTuple, error) { + // strip parentheses + if len(s) <= 2 { + return ExchangeRateTuple{}, fmt.Errorf("invalid string length") + } + + if s[0] != ExchangeRateTupleStringPrefix || s[len(s)-1] != ExchangeRateTupleStringSuffix { + return ExchangeRateTuple{}, fmt.Errorf("invalid ExchangeRateTuple delimiters, start is expected with '(', end with ')', got: %s", s) + } + + stripParentheses := s[1 : len(s)-1] + split := strings.Split(stripParentheses, ExchangeRateTuplePairRateSeparator) + if len(split) != 2 { + return ExchangeRateTuple{}, fmt.Errorf("invalid ExchangeRateTuple format") + } + + _, err := common.NewAssetPair(split[0]) + if err != nil { + return ExchangeRateTuple{}, fmt.Errorf("invalid pair definition %s: %w", split[0], err) + } + + dec, err := sdk.NewDecFromStr(split[1]) + if err != nil { + return ExchangeRateTuple{}, fmt.Errorf("invalid decimal %s: %w", split[1], err) + } + + return ExchangeRateTuple{ + Pair: split[0], + ExchangeRate: dec, + }, nil +} + +// ExchangeRateTuples - array of ExchangeRateTuple +type ExchangeRateTuples []ExchangeRateTuple + +// String implements fmt.Stringer interface +func (tuples ExchangeRateTuples) String() string { + out, _ := yaml.Marshal(tuples) + return string(out) +} + +func NewExchangeRateTuplesFromString(s string) (ExchangeRateTuples, error) { + stringTuples := strings.Split(s, ExchangeRateTuplesSeparator) + + tuples := make(ExchangeRateTuples, len(stringTuples)) + + duplicates := make(map[string]struct{}, len(stringTuples)) + + for i, stringTuple := range stringTuples { + exchangeRate, err := NewExchangeRateTupleFromString(stringTuple) + if err != nil { + return []ExchangeRateTuple{}, fmt.Errorf("invalid ExchangeRateTuple at index %d: %w", i, err) + } + + // check duplicates + if _, ok := duplicates[exchangeRate.Pair]; ok { + return []ExchangeRateTuple{}, fmt.Errorf("found duplicate at index %d: %s", i, exchangeRate.Pair) + } else { + duplicates[exchangeRate.Pair] = struct{}{} + } + + // insert exchange rate into the tuple + tuples[i] = exchangeRate + } + + return tuples, nil +} + +func (tuples ExchangeRateTuples) ToString() (string, error) { + tuplesStringSlice := make([]string, len(tuples)) + for i, r := range tuples { + rStr, err := r.ToString() + if err != nil { + return "", fmt.Errorf("invalid ExchangeRateTuple at index %d: %w", i, err) + } + + tuplesStringSlice[i] = rStr + } + + return strings.Join(tuplesStringSlice, "|"), nil +} + +// ParseExchangeRateTuples ExchangeRateTuple parser +func ParseExchangeRateTuples(tuplesStr string) (ExchangeRateTuples, error) { + tuples, err := NewExchangeRateTuplesFromString(tuplesStr) + if err != nil { + return nil, err + } + + return tuples, nil +} diff --git a/x/oracle/types/vote_test.go b/x/oracle/types/vote_test.go new file mode 100644 index 000000000..d6bb130c5 --- /dev/null +++ b/x/oracle/types/vote_test.go @@ -0,0 +1,86 @@ +package types_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/x/oracle/types" +) + +func TestParseExchangeRateTuples(t *testing.T) { + t.Run("inverse", func(t *testing.T) { + tuples := types.ExchangeRateTuples{ + { + Pair: "BTC:USD", + ExchangeRate: sdk.MustNewDecFromStr("40000.00"), + }, + + { + Pair: "ETH:USD", + ExchangeRate: sdk.MustNewDecFromStr("4000.00"), + }, + } + + tuplesStr, err := tuples.ToString() + require.NoError(t, err) + + parsedTuples, err := types.NewExchangeRateTuplesFromString(tuplesStr) + require.NoError(t, err) + + require.Equal(t, tuples, parsedTuples) + }) + + t.Run("check duplicates", func(t *testing.T) { + tuples := types.ExchangeRateTuples{ + { + Pair: "BTC:USD", + ExchangeRate: sdk.MustNewDecFromStr("40000.00"), + }, + + { + Pair: "BTC:USD", + ExchangeRate: sdk.MustNewDecFromStr("4000.00"), + }, + } + + tuplesStr, err := tuples.ToString() + require.NoError(t, err) + + _, err = types.NewExchangeRateTuplesFromString(tuplesStr) + require.ErrorContains(t, err, "found duplicate") + }) +} + +func TestExchangeRateTuple(t *testing.T) { + t.Run("inverse", func(t *testing.T) { + exchangeRate := types.ExchangeRateTuple{ + Pair: "BTC:USD", + ExchangeRate: sdk.MustNewDecFromStr("40000.00"), + } + exchangeRateStr, err := exchangeRate.ToString() + require.NoError(t, err) + + parsedExchangeRate, err := types.NewExchangeRateTupleFromString(exchangeRateStr) + require.NoError(t, err) + + require.Equal(t, exchangeRate, parsedExchangeRate) + }) + + t.Run("invalid size", func(t *testing.T) { + _, err := types.NewExchangeRateTupleFromString("00") + require.ErrorContains(t, err, "invalid string length") + }) + + t.Run("invalid delimiters", func(t *testing.T) { + _, err := types.NewExchangeRateTupleFromString("|1000.0,nibi:usd|") + require.ErrorContains(t, err, "invalid ExchangeRateTuple delimiters") + }) + + t.Run("invalid format", func(t *testing.T) { + _, err := types.NewExchangeRateTupleFromString("(1000.0,nibi:usd,1000.0)") + require.ErrorContains(t, err, "invalid ExchangeRateTuple format") + }) +} diff --git a/x/perp/keeper/calc.go b/x/perp/keeper/calc.go index cc8827756..d4aa48869 100644 --- a/x/perp/keeper/calc.go +++ b/x/perp/keeper/calc.go @@ -69,7 +69,9 @@ func (k Keeper) CalcRemainMarginWithFundingPayment( return remaining, err } -/* calcFreeCollateral computes the amount of collateral backing the position that can +/* + calcFreeCollateral computes the amount of collateral backing the position that can + be removed without giving the position bad debt. Factors in the unrealized PnL when calculating free collateral. diff --git a/x/perp/keeper/clearing_house.go b/x/perp/keeper/clearing_house.go index 85e9e4edb..a2f8c06d8 100644 --- a/x/perp/keeper/clearing_house.go +++ b/x/perp/keeper/clearing_house.go @@ -94,7 +94,6 @@ func (k Keeper) OpenPosition( // - Checks that the VPool exists. // - Checks that quote asset is not zero. // - Checks that leverage is not zero. -// func (k Keeper) checkOpenPositionRequirements(ctx sdk.Context, pair common.AssetPair, quoteAssetAmount sdk.Int, leverage sdk.Dec) error { if err := k.requireVpool(ctx, pair); err != nil { return err diff --git a/x/perp/keeper/liquidate.go b/x/perp/keeper/liquidate.go index 6aa331df5..9a0938931 100644 --- a/x/perp/keeper/liquidate.go +++ b/x/perp/keeper/liquidate.go @@ -8,7 +8,9 @@ import ( vpooltypes "github.com/NibiruChain/nibiru/x/vpool/types" ) -/* Liquidate allows to liquidate the trader position if the margin is below the +/* + Liquidate allows to liquidate the trader position if the margin is below the + required margin maintenance ratio. args: diff --git a/x/perp/keeper/margin.go b/x/perp/keeper/margin.go index 806a9034d..46fb34543 100644 --- a/x/perp/keeper/margin.go +++ b/x/perp/keeper/margin.go @@ -10,7 +10,9 @@ import ( vpooltypes "github.com/NibiruChain/nibiru/x/vpool/types" ) -/* AddMargin deleverages an existing position by adding margin (collateral) +/* + AddMargin deleverages an existing position by adding margin (collateral) + to it. Adding margin increases the margin ratio of the corresponding position. */ func (k Keeper) AddMargin( @@ -88,7 +90,9 @@ func (k Keeper) AddMargin( }, nil } -/* RemoveMargin further leverages an existing position by directly removing +/* + RemoveMargin further leverages an existing position by directly removing + the margin (collateral) that backs it from the vault. This also decreases the margin ratio of the position. @@ -249,11 +253,12 @@ backing a position is above or below the 'baseMarginRatio'. If 'largerThanOrEqualTo' is true, 'marginRatio' must be >= 'baseMarginRatio'. Args: - marginRatio: Ratio of the value of the margin and corresponding position(s). - marginRatio is defined as (margin + unrealizedPnL) / notional - baseMarginRatio: Specifies the threshold value that 'marginRatio' must meet. - largerThanOrEqualTo: Specifies whether 'marginRatio' should be larger or - smaller than 'baseMarginRatio'. + + marginRatio: Ratio of the value of the margin and corresponding position(s). + marginRatio is defined as (margin + unrealizedPnL) / notional + baseMarginRatio: Specifies the threshold value that 'marginRatio' must meet. + largerThanOrEqualTo: Specifies whether 'marginRatio' should be larger or + smaller than 'baseMarginRatio'. */ func requireMoreMarginRatio(marginRatio, baseMarginRatio sdk.Dec, largerThanOrEqualTo bool) error { if largerThanOrEqualTo { @@ -280,8 +285,8 @@ args: Returns: - positionNotional: the position's notional value as sdk.Dec (signed) - unrealizedPnl: the position's unrealized profits and losses (PnL) as sdk.Dec (signed) - For LONG positions, this is positionNotional - openNotional - For SHORT positions, this is openNotional - positionNotional + For LONG positions, this is positionNotional - openNotional + For SHORT positions, this is openNotional - positionNotional */ func (k Keeper) getPositionNotionalAndUnrealizedPnL( ctx sdk.Context, @@ -375,8 +380,8 @@ args: Returns: - positionNotional: the position's notional value as sdk.Dec (signed) - unrealizedPnl: the position's unrealized profits and losses (PnL) as sdk.Dec (signed) - For LONG positions, this is positionNotional - openNotional - For SHORT positions, this is openNotional - positionNotional + For LONG positions, this is positionNotional - openNotional + For SHORT positions, this is openNotional - positionNotional */ func (k Keeper) getPreferencePositionNotionalAndUnrealizedPnL( ctx sdk.Context, diff --git a/x/perp/types/expected_keepers_test.go b/x/perp/types/expected_keepers_test.go index fb149a53e..636411867 100644 --- a/x/perp/types/expected_keepers_test.go +++ b/x/perp/types/expected_keepers_test.go @@ -10,9 +10,11 @@ import ( "github.com/NibiruChain/nibiru/x/testutil/testapp" ) -/* TestExpectedKeepers verifies that the expected keeper interfaces in x/perp - (see interfaces.go) are implemented on the corresponding app keeper, - 'NibiruApp.KeeperName' +/* +TestExpectedKeepers verifies that the expected keeper interfaces in x/perp + + (see interfaces.go) are implemented on the corresponding app keeper, + 'NibiruApp.KeeperName' */ func TestExpectedKeepers(t *testing.T) { nibiruApp, _ := testapp.NewNibiruAppAndContext(true) diff --git a/x/pricefeed/client/cli/rest.go b/x/pricefeed/client/cli/rest.go index 3ce56cc80..27c98622c 100644 --- a/x/pricefeed/client/cli/rest.go +++ b/x/pricefeed/client/cli/rest.go @@ -13,7 +13,9 @@ import ( "github.com/NibiruChain/nibiru/x/pricefeed/types" ) -/* AddOracleProposalRESTHandler defines a REST handler an 'AddOracleProposal'. +/* + AddOracleProposalRESTHandler defines a REST handler an 'AddOracleProposal'. + The sub-route is mounted on the governance REST handler. */ func AddOracleProposalRESTHandler(clientCtx client.Context) govclientrest.ProposalRESTHandler { diff --git a/x/pricefeed/handler.go b/x/pricefeed/handler.go index 3a95dd24d..43a8b7446 100644 --- a/x/pricefeed/handler.go +++ b/x/pricefeed/handler.go @@ -31,8 +31,11 @@ func NewHandler(k keeper.Keeper) sdk.Handler { } } -/* NewPricefeedPropsalHandler defines a function that handles a proposal after it has -passed the governance process */ +/* + NewPricefeedPropsalHandler defines a function that handles a proposal after it has + +passed the governance process +*/ func NewPricefeedProposalHandler(k keeper.Keeper) govtypes.Handler { return func(ctx sdk.Context, content govtypes.Content) error { switch contentType := content.(type) { diff --git a/x/pricefeed/keeper/store.go b/x/pricefeed/keeper/store.go index b00c7c654..50616100c 100644 --- a/x/pricefeed/keeper/store.go +++ b/x/pricefeed/keeper/store.go @@ -19,7 +19,7 @@ func (k Keeper) ActivePairsStore() ActivePairsState { return (ActivePairsState)(k) } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // OraclesState implements methods for updating the "oracles" sdk.KVStore type OraclesState Keeper @@ -81,7 +81,7 @@ func (state OraclesState) Iterate( } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // ActivePairsState implements methods for updating the "active pairs" sdk.KVStore type ActivePairsState Keeper @@ -113,8 +113,11 @@ func (state ActivePairsState) Get( return isActive } -/* ActivePairsState.Set either sets a pair to active or deletes it from the -key-value store (i.e., pairs default to inactive if they don't exist). */ +/* + ActivePairsState.Set either sets a pair to active or deletes it from the + +key-value store (i.e., pairs default to inactive if they don't exist). +*/ func (state ActivePairsState) Set( ctx sdk.Context, pair common.AssetPair, active bool, ) { diff --git a/x/pricefeed/types/market.go b/x/pricefeed/types/market.go index 23652825c..a7af8f3c9 100644 --- a/x/pricefeed/types/market.go +++ b/x/pricefeed/types/market.go @@ -40,11 +40,14 @@ func NewQueryMarketsResponse(pair common.AssetPair, oracles []sdk.AccAddress, ac NewCurrentPrice returns an instance of CurrentPrice Args: - token0 (string): - token1 (string): - price (sdk.Dec): Price in units of token1 / token0 + + token0 (string): + token1 (string): + price (sdk.Dec): Price in units of token1 / token0 + Returns: - (CurrentPrice): Price for the asset pair. + + (CurrentPrice): Price for the asset pair. */ func NewCurrentPrice(token0 string, token1 string, price sdk.Dec) CurrentPrice { assetPair := common.AssetPair{Token0: token0, Token1: token1} @@ -55,11 +58,14 @@ func NewCurrentPrice(token0 string, token1 string, price sdk.Dec) CurrentPrice { NewCurrentTWAP returns an instance of CurrentTWAP Args: - token0 (string): - token1 (string): - price (sdk.Dec): Price in units of token1 / token0 + + token0 (string): + token1 (string): + price (sdk.Dec): Price in units of token1 / token0 + Returns: - (CurrentTWAP): Current TWAP price for the asset pair. + + (CurrentTWAP): Current TWAP price for the asset pair. */ func NewCurrentTWAP(token0 string, token1 string, numerator sdk.Dec, denominator sdk.Dec, price sdk.Dec) CurrentTWAP { assetPair := common.AssetPair{Token0: token0, Token1: token1} diff --git a/x/stablecoin/keeper/collateral_ratio.go b/x/stablecoin/keeper/collateral_ratio.go index 980e8301d..5850a71a5 100644 --- a/x/stablecoin/keeper/collateral_ratio.go +++ b/x/stablecoin/keeper/collateral_ratio.go @@ -156,16 +156,18 @@ the protocol is below the required amount defined by the current collateral rati Nibiru's NUSD stablecoin is taken to be the dollar that determines USD value. Args: - msg (MsgRecollateralize) { - Creator (string): Caller of 'Recollateralize' - Coll (sdk.Coin): Input collateral that will be sold to the protocol. - } + + msg (MsgRecollateralize) { + Creator (string): Caller of 'Recollateralize' + Coll (sdk.Coin): Input collateral that will be sold to the protocol. + } Returns: - response (MsgRecollateralizeResponse) { - Gov (sdk.Coin): Governance received as a reward for recollateralizing Nibiru. - } - err: Error condition for if the function succeeds or fails. + + response (MsgRecollateralizeResponse) { + Gov (sdk.Coin): Governance received as a reward for recollateralizing Nibiru. + } + err: Error condition for if the function succeeds or fails. */ func (k Keeper) Recollateralize( goCtx context.Context, msg *types.MsgRecollateralize, @@ -277,10 +279,13 @@ GovAmtFromRecollateralize computes the GOV token given as a reward for calling recollateralize. Args: - ctx (sdk.Context): Carries information about the current state of the application. - inUSD (sdk.Dec): Value in NUSD stablecoin to be used for recollateralization. + + ctx (sdk.Context): Carries information about the current state of the application. + inUSD (sdk.Dec): Value in NUSD stablecoin to be used for recollateralization. + Returns: - govOut (sdk.Int): Amount of GOV token rewarded for 'Recollateralize'. + + govOut (sdk.Int): Amount of GOV token rewarded for 'Recollateralize'. */ func (k *Keeper) GovAmtFromRecollateralize( ctx sdk.Context, inUSD sdk.Dec, @@ -317,11 +322,14 @@ BuybackGovAmtForTargetCollRatio returns the governance tokens that the protocol buyback in order to have the optimal collateral ration. Args: - ctx (sdk.Context): Carries information about the current state of the application. + + ctx (sdk.Context): Carries information about the current state of the application. + Returns: - neededGovAmt (sdk.Int): The needed Governance amount that the protocol can buyback in order to - achieve the optimal collateral ratio. - err (error): The error containing information if something went wrong. + + neededGovAmt (sdk.Int): The needed Governance amount that the protocol can buyback in order to + achieve the optimal collateral ratio. + err (error): The error containing information if something went wrong. */ func (k *Keeper) BuybackGovAmtForTargetCollRatio( ctx sdk.Context, @@ -454,10 +462,13 @@ CollAmtFromBuyback computes the COLL (collateral) given as a reward for calling buyback. Args: - ctx (sdk.Context): Carries information about the current state of the application. - valUSD (sdk.Dec): Value in NUSD stablecoin to be used for buyback. + + ctx (sdk.Context): Carries information about the current state of the application. + valUSD (sdk.Dec): Value in NUSD stablecoin to be used for buyback. + Returns: - collAmt (sdk.Int): Amount of COLL token rewarded for 'Buyback'. + + collAmt (sdk.Int): Amount of COLL token rewarded for 'Buyback'. */ func (k *Keeper) CollAmtFromBuyback( ctx sdk.Context, valUSD sdk.Dec, diff --git a/x/stablecoin/keeper/msg_server.go b/x/stablecoin/keeper/msg_server.go index 6861add41..e30961110 100644 --- a/x/stablecoin/keeper/msg_server.go +++ b/x/stablecoin/keeper/msg_server.go @@ -20,9 +20,11 @@ var _ types.MsgServer = msgServer{} /* Args: + goCtx Returns + MsgMintStableResponse: error: */ diff --git a/x/stablecoin/keeper/needed.go b/x/stablecoin/keeper/needed.go index 14cb01f43..f4cba6b59 100644 --- a/x/stablecoin/keeper/needed.go +++ b/x/stablecoin/keeper/needed.go @@ -6,10 +6,13 @@ import ( // Computes the amount of NIBI needed to mint NUSD given some COLL amount. // Args: -// collAmt sdk.Int: Amount of COLL given. +// +// collAmt sdk.Int: Amount of COLL given. +// // Returns: -// neededGovAmt sdk.Int: Amount of NIBI needed. -// mintableStableAmt sdk.Int: Amount of NUSD that can be minted. +// +// neededGovAmt sdk.Int: Amount of NIBI needed. +// mintableStableAmt sdk.Int: Amount of NUSD that can be minted. func NeededGovAmtGivenColl( collAmt sdk.Int, priceGov sdk.Dec, priceColl sdk.Dec, collRatio sdk.Dec) (neededGovAmt sdk.Int, mintableStableAmt sdk.Int) { @@ -23,10 +26,13 @@ func NeededGovAmtGivenColl( // Computes the amount of COLL needed to mint NUSD given some NIBI amount. // Args: -// govAmt sdk.Int: Amount of NIBI given. +// +// govAmt sdk.Int: Amount of NIBI given. +// // Returns: -// neededCollAmt sdk.Int: Amount of COLL needed. -// mintableStableAmt sdk.Int: Amount of NUSD that can be minted. +// +// neededCollAmt sdk.Int: Amount of COLL needed. +// mintableStableAmt sdk.Int: Amount of NUSD that can be minted. func NeededCollAmtGivenGov( govAmt sdk.Int, priceGov sdk.Dec, priceColl sdk.Dec, collRatio sdk.Dec) (neededCollAmt sdk.Int, mintableStableAmt sdk.Int) { diff --git a/x/testutil/testapp/testapp.go b/x/testutil/testapp/testapp.go index 713b709a3..9a192554b 100644 --- a/x/testutil/testapp/testapp.go +++ b/x/testutil/testapp/testapp.go @@ -93,9 +93,12 @@ const ( GenOracleMnemonic = "kit soon capital dry sadness balance rival embark behind coast online struggle deer crush hospital during man monkey prison action custom wink utility arrive" ) -/* NewTestGenesisStateFromDefault returns 'NewGenesisState' using the default +/* + NewTestGenesisStateFromDefault returns 'NewGenesisState' using the default + genesis as input. The blockchain genesis state is represented as a map from module -identifier strings to raw json messages. */ +identifier strings to raw json messages. +*/ func NewTestGenesisStateFromDefault() app.GenesisState { encodingConfig := app.MakeTestEncodingConfig() codec := encodingConfig.Marshaler @@ -134,8 +137,11 @@ func NewTestGenesisState(codec codec.Codec, inGenState app.GenesisState, // ---------------------------------------------------------------------------- // Module types.GenesisState functions -/* PricefeedGenesis returns an x/pricefeed GenesisState with additional -configuration for convenience during integration tests. */ +/* + PricefeedGenesis returns an x/pricefeed GenesisState with additional + +configuration for convenience during integration tests. +*/ func PricefeedGenesis() pricefeedtypes.GenesisState { oracle := sdk.MustAccAddressFromBech32(GenOracleAddress) oracleStrings := []string{oracle.String()} diff --git a/x/vpool/keeper/keeper.go b/x/vpool/keeper/keeper.go index 2975c77bc..0af1d5b4b 100644 --- a/x/vpool/keeper/keeper.go +++ b/x/vpool/keeper/keeper.go @@ -230,7 +230,8 @@ func (k Keeper) SwapQuoteForBase( }) } -/** +/* +* Check's that a pool that we're about to save to state does not violate the fluctuation limit. Always tries to check against a snapshot from a previous block. If one doesn't exist, then it just uses the current snapshot. This should run prior to updating the snapshot, otherwise it will compare the currently updated vpool to itself. @@ -267,7 +268,8 @@ func (k Keeper) checkFluctuationLimitRatio(ctx sdk.Context, pool *types.Pool) er return nil } -/** +/* +* isOverFluctuationLimit compares the updated pool's spot price with the current spot price. If the fluctuation limit ratio is zero, then the fluctuation limit check is skipped. @@ -297,7 +299,8 @@ func isOverFluctuationLimit(pool *types.Pool, snapshot types.ReserveSnapshot) bo return false } -/** +/* +* IsOverSpreadLimit compares the current spot price of the vpool (given by pair) to the underlying's index price (given by an oracle). It panics if you provide it with a pair that doesn't exist in the state. @@ -327,7 +330,8 @@ func (k Keeper) IsOverSpreadLimit(ctx sdk.Context, pair common.AssetPair) bool { return spotPrice.Sub(oraclePrice).Quo(oraclePrice).Abs().GTE(pool.MaxOracleSpreadRatio) } -/** +/* +* GetMaintenanceMarginRatio returns the maintenance margin ratio for the pool from the asset pair. args: diff --git a/x/vpool/keeper/prices.go b/x/vpool/keeper/prices.go index 5f57c3a3f..7550fd936 100644 --- a/x/vpool/keeper/prices.go +++ b/x/vpool/keeper/prices.go @@ -68,7 +68,6 @@ func (k Keeper) GetUnderlyingPrice(ctx sdk.Context, pair common.AssetPair) (sdk. } /* - So how much stablecoin you would get if you sold baseAssetAmount amount of perpetual contracts. Returns the amount of quote assets required to achieve a move of baseAssetAmount in a direction. diff --git a/x/vpool/keeper/snapshot.go b/x/vpool/keeper/snapshot.go index 2c03235df..a0b1fd8e3 100644 --- a/x/vpool/keeper/snapshot.go +++ b/x/vpool/keeper/snapshot.go @@ -9,7 +9,8 @@ import ( "github.com/NibiruChain/nibiru/x/vpool/types" ) -/** +/* +* updateSnapshot updates the snapshot of the current vpool. It creates a new one if the current block height is greater than the previous snapshot's block height. Otherwise, it updates the latest snapshot in state. @@ -143,7 +144,7 @@ type snapshotPriceOptions struct { Pure function that returns a price from a snapshot. Can choose from three types of calc options: SPOT, QUOTE_ASSET_SWAP, and BASE_ASSET_SWAP. -QUOTE_ASSET_SWAP and BASE_ASSET_SWAP require the `direction`` and `assetAmount`` args. +QUOTE_ASSET_SWAP and BASE_ASSET_SWAP require the `direction“ and `assetAmount“ args. SPOT does not require `direction` and `assetAmount`. args: diff --git a/x/vpool/types/pool.go b/x/vpool/types/pool.go index 072d2b924..8c3dc4b46 100644 --- a/x/vpool/types/pool.go +++ b/x/vpool/types/pool.go @@ -48,7 +48,7 @@ args: ret: - baseAmountOut: the amount of base assets required to make this hypothetical swap - always an absolute value + always an absolute value - err: error */ func (p *Pool) GetBaseAmountByQuoteAmount( @@ -88,7 +88,7 @@ args: ret: - quoteAmountOut: the amount of quote assets required to make this hypothetical swap - always an absolute value + always an absolute value - err: error */ func (p *Pool) GetQuoteAmountByBaseAmount( @@ -143,11 +143,14 @@ func (p *Pool) DecreaseQuoteAssetReserve(amount sdk.Dec) { NewCurrentTWAP returns an instance of CurrentTWAP Args: - token0 (string): - token1 (string): - price (sdk.Dec): Price in units of token1 / token0 + + token0 (string): + token1 (string): + price (sdk.Dec): Price in units of token1 / token0 + Returns: - (CurrentTWAP): Current TWAP price for the asset pair. + + (CurrentTWAP): Current TWAP price for the asset pair. */ func NewCurrentTWAP(token0 string, token1 string, numerator sdk.Dec, denominator sdk.Dec, price sdk.Dec) CurrentTWAP { assetPair := common.AssetPair{Token0: token0, Token1: token1}