Skip to content

Commit

Permalink
feat(oracle): MsgEditOracleParams sudo tx msg as part of #1642 (#1752)
Browse files Browse the repository at this point in the history
* feat(perp): MsgDonateToPerpFund

* changelog

* linter

* test assertiong

* Squashed commit of the following:

commit e43672a
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:27:28 2023 -0600

    test assertiong

commit 0090d2f
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:17:30 2023 -0600

    linter

commit 5121341
Merge: 596a840 68bddeb
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:12:10 2023 -0600

    Merge branch 'main' into realu/sg-perp

commit 596a840
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:10:15 2023 -0600

    changelog

commit 240dffe
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:07:46 2023 -0600

    feat(perp): MsgDonateToPerpFund

* test(perp-cli_test): Grab module acc addr programatically

* impl wip! keeper version without msg server or protos

* quicksave wip! - add protos and msg server + todos

* test(oracle): verify that params before are not equal

* refactor: sudo and admin name consistency + docs + remove struct
embedding

* Squashed commit of the following:

commit d3f0ce3
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:47:35 2023 -0600

    test(perp-cli_test): Grab module acc addr programatically

commit e43672a
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:27:28 2023 -0600

    test assertiong

commit 0090d2f
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:17:30 2023 -0600

    linter

commit 5121341
Merge: 596a840 68bddeb
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:12:10 2023 -0600

    Merge branch 'main' into realu/sg-perp

commit 596a840
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:10:15 2023 -0600

    changelog

commit 240dffe
Author: Unique-Divine <[email protected]>
Date:   Wed Dec 27 23:07:46 2023 -0600

    feat(perp): MsgDonateToPerpFund

* PR comments fix

* test(oracle): fix unit test case with invalid slash window
  • Loading branch information
Unique-Divine authored Jan 2, 2024
1 parent b4175f1 commit 1795b55
Show file tree
Hide file tree
Showing 16 changed files with 1,465 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1705](https://github.com/NibiruChain/nibiru/pull/1705) - feat(perp): Add oracle pair to market object
* [#1718](https://github.com/NibiruChain/nibiru/pull/1718) - fix: fees does not require additional funds
* [#1734](https://github.com/NibiruChain/nibiru/pull/1734) - feat(perp): MsgDonateToPerpFund sudo call as part of #1642
* [#1752](https://github.com/NibiruChain/nibiru/pull/1752) - feat(oracle): MsgEditOracleParams sudo tx msg as part of #1642
* [#1755](https://github.com/NibiruChain/nibiru/pull/1755) - feat(oracle): Add more events on validator's performance
* [#1749](https://github.com/NibiruChain/nibiru/pull/1749) - feat(perp): move close market from Wasm Binding to MsgCloseMarket

Expand Down
12 changes: 7 additions & 5 deletions app/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,18 +357,20 @@ func (app *NibiruApp) InitKeepers(
appCodec, keys[spottypes.StoreKey], app.GetSubspace(spottypes.ModuleName),
app.AccountKeeper, app.BankKeeper, app.DistrKeeper)

app.SudoKeeper = keeper.NewKeeper(
appCodec, keys[sudotypes.StoreKey],
)

app.OracleKeeper = oraclekeeper.NewKeeper(appCodec, keys[oracletypes.StoreKey],
app.AccountKeeper, app.BankKeeper, app.DistrKeeper, app.stakingKeeper, distrtypes.ModuleName,
app.AccountKeeper, app.BankKeeper, app.DistrKeeper, app.stakingKeeper,
app.SudoKeeper,
distrtypes.ModuleName,
)

app.EpochsKeeper = epochskeeper.NewKeeper(
appCodec, keys[epochstypes.StoreKey],
)

app.SudoKeeper = keeper.NewKeeper(
appCodec, keys[sudotypes.StoreKey],
)

app.PerpKeeperV2 = perpkeeper.NewKeeper(
appCodec, keys[perptypes.StoreKey],
app.AccountKeeper, app.BankKeeper, app.OracleKeeper, app.EpochsKeeper,
Expand Down
10 changes: 5 additions & 5 deletions proto/nibiru/oracle/v1/oracle.proto
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ message Params {
(gogoproto.nullable) = false
];

// Amount of time to look back for TWAP calculations
// Amount of time to look back for TWAP calculations.
// Ex: "900.000000069s" corresponds to 900 seconds and 69 nanoseconds in JSON.
google.protobuf.Duration twap_lookback_window = 8 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
Expand All @@ -79,9 +80,8 @@ message Params {
(gogoproto.nullable) = false
];

uint64 expiration_blocks = 11 [
(gogoproto.moretags) = "yaml:\"expiration_blocks\""
];
uint64 expiration_blocks = 11
[ (gogoproto.moretags) = "yaml:\"expiration_blocks\"" ];
}

// Struct for aggregate prevoting on the ExchangeRateVote.
Expand Down Expand Up @@ -154,4 +154,4 @@ message Rewards {
uint64 vote_periods = 2;
// Coins defines the amount of coins to distribute in a single vote period.
repeated cosmos.base.v1beta1.Coin coins = 3 [ (gogoproto.nullable) = false ];
}
}
68 changes: 68 additions & 0 deletions proto/nibiru/oracle/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package nibiru.oracle.v1;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "nibiru/oracle/v1/oracle.proto";

option go_package = "github.com/NibiruChain/nibiru/x/oracle/types";

Expand All @@ -29,6 +30,11 @@ service Msg {
returns (MsgDelegateFeedConsentResponse) {
option (google.api.http).post = "/nibiru/oracle/feeder-delegate";
}

rpc EditOracleParams(MsgEditOracleParams)
returns (MsgEditOracleParamsResponse) {
option (google.api.http).post = "/nibiru/oracle/edit-oracle-params";
}
}

// MsgAggregateExchangeRatePrevote represents a message to submit
Expand Down Expand Up @@ -84,3 +90,65 @@ message MsgDelegateFeedConsent {
// MsgDelegateFeedConsentResponse defines the Msg/DelegateFeedConsent response
// type.
message MsgDelegateFeedConsentResponse {}

// MsgEditOracleParams: gRPC tx message for updating the x/oracle module params
// [SUDO] Only callable by sudoers.
message MsgEditOracleParams {
string sender = 1;

string vote_period = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = true
];

// vote_threshold: [cosmossdk.io/math.LegacyDec] TODO:
string vote_threshold = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = true
];

// reward_band: [cosmossdk.io/math.LegacyDec] TODO:
string reward_band = 4 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = true
];

repeated string whitelist = 5 [ (gogoproto.nullable) = true ];

// slash_fraction: [cosmossdk.io/math.LegacyDec] TODO:
string slash_fraction = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = true
];

string slash_window = 7 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = true
];

// min_valid_per_window: [cosmossdk.io/math.LegacyDec] TODO:
string min_valid_per_window = 8 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = true
];

string twap_lookback_window = 9 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = true
];

