Skip to content

Commit

Permalink
add increment-only denom id
Browse files Browse the repository at this point in the history
  • Loading branch information
antstalepresh committed Jul 12, 2024
1 parent 4c25b89 commit 20e491d
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 370 deletions.
7 changes: 4 additions & 3 deletions proto/kujira/oracle/oracle.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ message Params {
(gogoproto.moretags) = "yaml:\"required_denoms\"",
(gogoproto.nullable) = false
];
string slash_fraction = 5 [
uint32 last_denom_id = 5;
string slash_fraction = 6 [
(gogoproto.moretags) = "yaml:\"slash_fraction\"",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
uint64 slash_window = 6 [(gogoproto.moretags) = "yaml:\"slash_window\""];
string min_valid_per_window = 7 [
uint64 slash_window = 7 [(gogoproto.moretags) = "yaml:\"slash_window\""];
string min_valid_per_window = 8 [
(gogoproto.moretags) = "yaml:\"min_valid_per_window\"",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
Expand Down
19 changes: 9 additions & 10 deletions proto/kujira/oracle/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,36 @@ option go_package = "github.com/Team-Kujira/core/x/oracle/types";
// Msg defines the oracle Msg service.
service Msg {
// AddRequiredDenom adds a new price to the required list of prices
rpc AddRequiredDenom(MsgAddRequiredDenom) returns (MsgAddRequiredDenomResponse);
rpc AddRequiredDenoms(MsgAddRequiredDenoms) returns (MsgAddRequiredDenomsResponse);

// RemoveRequiredDenom removes a price from the required list of prices
rpc RemoveRequiredDenom(MsgRemoveRequiredDenom) returns (MsgRemoveRequiredDenomResponse);
rpc RemoveRequiredDenoms(MsgRemoveRequiredDenoms) returns (MsgRemoveRequiredDenomsResponse);

// UpdateParams sets new module params
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
}

// MsgAddRequiredDenom represents a message to add a denom to the whitelist
message MsgAddRequiredDenom {
message MsgAddRequiredDenoms {
option (cosmos.msg.v1.signer) = "authority";

string authority = 1 [(gogoproto.moretags) = "yaml:\"authority\""];
string symbol = 2 [ (gogoproto.moretags) = "yaml:\"symbol\"" ];
uint32 id = 3 [ (gogoproto.moretags) = "yaml:\"id\"" ];
repeated string symbols = 2 [ (gogoproto.moretags) = "yaml:\"symbols\"" ];
}

// MsgAddRequiredDenomResponse defines the Msg/AddRequiredDenom response type.
message MsgAddRequiredDenomResponse {}
message MsgAddRequiredDenomsResponse {}

// MsgRemoveRequiredDenom represents a message to remove a denom from the whitelist
message MsgRemoveRequiredDenom {
message MsgRemoveRequiredDenoms {
option (cosmos.msg.v1.signer) = "authority";

string authority = 1 [(gogoproto.moretags) = "yaml:\"authority\""];
string symbol = 2 [ (gogoproto.moretags) = "yaml:\"symbol\"" ];
string authority = 1 [ (gogoproto.moretags) = "yaml:\"authority\"" ];
repeated string symbols = 2 [ (gogoproto.moretags) = "yaml:\"symbols\"" ];
}

// MsgRemoveRequiredDenomResponse defines the Msg/RemoveRequiredDenom response type.
message MsgRemoveRequiredDenomResponse {}
message MsgRemoveRequiredDenomsResponse {}

message MsgUpdateParams {
option (cosmos.msg.v1.signer) = "authority";
Expand Down
74 changes: 29 additions & 45 deletions x/oracle/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"context"
"fmt"
"reflect"

"cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -21,66 +22,65 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}

func (ms msgServer) AddRequiredDenom(goCtx context.Context, msg *types.MsgAddRequiredDenom) (*types.MsgAddRequiredDenomResponse, error) {
func (ms msgServer) AddRequiredDenoms(goCtx context.Context, msg *types.MsgAddRequiredDenoms) (*types.MsgAddRequiredDenomsResponse, error) {
if ms.authority != msg.Authority {
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.authority, msg.Authority)
}

ctx := sdk.UnwrapSDKContext(goCtx)
params := ms.GetParams(ctx)

denoms := params.RequiredDenoms
for _, denom := range denoms {
if denom.Denom == msg.Symbol {
return nil, fmt.Errorf("symbol '%s' already set as required denoms", msg.Symbol)
}
if denom.Id == msg.Id {
return nil, fmt.Errorf("id '%d' already set as required denoms", msg.Id)
existingSymbols := make(map[string]bool)
for _, denom := range params.RequiredDenoms {
existingSymbols[denom.Denom] = true
}

for _, denom := range msg.Symbols {
if existingSymbols[denom] {
return nil, fmt.Errorf("symbol '%s' already set as required denoms", denom)
}
params.RequiredDenoms = append(params.RequiredDenoms, types.Denom{
Denom: denom,
Id: params.LastDenomId + 1,
})
params.LastDenomId++
}

denoms = append(denoms, types.Denom{
Denom: msg.Symbol,
Id: msg.Id,
})
params.RequiredDenoms = denoms
err := ms.SetParams(ctx, params)
if err != nil {
return nil, types.ErrSetParams
}

return &types.MsgAddRequiredDenomResponse{}, nil
return &types.MsgAddRequiredDenomsResponse{}, nil
}

func (ms msgServer) RemoveRequiredDenom(goCtx context.Context, msg *types.MsgRemoveRequiredDenom) (*types.MsgRemoveRequiredDenomResponse, error) {
func (ms msgServer) RemoveRequiredDenoms(goCtx context.Context, msg *types.MsgRemoveRequiredDenoms) (*types.MsgRemoveRequiredDenomsResponse, error) {
if ms.authority != msg.Authority {
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.authority, msg.Authority)
}

ctx := sdk.UnwrapSDKContext(goCtx)
params := ms.GetParams(ctx)

denoms := params.RequiredDenoms
index := -1
for i, denom := range denoms {
if denom.Denom == msg.Symbol {
index = i
break
}
removingSymbols := make(map[string]bool)
for _, symbol := range msg.Symbols {
removingSymbols[symbol] = true
}

if index < 0 {
return nil, fmt.Errorf("symbol '%s' not found in required denoms", msg.Symbol)
requiredDenoms := []types.Denom{}
for _, denom := range params.RequiredDenoms {
if !removingSymbols[denom.Denom] {
requiredDenoms = append(requiredDenoms, denom)
}
}

denoms = append(denoms[:index], denoms[index+1:]...)
params.RequiredDenoms = denoms
params.RequiredDenoms = requiredDenoms
err := ms.SetParams(ctx, params)
if err != nil {
return nil, types.ErrSetParams
}

return &types.MsgRemoveRequiredDenomResponse{}, nil
return &types.MsgRemoveRequiredDenomsResponse{}, nil
}

func (ms msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
Expand All @@ -92,24 +92,8 @@ func (ms msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdatePara

// Check id and denom mapping change
params := ms.GetParams(ctx)
idToDenom := make(map[uint32]string)
denomToId := make(map[string]uint32)
for _, denom := range params.RequiredDenoms {
idToDenom[denom.Id] = denom.Denom
denomToId[denom.Denom] = denom.Id
}

for _, denom := range msg.Params.RequiredDenoms {
if oldDenom, ok := idToDenom[denom.Id]; ok {
if oldDenom != denom.Denom {
return nil, types.ErrDenomAssociatedToIdChanged
}
}
if oldId, ok := denomToId[denom.Denom]; ok {
if oldId != denom.Id {
return nil, types.ErrIdAssociatedToDenomChanged
}
}
if !reflect.DeepEqual(params.RequiredDenoms, msg.Params.RequiredDenoms) {
return nil, types.ErrCanNotUpdateRequiredDenoms
}

if err := ms.SetParams(ctx, *msg.Params); err != nil {
Expand Down
1 change: 0 additions & 1 deletion x/oracle/simulation/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ func TestDecodeDistributionStore(t *testing.T) {
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)},
{"other", ""},
}
Expand Down
8 changes: 4 additions & 4 deletions x/oracle/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import (
// 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(&MsgAddRequiredDenom{}, "oracle/MsgAddRequiredDenom", nil)
cdc.RegisterConcrete(&MsgRemoveRequiredDenom{}, "oracle/MsgRemoveRequiredDenom", nil)
cdc.RegisterConcrete(&MsgAddRequiredDenoms{}, "oracle/MsgAddRequiredDenoms", nil)
cdc.RegisterConcrete(&MsgRemoveRequiredDenoms{}, "oracle/MsgRemoveRequiredDenoms", nil)
cdc.RegisterConcrete(&MsgUpdateParams{}, "oracle/MsgUpdateParams", nil)
}

// RegisterInterfaces registers the x/oracle interfaces types with the interface registry
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgAddRequiredDenom{},
&MsgRemoveRequiredDenom{},
&MsgAddRequiredDenoms{},
&MsgRemoveRequiredDenoms{},
&MsgUpdateParams{},
)

Expand Down
3 changes: 1 addition & 2 deletions x/oracle/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,5 @@ var (
ErrUnknownDenom = errors.Register(ModuleName, 13, "unknown denom")
ErrBallotNotSorted = errors.Register(ModuleName, 14, "ballot not sorted")
ErrSetParams = errors.Register(ModuleName, 15, "could not set params")
ErrDenomAssociatedToIdChanged = errors.Register(ModuleName, 16, "could not update denom associated to an id")
ErrIdAssociatedToDenomChanged = errors.Register(ModuleName, 17, "could not update id associated to a denom")
ErrCanNotUpdateRequiredDenoms = errors.Register(ModuleName, 16, "could not update required denoms")
)
33 changes: 4 additions & 29 deletions x/oracle/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,22 @@ const (
//
// - 0x01<denom_Bytes>: sdk.Dec
//
// - 0x02<valAddress_Bytes>: accAddress
//
// - 0x03<valAddress_Bytes>: int64
//
// - 0x04<valAddress_Bytes>: AggregateExchangeRatePrevote
//
// - 0x05<valAddress_Bytes>: AggregateExchangeRateVote
//
// - 0x06<denom_Bytes>: sdk.Dec
// - 0x06: Params
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
ParamsKey = []byte{0x06}
WhitelistKey = []byte{0x07}
ExchangeRateKey = []byte{0x01} // prefix for each key to a rate
MissCounterKey = []byte{0x03} // prefix for each key to a miss counter
ParamsKey = []byte{0x06}
)

// GetExchangeRateKey - stored by *denom*
func GetExchangeRateKey(denom string) []byte {
return append(ExchangeRateKey, []byte(denom)...)
}

// GetFeederDelegationKey - stored by *Validator* address
func GetFeederDelegationKey(v sdk.ValAddress) []byte {
return append(FeederDelegationKey, address.MustLengthPrefix(v)...)
}

// GetMissCounterKey - stored by *Validator* address
func GetMissCounterKey(v sdk.ValAddress) []byte {
return append(MissCounterKey, address.MustLengthPrefix(v)...)
}

// GetAggregateExchangeRatePrevoteKey - stored by *Validator* address
func GetAggregateExchangeRatePrevoteKey(v sdk.ValAddress) []byte {
return append(AggregateExchangeRatePrevoteKey, address.MustLengthPrefix(v)...)
}

// GetAggregateExchangeRateVoteKey - stored by *Validator* address
func GetAggregateExchangeRateVoteKey(v sdk.ValAddress) []byte {
return append(AggregateExchangeRateVoteKey, address.MustLengthPrefix(v)...)
}
32 changes: 16 additions & 16 deletions x/oracle/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (

// ensure Msg interface compliance at compile time
var (
_ sdk.Msg = &MsgAddRequiredDenom{}
_ sdk.Msg = &MsgRemoveRequiredDenom{}
_ sdk.Msg = &MsgAddRequiredDenoms{}
_ sdk.Msg = &MsgRemoveRequiredDenoms{}
_ sdk.Msg = &MsgUpdateParams{}
)

Expand All @@ -24,26 +24,26 @@ const (
//-------------------------------------------------

// NewMsgAddRequiredDenom creates a MsgAddRequiredDenom instance
func NewMsgAddRequiredDenom(symbol string) *MsgAddRequiredDenom {
return &MsgAddRequiredDenom{
Symbol: symbol,
func NewMsgAddRequiredDenom(symbols []string) *MsgAddRequiredDenoms {
return &MsgAddRequiredDenoms{
Symbols: symbols,
}
}

// Route implements sdk.Msg
func (msg MsgAddRequiredDenom) Route() string { return RouterKey }
func (msg MsgAddRequiredDenoms) Route() string { return RouterKey }

// Type implements sdk.Msg
func (msg MsgAddRequiredDenom) Type() string { return TypeMsgAddRequiredDenom }
func (msg MsgAddRequiredDenoms) Type() string { return TypeMsgAddRequiredDenom }

// GetSigners implements sdk.Msg
func (msg MsgAddRequiredDenom) GetSigners() []sdk.AccAddress {
func (msg MsgAddRequiredDenoms) GetSigners() []sdk.AccAddress {
addr, _ := sdk.AccAddressFromBech32(msg.Authority)
return []sdk.AccAddress{addr}
}

// ValidateBasic implements sdk.Msg
func (msg MsgAddRequiredDenom) ValidateBasic() error {
func (msg MsgAddRequiredDenoms) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Authority)
if err != nil {
return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid authority address (%s)", err)
Expand All @@ -53,26 +53,26 @@ func (msg MsgAddRequiredDenom) ValidateBasic() error {
}

// NewMsgRemoveRequiredDenom creates a MsgRemoveRequiredDenom instance
func NewMsgRemoveRequiredDenom(symbol string) *MsgRemoveRequiredDenom {
return &MsgRemoveRequiredDenom{
Symbol: symbol,
func NewMsgRemoveRequiredDenom(symbols []string) *MsgRemoveRequiredDenoms {
return &MsgRemoveRequiredDenoms{
Symbols: symbols,
}
}

// Route implements sdk.Msg
func (msg MsgRemoveRequiredDenom) Route() string { return RouterKey }
func (msg MsgRemoveRequiredDenoms) Route() string { return RouterKey }

// Type implements sdk.Msg
func (msg MsgRemoveRequiredDenom) Type() string { return TypeMsgRemoveRequiredDenom }
func (msg MsgRemoveRequiredDenoms) Type() string { return TypeMsgRemoveRequiredDenom }

// GetSigners implements sdk.Msg
func (msg MsgRemoveRequiredDenom) GetSigners() []sdk.AccAddress {
func (msg MsgRemoveRequiredDenoms) GetSigners() []sdk.AccAddress {
addr, _ := sdk.AccAddressFromBech32(msg.Authority)
return []sdk.AccAddress{addr}
}

// ValidateBasic implements sdk.Msg
func (msg MsgRemoveRequiredDenom) ValidateBasic() error {
func (msg MsgRemoveRequiredDenoms) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Authority)
if err != nil {
return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid authority address (%s)", err)
Expand Down
Loading

0 comments on commit 20e491d

Please sign in to comment.