Skip to content

Commit

Permalink
feat: add relayer fee settings (#1197)
Browse files Browse the repository at this point in the history
# Related Github tickets

- VolumeFi#1710

# Background

> This change adds the concept of individual
> relayer fees that may be set by any active
> validator for any supported target chain.

# Testing completed

- [x] test coverage exists or has been added/updated
- [x] tested in a private testnet

# Breaking changes

- [x] I have checked my code for breaking changes
- [x] If there are breaking changes, there is a supporting migration.
  • Loading branch information
byte-bandit authored Jun 21, 2024
1 parent d3bc02e commit 4ff05b3
Show file tree
Hide file tree
Showing 30 changed files with 2,504 additions and 142 deletions.
1 change: 1 addition & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ func New(
app.BankKeeper,
app.AccountKeeper,
app.SchedulerKeeper,
app.EvmKeeper,
)

app.ScopedConsensusKeeper = scopedConsensusKeeper
Expand Down
38 changes: 38 additions & 0 deletions proto/palomachain/paloma/treasury/fees.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,48 @@ import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "palomachain/paloma/treasury/params.proto";
import "cosmos_proto/cosmos.proto";
import "amino/amino.proto";

option go_package = "github.com/palomachain/paloma/x/treasury/types";

// Empty represents an empty message
message Empty {}

message Fees {
string communityFundFee = 1;
string securityFee = 2;
}

// Represents the fee setting of an individual relayer for a target chain.
message RelayerFeeSetting {
option (gogoproto.equal) = true;
option (gogoproto.goproto_stringer) = true;

message FeeSetting {
option (gogoproto.equal) = true;
option (gogoproto.goproto_stringer) = true;
// Describes the factor by which the gas spent on a
// relayed transaction will be reimbursed.
// e.g. `1.2` -> relayer asks to be reimbursed with `total_gas_cost * 1.2`
// lower fee settings prioritize the relayer higher in the
// pool.
// A value below 1 indicates likely partial loss of funds.
// `0` means no fees, with a total loss of funds.
// Negative values are rejected.
string multiplicator = 1 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(amino.dont_omitempty) = true,
(gogoproto.nullable) = false
];

// Indicates the reference ID of the target chain.
string chain_reference_id = 2;
}

// Validator address of a validator participating in consensus.
string val_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

repeated FeeSetting fees = 2 [(gogoproto.nullable) = false];
}
3 changes: 2 additions & 1 deletion proto/palomachain/paloma/treasury/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ option go_package = "github.com/palomachain/paloma/x/treasury/types";
// GenesisState defines the treasury module's genesis state.
message GenesisState {
Params params = 1 [ (gogoproto.nullable) = false ];
Fees treasuryFees = 2;
Fees treasuryFees = 2[ (gogoproto.nullable) = false ];
repeated RelayerFeeSetting relayer_fee_settings = 3[ (gogoproto.nullable) = false ];
}
15 changes: 15 additions & 0 deletions proto/palomachain/paloma/treasury/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package palomachain.paloma.treasury;
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "cosmos_proto/cosmos.proto";

import "palomachain/paloma/treasury/params.proto";
import "palomachain/paloma/treasury/fees.proto";

Expand All @@ -19,6 +21,11 @@ service Query {
rpc QueryFees(QueryFeesRequest) returns (Fees) {
option (google.api.http).get = "/palomachain/paloma/treasury/fees";
}

// RelayerFee queries the fee settings of a validator participating in consensus.
rpc RelayerFee(QueryRelayerFeeRequest) returns (RelayerFeeSetting) {
option (google.api.http).get = "/palomachain/paloma/treasury/relayer_fee";
}
}

// QueryParamsRequest is request type for the Query/Params RPC method.
Expand All @@ -31,3 +38,11 @@ message QueryParamsResponse {
}

message QueryFeesRequest {}