string min_voters = 10 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = true
];

// VoteThreshold: [cosmossdk.io/math.LegacyDec] TODO:
string validator_fee_ratio = 11 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = true
];
}

// MsgEditOracleParamsResponse defines the Msg/EditOracleParams response
// type.
message MsgEditOracleParamsResponse { nibiru.oracle.v1.Params new_params = 1; }
23 changes: 18 additions & 5 deletions x/oracle/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ type Keeper struct {
bankKeeper types.BankKeeper
distrKeeper types.DistributionKeeper
StakingKeeper types.StakingKeeper
SudoKeeper types.SudoKeeper

distrModuleName string

// Module parameters
Params collections.Item[types.Params]
ExchangeRates collections.Map[asset.Pair, types.DatedPrice]
FeederDelegations collections.Map[sdk.ValAddress, sdk.AccAddress]
Expand All @@ -38,30 +40,40 @@ type Keeper struct {
Votes collections.Map[sdk.ValAddress, types.AggregateExchangeRateVote]

// PriceSnapshots maps types.PriceSnapshot to the asset.Pair of the snapshot and the creation timestamp as keys.Uint64Key.
PriceSnapshots collections.Map[collections.Pair[asset.Pair, time.Time], types.PriceSnapshot]
PriceSnapshots collections.Map[
collections.Pair[asset.Pair, time.Time],
types.PriceSnapshot]
WhitelistedPairs collections.KeySet[asset.Pair]
Rewards collections.Map[uint64, types.Rewards]
RewardsID collections.Sequence
}

// NewKeeper constructs a new keeper for oracle
func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey,
func NewKeeper(
cdc codec.BinaryCodec,
storeKey storetypes.StoreKey,

accountKeeper types.AccountKeeper,
bankKeeper types.BankKeeper, distrKeeper types.DistributionKeeper,
stakingKeeper types.StakingKeeper, distrName string,
bankKeeper types.BankKeeper,
distrKeeper types.DistributionKeeper,
stakingKeeper types.StakingKeeper,
sudoKeeper types.SudoKeeper,

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))
}

return Keeper{
k := Keeper{
cdc: cdc,
storeKey: storeKey,
AccountKeeper: accountKeeper,
bankKeeper: bankKeeper,
distrKeeper: distrKeeper,
StakingKeeper: stakingKeeper,
SudoKeeper: sudoKeeper,
distrModuleName: distrName,
Params: collections.NewItem(storeKey, 11, collections.ProtoValueEncoder[types.Params](cdc)),
ExchangeRates: collections.NewMap(storeKey, 1, asset.PairKeyEncoder, collections.ProtoValueEncoder[types.DatedPrice](cdc)),
Expand All @@ -76,6 +88,7 @@ func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey,
collections.Uint64KeyEncoder, collections.ProtoValueEncoder[types.Rewards](cdc)),
RewardsID: collections.NewSequence(storeKey, 9),
}
return k
}

