diff --git a/proto/lavanet/lava/rewards/genesis.proto b/proto/lavanet/lava/rewards/genesis.proto index 90d8e9f533..85fc3283a3 100644 --- a/proto/lavanet/lava/rewards/genesis.proto +++ b/proto/lavanet/lava/rewards/genesis.proto @@ -20,5 +20,6 @@ message GenesisState { cosmos.base.v1beta1.Coin min_iprpc_cost = 5 [(gogoproto.nullable) = false]; repeated IprpcReward iprpc_rewards = 6 [(gogoproto.nullable) = false]; uint64 iprpc_rewards_current = 7; + repeated PendingIbcIprpcFund pending_ibc_iprpc_funds = 8 [(gogoproto.nullable) = false]; // this line is used by starport scaffolding # genesis/proto/state } \ No newline at end of file diff --git a/proto/lavanet/lava/rewards/iprpc.proto b/proto/lavanet/lava/rewards/iprpc.proto index 8e5733ac19..7c2d0f135b 100644 --- a/proto/lavanet/lava/rewards/iprpc.proto +++ b/proto/lavanet/lava/rewards/iprpc.proto @@ -23,4 +23,13 @@ message IprpcMemo { string creator = 1; string spec = 2; uint64 duration = 3; // Iprpc fund period in months +} + +message PendingIbcIprpcFund { + uint64 index = 1; // unique index + string creator = 2; + string spec = 3; + uint64 duration = 4; + cosmos.base.v1beta1.Coin fund = 5 [(gogoproto.nullable) = false]; + uint64 expiry = 6; // expiry timestamp } \ No newline at end of file diff --git a/proto/lavanet/lava/rewards/params.proto b/proto/lavanet/lava/rewards/params.proto index f2107fc39a..03c0217de8 100644 --- a/proto/lavanet/lava/rewards/params.proto +++ b/proto/lavanet/lava/rewards/params.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package lavanet.lava.rewards; import "gogoproto/gogo.proto"; - +import "google/protobuf/duration.proto"; option go_package = "github.com/lavanet/lava/x/rewards/types"; // Params defines the parameters for the module. @@ -40,4 +40,10 @@ message Params { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + + google.protobuf.Duration ibc_iprpc_expiration = 7 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"ibc_iprpc_expiration\"" + ]; } \ No newline at end of file diff --git a/proto/lavanet/lava/rewards/query.proto b/proto/lavanet/lava/rewards/query.proto index d8ba5a3c33..b63484b82e 100644 --- a/proto/lavanet/lava/rewards/query.proto +++ b/proto/lavanet/lava/rewards/query.proto @@ -47,6 +47,11 @@ service Query { rpc IprpcSpecReward(QueryIprpcSpecRewardRequest) returns (QueryIprpcSpecRewardResponse) { option (google.api.http).get = "/lavanet/lava/rewards/iprpc_spec_reward/{spec}"; } + + // PendingIbcIprpcFunds queries for a spec's IPRPC reward + rpc PendingIbcIprpcFunds(QueryPendingIbcIprpcFundsRequest) returns (QueryPendingIbcIprpcFundsResponse) { + option (google.api.http).get = "/lavanet/lava/rewards/pending_ibc_iprpc_funds/{filter}"; + } // this line is used by starport scaffolding # 2 } @@ -134,4 +139,19 @@ message QueryIprpcSpecRewardResponse { uint64 current_month_id = 2; } +// QueryPendingIbcIprpcFundsRequest is request type for the Query/PendingIbcIprpcFund RPC method. +message QueryPendingIbcIprpcFundsRequest { + string filter = 1; // can be an uint64 index, creator name and spec name +} + +message PendingIbcIprpcFundInfo { + PendingIbcIprpcFund pending_ibc_iprpc_fund = 1 [(gogoproto.nullable) = false]; + cosmos.base.v1beta1.Coin cost = 2 [(gogoproto.nullable) = false]; // equals to min_iprpc_cost * duration +} + +// QueryPendingIbcIprpcFundsResponse is response type for the Query/PendingIbcIprpcFund RPC method. +message QueryPendingIbcIprpcFundsResponse { + repeated PendingIbcIprpcFundInfo pending_ibc_iprpc_funds_info = 1 [(gogoproto.nullable) = false]; +} + // this line is used by starport scaffolding # 3 \ No newline at end of file diff --git a/proto/lavanet/lava/rewards/tx.proto b/proto/lavanet/lava/rewards/tx.proto index 1e4c23daee..fc3f34b574 100644 --- a/proto/lavanet/lava/rewards/tx.proto +++ b/proto/lavanet/lava/rewards/tx.proto @@ -12,6 +12,7 @@ option go_package = "github.com/lavanet/lava/x/rewards/types"; service Msg { rpc SetIprpcData(MsgSetIprpcData) returns (MsgSetIprpcDataResponse); rpc FundIprpc(MsgFundIprpc) returns (MsgFundIprpcResponse); + rpc CoverIbcIprpcFundCost(MsgCoverIbcIprpcFundCost) returns (MsgCoverIbcIprpcFundCostResponse); // this line is used by starport scaffolding # proto/tx/rpc } @@ -37,4 +38,12 @@ message MsgFundIprpc { message MsgFundIprpcResponse { } +message MsgCoverIbcIprpcFundCost { + string creator = 1; + uint64 index = 2; // PendingIbcIprpcFund index +} + +message MsgCoverIbcIprpcFundCostResponse { +} + // this line is used by starport scaffolding # proto/tx/message \ No newline at end of file diff --git a/scripts/test/cli_test.sh b/scripts/test/cli_test.sh index 9062f12217..0d6aab715f 100755 --- a/scripts/test/cli_test.sh +++ b/scripts/test/cli_test.sh @@ -186,6 +186,7 @@ trace lavad q rewards show-iprpc-data > /dev/null trace lavad q rewards iprpc-provider-reward > /dev/null trace lavad q rewards iprpc-spec-reward > /dev/null trace lavad q rewards provider-reward >/dev/null +trace lavad q rewards pending-ibc-iprpc-funds > /dev/null echo "Testing rewards tx commands" trace lavad tx rewards fund-iprpc ETH1 4 100000ulava --from alice >/dev/null diff --git a/testutil/common/tester.go b/testutil/common/tester.go index f00b67e9cc..0098d3c51d 100644 --- a/testutil/common/tester.go +++ b/testutil/common/tester.go @@ -14,6 +14,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" testkeeper "github.com/lavanet/lava/testutil/keeper" "github.com/lavanet/lava/utils" "github.com/lavanet/lava/utils/lavaslices" @@ -25,6 +26,7 @@ import ( pairingtypes "github.com/lavanet/lava/x/pairing/types" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" + "github.com/lavanet/lava/x/rewards" rewardstypes "github.com/lavanet/lava/x/rewards/types" spectypes "github.com/lavanet/lava/x/spec/types" subscriptiontypes "github.com/lavanet/lava/x/subscription/types" @@ -34,10 +36,11 @@ import ( type Tester struct { T *testing.T - GoCtx context.Context - Ctx sdk.Context - Servers *testkeeper.Servers - Keepers *testkeeper.Keepers + GoCtx context.Context + Ctx sdk.Context + Servers *testkeeper.Servers + Keepers *testkeeper.Keepers + IbcTransfer porttypes.Middleware accounts map[string]sigs.Account plans map[string]planstypes.Plan @@ -75,11 +78,12 @@ func NewTesterRaw(t *testing.T) *Tester { servers, keepers, GoCtx := testkeeper.InitAllKeepers(t) ts := &Tester{ - T: t, - GoCtx: GoCtx, - Ctx: sdk.UnwrapSDKContext(GoCtx), - Servers: servers, - Keepers: keepers, + T: t, + GoCtx: GoCtx, + Ctx: sdk.UnwrapSDKContext(GoCtx), + Servers: servers, + Keepers: keepers, + IbcTransfer: rewards.NewIBCMiddleware(keepers.IbcTransfer, keepers.Rewards), accounts: make(map[string]sigs.Account), plans: make(map[string]planstypes.Plan), @@ -699,6 +703,11 @@ func (ts *Tester) TxRewardsFundIprpc(creator string, spec string, duration uint6 return ts.Servers.RewardsServer.FundIprpc(ts.GoCtx, msg) } +func (ts *Tester) TxRewardsCoverIbcIprpcFundCost(creator string, index uint64) (*rewardstypes.MsgCoverIbcIprpcFundCostResponse, error) { + msg := rewardstypes.NewMsgCoverIbcIprpcFundCost(creator, index) + return ts.Servers.RewardsServer.CoverIbcIprpcFundCost(ts.GoCtx, msg) +} + // TxCreateValidator: implement 'tx staking createvalidator' and bond its tokens func (ts *Tester) TxCreateValidator(validator sigs.Account, amount math.Int) { consensusPowerTokens := ts.Keepers.StakingKeeper.TokensFromConsensusPower(ts.Ctx, 1) @@ -969,6 +978,7 @@ func (ts *Tester) QueryRewardsShowIprpcData() (*rewardstypes.QueryShowIprpcDataR return ts.Keepers.Rewards.ShowIprpcData(ts.GoCtx, msg) } +// QueryRewardsShowIprpcData implements 'q rewards iprpc-provider-reward-estimation' func (ts *Tester) QueryRewardsIprpcProviderRewardEstimation(provider string) (*rewardstypes.QueryIprpcProviderRewardEstimationResponse, error) { msg := &rewardstypes.QueryIprpcProviderRewardEstimationRequest{ Provider: provider, @@ -976,6 +986,7 @@ func (ts *Tester) QueryRewardsIprpcProviderRewardEstimation(provider string) (*r return ts.Keepers.Rewards.IprpcProviderRewardEstimation(ts.GoCtx, msg) } +// QueryRewardsShowIprpcData implements 'q rewards iprpc-spec-reward' func (ts *Tester) QueryRewardsIprpcSpecReward(spec string) (*rewardstypes.QueryIprpcSpecRewardResponse, error) { msg := &rewardstypes.QueryIprpcSpecRewardRequest{ Spec: spec, @@ -983,6 +994,14 @@ func (ts *Tester) QueryRewardsIprpcSpecReward(spec string) (*rewardstypes.QueryI return ts.Keepers.Rewards.IprpcSpecReward(ts.GoCtx, msg) } +// QueryRewardsShowIprpcData implements 'q rewards pending-ibc-iprpc-funds' +func (ts *Tester) QueryRewardsPendingIbcIprpcFunds(filter string) (*rewardstypes.QueryPendingIbcIprpcFundsResponse, error) { + msg := &rewardstypes.QueryPendingIbcIprpcFundsRequest{ + Filter: filter, + } + return ts.Keepers.Rewards.PendingIbcIprpcFunds(ts.GoCtx, msg) +} + // block/epoch helpers // QueryRewardsProviderReward implements 'q rewards provider-reward' func (ts *Tester) QueryRewardsProviderReward(chainID string, provider string) (*rewardstypes.QueryProviderRewardResponse, error) { diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 9de45e6ef9..f93533bd4d 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -31,6 +31,7 @@ import ( slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" commonconsts "github.com/lavanet/lava/testutil/common/consts" "github.com/lavanet/lava/utils/sigs" conflictkeeper "github.com/lavanet/lava/x/conflict/keeper" @@ -95,6 +96,7 @@ type Keepers struct { SlashingKeeper slashingkeeper.Keeper Rewards rewardskeeper.Keeper Distribution distributionkeeper.Keeper + IbcTransfer mockIbcTransferKeeper } type Servers struct { @@ -111,6 +113,7 @@ type Servers struct { SlashingServer slashingtypes.MsgServer RewardsServer rewardstypes.MsgServer DistributionServer distributiontypes.MsgServer + IbcTransferServer ibctransfertypes.MsgServer } type KeeperBeginBlockerWithRequest interface { @@ -142,6 +145,9 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { distributionStoreKey := sdk.NewKVStoreKey(distributiontypes.StoreKey) stateStore.MountStoreWithDB(distributionStoreKey, storetypes.StoreTypeIAVL, db) + ibctransferStoreKey := sdk.NewKVStoreKey(ibctransfertypes.StoreKey) + stateStore.MountStoreWithDB(ibctransferStoreKey, storetypes.StoreTypeIAVL, db) + stakingStoreKey := sdk.NewKVStoreKey(stakingtypes.StoreKey) stateStore.MountStoreWithDB(stakingStoreKey, storetypes.StoreTypeIAVL, db) @@ -217,6 +223,7 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { paramsKeeper.Subspace(rewardstypes.ModuleName) paramsKeeper.Subspace(distributiontypes.ModuleName) paramsKeeper.Subspace(dualstakingtypes.ModuleName) + paramsKeeper.Subspace(ibctransfertypes.ModuleName) // paramsKeeper.Subspace(conflicttypes.ModuleName) //TODO... epochparamsSubspace, _ := paramsKeeper.GetSubspace(epochstoragetypes.ModuleName) @@ -245,11 +252,13 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { ) downtimeParamsSubspace, _ := paramsKeeper.GetSubspace(downtimemoduletypes.ModuleName) + ibctransferparamsSubspace, _ := paramsKeeper.GetSubspace(ibctransfertypes.ModuleName) ks := Keepers{} ks.TimerStoreKeeper = timerstorekeeper.NewKeeper(cdc) ks.AccountKeeper = mockAccountKeeper{} ks.BankKeeper = mockBankKeeper{} + ks.IbcTransfer = NewMockIbcTransferKeeper(ibctransferStoreKey, cdc, ibctransferparamsSubspace, ks.AccountKeeper, ks.BankKeeper) init_balance() ks.StakingKeeper = *stakingkeeper.NewKeeper(cdc, stakingStoreKey, ks.AccountKeeper, ks.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String()) ks.Distribution = distributionkeeper.NewKeeper(cdc, distributionStoreKey, ks.AccountKeeper, ks.BankKeeper, ks.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String()) diff --git a/testutil/keeper/mock_keepers.go b/testutil/keeper/mock_keepers.go index 535c25c180..53c84f0630 100644 --- a/testutil/keeper/mock_keepers.go +++ b/testutil/keeper/mock_keepers.go @@ -4,9 +4,17 @@ import ( "fmt" "time" + "cosmossdk.io/math" tenderminttypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v7/modules/core/exported" ) // account keeper mock @@ -156,6 +164,101 @@ func (k mockBankKeeper) BlockedAddr(addr sdk.AccAddress) bool { return false } +// Mock IBC transfer keeper +type mockIbcTransferKeeper struct { + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + paramSpace paramstypes.Subspace + authKeeper mockAccountKeeper + bankKeeper mockBankKeeper +} + +const ( + MockSrcPort = "src" + MockSrcChannel = "srcc" + MockDestPort = "dest" + MockDestChannel = "destc" +) + +func NewMockIbcTransferKeeper(storeKey storetypes.StoreKey, cdc codec.BinaryCodec, paramSpace paramstypes.Subspace, authKeeper mockAccountKeeper, bankKeeper mockBankKeeper) mockIbcTransferKeeper { + return mockIbcTransferKeeper{ + storeKey: storeKey, + cdc: cdc, + paramSpace: paramSpace, + authKeeper: authKeeper, + bankKeeper: bankKeeper, + } +} + +func (k mockIbcTransferKeeper) OnChanOpenInit(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) { + return "", nil +} + +func (k mockIbcTransferKeeper) OnChanOpenTry(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string) (version string, err error) { + return "", nil +} + +func (k mockIbcTransferKeeper) OnChanOpenAck(ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string) error { + return nil +} + +func (k mockIbcTransferKeeper) OnChanOpenConfirm(ctx sdk.Context, portID, channelID string) error { + return nil +} + +func (k mockIbcTransferKeeper) OnChanCloseInit(ctx sdk.Context, portID, channelID string) error { + return nil +} + +func (k mockIbcTransferKeeper) OnChanCloseConfirm(ctx sdk.Context, portID, channelID string) error { + return nil +} + +func (k mockIbcTransferKeeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) exported.Acknowledgement { + // get data from packet + var data ibctransfertypes.FungibleTokenPacketData + if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + + // parse data + senderAcc, err := sdk.AccAddressFromBech32(data.Sender) + if err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + receiverAcc, err := sdk.AccAddressFromBech32(data.Receiver) + if err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + amount, ok := math.NewIntFromString(data.Amount) + if !ok { + return channeltypes.NewErrorAcknowledgement(fmt.Errorf("invalid amount in transfer data: %s", data.Amount)) + } + + // sub balance from sender in original denom, add balance to receiver (on other chain) with IBC Denom + coins := sdk.NewCoins(sdk.NewCoin(data.Denom, amount)) + err = k.bankKeeper.SubFromBalance(senderAcc, coins) + if err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + ibcCoins := sdk.NewCoins(ibctransfertypes.GetTransferCoin(packet.DestinationPort, packet.DestinationChannel, data.Denom, amount)) + err = k.bankKeeper.AddToBalance(receiverAcc, ibcCoins) + if err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + + return channeltypes.NewResultAcknowledgement([]byte{byte(1)}) +} + +func (k mockIbcTransferKeeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { + return nil +} + +func (k mockIbcTransferKeeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { + return nil +} + +// Mock BlockStore type MockBlockStore struct { height int64 blockHistory map[int64]*tenderminttypes.Block diff --git a/utils/maps/maps.go b/utils/maps/maps.go index 35ed70e593..5a0d180bb9 100644 --- a/utils/maps/maps.go +++ b/utils/maps/maps.go @@ -1,5 +1,7 @@ package maps +import "encoding/binary" + func FindLargestIntValueInMap[K comparable](myMap map[K]int) (K, int) { var maxVal int var maxKey K @@ -15,3 +17,15 @@ func FindLargestIntValueInMap[K comparable](myMap map[K]int) (K, int) { return maxKey, maxVal } + +// GetIDBytes returns the byte representation of the uint64 ID +func GetIDBytes(id uint64) []byte { + bz := make([]byte, 8) + binary.BigEndian.PutUint64(bz, id) + return bz +} + +// GetIDFromBytes returns ID in uint64 format from a byte array +func GetIDFromBytes(bz []byte) uint64 { + return binary.BigEndian.Uint64(bz) +} diff --git a/x/rewards/README.md b/x/rewards/README.md index 72f717f9b8..9dcd210622 100644 --- a/x/rewards/README.md +++ b/x/rewards/README.md @@ -18,11 +18,15 @@ Please note that this module replaces Cosmos SDK's mint module, which is typical * [Validators Rewards Pool](#validators-rewards-pool) * [Providers Rewards Pool](#providers-rewards-pool) * [IPRPC](#iprpc) + * [IPRPC over IBC](#iprpc-over-ibc) * [Parameters](#parameters) * [MinBondedTarget](#minbondedtarget) * [MaxBondedTarget](#maxbondedtarget) * [LowFactor](#lowfactor) * [LeftOverBurnRate](#leftoverburnrate) + * [MaxRewardsBoost](#maxrewardsboost) + * [ValidatorsSubscriptionParticipation](#validatorssubscriptionparticipation) + * [IbcIprpcExpiration](#ibciprpcexpiration) * [Queries](#queries) * [Transactions](#transactions) * [Proposals](#proposals) @@ -124,6 +128,26 @@ Users have the freedom to fund the pool with any token of their choice, for any In order to fund the IPRPC pool, the user's funds must cover the monthly minimum IPRPC cost, a parameter determined by governance. This minimum IPRPC cost will be subtracted from the monthly emission. +#### IPRPC over IBC + +To ease the funding process of funding the IPRPC pool, users can send an `ibc-transfer` transaction to fund the IPRPC pool directly from the source chain. For example, using IPRPC over IBC allows funding the IPRPC pool by sending a single `ibc-transfer` to an Osmosis node. + +To make the `ibc-transfer` transaction fund the IPRPC pool, it must contain a custom memo with the following format: + +```json +{ + "iprpc": { + "creator": "alice", + "spec": "ETH1", + "duration": "3" + } +} +``` + +The creator field can be any name, the spec field must be an on-chain spec ID, and the duration should be the funding period (in months). Users can use the `generate-ibc-iprpc-tx` helper command with the `--memo-only` flag to generate a valid IPRPC memo. If the flag is not included, this command creates a valid `ibc-transfer` transaction JSON with a custom memo. The only remaining step is to sign and send the transaction. + +As mentioned above, funding the IPRPC pool requires a fee derived from the monthly minimum IPRPC cost. Because of that, all IPRPC over IBC requests are considered a pending IPRPC fund request until the fee is paid. To view the current pending requests, users can use the `pending-ibc-iprpc-funds` query and cover the minimum cost using the `cover-ibc-iprpc-fund-cost` transaction. The expiration of pending IPRPC fund requests is dictated by the `IbcIprpcExpiration`, which equals the expiration period in months. + ## Parameters The rewards module contains the following parameters: @@ -136,6 +160,7 @@ The rewards module contains the following parameters: | LeftOverBurnRate | math.LegacyDec | 1 | | MaxRewardsBoost | uint64 | 5 | | ValidatorsSubscriptionParticipation | math.LegacyDec | 0.05 | +| IbcIprpcExpiration | uint64 | 3 | ### MinBondedTarget @@ -176,6 +201,10 @@ MaxRewardsBoost is a multiplier that determines the maximum bonus for provider r ValidatorsSubscriptionParticipation is used to calculate the providers rewards participation fees. +### IbcIprpcExpiration + +IbcIprpcExpiration determines the pending IPRPC over IBC fund requests expiration in months. + ## Queries The rewards module supports the following queries: @@ -188,6 +217,8 @@ The rewards module supports the following queries: | `show-iprpc-data` | none | shows the IPRPC data that includes the minimum IPRPC cost and a list of IPRPC eligible subscriptions | | `iprpc-provider-reward` | provider (string) | shows the estimated IPRPC rewards for a specific provider (relative to its serviced CU) for the upcoming monthly emission | | `iprpc-spec-rewards` | spec (string, optional) | shows a specific spec's IPRPC rewards (for the entire period). If no spec is given, all IPRPC rewards are shown | +| `generate-ibc-iprpc-tx` | spec (string), duration (uint64, in months), amount (sdk.Coin, optional), src-port (string, optional), src-channel (string, optional), --from (string, mandatory), --node (string, mandatory), --memo-only (optional) | generates an `ibc-transfer` transaction JSON that can be used to fund the IPRPC pool over IBC. To generate only the custom memo that triggers the IPRPC funding, use the `--memo-only` flag. | +| `pending-ibc-iprpc-funds` | filter (string, optional) | Lists the pending IPRPC over IBC fund requests. Use the optional filter to filter by index, creator, or spec. Each entry is shown with the minimum IPRPC cost that needs to be paid to apply it. | Note, use the provider's operator address for the `iprpc-provider-reward` query. For more information on the operator and vault addresses see the pairing module's [README.md](../pairing/README.md). @@ -200,6 +231,7 @@ The rewards module supports the following transactions: | Transaction | Arguments | What it does | | ---------- | --------------- | ----------------------------------------------| | `fund-iprpc` | spec (string), duration (uint64, in months), coins (sdk.Coins, for example: `100ulava,50ibctoken`) | fund the IPRPC pool to a specific spec with ulava or IBC wrapped tokens. The tokens will be vested for `duration` months. | +| `cover-ibc-iprpc-fund-cost` | index (uint64) | cover the costs of a pending IPRPC over IBC fund request by index. The required minimum IPRPC cost is automatically paid by the transaction sender. | Please note that the coins specified in the `fund-iprpc` transaction is the monthly emission fund. For instance, if you specify a fund of 100ulava for a duration of three months, providers will receive 100ulava each month, not 33ulava. @@ -229,4 +261,7 @@ The rewards module has the following events: | `iprpc_pool_emmission` | a successful distribution of IPRPC bonus rewards | | `set_iprpc_data` | a successful setting of IPRPC data | | `fund_iprpc` | a successful funding of the IPRPC pool | -| `transfer_iprpc_reward_to_next_month` | a successful transfer of the current month's IPRPC reward to the next month. Happens when there are no providers eligible for IPRPC rewards in the current month | \ No newline at end of file +| `transfer_iprpc_reward_to_next_month` | a successful transfer of the current month's IPRPC reward to the next month. Happens when there are no providers eligible for IPRPC rewards in the current month | +| `pending_ibc_iprpc_fund_created` | a successful IPRPC over IBC fund request which creates a pending fund request entry on-chain | +| `cover_ibc_iprpc_fund_cost` | a successful cost coverage of a pending IPRPC fund request that applies the request and funds the IPRPC pool | +| `expired_pending_ibc_iprpc_fund_removed` | a successful removal of an expired pending IPRPC fund request | \ No newline at end of file diff --git a/x/rewards/client/cli/query.go b/x/rewards/client/cli/query.go index bb32aa4781..49379a4e1e 100644 --- a/x/rewards/client/cli/query.go +++ b/x/rewards/client/cli/query.go @@ -31,6 +31,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdQueryIprpcProviderRewardEstimation()) cmd.AddCommand(CmdQueryIprpcSpecReward()) cmd.AddCommand(CmdQueryProviderReward()) + cmd.AddCommand(CmdQueryPendingIbcIprpcFunds()) // this line is used by starport scaffolding # 1 return cmd diff --git a/x/rewards/client/cli/query_pending_ibc_iprpc_funds.go b/x/rewards/client/cli/query_pending_ibc_iprpc_funds.go new file mode 100644 index 0000000000..fac9f25d2b --- /dev/null +++ b/x/rewards/client/cli/query_pending_ibc_iprpc_funds.go @@ -0,0 +1,51 @@ +package cli + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/lavanet/lava/x/rewards/types" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdQueryPendingIbcIprpcFunds() *cobra.Command { + cmd := &cobra.Command{ + Use: "pending-ibc-iprpc-funds [filter: index/creator/spec]", + Short: "Query for pending IBC IPRPC funds", + Long: `Query for pending IBC IPRPC funds. Use the optional filter argument to get a specific fund (using its index), + funds of a specific creator or funds for a specific spec. Each fund has its own cost which is derived from the minimum IPRPC + cost for funding the IPRPC pool, multiplied by the fund's duration. To cover the cost and apply the pending fund, use + the "lavad tx rewards cover-ibc-iprpc-cost" TX`, + Args: cobra.RangeArgs(0, 1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + filter := "" + if len(args) > 0 { + filter = args[0] + } + + params := &types.QueryPendingIbcIprpcFundsRequest{ + Filter: filter, + } + + res, err := queryClient.PendingIbcIprpcFunds(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/rewards/client/cli/tx.go b/x/rewards/client/cli/tx.go index c47ae629e6..fb52ce5c94 100644 --- a/x/rewards/client/cli/tx.go +++ b/x/rewards/client/cli/tx.go @@ -42,6 +42,7 @@ func GetTxCmd() *cobra.Command { } cmd.AddCommand(CmdFundIprpc()) + cmd.AddCommand(CmdCoverIbcIprpcFundCost()) cmd.AddCommand(CmdTxSubmitIbcIprpcProposal()) // this line is used by starport scaffolding # 1 diff --git a/x/rewards/client/cli/tx_cover_ibc_iprpc_fund_cost.go b/x/rewards/client/cli/tx_cover_ibc_iprpc_fund_cost.go new file mode 100644 index 0000000000..d94f9bfad1 --- /dev/null +++ b/x/rewards/client/cli/tx_cover_ibc_iprpc_fund_cost.go @@ -0,0 +1,49 @@ +package cli + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/lavanet/lava/x/rewards/types" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdCoverIbcIprpcFundCost() *cobra.Command { + cmd := &cobra.Command{ + Use: "cover-ibc-iprpc-fund-cost [index] --from ", + Short: "Apply a pending IBC IPRPC fund by paying its mandatory minimum cost of funding the IPRPC pool", + Long: `Apply a pending IBC IPRPC fund by paying its mandatory minimum cost of funding the IPRPC pool. Find your desired + fund's index and cost by using the query pending-ibc-iprpc-funds. By sending this message, the full cost of the fund will be + paid automatically. Then, the pending fund's coins will be sent to the IPRPC pool.`, + Example: `lavad tx rewards cover-ibc-iprpc-fund-cost 4 --from alice`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + index, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + msg := types.NewMsgCoverIbcIprpcFundCost( + clientCtx.GetFromAddress().String(), + index, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + cmd.MarkFlagRequired(flags.FlagFrom) + return cmd +} diff --git a/x/rewards/genesis.go b/x/rewards/genesis.go index bfe82663a5..da8ee0e26a 100644 --- a/x/rewards/genesis.go +++ b/x/rewards/genesis.go @@ -24,6 +24,9 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) } k.SetIprpcRewardsCurrentId(ctx, genState.IprpcRewardsCurrent) k.SetIprpcData(ctx, genState.MinIprpcCost, genState.IprpcSubscriptions) + for _, pendingIprpcFund := range genState.PendingIbcIprpcFunds { + k.SetPendingIbcIprpcFund(ctx, pendingIprpcFund) + } } // ExportGenesis returns the capability module's exported genesis. @@ -36,6 +39,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis.MinIprpcCost = k.GetMinIprpcCost(ctx) genesis.IprpcRewards = k.GetAllIprpcReward(ctx) genesis.IprpcRewardsCurrent = k.GetIprpcRewardsCurrentId(ctx) + genesis.PendingIbcIprpcFunds = k.GetAllPendingIbcIprpcFund(ctx) // this line is used by starport scaffolding # genesis/module/export return genesis diff --git a/x/rewards/genesis_test.go b/x/rewards/genesis_test.go index cd7e508195..83b2507d99 100644 --- a/x/rewards/genesis_test.go +++ b/x/rewards/genesis_test.go @@ -3,6 +3,7 @@ package rewards import ( "testing" + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" testkeeper "github.com/lavanet/lava/testutil/keeper" "github.com/lavanet/lava/testutil/nullify" @@ -25,6 +26,24 @@ func TestGenesis(t *testing.T) { }, }, IprpcRewardsCurrent: 2, + PendingIbcIprpcFunds: []types.PendingIbcIprpcFund{ + { + Index: 1, + Creator: "1", + Spec: "s1", + Duration: 1, + Fund: sdk.NewCoin("denom", math.OneInt()), + Expiry: 1, + }, + { + Index: 2, + Creator: "2", + Spec: "s2", + Duration: 2, + Fund: sdk.NewCoin("denom", math.OneInt().AddRaw(1)), + Expiry: 2, + }, + }, // this line is used by starport scaffolding # genesis/test/state } @@ -40,5 +59,6 @@ func TestGenesis(t *testing.T) { require.ElementsMatch(t, genesisState.IprpcRewards, got.IprpcRewards) require.Equal(t, genesisState.IprpcRewardsCurrent, got.IprpcRewardsCurrent) + require.ElementsMatch(t, genesisState.PendingIbcIprpcFunds, got.PendingIbcIprpcFunds) // this line is used by starport scaffolding # genesis/test/assert } diff --git a/x/rewards/ibc_middleware.go b/x/rewards/ibc_middleware.go index 6d24fb4641..59e9a69402 100644 --- a/x/rewards/ibc_middleware.go +++ b/x/rewards/ibc_middleware.go @@ -3,6 +3,7 @@ package rewards import ( "errors" "fmt" + "strconv" sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" @@ -109,6 +110,23 @@ func (im IBCMiddleware) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet return channeltypes.NewErrorAcknowledgement(err) } + // get the IBC tokens that were transferred to the IbcIprpcReceiverAddress + amount, ok := sdk.NewIntFromString(data.Amount) + if !ok { + detailedErr := utils.LavaFormatError("rewards module IBC middleware processing failed", fmt.Errorf("invalid amount in ibc-transfer data"), + utils.LogAttr("data", data), + ) + return channeltypes.NewErrorAcknowledgement(detailedErr) + } + ibcTokens := transfertypes.GetTransferCoin(packet.DestinationPort, packet.DestinationChannel, data.Denom, amount) + + // set pending IPRPC over IBC requests on-chain + // leftovers are the tokens that were not registered in the PendingIbcIprpcFund objects due to int division + piif, leftovers, err := im.keeper.NewPendingIbcIprpcFund(ctx, memo.Creator, memo.Spec, memo.Duration, ibcTokens) + if err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + // send the IBC transfer to get the tokens ack := im.sendIbcTransfer(ctx, packet, relayer, data.Sender, types.IbcIprpcReceiverAddress().String()) if ack == nil || !ack.Success() { @@ -117,31 +135,38 @@ func (im IBCMiddleware) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet // on the IBC transfer module's side (which returns a non-nil ack when executed without errors). Asynchronous // processing can be queued processing of packets, interacting with external APIs and more. These can cause // delays in the IBC-transfer's processing which will make the module return a nil ack until the processing is done. - // Asyncronous acks are handled in the WriteAcknowledgement middleware method. + im.keeper.RemovePendingIbcIprpcFund(ctx, piif.Index) return ack } - // get the IBC tokens that were transferred to the IbcIprpcReceiverAddress - amount, ok := sdk.NewIntFromString(data.Amount) - if !ok { - detailedErr := utils.LavaFormatError("rewards module IBC middleware processing failed", fmt.Errorf("invalid amount in ibc-transfer data"), - utils.LogAttr("data", data), + // send the IBC tokens from IbcIprpcReceiver to PendingIprpcPool + err = im.keeper.SendIbcIprpcReceiverTokensToPendingIprpcPool(ctx, ibcTokens) + if err != nil { + detailedErr := utils.LavaFormatError("sending token from IbcIprpcReceiver to the PendingIprpcPool failed", err, + utils.LogAttr("sender", data.Sender), ) return channeltypes.NewErrorAcknowledgement(detailedErr) } - ibcTokens := transfertypes.GetTransferCoin(packet.DestinationPort, packet.DestinationChannel, data.Denom, amount) - // send the IBC tokens from IbcIprpcReceiver to PendingIprpcPool - err = im.keeper.SendIbcIprpcReceiverTokensToPendingIprpcPool(ctx, ibcTokens) + // transfer the leftover IBC tokens to the community pool + err = im.keeper.FundCommunityPoolFromIbcIprpcReceiver(ctx, leftovers) if err != nil { - detailedErr := utils.LavaFormatError("sending token from IbcIprpcReceiver to the PendingIprpcPool failed", err, + detailedErr := utils.LavaFormatError("could not send leftover tokens from IbcIprpcReceiverAddress to community pool, tokens are locked in IbcIprpcReceiverAddress", err, + utils.LogAttr("amount", leftovers.String()), utils.LogAttr("sender", data.Sender), ) return channeltypes.NewErrorAcknowledgement(detailedErr) } - // TODO: define a PendingIbcIprpcFund store to keep track on pending requests. Also create an event that - // a new pending request has been created + // make event + utils.LogLavaEvent(ctx, im.keeper.Logger(ctx), types.NewPendingIbcIprpcFundEventName, map[string]string{ + "index": strconv.FormatUint(piif.Index, 10), + "creator": piif.Creator, + "spec": piif.Spec, + "duration": strconv.FormatUint(piif.Duration, 10), + "monthly_fund": piif.Fund.String(), + "expiry": strconv.FormatUint(piif.Expiry, 10), + }, "New pending IBC IPRPC fund was created successfully") return channeltypes.NewResultAcknowledgement([]byte{byte(1)}) } diff --git a/x/rewards/keeper/grpc_query_pending_ibc_iprpc_funds.go b/x/rewards/keeper/grpc_query_pending_ibc_iprpc_funds.go new file mode 100644 index 0000000000..b8be2d28d2 --- /dev/null +++ b/x/rewards/keeper/grpc_query_pending_ibc_iprpc_funds.go @@ -0,0 +1,63 @@ +package keeper + +import ( + "context" + "fmt" + "strconv" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/x/rewards/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (k Keeper) PendingIbcIprpcFunds(goCtx context.Context, req *types.QueryPendingIbcIprpcFundsRequest) (*types.QueryPendingIbcIprpcFundsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + piifs := []types.PendingIbcIprpcFund{} + infos := []types.PendingIbcIprpcFundInfo{} + ctx := sdk.UnwrapSDKContext(goCtx) + + // get the relevant PendingIbcIprpcFund objects by filter + if index, err := strconv.ParseUint(req.Filter, 10, 64); err == nil { + // index filter + piif, found := k.GetPendingIbcIprpcFund(ctx, index) + if !found { + return nil, fmt.Errorf("PendingIbcIprpcFund not found with index %d", index) + } + piifs = append(piifs, piif) + } else if _, found := k.specKeeper.GetSpec(ctx, req.Filter); found { + // spec filter + allPiifs := k.GetAllPendingIbcIprpcFund(ctx) + for _, piif := range allPiifs { + if piif.Spec == req.Filter { + piifs = append(piifs, piif) + } + } + } else if req.Filter != "" { + // creator filter + allPiifs := k.GetAllPendingIbcIprpcFund(ctx) + for _, piif := range allPiifs { + if piif.Creator == req.Filter { + piifs = append(piifs, piif) + } + } + } else { + // no filter + piifs = k.GetAllPendingIbcIprpcFund(ctx) + } + + // construct PendingIbcIprpcFundInfo list (calculate cost to apply) + if len(piifs) == 0 { + return nil, fmt.Errorf("PendingIbcIprpcFund not found with filter %s", req.Filter) + } + + for _, piif := range piifs { + cost := k.CalcPendingIbcIprpcFundMinCost(ctx, piif) + infos = append(infos, types.PendingIbcIprpcFundInfo{PendingIbcIprpcFund: piif, Cost: cost}) + } + + return &types.QueryPendingIbcIprpcFundsResponse{PendingIbcIprpcFundsInfo: infos}, nil +} diff --git a/x/rewards/keeper/helpers_test.go b/x/rewards/keeper/helpers_test.go index 3bfbbc0f75..b11bb47331 100644 --- a/x/rewards/keeper/helpers_test.go +++ b/x/rewards/keeper/helpers_test.go @@ -10,6 +10,8 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/lavanet/lava/testutil/common" testkeeper "github.com/lavanet/lava/testutil/keeper" "github.com/lavanet/lava/testutil/sample" @@ -36,6 +38,7 @@ var ( sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(1100)), sdk.NewCoin(ibcDenom, sdk.NewInt(500)), ) + mockSpec string = "mockspec" mockSpec2 string = "mock2" ) @@ -227,3 +230,43 @@ func (ts *tester) makeBondedRatioNonZero() { bondedRatio = ts.Keepers.StakingKeeper.BondedRatio(ts.Ctx) require.True(ts.T, bondedRatio.Equal(sdk.NewDecWithPrec(25, 2))) // according to "valInitBalance", bondedRatio should be 0.25 } + +func (ts *tester) SendIprpcOverIbcTransferPacket(sender sdk.AccAddress, amount sdk.Coin, duration uint64) { + // get the sender's and PendingIprpcPool before sending the packet + senderBalanceBefore := ts.Keepers.BankKeeper.GetBalance(ts.Ctx, sender, amount.Denom) + pendingIprpcPoolBalanceBefore := ts.Keepers.Rewards.TotalPoolTokens(ts.Ctx, rewardstypes.PendingIprpcPoolName) + + // create packet data + memo, err := rewardstypes.CreateIprpcMemo(sender.String(), mockSpec, duration) + require.NoError(ts.T, err) + data := transfertypes.NewFungibleTokenPacketData(amount.Denom, amount.Amount.String(), sender.String(), "dummy", memo) + marshelledData, err := transfertypes.ModuleCdc.MarshalJSON(&data) + require.NoError(ts.T, err) + + // create packet + packet := channeltypes.NewPacket(marshelledData, 0, testkeeper.MockSrcPort, testkeeper.MockSrcChannel, testkeeper.MockDestPort, testkeeper.MockDestChannel, clienttypes.ZeroHeight(), 1) + + // call OnRecvPacket + ack := ts.IbcTransfer.OnRecvPacket(ts.Ctx, packet, sample.AccAddressObject()) + if ack == nil || !ack.Success() { + require.FailNow(ts.T, "ibc transfer failed") + } + + // verify the sender's balance went down and the PendingIprpcPool balance went up + senderBalanceAfter := ts.Keepers.BankKeeper.GetBalance(ts.Ctx, sender, amount.Denom) + pendingIprpcPoolBalanceAfter := ts.Keepers.Rewards.TotalPoolTokens(ts.Ctx, rewardstypes.PendingIprpcPoolName) + + senderDiff := sdk.NewCoins(senderBalanceBefore.Sub(senderBalanceAfter)) + require.True(ts.T, senderDiff.IsEqual(sdk.NewCoins(amount))) + + // pending pool gets the funds after going through the IBC channel -> check balance with ibc denom (subtracting leftovers) + pendingIprpcPoolDiff := pendingIprpcPoolBalanceAfter.Sub(pendingIprpcPoolBalanceBefore...) + leftoversAmount := amount.Amount.ModRaw(int64(duration)) + ibcTokens := transfertypes.GetTransferCoin(packet.DestinationPort, packet.DestinationChannel, amount.Denom, amount.Amount) + expectedIbcSenderDiff := sdk.NewCoins(sdk.NewCoin(ibcTokens.Denom, ibcTokens.Amount.Sub(leftoversAmount))) + require.True(ts.T, expectedIbcSenderDiff.IsEqual(pendingIprpcPoolDiff)) +} + +func GetIbcCoins(amount sdk.Coin) sdk.Coin { + return transfertypes.GetTransferCoin(testkeeper.MockDestPort, testkeeper.MockDestChannel, amount.Denom, amount.Amount) +} diff --git a/x/rewards/keeper/ibc_iprpc.go b/x/rewards/keeper/ibc_iprpc.go index f968a6017a..02f0132d8c 100644 --- a/x/rewards/keeper/ibc_iprpc.go +++ b/x/rewards/keeper/ibc_iprpc.go @@ -3,11 +3,15 @@ package keeper import ( "errors" "fmt" + "strconv" + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" "github.com/lavanet/lava/utils" "github.com/lavanet/lava/utils/decoder" + "github.com/lavanet/lava/utils/maps" "github.com/lavanet/lava/x/rewards/types" ) @@ -27,7 +31,7 @@ An example of the expected IPRPC over IBC memo field: } The tokens will be transferred to the pool once the minimum IPRPC funding fee is paid. In the meantime, the IPRPC over IBC -funds are saved in the IbcIprpcFund scaffolded map. +funds are saved in the PendingIprpcFund scaffolded map. */ @@ -74,6 +78,250 @@ func printInvalidMemoWarning(memo types.IprpcMemo, description string) error { return types.ErrIprpcMemoInvalid } +// The PendingIbcIprpcFund object holds all the necessary information for a pending IPRPC over IBC fund request that its min +// IPRPC cost was not covered. The min cost can be covered using the cover-ibc-iprpc-costs TX. Then, the funds will be transferred +// to the IPRPC pool from the next month for the pending fund's duration field. The corresponding PendingIbcIprpcFund will be deleted. +// Also, every PendingIbcIprpcFund has an expiration on which the object is deleted. There will be no refund of the funds +// upon expiration. The expiration period is determined by the reward module's parameter IbcIprpcExpiration. + +// NewPendingIbcIprpcFund sets a new PendingIbcIprpcFund object. It validates the input and sets the object with the right index and expiry +func (k Keeper) NewPendingIbcIprpcFund(ctx sdk.Context, creator string, spec string, duration uint64, fund sdk.Coin) (newPendingIbcIprpcFund types.PendingIbcIprpcFund, leftovers sdk.Coin, err error) { + zeroCoin := sdk.NewCoin(fund.Denom, math.ZeroInt()) + // validate spec and funds + _, found := k.specKeeper.GetSpec(ctx, spec) + if !found { + return types.PendingIbcIprpcFund{}, zeroCoin, utils.LavaFormatError("spec not found", fmt.Errorf("cannot create PendingIbcIprpcFund"), + utils.LogAttr("creator", creator), + utils.LogAttr("spec", spec), + utils.LogAttr("duration", duration), + utils.LogAttr("funds", fund), + ) + } + if fund.IsNil() || !fund.IsValid() { + return types.PendingIbcIprpcFund{}, zeroCoin, utils.LavaFormatError("invalid funds", fmt.Errorf("cannot create PendingIbcIprpcFund"), + utils.LogAttr("creator", creator), + utils.LogAttr("spec", spec), + utils.LogAttr("duration", duration), + utils.LogAttr("funds", fund), + ) + } + + // divide funds by duration since we use addSpecFunds() when applying the PendingIbcIprpcFund + // which assumes that each month will get the input fund + monthlyFund := sdk.NewCoin(fund.Denom, fund.Amount.QuoRaw(int64(duration))) + if monthlyFund.IsZero() { + return types.PendingIbcIprpcFund{}, zeroCoin, utils.LavaFormatWarning("fund amount cannot be less than duration", fmt.Errorf("cannot create PendingIbcIprpcFund"), + utils.LogAttr("creator", creator), + utils.LogAttr("spec", spec), + utils.LogAttr("duration", duration), + utils.LogAttr("funds", fund), + ) + } + + // leftovers will be transferred to the community pool in the calling function + leftovers = sdk.NewCoin(fund.Denom, fund.Amount.Sub(monthlyFund.Amount.MulRaw(int64(duration)))) + + // get index for the new object + latestPendingIbcIprpcFund := k.GetLatestPendingIbcIprpcFund(ctx) + newIndex := uint64(0) + if !latestPendingIbcIprpcFund.IsEmpty() { + newIndex = latestPendingIbcIprpcFund.Index + 1 + } + + // get expiry from current block time (using the rewards module parameter) + expiry := k.CalcPendingIbcIprpcFundExpiration(ctx) + + pendingIbcIprpcFund := types.PendingIbcIprpcFund{ + Index: newIndex, + Creator: creator, + Spec: spec, + Duration: duration, + Fund: monthlyFund, + Expiry: expiry, + } + + // sanity check + if !pendingIbcIprpcFund.IsValid() { + return types.PendingIbcIprpcFund{}, zeroCoin, utils.LavaFormatError("PendingIbcIprpcFund is invalid. expiry and duration must be positive, fund cannot be zero", fmt.Errorf("cannot create PendingIbcIprpcFund"), + utils.LogAttr("creator", creator), + utils.LogAttr("spec", spec), + utils.LogAttr("duration", duration), + utils.LogAttr("funds", fund), + utils.LogAttr("expiry", expiry), + ) + } + + k.SetPendingIbcIprpcFund(ctx, pendingIbcIprpcFund) + + return pendingIbcIprpcFund, leftovers, nil +} + +// SetPendingIbcIprpcFund set an PendingIbcIprpcFund in the PendingIbcIprpcFund store +func (k Keeper) SetPendingIbcIprpcFund(ctx sdk.Context, pendingIbcIprpcFund types.PendingIbcIprpcFund) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PendingIbcIprpcFundPrefix)) + b := k.cdc.MustMarshal(&pendingIbcIprpcFund) + store.Set(maps.GetIDBytes(pendingIbcIprpcFund.Index), b) +} + +// IsPendingIbcIprpcFund gets an PendingIbcIprpcFund from the PendingIbcIprpcFund store +func (k Keeper) GetPendingIbcIprpcFund(ctx sdk.Context, id uint64) (val types.PendingIbcIprpcFund, found bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PendingIbcIprpcFundPrefix)) + b := store.Get(maps.GetIDBytes(id)) + if b == nil { + return val, false + } + k.cdc.MustUnmarshal(b, &val) + return val, true +} + +// RemovePendingIbcIprpcFund removes an PendingIbcIprpcFund from the PendingIbcIprpcFund store +func (k Keeper) RemovePendingIbcIprpcFund(ctx sdk.Context, id uint64) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PendingIbcIprpcFundPrefix)) + store.Delete(maps.GetIDBytes(id)) +} + +// GetAllPendingIbcIprpcFund returns all PendingIbcIprpcFund from the PendingIbcIprpcFund store +func (k Keeper) GetAllPendingIbcIprpcFund(ctx sdk.Context) (list []types.PendingIbcIprpcFund) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PendingIbcIprpcFundPrefix)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.PendingIbcIprpcFund + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} + +// RemoveExpiredPendingIbcIprpcFunds removes all the expired PendingIbcIprpcFund objects from the PendingIbcIprpcFund store +func (k Keeper) RemoveExpiredPendingIbcIprpcFunds(ctx sdk.Context) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PendingIbcIprpcFundPrefix)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.PendingIbcIprpcFund + k.cdc.MustUnmarshal(iterator.Value(), &val) + if val.IsExpired(ctx) { + err := k.FundCommunityPoolFromModule(ctx, sdk.NewCoins(val.Fund), string(types.PendingIprpcPoolName)) + if err != nil { + utils.LavaFormatError("failed funding community pool from expired IBC IPRPC fund, removing without funding", err, + utils.LogAttr("pending_ibc_iprpc_fund", val.String()), + ) + } + k.RemovePendingIbcIprpcFund(ctx, val.Index) + utils.LogLavaEvent(ctx, k.Logger(ctx), types.ExpiredPendingIbcIprpcFundRemovedEventName, map[string]string{ + "index": strconv.FormatUint(val.Index, 10), + "creator": val.Creator, + "spec": val.Spec, + "duration": strconv.FormatUint(val.Duration, 10), + "monthly_fund": val.Fund.String(), + "expiry": strconv.FormatUint(val.Expiry, 10), + }, "Expired pending IBC IPRPC fund was removed. Funds were transferred to the community pool") + } else { + break + } + } +} + +// GetLatestPendingIbcIprpcFund gets the latest PendingIbcIprpcFund from the PendingIbcIprpcFund store +func (k Keeper) GetLatestPendingIbcIprpcFund(ctx sdk.Context) types.PendingIbcIprpcFund { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PendingIbcIprpcFundPrefix)) + iterator := sdk.KVStoreReversePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.PendingIbcIprpcFund + k.cdc.MustUnmarshal(iterator.Value(), &val) + return val + } + + return types.PendingIbcIprpcFund{} +} + +// CalcPendingIbcIprpcFundMinCost calculates the required cost to apply it (transfer the funds to the IPRPC pool) +func (k Keeper) CalcPendingIbcIprpcFundMinCost(ctx sdk.Context, pendingIbcIprpcFund types.PendingIbcIprpcFund) sdk.Coin { + minCost := k.GetMinIprpcCost(ctx) + minCost.Amount = minCost.Amount.MulRaw(int64(pendingIbcIprpcFund.Duration)) + return minCost +} + +// CalcPendingIbcIprpcFundExpiration returns the expiration timestamp of a PendingIbcIprpcFund +func (k Keeper) CalcPendingIbcIprpcFundExpiration(ctx sdk.Context) uint64 { + return uint64(ctx.BlockTime().Add(k.IbcIprpcExpiration(ctx)).UTC().Unix()) +} + +// CoverIbcIprpcFundCost covers the cost of a PendingIbcIprpcFund by sending the min cost funds to the IBC IPRPC receiver +// address and call FundIprpc(). Finally, it removes the PendingIbcIprpcFund object from the store +func (k Keeper) CoverIbcIprpcFundCost(ctx sdk.Context, creator string, index uint64) (costCovered sdk.Coin, err error) { + zeroCoin := sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), math.ZeroInt()) + creatorAddr, err := sdk.AccAddressFromBech32(creator) + if err != nil { + return zeroCoin, utils.LavaFormatWarning("invalid creator address. not Bech32", types.ErrCoverIbcIprpcFundCostFailed, + utils.LogAttr("creator", creator), + utils.LogAttr("index", index), + ) + } + + // get the PendingIbcIprpcFund with index + piif, found := k.GetPendingIbcIprpcFund(ctx, index) + if !found { + return zeroCoin, utils.LavaFormatWarning("PendingIbcIprpcFund not found", types.ErrCoverIbcIprpcFundCostFailed, + utils.LogAttr("creator", creator), + utils.LogAttr("index", index), + ) + } + + // sanity check: PendingIbcIprpcFund is not expired + if piif.IsExpired(ctx) { + k.RemovePendingIbcIprpcFund(ctx, index) + return zeroCoin, utils.LavaFormatWarning("PendingIbcIprpcFund with index is expired (deleted fund)", types.ErrCoverIbcIprpcFundCostFailed, + utils.LogAttr("creator", creator), + utils.LogAttr("index", index), + ) + } + + // send the min cost to the ValidatorsRewardsAllocationPoolName (gov module doesn't pay min cost) + cost := zeroCoin + if creator != k.authority { + cost = k.CalcPendingIbcIprpcFundMinCost(ctx, piif) + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, creatorAddr, string(types.ValidatorsRewardsAllocationPoolName), sdk.NewCoins(cost)) + if err != nil { + return zeroCoin, utils.LavaFormatWarning(types.ErrCoverIbcIprpcFundCostFailed.Error(), err, + utils.LogAttr("creator", creator), + utils.LogAttr("index", index), + ) + } + } + + // fund the iprpc pool from PendingIprpcPool (inside, the PendingIprpcPool and the gov module are not paying the min cost) + err = k.FundIprpc(ctx, string(types.PendingIprpcPoolName), piif.Duration, sdk.NewCoins(piif.Fund), piif.Spec) + if err != nil { + return zeroCoin, utils.LavaFormatWarning(types.ErrCoverIbcIprpcFundCostFailed.Error(), err, + utils.LogAttr("creator", creator), + utils.LogAttr("index", index), + ) + } + + // remove the PendingIbcIprpcFund + k.RemovePendingIbcIprpcFund(ctx, index) + + return cost, nil +} + +func (k Keeper) SendIbcTokensToPendingIprpcPool(ctx sdk.Context, amount sdk.Coin) error { + return k.bankKeeper.SendCoinsFromAccountToModule(ctx, types.IbcIprpcReceiverAddress(), string(types.PendingIprpcPoolName), sdk.NewCoins(amount)) +} + +func (k Keeper) FundCommunityPoolFromIbcIprpcReceiver(ctx sdk.Context, amount sdk.Coin) error { + return k.distributionKeeper.FundCommunityPool(ctx, sdk.NewCoins(amount), types.IbcIprpcReceiverAddress()) +} + // SendIbcIprpcReceiverTokensToPendingIprpcPool sends tokens from the IbcIprpcReceiver to the PendingIprpcPool as part of the IPRPC over IBC mechanism // if the transfer fails, we try to transfer the tokens to the community pool func (k Keeper) SendIbcIprpcReceiverTokensToPendingIprpcPool(ctx sdk.Context, amount sdk.Coin) error { @@ -90,7 +338,7 @@ func (k Keeper) SendIbcIprpcReceiverTokensToPendingIprpcPool(ctx sdk.Context, am err1 := k.bankKeeper.SendCoinsFromAccountToModule(ctx, types.IbcIprpcReceiverAddress(), string(types.PendingIprpcPoolName), sdk.NewCoins(amount)) if err1 != nil { // we couldn't transfer the funds to the pending IPRPC fund request pool, try moving it to the community pool - err2 := k.distributionKeeper.FundCommunityPool(ctx, sdk.NewCoins(amount), types.IbcIprpcReceiverAddress()) + err2 := k.FundCommunityPoolFromIbcIprpcReceiver(ctx, amount) if err2 != nil { // community pool transfer failed, token kept locked in IbcIprpcReceiverAddress, return err ack return utils.LavaFormatError("could not send tokens from IbcIprpcReceiverAddress to pending IPRPC pool or community pool, tokens are locked in IbcIprpcReceiverAddress", diff --git a/x/rewards/keeper/ibc_iprpc_test.go b/x/rewards/keeper/ibc_iprpc_test.go index 667e642817..bb4fb50c30 100644 --- a/x/rewards/keeper/ibc_iprpc_test.go +++ b/x/rewards/keeper/ibc_iprpc_test.go @@ -1,10 +1,21 @@ package keeper_test import ( + "strconv" "testing" + "time" sdkerrors "cosmossdk.io/errors" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/lavanet/lava/testutil/keeper" + "github.com/lavanet/lava/testutil/nullify" + "github.com/lavanet/lava/testutil/sample" + commontypes "github.com/lavanet/lava/utils/common/types" + "github.com/lavanet/lava/x/rewards/keeper" "github.com/lavanet/lava/x/rewards/types" + "github.com/stretchr/testify/require" ) @@ -127,3 +138,390 @@ func TestParseIprpcOverIbcMemo(t *testing.T) { }) } } + +// Prevent strconv unused error +var _ = strconv.IntSize + +// createNPendingIbcIprpcFunds is a helper function that creates an n-sized array of PendingIbcIprpcFund objects +func createNPendingIbcIprpcFunds(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.PendingIbcIprpcFund { + items := make([]types.PendingIbcIprpcFund, n) + for i := range items { + items[i] = types.PendingIbcIprpcFund{ + Index: uint64(i), + Creator: "dummy", + Spec: "mock", + Duration: uint64(i), + Fund: GetIbcCoins(sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(int64(i+1)))), + Expiry: uint64(ctx.BlockTime().UTC().Unix()) + uint64(i), + } + keeper.SetPendingIbcIprpcFund(ctx, items[i]) + } + return items +} + +// TestPendingIbcIprpcFundsGet tests GetPendingIbcIprpcFund() +func TestPendingIbcIprpcFundsGet(t *testing.T) { + keeper, ctx := keepertest.RewardsKeeper(t) + items := createNPendingIbcIprpcFunds(keeper, ctx, 10) + for _, item := range items { + res, found := keeper.GetPendingIbcIprpcFund(ctx, item.Index) + require.True(t, found) + require.True(t, res.IsEqual(item)) + } +} + +// TestPendingIbcIprpcFundsRemove tests RemovePendingIbcIprpcFund +func TestPendingIbcIprpcFundsRemove(t *testing.T) { + keeper, ctx := keepertest.RewardsKeeper(t) + items := createNPendingIbcIprpcFunds(keeper, ctx, 10) + for _, item := range items { + keeper.RemovePendingIbcIprpcFund(ctx, item.Index) + _, found := keeper.GetPendingIbcIprpcFund(ctx, item.Index) + require.False(t, found) + } +} + +// TestPendingIbcIprpcFundsGetAll tests GetAllPendingIbcIprpcFund +func TestPendingIbcIprpcFundsGetAll(t *testing.T) { + keeper, ctx := keepertest.RewardsKeeper(t) + items := createNPendingIbcIprpcFunds(keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllPendingIbcIprpcFund(ctx)), + ) +} + +// TestPendingIbcIprpcFundsRemoveExpired tests RemoveExpiredPendingIbcIprpcFunds and IsExpired +func TestPendingIbcIprpcFundsRemoveExpired(t *testing.T) { + keeper, ctx := keepertest.RewardsKeeper(t) + items := createNPendingIbcIprpcFunds(keeper, ctx, 10) + + // advance time so some of the PendingIbcIprpcFund will expire + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(3 * time.Second)) + + // verify they're expired + for i := range items { + if i <= 3 { + require.True(t, items[i].IsExpired(ctx)) + } else { + require.False(t, items[i].IsExpired(ctx)) + } + } + + // remove expired PendingIbcIprpcFund and check they cannot be found + keeper.RemoveExpiredPendingIbcIprpcFunds(ctx) + for _, item := range items { + _, found := keeper.GetPendingIbcIprpcFund(ctx, item.Index) + if item.Index <= 3 { + require.False(t, found) + } else { + require.True(t, found) + } + } +} + +// TestPendingIbcIprpcFundsRemoveExpiredWithBeginBlock tests that expired PendingIbcIprpcFunds are removed with BeginBlock +// Also, their funds should be sent to the community pool +func TestPendingIbcIprpcFundsRemoveExpiredWithBeginBlock(t *testing.T) { + ts := newTester(t, false) + keeper, ctx := ts.Keepers.Rewards, ts.Ctx + items := createNPendingIbcIprpcFunds(&keeper, ctx, 10) + + // let funder be the account that sends the ibc-transfer msg + funder := sample.AccAddressObject() + funderBalance := sdk.NewCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(10000))) + err := ts.Keepers.BankKeeper.SetBalance(ctx, funder, funderBalance) + require.NoError(t, err) + + // IbcIprpcReceiver gets its balance via an IBC transfer + ts.SendIprpcOverIbcTransferPacket(funder, sdk.NewCoin(ts.TokenDenom(), iprpcFunds.AmountOf(ts.TokenDenom())), 1) + + // advance block with 3 seconds to expire some of the PendingIbcIprpcFunds + ts.AdvanceBlock(3 * time.Second) + + // check that expired PendingIbcIprpcFunds were removed + for _, item := range items { + _, found := keeper.GetPendingIbcIprpcFund(ctx, item.Index) + if item.Index <= 3 { + require.False(t, found) + } else { + require.True(t, found) + } + } + + // check the community pool's balance (objects in indices 0-3 were removed, so expected balance is 1+2+3+4=10ulava) + expectedBalance := GetIbcCoins(sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10))) + communityCoins := ts.Keepers.Distribution.GetFeePoolCommunityCoins(ts.Ctx) + communityBalance := communityCoins.AmountOf(expectedBalance.Denom).TruncateInt() + require.True(t, communityBalance.Equal(expectedBalance.Amount)) +} + +// TestPendingIbcIprpcFundGetLatest tests GetLatestPendingIbcIprpcFund +func TestPendingIbcIprpcFundGetLatest(t *testing.T) { + keeper, ctx := keepertest.RewardsKeeper(t) + latest := keeper.GetLatestPendingIbcIprpcFund(ctx) + require.True(t, latest.IsEmpty()) + items := createNPendingIbcIprpcFunds(keeper, ctx, 10) + latest = keeper.GetLatestPendingIbcIprpcFund(ctx) + require.True(t, latest.IsEqual(items[len(items)-1])) +} + +// TestPendingIbcIprpcFundNew tests NewPendingIbcIprpcFund +func TestPendingIbcIprpcFundNew(t *testing.T) { + ts := newTester(t, false) + keeper, ctx := ts.Keepers.Rewards, ts.Ctx + spec := ts.Spec("mock") + validFunds := sdk.NewCoin("denom", math.OneInt()) + + template := []struct { + name string + spec string + funds sdk.Coin + success bool + }{ + {"valid", spec.Index, validFunds, true}, + {"invalid fund", spec.Index, sdk.NewCoin(ts.TokenDenom(), math.ZeroInt()), false}, + {"non-existent spec", "eth", validFunds, false}, + } + + for _, tt := range template { + t.Run(tt.name, func(t *testing.T) { + _, _, err := keeper.NewPendingIbcIprpcFund(ctx, "creator", tt.spec, 1, tt.funds) + if tt.success { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} + +// TestCalcPendingIbcIprpcFundMinCost tests CalcPendingIbcIprpcFundMinCost +func TestCalcPendingIbcIprpcFundMinCost(t *testing.T) { + ts := newTester(t, true) + ts.setupForIprpcTests(false) + keeper, ctx := ts.Keepers.Rewards, ts.Ctx + latest := keeper.GetLatestPendingIbcIprpcFund(ctx) + minCost := keeper.CalcPendingIbcIprpcFundMinCost(ctx, latest) + expectedMinCost := sdk.NewCoin(ts.TokenDenom(), keeper.GetMinIprpcCost(ctx).Amount.MulRaw(int64(latest.Duration))) + require.True(t, minCost.IsEqual(expectedMinCost)) +} + +// TestCalcPendingIbcIprpcFundExpiration tests CalcPendingIbcIprpcFundExpiration +func TestCalcPendingIbcIprpcFundExpiration(t *testing.T) { + keeper, ctx := keepertest.RewardsKeeper(t) + expectedExpiry := uint64(ctx.BlockTime().Add(keeper.IbcIprpcExpiration(ctx)).UTC().Unix()) + expiry := keeper.CalcPendingIbcIprpcFundExpiration(ctx) + require.Equal(t, expectedExpiry, expiry) +} + +// TestPendingIbcIprpcFundsQuery tests that the pending-ibc-iprpc-funds query works as expected with filters +func TestPendingIbcIprpcFundsQuery(t *testing.T) { + ts := newTester(t, true) + ts.setupForIprpcTests(false) + keeper, ctx := ts.Keepers.Rewards, ts.Ctx + items := createNPendingIbcIprpcFunds(&keeper, ctx, 3) + + // make some of the PendingIbcIprpcFunds different with creator and spec + items[0].Creator = "blabla" + items[1].Spec = mockSpec2 + keeper.SetPendingIbcIprpcFund(ctx, items[0]) + keeper.SetPendingIbcIprpcFund(ctx, items[1]) + + minCost := keeper.GetMinIprpcCost(ctx) + template := []struct { + name string + filter string + expectedPendingIbcIprpcFundInfo []types.PendingIbcIprpcFundInfo + success bool + }{ + {"no filter", "", []types.PendingIbcIprpcFundInfo{ + {PendingIbcIprpcFund: items[0], Cost: sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(int64(items[0].Duration)))}, + {PendingIbcIprpcFund: items[1], Cost: sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(int64(items[1].Duration)))}, + {PendingIbcIprpcFund: items[2], Cost: sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(int64(items[2].Duration)))}, + }, true}, + {"index filter", "2", []types.PendingIbcIprpcFundInfo{ + {PendingIbcIprpcFund: items[2], Cost: sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(int64(items[2].Duration)))}, + }, true}, + {"creator filter", "blabla", []types.PendingIbcIprpcFundInfo{ + {PendingIbcIprpcFund: items[0], Cost: sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(int64(items[0].Duration)))}, + }, true}, + {"spec filter", mockSpec2, []types.PendingIbcIprpcFundInfo{ + {PendingIbcIprpcFund: items[1], Cost: sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(int64(items[1].Duration)))}, + }, true}, + {"invalid index filter", "100", []types.PendingIbcIprpcFundInfo{}, false}, + {"invalid creator/spec filter", "yoyo", []types.PendingIbcIprpcFundInfo{}, false}, + } + + for _, tt := range template { + t.Run(tt.name, func(t *testing.T) { + res, err := ts.QueryRewardsPendingIbcIprpcFunds(tt.filter) + if tt.success { + require.NoError(t, err) + foundMatch := false + for _, piifi := range res.PendingIbcIprpcFundsInfo { + for _, expectedPiifi := range tt.expectedPendingIbcIprpcFundInfo { + if piifi.PendingIbcIprpcFund.IsEqual(expectedPiifi.PendingIbcIprpcFund) && piifi.Cost.IsEqual(expectedPiifi.Cost) { + foundMatch = true + break + } + } + if !foundMatch { + require.FailNow(t, "info result not matching expected") + } + foundMatch = false + } + } else { + require.Error(t, err) + } + }) + } +} + +// TestPendingIbcIprpcFundNewFunds tests that when creating a new PendingIbcIprpcFund the original +// fund gets divided by duration and the division leftovers are transferred to the community pool +func TestPendingIbcIprpcFundNewFunds(t *testing.T) { + template := []struct { + name string + funds math.Int + duration uint64 + expectedFundsInPending math.Int + expectedFundsInCommunity math.Int + success bool + }{ + {"divisiable - 9ulava", math.NewInt(9), 3, math.NewInt(3), math.ZeroInt(), true}, + {"not divisiable - 10ulava", math.NewInt(10), 3, math.NewInt(3), math.OneInt(), true}, + {"less than duration - 1ulava", math.NewInt(1), 3, math.ZeroInt(), math.ZeroInt(), false}, + {"one month duration - 10ulava", math.NewInt(10), 1, math.NewInt(10), math.ZeroInt(), true}, + } + + for _, tt := range template { + t.Run(tt.name, func(t *testing.T) { + ts := newTester(t, false) + keeper, ctx := ts.Keepers.Rewards, ts.Ctx + spec := ts.Spec("mock") + funds := sdk.NewCoin(ts.TokenDenom(), tt.funds) + + // let funder be the account that sends the ibc-transfer msg + funder := sample.AccAddressObject() + funderBalance := sdk.NewCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(10000))) + err := ts.Keepers.BankKeeper.SetBalance(ctx, funder, funderBalance) + require.NoError(t, err) + + // IbcIprpcReceiver gets its balance via an IBC transfer (leftover funds are taken from it to the community pool) + ts.SendIprpcOverIbcTransferPacket(funder, funds, 1) + + // create a new PendingIbcIprpcFund + piif, leftovers, err := keeper.NewPendingIbcIprpcFund(ctx, "creator", spec.Index, tt.duration, funds) + if tt.success { + require.NoError(t, err) + require.True(t, piif.Fund.Amount.Equal(tt.expectedFundsInPending)) + require.True(t, leftovers.Amount.Equal(tt.expectedFundsInCommunity)) + } else { + require.Error(t, err) + } + }) + } +} + +// TestCoverIbcIprpcFundCost tests that the cover-ibc-iprpc-fund-cost transaction +// Scenarios: +// 0. Create 2 PendingIbcIprpcFund objects and fund PendingIprpcPool and gov. First with 101ulava for 2 months, second with +// 99ulava for 2 months. Expected: PendingIbcIprpcFund with 50ulava, PendingIbcIprpcFund with 49ulava, community pool 2ulava +// 1. Cover costs with alice for first PendingIbcIprpcFund. Expect two iprpc rewards from next month of 50ulava, PendingIbcIprpcFund +// removed, IPRPC pool with 100ulava, second PendingIbcIprpcFund remains (49ulava), alice balance reduced by MinIprpcCost +// 2. Cover costs with gov module for second PendingIbcIprpcFund. Expect two iprpc rewards from next month of 99ulava, PendingIbcIprpcFund +// removed, IPRPC pool with 198ulava, gov module balance not reduced by MinIprpcCost +func TestCoverIbcIprpcFundCost(t *testing.T) { + ts := newTester(t, true) + ts.setupForIprpcTests(false) + keeper, ctx := ts.Keepers.Rewards, ts.Ctx + + // let funder be a dummy account to send the IBC transfer coins + // let alice be the account that cover costs + funder := sample.AccAddressObject() + funderBalance := sdk.NewCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(10000))) + err := ts.Keepers.BankKeeper.SetBalance(ctx, funder, funderBalance) + require.NoError(t, err) + + alice := sample.AccAddressObject() + aliceBalance := sdk.NewCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(10000))) + err = ts.Keepers.BankKeeper.SetBalance(ctx, alice, aliceBalance) + require.NoError(t, err) + + // set min IPRPC cost to be 50ulava (for validation checks later) + minCost := sdk.NewCoin(ts.TokenDenom(), math.NewInt(50)) + keeper.SetMinIprpcCost(ctx, minCost) + + // create 2 pending IPRPC requests + funds1 := sdk.NewCoin(ts.TokenDenom(), math.NewInt(101)) // will be index 0 + ts.SendIprpcOverIbcTransferPacket(funder, funds1, 2) + funds2 := sdk.NewCoin(ts.TokenDenom(), math.NewInt(99)) // will be index 1 + ts.SendIprpcOverIbcTransferPacket(funder, funds2, 2) + expectedPendingIprpcPoolBalance := GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(198))) // 99+101-leftovers = 99+101-2 + pendingIprpcPoolBalance := ts.Keepers.Rewards.TotalPoolTokens(ctx, types.PendingIprpcPoolName) + require.True(t, pendingIprpcPoolBalance.IsEqual(sdk.NewCoins(expectedPendingIprpcPoolBalance))) + + // fund the gov module with a dummy balance, just to see it's not changing + govModuleBalance := sdk.NewCoins(sdk.NewCoin(ts.TokenDenom(), math.OneInt())) + govModule := ts.Keepers.AccountKeeper.GetModuleAddress("gov") + err = ts.Keepers.BankKeeper.SetBalance(ctx, govModule, govModuleBalance) + require.NoError(t, err) + + // cover costs of first PendingIbcIprpcFund with alice + expectedMinCost := sdk.NewCoin(minCost.Denom, minCost.Amount.MulRaw(2)) + _, err = ts.TxRewardsCoverIbcIprpcFundCost(alice.String(), 0) + require.NoError(t, err) + _, found := keeper.GetPendingIbcIprpcFund(ctx, 0) + require.False(t, found) + require.Equal(t, expectedMinCost.Amount.Int64(), aliceBalance.AmountOf(ts.TokenDenom()).Int64()-ts.GetBalance(alice)) + + res, err := ts.QueryRewardsIprpcSpecReward(mockSpec) + require.NoError(t, err) + expectedIprpcRewards := []types.IprpcReward{ + {Id: 1, SpecFunds: []types.Specfund{{Spec: mockSpec, Fund: sdk.NewCoins(GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(50))))}}}, + {Id: 2, SpecFunds: []types.Specfund{{Spec: mockSpec, Fund: sdk.NewCoins(GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(50))))}}}, + } + require.Len(t, res.IprpcRewards, len(expectedIprpcRewards)) + for i := range res.IprpcRewards { + require.Equal(t, expectedIprpcRewards[i].Id, res.IprpcRewards[i].Id) + require.ElementsMatch(t, expectedIprpcRewards[i].SpecFunds, res.IprpcRewards[i].SpecFunds) + } + + _, found = keeper.GetPendingIbcIprpcFund(ctx, 1) + require.True(t, found) + + expectedIprpcPoolBalance := sdk.NewCoins(GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(100)))) + iprpcPoolBalance := ts.Keepers.Rewards.TotalPoolTokens(ts.Ctx, types.IprpcPoolName) + require.True(t, expectedIprpcPoolBalance.IsEqual(iprpcPoolBalance)) + + // cover costs of second PendingIbcIprpcFund with gov + // note that the gov module's balance should not change since it's the only account + // that doesn't need to pay min cost (see check below) + _, err = ts.TxRewardsCoverIbcIprpcFundCost(govModule.String(), 1) + require.NoError(t, err) + _, found = keeper.GetPendingIbcIprpcFund(ctx, 1) + require.False(t, found) + require.Equal(t, int64(0), govModuleBalance.AmountOf(ts.TokenDenom()).Int64()-ts.GetBalance(govModule)) + + res, err = ts.QueryRewardsIprpcSpecReward(mockSpec) + require.NoError(t, err) + expectedIprpcRewards = []types.IprpcReward{ + {Id: 1, SpecFunds: []types.Specfund{{Spec: mockSpec, Fund: sdk.NewCoins(GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(99))))}}}, + {Id: 2, SpecFunds: []types.Specfund{{Spec: mockSpec, Fund: sdk.NewCoins(GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(99))))}}}, + } + require.Len(t, res.IprpcRewards, len(expectedIprpcRewards)) + for i := range res.IprpcRewards { + require.Equal(t, expectedIprpcRewards[i].Id, res.IprpcRewards[i].Id) + require.ElementsMatch(t, expectedIprpcRewards[i].SpecFunds, res.IprpcRewards[i].SpecFunds) + } + + expectedIprpcPoolBalance = sdk.NewCoins(GetIbcCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(198)))) + iprpcPoolBalance = ts.Keepers.Rewards.TotalPoolTokens(ts.Ctx, types.IprpcPoolName) + require.True(t, expectedIprpcPoolBalance.IsEqual(iprpcPoolBalance)) + + // verify that PendingIprpcPool has 0ulava balance (in the IBC middleware, the leftovers + // of both IPRPC over IBC are sent to the community pool) + pendingIprpcPoolBalance = ts.Keepers.Rewards.TotalPoolTokens(ts.Ctx, types.PendingIprpcPoolName) + require.True(t, pendingIprpcPoolBalance.Empty()) +} diff --git a/x/rewards/keeper/iprpc.go b/x/rewards/keeper/iprpc.go index cccaaee334..41d2e60dd6 100644 --- a/x/rewards/keeper/iprpc.go +++ b/x/rewards/keeper/iprpc.go @@ -17,40 +17,56 @@ func (k Keeper) FundIprpc(ctx sdk.Context, creator string, duration uint64, fund return utils.LavaFormatWarning("spec not found or disabled", types.ErrFundIprpc) } - // check fund consists of minimum amount of ulava (min_iprpc_cost) - minIprpcFundCost := k.GetMinIprpcCost(ctx) - if fund.AmountOf(k.stakingKeeper.BondDenom(ctx)).LT(minIprpcFundCost.Amount) { - return utils.LavaFormatWarning("insufficient ulava tokens in fund. should be at least min iprpc cost * duration", types.ErrFundIprpc, - utils.LogAttr("min_iprpc_cost", k.GetMinIprpcCost(ctx).String()), - utils.LogAttr("duration", strconv.FormatUint(duration, 10)), - utils.LogAttr("fund_ulava_amount", fund.AmountOf(k.stakingKeeper.BondDenom(ctx))), - ) - } - - // check creator has enough balance - addr, err := sdk.AccAddressFromBech32(creator) - if err != nil { - return utils.LavaFormatWarning("invalid creator address", types.ErrFundIprpc) - } + // calculate total funds to transfer to the IPRPC pool (input fund is monthly fund) + totalFunds := fund.MulInt(math.NewIntFromUint64(duration)) + + // if the fund TX originates from the gov module (keeper's authority field) or the pending IPRPC pool it's not paying the minimum IPRPC cost + if creator != k.authority && creator != string(types.PendingIprpcPoolName) { + // check fund consists of minimum amount of ulava (min_iprpc_cost) + minIprpcFundCost := k.GetMinIprpcCost(ctx) + if fund.AmountOf(k.stakingKeeper.BondDenom(ctx)).LT(minIprpcFundCost.Amount) { + return utils.LavaFormatWarning("insufficient ulava tokens in fund. should be at least min iprpc cost * duration", types.ErrFundIprpc, + utils.LogAttr("min_iprpc_cost", k.GetMinIprpcCost(ctx).String()), + utils.LogAttr("duration", strconv.FormatUint(duration, 10)), + utils.LogAttr("fund_ulava_amount", fund.AmountOf(k.stakingKeeper.BondDenom(ctx))), + ) + } else if fund.IsEqual(sdk.NewCoins(minIprpcFundCost)) { + return utils.LavaFormatWarning("funds are equal to min iprpc cost, no funds left to send to iprpc pool", types.ErrFundIprpc, + utils.LogAttr("creator", creator), + utils.LogAttr("spec", spec), + utils.LogAttr("funds", fund.String()), + utils.LogAttr("min_iprpc_cost", minIprpcFundCost.String()), + ) + } - // send the minimum cost to the validators allocation pool (and subtract them from the fund) - minIprpcFundCostCoins := sdk.NewCoins(minIprpcFundCost).MulInt(sdk.NewIntFromUint64(duration)) - err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, string(types.ValidatorsRewardsAllocationPoolName), minIprpcFundCostCoins) - if err != nil { - return utils.LavaFormatError(types.ErrFundIprpc.Error()+"for funding validator allocation pool", err, - utils.LogAttr("creator", creator), - utils.LogAttr("min_iprpc_fund_cost", minIprpcFundCost.String()), - ) + // send the minimum cost to the validators allocation pool (and subtract them from the fund) + minIprpcFundCostCoins := sdk.NewCoins(minIprpcFundCost).MulInt(sdk.NewIntFromUint64(duration)) + addr, err := sdk.AccAddressFromBech32(creator) + if err != nil { + return utils.LavaFormatError(types.ErrFundIprpc.Error()+"for funding validator allocation pool with min iprpc cost", err, + utils.LogAttr("creator", creator), + utils.LogAttr("min_iprpc_fund_cost", minIprpcFundCost.String()), + ) + } + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, string(types.ValidatorsRewardsAllocationPoolName), minIprpcFundCostCoins) + if err != nil { + return utils.LavaFormatError(types.ErrFundIprpc.Error()+"for funding validator allocation pool with min iprpc cost", err, + utils.LogAttr("creator", creator), + utils.LogAttr("min_iprpc_fund_cost", minIprpcFundCost.String()), + ) + } + fund = fund.Sub(minIprpcFundCost) + totalFunds = fund.MulInt(math.NewIntFromUint64(duration)) } - fund = fund.Sub(minIprpcFundCost) - allFunds := fund.MulInt(math.NewIntFromUint64(duration)) // send the funds to the iprpc pool - err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, string(types.IprpcPoolName), allFunds) + err := k.sendCoinsToIprpcPool(ctx, creator, totalFunds) if err != nil { return utils.LavaFormatError(types.ErrFundIprpc.Error()+"for funding iprpc pool", err, utils.LogAttr("creator", creator), - utils.LogAttr("fund", fund.String()), + utils.LogAttr("monthly_fund", fund.String()), + utils.LogAttr("duration", duration), + utils.LogAttr("total_fund", totalFunds.String()), ) } @@ -60,6 +76,20 @@ func (k Keeper) FundIprpc(ctx sdk.Context, creator string, duration uint64, fund return nil } +func (k Keeper) sendCoinsToIprpcPool(ctx sdk.Context, sender string, amount sdk.Coins) error { + // sender is gov module or pending IPRPC pool - use SendCoinsFromModuleToModule + if sender == k.authority || sender == string(types.PendingIprpcPoolName) { + return k.bankKeeper.SendCoinsFromModuleToModule(ctx, sender, string(types.IprpcPoolName), amount) + } + + addr, err := sdk.AccAddressFromBech32(sender) + if err != nil { + return err + } + + return k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, string(types.IprpcPoolName), amount) +} + // handleNoIprpcRewardToProviders handles the situation in which there are no providers to send IPRPC rewards to // so the IPRPC rewards transfer to the next month func (k Keeper) handleNoIprpcRewardToProviders(ctx sdk.Context, iprpcFunds []types.Specfund) { diff --git a/x/rewards/keeper/iprpc_reward.go b/x/rewards/keeper/iprpc_reward.go index 4df6b9c713..19f7cab20d 100644 --- a/x/rewards/keeper/iprpc_reward.go +++ b/x/rewards/keeper/iprpc_reward.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/utils/maps" "github.com/lavanet/lava/x/rewards/types" ) @@ -36,13 +37,13 @@ func (k Keeper) SetIprpcRewardsCurrentId(ctx sdk.Context, current uint64) { func (k Keeper) SetIprpcReward(ctx sdk.Context, iprpcReward types.IprpcReward) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.IprpcRewardPrefix)) b := k.cdc.MustMarshal(&iprpcReward) - store.Set(GetIprpcRewardIDBytes(iprpcReward.Id), b) + store.Set(maps.GetIDBytes(iprpcReward.Id), b) } // GetIprpcReward returns a IprpcReward from its id func (k Keeper) GetIprpcReward(ctx sdk.Context, id uint64) (val types.IprpcReward, found bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.IprpcRewardPrefix)) - b := store.Get(GetIprpcRewardIDBytes(id)) + b := store.Get(maps.GetIDBytes(id)) if b == nil { return val, false } @@ -53,7 +54,7 @@ func (k Keeper) GetIprpcReward(ctx sdk.Context, id uint64) (val types.IprpcRewar // RemoveIprpcReward removes a IprpcReward from the store func (k Keeper) RemoveIprpcReward(ctx sdk.Context, id uint64) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.IprpcRewardPrefix)) - store.Delete(GetIprpcRewardIDBytes(id)) + store.Delete(maps.GetIDBytes(id)) } // GetAllIprpcReward returns all IprpcReward @@ -72,18 +73,6 @@ func (k Keeper) GetAllIprpcReward(ctx sdk.Context) (list []types.IprpcReward) { return } -// GetIprpcRewardIDBytes returns the byte representation of the ID -func GetIprpcRewardIDBytes(id uint64) []byte { - bz := make([]byte, 8) - binary.BigEndian.PutUint64(bz, id) - return bz -} - -// GetIprpcRewardIDFromBytes returns ID in uint64 format from a byte array -func GetIprpcRewardIDFromBytes(bz []byte) uint64 { - return binary.BigEndian.Uint64(bz) -} - // PopIprpcReward gets the lowest id IprpcReward object and removes it func (k Keeper) PopIprpcReward(ctx sdk.Context) (types.IprpcReward, bool) { current := k.GetIprpcRewardsCurrentId(ctx) diff --git a/x/rewards/keeper/iprpc_test.go b/x/rewards/keeper/iprpc_test.go index fd94755a6b..100e2c488b 100644 --- a/x/rewards/keeper/iprpc_test.go +++ b/x/rewards/keeper/iprpc_test.go @@ -31,12 +31,14 @@ func TestFundIprpcTX(t *testing.T) { } // we fund as follows (to all we add the min IPRPC price. the description below is the funds that go to the pool): + // - invalid amount = exactly minIprpcCost // - 10ulava, 1 month, mockspec // - 50uibc, 1 month, mockspec // - 90ulava + 30uibc, 3 months, mockspec2 // - 130uibc, 3 months, mockspec // - 10ulava + 120uibc, 12 months, mockspec2 fundIprpcTXsData := []fundIprpcData{ + {spec: ts.specs[0].Index, duration: 1, fund: sdk.NewCoins(minIprpcCost)}, // invalid {spec: ts.specs[0].Index, duration: 1, fund: sdk.NewCoins( sdk.NewCoin(ts.BondDenom(), math.NewInt(10+minIprpcCost.Amount.Int64())), )}, @@ -58,9 +60,13 @@ func TestFundIprpcTX(t *testing.T) { )}, } - for _, txData := range fundIprpcTXsData { + for i, txData := range fundIprpcTXsData { _, err = ts.TxRewardsFundIprpc(consumer, txData.spec, txData.duration, txData.fund) - require.NoError(t, err) + if i == 0 { + require.Error(t, err) + } else { + require.NoError(t, err) + } } // Expected total IPRPC pool balance (by TXs): diff --git a/x/rewards/keeper/keeper.go b/x/rewards/keeper/keeper.go index 064cd784b4..54d2c73acc 100644 --- a/x/rewards/keeper/keeper.go +++ b/x/rewards/keeper/keeper.go @@ -113,6 +113,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // redeclaring BeginBlock for testing (this is not called outside of unit tests) func (k Keeper) BeginBlock(ctx sdk.Context) { k.DistributeBlockReward(ctx) + k.RemoveExpiredPendingIbcIprpcFunds(ctx) } func (k Keeper) GetModuleAddress() string { diff --git a/x/rewards/keeper/migrations.go b/x/rewards/keeper/migrations.go index 80f6d3486e..9b0c527307 100644 --- a/x/rewards/keeper/migrations.go +++ b/x/rewards/keeper/migrations.go @@ -2,6 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/x/rewards/types" ) type Migrator struct { @@ -16,3 +17,9 @@ func NewMigrator(keeper Keeper) Migrator { func (m Migrator) MigrateVersion1To2(ctx sdk.Context) error { return m.keeper.SetIprpcData(ctx, sdk.NewCoin(m.keeper.stakingKeeper.BondDenom(ctx), sdk.NewInt(100000000)), []string{}) } + +// MigrateVersion2To3 sets PendingIbcIprpcExpiration to 3 months +func (m Migrator) MigrateVersion2To3(ctx sdk.Context) error { + m.keeper.SetParams(ctx, types.DefaultGenesis().Params) + return nil +} diff --git a/x/rewards/keeper/msg_server_cover_ibc_iprpc_fund_cost.go b/x/rewards/keeper/msg_server_cover_ibc_iprpc_fund_cost.go new file mode 100644 index 0000000000..2a3e2e83b7 --- /dev/null +++ b/x/rewards/keeper/msg_server_cover_ibc_iprpc_fund_cost.go @@ -0,0 +1,32 @@ +package keeper + +import ( + "context" + "strconv" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/x/rewards/types" +) + +func (k msgServer) CoverIbcIprpcFundCost(goCtx context.Context, msg *types.MsgCoverIbcIprpcFundCost) (*types.MsgCoverIbcIprpcFundCostResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + err := msg.ValidateBasic() + if err != nil { + return &types.MsgCoverIbcIprpcFundCostResponse{}, err + } + + cost, err := k.Keeper.CoverIbcIprpcFundCost(ctx, msg.Creator, msg.Index) + if err == nil { + logger := k.Keeper.Logger(ctx) + details := map[string]string{ + "creator": msg.Creator, + "index": strconv.FormatUint(msg.Index, 10), + "cost_covered": cost.String(), + } + utils.LogLavaEvent(ctx, logger, types.CoverIbcIprpcFundCostEventName, details, "Covered costs of pending IBC IPRPC fund successfully") + } + + return &types.MsgCoverIbcIprpcFundCostResponse{}, err +} diff --git a/x/rewards/keeper/msg_server_fund_iprpc.go b/x/rewards/keeper/msg_server_fund_iprpc.go index d0e4e4a678..3c28e46717 100644 --- a/x/rewards/keeper/msg_server_fund_iprpc.go +++ b/x/rewards/keeper/msg_server_fund_iprpc.go @@ -21,6 +21,7 @@ func (k msgServer) FundIprpc(goCtx context.Context, msg *types.MsgFundIprpc) (*t if err == nil { logger := k.Keeper.Logger(ctx) details := map[string]string{ + "creator": msg.Creator, "spec": msg.Spec, "duration": strconv.FormatUint(msg.Duration, 10), "amounts": msg.Amounts.String(), diff --git a/x/rewards/keeper/params.go b/x/rewards/keeper/params.go index a2c2cb1a8f..9abd06b8bb 100644 --- a/x/rewards/keeper/params.go +++ b/x/rewards/keeper/params.go @@ -1,6 +1,8 @@ package keeper import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/x/rewards/types" ) @@ -14,6 +16,7 @@ func (k Keeper) GetParams(ctx sdk.Context) types.Params { k.LeftoverBurnRate(ctx), k.MaxRewardBoost(ctx), k.ValidatorsSubscriptionParticipation(ctx), + k.IbcIprpcExpiration(ctx), ) } @@ -57,3 +60,9 @@ func (k Keeper) ValidatorsSubscriptionParticipation(ctx sdk.Context) (res sdk.De k.paramstore.Get(ctx, types.KeyValidatorsSubscriptionParticipation, &res) return } + +// IbcIprpcExpiration returns the IbcIprpcExpiration param +func (k Keeper) IbcIprpcExpiration(ctx sdk.Context) (res time.Duration) { + k.paramstore.Get(ctx, types.KeyIbcIprpcExpiration, &res) + return +} diff --git a/x/rewards/keeper/pool_test.go b/x/rewards/keeper/pool_test.go index 142a4c1a0d..9cd34c91e8 100644 --- a/x/rewards/keeper/pool_test.go +++ b/x/rewards/keeper/pool_test.go @@ -328,6 +328,7 @@ func TestBondedTargetFactorEdgeCases(t *testing.T) { LeftoverBurnRate: types.DefaultLeftOverBurnRate, MaxRewardBoost: types.DefaultMaxRewardBoost, ValidatorsSubscriptionParticipation: types.DefaultValidatorsSubscriptionParticipation, + IbcIprpcExpiration: types.DefaultIbcIprpcExpiration, } ts.Keepers.Rewards.SetParams(ts.Ctx, params) diff --git a/x/rewards/module.go b/x/rewards/module.go index cba6a9c05d..4232bbbfd9 100644 --- a/x/rewards/module.go +++ b/x/rewards/module.go @@ -135,6 +135,12 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { // panic:ok: at start up, migration cannot proceed anyhow panic(fmt.Errorf("%s: failed to register migration to v2: %w", types.ModuleName, err)) } + + // register v2 -> v3 migration + if err := cfg.RegisterMigration(types.ModuleName, 2, migrator.MigrateVersion2To3); err != nil { + // panic:ok: at start up, migration cannot proceed anyhow + panic(fmt.Errorf("%s: failed to register migration to v3: %w", types.ModuleName, err)) + } } // RegisterInvariants registers the capability module's invariants. @@ -159,7 +165,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 2 } +func (AppModule) ConsensusVersion() uint64 { return 3 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/rewards/types/errors.go b/x/rewards/types/errors.go index 5fcb1336ce..b3dae1c670 100644 --- a/x/rewards/types/errors.go +++ b/x/rewards/types/errors.go @@ -8,7 +8,8 @@ import ( // x/rewards module sentinel errors var ( - ErrFundIprpc = sdkerrors.Register(ModuleName, 1, "fund iprpc TX failed") - ErrMemoNotIprpcOverIbc = sdkerrors.Register(ModuleName, 2, "ibc-transfer packet's memo is not in the right format of IPRPC over IBC") - ErrIprpcMemoInvalid = sdkerrors.Register(ModuleName, 3, "ibc-transfer packet's memo of IPRPC over IBC is invalid") + ErrFundIprpc = sdkerrors.Register(ModuleName, 1, "fund iprpc TX failed") + ErrMemoNotIprpcOverIbc = sdkerrors.Register(ModuleName, 2, "ibc-transfer packet's memo is not in the right format of IPRPC over IBC") + ErrIprpcMemoInvalid = sdkerrors.Register(ModuleName, 3, "ibc-transfer packet's memo of IPRPC over IBC is invalid") + ErrCoverIbcIprpcFundCostFailed = sdkerrors.Register(ModuleName, 4, "cover ibc iprpc fund cost failed") ) diff --git a/x/rewards/types/genesis.go b/x/rewards/types/genesis.go index 217ed9506d..fa39c6a8fa 100644 --- a/x/rewards/types/genesis.go +++ b/x/rewards/types/genesis.go @@ -17,13 +17,14 @@ const DefaultIndex uint64 = 1 func DefaultGenesis() *GenesisState { return &GenesisState{ // this line is used by starport scaffolding # genesis/types/default - Params: DefaultParams(), - RefillRewardsTS: *types.DefaultGenesis(), - BasePays: []BasePayGenesis{}, - IprpcSubscriptions: []string{}, - MinIprpcCost: sdk.NewCoin(commontypes.TokenDenom, sdk.ZeroInt()), - IprpcRewards: []IprpcReward{}, - IprpcRewardsCurrent: 0, + Params: DefaultParams(), + RefillRewardsTS: *types.DefaultGenesis(), + BasePays: []BasePayGenesis{}, + IprpcSubscriptions: []string{}, + MinIprpcCost: sdk.NewCoin(commontypes.TokenDenom, sdk.ZeroInt()), + IprpcRewards: []IprpcReward{}, + IprpcRewardsCurrent: 0, + PendingIbcIprpcFunds: []PendingIbcIprpcFund{}, } } @@ -68,5 +69,11 @@ func (gs GenesisState) Validate() error { } } + for _, pendingIbcIprpcFund := range gs.PendingIbcIprpcFunds { + if !pendingIbcIprpcFund.IsValid() { + return fmt.Errorf("invalid ibc iprpc fund: %s", pendingIbcIprpcFund.String()) + } + } + return gs.Params.Validate() } diff --git a/x/rewards/types/genesis.pb.go b/x/rewards/types/genesis.pb.go index d39a2fc306..4e6bfcf7b6 100644 --- a/x/rewards/types/genesis.pb.go +++ b/x/rewards/types/genesis.pb.go @@ -27,13 +27,14 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the rewards module's genesis state. type GenesisState struct { - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - RefillRewardsTS types.GenesisState `protobuf:"bytes,2,opt,name=refillRewardsTS,proto3" json:"refillRewardsTS"` - BasePays []BasePayGenesis `protobuf:"bytes,3,rep,name=base_pays,json=basePays,proto3" json:"base_pays"` - IprpcSubscriptions []string `protobuf:"bytes,4,rep,name=iprpc_subscriptions,json=iprpcSubscriptions,proto3" json:"iprpc_subscriptions,omitempty"` - MinIprpcCost types1.Coin `protobuf:"bytes,5,opt,name=min_iprpc_cost,json=minIprpcCost,proto3" json:"min_iprpc_cost"` - IprpcRewards []IprpcReward `protobuf:"bytes,6,rep,name=iprpc_rewards,json=iprpcRewards,proto3" json:"iprpc_rewards"` - IprpcRewardsCurrent uint64 `protobuf:"varint,7,opt,name=iprpc_rewards_current,json=iprpcRewardsCurrent,proto3" json:"iprpc_rewards_current,omitempty"` + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + RefillRewardsTS types.GenesisState `protobuf:"bytes,2,opt,name=refillRewardsTS,proto3" json:"refillRewardsTS"` + BasePays []BasePayGenesis `protobuf:"bytes,3,rep,name=base_pays,json=basePays,proto3" json:"base_pays"` + IprpcSubscriptions []string `protobuf:"bytes,4,rep,name=iprpc_subscriptions,json=iprpcSubscriptions,proto3" json:"iprpc_subscriptions,omitempty"` + MinIprpcCost types1.Coin `protobuf:"bytes,5,opt,name=min_iprpc_cost,json=minIprpcCost,proto3" json:"min_iprpc_cost"` + IprpcRewards []IprpcReward `protobuf:"bytes,6,rep,name=iprpc_rewards,json=iprpcRewards,proto3" json:"iprpc_rewards"` + IprpcRewardsCurrent uint64 `protobuf:"varint,7,opt,name=iprpc_rewards_current,json=iprpcRewardsCurrent,proto3" json:"iprpc_rewards_current,omitempty"` + PendingIbcIprpcFunds []PendingIbcIprpcFund `protobuf:"bytes,8,rep,name=pending_ibc_iprpc_funds,json=pendingIbcIprpcFunds,proto3" json:"pending_ibc_iprpc_funds"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -118,6 +119,13 @@ func (m *GenesisState) GetIprpcRewardsCurrent() uint64 { return 0 } +func (m *GenesisState) GetPendingIbcIprpcFunds() []PendingIbcIprpcFund { + if m != nil { + return m.PendingIbcIprpcFunds + } + return nil +} + func init() { proto.RegisterType((*GenesisState)(nil), "lavanet.lava.rewards.GenesisState") } @@ -127,34 +135,37 @@ func init() { } var fileDescriptor_02c24f4df31ca14e = []byte{ - // 429 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x41, 0x6f, 0xd3, 0x30, - 0x14, 0x80, 0x13, 0x52, 0x0a, 0xf3, 0x06, 0x48, 0xde, 0x90, 0x42, 0x85, 0x42, 0x36, 0x40, 0xe4, - 0x64, 0x6b, 0xe5, 0xc6, 0x8d, 0x56, 0x68, 0x42, 0xe2, 0x30, 0xa5, 0x70, 0xe1, 0x12, 0x39, 0xc1, - 0x04, 0x4b, 0x8d, 0x1d, 0xf9, 0xb9, 0x83, 0xfe, 0x0b, 0x7e, 0xd6, 0x8e, 0x3b, 0x72, 0x42, 0xa8, - 0xe5, 0x87, 0xa0, 0xd8, 0x2e, 0x6d, 0xa7, 0x9c, 0x6c, 0xf9, 0x7d, 0xef, 0xf3, 0x7b, 0x4f, 0x0f, - 0x9d, 0xcd, 0xd9, 0x15, 0x93, 0xdc, 0xd0, 0xee, 0xa4, 0x9a, 0x7f, 0x67, 0xfa, 0x0b, 0xd0, 0x9a, - 0x4b, 0x0e, 0x02, 0x48, 0xab, 0x95, 0x51, 0xf8, 0xc4, 0x33, 0xa4, 0x3b, 0x89, 0x67, 0x46, 0x27, - 0xb5, 0xaa, 0x95, 0x05, 0x68, 0x77, 0x73, 0xec, 0xe8, 0xb4, 0xd7, 0xd7, 0x32, 0xcd, 0x1a, 0xaf, - 0x1b, 0x3d, 0xef, 0x45, 0x4a, 0x06, 0xbc, 0x68, 0xd9, 0xd2, 0x43, 0x69, 0x2f, 0x24, 0x5a, 0xdd, - 0x56, 0xbd, 0x1a, 0x23, 0x1a, 0xae, 0xc1, 0x28, 0xcd, 0xdd, 0xd5, 0x43, 0x49, 0xa5, 0xa0, 0x51, - 0xce, 0x4e, 0xaf, 0xce, 0x4b, 0x6e, 0xd8, 0x39, 0xad, 0x94, 0x90, 0x2e, 0x7e, 0xf6, 0x37, 0x42, - 0x47, 0x17, 0xae, 0xd9, 0x99, 0x61, 0x86, 0xe3, 0x37, 0x68, 0xe8, 0x8a, 0x8d, 0xc3, 0x34, 0xcc, - 0x0e, 0xc7, 0x4f, 0x49, 0x5f, 0xf3, 0xe4, 0xd2, 0x32, 0x93, 0xc1, 0xf5, 0xef, 0x67, 0x41, 0xee, - 0x33, 0xf0, 0x27, 0xf4, 0x48, 0xf3, 0xaf, 0x62, 0x3e, 0xcf, 0x1d, 0xf5, 0x71, 0x16, 0xdf, 0xb1, - 0x92, 0x97, 0xfb, 0x92, 0x6d, 0xad, 0x64, 0xf7, 0x6f, 0x6f, 0xbb, 0xed, 0xc0, 0x17, 0xe8, 0x60, - 0x33, 0x1c, 0x88, 0xa3, 0x34, 0xca, 0x0e, 0xc7, 0x2f, 0xfa, 0xab, 0x9a, 0x30, 0xe0, 0x97, 0x6c, - 0xe9, 0xa5, 0xde, 0x77, 0xbf, 0x74, 0xaf, 0x80, 0x29, 0x3a, 0xb6, 0x03, 0x2c, 0x60, 0x51, 0x42, - 0xa5, 0x45, 0x6b, 0x84, 0x92, 0x10, 0x0f, 0xd2, 0x28, 0x3b, 0xc8, 0xb1, 0x0d, 0xcd, 0x76, 0x23, - 0xf8, 0x1d, 0x7a, 0xd8, 0x08, 0x59, 0xb8, 0xa4, 0x4a, 0x81, 0x89, 0xef, 0xda, 0x7e, 0x9e, 0x10, - 0x37, 0x56, 0xd2, 0xa9, 0x89, 0x1f, 0x2b, 0x99, 0x2a, 0x21, 0xfd, 0x9f, 0x47, 0x8d, 0x90, 0xef, - 0xbb, 0xac, 0xa9, 0x02, 0x83, 0x3f, 0xa0, 0x07, 0x4e, 0xe1, 0xeb, 0x8c, 0x87, 0xb6, 0x89, 0xd3, - 0xfe, 0x26, 0x6c, 0x9e, 0xeb, 0x7e, 0x63, 0x13, 0xdb, 0x27, 0xc0, 0x63, 0xf4, 0x78, 0xcf, 0x56, - 0x54, 0x0b, 0xad, 0xb9, 0x34, 0xf1, 0xbd, 0x34, 0xcc, 0x06, 0xf9, 0xf1, 0x2e, 0x3c, 0x75, 0xa1, - 0xc9, 0xdb, 0xeb, 0x55, 0x12, 0xde, 0xac, 0x92, 0xf0, 0xcf, 0x2a, 0x09, 0x7f, 0xae, 0x93, 0xe0, - 0x66, 0x9d, 0x04, 0xbf, 0xd6, 0x49, 0xf0, 0xf9, 0x55, 0x2d, 0xcc, 0xb7, 0x45, 0x49, 0x2a, 0xd5, - 0xd0, 0xbd, 0x85, 0xfa, 0xf1, 0x7f, 0xe9, 0xcc, 0xb2, 0xe5, 0x50, 0x0e, 0xed, 0xc2, 0xbc, 0xfe, - 0x17, 0x00, 0x00, 0xff, 0xff, 0x15, 0xb1, 0xb4, 0xbe, 0x31, 0x03, 0x00, 0x00, + // 471 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x1b, 0x5a, 0xca, 0xe6, 0x0d, 0x90, 0xbc, 0x22, 0x42, 0x85, 0x42, 0x36, 0x40, 0x94, + 0x8b, 0xa3, 0x95, 0x1b, 0x37, 0x5a, 0xc1, 0x34, 0x89, 0xc3, 0xd4, 0xc2, 0x85, 0x4b, 0xe4, 0xa4, + 0x6e, 0xb0, 0xd4, 0xd8, 0x96, 0x9f, 0x33, 0xe8, 0xb7, 0xe0, 0x63, 0xed, 0xc0, 0x61, 0x47, 0x4e, + 0x08, 0xb5, 0x5f, 0x04, 0xc5, 0x76, 0x59, 0x0b, 0xe1, 0x14, 0xcb, 0xef, 0xff, 0x7e, 0xfe, 0xff, + 0x5f, 0x1e, 0x3a, 0x59, 0xd0, 0x4b, 0x2a, 0x98, 0x49, 0xea, 0x6f, 0xa2, 0xd9, 0x17, 0xaa, 0x67, + 0x90, 0x14, 0x4c, 0x30, 0xe0, 0x40, 0x94, 0x96, 0x46, 0xe2, 0x9e, 0xd7, 0x90, 0xfa, 0x4b, 0xbc, + 0xa6, 0xdf, 0x2b, 0x64, 0x21, 0xad, 0x20, 0xa9, 0x4f, 0x4e, 0xdb, 0x3f, 0x6e, 0xe4, 0x29, 0xaa, + 0x69, 0xe9, 0x71, 0xfd, 0xa7, 0x8d, 0x92, 0x8c, 0x02, 0x4b, 0x15, 0x5d, 0x7a, 0x51, 0xdc, 0x28, + 0xe2, 0x4a, 0xab, 0xbc, 0x11, 0x63, 0x78, 0xc9, 0x34, 0x18, 0xa9, 0x99, 0x3b, 0x7a, 0x51, 0x94, + 0x4b, 0x28, 0xa5, 0xa3, 0x27, 0x97, 0xa7, 0x19, 0x33, 0xf4, 0x34, 0xc9, 0x25, 0x17, 0xae, 0x7e, + 0xf2, 0xbd, 0x83, 0x0e, 0xcf, 0x5c, 0xd8, 0xa9, 0xa1, 0x86, 0xe1, 0xd7, 0xa8, 0xeb, 0xcc, 0x86, + 0x41, 0x1c, 0x0c, 0x0e, 0x86, 0x8f, 0x49, 0x53, 0x78, 0x72, 0x61, 0x35, 0xa3, 0xce, 0xd5, 0xcf, + 0x27, 0xad, 0x89, 0xef, 0xc0, 0x1f, 0xd1, 0x7d, 0xcd, 0xe6, 0x7c, 0xb1, 0x98, 0x38, 0xd5, 0x87, + 0x69, 0x78, 0xcb, 0x42, 0x9e, 0xef, 0x42, 0x6e, 0xbc, 0x92, 0xed, 0xb7, 0x3d, 0xed, 0x6f, 0x06, + 0x3e, 0x43, 0xfb, 0x9b, 0xe1, 0x40, 0xd8, 0x8e, 0xdb, 0x83, 0x83, 0xe1, 0xb3, 0x66, 0x57, 0x23, + 0x0a, 0xec, 0x82, 0x2e, 0x3d, 0xd4, 0xf3, 0xf6, 0x32, 0x77, 0x0b, 0x38, 0x41, 0x47, 0x76, 0x80, + 0x29, 0x54, 0x19, 0xe4, 0x9a, 0x2b, 0xc3, 0xa5, 0x80, 0xb0, 0x13, 0xb7, 0x07, 0xfb, 0x13, 0x6c, + 0x4b, 0xd3, 0xed, 0x0a, 0x7e, 0x8b, 0xee, 0x95, 0x5c, 0xa4, 0xae, 0x29, 0x97, 0x60, 0xc2, 0xdb, + 0x36, 0xcf, 0x23, 0xe2, 0xc6, 0x4a, 0x6a, 0x34, 0xf1, 0x63, 0x25, 0x63, 0xc9, 0x85, 0x7f, 0xf3, + 0xb0, 0xe4, 0xe2, 0xbc, 0xee, 0x1a, 0x4b, 0x30, 0xf8, 0x3d, 0xba, 0xeb, 0x10, 0xde, 0x67, 0xd8, + 0xb5, 0x21, 0x8e, 0x9b, 0x43, 0xd8, 0x3e, 0x97, 0x7e, 0x43, 0xe3, 0x37, 0x57, 0x80, 0x87, 0xe8, + 0xc1, 0x0e, 0x2d, 0xcd, 0x2b, 0xad, 0x99, 0x30, 0xe1, 0x9d, 0x38, 0x18, 0x74, 0x26, 0x47, 0xdb, + 0xe2, 0xb1, 0x2b, 0xe1, 0x39, 0x7a, 0xa8, 0x98, 0x98, 0x71, 0x51, 0xa4, 0x3c, 0xcb, 0x7d, 0xa0, + 0x79, 0x25, 0x66, 0x10, 0xee, 0x59, 0x2f, 0x2f, 0xff, 0xf3, 0x9b, 0x5d, 0xd3, 0x79, 0x96, 0x5b, + 0x57, 0xef, 0x2a, 0xb1, 0xf1, 0xd4, 0x53, 0xff, 0x96, 0x60, 0xf4, 0xe6, 0x6a, 0x15, 0x05, 0xd7, + 0xab, 0x28, 0xf8, 0xb5, 0x8a, 0x82, 0x6f, 0xeb, 0xa8, 0x75, 0xbd, 0x8e, 0x5a, 0x3f, 0xd6, 0x51, + 0xeb, 0xd3, 0x8b, 0x82, 0x9b, 0xcf, 0x55, 0x46, 0x72, 0x59, 0x26, 0x3b, 0x8b, 0xfb, 0xf5, 0xcf, + 0x72, 0x9b, 0xa5, 0x62, 0x90, 0x75, 0xed, 0x62, 0xbe, 0xfa, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xd2, 0xf1, 0x4f, 0x99, 0x03, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -177,6 +188,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.PendingIbcIprpcFunds) > 0 { + for iNdEx := len(m.PendingIbcIprpcFunds) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PendingIbcIprpcFunds[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + } if m.IprpcRewardsCurrent != 0 { i = encodeVarintGenesis(dAtA, i, uint64(m.IprpcRewardsCurrent)) i-- @@ -296,6 +321,12 @@ func (m *GenesisState) Size() (n int) { if m.IprpcRewardsCurrent != 0 { n += 1 + sovGenesis(uint64(m.IprpcRewardsCurrent)) } + if len(m.PendingIbcIprpcFunds) > 0 { + for _, e := range m.PendingIbcIprpcFunds { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -552,6 +583,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { break } } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingIbcIprpcFunds", 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.PendingIbcIprpcFunds = append(m.PendingIbcIprpcFunds, PendingIbcIprpcFund{}) + if err := m.PendingIbcIprpcFunds[len(m.PendingIbcIprpcFunds)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/rewards/types/genesis_test.go b/x/rewards/types/genesis_test.go index e7745ca5ad..17b99ebaef 100644 --- a/x/rewards/types/genesis_test.go +++ b/x/rewards/types/genesis_test.go @@ -31,6 +31,20 @@ func TestGenesisState_Validate(t *testing.T) { }, valid: false, }, + { + desc: "invalid ibc iprpc funds", + genState: &types.GenesisState{ + Params: types.DefaultParams(), + RefillRewardsTS: types.DefaultGenesis().RefillRewardsTS, + BasePays: types.DefaultGenesis().BasePays, + IprpcSubscriptions: types.DefaultGenesis().IprpcSubscriptions, + MinIprpcCost: types.DefaultGenesis().MinIprpcCost, + IprpcRewards: types.DefaultGenesis().IprpcRewards, + IprpcRewardsCurrent: types.DefaultGenesis().GetIprpcRewardsCurrent(), + PendingIbcIprpcFunds: []types.PendingIbcIprpcFund{{Expiry: 0}}, + }, + valid: false, + }, // this line is used by starport scaffolding # types/genesis/testcase } { t.Run(tc.desc, func(t *testing.T) { diff --git a/x/rewards/types/ibc_iprpc.go b/x/rewards/types/ibc_iprpc.go index 8c5411cad5..35535c717e 100644 --- a/x/rewards/types/ibc_iprpc.go +++ b/x/rewards/types/ibc_iprpc.go @@ -36,10 +36,6 @@ func CreateIprpcMemo(creator string, spec string, duration uint64) (memoStr stri // IbcIprpcReceiverAddress is a temporary address that holds the funds from an IPRPC over IBC request. The funds are // then immediately transferred to the pending IPRPC pool // Note, the NewModuleAddress() function is used for convenience. The IbcIprpcReceiver is not a module account -const ( - IbcIprpcReceiver = "iprpc" -) - func IbcIprpcReceiverAddress() sdk.AccAddress { return authtypes.NewModuleAddress(IbcIprpcReceiver) } @@ -49,3 +45,35 @@ func IbcIprpcReceiverAddress() sdk.AccAddress { const ( PendingIprpcPoolName Pool = "pending_iprpc_pool" ) + +// PendingIbcIprpcFund methods and constants +const ( + IbcIprpcReceiver = "iprpc" +) + +const ( + PendingIbcIprpcFundPrefix = "PendingIbcIprpcFund/" +) + +func (piif PendingIbcIprpcFund) IsEqual(other PendingIbcIprpcFund) bool { + return piif.Index == other.Index && piif.Creator == other.Creator && piif.Spec == other.Spec && + piif.Duration == other.Duration && piif.Expiry == other.Expiry && piif.Fund.IsEqual(other.Fund) +} + +func (piif PendingIbcIprpcFund) IsEmpty() bool { + return piif.IsEqual(PendingIbcIprpcFund{}) +} + +func (piif PendingIbcIprpcFund) IsValid() bool { + return piif.Expiry > 0 && piif.Fund.IsValid() && piif.Fund.Amount.IsPositive() && piif.Duration > 0 +} + +func (piif PendingIbcIprpcFund) IsExpired(ctx sdk.Context) bool { + return uint64(ctx.BlockTime().UTC().Unix()) >= piif.Expiry +} + +const ( + NewPendingIbcIprpcFundEventName = "pending_ibc_iprpc_fund_created" + ExpiredPendingIbcIprpcFundRemovedEventName = "expired_pending_ibc_iprpc_fund_removed" + CoverIbcIprpcFundCostEventName = "cover_ibc_iprpc_fund_cost" +) diff --git a/x/rewards/types/ibc_iprpc_test.go b/x/rewards/types/ibc_iprpc_test.go index 2b993cfce2..d6b03fb6c8 100644 --- a/x/rewards/types/ibc_iprpc_test.go +++ b/x/rewards/types/ibc_iprpc_test.go @@ -3,6 +3,9 @@ package types_test import ( "testing" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + commontypes "github.com/lavanet/lava/utils/common/types" "github.com/lavanet/lava/x/rewards/types" "github.com/stretchr/testify/require" ) @@ -27,3 +30,68 @@ func TestIprpcMemoIsEqual(t *testing.T) { }) } } + +// TestPendingIbcIprpcFundIsEqual tests PendingIbcIprpcFund method: IsEqual +func TestPendingIbcIprpcFundIsEqual(t *testing.T) { + piif := types.PendingIbcIprpcFund{ + Index: 1, Creator: "creator", Spec: "spec", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 10, + } + template := []struct { + name string + piif types.PendingIbcIprpcFund + isEqual bool + }{ + {"equal", types.PendingIbcIprpcFund{Index: 1, Creator: "creator", Spec: "spec", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 10}, true}, + {"different index", types.PendingIbcIprpcFund{Index: 2, Creator: "creator", Spec: "spec", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 10}, false}, + {"different creator", types.PendingIbcIprpcFund{Index: 1, Creator: "creator2", Spec: "spec", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 10}, false}, + {"different spec", types.PendingIbcIprpcFund{Index: 1, Creator: "creator", Spec: "spec2", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 10}, false}, + {"different duration", types.PendingIbcIprpcFund{Index: 1, Creator: "creator", Spec: "spec", Duration: 2, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 10}, false}, + {"different fund", types.PendingIbcIprpcFund{Index: 1, Creator: "creator", Spec: "spec", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt().AddRaw(1)), Expiry: 10}, false}, + {"different expiry", types.PendingIbcIprpcFund{Index: 1, Creator: "creator", Spec: "spec", Duration: 3, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Expiry: 12}, false}, + } + + for _, tt := range template { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.isEqual, piif.IsEqual(tt.piif)) + }) + } +} + +// TestPendingIbcIprpcFundIsEmpty tests PendingIbcIprpcFund method: IsEmpty +func TestPendingIbcIprpcFundIsEmpty(t *testing.T) { + template := []struct { + name string + piif types.PendingIbcIprpcFund + isEmpty bool + }{ + {"empty", types.PendingIbcIprpcFund{}, true}, + {"not empty", types.PendingIbcIprpcFund{Index: 1}, false}, + } + + for _, tt := range template { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.isEmpty, tt.piif.IsEmpty()) + }) + } +} + +// TestPendingIbcIprpcFundIsValid tests PendingIbcIprpcFund method: IsValid +func TestPendingIbcIprpcFundIsValid(t *testing.T) { + template := []struct { + name string + piif types.PendingIbcIprpcFund + isValid bool + }{ + {"valid", types.PendingIbcIprpcFund{Expiry: 1, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Duration: 1}, true}, + {"empty", types.PendingIbcIprpcFund{}, false}, + {"invalid expiry", types.PendingIbcIprpcFund{Expiry: 0, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Duration: 1}, false}, + {"invalid fund amount", types.PendingIbcIprpcFund{Expiry: 1, Fund: sdk.NewCoin(commontypes.TokenDenom, math.ZeroInt()), Duration: 1}, false}, + {"invalid duration", types.PendingIbcIprpcFund{Expiry: 1, Fund: sdk.NewCoin(commontypes.TokenDenom, math.OneInt()), Duration: 0}, false}, + } + + for _, tt := range template { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.isValid, tt.piif.IsValid()) + }) + } +} diff --git a/x/rewards/types/iprpc.pb.go b/x/rewards/types/iprpc.pb.go index f8d29aca9a..3ede0b7d18 100644 --- a/x/rewards/types/iprpc.pb.go +++ b/x/rewards/types/iprpc.pb.go @@ -190,38 +190,127 @@ func (m *IprpcMemo) GetDuration() uint64 { return 0 } +type PendingIbcIprpcFund struct { + Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Creator string `protobuf:"bytes,2,opt,name=creator,proto3" json:"creator,omitempty"` + Spec string `protobuf:"bytes,3,opt,name=spec,proto3" json:"spec,omitempty"` + Duration uint64 `protobuf:"varint,4,opt,name=duration,proto3" json:"duration,omitempty"` + Fund types.Coin `protobuf:"bytes,5,opt,name=fund,proto3" json:"fund"` + Expiry uint64 `protobuf:"varint,6,opt,name=expiry,proto3" json:"expiry,omitempty"` +} + +func (m *PendingIbcIprpcFund) Reset() { *m = PendingIbcIprpcFund{} } +func (m *PendingIbcIprpcFund) String() string { return proto.CompactTextString(m) } +func (*PendingIbcIprpcFund) ProtoMessage() {} +func (*PendingIbcIprpcFund) Descriptor() ([]byte, []int) { + return fileDescriptor_1293618a311573f7, []int{3} +} +func (m *PendingIbcIprpcFund) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PendingIbcIprpcFund) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PendingIbcIprpcFund.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 *PendingIbcIprpcFund) XXX_Merge(src proto.Message) { + xxx_messageInfo_PendingIbcIprpcFund.Merge(m, src) +} +func (m *PendingIbcIprpcFund) XXX_Size() int { + return m.Size() +} +func (m *PendingIbcIprpcFund) XXX_DiscardUnknown() { + xxx_messageInfo_PendingIbcIprpcFund.DiscardUnknown(m) +} + +var xxx_messageInfo_PendingIbcIprpcFund proto.InternalMessageInfo + +func (m *PendingIbcIprpcFund) GetIndex() uint64 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *PendingIbcIprpcFund) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *PendingIbcIprpcFund) GetSpec() string { + if m != nil { + return m.Spec + } + return "" +} + +func (m *PendingIbcIprpcFund) GetDuration() uint64 { + if m != nil { + return m.Duration + } + return 0 +} + +func (m *PendingIbcIprpcFund) GetFund() types.Coin { + if m != nil { + return m.Fund + } + return types.Coin{} +} + +func (m *PendingIbcIprpcFund) GetExpiry() uint64 { + if m != nil { + return m.Expiry + } + return 0 +} + func init() { proto.RegisterType((*IprpcReward)(nil), "lavanet.lava.rewards.IprpcReward") proto.RegisterType((*Specfund)(nil), "lavanet.lava.rewards.Specfund") proto.RegisterType((*IprpcMemo)(nil), "lavanet.lava.rewards.IprpcMemo") + proto.RegisterType((*PendingIbcIprpcFund)(nil), "lavanet.lava.rewards.PendingIbcIprpcFund") } func init() { proto.RegisterFile("lavanet/lava/rewards/iprpc.proto", fileDescriptor_1293618a311573f7) } var fileDescriptor_1293618a311573f7 = []byte{ - // 343 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xb1, 0x4e, 0xf3, 0x30, - 0x14, 0x85, 0x93, 0x34, 0xfa, 0xff, 0xd6, 0x95, 0x18, 0xac, 0x0e, 0xa1, 0x83, 0x5b, 0x75, 0xa1, - 0x0b, 0x36, 0x85, 0x27, 0xa0, 0x95, 0x90, 0x18, 0x58, 0x82, 0x58, 0x58, 0x2a, 0xc7, 0x31, 0xc5, - 0x82, 0xc6, 0x91, 0xed, 0x16, 0x98, 0x78, 0x05, 0x9e, 0x83, 0x27, 0xe9, 0xd8, 0x91, 0x09, 0x50, - 0xfb, 0x22, 0xc8, 0x8e, 0x1b, 0x15, 0x89, 0xe9, 0xda, 0x3a, 0xe7, 0x1e, 0x7f, 0xd7, 0x17, 0xf4, - 0x1f, 0xe9, 0x92, 0x16, 0xdc, 0x10, 0x5b, 0x89, 0xe2, 0x4f, 0x54, 0xe5, 0x9a, 0x88, 0x52, 0x95, - 0x0c, 0x97, 0x4a, 0x1a, 0x09, 0x3b, 0xde, 0x81, 0x6d, 0xc5, 0xde, 0xd1, 0xed, 0xcc, 0xe4, 0x4c, - 0x3a, 0x03, 0xb1, 0xa7, 0xca, 0xdb, 0x45, 0x4c, 0xea, 0xb9, 0xd4, 0x24, 0xa3, 0x9a, 0x93, 0xe5, - 0x28, 0xe3, 0x86, 0x8e, 0x08, 0x93, 0xa2, 0xa8, 0xf4, 0x41, 0x06, 0xda, 0x97, 0x36, 0x3a, 0x75, - 0x29, 0xf0, 0x00, 0x44, 0x22, 0x4f, 0xc2, 0x7e, 0x38, 0x8c, 0xd3, 0x48, 0xe4, 0x70, 0x02, 0x80, - 0x2e, 0x39, 0x9b, 0xde, 0x2d, 0x8a, 0x5c, 0x27, 0x51, 0xbf, 0x31, 0x6c, 0x9f, 0x22, 0xfc, 0xd7, - 0xfb, 0xf8, 0xba, 0xe4, 0xcc, 0xda, 0xc6, 0xf1, 0xea, 0xb3, 0x17, 0xa4, 0x2d, 0xdb, 0x77, 0x61, - 0xdb, 0x06, 0xaf, 0xa0, 0xb9, 0x13, 0x21, 0x04, 0xb1, 0x15, 0xdc, 0x13, 0xad, 0xd4, 0x9d, 0xe1, - 0x14, 0xc4, 0x56, 0xf3, 0xf1, 0x87, 0xb8, 0x42, 0xc6, 0x16, 0x19, 0x7b, 0x64, 0x3c, 0x91, 0xa2, - 0x18, 0x9f, 0xd8, 0xe4, 0xf7, 0xaf, 0xde, 0x70, 0x26, 0xcc, 0xfd, 0x22, 0xc3, 0x4c, 0xce, 0x89, - 0x9f, 0xaf, 0x2a, 0xc7, 0x3a, 0x7f, 0x20, 0xe6, 0xa5, 0xe4, 0xda, 0x35, 0xe8, 0xd4, 0x05, 0x0f, - 0x6e, 0x40, 0xcb, 0x0d, 0x79, 0xc5, 0xe7, 0x12, 0x26, 0xe0, 0x3f, 0x53, 0x9c, 0x1a, 0xa9, 0x3c, - 0xc4, 0xee, 0x5a, 0xb3, 0x45, 0x7b, 0x6c, 0x5d, 0xd0, 0xcc, 0x17, 0x8a, 0x1a, 0x21, 0x8b, 0xa4, - 0xe1, 0xbe, 0xa5, 0xbe, 0x8f, 0xcf, 0x57, 0x1b, 0x14, 0xae, 0x37, 0x28, 0xfc, 0xde, 0xa0, 0xf0, - 0x6d, 0x8b, 0x82, 0xf5, 0x16, 0x05, 0x1f, 0x5b, 0x14, 0xdc, 0x1e, 0xed, 0x01, 0xfe, 0x5a, 0xe7, - 0x73, 0xbd, 0x50, 0x47, 0x99, 0xfd, 0x73, 0x5b, 0x38, 0xfb, 0x09, 0x00, 0x00, 0xff, 0xff, 0x51, - 0x32, 0xe9, 0xcc, 0xf5, 0x01, 0x00, 0x00, + // 411 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xb1, 0xae, 0xd3, 0x30, + 0x14, 0x4d, 0xd2, 0xbc, 0xf2, 0xea, 0x27, 0x31, 0x98, 0x0a, 0x85, 0x0e, 0x7e, 0x51, 0x16, 0xba, + 0x60, 0x53, 0xfa, 0x05, 0xb4, 0x12, 0x52, 0x07, 0x24, 0x14, 0xc4, 0xc2, 0x52, 0x25, 0xb6, 0x09, + 0x16, 0xd4, 0x8e, 0xec, 0xb4, 0xb4, 0x13, 0xbf, 0xc0, 0x77, 0xf0, 0x19, 0x4c, 0x1d, 0x3b, 0x32, + 0x01, 0x6a, 0x7f, 0x04, 0xd9, 0x71, 0xab, 0x56, 0x2a, 0x4c, 0xce, 0xd5, 0x3d, 0xf7, 0x9c, 0x73, + 0x4f, 0x2e, 0x48, 0x3f, 0x17, 0xab, 0x42, 0xf2, 0x86, 0xd8, 0x97, 0x68, 0xfe, 0xa5, 0xd0, 0xcc, + 0x10, 0x51, 0xeb, 0x9a, 0xe2, 0x5a, 0xab, 0x46, 0xc1, 0xbe, 0x47, 0x60, 0xfb, 0x62, 0x8f, 0x18, + 0xf4, 0x2b, 0x55, 0x29, 0x07, 0x20, 0xf6, 0xab, 0xc5, 0x0e, 0x10, 0x55, 0x66, 0xa1, 0x0c, 0x29, + 0x0b, 0xc3, 0xc9, 0x6a, 0x54, 0xf2, 0xa6, 0x18, 0x11, 0xaa, 0x84, 0x6c, 0xfb, 0x59, 0x09, 0xee, + 0x66, 0x96, 0x3a, 0x77, 0x2c, 0xf0, 0x21, 0x88, 0x04, 0x4b, 0xc2, 0x34, 0x1c, 0xc6, 0x79, 0x24, + 0x18, 0x9c, 0x02, 0x60, 0x6a, 0x4e, 0xe7, 0x1f, 0x96, 0x92, 0x99, 0x24, 0x4a, 0x3b, 0xc3, 0xbb, + 0x17, 0x08, 0x5f, 0xd3, 0xc7, 0x6f, 0x6b, 0x4e, 0x2d, 0x6c, 0x12, 0x6f, 0x7f, 0xdd, 0x07, 0x79, + 0xcf, 0xce, 0xbd, 0xb2, 0x63, 0xd9, 0x57, 0x70, 0x7b, 0x6c, 0x42, 0x08, 0x62, 0xdb, 0x70, 0x12, + 0xbd, 0xdc, 0x7d, 0xc3, 0x39, 0x88, 0x6d, 0xcf, 0xd3, 0x3f, 0xc1, 0xad, 0x65, 0x6c, 0x2d, 0x63, + 0x6f, 0x19, 0x4f, 0x95, 0x90, 0x93, 0xe7, 0x96, 0xf9, 0xfb, 0xef, 0xfb, 0x61, 0x25, 0x9a, 0x8f, + 0xcb, 0x12, 0x53, 0xb5, 0x20, 0x7e, 0xbf, 0xf6, 0x79, 0x66, 0xd8, 0x27, 0xd2, 0x6c, 0x6a, 0x6e, + 0xdc, 0x80, 0xc9, 0x1d, 0x71, 0xf6, 0x0e, 0xf4, 0xdc, 0x92, 0xaf, 0xf9, 0x42, 0xc1, 0x04, 0x3c, + 0xa0, 0x9a, 0x17, 0x8d, 0xd2, 0xde, 0xc4, 0xb1, 0x3c, 0x79, 0x8b, 0xce, 0xbc, 0x0d, 0xc0, 0x2d, + 0x5b, 0xea, 0xa2, 0x11, 0x4a, 0x26, 0x1d, 0x17, 0xcb, 0xa9, 0xce, 0x7e, 0x84, 0xe0, 0xd1, 0x1b, + 0x2e, 0x99, 0x90, 0xd5, 0xac, 0xa4, 0x4e, 0xc1, 0x2e, 0x0c, 0xfb, 0xe0, 0x46, 0x48, 0xc6, 0xd7, + 0x3e, 0xc7, 0xb6, 0x38, 0xd7, 0x8d, 0xae, 0xeb, 0x76, 0xfe, 0xa1, 0x1b, 0x5f, 0xea, 0xc2, 0xb1, + 0xcf, 0xeb, 0x26, 0x0d, 0xff, 0x9f, 0x57, 0xfb, 0x27, 0x1c, 0x18, 0x3e, 0x06, 0x5d, 0xbe, 0xae, + 0x85, 0xde, 0x24, 0x5d, 0x47, 0xe7, 0xab, 0xc9, 0xcb, 0xed, 0x1e, 0x85, 0xbb, 0x3d, 0x0a, 0xff, + 0xec, 0x51, 0xf8, 0xed, 0x80, 0x82, 0xdd, 0x01, 0x05, 0x3f, 0x0f, 0x28, 0x78, 0xff, 0xf4, 0x2c, + 0xe5, 0x8b, 0x9b, 0x5c, 0x9f, 0xae, 0xd2, 0x45, 0x5d, 0x76, 0xdd, 0x29, 0x8d, 0xff, 0x06, 0x00, + 0x00, 0xff, 0xff, 0xae, 0x70, 0x26, 0xfe, 0xba, 0x02, 0x00, 0x00, } func (m *IprpcReward) Marshal() (dAtA []byte, err error) { @@ -352,6 +441,68 @@ func (m *IprpcMemo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PendingIbcIprpcFund) 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 *PendingIbcIprpcFund) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PendingIbcIprpcFund) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Expiry != 0 { + i = encodeVarintIprpc(dAtA, i, uint64(m.Expiry)) + i-- + dAtA[i] = 0x30 + } + { + size, err := m.Fund.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintIprpc(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if m.Duration != 0 { + i = encodeVarintIprpc(dAtA, i, uint64(m.Duration)) + i-- + dAtA[i] = 0x20 + } + if len(m.Spec) > 0 { + i -= len(m.Spec) + copy(dAtA[i:], m.Spec) + i = encodeVarintIprpc(dAtA, i, uint64(len(m.Spec))) + i-- + dAtA[i] = 0x1a + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintIprpc(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x12 + } + if m.Index != 0 { + i = encodeVarintIprpc(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintIprpc(dAtA []byte, offset int, v uint64) int { offset -= sovIprpc(v) base := offset @@ -420,6 +571,34 @@ func (m *IprpcMemo) Size() (n int) { return n } +func (m *PendingIbcIprpcFund) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Index != 0 { + n += 1 + sovIprpc(uint64(m.Index)) + } + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovIprpc(uint64(l)) + } + l = len(m.Spec) + if l > 0 { + n += 1 + l + sovIprpc(uint64(l)) + } + if m.Duration != 0 { + n += 1 + sovIprpc(uint64(m.Duration)) + } + l = m.Fund.Size() + n += 1 + l + sovIprpc(uint64(l)) + if m.Expiry != 0 { + n += 1 + sovIprpc(uint64(m.Expiry)) + } + return n +} + func sovIprpc(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -778,6 +957,210 @@ func (m *IprpcMemo) Unmarshal(dAtA []byte) error { } return nil } +func (m *PendingIbcIprpcFund) 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 ErrIntOverflowIprpc + } + 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: PendingIbcIprpcFund: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PendingIbcIprpcFund: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIprpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIprpc + } + 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 ErrInvalidLengthIprpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIprpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIprpc + } + 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 ErrInvalidLengthIprpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIprpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Spec = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", wireType) + } + m.Duration = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIprpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Duration |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Fund", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIprpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthIprpc + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthIprpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Fund.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + m.Expiry = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIprpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Expiry |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipIprpc(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthIprpc + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipIprpc(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/rewards/types/message_cover_ibc_iprpc_fund_cost.go b/x/rewards/types/message_cover_ibc_iprpc_fund_cost.go new file mode 100644 index 0000000000..6e6165ddf5 --- /dev/null +++ b/x/rewards/types/message_cover_ibc_iprpc_fund_cost.go @@ -0,0 +1,48 @@ +package types + +import ( + sdkerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgCoverIbcIprpcFundCost = "cover_ibc_iprpc_fund_cost" + +var _ sdk.Msg = &MsgCoverIbcIprpcFundCost{} + +func NewMsgCoverIbcIprpcFundCost(creator string, index uint64) *MsgCoverIbcIprpcFundCost { + return &MsgCoverIbcIprpcFundCost{ + Creator: creator, + Index: index, + } +} + +func (msg *MsgCoverIbcIprpcFundCost) Route() string { + return RouterKey +} + +func (msg *MsgCoverIbcIprpcFundCost) Type() string { + return TypeMsgCoverIbcIprpcFundCost +} + +func (msg *MsgCoverIbcIprpcFundCost) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + return []sdk.AccAddress{creator} +} + +func (msg *MsgCoverIbcIprpcFundCost) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgCoverIbcIprpcFundCost) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkerrors.Wrapf(legacyerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + + return nil +} diff --git a/x/rewards/types/message_cover_ibc_iprpc_fund_cost_test.go b/x/rewards/types/message_cover_ibc_iprpc_fund_cost_test.go new file mode 100644 index 0000000000..cb0245e406 --- /dev/null +++ b/x/rewards/types/message_cover_ibc_iprpc_fund_cost_test.go @@ -0,0 +1,43 @@ +package types + +import ( + "testing" + + "github.com/lavanet/lava/testutil/sample" + "github.com/stretchr/testify/require" +) + +func TestCoverIbcIprpcFundCost_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg MsgCoverIbcIprpcFundCost + valid bool + }{ + { + name: "valid", + msg: MsgCoverIbcIprpcFundCost{ + Creator: sample.AccAddress(), + Index: 1, + }, + valid: true, + }, + { + name: "invalid creator address", + msg: MsgCoverIbcIprpcFundCost{ + Creator: "invalid_address", + Index: 1, + }, + valid: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.msg.ValidateBasic() + if tt.valid { + require.NoError(t, err) + return + } + require.Error(t, err) + }) + } +} diff --git a/x/rewards/types/params.go b/x/rewards/types/params.go index c085a97409..58d6309e51 100644 --- a/x/rewards/types/params.go +++ b/x/rewards/types/params.go @@ -2,6 +2,7 @@ package types import ( "fmt" + "time" sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" @@ -40,6 +41,11 @@ var ( DefaultValidatorsSubscriptionParticipation sdk.Dec = sdk.NewDecWithPrec(5, 2) // 0.05 ) +var ( + KeyIbcIprpcExpiration = []byte("IbcIprpcExpiration") + DefaultIbcIprpcExpiration time.Duration = time.Hour * 24 * 30 * 3 // 3 months +) + // ParamKeyTable the param key table for launch module func ParamKeyTable() paramtypes.KeyTable { return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) @@ -53,6 +59,7 @@ func NewParams( leftoverBurnRate sdk.Dec, maxRewardBoost uint64, validatorsSubscriptionParticipation sdk.Dec, + ibcIprpcExpiration time.Duration, ) Params { return Params{ MinBondedTarget: minBondedTarget, @@ -61,6 +68,7 @@ func NewParams( LeftoverBurnRate: leftoverBurnRate, MaxRewardBoost: maxRewardBoost, ValidatorsSubscriptionParticipation: validatorsSubscriptionParticipation, + IbcIprpcExpiration: ibcIprpcExpiration, } } @@ -73,6 +81,7 @@ func DefaultParams() Params { DefaultLeftOverBurnRate, DefaultMaxRewardBoost, DefaultValidatorsSubscriptionParticipation, + DefaultIbcIprpcExpiration, ) } @@ -85,6 +94,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeyLeftoverBurnRate, &p.LeftoverBurnRate, validateDec), paramtypes.NewParamSetPair(KeyMaxRewardBoost, &p.MaxRewardBoost, validateuint64), paramtypes.NewParamSetPair(KeyValidatorsSubscriptionParticipation, &p.ValidatorsSubscriptionParticipation, validateDec), + paramtypes.NewParamSetPair(KeyIbcIprpcExpiration, &p.IbcIprpcExpiration, validateDuration), } } @@ -118,6 +128,10 @@ func (p Params) Validate() error { return fmt.Errorf("invalid ValidatorsSubscriptionParticipation. Error: %s", err.Error()) } + if err := validateDuration(p.IbcIprpcExpiration); err != nil { + return fmt.Errorf("invalid IbcIprpcExpiration. Error: %s", err.Error()) + } + return nil } @@ -149,3 +163,16 @@ func validateuint64(v interface{}) error { return nil } + +func validateDuration(v interface{}) error { + param, ok := v.(time.Duration) + if !ok { + return fmt.Errorf("invalid parameter type: %T", v) + } + + if param.Seconds() == float64(0) { + return fmt.Errorf("invalid duration parameter") + } + + return nil +} diff --git a/x/rewards/types/params.pb.go b/x/rewards/types/params.pb.go index 248deb19ec..c436ea6649 100644 --- a/x/rewards/types/params.pb.go +++ b/x/rewards/types/params.pb.go @@ -8,15 +8,19 @@ import ( github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/durationpb" io "io" math "math" math_bits "math/bits" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +var _ = time.Kitchen // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -32,6 +36,7 @@ type Params struct { LeftoverBurnRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=leftover_burn_rate,json=leftoverBurnRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"leftover_burn_rate" yaml:"leftover_burn_rate"` MaxRewardBoost uint64 `protobuf:"varint,5,opt,name=max_reward_boost,json=maxRewardBoost,proto3" json:"max_reward_boost,omitempty"` ValidatorsSubscriptionParticipation github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=validators_subscription_participation,json=validatorsSubscriptionParticipation,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"validators_subscription_participation" yaml:"validators_subscription_participation"` + IbcIprpcExpiration time.Duration `protobuf:"bytes,7,opt,name=ibc_iprpc_expiration,json=ibcIprpcExpiration,proto3,stdduration" json:"ibc_iprpc_expiration" yaml:"ibc_iprpc_expiration"` } func (m *Params) Reset() { *m = Params{} } @@ -73,6 +78,13 @@ func (m *Params) GetMaxRewardBoost() uint64 { return 0 } +func (m *Params) GetIbcIprpcExpiration() time.Duration { + if m != nil { + return m.IbcIprpcExpiration + } + return 0 +} + func init() { proto.RegisterType((*Params)(nil), "lavanet.lava.rewards.Params") } @@ -80,34 +92,39 @@ func init() { func init() { proto.RegisterFile("lavanet/lava/rewards/params.proto", fileDescriptor_12687c5fbcde5c39) } var fileDescriptor_12687c5fbcde5c39 = []byte{ - // 418 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xbf, 0x8e, 0x94, 0x50, - 0x14, 0xc6, 0x41, 0x67, 0x27, 0xd9, 0x5b, 0xe8, 0x2e, 0xd9, 0x02, 0x2d, 0x60, 0xc5, 0xa8, 0x53, - 0x28, 0x14, 0x76, 0xdb, 0x89, 0xc6, 0x42, 0x9b, 0x0d, 0x5a, 0x59, 0x78, 0x73, 0x80, 0xbb, 0x78, - 0x23, 0x70, 0xc8, 0xbd, 0x17, 0x86, 0x79, 0x0b, 0x4b, 0x4b, 0x9f, 0xc1, 0xda, 0x07, 0xd8, 0x72, - 0x4a, 0x63, 0x31, 0x31, 0x33, 0x6f, 0xe0, 0x13, 0x18, 0x2e, 0xe8, 0xfc, 0x6b, 0x9c, 0x58, 0x9d, - 0xc3, 0x97, 0x8f, 0xef, 0xf7, 0x05, 0x72, 0xc8, 0xbd, 0x1c, 0x1a, 0x28, 0x99, 0x0a, 0xba, 0x19, - 0x08, 0x36, 0x05, 0x91, 0xca, 0xa0, 0x02, 0x01, 0x85, 0xf4, 0x2b, 0x81, 0x0a, 0xad, 0xb3, 0xc1, - 0xe2, 0x77, 0xd3, 0x1f, 0x2c, 0x77, 0xcf, 0x32, 0xcc, 0x50, 0x1b, 0x82, 0x6e, 0xeb, 0xbd, 0xde, - 0xb7, 0x23, 0x32, 0xbe, 0xd4, 0x2f, 0x5b, 0x0d, 0x39, 0x2d, 0x78, 0x49, 0x63, 0x2c, 0x53, 0x96, - 0x52, 0x05, 0x22, 0x63, 0xca, 0x36, 0xcf, 0xcd, 0xc9, 0x71, 0xf8, 0xea, 0x7a, 0xe1, 0x1a, 0x3f, - 0x16, 0xee, 0xc3, 0x8c, 0xab, 0x0f, 0x75, 0xec, 0x27, 0x58, 0x04, 0x09, 0xca, 0x02, 0xe5, 0x30, - 0x9e, 0xc8, 0xf4, 0x63, 0xa0, 0x66, 0x15, 0x93, 0xfe, 0x0b, 0x96, 0xfc, 0x5a, 0xb8, 0xf6, 0x0c, - 0x8a, 0xfc, 0xc2, 0xdb, 0x0b, 0xf4, 0xa2, 0xdb, 0x05, 0x2f, 0x43, 0x2d, 0xbd, 0xd5, 0x8a, 0xe6, - 0x42, 0xbb, 0xc3, 0xbd, 0xf1, 0x9f, 0xdc, 0xdd, 0xc0, 0x8e, 0x0b, 0xed, 0x16, 0x37, 0x26, 0x24, - 0xc7, 0x29, 0xbd, 0x82, 0x44, 0xa1, 0xb0, 0x6f, 0x6a, 0xe0, 0xf3, 0x83, 0x81, 0xa7, 0x3d, 0x70, - 0x9d, 0xe4, 0x45, 0xc7, 0x39, 0x4e, 0x5f, 0xea, 0xdd, 0x9a, 0x11, 0x2b, 0x67, 0x57, 0x0a, 0x1b, - 0x26, 0x68, 0x5c, 0x8b, 0x92, 0x0a, 0x50, 0xcc, 0x1e, 0x69, 0xd6, 0xeb, 0x83, 0x59, 0x77, 0x06, - 0xd6, 0x5e, 0xa2, 0x17, 0x9d, 0xfc, 0x11, 0xc3, 0x5a, 0x94, 0x11, 0x28, 0x66, 0x4d, 0xc8, 0x49, - 0xf7, 0x15, 0xfa, 0xdf, 0x4f, 0x63, 0x44, 0xa9, 0xec, 0xa3, 0x73, 0x73, 0x32, 0x8a, 0x6e, 0x15, - 0xd0, 0x46, 0x5a, 0x0e, 0x3b, 0xd5, 0xfa, 0x6a, 0x92, 0x07, 0x0d, 0xe4, 0x3c, 0x05, 0x85, 0x42, - 0x52, 0x59, 0xc7, 0x32, 0x11, 0xbc, 0x52, 0x1c, 0x4b, 0x5a, 0x81, 0x50, 0x3c, 0xe1, 0x15, 0x74, - 0x4f, 0xf6, 0x58, 0x17, 0x7f, 0x7f, 0x70, 0xf1, 0xc7, 0x7d, 0xf1, 0x7f, 0x82, 0x78, 0xd1, 0xfd, - 0xb5, 0xef, 0xcd, 0x86, 0xed, 0x72, 0xd3, 0x75, 0x31, 0xfa, 0xfc, 0xc5, 0x35, 0xc2, 0x67, 0xd7, - 0x4b, 0xc7, 0x9c, 0x2f, 0x1d, 0xf3, 0xe7, 0xd2, 0x31, 0x3f, 0xad, 0x1c, 0x63, 0xbe, 0x72, 0x8c, - 0xef, 0x2b, 0xc7, 0x78, 0xf7, 0x68, 0xa3, 0xdc, 0xd6, 0xc9, 0xb4, 0x7f, 0x8f, 0x46, 0x37, 0x8c, - 0xc7, 0xfa, 0x10, 0x9e, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xed, 0xaf, 0xe7, 0x4f, 0x59, 0x03, - 0x00, 0x00, + // 497 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xb1, 0x6e, 0xd3, 0x40, + 0x1c, 0xc6, 0x6d, 0x08, 0x41, 0x35, 0x12, 0xb4, 0x56, 0x06, 0xb7, 0x48, 0x76, 0x30, 0x82, 0x66, + 0x00, 0x5b, 0x82, 0xad, 0x1b, 0xa6, 0x20, 0x01, 0x4b, 0x65, 0x98, 0x18, 0x38, 0xdd, 0xd9, 0x17, + 0x73, 0xc2, 0xf6, 0xdf, 0xba, 0x3b, 0x27, 0xce, 0x5b, 0x30, 0x76, 0xe4, 0x19, 0xfa, 0x14, 0x1d, + 0x3b, 0x22, 0x86, 0x80, 0x92, 0x37, 0xe8, 0x13, 0xa0, 0x3b, 0xbb, 0x6d, 0xda, 0x32, 0x10, 0x75, + 0x3a, 0xfb, 0x7f, 0x9f, 0xbe, 0xdf, 0xa7, 0xbf, 0xbe, 0xb3, 0x1e, 0xe5, 0x78, 0x82, 0x4b, 0x2a, + 0x43, 0x75, 0x86, 0x9c, 0x4e, 0x31, 0x4f, 0x45, 0x58, 0x61, 0x8e, 0x0b, 0x11, 0x54, 0x1c, 0x24, + 0xd8, 0x83, 0x4e, 0x12, 0xa8, 0x33, 0xe8, 0x24, 0x3b, 0x83, 0x0c, 0x32, 0xd0, 0x82, 0x50, 0x7d, + 0xb5, 0xda, 0x1d, 0x37, 0x03, 0xc8, 0x72, 0x1a, 0xea, 0x3f, 0x52, 0x8f, 0xc3, 0xb4, 0xe6, 0x58, + 0x32, 0x28, 0xdb, 0x7b, 0xff, 0xa8, 0x6f, 0xf5, 0x0f, 0xb4, 0xb9, 0x3d, 0xb1, 0xb6, 0x0a, 0x56, + 0x22, 0x02, 0x65, 0x4a, 0x53, 0x24, 0x31, 0xcf, 0xa8, 0x74, 0xcc, 0xa1, 0x39, 0xda, 0x88, 0xde, + 0x1f, 0xcf, 0x3d, 0xe3, 0xd7, 0xdc, 0x7b, 0x9a, 0x31, 0xf9, 0xb5, 0x26, 0x41, 0x02, 0x45, 0x98, + 0x80, 0x28, 0x40, 0x74, 0xc7, 0x73, 0x91, 0x7e, 0x0b, 0xe5, 0xac, 0xa2, 0x22, 0xd8, 0xa7, 0xc9, + 0xe9, 0xdc, 0x73, 0x66, 0xb8, 0xc8, 0xf7, 0xfc, 0x6b, 0x86, 0x7e, 0xfc, 0xa0, 0x60, 0x65, 0xa4, + 0x47, 0x9f, 0xf4, 0x44, 0x73, 0x71, 0x73, 0x85, 0x7b, 0xeb, 0x86, 0xdc, 0xab, 0x86, 0x8a, 0x8b, + 0x9b, 0x4b, 0x5c, 0x62, 0x59, 0x39, 0x4c, 0xd1, 0x18, 0x27, 0x12, 0xb8, 0x73, 0x5b, 0x03, 0x5f, + 0xaf, 0x0d, 0xdc, 0x6a, 0x81, 0x17, 0x4e, 0x7e, 0xbc, 0x91, 0xc3, 0xf4, 0xad, 0xfe, 0xb6, 0x67, + 0x96, 0x9d, 0xd3, 0xb1, 0x84, 0x09, 0xe5, 0x88, 0xd4, 0xbc, 0x44, 0x1c, 0x4b, 0xea, 0xf4, 0x34, + 0xeb, 0xc3, 0xda, 0xac, 0xed, 0x8e, 0x75, 0xcd, 0xd1, 0x8f, 0x37, 0xcf, 0x86, 0x51, 0xcd, 0xcb, + 0x18, 0x4b, 0x6a, 0x8f, 0xac, 0x4d, 0xb5, 0x85, 0xb6, 0x1e, 0x88, 0x00, 0x08, 0xe9, 0xdc, 0x19, + 0x9a, 0xa3, 0x5e, 0x7c, 0xbf, 0xc0, 0x4d, 0xac, 0xc7, 0x91, 0x9a, 0xda, 0x47, 0xa6, 0xf5, 0x64, + 0x82, 0x73, 0x96, 0x62, 0x09, 0x5c, 0x20, 0x51, 0x13, 0x91, 0x70, 0x56, 0xa9, 0x96, 0xa0, 0x0a, + 0x73, 0xc9, 0x12, 0x56, 0xe9, 0xce, 0x38, 0x7d, 0x1d, 0xfc, 0xcb, 0xda, 0xc1, 0x9f, 0xb5, 0xc1, + 0xff, 0x0b, 0xe2, 0xc7, 0x8f, 0x2f, 0x74, 0x1f, 0x57, 0x64, 0x07, 0xab, 0x2a, 0x5b, 0x5a, 0x03, + 0x46, 0x12, 0xc4, 0x2a, 0x5e, 0x25, 0x88, 0x36, 0x15, 0x6b, 0x6b, 0xed, 0xdc, 0x1d, 0x9a, 0xa3, + 0x7b, 0x2f, 0xb6, 0x83, 0xb6, 0xf7, 0xc1, 0x59, 0xef, 0x83, 0xfd, 0xae, 0xf7, 0xd1, 0xae, 0x4a, + 0x7f, 0x3a, 0xf7, 0x1e, 0xb6, 0x99, 0xfe, 0x65, 0xe2, 0x1f, 0xfe, 0xf6, 0xcc, 0xd8, 0x66, 0x24, + 0x79, 0xa7, 0x6e, 0xde, 0x9c, 0x5f, 0xec, 0xf5, 0x0e, 0x7f, 0x78, 0x46, 0xf4, 0xea, 0x78, 0xe1, + 0x9a, 0x27, 0x0b, 0xd7, 0xfc, 0xb3, 0x70, 0xcd, 0xef, 0x4b, 0xd7, 0x38, 0x59, 0xba, 0xc6, 0xcf, + 0xa5, 0x6b, 0x7c, 0xde, 0x5d, 0x59, 0xc9, 0xa5, 0x87, 0xdc, 0x9c, 0x3f, 0x65, 0xbd, 0x17, 0xd2, + 0xd7, 0xc1, 0x5e, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x76, 0x3d, 0xbd, 0xec, 0xef, 0x03, 0x00, + 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -130,6 +147,14 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + n1, err1 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.IbcIprpcExpiration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.IbcIprpcExpiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintParams(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x3a { size := m.ValidatorsSubscriptionParticipation.Size() i -= size @@ -218,6 +243,8 @@ func (m *Params) Size() (n int) { } l = m.ValidatorsSubscriptionParticipation.Size() n += 1 + l + sovParams(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.IbcIprpcExpiration) + n += 1 + l + sovParams(uint64(l)) return n } @@ -445,6 +472,39 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IbcIprpcExpiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.IbcIprpcExpiration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/rewards/types/query.pb.go b/x/rewards/types/query.pb.go index dfd1109e68..893b6314d8 100644 --- a/x/rewards/types/query.pb.go +++ b/x/rewards/types/query.pb.go @@ -800,6 +800,148 @@ func (m *QueryIprpcSpecRewardResponse) GetCurrentMonthId() uint64 { return 0 } +// QueryPendingIbcIprpcFundsRequest is request type for the Query/PendingIbcIprpcFund RPC method. +type QueryPendingIbcIprpcFundsRequest struct { + Filter string `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` +} + +func (m *QueryPendingIbcIprpcFundsRequest) Reset() { *m = QueryPendingIbcIprpcFundsRequest{} } +func (m *QueryPendingIbcIprpcFundsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPendingIbcIprpcFundsRequest) ProtoMessage() {} +func (*QueryPendingIbcIprpcFundsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_15bce9a904340007, []int{16} +} +func (m *QueryPendingIbcIprpcFundsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPendingIbcIprpcFundsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPendingIbcIprpcFundsRequest.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 *QueryPendingIbcIprpcFundsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPendingIbcIprpcFundsRequest.Merge(m, src) +} +func (m *QueryPendingIbcIprpcFundsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPendingIbcIprpcFundsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPendingIbcIprpcFundsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPendingIbcIprpcFundsRequest proto.InternalMessageInfo + +func (m *QueryPendingIbcIprpcFundsRequest) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +type PendingIbcIprpcFundInfo struct { + PendingIbcIprpcFund PendingIbcIprpcFund `protobuf:"bytes,1,opt,name=pending_ibc_iprpc_fund,json=pendingIbcIprpcFund,proto3" json:"pending_ibc_iprpc_fund"` + Cost types.Coin `protobuf:"bytes,2,opt,name=cost,proto3" json:"cost"` +} + +func (m *PendingIbcIprpcFundInfo) Reset() { *m = PendingIbcIprpcFundInfo{} } +func (m *PendingIbcIprpcFundInfo) String() string { return proto.CompactTextString(m) } +func (*PendingIbcIprpcFundInfo) ProtoMessage() {} +func (*PendingIbcIprpcFundInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_15bce9a904340007, []int{17} +} +func (m *PendingIbcIprpcFundInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PendingIbcIprpcFundInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PendingIbcIprpcFundInfo.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 *PendingIbcIprpcFundInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_PendingIbcIprpcFundInfo.Merge(m, src) +} +func (m *PendingIbcIprpcFundInfo) XXX_Size() int { + return m.Size() +} +func (m *PendingIbcIprpcFundInfo) XXX_DiscardUnknown() { + xxx_messageInfo_PendingIbcIprpcFundInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_PendingIbcIprpcFundInfo proto.InternalMessageInfo + +func (m *PendingIbcIprpcFundInfo) GetPendingIbcIprpcFund() PendingIbcIprpcFund { + if m != nil { + return m.PendingIbcIprpcFund + } + return PendingIbcIprpcFund{} +} + +func (m *PendingIbcIprpcFundInfo) GetCost() types.Coin { + if m != nil { + return m.Cost + } + return types.Coin{} +} + +// QueryPendingIbcIprpcFundsResponse is response type for the Query/PendingIbcIprpcFund RPC method. +type QueryPendingIbcIprpcFundsResponse struct { + PendingIbcIprpcFundsInfo []PendingIbcIprpcFundInfo `protobuf:"bytes,1,rep,name=pending_ibc_iprpc_funds_info,json=pendingIbcIprpcFundsInfo,proto3" json:"pending_ibc_iprpc_funds_info"` +} + +func (m *QueryPendingIbcIprpcFundsResponse) Reset() { *m = QueryPendingIbcIprpcFundsResponse{} } +func (m *QueryPendingIbcIprpcFundsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPendingIbcIprpcFundsResponse) ProtoMessage() {} +func (*QueryPendingIbcIprpcFundsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_15bce9a904340007, []int{18} +} +func (m *QueryPendingIbcIprpcFundsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPendingIbcIprpcFundsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPendingIbcIprpcFundsResponse.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 *QueryPendingIbcIprpcFundsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPendingIbcIprpcFundsResponse.Merge(m, src) +} +func (m *QueryPendingIbcIprpcFundsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPendingIbcIprpcFundsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPendingIbcIprpcFundsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPendingIbcIprpcFundsResponse proto.InternalMessageInfo + +func (m *QueryPendingIbcIprpcFundsResponse) GetPendingIbcIprpcFundsInfo() []PendingIbcIprpcFundInfo { + if m != nil { + return m.PendingIbcIprpcFundsInfo + } + return nil +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "lavanet.lava.rewards.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "lavanet.lava.rewards.QueryParamsResponse") @@ -817,78 +959,89 @@ func init() { proto.RegisterType((*QueryIprpcProviderRewardEstimationResponse)(nil), "lavanet.lava.rewards.QueryIprpcProviderRewardEstimationResponse") proto.RegisterType((*QueryIprpcSpecRewardRequest)(nil), "lavanet.lava.rewards.QueryIprpcSpecRewardRequest") proto.RegisterType((*QueryIprpcSpecRewardResponse)(nil), "lavanet.lava.rewards.QueryIprpcSpecRewardResponse") + proto.RegisterType((*QueryPendingIbcIprpcFundsRequest)(nil), "lavanet.lava.rewards.QueryPendingIbcIprpcFundsRequest") + proto.RegisterType((*PendingIbcIprpcFundInfo)(nil), "lavanet.lava.rewards.PendingIbcIprpcFundInfo") + proto.RegisterType((*QueryPendingIbcIprpcFundsResponse)(nil), "lavanet.lava.rewards.QueryPendingIbcIprpcFundsResponse") } func init() { proto.RegisterFile("lavanet/lava/rewards/query.proto", fileDescriptor_15bce9a904340007) } var fileDescriptor_15bce9a904340007 = []byte{ - // 1041 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x6f, 0xdc, 0x44, - 0x14, 0x8e, 0xf3, 0x3b, 0x2f, 0x6d, 0x80, 0x49, 0xa4, 0x6e, 0x9c, 0x74, 0x9b, 0x9a, 0xa0, 0x6c, - 0x23, 0xc5, 0x4e, 0x82, 0x54, 0x10, 0x08, 0x28, 0x09, 0x3f, 0x14, 0xa9, 0x48, 0xad, 0x97, 0x13, - 0x17, 0x6b, 0xd6, 0x3b, 0xbb, 0x6b, 0xd5, 0xf6, 0x38, 0x9e, 0xd9, 0x84, 0x0a, 0x2a, 0x24, 0x10, - 0x07, 0x24, 0x0e, 0x48, 0x48, 0x88, 0x2b, 0x12, 0x27, 0x4e, 0xfc, 0x19, 0x3d, 0x56, 0xe2, 0xc2, - 0x09, 0x50, 0xc2, 0x5f, 0xc0, 0x5f, 0x80, 0xe6, 0xcd, 0x78, 0xb3, 0x9b, 0x38, 0x9b, 0x6d, 0x4f, - 0x6b, 0xcf, 0x7c, 0xef, 0x7d, 0xdf, 0xf7, 0xe6, 0xcd, 0x5b, 0xc3, 0x5a, 0x4c, 0x8f, 0x68, 0xca, - 0xa4, 0xa7, 0x7e, 0xbd, 0x9c, 0x1d, 0xd3, 0xbc, 0x29, 0xbc, 0xc3, 0x2e, 0xcb, 0x1f, 0xbb, 0x59, - 0xce, 0x25, 0x27, 0x4b, 0x06, 0xe1, 0xaa, 0x5f, 0xd7, 0x20, 0xec, 0xa5, 0x36, 0x6f, 0x73, 0x04, - 0x78, 0xea, 0x49, 0x63, 0xed, 0xd5, 0x36, 0xe7, 0xed, 0x98, 0x79, 0x34, 0x8b, 0x3c, 0x9a, 0xa6, - 0x5c, 0x52, 0x19, 0xf1, 0x54, 0x98, 0xdd, 0xcd, 0x90, 0x8b, 0x84, 0x0b, 0xaf, 0x41, 0x05, 0xd3, - 0x14, 0xde, 0xd1, 0x4e, 0x83, 0x49, 0xba, 0xe3, 0x65, 0xb4, 0x1d, 0xa5, 0x08, 0x36, 0xd8, 0xdb, - 0xa5, 0xba, 0x32, 0x9a, 0xd3, 0xa4, 0x48, 0x57, 0x2e, 0x3d, 0xca, 0xf2, 0x2c, 0x34, 0x88, 0x6a, - 0x3f, 0x61, 0x41, 0x15, 0xf2, 0xc8, 0x90, 0x38, 0x4b, 0x40, 0x1e, 0x2a, 0x19, 0x0f, 0x30, 0xad, - 0xcf, 0x0e, 0xbb, 0x4c, 0x48, 0xe7, 0x21, 0x2c, 0x0e, 0xac, 0x8a, 0x8c, 0xa7, 0x82, 0x91, 0xb7, - 0x60, 0x5a, 0xd3, 0x57, 0xac, 0x35, 0xab, 0x36, 0xbf, 0xbb, 0xea, 0x96, 0x15, 0xc6, 0xd5, 0x51, - 0x7b, 0x93, 0x4f, 0xff, 0xba, 0x35, 0xe6, 0x9b, 0x08, 0x67, 0x11, 0x5e, 0xd1, 0x29, 0x39, 0x8f, - 0x7b, 0x3c, 0xdf, 0x5a, 0x30, 0xab, 0x16, 0x0e, 0xd2, 0x16, 0x27, 0x04, 0x26, 0x53, 0x9a, 0x30, - 0xcc, 0x3d, 0xe7, 0xe3, 0x33, 0x61, 0x30, 0xd3, 0xa0, 0x31, 0x4d, 0x43, 0x56, 0x19, 0x5f, 0x9b, - 0xa8, 0xcd, 0xef, 0x2e, 0xbb, 0xda, 0x90, 0xab, 0x0c, 0xb9, 0xc6, 0x90, 0xbb, 0xcf, 0xa3, 0x74, - 0x6f, 0x5b, 0xf1, 0xfd, 0xf6, 0xf7, 0xad, 0x5a, 0x3b, 0x92, 0x9d, 0x6e, 0xc3, 0x0d, 0x79, 0xe2, - 0x19, 0xf7, 0xfa, 0x67, 0x4b, 0x34, 0x1f, 0x79, 0xf2, 0x71, 0xc6, 0x04, 0x06, 0x08, 0xbf, 0xc8, - 0xed, 0xfc, 0x67, 0x15, 0x65, 0xd0, 0xea, 0x7a, 0x7e, 0xa7, 0x32, 0xb5, 0x50, 0xb1, 0x90, 0xbb, - 0x7a, 0x89, 0x5d, 0x63, 0xc0, 0x18, 0xd6, 0x21, 0x64, 0x1d, 0x16, 0x64, 0x94, 0xb0, 0x40, 0xf2, - 0x20, 0x67, 0xad, 0x28, 0x8e, 0x2b, 0xe3, 0x6b, 0x56, 0x6d, 0xc2, 0xbf, 0xa6, 0x56, 0x3f, 0xe5, - 0x3e, 0xae, 0x91, 0xb7, 0xc1, 0x66, 0x42, 0x46, 0x09, 0x95, 0xac, 0x19, 0x34, 0x62, 0x1e, 0x3e, - 0x12, 0x7d, 0x11, 0x13, 0x18, 0x71, 0xa3, 0x87, 0xd8, 0x43, 0x40, 0x2f, 0xf8, 0x1d, 0x58, 0xa1, - 0x71, 0xcc, 0x43, 0x6c, 0x9a, 0x40, 0xd1, 0x06, 0x09, 0x4f, 0x65, 0x47, 0x04, 0x31, 0x6b, 0xc9, - 0xca, 0x24, 0x46, 0x57, 0xce, 0x20, 0x4a, 0xe8, 0x27, 0x08, 0xb8, 0xcf, 0x5a, 0xd2, 0x59, 0x86, - 0x1b, 0xe8, 0x19, 0xb3, 0xfa, 0x68, 0xa6, 0x38, 0x97, 0x3a, 0x54, 0x2e, 0x6e, 0x99, 0xa2, 0xbc, - 0x01, 0xd3, 0xda, 0xb9, 0x69, 0x82, 0x21, 0x27, 0x62, 0x3a, 0x40, 0xc3, 0x9d, 0x15, 0x58, 0xc6, - 0xa4, 0xf5, 0x0e, 0x3f, 0x3e, 0x50, 0x2d, 0xfa, 0x01, 0x95, 0xb4, 0x60, 0xfc, 0xce, 0x02, 0xbb, - 0x6c, 0xb7, 0x77, 0x12, 0xb3, 0x49, 0x94, 0x06, 0x21, 0x17, 0x72, 0x54, 0xda, 0x99, 0x24, 0x4a, - 0xf7, 0xb9, 0x90, 0xc4, 0x83, 0x45, 0xbc, 0x11, 0x81, 0xe8, 0x36, 0x44, 0x98, 0x47, 0x19, 0x5e, - 0x48, 0xec, 0xa7, 0x39, 0x9f, 0xe0, 0x56, 0xbd, 0x7f, 0xc7, 0xa9, 0x1b, 0x29, 0x0f, 0x72, 0x7e, - 0x14, 0x35, 0x59, 0x3e, 0x50, 0x1b, 0xb2, 0x0c, 0xb3, 0x61, 0x87, 0x46, 0x69, 0x10, 0x35, 0x4d, - 0xab, 0xce, 0xe0, 0xfb, 0x41, 0x93, 0xd8, 0x30, 0x9b, 0x99, 0x18, 0x3c, 0xed, 0x39, 0xbf, 0xf7, - 0xee, 0x7c, 0x09, 0xa0, 0xf3, 0x60, 0xaf, 0xbf, 0x58, 0x12, 0x55, 0x7b, 0x9a, 0xf0, 0x6e, 0x2a, - 0xb1, 0x35, 0x46, 0xa9, 0xbd, 0x86, 0x3b, 0x01, 0xac, 0x94, 0x5a, 0x32, 0xe5, 0xbd, 0x07, 0x33, - 0xa6, 0x9b, 0x4d, 0xab, 0xaf, 0x95, 0xb7, 0xfa, 0x99, 0x83, 0xa2, 0xc8, 0x66, 0xc7, 0xf9, 0x18, - 0xee, 0x20, 0x01, 0x1e, 0xdd, 0x20, 0xcb, 0x87, 0xba, 0x7d, 0x23, 0x9e, 0x16, 0x25, 0xec, 0xb7, - 0x68, 0x9d, 0xab, 0xd3, 0x21, 0x6c, 0x8e, 0x92, 0xc8, 0x08, 0xdf, 0x07, 0x10, 0x19, 0x0b, 0x83, - 0x56, 0x37, 0x6d, 0x5e, 0x71, 0x4d, 0xeb, 0x19, 0x0b, 0x15, 0xcc, 0x28, 0x9f, 0x53, 0x71, 0x1f, - 0xa9, 0x30, 0x67, 0xc7, 0x14, 0x07, 0x29, 0x15, 0x6c, 0xf0, 0xc0, 0x09, 0x4c, 0x2a, 0x6c, 0x31, - 0x97, 0xd4, 0xb3, 0xf3, 0x93, 0x05, 0xab, 0xe5, 0x31, 0x46, 0xd8, 0x7d, 0xb8, 0xae, 0x9b, 0x6e, - 0xb0, 0xae, 0xb7, 0xcb, 0xb5, 0x61, 0x16, 0x9d, 0xc1, 0xc8, 0xbb, 0x16, 0x9d, 0x2d, 0x09, 0x52, - 0x83, 0x97, 0xc3, 0x6e, 0x9e, 0xb3, 0x54, 0xea, 0x1b, 0xae, 0xda, 0x46, 0xf5, 0xc6, 0xa4, 0xbf, - 0x60, 0xd6, 0xf1, 0x5e, 0x1f, 0x34, 0x77, 0xbf, 0x9f, 0x83, 0x29, 0x14, 0x46, 0xbe, 0xb1, 0x60, - 0x5a, 0x4f, 0x62, 0x52, 0x2b, 0x67, 0xbd, 0x38, 0xf8, 0xed, 0x3b, 0x23, 0x20, 0xb5, 0x43, 0x67, - 0xfd, 0xeb, 0x3f, 0xfe, 0xfd, 0x71, 0xbc, 0x4a, 0x56, 0xbd, 0x21, 0xff, 0x53, 0xe4, 0x2b, 0x98, - 0xc2, 0x99, 0x4a, 0x36, 0x86, 0x65, 0xee, 0xfb, 0x4f, 0xb0, 0x6b, 0x57, 0x03, 0x8d, 0x82, 0x57, - 0x51, 0xc1, 0x4d, 0xb2, 0x72, 0x89, 0x02, 0xe4, 0xfd, 0xd9, 0x82, 0xf9, 0xbe, 0x31, 0x46, 0xb6, - 0x86, 0xa4, 0xbf, 0x38, 0x09, 0x6d, 0x77, 0x54, 0xb8, 0xd1, 0xb4, 0x89, 0x9a, 0xd6, 0x89, 0x53, - 0xae, 0x09, 0x47, 0xbc, 0xe9, 0x09, 0xf2, 0x8b, 0x05, 0xd7, 0x07, 0xc6, 0x1d, 0xf1, 0x86, 0xb0, - 0x95, 0x8d, 0x4d, 0x7b, 0x7b, 0xf4, 0x00, 0x23, 0x70, 0x0b, 0x05, 0x6e, 0x90, 0xd7, 0xca, 0x05, - 0x8a, 0x0e, 0x3f, 0x0e, 0x74, 0xe7, 0x36, 0x95, 0xa2, 0x5f, 0x2d, 0x58, 0x18, 0xbc, 0x85, 0x64, - 0x18, 0x67, 0xe9, 0xc8, 0xb4, 0x77, 0x9e, 0x23, 0x62, 0x34, 0x99, 0xc5, 0xb8, 0x28, 0x4a, 0x79, - 0x62, 0xc1, 0xcd, 0xa1, 0x13, 0x83, 0xbc, 0x37, 0x44, 0xc3, 0x28, 0x43, 0xcb, 0xbe, 0xf7, 0xe2, - 0x09, 0x8c, 0xa7, 0x77, 0xd1, 0xd3, 0x9b, 0xe4, 0xae, 0x77, 0xf9, 0x67, 0x5b, 0x70, 0xce, 0x99, - 0xf7, 0x45, 0xb1, 0xf0, 0x84, 0xfc, 0x6e, 0xc1, 0x4b, 0xe7, 0xe6, 0x0d, 0xd9, 0xb9, 0x4a, 0xd5, - 0x85, 0x79, 0x66, 0xef, 0x3e, 0x4f, 0x88, 0x91, 0x7e, 0x17, 0xa5, 0x6f, 0x13, 0x77, 0x98, 0x74, - 0x9c, 0xc4, 0x85, 0x6c, 0xf5, 0xf2, 0x64, 0xef, 0xfd, 0xa7, 0x27, 0x55, 0xeb, 0xd9, 0x49, 0xd5, - 0xfa, 0xe7, 0xa4, 0x6a, 0xfd, 0x70, 0x5a, 0x1d, 0x7b, 0x76, 0x5a, 0x1d, 0xfb, 0xf3, 0xb4, 0x3a, - 0xf6, 0xd9, 0x46, 0xdf, 0x57, 0xda, 0x40, 0xce, 0xcf, 0x7b, 0x59, 0xf1, 0x53, 0xad, 0x31, 0x8d, - 0x1f, 0xaa, 0xaf, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x0e, 0xc7, 0x33, 0xa7, 0x0b, 0x00, - 0x00, + // 1180 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xcf, 0x6f, 0x1b, 0xc5, + 0x17, 0xcf, 0xa6, 0x6e, 0x7e, 0xbc, 0xb4, 0xf9, 0x7e, 0x99, 0x44, 0x8d, 0xb3, 0x49, 0x5d, 0x67, + 0x09, 0x8a, 0x13, 0x29, 0xbb, 0x49, 0x2a, 0xa5, 0xa8, 0x08, 0x28, 0x09, 0x3f, 0x14, 0xa9, 0x48, + 0xad, 0xc3, 0x89, 0xcb, 0x6a, 0xbd, 0x1e, 0x3b, 0xa3, 0xda, 0x3b, 0x9b, 0x9d, 0x75, 0x42, 0x55, + 0x22, 0x24, 0x10, 0x07, 0x6e, 0x48, 0x48, 0xa8, 0x57, 0x24, 0x4e, 0x9c, 0x38, 0xf0, 0x3f, 0xd0, + 0x63, 0x25, 0x24, 0xc4, 0x09, 0x50, 0xc2, 0x5f, 0xc0, 0x5f, 0x80, 0xe6, 0xcd, 0xac, 0x63, 0xc7, + 0xeb, 0xcd, 0xa6, 0x27, 0xef, 0xce, 0x7c, 0xde, 0x7b, 0x9f, 0xcf, 0x9b, 0xf7, 0xe6, 0xad, 0xa1, + 0xdc, 0xf2, 0x8e, 0xbc, 0x80, 0xc6, 0x8e, 0xfc, 0x75, 0x22, 0x7a, 0xec, 0x45, 0x75, 0xe1, 0x1c, + 0x76, 0x68, 0xf4, 0xd4, 0x0e, 0x23, 0x1e, 0x73, 0x32, 0xab, 0x11, 0xb6, 0xfc, 0xb5, 0x35, 0xc2, + 0x9c, 0x6d, 0xf2, 0x26, 0x47, 0x80, 0x23, 0x9f, 0x14, 0xd6, 0x5c, 0x6c, 0x72, 0xde, 0x6c, 0x51, + 0xc7, 0x0b, 0x99, 0xe3, 0x05, 0x01, 0x8f, 0xbd, 0x98, 0xf1, 0x40, 0xe8, 0xdd, 0x35, 0x9f, 0x8b, + 0x36, 0x17, 0x4e, 0xcd, 0x13, 0x54, 0x85, 0x70, 0x8e, 0x36, 0x6b, 0x34, 0xf6, 0x36, 0x9d, 0xd0, + 0x6b, 0xb2, 0x00, 0xc1, 0x1a, 0xbb, 0x94, 0xca, 0x2b, 0xf4, 0x22, 0xaf, 0x9d, 0xb8, 0x4b, 0xa7, + 0xce, 0xc2, 0x28, 0xf4, 0x35, 0xa2, 0xd4, 0x1b, 0x30, 0x09, 0xe5, 0x73, 0xa6, 0x83, 0x58, 0xb3, + 0x40, 0x1e, 0x4b, 0x1a, 0x8f, 0xd0, 0x6d, 0x95, 0x1e, 0x76, 0xa8, 0x88, 0xad, 0xc7, 0x30, 0xd3, + 0xb7, 0x2a, 0x42, 0x1e, 0x08, 0x4a, 0xee, 0xc3, 0x98, 0x0a, 0x5f, 0x34, 0xca, 0x46, 0x65, 0x6a, + 0x6b, 0xd1, 0x4e, 0x4b, 0x8c, 0xad, 0xac, 0x76, 0x0a, 0x2f, 0xfe, 0xbc, 0x33, 0x52, 0xd5, 0x16, + 0xd6, 0x0c, 0xbc, 0xa6, 0x5c, 0x72, 0xde, 0xea, 0xc6, 0xf9, 0xda, 0x80, 0x09, 0xb9, 0xb0, 0x17, + 0x34, 0x38, 0x21, 0x50, 0x08, 0xbc, 0x36, 0x45, 0xdf, 0x93, 0x55, 0x7c, 0x26, 0x14, 0xc6, 0x6b, + 0x5e, 0xcb, 0x0b, 0x7c, 0x5a, 0x1c, 0x2d, 0x5f, 0xab, 0x4c, 0x6d, 0xcd, 0xdb, 0x4a, 0x90, 0x2d, + 0x05, 0xd9, 0x5a, 0x90, 0xbd, 0xcb, 0x59, 0xb0, 0xb3, 0x21, 0xe3, 0xfd, 0xf4, 0xd7, 0x9d, 0x4a, + 0x93, 0xc5, 0x07, 0x9d, 0x9a, 0xed, 0xf3, 0xb6, 0xa3, 0xd5, 0xab, 0x9f, 0x75, 0x51, 0x7f, 0xe2, + 0xc4, 0x4f, 0x43, 0x2a, 0xd0, 0x40, 0x54, 0x13, 0xdf, 0xd6, 0xbf, 0x46, 0x92, 0x06, 0xc5, 0xae, + 0xab, 0xf7, 0x7a, 0x28, 0x17, 0x8a, 0x06, 0xc6, 0x2e, 0x0d, 0x91, 0xab, 0x05, 0x68, 0xc1, 0xca, + 0x84, 0x2c, 0xc3, 0x74, 0xcc, 0xda, 0xd4, 0x8d, 0xb9, 0x1b, 0xd1, 0x06, 0x6b, 0xb5, 0x8a, 0xa3, + 0x65, 0xa3, 0x72, 0xad, 0x7a, 0x43, 0xae, 0x7e, 0xc2, 0xab, 0xb8, 0x46, 0xde, 0x02, 0x93, 0x8a, + 0x98, 0xb5, 0xbd, 0x98, 0xd6, 0xdd, 0x5a, 0x8b, 0xfb, 0x4f, 0x44, 0x8f, 0xc5, 0x35, 0xb4, 0x98, + 0xeb, 0x22, 0x76, 0x10, 0xd0, 0x35, 0x7e, 0x1b, 0x16, 0xbc, 0x56, 0x8b, 0xfb, 0x58, 0x34, 0xae, + 0x0c, 0xeb, 0xb6, 0x79, 0x10, 0x1f, 0x08, 0xb7, 0x45, 0x1b, 0x71, 0xb1, 0x80, 0xd6, 0xc5, 0x73, + 0x88, 0x24, 0xfa, 0x31, 0x02, 0x1e, 0xd2, 0x46, 0x6c, 0xcd, 0xc3, 0x1c, 0x6a, 0x46, 0xaf, 0x55, + 0x14, 0x93, 0x9c, 0xcb, 0x3e, 0x14, 0x07, 0xb7, 0x74, 0x52, 0xee, 0xc1, 0x98, 0x52, 0xae, 0x8b, + 0x20, 0xe3, 0x44, 0x74, 0x05, 0x28, 0xb8, 0xb5, 0x00, 0xf3, 0xe8, 0x74, 0xff, 0x80, 0x1f, 0xef, + 0xc9, 0x12, 0x7d, 0xdf, 0x8b, 0xbd, 0x24, 0xe2, 0x37, 0x06, 0x98, 0x69, 0xbb, 0xdd, 0x93, 0x98, + 0x68, 0xb3, 0xc0, 0xf5, 0xb9, 0x88, 0xf3, 0x86, 0x1d, 0x6f, 0xb3, 0x60, 0x97, 0x8b, 0x98, 0x38, + 0x30, 0x83, 0x1d, 0xe1, 0x8a, 0x4e, 0x4d, 0xf8, 0x11, 0x0b, 0xb1, 0x21, 0xb1, 0x9e, 0x26, 0xab, + 0x04, 0xb7, 0xf6, 0x7b, 0x77, 0xac, 0x7d, 0x4d, 0xe5, 0x51, 0xc4, 0x8f, 0x58, 0x9d, 0x46, 0x7d, + 0xb9, 0x21, 0xf3, 0x30, 0xe1, 0x1f, 0x78, 0x2c, 0x70, 0x59, 0x5d, 0x97, 0xea, 0x38, 0xbe, 0xef, + 0xd5, 0x89, 0x09, 0x13, 0xa1, 0xb6, 0xc1, 0xd3, 0x9e, 0xac, 0x76, 0xdf, 0xad, 0xcf, 0x01, 0x94, + 0x1f, 0xac, 0xf5, 0x57, 0x73, 0x22, 0x73, 0xef, 0xb5, 0x79, 0x27, 0x88, 0xb1, 0x34, 0xf2, 0xe4, + 0x5e, 0xc1, 0x2d, 0x17, 0x16, 0x52, 0x25, 0xe9, 0xf4, 0x3e, 0x80, 0x71, 0x5d, 0xcd, 0xba, 0xd4, + 0xcb, 0xe9, 0xa5, 0x7e, 0xae, 0x20, 0x49, 0xb2, 0xde, 0xb1, 0x3e, 0x82, 0x55, 0x0c, 0x80, 0x47, + 0xd7, 0x1f, 0xe5, 0x03, 0x55, 0xbe, 0x8c, 0x07, 0x49, 0x0a, 0x7b, 0x25, 0x1a, 0x17, 0xf2, 0x74, + 0x08, 0x6b, 0x79, 0x1c, 0x69, 0xe2, 0xbb, 0x00, 0x22, 0xa4, 0xbe, 0xdb, 0xe8, 0x04, 0xf5, 0x4b, + 0xda, 0x74, 0x3f, 0xa4, 0xbe, 0x84, 0x69, 0xe6, 0x93, 0xd2, 0xee, 0x43, 0x69, 0x66, 0x6d, 0xea, + 0xe4, 0x60, 0x48, 0x09, 0xeb, 0x3f, 0x70, 0x02, 0x05, 0x89, 0x4d, 0xee, 0x25, 0xf9, 0x6c, 0x7d, + 0x6f, 0xc0, 0x62, 0xba, 0x8d, 0x26, 0xf6, 0x10, 0x6e, 0xaa, 0xa2, 0xeb, 0xcf, 0xeb, 0x52, 0x3a, + 0x37, 0xf4, 0xa2, 0x3c, 0x68, 0x7a, 0x37, 0xd8, 0xf9, 0x92, 0x20, 0x15, 0xf8, 0xbf, 0xdf, 0x89, + 0x22, 0x1a, 0xc4, 0xaa, 0xc3, 0x65, 0xd9, 0xc8, 0xda, 0x28, 0x54, 0xa7, 0xf5, 0x3a, 0xf6, 0xf5, + 0x5e, 0xdd, 0xba, 0x0f, 0x65, 0x75, 0xd0, 0x34, 0xa8, 0xb3, 0xa0, 0xb9, 0x57, 0xf3, 0xd1, 0x37, + 0x0a, 0x4d, 0x04, 0xdd, 0x82, 0xb1, 0x06, 0x6b, 0xc5, 0xdd, 0xe4, 0xeb, 0x37, 0xeb, 0x17, 0x03, + 0xe6, 0x52, 0xec, 0xb0, 0x60, 0xeb, 0x70, 0x2b, 0x54, 0x5b, 0x2e, 0xab, 0xf9, 0xae, 0xd2, 0x26, + 0xd3, 0xa9, 0xdb, 0x71, 0x75, 0xc8, 0xdd, 0x38, 0xe8, 0x4e, 0x0b, 0x9c, 0x09, 0x07, 0xb7, 0xc8, + 0x5d, 0x28, 0x60, 0x8b, 0x8f, 0xe6, 0xab, 0x6e, 0x04, 0x5b, 0xcf, 0x0d, 0x58, 0xca, 0xd0, 0xac, + 0x0f, 0x44, 0xc0, 0x62, 0xba, 0x00, 0xe1, 0xb2, 0xa0, 0xc1, 0xf5, 0xf9, 0xac, 0xe7, 0x96, 0xd1, + 0xd3, 0x04, 0xc5, 0x14, 0x29, 0x42, 0xee, 0x6f, 0xfd, 0x0e, 0x70, 0x1d, 0xa9, 0x91, 0xaf, 0x0c, + 0x18, 0x53, 0x73, 0x91, 0x54, 0xd2, 0x63, 0x0c, 0x8e, 0x61, 0x73, 0x35, 0x07, 0x52, 0xc9, 0xb3, + 0x96, 0xbf, 0xfc, 0xed, 0x9f, 0xef, 0x46, 0x4b, 0x64, 0xd1, 0xc9, 0xf8, 0x6a, 0x20, 0x5f, 0xc0, + 0x75, 0x9c, 0x70, 0x64, 0x25, 0xcb, 0x73, 0xcf, 0x84, 0x36, 0x2b, 0x97, 0x03, 0x35, 0x83, 0xd7, + 0x91, 0xc1, 0x6d, 0xb2, 0x30, 0x84, 0x01, 0xc6, 0x7d, 0x6e, 0xc0, 0x54, 0xcf, 0x50, 0x21, 0xeb, + 0x19, 0xee, 0x07, 0xe7, 0x92, 0x69, 0xe7, 0x85, 0x6b, 0x4e, 0x6b, 0xc8, 0x69, 0x99, 0x58, 0xe9, + 0x9c, 0x70, 0xe0, 0xea, 0x0e, 0x25, 0x3f, 0x18, 0x70, 0xb3, 0x6f, 0xf8, 0x10, 0x27, 0x23, 0x5a, + 0xda, 0x10, 0x33, 0x37, 0xf2, 0x1b, 0x68, 0x82, 0xeb, 0x48, 0x70, 0x85, 0xbc, 0x91, 0x4e, 0x50, + 0x1c, 0xf0, 0x63, 0x5d, 0xaa, 0x75, 0xc9, 0xe8, 0x47, 0x03, 0xa6, 0xfb, 0xef, 0x44, 0x92, 0x15, + 0x33, 0x75, 0x80, 0x99, 0x9b, 0x57, 0xb0, 0xc8, 0x47, 0x33, 0xb9, 0xbc, 0x93, 0x54, 0x9e, 0x1a, + 0x70, 0x3b, 0xf3, 0xfe, 0x26, 0xef, 0x66, 0x70, 0xc8, 0x33, 0x42, 0xcc, 0x07, 0xaf, 0xee, 0x40, + 0x6b, 0x7a, 0x07, 0x35, 0xbd, 0x49, 0xb6, 0x9d, 0xe1, 0x1f, 0xd1, 0xee, 0x05, 0x65, 0xce, 0xb3, + 0x64, 0xe1, 0x84, 0xfc, 0x6c, 0xc0, 0xff, 0x2e, 0xdc, 0xfe, 0x64, 0xf3, 0x32, 0x56, 0x03, 0xd3, + 0xc5, 0xdc, 0xba, 0x8a, 0x89, 0xa6, 0xbe, 0x8d, 0xd4, 0x37, 0x88, 0x9d, 0x45, 0x1d, 0xe7, 0x62, + 0x42, 0x5b, 0xbe, 0x9c, 0x90, 0x5f, 0x0d, 0x98, 0x4d, 0xbb, 0x24, 0xc9, 0x76, 0x56, 0x49, 0x0c, + 0x9f, 0x24, 0xe6, 0xbd, 0x2b, 0xdb, 0xe5, 0x4b, 0xfe, 0x90, 0x9b, 0xda, 0x79, 0xa6, 0x26, 0xd5, + 0xc9, 0xce, 0x7b, 0x2f, 0x4e, 0x4b, 0xc6, 0xcb, 0xd3, 0x92, 0xf1, 0xf7, 0x69, 0xc9, 0xf8, 0xf6, + 0xac, 0x34, 0xf2, 0xf2, 0xac, 0x34, 0xf2, 0xc7, 0x59, 0x69, 0xe4, 0xd3, 0x95, 0x9e, 0xaf, 0xff, + 0x3e, 0xdf, 0x9f, 0x75, 0xbd, 0xe3, 0x5f, 0x80, 0xda, 0x18, 0xfe, 0x01, 0xba, 0xfb, 0x5f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x0b, 0xa7, 0x5f, 0x9f, 0xff, 0x0d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -917,6 +1070,8 @@ type QueryClient interface { IprpcProviderRewardEstimation(ctx context.Context, in *QueryIprpcProviderRewardEstimationRequest, opts ...grpc.CallOption) (*QueryIprpcProviderRewardEstimationResponse, error) // IprpcSpecReward queries for a spec's IPRPC reward IprpcSpecReward(ctx context.Context, in *QueryIprpcSpecRewardRequest, opts ...grpc.CallOption) (*QueryIprpcSpecRewardResponse, error) + // PendingIbcIprpcFunds queries for a spec's IPRPC reward + PendingIbcIprpcFunds(ctx context.Context, in *QueryPendingIbcIprpcFundsRequest, opts ...grpc.CallOption) (*QueryPendingIbcIprpcFundsResponse, error) } type queryClient struct { @@ -990,6 +1145,15 @@ func (c *queryClient) IprpcSpecReward(ctx context.Context, in *QueryIprpcSpecRew return out, nil } +func (c *queryClient) PendingIbcIprpcFunds(ctx context.Context, in *QueryPendingIbcIprpcFundsRequest, opts ...grpc.CallOption) (*QueryPendingIbcIprpcFundsResponse, error) { + out := new(QueryPendingIbcIprpcFundsResponse) + err := c.cc.Invoke(ctx, "/lavanet.lava.rewards.Query/PendingIbcIprpcFunds", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Parameters queries the parameters of the module. @@ -1006,6 +1170,8 @@ type QueryServer interface { IprpcProviderRewardEstimation(context.Context, *QueryIprpcProviderRewardEstimationRequest) (*QueryIprpcProviderRewardEstimationResponse, error) // IprpcSpecReward queries for a spec's IPRPC reward IprpcSpecReward(context.Context, *QueryIprpcSpecRewardRequest) (*QueryIprpcSpecRewardResponse, error) + // PendingIbcIprpcFunds queries for a spec's IPRPC reward + PendingIbcIprpcFunds(context.Context, *QueryPendingIbcIprpcFundsRequest) (*QueryPendingIbcIprpcFundsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1033,6 +1199,9 @@ func (*UnimplementedQueryServer) IprpcProviderRewardEstimation(ctx context.Conte func (*UnimplementedQueryServer) IprpcSpecReward(ctx context.Context, req *QueryIprpcSpecRewardRequest) (*QueryIprpcSpecRewardResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method IprpcSpecReward not implemented") } +func (*UnimplementedQueryServer) PendingIbcIprpcFunds(ctx context.Context, req *QueryPendingIbcIprpcFundsRequest) (*QueryPendingIbcIprpcFundsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PendingIbcIprpcFunds not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1164,6 +1333,24 @@ func _Query_IprpcSpecReward_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Query_PendingIbcIprpcFunds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPendingIbcIprpcFundsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).PendingIbcIprpcFunds(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/lavanet.lava.rewards.Query/PendingIbcIprpcFunds", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).PendingIbcIprpcFunds(ctx, req.(*QueryPendingIbcIprpcFundsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "lavanet.lava.rewards.Query", HandlerType: (*QueryServer)(nil), @@ -1196,6 +1383,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "IprpcSpecReward", Handler: _Query_IprpcSpecReward_Handler, }, + { + MethodName: "PendingIbcIprpcFunds", + Handler: _Query_PendingIbcIprpcFunds_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "lavanet/lava/rewards/query.proto", @@ -1757,6 +1948,116 @@ func (m *QueryIprpcSpecRewardResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *QueryPendingIbcIprpcFundsRequest) 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 *QueryPendingIbcIprpcFundsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPendingIbcIprpcFundsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Filter) > 0 { + i -= len(m.Filter) + copy(dAtA[i:], m.Filter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Filter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PendingIbcIprpcFundInfo) 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 *PendingIbcIprpcFundInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PendingIbcIprpcFundInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Cost.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.PendingIbcIprpcFund.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 *QueryPendingIbcIprpcFundsResponse) 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 *QueryPendingIbcIprpcFundsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPendingIbcIprpcFundsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PendingIbcIprpcFundsInfo) > 0 { + for iNdEx := len(m.PendingIbcIprpcFundsInfo) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PendingIbcIprpcFundsInfo[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 encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -1996,6 +2297,47 @@ func (m *QueryIprpcSpecRewardResponse) Size() (n int) { return n } +func (m *QueryPendingIbcIprpcFundsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Filter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *PendingIbcIprpcFundInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.PendingIbcIprpcFund.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.Cost.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryPendingIbcIprpcFundsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.PendingIbcIprpcFundsInfo) > 0 { + for _, e := range m.PendingIbcIprpcFundsInfo { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -3436,6 +3778,288 @@ func (m *QueryIprpcSpecRewardResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryPendingIbcIprpcFundsRequest) 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: QueryPendingIbcIprpcFundsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPendingIbcIprpcFundsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filter", 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.Filter = 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 *PendingIbcIprpcFundInfo) 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: PendingIbcIprpcFundInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PendingIbcIprpcFundInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingIbcIprpcFund", 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.PendingIbcIprpcFund.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cost", 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.Cost.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 *QueryPendingIbcIprpcFundsResponse) 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: QueryPendingIbcIprpcFundsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPendingIbcIprpcFundsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingIbcIprpcFundsInfo", 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.PendingIbcIprpcFundsInfo = append(m.PendingIbcIprpcFundsInfo, PendingIbcIprpcFundInfo{}) + if err := m.PendingIbcIprpcFundsInfo[len(m.PendingIbcIprpcFundsInfo)-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 skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/rewards/types/query.pb.gw.go b/x/rewards/types/query.pb.gw.go index 94fe230994..ce5ca78063 100644 --- a/x/rewards/types/query.pb.gw.go +++ b/x/rewards/types/query.pb.gw.go @@ -249,6 +249,60 @@ func local_request_Query_IprpcSpecReward_0(ctx context.Context, marshaler runtim } +func request_Query_PendingIbcIprpcFunds_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPendingIbcIprpcFundsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["filter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "filter") + } + + protoReq.Filter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "filter", err) + } + + msg, err := client.PendingIbcIprpcFunds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_PendingIbcIprpcFunds_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPendingIbcIprpcFundsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["filter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "filter") + } + + protoReq.Filter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "filter", err) + } + + msg, err := server.PendingIbcIprpcFunds(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. @@ -416,6 +470,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_PendingIbcIprpcFunds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PendingIbcIprpcFunds_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PendingIbcIprpcFunds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -597,6 +674,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_PendingIbcIprpcFunds_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_PendingIbcIprpcFunds_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_PendingIbcIprpcFunds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -614,6 +711,8 @@ var ( pattern_Query_IprpcProviderRewardEstimation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"lavanet", "lava", "rewards", "iprpc_provider_reward", "provider"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_IprpcSpecReward_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"lavanet", "lava", "rewards", "iprpc_spec_reward", "spec"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_PendingIbcIprpcFunds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"lavanet", "lava", "rewards", "pending_ibc_iprpc_funds", "filter"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -630,4 +729,6 @@ var ( forward_Query_IprpcProviderRewardEstimation_0 = runtime.ForwardResponseMessage forward_Query_IprpcSpecReward_0 = runtime.ForwardResponseMessage + + forward_Query_PendingIbcIprpcFunds_0 = runtime.ForwardResponseMessage ) diff --git a/x/rewards/types/tx.pb.go b/x/rewards/types/tx.pb.go index 36a497f99f..baafc963e4 100644 --- a/x/rewards/types/tx.pb.go +++ b/x/rewards/types/tx.pb.go @@ -230,45 +230,139 @@ func (m *MsgFundIprpcResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgFundIprpcResponse proto.InternalMessageInfo +type MsgCoverIbcIprpcFundCost struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + Index uint64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` +} + +func (m *MsgCoverIbcIprpcFundCost) Reset() { *m = MsgCoverIbcIprpcFundCost{} } +func (m *MsgCoverIbcIprpcFundCost) String() string { return proto.CompactTextString(m) } +func (*MsgCoverIbcIprpcFundCost) ProtoMessage() {} +func (*MsgCoverIbcIprpcFundCost) Descriptor() ([]byte, []int) { + return fileDescriptor_6a4c66e189226d78, []int{4} +} +func (m *MsgCoverIbcIprpcFundCost) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCoverIbcIprpcFundCost) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCoverIbcIprpcFundCost.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 *MsgCoverIbcIprpcFundCost) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCoverIbcIprpcFundCost.Merge(m, src) +} +func (m *MsgCoverIbcIprpcFundCost) XXX_Size() int { + return m.Size() +} +func (m *MsgCoverIbcIprpcFundCost) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCoverIbcIprpcFundCost.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCoverIbcIprpcFundCost proto.InternalMessageInfo + +func (m *MsgCoverIbcIprpcFundCost) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgCoverIbcIprpcFundCost) GetIndex() uint64 { + if m != nil { + return m.Index + } + return 0 +} + +type MsgCoverIbcIprpcFundCostResponse struct { +} + +func (m *MsgCoverIbcIprpcFundCostResponse) Reset() { *m = MsgCoverIbcIprpcFundCostResponse{} } +func (m *MsgCoverIbcIprpcFundCostResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCoverIbcIprpcFundCostResponse) ProtoMessage() {} +func (*MsgCoverIbcIprpcFundCostResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_6a4c66e189226d78, []int{5} +} +func (m *MsgCoverIbcIprpcFundCostResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCoverIbcIprpcFundCostResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCoverIbcIprpcFundCostResponse.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 *MsgCoverIbcIprpcFundCostResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCoverIbcIprpcFundCostResponse.Merge(m, src) +} +func (m *MsgCoverIbcIprpcFundCostResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCoverIbcIprpcFundCostResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCoverIbcIprpcFundCostResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCoverIbcIprpcFundCostResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgSetIprpcData)(nil), "lavanet.lava.rewards.MsgSetIprpcData") proto.RegisterType((*MsgSetIprpcDataResponse)(nil), "lavanet.lava.rewards.MsgSetIprpcDataResponse") proto.RegisterType((*MsgFundIprpc)(nil), "lavanet.lava.rewards.MsgFundIprpc") proto.RegisterType((*MsgFundIprpcResponse)(nil), "lavanet.lava.rewards.MsgFundIprpcResponse") + proto.RegisterType((*MsgCoverIbcIprpcFundCost)(nil), "lavanet.lava.rewards.MsgCoverIbcIprpcFundCost") + proto.RegisterType((*MsgCoverIbcIprpcFundCostResponse)(nil), "lavanet.lava.rewards.MsgCoverIbcIprpcFundCostResponse") } func init() { proto.RegisterFile("lavanet/lava/rewards/tx.proto", fileDescriptor_6a4c66e189226d78) } var fileDescriptor_6a4c66e189226d78 = []byte{ - // 443 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcd, 0x6e, 0xd4, 0x30, - 0x10, 0xc7, 0xd7, 0xec, 0x8a, 0xb2, 0x66, 0x05, 0x92, 0x59, 0x41, 0x1a, 0x41, 0xba, 0x8a, 0x84, - 0x88, 0x90, 0x6a, 0xd3, 0xf2, 0x04, 0xb4, 0x80, 0xc4, 0x61, 0x2f, 0xe9, 0x0d, 0x0e, 0x95, 0x93, - 0x58, 0xa9, 0x05, 0xb1, 0x23, 0x8f, 0x53, 0xda, 0xb7, 0xe0, 0x2d, 0x90, 0x78, 0x09, 0xae, 0x7b, - 0xec, 0x91, 0x13, 0xa0, 0xdd, 0x17, 0x41, 0x76, 0x92, 0xee, 0xb6, 0xe2, 0xeb, 0x34, 0x63, 0xff, - 0x67, 0xc6, 0xbf, 0x19, 0x0f, 0x7e, 0xf4, 0x81, 0x9f, 0x72, 0x25, 0x2c, 0x73, 0x96, 0x19, 0xf1, - 0x91, 0x9b, 0x02, 0x98, 0x3d, 0xa3, 0xb5, 0xd1, 0x56, 0x93, 0x69, 0x27, 0x53, 0x67, 0x69, 0x27, - 0x87, 0x51, 0xae, 0xa1, 0xd2, 0xc0, 0x32, 0x0e, 0x82, 0x9d, 0xee, 0x65, 0xc2, 0xf2, 0x3d, 0x96, - 0x6b, 0xa9, 0xda, 0xac, 0x70, 0x5a, 0xea, 0x52, 0x7b, 0x97, 0x39, 0xaf, 0xbd, 0x8d, 0x3f, 0x23, - 0x7c, 0x77, 0x0e, 0xe5, 0x91, 0xb0, 0x6f, 0x6a, 0x53, 0xe7, 0x2f, 0xb9, 0xe5, 0xe4, 0x21, 0x1e, - 0xf3, 0xc6, 0x9e, 0x68, 0x23, 0xed, 0x79, 0x80, 0x66, 0x28, 0x19, 0xa7, 0xeb, 0x0b, 0xf2, 0x0a, - 0xdf, 0xa9, 0xa4, 0x3a, 0x96, 0x2e, 0xfc, 0x38, 0xd7, 0x60, 0x83, 0x1b, 0x33, 0x94, 0xdc, 0xde, - 0xdf, 0xa6, 0x2d, 0x00, 0x75, 0x00, 0xb4, 0x03, 0xa0, 0x87, 0x5a, 0xaa, 0x83, 0xd1, 0xe2, 0xfb, - 0xce, 0x20, 0x9d, 0x54, 0x52, 0xf9, 0x47, 0x0e, 0x35, 0x58, 0xc2, 0xf0, 0xbd, 0xb6, 0x04, 0x34, - 0x19, 0xe4, 0x46, 0xd6, 0x56, 0x6a, 0x05, 0xc1, 0x70, 0x36, 0x4c, 0xc6, 0x29, 0xf1, 0xd2, 0xd1, - 0xa6, 0x12, 0x6f, 0xe3, 0x07, 0xd7, 0x40, 0x53, 0x01, 0xb5, 0x56, 0x20, 0xe2, 0xaf, 0x08, 0x4f, - 0xe6, 0x50, 0xbe, 0x6e, 0x54, 0xe1, 0x45, 0x12, 0xe0, 0xad, 0xdc, 0x08, 0x6e, 0xb5, 0xe9, 0xf8, - 0xfb, 0x23, 0x09, 0xf1, 0xad, 0xa2, 0x31, 0xdc, 0x95, 0xf4, 0xdc, 0xa3, 0xf4, 0xf2, 0x4c, 0x04, - 0xde, 0xe2, 0x95, 0x6e, 0x94, 0x6d, 0x31, 0xfe, 0xda, 0xd2, 0x33, 0xd7, 0xd2, 0x97, 0x1f, 0x3b, - 0x49, 0x29, 0xed, 0x49, 0x93, 0xd1, 0x5c, 0x57, 0xac, 0xfb, 0x80, 0xd6, 0xec, 0x42, 0xf1, 0x9e, - 0xd9, 0xf3, 0x5a, 0x80, 0x4f, 0x80, 0xb4, 0xaf, 0x4d, 0x08, 0x1e, 0x41, 0x2d, 0xf2, 0x60, 0xe4, - 0xc9, 0xbc, 0x1f, 0xdf, 0xc7, 0xd3, 0xcd, 0x06, 0xfa, 0xce, 0xf6, 0x17, 0x08, 0x0f, 0xe7, 0x50, - 0x92, 0x02, 0x4f, 0xae, 0x7c, 0xd1, 0x63, 0xfa, 0xbb, 0x1d, 0xa0, 0xd7, 0x06, 0x14, 0xee, 0xfe, - 0x57, 0x58, 0xff, 0x1a, 0x79, 0x87, 0xc7, 0xeb, 0x19, 0xc6, 0x7f, 0xcc, 0xbd, 0x8c, 0x09, 0x9f, - 0xfe, 0x3b, 0xa6, 0x2f, 0x7e, 0xf0, 0x62, 0xb1, 0x8c, 0xd0, 0xc5, 0x32, 0x42, 0x3f, 0x97, 0x11, - 0xfa, 0xb4, 0x8a, 0x06, 0x17, 0xab, 0x68, 0xf0, 0x6d, 0x15, 0x0d, 0xde, 0x3e, 0xd9, 0x98, 0xe1, - 0x95, 0xcd, 0x3f, 0x5b, 0xef, 0xbe, 0x1b, 0x64, 0x76, 0xd3, 0xef, 0xec, 0xf3, 0x5f, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x87, 0x10, 0x57, 0xff, 0x20, 0x03, 0x00, 0x00, + // 501 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4f, 0x6f, 0xd3, 0x3e, + 0x18, 0x6e, 0xd6, 0xfe, 0x7e, 0xa3, 0xa6, 0x02, 0xc9, 0x14, 0xc8, 0x22, 0xc8, 0xaa, 0x48, 0x88, + 0x0a, 0x69, 0x36, 0x1b, 0x12, 0x77, 0x56, 0x40, 0x1a, 0x52, 0x2f, 0xd9, 0x0d, 0x0e, 0x93, 0x93, + 0x58, 0x99, 0x05, 0xb1, 0x23, 0xbf, 0x4e, 0xe9, 0x4e, 0x7c, 0x05, 0xbe, 0x05, 0x12, 0x5f, 0x82, + 0xeb, 0xb8, 0xed, 0xc8, 0x09, 0x50, 0xfb, 0x45, 0x50, 0x9c, 0xa4, 0xed, 0xa6, 0x96, 0x3f, 0x27, + 0xff, 0x79, 0x1e, 0x3f, 0x7e, 0x1e, 0xfb, 0x7d, 0xd1, 0xfd, 0x77, 0x6c, 0xc2, 0x24, 0x37, 0xb4, + 0x1c, 0xa9, 0xe6, 0xef, 0x99, 0x4e, 0x80, 0x9a, 0x29, 0xc9, 0xb5, 0x32, 0x0a, 0xf7, 0x6b, 0x98, + 0x94, 0x23, 0xa9, 0x61, 0xcf, 0x8f, 0x15, 0x64, 0x0a, 0x68, 0xc4, 0x80, 0xd3, 0xc9, 0x7e, 0xc4, + 0x0d, 0xdb, 0xa7, 0xb1, 0x12, 0xb2, 0x3a, 0xe5, 0xf5, 0x53, 0x95, 0x2a, 0x3b, 0xa5, 0xe5, 0xac, + 0xda, 0x0d, 0x3e, 0x39, 0xe8, 0xe6, 0x18, 0xd2, 0x63, 0x6e, 0x8e, 0x72, 0x9d, 0xc7, 0xcf, 0x99, + 0x61, 0xf8, 0x1e, 0xea, 0xb2, 0xc2, 0x9c, 0x2a, 0x2d, 0xcc, 0x99, 0xeb, 0x0c, 0x9c, 0x61, 0x37, + 0x5c, 0x6e, 0xe0, 0x17, 0xe8, 0x46, 0x26, 0xe4, 0x89, 0x28, 0xe9, 0x27, 0xb1, 0x02, 0xe3, 0x6e, + 0x0d, 0x9c, 0xe1, 0xf5, 0x83, 0x1d, 0x52, 0x19, 0x20, 0xa5, 0x01, 0x52, 0x1b, 0x20, 0x23, 0x25, + 0xe4, 0x61, 0xe7, 0xfc, 0xfb, 0x6e, 0x2b, 0xec, 0x65, 0x42, 0xda, 0x4b, 0x46, 0x0a, 0x0c, 0xa6, + 0xe8, 0x56, 0x25, 0x01, 0x45, 0x04, 0xb1, 0x16, 0xb9, 0x11, 0x4a, 0x82, 0xdb, 0x1e, 0xb4, 0x87, + 0xdd, 0x10, 0x5b, 0xe8, 0x78, 0x15, 0x09, 0x76, 0xd0, 0xdd, 0x2b, 0x46, 0x43, 0x0e, 0xb9, 0x92, + 0xc0, 0x83, 0x2f, 0x0e, 0xea, 0x8d, 0x21, 0x7d, 0x59, 0xc8, 0xc4, 0x82, 0xd8, 0x45, 0xdb, 0xb1, + 0xe6, 0xcc, 0x28, 0x5d, 0xfb, 0x6f, 0x96, 0xd8, 0x43, 0xd7, 0x92, 0x42, 0xb3, 0x52, 0xd2, 0xfa, + 0xee, 0x84, 0x8b, 0x35, 0xe6, 0x68, 0x9b, 0x65, 0xaa, 0x90, 0xa6, 0xb2, 0xf1, 0xdb, 0x48, 0x8f, + 0xcb, 0x48, 0x9f, 0x7f, 0xec, 0x0e, 0x53, 0x61, 0x4e, 0x8b, 0x88, 0xc4, 0x2a, 0xa3, 0xf5, 0x07, + 0x54, 0xc3, 0x1e, 0x24, 0x6f, 0xa9, 0x39, 0xcb, 0x39, 0xd8, 0x03, 0x10, 0x36, 0xda, 0x18, 0xa3, + 0x0e, 0xe4, 0x3c, 0x76, 0x3b, 0xd6, 0x99, 0x9d, 0x07, 0x77, 0x50, 0x7f, 0x35, 0xc0, 0x22, 0xd9, + 0x2b, 0xe4, 0x8e, 0x21, 0x1d, 0xa9, 0x09, 0xd7, 0x47, 0x51, 0x6c, 0xb1, 0x92, 0x64, 0x5f, 0x70, + 0x73, 0xc8, 0x3e, 0xfa, 0x4f, 0xc8, 0x84, 0x4f, 0xeb, 0x84, 0xd5, 0x22, 0x08, 0xd0, 0x60, 0x93, + 0x56, 0x73, 0xdf, 0xc1, 0xd7, 0x2d, 0xd4, 0x1e, 0x43, 0x8a, 0x13, 0xd4, 0xbb, 0x54, 0x12, 0x0f, + 0xc8, 0xba, 0x9a, 0x23, 0x57, 0x3e, 0xc4, 0xdb, 0xfb, 0x2b, 0x5a, 0x73, 0x1b, 0x7e, 0x83, 0xba, + 0xcb, 0x3f, 0x0b, 0x36, 0x9e, 0x5d, 0x70, 0xbc, 0x47, 0x7f, 0xe6, 0x2c, 0xc4, 0x3f, 0xa0, 0xdb, + 0xeb, 0xdf, 0x8d, 0x6c, 0x14, 0x59, 0xcb, 0xf7, 0x9e, 0xfe, 0x1b, 0xbf, 0x31, 0x70, 0xf8, 0xec, + 0x7c, 0xe6, 0x3b, 0x17, 0x33, 0xdf, 0xf9, 0x39, 0xf3, 0x9d, 0x8f, 0x73, 0xbf, 0x75, 0x31, 0xf7, + 0x5b, 0xdf, 0xe6, 0x7e, 0xeb, 0xf5, 0xc3, 0x95, 0xa2, 0xb9, 0xd4, 0xea, 0xd3, 0x65, 0xb3, 0x97, + 0x95, 0x13, 0xfd, 0x6f, 0x9b, 0xf4, 0xc9, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, 0x41, 0xbe, + 0x81, 0x11, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -285,6 +379,7 @@ const _ = grpc.SupportPackageIsVersion4 type MsgClient interface { SetIprpcData(ctx context.Context, in *MsgSetIprpcData, opts ...grpc.CallOption) (*MsgSetIprpcDataResponse, error) FundIprpc(ctx context.Context, in *MsgFundIprpc, opts ...grpc.CallOption) (*MsgFundIprpcResponse, error) + CoverIbcIprpcFundCost(ctx context.Context, in *MsgCoverIbcIprpcFundCost, opts ...grpc.CallOption) (*MsgCoverIbcIprpcFundCostResponse, error) } type msgClient struct { @@ -313,10 +408,20 @@ func (c *msgClient) FundIprpc(ctx context.Context, in *MsgFundIprpc, opts ...grp return out, nil } +func (c *msgClient) CoverIbcIprpcFundCost(ctx context.Context, in *MsgCoverIbcIprpcFundCost, opts ...grpc.CallOption) (*MsgCoverIbcIprpcFundCostResponse, error) { + out := new(MsgCoverIbcIprpcFundCostResponse) + err := c.cc.Invoke(ctx, "/lavanet.lava.rewards.Msg/CoverIbcIprpcFundCost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { SetIprpcData(context.Context, *MsgSetIprpcData) (*MsgSetIprpcDataResponse, error) FundIprpc(context.Context, *MsgFundIprpc) (*MsgFundIprpcResponse, error) + CoverIbcIprpcFundCost(context.Context, *MsgCoverIbcIprpcFundCost) (*MsgCoverIbcIprpcFundCostResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -329,6 +434,9 @@ func (*UnimplementedMsgServer) SetIprpcData(ctx context.Context, req *MsgSetIprp func (*UnimplementedMsgServer) FundIprpc(ctx context.Context, req *MsgFundIprpc) (*MsgFundIprpcResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method FundIprpc not implemented") } +func (*UnimplementedMsgServer) CoverIbcIprpcFundCost(ctx context.Context, req *MsgCoverIbcIprpcFundCost) (*MsgCoverIbcIprpcFundCostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CoverIbcIprpcFundCost not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -370,6 +478,24 @@ func _Msg_FundIprpc_Handler(srv interface{}, ctx context.Context, dec func(inter return interceptor(ctx, in, info, handler) } +func _Msg_CoverIbcIprpcFundCost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCoverIbcIprpcFundCost) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CoverIbcIprpcFundCost(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/lavanet.lava.rewards.Msg/CoverIbcIprpcFundCost", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CoverIbcIprpcFundCost(ctx, req.(*MsgCoverIbcIprpcFundCost)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "lavanet.lava.rewards.Msg", HandlerType: (*MsgServer)(nil), @@ -382,6 +508,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "FundIprpc", Handler: _Msg_FundIprpc_Handler, }, + { + MethodName: "CoverIbcIprpcFundCost", + Handler: _Msg_CoverIbcIprpcFundCost_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "lavanet/lava/rewards/tx.proto", @@ -538,6 +668,64 @@ func (m *MsgFundIprpcResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgCoverIbcIprpcFundCost) 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 *MsgCoverIbcIprpcFundCost) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCoverIbcIprpcFundCost) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Index != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x10 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCoverIbcIprpcFundCostResponse) 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 *MsgCoverIbcIprpcFundCostResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCoverIbcIprpcFundCostResponse) 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 @@ -614,6 +802,31 @@ func (m *MsgFundIprpcResponse) Size() (n int) { return n } +func (m *MsgCoverIbcIprpcFundCost) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Index != 0 { + n += 1 + sovTx(uint64(m.Index)) + } + return n +} + +func (m *MsgCoverIbcIprpcFundCostResponse) 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 } @@ -1034,6 +1247,157 @@ func (m *MsgFundIprpcResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgCoverIbcIprpcFundCost) 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: MsgCoverIbcIprpcFundCost: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCoverIbcIprpcFundCost: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", 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.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *MsgCoverIbcIprpcFundCostResponse) 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: MsgCoverIbcIprpcFundCostResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCoverIbcIprpcFundCostResponse: 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