// QueryRelayerFeeRequest is the request type for the Query/RelayerFee RPC method.
message QueryRelayerFeeRequest {
// val_address holds the validator address of the validator you want to query
// for.
string val_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
}

20 changes: 19 additions & 1 deletion proto/palomachain/paloma/treasury/tx.proto
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
syntax = "proto3";
package palomachain.paloma.treasury;

import "gogoproto/gogo.proto";
import "cosmos/msg/v1/msg.proto";

import "palomachain/paloma/valset/common.proto";
import "palomachain/paloma/treasury/fees.proto";

option go_package = "github.com/palomachain/paloma/x/treasury/types";

// Msg defines the Msg service.
service Msg {}
service Msg {
rpc UpsertRelayerFee(MsgUpsertRelayerFee)
returns (Empty);
}

message MsgUpsertRelayerFee {
option (cosmos.msg.v1.signer) = "metadata";

palomachain.paloma.valset.MsgMetadata metadata = 1
[ (gogoproto.nullable) = false ];

RelayerFeeSetting fee_setting = 2;
}
1 change: 1 addition & 0 deletions testutil/keeper/treasury.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func TreasuryKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
nil,
nil,
nil,
nil,
)

ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
Expand Down
96 changes: 96 additions & 0 deletions util/keeper/mocks/KVStoreWrapper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 28 additions & 8 deletions util/keeper/wrapper.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
package keeper

import (
"github.com/cosmos/cosmos-sdk/codec"
"context"

corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/gogoproto/proto"
)

type Byter interface {
Bytes() []byte
}