// Logger returns a module-specific logger.
Expand Down
20 changes: 19 additions & 1 deletion x/oracle/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (ms msgServer) AggregateExchangeRateVote(
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,
types.ErrHashVerificationFailed, "must be given %s not %s", aggregatePrevote.Hash, hash,
)
}

Expand Down Expand Up @@ -167,3 +167,21 @@ func (ms msgServer) DelegateFeedConsent(

return &types.MsgDelegateFeedConsentResponse{}, err
}

// EditOracleParams: gRPC tx msg for editing the oracle module params.
// [SUDO] Only callable by sudoers.
func (ms msgServer) EditOracleParams(
goCtx context.Context, msg *types.MsgEditOracleParams,
) (resp *types.MsgEditOracleParamsResponse, err error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// Stateless field validation is already performed in msg.ValidateBasic()
// before the current scope is reached.
sender, _ := sdk.AccAddressFromBech32(msg.Sender)
newParams, err := ms.Sudo().EditOracleParams(
ctx, *msg, sender,
)
resp = &types.MsgEditOracleParamsResponse{
NewParams: &newParams,
}
return resp, err
}
100 changes: 100 additions & 0 deletions x/oracle/keeper/sudo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package keeper

import (
"fmt"
"time"

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

"github.com/NibiruChain/nibiru/x/common/asset"
oracletypes "github.com/NibiruChain/nibiru/x/oracle/types"
)

// Sudo extends the Keeper with sudo functions. See sudo.go. Sudo is syntactic
// sugar to separate admin calls off from the other Keeper methods.
//
// These Sudo functions should:
// 1. Not be called in other methods in the x/perp module.
// 2. Only be callable by the x/sudo root or sudo contracts.
//
// The intention behind "Keeper.Sudo()" is to make it more obvious to the
// developer that an unsafe function is being used when it's called.
func (k Keeper) Sudo() sudoExtension { return sudoExtension{k} }

type sudoExtension struct{ Keeper }

// ------------------------------------------------------------------
// Admin.EditOracleParams

func (k sudoExtension) EditOracleParams(
ctx sdk.Context, newParams oracletypes.MsgEditOracleParams,
sender sdk.AccAddress,
) (paramsAfter oracletypes.Params, err error) {
if err := k.SudoKeeper.CheckPermissions(sender, ctx); err != nil {
return paramsAfter, err
}

params, err := k.Params.Get(ctx)
if err != nil {
return paramsAfter, fmt.Errorf("%w: failed to read oracle params", err)
}

paramsAfter = MergeOracleParams(newParams, params)
k.UpdateParams(ctx, paramsAfter)
return paramsAfter, paramsAfter.Validate()
}

// MergeOracleParams: Takes the given oracle params and merges them into the
// existing partial params, keeping any existing values that are not set in the
// partial.
func MergeOracleParams(
partial oracletypes.MsgEditOracleParams,
oracleParams oracletypes.Params,
) oracletypes.Params {
if partial.VotePeriod != nil {
oracleParams.VotePeriod = partial.VotePeriod.Uint64()
}

if partial.VoteThreshold != nil {
oracleParams.VoteThreshold = *partial.VoteThreshold
}

if partial.RewardBand != nil {
oracleParams.RewardBand = *partial.RewardBand
}

if partial.Whitelist != nil {
whitelist := make([]asset.Pair, len(partial.Whitelist))
for i, pair := range partial.Whitelist {
whitelist[i] = asset.MustNewPair(pair)
}

oracleParams.Whitelist = whitelist
}

if partial.SlashFraction != nil {
oracleParams.SlashFraction = *partial.SlashFraction
}

if partial.SlashWindow != nil {
oracleParams.SlashWindow = partial.SlashWindow.Uint64()
}

if partial.MinValidPerWindow != nil {
oracleParams.MinValidPerWindow = *partial.MinValidPerWindow
}

if partial.TwapLookbackWindow != nil {
oracleParams.TwapLookbackWindow = time.Duration(partial.TwapLookbackWindow.Int64())
}

if partial.MinVoters != nil {
oracleParams.MinVoters = partial.MinVoters.Uint64()
}

if partial.ValidatorFeeRatio != nil {
oracleParams.ValidatorFeeRatio = *partial.ValidatorFeeRatio
}

return oracleParams
}
Loading

0 comments on commit 1795b55

Please sign in to comment.