func NewKvStoreWrapper[T codec.ProtoMarshaler](s StoreGetterFn, ps ProtoSerializer) *KVStoreWrapper[T] {
return &KVStoreWrapper[T]{
func NewKvStoreWrapper[T proto.Message](s StoreGetterFn, ps ProtoSerializer) *kvStoreWrapper[T] {
return &kvStoreWrapper[T]{
sg: s,
ps: ps,
}
}

type KVStoreWrapper[T codec.ProtoMarshaler] struct {
//go:generate mockery --name=KVStoreWrapper
type KVStoreWrapper[T proto.Message] interface {
Get(ctx types.Context, key Byter) (T, error)
Set(ctx types.Context, key Byter, value T) error
Iterate(ctx types.Context, fn func([]byte, T) bool) error
}

type kvStoreWrapper[T proto.Message] struct {
sg StoreGetterFn
ps ProtoSerializer
}

func (v *KVStoreWrapper[T]) Get(ctx types.Context, key Byter) (T, error) {
func (v *kvStoreWrapper[T]) Get(ctx types.Context, key Byter) (T, error) {
return Load[T](v.sg(ctx), v.ps, key.Bytes())
}

func (v *KVStoreWrapper[T]) Set(ctx types.Context, key Byter, value T) error {
func (v *kvStoreWrapper[T]) Set(ctx types.Context, key Byter, value T) error {
return Save(v.sg(ctx), v.ps, key.Bytes(), value)
}

func (v *KVStoreWrapper[T]) Iterate(ctx types.Context, fn func([]byte, T) bool) error {
return IterAllFnc[T](v.sg(ctx), v.ps, fn)
func (v *kvStoreWrapper[T]) Iterate(ctx types.Context, fn func([]byte, T) bool) error {
return IterAllFnc(v.sg(ctx), v.ps, fn)
}

func StoreFactory(storeKey corestore.KVStoreService, p string) func(ctx context.Context) storetypes.KVStore {
return func(ctx context.Context) storetypes.KVStore {
s := runtime.KVStoreAdapter(storeKey.OpenKVStore(ctx))
return prefix.NewStore(s, []byte(p))
}
}
25 changes: 8 additions & 17 deletions x/metrix/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ import (
corestore "cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/math"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/runtime"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/gogoproto/proto"
keeperutil "github.com/palomachain/paloma/util/keeper"
"github.com/palomachain/paloma/util/liblog"
"github.com/palomachain/paloma/util/palomath"
Expand Down Expand Up @@ -56,9 +54,9 @@ type (
slashing types.SlashingKeeper
staking types.StakingKeeper

metrics *keeperutil.KVStoreWrapper[*types.ValidatorMetrics]
history *keeperutil.KVStoreWrapper[*types.ValidatorHistory]
messageNonceCache *keeperutil.KVStoreWrapper[*types.HistoricRelayData]
metrics keeperutil.KVStoreWrapper[*types.ValidatorMetrics]
history keeperutil.KVStoreWrapper[*types.ValidatorHistory]
messageNonceCache keeperutil.KVStoreWrapper[*types.HistoricRelayData]
AddressCodec address.Codec
}
)
Expand All @@ -81,9 +79,9 @@ func NewKeeper(
paramstore: ps,
slashing: slashing,
staking: staking,
metrics: keeperutil.NewKvStoreWrapper[*types.ValidatorMetrics](storeFactory(storeKey, types.MetricsStorePrefix), cdc),
history: keeperutil.NewKvStoreWrapper[*types.ValidatorHistory](storeFactory(storeKey, types.HistoryStorePrefix), cdc),
messageNonceCache: keeperutil.NewKvStoreWrapper[*types.HistoricRelayData](storeFactory(storeKey, types.MessageNonceCacheStorePrefix), cdc),
metrics: keeperutil.NewKvStoreWrapper[*types.ValidatorMetrics](keeperutil.StoreFactory(storeKey, types.MetricsStorePrefix), cdc),
history: keeperutil.NewKvStoreWrapper[*types.ValidatorHistory](keeperutil.StoreFactory(storeKey, types.HistoryStorePrefix), cdc),
messageNonceCache: keeperutil.NewKvStoreWrapper[*types.HistoricRelayData](keeperutil.StoreFactory(storeKey, types.MessageNonceCacheStorePrefix), cdc),
AddressCodec: addressCodec,
}
}
Expand Down Expand Up @@ -478,13 +476,6 @@ func (k Keeper) tryUpdateRecord(ctx context.Context, valAddr sdk.ValAddress, pat
return nil
}

func storeFactory(storeKey corestore.KVStoreService, p string) func(ctx context.Context) storetypes.KVStore {
return func(ctx context.Context) storetypes.KVStore {
s := runtime.KVStoreAdapter(storeKey.OpenKVStore(ctx))
return prefix.NewStore(s, types.KeyPrefix(p))
}
}

func calculateUptime(window, missed int64) math.LegacyDec {
if window < 1 || missed < 0 || missed > window {
return math.LegacyNewDec(0)
Expand All @@ -498,7 +489,7 @@ func calculateUptime(window, missed int64) math.LegacyDec {
return palomath.BigIntDiv(diff, w)
}

func getFromStore[T codec.ProtoMarshaler](ctx context.Context, store *keeperutil.KVStoreWrapper[T], key keeperutil.Byter) (T, error) {
func getFromStore[T proto.Message](ctx context.Context, store keeperutil.KVStoreWrapper[T], key keeperutil.Byter) (T, error) {
var empty T
sdkCtx := sdk.UnwrapSDKContext(ctx)
data, err := store.Get(sdkCtx, key)
Expand Down
4 changes: 0 additions & 4 deletions x/metrix/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,3 @@ func (m CacheKey) Bytes() []byte { return []byte(m) }
type Key []byte

func (k Key) Bytes() []byte { return k }

func KeyPrefix(p string) []byte {
return []byte(p)
}
1 change: 1 addition & 0 deletions x/treasury/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command {

cmd.AddCommand(CmdQueryParams())
cmd.AddCommand(CmdGetFees())
cmd.AddCommand(CmdGetRelayerFee())

return cmd
}
Loading

0 comments on commit 4ff05b3

Please sign in to comment.