diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 932e04cecb..9de92e14ca 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,14 +12,14 @@ jobs: lint: runs-on: ubuntu-latest steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install Go uses: actions/setup-go@v5 with: go-version: 1.20.5 - - name: Checkout code - uses: actions/checkout@v4 - - name: Lint uses: golangci/golangci-lint-action@v4 with: diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml index ad9c6f12c3..95cc07032a 100644 --- a/.github/workflows/proto.yml +++ b/.github/workflows/proto.yml @@ -23,15 +23,15 @@ jobs: # with: # input: "proto" - break-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.38.0 - - uses: bufbuild/buf-breaking-action@v1 - with: - input: "proto" - against: "https://github.com/${{ github.repository }}.git#branch=${{ github.event.pull_request.base.ref }},ref=HEAD~1,subdir=proto" + # break-check: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - uses: bufbuild/buf-setup-action@v1.38.0 + # - uses: bufbuild/buf-breaking-action@v1 + # with: + # input: "proto" + # against: "https://github.com/${{ github.repository }}.git#branch=${{ github.event.pull_request.base.ref }},ref=HEAD~1,subdir=proto" validate-check: runs-on: ubuntu-latest diff --git a/app/app.go b/app/app.go index 7297ef3b99..54dfedb250 100644 --- a/app/app.go +++ b/app/app.go @@ -166,42 +166,6 @@ const ( // Upgrades add here future upgrades (upgrades.Upgrade) var Upgrades = []upgrades.Upgrade{ - upgrades.Upgrade_0_22_0, - upgrades.Upgrade_0_23_0, - upgrades.Upgrade_0_23_2, - upgrades.Upgrade_0_23_4, - upgrades.Upgrade_0_23_5, - upgrades.Upgrade_0_24_0, - upgrades.Upgrade_0_25_0, - upgrades.Upgrade_0_25_1, - upgrades.Upgrade_0_25_2, - upgrades.Upgrade_0_26_0, - upgrades.Upgrade_0_26_1, - upgrades.Upgrade_0_26_2, - upgrades.Upgrade_0_27_0, - upgrades.Upgrade_0_30_0, - upgrades.Upgrade_0_30_1, - upgrades.Upgrade_0_30_2, - upgrades.Upgrade_0_31_0, - upgrades.Upgrade_0_31_1, - upgrades.Upgrade_0_32_0, - upgrades.Upgrade_0_32_3, - upgrades.Upgrade_0_33_0, - upgrades.Upgrade_0_34_0, - upgrades.Upgrade_0_35_0, - upgrades.Upgrade_1_0_0, - upgrades.Upgrade_1_0_1, - upgrades.Upgrade_1_1_0, - upgrades.Upgrade_1_2_0, - upgrades.Upgrade_2_0_0, - upgrades.Upgrade_2_1_0, - upgrades.Upgrade_2_1_1, - upgrades.Upgrade_2_1_3, - upgrades.Upgrade_2_2_0, - upgrades.Upgrade_2_4_0, - upgrades.Upgrade_2_5_0, - upgrades.Upgrade_3_0_0, - upgrades.Upgrade_3_0_1, upgrades.Upgrade_3_1_0, } diff --git a/app/upgrades/empty_upgrades.go b/app/upgrades/empty_upgrades.go index 348fd31622..1b18de859a 100644 --- a/app/upgrades/empty_upgrades.go +++ b/app/upgrades/empty_upgrades.go @@ -4,19 +4,8 @@ import ( store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - "github.com/cosmos/cosmos-sdk/x/group" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" - icacontrollertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" - icahosttypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types" "github.com/lavanet/lava/v3/app/keepers" - v1 "github.com/lavanet/lava/v3/x/downtime/v1" - dualstakingtypes "github.com/lavanet/lava/v3/x/dualstaking/types" - fixationtypes "github.com/lavanet/lava/v3/x/fixationstore/types" - protocoltypes "github.com/lavanet/lava/v3/x/protocol/types" - rewardstypes "github.com/lavanet/lava/v3/x/rewards/types" ) func defaultUpgradeHandler( @@ -45,256 +34,6 @@ func defaultUpgradeHandler( // }, // } -var Upgrade_0_22_0 = Upgrade{ - UpgradeName: "v0.22.0", - CreateUpgradeHandler: v0_22_0_UpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -func v0_22_0_UpgradeHandler( - m *module.Manager, - c module.Configurator, - bapm BaseAppParamManager, - lk *keepers.LavaKeepers, -) upgradetypes.UpgradeHandler { - return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { - lk.DowntimeKeeper.SetParams(ctx, v1.DefaultParams()) - lk.ProtocolKeeper.SetParams(ctx, protocoltypes.DefaultParams()) - return m.RunMigrations(ctx, c, vm) - } -} - -var Upgrade_0_23_0 = Upgrade{ - UpgradeName: "v0.23.0", - CreateUpgradeHandler: v0_23_0_UpgradeHandler, - StoreUpgrades: store.StoreUpgrades{Added: []string{dualstakingtypes.StoreKey}}, -} - -func v0_23_0_UpgradeHandler( - m *module.Manager, - c module.Configurator, - bapm BaseAppParamManager, - lk *keepers.LavaKeepers, -) upgradetypes.UpgradeHandler { - return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { - lk.PairingKeeper.InitProviderQoS(ctx, *fixationtypes.DefaultGenesis()) - return m.RunMigrations(ctx, c, vm) - } -} - -var Upgrade_0_23_2 = Upgrade{ - UpgradeName: "v0.23.2", // upgrade name - CreateUpgradeHandler: defaultUpgradeHandler, // upgrade handler (default) - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_23_4 = Upgrade{ - UpgradeName: "v0.23.4", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_23_5 = Upgrade{ - UpgradeName: "v0.23.5", - CreateUpgradeHandler: v0_23_0_UpgradeHandler, - StoreUpgrades: store.StoreUpgrades{Added: []string{dualstakingtypes.StoreKey}}, -} - -var Upgrade_0_24_0 = Upgrade{ - UpgradeName: "v0.24.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_25_0 = Upgrade{ - UpgradeName: "v0.25.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_25_1 = Upgrade{ - UpgradeName: "v0.25.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_25_2 = Upgrade{ - UpgradeName: "v0.25.2", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_26_0 = Upgrade{ - UpgradeName: "v0.26.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_26_1 = Upgrade{ - UpgradeName: "v0.26.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_26_2 = Upgrade{ - UpgradeName: "v0.26.2", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_27_0 = Upgrade{ - UpgradeName: "v0.27.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_30_0 = Upgrade{ - UpgradeName: "v0.30.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_30_1 = Upgrade{ - UpgradeName: "v0.30.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_30_2 = Upgrade{ - UpgradeName: "v0.30.2", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_31_0 = Upgrade{ - UpgradeName: "v0.31.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_31_1 = Upgrade{ - UpgradeName: "v0.31.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_32_0 = Upgrade{ - UpgradeName: "v0.32.0", - CreateUpgradeHandler: v0_32_0_UpgradeHandler, - StoreUpgrades: store.StoreUpgrades{ - Added: []string{rewardstypes.StoreKey}, - Deleted: []string{minttypes.StoreKey}, - }, -} - -var Upgrade_0_32_3 = Upgrade{ - UpgradeName: "v0.32.3", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_33_0 = Upgrade{ - UpgradeName: "v0.33.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_0_34_0 = Upgrade{ - UpgradeName: "v0.34.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{ - Added: []string{icahosttypes.StoreKey, icacontrollertypes.StoreKey}, - }, -} - -var Upgrade_0_35_0 = Upgrade{ - UpgradeName: "v0.35.0", - CreateUpgradeHandler: v_35_0, - StoreUpgrades: store.StoreUpgrades{Added: []string{authzkeeper.StoreKey, group.StoreKey}}, -} - -var Upgrade_1_0_0 = Upgrade{ - UpgradeName: "v1.0.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_1_0_1 = Upgrade{ - UpgradeName: "v1.0.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_1_1_0 = Upgrade{ - UpgradeName: "v1.1.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_1_2_0 = Upgrade{ - UpgradeName: "v1.2.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_2_0_0 = Upgrade{ - UpgradeName: "v2.0.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{ - Added: []string{packetforwardtypes.StoreKey}, - }, -} - -var Upgrade_2_1_0 = Upgrade{ - UpgradeName: "v2.1.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_2_1_1 = Upgrade{ - UpgradeName: "v2.1.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_2_1_3 = Upgrade{ - UpgradeName: "v2.1.3", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_2_2_0 = Upgrade{ - UpgradeName: "v2.2.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{ - Added: []string{packetforwardtypes.StoreKey}, - }, -} - -var Upgrade_2_4_0 = Upgrade{ - UpgradeName: "v2.4.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_2_5_0 = Upgrade{ - UpgradeName: "v2.5.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_3_0_0 = Upgrade{ - UpgradeName: "v3.0.0", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - -var Upgrade_3_0_1 = Upgrade{ - UpgradeName: "v3.0.1", - CreateUpgradeHandler: defaultUpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, -} - var Upgrade_3_1_0 = Upgrade{ UpgradeName: "v3.1.0", CreateUpgradeHandler: defaultUpgradeHandler, diff --git a/app/upgrades/upgrade_0_32_0.go b/app/upgrades/upgrade_0_32_0.go deleted file mode 100644 index 79eb7971c8..0000000000 --- a/app/upgrades/upgrade_0_32_0.go +++ /dev/null @@ -1,69 +0,0 @@ -package upgrades - -import ( - "fmt" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/x/bank/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/lavanet/lava/v3/app/keepers" - dualstakingtypes "github.com/lavanet/lava/v3/x/dualstaking/types" - rewardstypes "github.com/lavanet/lava/v3/x/rewards/types" -) - -func v0_32_0_UpgradeHandler( - m *module.Manager, - c module.Configurator, - bapm BaseAppParamManager, - lk *keepers.LavaKeepers, -) upgradetypes.UpgradeHandler { - return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { - // rewards pool - totalSupply, err := lk.BankKeeper.TotalSupply(ctx, &types.QueryTotalSupplyRequest{}) - if err != nil { - return nil, err - } - allocate := totalSupply.Supply.QuoInt(sdk.NewIntFromUint64(33)) - err = lk.BankKeeper.MintCoins(ctx, string(rewardstypes.ValidatorsRewardsAllocationPoolName), allocate) - if err != nil { - return nil, err - } - err = lk.BankKeeper.MintCoins(ctx, string(rewardstypes.ProvidersRewardsAllocationPool), allocate) - if err != nil { - return nil, err - } - - rewards := lk.DualstakingKeeper.GetAllDelegatorReward(ctx) - for _, reward := range rewards { - lk.DualstakingKeeper.RemoveDelegatorReward(ctx, dualstakingtypes.DelegationKey(reward.Provider, reward.Delegator, reward.ChainId)) - } - rewards = lk.DualstakingKeeper.GetAllDelegatorReward(ctx) - if len(rewards) != 0 { - return nil, fmt.Errorf("v0.32.0 UpgradeHandler: did not delete all rewards") - } - - // expedited proposal - // deposit - params := lk.GovKeeper.GetParams(ctx) - params.ExpeditedMinDeposit = append(params.ExpeditedMinDeposit, params.MinDeposit[0].AddAmount(sdk.NewIntFromUint64(1000))) - - // tally - params.ExpeditedThreshold = "0.75" - - // voting - seconds := params.VotingPeriod.Nanoseconds() - duration := time.Duration(seconds/10) * time.Nanosecond - params.ExpeditedVotingPeriod = &duration - - if err = params.ValidateBasic(); err != nil { - return nil, err - } - - if err := lk.GovKeeper.SetParams(ctx, params); err != nil { - return nil, err - } - return m.RunMigrations(ctx, c, vm) - } -} diff --git a/proto/lavanet/lava/dualstaking/delegate.proto b/proto/lavanet/lava/dualstaking/delegate.proto index ea0d3986f1..8926254f89 100644 --- a/proto/lavanet/lava/dualstaking/delegate.proto +++ b/proto/lavanet/lava/dualstaking/delegate.proto @@ -7,8 +7,8 @@ import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; message Delegation { + reserved 2; string provider = 1; // provider receives the delegated funds - string chainID = 2; // chainID to which staking delegate funds string delegator = 3; // delegator that owns the delegated funds cosmos.base.v1beta1.Coin amount = 4 [(gogoproto.nullable) = false]; int64 timestamp = 5; // Unix timestamp of the delegation (+ month) diff --git a/proto/lavanet/lava/dualstaking/delegator_reward.proto b/proto/lavanet/lava/dualstaking/delegator_reward.proto index 1145cf685e..c48be80aa6 100644 --- a/proto/lavanet/lava/dualstaking/delegator_reward.proto +++ b/proto/lavanet/lava/dualstaking/delegator_reward.proto @@ -7,9 +7,9 @@ import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; message DelegatorReward { + reserved 3; string delegator = 1; string provider = 2; - string chain_id = 3; repeated cosmos.base.v1beta1.Coin amount = 4 [ (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false diff --git a/proto/lavanet/lava/dualstaking/genesis.proto b/proto/lavanet/lava/dualstaking/genesis.proto index b6a97c3491..1c37aac064 100644 --- a/proto/lavanet/lava/dualstaking/genesis.proto +++ b/proto/lavanet/lava/dualstaking/genesis.proto @@ -3,17 +3,15 @@ package lavanet.lava.dualstaking; import "gogoproto/gogo.proto"; import "lavanet/lava/dualstaking/params.proto"; -import "lavanet/lava/fixationstore/fixation.proto"; -import "lavanet/lava/timerstore/timer.proto"; import "lavanet/lava/dualstaking/delegator_reward.proto"; +import "lavanet/lava/dualstaking/delegate.proto"; option go_package = "github.com/lavanet/lava/v3/x/dualstaking/types"; // GenesisState defines the dualstaking module's genesis state. message GenesisState { Params params = 1 [(gogoproto.nullable) = false]; - lavanet.lava.fixationstore.GenesisState delegationsFS = 2 [(gogoproto.nullable) = false]; - lavanet.lava.fixationstore.GenesisState delegatorsFS = 3 [(gogoproto.nullable) = false]; - reserved 4; + reserved 2,3,4; repeated DelegatorReward delegator_reward_list = 5 [(gogoproto.nullable) = false]; + repeated Delegation Delegations = 6 [(gogoproto.nullable) = false]; } diff --git a/proto/lavanet/lava/dualstaking/query.proto b/proto/lavanet/lava/dualstaking/query.proto index 3cb0941678..a0892a84f3 100644 --- a/proto/lavanet/lava/dualstaking/query.proto +++ b/proto/lavanet/lava/dualstaking/query.proto @@ -76,8 +76,8 @@ message QueryDelegatorRewardsResponse { } message DelegatorRewardInfo { + reserved 2; string provider = 1; - string chain_id = 2; repeated cosmos.base.v1beta1.Coin amount = 3 [ (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false diff --git a/proto/lavanet/lava/epochstorage/provider_metadata.proto b/proto/lavanet/lava/epochstorage/provider_metadata.proto new file mode 100644 index 0000000000..449c3989ac --- /dev/null +++ b/proto/lavanet/lava/epochstorage/provider_metadata.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +package lavanet.lava.epochstorage; + +option go_package = "github.com/lavanet/lava/v3/x/epochstorage/types"; +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "amino/amino.proto"; +import "cosmos/staking/v1beta1/staking.proto"; + +message ProviderMetadata { + string provider = 1; + string vault = 2; + cosmos.base.v1beta1.Coin total_delegations = 3 [(gogoproto.nullable) = false]; + repeated string chains = 4; + uint64 delegate_commission = 5; // delegation commission (precentage 0-100) + uint64 last_change = 6; + cosmos.staking.v1beta1.Description description = 7 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; +} \ No newline at end of file diff --git a/proto/lavanet/lava/epochstorage/query.proto b/proto/lavanet/lava/epochstorage/query.proto index 402a498fe3..8598ce9ec0 100644 --- a/proto/lavanet/lava/epochstorage/query.proto +++ b/proto/lavanet/lava/epochstorage/query.proto @@ -7,6 +7,7 @@ import "lavanet/lava/epochstorage/params.proto"; import "lavanet/lava/epochstorage/stake_storage.proto"; import "lavanet/lava/epochstorage/epoch_details.proto"; import "lavanet/lava/epochstorage/fixated_params.proto"; +import "lavanet/lava/epochstorage/provider_metadata.proto"; // this line is used by starport scaffolding # 1 import "cosmos/base/v1beta1/coin.proto"; import "gogoproto/gogo.proto"; @@ -44,6 +45,11 @@ service Query { option (google.api.http).get = "/lavanet/lava/epochstorage/fixated_params"; } + // Queries provider metadata. + rpc ProviderMetaData(QueryProviderMetaDataRequest) returns (QueryProviderMetaDataResponse) { + option (google.api.http).get = "/lavanet/lava/epochstorage/provider_metadata/{provider}"; + } + // this line is used by starport scaffolding # 2 } @@ -98,4 +104,12 @@ message QueryAllFixatedParamsResponse { cosmos.base.query.v1beta1.PageResponse pagination = 2; } +message QueryProviderMetaDataRequest { + string provider = 1; +} + +message QueryProviderMetaDataResponse { + repeated ProviderMetadata MetaData = 1 [(gogoproto.nullable) = false]; +} + // this line is used by starport scaffolding # 3 diff --git a/proto/lavanet/lava/epochstorage/stake_entry.proto b/proto/lavanet/lava/epochstorage/stake_entry.proto index 89b832d854..999ab14af8 100644 --- a/proto/lavanet/lava/epochstorage/stake_entry.proto +++ b/proto/lavanet/lava/epochstorage/stake_entry.proto @@ -9,7 +9,7 @@ import "cosmos/staking/v1beta1/staking.proto"; import "amino/amino.proto"; message StakeEntry { - reserved 7,10; + reserved 7,10,12; cosmos.base.v1beta1.Coin stake = 1 [(gogoproto.nullable) = false]; string address = 2; uint64 stake_applied_block = 3; @@ -19,7 +19,6 @@ message StakeEntry { string moniker = 8; cosmos.base.v1beta1.Coin delegate_total = 9 [(gogoproto.nullable) = false]; // delegation total uint64 delegate_commission = 11; // delegation commission (precentage 0-100) - uint64 last_change = 12; BlockReport block_report = 13; string vault = 14; cosmos.staking.v1beta1.Description description = 15 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; diff --git a/proto/lavanet/lava/pairing/tx.proto b/proto/lavanet/lava/pairing/tx.proto index 84adcbe410..987f3805ab 100644 --- a/proto/lavanet/lava/pairing/tx.proto +++ b/proto/lavanet/lava/pairing/tx.proto @@ -17,6 +17,7 @@ service Msg { rpc RelayPayment(MsgRelayPayment) returns (MsgRelayPaymentResponse); rpc FreezeProvider(MsgFreezeProvider) returns (MsgFreezeProviderResponse); rpc UnfreezeProvider(MsgUnfreezeProvider) returns (MsgUnfreezeProviderResponse); + rpc MoveProviderStake(MsgMoveProviderStake) returns (MsgMoveProviderStakeResponse); // this line is used by starport scaffolding # proto/tx/rpc } @@ -85,4 +86,16 @@ message MsgUnfreezeProvider { message MsgUnfreezeProviderResponse { } + +message MsgMoveProviderStake { + option (amino.name) = "pairing/MoveProviderStake"; + string creator = 1; + string src_chain =2; + string dst_chain =3; + cosmos.base.v1beta1.Coin amount = 4 [(gogoproto.nullable) = false]; +} + +message MsgMoveProviderStakeResponse { +} + // this line is used by starport scaffolding # proto/tx/message \ No newline at end of file diff --git a/protocol/monitoring/health.go b/protocol/monitoring/health.go index e801b9bdf3..10d68d283c 100644 --- a/protocol/monitoring/health.go +++ b/protocol/monitoring/health.go @@ -19,7 +19,6 @@ import ( "github.com/lavanet/lava/v3/protocol/rpcprovider" "github.com/lavanet/lava/v3/utils" "github.com/lavanet/lava/v3/utils/rand" - dualstakingtypes "github.com/lavanet/lava/v3/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/v3/x/epochstorage/types" pairingtypes "github.com/lavanet/lava/v3/x/pairing/types" protocoltypes "github.com/lavanet/lava/v3/x/protocol/types" @@ -128,7 +127,7 @@ func RunHealth(ctx context.Context, errCh := make(chan error, 1) // get a list of all necessary specs for the test - dualStakingQuerier := dualstakingtypes.NewQueryClient(clientCtx) + epochstorageQuerier := epochstoragetypes.NewQueryClient(clientCtx) if getAllProviders { // var specResp *spectypes.QueryGetSpecResponse var specsResp *spectypes.QueryShowAllChainsResponse @@ -157,28 +156,23 @@ func RunHealth(ctx context.Context, defer wgproviders.Done() var err error for i := 0; i < BasicQueryRetries; i++ { - var response *dualstakingtypes.QueryDelegatorProvidersResponse + var response *epochstoragetypes.QueryProviderMetaDataResponse queryCtx, cancel := context.WithTimeout(ctx, 2*time.Second) - response, err = dualStakingQuerier.DelegatorProviders(queryCtx, &dualstakingtypes.QueryDelegatorProvidersRequest{ - Delegator: providerAddress, - WithPending: false, - }) + response, err = epochstorageQuerier.ProviderMetaData(queryCtx, &epochstoragetypes.QueryProviderMetaDataRequest{Provider: providerAddress}) cancel() if err != nil || response == nil { time.Sleep(QuerySleepTime) continue } - delegations := response.GetDelegations() - for _, delegation := range delegations { - if delegation.Provider == providerAddress { - healthResults.setSpec(&spectypes.Spec{Index: delegation.ChainID}) - for _, apiInterface := range chainIdToApiInterfaces[delegation.ChainID] { - healthResults.SetProviderData(LavaEntity{ - Address: providerAddress, - SpecId: delegation.ChainID, - ApiInterface: apiInterface, - }, ReplyData{}) - } + + for _, chain := range response.MetaData[0].Chains { + healthResults.setSpec(&spectypes.Spec{Index: chain}) + for _, apiInterface := range chainIdToApiInterfaces[chain] { + healthResults.SetProviderData(LavaEntity{ + Address: providerAddress, + SpecId: chain, + ApiInterface: apiInterface, + }, ReplyData{}) } } return diff --git a/testutil/common/tester.go b/testutil/common/tester.go index 0a13df8d4f..22d4a18e48 100644 --- a/testutil/common/tester.go +++ b/testutil/common/tester.go @@ -161,6 +161,11 @@ func (ts *Tester) StakeProvider(vault string, provider string, spec spectypes.Sp return ts.StakeProviderExtra(vault, provider, spec, amount, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) } +func (ts *Tester) StakeProviderCommision(vault string, provider string, spec spectypes.Spec, amount int64, commission uint64) error { + d := MockDescription() + return ts.StakeProviderFull(vault, provider, spec, amount, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, commission) +} + func (ts *Tester) StakeProviderExtra( vault string, provider string, @@ -173,6 +178,35 @@ func (ts *Tester) StakeProviderExtra( website string, securityContact string, descriptionDetails string, +) error { + return ts.StakeProviderFull(vault, + provider, + spec, + amount, + endpoints, + geoloc, + moniker, + identity, + website, + securityContact, + descriptionDetails, + uint64(100), + ) +} + +func (ts *Tester) StakeProviderFull( + vault string, + provider string, + spec spectypes.Spec, + amount int64, + endpoints []epochstoragetypes.Endpoint, + geoloc int32, + moniker string, + identity string, + website string, + securityContact string, + descriptionDetails string, + commission uint64, ) error { // if geoloc left zero, use default 1 if geoloc == 0 { @@ -199,7 +233,7 @@ func (ts *Tester) StakeProviderExtra( stake := sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(amount)) description := stakingtypes.NewDescription(moniker, identity, website, securityContact, descriptionDetails) - _, err := ts.TxPairingStakeProvider(vault, provider, spec.Index, stake, endpoints, geoloc, description) + _, err := ts.TxPairingStakeProvider(vault, provider, spec.Index, stake, endpoints, geoloc, description, commission) return err } @@ -352,9 +386,8 @@ func (ts *Tester) VotePeriod() uint64 { return ts.Keepers.Conflict.VotePeriod(ts.Ctx) } -func (ts *Tester) ChangeDelegationTimestamp(provider, delegator, chainID string, block uint64, timestamp int64) error { - index := dualstakingtypes.DelegationKey(provider, delegator, chainID) - return ts.Keepers.Dualstaking.ChangeDelegationTimestampForTesting(ts.Ctx, index, block, timestamp) +func (ts *Tester) ChangeDelegationTimestamp(provider, delegator string, block uint64, timestamp int64) error { + return ts.Keepers.Dualstaking.ChangeDelegationTimestampForTesting(ts.Ctx, provider, delegator, timestamp) } // proposals, transactions, queries @@ -379,7 +412,6 @@ func (ts *Tester) TxProposalAddSpecs(specs ...spectypes.Spec) error { func (ts *Tester) TxDualstakingDelegate( creator string, provider string, - chainID string, amount sdk.Coin, ) (*dualstakingtypes.MsgDelegateResponse, error) { validator, _ := ts.GetAccount(VALIDATOR, 0) @@ -387,7 +419,6 @@ func (ts *Tester) TxDualstakingDelegate( creator, sdk.ValAddress(validator.Addr).String(), provider, - chainID, amount, ) } @@ -397,14 +428,13 @@ func (ts *Tester) TxDualstakingDelegateValidator( creator string, validator string, provider string, - chainID string, amount sdk.Coin, ) (*dualstakingtypes.MsgDelegateResponse, error) { msg := &dualstakingtypes.MsgDelegate{ Creator: creator, Validator: validator, Provider: provider, - ChainID: chainID, + ChainID: "chainID", Amount: amount, } return ts.Servers.DualstakingServer.Delegate(ts.GoCtx, msg) @@ -415,16 +445,14 @@ func (ts *Tester) TxDualstakingRedelegate( creator string, fromProvider string, toProvider string, - fromChainID string, - toChainID string, amount sdk.Coin, ) (*dualstakingtypes.MsgRedelegateResponse, error) { msg := &dualstakingtypes.MsgRedelegate{ Creator: creator, FromProvider: fromProvider, ToProvider: toProvider, - FromChainID: fromChainID, - ToChainID: toChainID, + FromChainID: "fromChainID", + ToChainID: "toChainID", Amount: amount, } return ts.Servers.DualstakingServer.Redelegate(ts.GoCtx, msg) @@ -434,7 +462,6 @@ func (ts *Tester) TxDualstakingRedelegate( func (ts *Tester) TxDualstakingUnbond( creator string, provider string, - chainID string, amount sdk.Coin, ) (*dualstakingtypes.MsgUnbondResponse, error) { validator, _ := ts.GetAccount(VALIDATOR, 0) @@ -442,7 +469,6 @@ func (ts *Tester) TxDualstakingUnbond( creator, sdk.ValAddress(validator.Addr).String(), provider, - chainID, amount, ) } @@ -452,14 +478,13 @@ func (ts *Tester) TxDualstakingUnbondValidator( creator string, validator string, provider string, - chainID string, amount sdk.Coin, ) (*dualstakingtypes.MsgUnbondResponse, error) { msg := &dualstakingtypes.MsgUnbond{ Creator: creator, Validator: validator, Provider: provider, - ChainID: chainID, + ChainID: "chainID", Amount: amount, } return ts.Servers.DualstakingServer.Unbond(ts.GoCtx, msg) @@ -573,6 +598,7 @@ func (ts *Tester) TxPairingStakeProvider( endpoints []epochstoragetypes.Endpoint, geoloc int32, description stakingtypes.Description, + commission uint64, ) (*pairingtypes.MsgStakeProviderResponse, error) { val, _ := ts.GetAccount(VALIDATOR, 0) msg := &pairingtypes.MsgStakeProvider{ @@ -583,7 +609,7 @@ func (ts *Tester) TxPairingStakeProvider( Geolocation: geoloc, Endpoints: endpoints, DelegateLimit: sdk.NewCoin(ts.Keepers.StakingKeeper.BondDenom(ts.Ctx), sdk.ZeroInt()), - DelegateCommission: 100, + DelegateCommission: commission, Address: provider, Description: description, } @@ -688,6 +714,17 @@ func (ts *Tester) TxPairingUnfreezeProvider(addr, chainID string) (*pairingtypes return ts.Servers.PairingServer.UnfreezeProvider(ts.GoCtx, msg) } +// TxPairingMoveStake: implement 'tx pairing move-provider-stake' +func (ts *Tester) TxPairingMoveStake(provider, src, dst string, amount int64) (*pairingtypes.MsgMoveProviderStakeResponse, error) { + msg := &pairingtypes.MsgMoveProviderStake{ + Creator: provider, + SrcChain: src, + DstChain: dst, + Amount: NewCoin(ts.BondDenom(), amount), + } + return ts.Servers.PairingServer.MoveProviderStake(ts.GoCtx, msg) +} + func (ts *Tester) TxRewardsSetIprpcDataProposal(authority string, cost sdk.Coin, subs []string) (*rewardstypes.MsgSetIprpcDataResponse, error) { msg := rewardstypes.NewMsgSetIprpcData(authority, cost, subs) return ts.Servers.RewardsServer.SetIprpcData(ts.GoCtx, msg) @@ -885,19 +922,17 @@ func (ts *Tester) QueryPairingSubscriptionMonthlyPayout(consumer string) (*pairi } // QueryPairingVerifyPairing implements 'q dualstaking delegator-providers' -func (ts *Tester) QueryDualstakingDelegatorProviders(delegator string, withPending bool) (*dualstakingtypes.QueryDelegatorProvidersResponse, error) { +func (ts *Tester) QueryDualstakingDelegatorProviders(delegator string) (*dualstakingtypes.QueryDelegatorProvidersResponse, error) { msg := &dualstakingtypes.QueryDelegatorProvidersRequest{ - Delegator: delegator, - WithPending: withPending, + Delegator: delegator, } return ts.Keepers.Dualstaking.DelegatorProviders(ts.GoCtx, msg) } // QueryDualstakingProviderDelegators implements 'q dualstaking provider-delegators' -func (ts *Tester) QueryDualstakingProviderDelegators(provider string, withPending bool) (*dualstakingtypes.QueryProviderDelegatorsResponse, error) { +func (ts *Tester) QueryDualstakingProviderDelegators(provider string) (*dualstakingtypes.QueryProviderDelegatorsResponse, error) { msg := &dualstakingtypes.QueryProviderDelegatorsRequest{ - Provider: provider, - WithPending: withPending, + Provider: provider, } return ts.Keepers.Dualstaking.ProviderDelegators(ts.GoCtx, msg) } diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 03a6f5f336..247aa2ab5a 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -335,8 +335,6 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { ctx = ctx.WithBlockTime(fixedDate) } - ks.Dualstaking.InitDelegations(ctx, *fixationtypes.DefaultGenesis()) - ks.Dualstaking.InitDelegators(ctx, *fixationtypes.DefaultGenesis()) ks.Plans.InitPlans(ctx, *fixationtypes.DefaultGenesis()) ks.Subscription.InitSubscriptions(ctx, *fixationtypes.DefaultGenesis()) ks.Subscription.InitSubscriptionsTimers(ctx, *timerstoretypes.DefaultGenesis()) diff --git a/utils/common/types/provider.go b/utils/common/types/provider.go index f83a43d723..7921bbbe1a 100644 --- a/utils/common/types/provider.go +++ b/utils/common/types/provider.go @@ -2,7 +2,5 @@ package types // empty provider consts const ( - EMPTY_PROVIDER = "empty_provider" - EMPTY_PROVIDER_CHAINID = "" - EMPTY_PROVIDER_CHAINID_STAR = "*" + EMPTY_PROVIDER = "empty_provider" ) diff --git a/utils/lavaslices/slices.go b/utils/lavaslices/slices.go index 747b5fc3f0..abad07d4f1 100644 --- a/utils/lavaslices/slices.go +++ b/utils/lavaslices/slices.go @@ -146,6 +146,15 @@ func Remove[T comparable](slice []T, elem T) ([]T, bool) { return slice, false } +func AddUnique[T comparable](slice []T, elem T) []T { + for _, e := range slice { + if e == elem { + return slice + } + } + return append(slice, elem) +} + func IsSubset[T comparable](subset, superset []T) bool { subsetMap := make(map[T]bool) commonMap := make(map[T]bool) diff --git a/x/dualstaking/README.md b/x/dualstaking/README.md index 61b0cac937..682b40cc81 100644 --- a/x/dualstaking/README.md +++ b/x/dualstaking/README.md @@ -34,7 +34,7 @@ Dualstaking makes this happen by "duplicating" delegations, for each validator d ### Delegation Dualstaking introduces provider delegations to the Lava network. Provider delegations allow users to delegate their tokens to a specific provider, similar to validators, in order to contribute to their success and claim a portion of the rewards awarded to the provider. -When a provider stakes tokens, they create a self-delegation entry. Whenever a provider receives rewards, all delegators are eligible for a portion of the rewards based on their delegation amount and the commission rate set by the provider. +When a provider stakes tokens, they create a self-delegation entry. Whenever a provider receives rewards, all delegators are eligible for a portion of the rewards based on their delegation amount and the commission rate set by the provider. The delegations for a provider is split between the chains of the provider, distributed according the the providers stakes. ### Empty Provider @@ -123,9 +123,9 @@ The Dualstaking module supports the following transactions: | Transaction | Arguments | What it does | | ---------- | --------------- | ----------------------------------------------| -| `delegate` | validator-addr(string) provider-addr (string) chain-id (string) amount (coin)| delegate to validator and provider the given amount| -| `redelegate` | src-provider-addr (string) src-chain-id (string) dst-provider-addr (string) dst-chain-id (string) amount (coin)| redelegate provider delegation from source provider to destination provider| -| `unbond` | validator-addr (string) provider-addr (string) chain-id (string) amount (coin) | undong from validator and provider the given amount | +| `delegate` | validator-addr(string) provider-addr (string) amount (coin)| delegate to validator and provider the given amount| +| `redelegate` | src-provider-addr (string) dst-provider-addr (string) amount (coin)| redelegate provider delegation from source provider to destination provider| +| `unbond` | validator-addr (string) provider-addr (string) amount (coin) | undong from validator and provider the given amount | | `claim-rewards` | optional: provider-addr (string)| claim the rewards from a given provider or all rewards | diff --git a/x/dualstaking/genesis.go b/x/dualstaking/genesis.go index 5b6fecf674..ae00d5de7c 100644 --- a/x/dualstaking/genesis.go +++ b/x/dualstaking/genesis.go @@ -11,8 +11,12 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) // this line is used by starport scaffolding # genesis/module/init k.SetParams(ctx, genState.Params) - k.InitDelegations(ctx, genState.DelegationsFS) - k.InitDelegators(ctx, genState.DelegatorsFS) + for _, d := range genState.Delegations { + err := k.SetDelegation(ctx, d) + if err != nil { + panic(err) + } + } // Set all the DelegatorReward for _, elem := range genState.DelegatorRewardList { @@ -25,8 +29,12 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis := types.DefaultGenesis() genesis.Params = k.GetParams(ctx) - genesis.DelegationsFS = k.ExportDelegations(ctx) - genesis.DelegatorsFS = k.ExportDelegators(ctx) + var err error + genesis.Delegations, err = k.GetAllDelegations(ctx) + if err != nil { + panic(err) + } + genesis.DelegatorRewardList = k.GetAllDelegatorReward(ctx) // this line is used by starport scaffolding # genesis/module/export diff --git a/x/dualstaking/keeper/balance.go b/x/dualstaking/keeper/balance.go index 92292835ab..f443b2e461 100644 --- a/x/dualstaking/keeper/balance.go +++ b/x/dualstaking/keeper/balance.go @@ -17,8 +17,8 @@ func (k Keeper) BalanceDelegator(ctx sdk.Context, delegator sdk.AccAddress) (int return providers, nil } else if diff.IsPositive() { // less provider delegations,a delegation operation was done, delegate to empty provider - err = k.delegate(ctx, delegator.String(), commontypes.EMPTY_PROVIDER, commontypes.EMPTY_PROVIDER_CHAINID, - sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), diff)) + err = k.delegate(ctx, delegator.String(), commontypes.EMPTY_PROVIDER, + sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), diff), false) if err != nil { return providers, err } diff --git a/x/dualstaking/keeper/delegate.go b/x/dualstaking/keeper/delegate.go index 6e164e8c44..9b72a2bdec 100644 --- a/x/dualstaking/keeper/delegate.go +++ b/x/dualstaking/keeper/delegate.go @@ -18,8 +18,7 @@ package keeper // tracking the list of providers for a delegator, indexed by the delegator. import ( - "fmt" - + "cosmossdk.io/collections" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/utils" @@ -33,49 +32,24 @@ import ( // increaseDelegation increases the delegation of a delegator to a provider for a // given chain. It updates the fixation stores for both delegations and delegators, // and updates the (epochstorage) stake-entry. -func (k Keeper) increaseDelegation(ctx sdk.Context, delegator, provider, chainID string, amount sdk.Coin, nextEpoch uint64) error { - // get, update and append the delegation entry - var delegationEntry types.Delegation - index := types.DelegationKey(provider, delegator, chainID) - found := k.delegationFS.FindEntry(ctx, index, nextEpoch, &delegationEntry) - if !found { +func (k Keeper) increaseDelegation(ctx sdk.Context, delegator, provider string, amount sdk.Coin, stake bool) error { + // get, update the delegation entry + delegation, err := k.delegations.Get(ctx, types.DelegationKey(provider, delegator)) + if err != nil { // new delegation (i.e. not increase of existing one) - delegationEntry = types.NewDelegation(delegator, provider, chainID, ctx.BlockTime(), k.stakingKeeper.BondDenom(ctx)) + delegation = types.NewDelegation(delegator, provider, ctx.BlockTime(), k.stakingKeeper.BondDenom(ctx)) } - delegationEntry.AddAmount(amount) + delegation.AddAmount(amount) - err := k.delegationFS.AppendEntry(ctx, index, nextEpoch, &delegationEntry) + err = k.delegations.Set(ctx, types.DelegationKey(provider, delegator), delegation) if err != nil { - // append should never fail here - return utils.LavaFormatError("critical: append delegation entry", err, - utils.Attribute{Key: "delegator", Value: delegationEntry.Delegator}, - utils.Attribute{Key: "provider", Value: delegationEntry.Provider}, - utils.Attribute{Key: "chainID", Value: delegationEntry.ChainID}, - ) - } - - // get, update and append the delegator entry - var delegatorEntry types.Delegator - index = types.DelegatorKey(delegator) - _ = k.delegatorFS.FindEntry(ctx, index, nextEpoch, &delegatorEntry) - - contains := delegatorEntry.AddProvider(provider) - if !contains { - err = k.delegatorFS.AppendEntry(ctx, index, nextEpoch, &delegatorEntry) - if err != nil { - // append should never fail here - return utils.LavaFormatError("critical: append delegator entry", err, - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - } + return err } if provider != commontypes.EMPTY_PROVIDER { // update the stake entry - return k.modifyStakeEntryDelegation(ctx, delegator, provider, chainID, amount, true) + return k.AfterDelegationModified(ctx, delegator, provider, amount, true, stake) } return nil @@ -84,160 +58,126 @@ func (k Keeper) increaseDelegation(ctx sdk.Context, delegator, provider, chainID // decreaseDelegation decreases the delegation of a delegator to a provider for a // given chain. It updates the fixation stores for both delegations and delegators, // and updates the (epochstorage) stake-entry. -func (k Keeper) decreaseDelegation(ctx sdk.Context, delegator, provider, chainID string, amount sdk.Coin, nextEpoch uint64) error { +func (k Keeper) decreaseDelegation(ctx sdk.Context, delegator, provider string, amount sdk.Coin, stake bool) error { // get, update and append the delegation entry - var delegationEntry types.Delegation - index := types.DelegationKey(provider, delegator, chainID) - found := k.delegationFS.FindEntry(ctx, index, nextEpoch, &delegationEntry) + delegation, found := k.GetDelegation(ctx, provider, delegator) if !found { return types.ErrDelegationNotFound } - if delegationEntry.Amount.IsLT(amount) { + if delegation.Amount.IsLT(amount) { return types.ErrInsufficientDelegation } - delegationEntry.SubAmount(amount) + delegation.SubAmount(amount) - // if delegation now becomes zero, then remove this entry altogether; - // otherwise just append the new version (for next epoch). - if delegationEntry.Amount.IsZero() { - err := k.delegationFS.DelEntry(ctx, index, nextEpoch) + if delegation.Amount.IsZero() { + err := k.RemoveDelegation(ctx, delegation) if err != nil { - // delete should never fail here - return utils.LavaFormatError("critical: delete delegation entry", err, - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) + return err } } else { - err := k.delegationFS.AppendEntry(ctx, index, nextEpoch, &delegationEntry) + err := k.SetDelegation(ctx, delegation) if err != nil { - // append should never fail here - return utils.LavaFormatError("failed to update delegation entry", err, - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - } - } - - // get, update and append the delegator entry - var delegatorEntry types.Delegator - index = types.DelegatorKey(delegator) - found = k.delegatorFS.FindEntry(ctx, index, nextEpoch, &delegatorEntry) - if !found { - // we found the delegation above, so the delegator must exist as well - return utils.LavaFormatError("critical: delegator entry for delegation not found", - types.ErrDelegationNotFound, - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - } - - // if delegation now becomes zero, then remove this provider from the delegator - // entry; and if the delegator entry becomes entry then remove it altogether. - // otherwise just append the new version (for next epoch). - if delegationEntry.Amount.IsZero() { - if len(k.GetAllProviderDelegatorDelegations(ctx, delegator, provider, nextEpoch)) == 0 { - delegatorEntry.DelProvider(provider) - if delegatorEntry.IsEmpty() { - err := k.delegatorFS.DelEntry(ctx, index, nextEpoch) - if err != nil { - // delete should never fail here - return utils.LavaFormatError("critical: delete delegator entry", err, - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - } - } else { - err := k.delegatorFS.AppendEntry(ctx, index, nextEpoch, &delegatorEntry) - if err != nil { - // append should never fail here - return utils.LavaFormatError("failed to update delegator entry", err, - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - } - } + return err } } if provider != commontypes.EMPTY_PROVIDER { - return k.modifyStakeEntryDelegation(ctx, delegator, provider, chainID, amount, false) + return k.AfterDelegationModified(ctx, delegator, provider, amount, false, stake) } return nil } -// modifyStakeEntryDelegation modifies the (epochstorage) stake-entry of the provider for a chain based on the action (increase or decrease). -func (k Keeper) modifyStakeEntryDelegation(ctx sdk.Context, delegator, provider, chainID string, amount sdk.Coin, increase bool) (err error) { - stakeEntry, exists := k.epochstorageKeeper.GetStakeEntryCurrent(ctx, chainID, provider) - if !exists || provider != stakeEntry.Address { +// this method is called after a delegation is called and redistributes the delegations among the stake entries of the provider. +// 'stake' arg needs to be true if the code reached here from pairing stake/unstake tx (this means the 'stake' field is already set) +func (k Keeper) AfterDelegationModified(ctx sdk.Context, delegator, provider string, amount sdk.Coin, increase, stake bool) (err error) { + // get all entries + metadata, err := k.epochstorageKeeper.GetMetadata(ctx, provider) + if err != nil { if increase { - return epochstoragetypes.ErrProviderNotStaked + return err + } else { + // we want to allow decreasing if the provider does not exist + return nil } - // For decrease, if the provider doesn't exist, return without error - return nil } - if delegator == stakeEntry.Vault { - if increase { - stakeEntry.Stake = stakeEntry.Stake.Add(amount) - } else { - stakeEntry.Stake, err = stakeEntry.Stake.SafeSub(amount) - if err != nil { - return fmt.Errorf("invalid or insufficient funds: %w", err) - } + // get all entries + TotalSelfDelegation := sdk.ZeroInt() + entries := []*epochstoragetypes.StakeEntry{} + for _, chain := range metadata.Chains { + entry, found := k.epochstorageKeeper.GetStakeEntryCurrent(ctx, chain, provider) + if !found { + panic("AfterDelegationModified: entry not found") } - } else { - if increase { - stakeEntry.DelegateTotal = stakeEntry.DelegateTotal.Add(amount) - } else { - stakeEntry.DelegateTotal, err = stakeEntry.DelegateTotal.SafeSub(amount) - if err != nil { - return fmt.Errorf("invalid or insufficient funds: %w", err) + + entries = append(entries, &entry) + TotalSelfDelegation = TotalSelfDelegation.Add(entry.Stake.Amount) + } + + // regular delegation + if !amount.IsZero() { + if delegator != metadata.Vault { + if increase { + metadata.TotalDelegations = metadata.TotalDelegations.Add(amount) + } else { + metadata.TotalDelegations, err = metadata.TotalDelegations.SafeSub(amount) + if err != nil { + return err + } + } + } else if !stake { + // distribute self delegations if done through the dualstaking tx + total := amount.Amount + count := int64(len(entries)) + for _, entry := range entries { + part := total.QuoRaw(count) + if increase { + entry.Stake = entry.Stake.AddAmount(part) + TotalSelfDelegation = TotalSelfDelegation.Add(part) + } else { + entry.Stake.Amount, err = entry.Stake.Amount.SafeSub(part) + if err != nil { + return err + } + TotalSelfDelegation = TotalSelfDelegation.Sub(part) + if entry.Stake.IsLT(k.GetParams(ctx).MinSelfDelegation) { + return utils.LavaFormatError("self delegation below minimum, use unstake tx", nil, utils.LogAttr("chainID", entry.Chain)) + } + } + total = total.Sub(part) + count-- } } + k.epochstorageKeeper.SetMetadata(ctx, metadata) } details := map[string]string{ - "provider_vault": stakeEntry.Vault, - "provider_provider": stakeEntry.Address, - "chain_id": stakeEntry.Chain, - "moniker": stakeEntry.Description.Moniker, - "description": stakeEntry.Description.String(), - "stake": stakeEntry.Stake.String(), - "effective_stake": stakeEntry.TotalStake().String() + stakeEntry.Stake.Denom, - } - - if stakeEntry.Stake.IsLT(k.GetParams(ctx).MinSelfDelegation) { - k.epochstorageKeeper.RemoveStakeEntryCurrent(ctx, chainID, stakeEntry.Address) - details["min_self_delegation"] = k.GetParams(ctx).MinSelfDelegation.String() - utils.LogLavaEvent(ctx, k.Logger(ctx), types.UnstakeFromUnbond, details, "unstaking provider due to unbond that lowered its stake below min self delegation") - return nil - } else if stakeEntry.TotalStake().LT(k.specKeeper.GetMinStake(ctx, chainID).Amount) { - details["min_spec_stake"] = k.specKeeper.GetMinStake(ctx, chainID).String() - utils.LogLavaEvent(ctx, k.Logger(ctx), types.FreezeFromUnbond, details, "freezing provider due to stake below min spec stake") - stakeEntry.Freeze() - } else if delegator == stakeEntry.Vault && stakeEntry.IsFrozen() && !stakeEntry.IsJailed(ctx.BlockTime().UTC().Unix()) { - stakeEntry.UnFreeze(k.epochstorageKeeper.GetCurrentNextEpoch(ctx) + 1) - } - - k.epochstorageKeeper.SetStakeEntryCurrent(ctx, stakeEntry) + "provider": provider, + } + + for _, entry := range entries { + details[entry.Chain] = entry.Chain + entry.DelegateTotal = sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), metadata.TotalDelegations.Amount.Mul(entry.Stake.Amount).Quo(TotalSelfDelegation)) + if entry.TotalStake().LT(k.specKeeper.GetMinStake(ctx, entry.Chain).Amount) { + details["min_spec_stake"] = k.specKeeper.GetMinStake(ctx, entry.Chain).String() + details["stake"] = entry.TotalStake().String() + utils.LogLavaEvent(ctx, k.Logger(ctx), types.FreezeFromUnbond, details, "freezing provider due to stake below min spec stake") + entry.Freeze() + } else if delegator == entry.Vault && entry.IsFrozen() && !entry.IsJailed(ctx.BlockTime().UTC().Unix()) { + entry.UnFreeze(k.epochstorageKeeper.GetCurrentNextEpoch(ctx) + 1) + } + k.epochstorageKeeper.SetStakeEntryCurrent(ctx, *entry) + } return nil } // delegate lets a delegator delegate an amount of coins to a provider. // (effective on next epoch) -func (k Keeper) delegate(ctx sdk.Context, delegator, provider, chainID string, amount sdk.Coin) error { - nextEpoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - +func (k Keeper) delegate(ctx sdk.Context, delegator, provider string, amount sdk.Coin, stake bool) error { _, err := sdk.AccAddressFromBech32(delegator) if err != nil { return utils.LavaFormatWarning("invalid delegator address", err, @@ -257,17 +197,15 @@ func (k Keeper) delegate(ctx sdk.Context, delegator, provider, chainID string, a return utils.LavaFormatWarning("failed to delegate: coin validation failed", err, utils.Attribute{Key: "delegator", Value: delegator}, utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, ) } - err = k.increaseDelegation(ctx, delegator, provider, chainID, amount, nextEpoch) + err = k.increaseDelegation(ctx, delegator, provider, amount, stake) if err != nil { return utils.LavaFormatWarning("failed to increase delegation", err, utils.Attribute{Key: "delegator", Value: delegator}, utils.Attribute{Key: "provider", Value: provider}, utils.Attribute{Key: "amount", Value: amount.String()}, - utils.Attribute{Key: "chainID", Value: chainID}, ) } @@ -277,19 +215,7 @@ func (k Keeper) delegate(ctx sdk.Context, delegator, provider, chainID string, a // Redelegate lets a delegator transfer its delegation between providers, but // without the funds being subject to unstakeHoldBlocks witholding period. // (effective on next epoch) -func (k Keeper) Redelegate(ctx sdk.Context, delegator, from, to, fromChainID, toChainID string, amount sdk.Coin) error { - _, foundFrom := k.specKeeper.GetSpec(ctx, fromChainID) - _, foundTo := k.specKeeper.GetSpec(ctx, toChainID) - if (!foundFrom && fromChainID != commontypes.EMPTY_PROVIDER_CHAINID) || - (!foundTo && toChainID != commontypes.EMPTY_PROVIDER_CHAINID) { - return utils.LavaFormatWarning("cannot redelegate with invalid chain IDs", fmt.Errorf("chain ID not found"), - utils.LogAttr("from_chain_id", fromChainID), - utils.LogAttr("to_chain_id", toChainID), - ) - } - - nextEpoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - +func (k Keeper) Redelegate(ctx sdk.Context, delegator, from, to string, amount sdk.Coin, stake bool) error { if _, err := sdk.AccAddressFromBech32(delegator); err != nil { return utils.LavaFormatWarning("invalid delegator address", err, utils.Attribute{Key: "delegator", Value: delegator}, @@ -319,7 +245,7 @@ func (k Keeper) Redelegate(ctx sdk.Context, delegator, from, to, fromChainID, to ) } - err := k.increaseDelegation(ctx, delegator, to, toChainID, amount, nextEpoch) + err := k.increaseDelegation(ctx, delegator, to, amount, stake) if err != nil { return utils.LavaFormatWarning("failed to increase delegation", err, utils.Attribute{Key: "delegator", Value: delegator}, @@ -328,7 +254,7 @@ func (k Keeper) Redelegate(ctx sdk.Context, delegator, from, to, fromChainID, to ) } - err = k.decreaseDelegation(ctx, delegator, from, fromChainID, amount, nextEpoch) + err = k.decreaseDelegation(ctx, delegator, from, amount, stake) if err != nil { return utils.LavaFormatWarning("failed to decrease delegation", err, utils.Attribute{Key: "delegator", Value: delegator}, @@ -348,15 +274,7 @@ func (k Keeper) Redelegate(ctx sdk.Context, delegator, from, to, fromChainID, to // before released and transferred back to the delegator. The rewards from the // provider will be updated accordingly (or terminate) from the next epoch. // (effective on next epoch) -func (k Keeper) unbond(ctx sdk.Context, delegator, provider, chainID string, amount sdk.Coin) error { - _, found := k.specKeeper.GetSpec(ctx, chainID) - if chainID != commontypes.EMPTY_PROVIDER_CHAINID && !found { - return utils.LavaFormatWarning("cannot unbond with invalid chain ID", fmt.Errorf("chain ID not found"), - utils.LogAttr("chain_id", chainID)) - } - - nextEpoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - +func (k Keeper) unbond(ctx sdk.Context, delegator, provider string, amount sdk.Coin, stake bool) error { if _, err := sdk.AccAddressFromBech32(delegator); err != nil { return utils.LavaFormatWarning("invalid delegator address", err, utils.Attribute{Key: "delegator", Value: delegator}, @@ -378,7 +296,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegator, provider, chainID string, amo ) } - err := k.decreaseDelegation(ctx, delegator, provider, chainID, amount, nextEpoch) + err := k.decreaseDelegation(ctx, delegator, provider, amount, stake) if err != nil { return utils.LavaFormatWarning("failed to decrease delegation", err, utils.Attribute{Key: "delegator", Value: delegator}, @@ -391,7 +309,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegator, provider, chainID string, amo } // GetDelegatorProviders gets all the providers the delegator is delegated to -func (k Keeper) GetDelegatorProviders(ctx sdk.Context, delegator string, epoch uint64) (providers []string, err error) { +func (k Keeper) GetDelegatorProviders(ctx sdk.Context, delegator string) (providers []string, err error) { _, err = sdk.AccAddressFromBech32(delegator) if err != nil { return nil, utils.LavaFormatWarning("cannot get delegator's providers", err, @@ -399,14 +317,23 @@ func (k Keeper) GetDelegatorProviders(ctx sdk.Context, delegator string, epoch u ) } - var delegatorEntry types.Delegator - prefix := types.DelegatorKey(delegator) - k.delegatorFS.FindEntry(ctx, prefix, epoch, &delegatorEntry) + iter, err := k.delegations.Indexes.ReverseIndex.MatchExact(ctx, delegator) + if err != nil { + return nil, err + } + + for ; iter.Valid(); iter.Next() { + key, err := iter.PrimaryKey() + if err != nil { + return nil, err + } + providers = append(providers, key.K1()) + } - return delegatorEntry.Providers, nil + return providers, nil } -func (k Keeper) GetProviderDelegators(ctx sdk.Context, provider string, epoch uint64) ([]types.Delegation, error) { +func (k Keeper) GetProviderDelegators(ctx sdk.Context, provider string) ([]types.Delegation, error) { if provider != commontypes.EMPTY_PROVIDER { _, err := sdk.AccAddressFromBech32(provider) if err != nil { @@ -416,76 +343,52 @@ func (k Keeper) GetProviderDelegators(ctx sdk.Context, provider string, epoch ui } } - var delegations []types.Delegation - indices := k.delegationFS.GetAllEntryIndicesWithPrefix(ctx, provider) - for _, ind := range indices { - var delegation types.Delegation - found := k.delegationFS.FindEntry(ctx, ind, epoch, &delegation) - if !found { - provider, delegator, chainID := types.DelegationKeyDecode(ind) - utils.LavaFormatError("delegationFS entry index has no entry", fmt.Errorf("provider delegation not found"), - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - continue - } - delegations = append(delegations, delegation) + iter, err := k.delegations.Iterate(ctx, collections.NewPrefixedPairRange[string, string](provider)) + if err != nil { + return nil, err } - return delegations, nil + return iter.Values() } -func (k Keeper) GetDelegation(ctx sdk.Context, delegator, provider, chainID string, epoch uint64) (types.Delegation, bool) { - var delegationEntry types.Delegation - index := types.DelegationKey(provider, delegator, chainID) - found := k.delegationFS.FindEntry(ctx, index, epoch, &delegationEntry) - - return delegationEntry, found +func (k Keeper) GetDelegation(ctx sdk.Context, provider, delegator string) (types.Delegation, bool) { + delegation, err := k.delegations.Get(ctx, types.DelegationKey(provider, delegator)) + return delegation, err == nil } -func (k Keeper) GetAllProviderDelegatorDelegations(ctx sdk.Context, delegator, provider string, epoch uint64) []types.Delegation { - prefix := types.DelegationKey(provider, delegator, "") - indices := k.delegationFS.GetAllEntryIndicesWithPrefix(ctx, prefix) - - var delegations []types.Delegation - for _, ind := range indices { - var delegation types.Delegation - _, deleted, _, found := k.delegationFS.FindEntryDetailed(ctx, ind, epoch, &delegation) - if !found { - if !deleted { - provider, delegator, chainID := types.DelegationKeyDecode(ind) - utils.LavaFormatError("delegationFS entry index has no entry", fmt.Errorf("provider delegation not found"), - utils.Attribute{Key: "delegator", Value: delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: chainID}, - ) - } - continue - } - delegations = append(delegations, delegation) +func (k Keeper) GetAllDelegations(ctx sdk.Context) ([]types.Delegation, error) { + iter, err := k.delegations.Iterate(ctx, nil) + if err != nil { + return nil, err } - return delegations + return iter.Values() +} + +func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) error { + return k.delegations.Set(ctx, types.DelegationKey(delegation.Provider, delegation.Delegator), delegation) +} + +func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) error { + return k.delegations.Remove(ctx, types.DelegationKey(delegation.Provider, delegation.Delegator)) } func (k Keeper) UnbondUniformProviders(ctx sdk.Context, delegator string, amount sdk.Coin) error { - epoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - providers, err := k.GetDelegatorProviders(ctx, delegator, epoch) + providers, err := k.GetDelegatorProviders(ctx, delegator) if err != nil { return err } // first remove from the empty provider if lavaslices.Contains[string](providers, commontypes.EMPTY_PROVIDER) { - delegation, found := k.GetDelegation(ctx, delegator, commontypes.EMPTY_PROVIDER, commontypes.EMPTY_PROVIDER_CHAINID, epoch) + delegation, found := k.GetDelegation(ctx, commontypes.EMPTY_PROVIDER, delegator) if found { if delegation.Amount.Amount.GTE(amount.Amount) { // we have enough here, remove all from empty delegator and bail - return k.unbond(ctx, delegator, commontypes.EMPTY_PROVIDER, commontypes.EMPTY_PROVIDER_CHAINID, amount) + return k.unbond(ctx, delegator, commontypes.EMPTY_PROVIDER, amount, false) } else { // we dont have enough in the empty provider, remove everything and continue with the rest - err = k.unbond(ctx, delegator, commontypes.EMPTY_PROVIDER, commontypes.EMPTY_PROVIDER_CHAINID, delegation.Amount) + err = k.unbond(ctx, delegator, commontypes.EMPTY_PROVIDER, delegation.Amount, false) if err != nil { return err } @@ -498,30 +401,27 @@ func (k Keeper) UnbondUniformProviders(ctx sdk.Context, delegator string, amount var delegations []types.Delegation for _, provider := range providers { - delegations = append(delegations, k.GetAllProviderDelegatorDelegations(ctx, delegator, provider, epoch)...) + delegation, found := k.GetDelegation(ctx, provider, delegator) + if found { + delegations = append(delegations, delegation) + } } slices.SortFunc(delegations, func(i, j types.Delegation) bool { return i.Amount.IsLT(j.Amount) }) - type delegationKey struct { - provider string - chainID string - } - unbondAmount := map[delegationKey]sdk.Coin{} - + unbondAmount := map[string]sdk.Coin{} // first round of deduction for i := range delegations { - key := delegationKey{provider: delegations[i].Provider, chainID: delegations[i].ChainID} amountToDeduct := amount.Amount.QuoRaw(int64(len(delegations) - i)) if delegations[i].Amount.Amount.LT(amountToDeduct) { - unbondAmount[key] = delegations[i].Amount + unbondAmount[delegations[i].Provider] = delegations[i].Amount amount = amount.Sub(delegations[i].Amount) delegations[i].Amount.Amount = sdk.ZeroInt() } else { coinToDeduct := sdk.NewCoin(delegations[i].Amount.Denom, amountToDeduct) - unbondAmount[key] = coinToDeduct + unbondAmount[delegations[i].Provider] = coinToDeduct amount = amount.Sub(coinToDeduct) delegations[i].Amount = delegations[i].Amount.Sub(coinToDeduct) } @@ -532,7 +432,7 @@ func (k Keeper) UnbondUniformProviders(ctx sdk.Context, delegator string, amount if amount.IsZero() { break } - key := delegationKey{provider: delegations[i].Provider, chainID: delegations[i].ChainID} + key := delegations[i].Provider if delegations[i].Amount.Amount.LT(amount.Amount) { unbondAmount[key].Add(delegations[i].Amount) amount = amount.Sub(delegations[i].Amount) @@ -544,8 +444,8 @@ func (k Keeper) UnbondUniformProviders(ctx sdk.Context, delegator string, amount // now unbond all for i := range delegations { - key := delegationKey{provider: delegations[i].Provider, chainID: delegations[i].ChainID} - err := k.unbond(ctx, delegator, delegations[i].Provider, delegations[i].ChainID, unbondAmount[key]) + key := delegations[i].Provider + err := k.unbond(ctx, delegator, delegations[i].Provider, unbondAmount[key], false) if err != nil { return err } @@ -556,16 +456,15 @@ func (k Keeper) UnbondUniformProviders(ctx sdk.Context, delegator string, amount // returns the difference between validators delegations and provider delegation (validators-providers) func (k Keeper) VerifyDelegatorBalance(ctx sdk.Context, delAddr sdk.AccAddress) (math.Int, int, error) { - nextEpoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - providers, err := k.GetDelegatorProviders(ctx, delAddr.String(), nextEpoch) + providers, err := k.GetDelegatorProviders(ctx, delAddr.String()) if err != nil { return math.ZeroInt(), 0, err } sumProviderDelegations := sdk.ZeroInt() for _, p := range providers { - delegations := k.GetAllProviderDelegatorDelegations(ctx, delAddr.String(), p, nextEpoch) - for _, d := range delegations { + d, found := k.GetDelegation(ctx, p, delAddr.String()) + if found { sumProviderDelegations = sumProviderDelegations.Add(d.Amount.Amount) } } diff --git a/x/dualstaking/keeper/delegate_test.go b/x/dualstaking/keeper/delegate_test.go index 2ef090c060..0518f01771 100644 --- a/x/dualstaking/keeper/delegate_test.go +++ b/x/dualstaking/keeper/delegate_test.go @@ -44,13 +44,6 @@ func TestDelegateFail(t *testing.T) { chainID: "mockspec", amount: 1, }, - { - name: "bad chainID", - delegator: client1Addr, - provider: provider1Addr, - chainID: "invalid", - amount: 1, - }, { name: "bad amount", delegator: client1Addr, @@ -78,7 +71,7 @@ func TestDelegateFail(t *testing.T) { t.Run(tt.name, func(t *testing.T) { amount := sdk.NewCoin(commontypes.TokenDenom, sdk.ZeroInt()) amount.Amount = amount.Amount.Add(sdk.NewInt(tt.amount)) - _, err := ts.TxDualstakingDelegate(tt.delegator, tt.provider, tt.chainID, amount) + _, err := ts.TxDualstakingDelegate(tt.delegator, tt.provider, amount) require.Error(t, err, tt.name) }) } @@ -97,7 +90,7 @@ func TestDelegate(t *testing.T) { // delegate once amount := sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10000)) - _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) // not yet in effect @@ -111,10 +104,10 @@ func TestDelegate(t *testing.T) { require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) // delegate twice same block (fail) - _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) - _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) @@ -143,7 +136,7 @@ func TestRedelegateFail(t *testing.T) { // delegate once for setup amount := sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10000)) - _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) template := []struct { @@ -178,14 +171,6 @@ func TestRedelegateFail(t *testing.T) { chainID: "mockspec", amount: 1, }, - { - name: "bad chainID", - delegator: client1Addr, - provider1: provider1Addr, - provider2: provider2Addr, - chainID: "invalid", - amount: 1, - }, { name: "bad amount", delegator: client1Addr, @@ -225,7 +210,7 @@ func TestRedelegateFail(t *testing.T) { amount := sdk.NewCoin(commontypes.TokenDenom, sdk.ZeroInt()) amount.Amount = amount.Amount.Add(sdk.NewInt(tt.amount)) _, err := ts.TxDualstakingRedelegate( - tt.delegator, tt.provider1, tt.provider2, tt.chainID, tt.chainID, amount) + tt.delegator, tt.provider1, tt.provider2, amount) require.Error(t, err, tt.name) }) } @@ -247,7 +232,7 @@ func TestRedelegate(t *testing.T) { // delegate once amount := sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10000)) _, err := ts.TxDualstakingDelegate( - client1Addr, provider1Addr, ts.spec.Name, amount) + client1Addr, provider1Addr, amount) require.NoError(t, err) // advance epoch to digest the delegate @@ -262,7 +247,7 @@ func TestRedelegate(t *testing.T) { // redelegate once amount = sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(5000)) _, err = ts.TxDualstakingRedelegate( - client1Addr, provider1Addr, provider2Addr, ts.spec.Name, ts.spec.Name, amount) + client1Addr, provider1Addr, provider2Addr, amount) require.NoError(t, err) stakeEntry1 = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) stakeEntry2 = ts.getStakeEntry(provider2Acct.Addr.String(), ts.spec.Name) @@ -283,8 +268,7 @@ func TestRedelegate(t *testing.T) { // redelegate from unstaking provider amount = sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(5000)) - _, err = ts.TxDualstakingRedelegate( - client1Addr, provider1Addr, provider2Addr, ts.spec.Name, ts.spec.Name, amount) + _, err = ts.TxDualstakingRedelegate(client1Addr, provider1Addr, provider2Addr, amount) require.NoError(t, err) // advance epoch to digest the delegate ts.AdvanceEpoch() @@ -308,7 +292,7 @@ func TestUnbondFail(t *testing.T) { // delegate once for setup amount := sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10000)) - _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) template := []struct { @@ -332,13 +316,6 @@ func TestUnbondFail(t *testing.T) { chainID: "mockspec", amount: 1, }, - { - name: "bad chainID", - delegator: client1Addr, - provider: provider1Addr, - chainID: "invalid", - amount: 1, - }, { name: "bad amount", delegator: client1Addr, @@ -366,7 +343,7 @@ func TestUnbondFail(t *testing.T) { t.Run(tt.name, func(t *testing.T) { amount := sdk.NewCoin(commontypes.TokenDenom, sdk.ZeroInt()) amount.Amount = amount.Amount.Add(sdk.NewInt(tt.amount)) - _, err := ts.TxDualstakingUnbond(tt.delegator, tt.provider, tt.chainID, amount) + _, err := ts.TxDualstakingUnbond(tt.delegator, tt.provider, amount) require.Error(t, err, tt.name) }) } @@ -392,69 +369,68 @@ func TestUnbond(t *testing.T) { // delegate once amount := sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10000)) - _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) - _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, spec2.Index, amount) + _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) // advance epoch to digest the delegate ts.AdvanceEpoch() // now in effect - delegated = delegated.Add(amount) + delegated = delegated.Add(amount).Add(amount) stakeEntry := ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) + require.True(t, delegated.Amount.QuoRaw(2).Equal(stakeEntry.DelegateTotal.Amount)) - res, err := ts.QueryDualstakingDelegatorProviders(client1Addr, true) + res, err := ts.QueryDualstakingDelegatorProviders(client1Addr) require.NoError(t, err) - require.Len(t, res.Delegations, 2) + require.Len(t, res.Delegations, 1) // unbond once amount = sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(1000)) - _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, amount) require.NoError(t, err) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) - + require.True(t, delegated.Amount.QuoRaw(2).Equal(stakeEntry.DelegateTotal.Amount)) // advance epoch to digest the delegate ts.AdvanceEpoch() // now in effect delegated = delegated.Sub(amount) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) + require.True(t, delegated.Amount.QuoRaw(2).Equal(stakeEntry.DelegateTotal.Amount)) // unbond twice in same block, and then in next block - _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, amount) require.NoError(t, err) // _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, amount) // require.Error(t, err) ts.AdvanceBlock() - _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, amount) require.NoError(t, err) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) + require.True(t, delegated.Amount.QuoRaw(2).Equal(stakeEntry.DelegateTotal.Amount)) // advance epoch to digest the delegate ts.AdvanceEpoch() // now in effect delegated = delegated.Sub(amount).Sub(amount) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) + require.True(t, delegated.Amount.QuoRaw(2).Equal(stakeEntry.DelegateTotal.Amount)) _, err = ts.TxPairingUnstakeProvider(provider1Acct.GetVaultAddr(), ts.spec.Name) require.NoError(t, err) // unbond from unstaking provider - _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, amount) require.NoError(t, err) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) + require.True(t, delegated.Amount.QuoRaw(2).Equal(stakeEntry.DelegateTotal.Amount)) delegated = delegated.Sub(amount) // unbond from unstaking provider everything - _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, delegated) + _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, delegated) require.NoError(t, err) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) @@ -469,10 +445,9 @@ func TestUnbond(t *testing.T) { ts.verifyDelegatorsBalance() - res, err = ts.QueryDualstakingDelegatorProviders(client1Addr, true) + res, err = ts.QueryDualstakingDelegatorProviders(client1Addr) require.NoError(t, err) - require.Len(t, res.Delegations, 1) - require.Equal(t, provider1Addr, res.Delegations[0].Provider) + require.Len(t, res.Delegations, 0) } func TestBondUnbondBond(t *testing.T) { @@ -488,7 +463,7 @@ func TestBondUnbondBond(t *testing.T) { // delegate once amount := sdk.NewCoin(commontypes.TokenDenom, sdk.NewInt(10000)) - _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err := ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) // advance epoch to digest the delegate @@ -499,7 +474,7 @@ func TestBondUnbondBond(t *testing.T) { require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) // unbond once - _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingUnbond(client1Addr, provider1Addr, amount) require.NoError(t, err) stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) @@ -512,7 +487,7 @@ func TestBondUnbondBond(t *testing.T) { require.True(t, delegated.IsEqual(stakeEntry.DelegateTotal)) // delegate second time - _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, ts.spec.Name, amount) + _, err = ts.TxDualstakingDelegate(client1Addr, provider1Addr, amount) require.NoError(t, err) ts.AdvanceEpoch() @@ -533,7 +508,7 @@ func TestDualstakingUnbondStakeIsLowerThanMinStakeCausesFreeze(t *testing.T) { amountToUnbond := staked.Sub(minSelfDelegation.AddAmount(math.OneInt())) // unbond once (not unstaking completely but still below min stake) - _, err := ts.TxDualstakingUnbond(provider1Acct.GetVaultAddr(), provider, ts.spec.Name, amountToUnbond) + _, err := ts.TxDualstakingUnbond(provider1Acct.GetVaultAddr(), provider, amountToUnbond) require.NoError(t, err) stakeEntry := ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) @@ -548,7 +523,7 @@ func TestDualstakingUnbondStakeIsLowerThanMinStakeCausesFreeze(t *testing.T) { require.True(t, stakeEntry.IsFrozen()) } -func TestDualstakingUnbondStakeIsLowerThanMinSelfDelegationCausesUnstake(t *testing.T) { +func TestDualstakingUnbondStakeIsLowerThanMinSelfDelegationCausesError(t *testing.T) { ts := newTester(t) // 0 delegator, 1 provider staked, 0 provider unstaked, 0 provider unstaking @@ -560,16 +535,8 @@ func TestDualstakingUnbondStakeIsLowerThanMinSelfDelegationCausesUnstake(t *test amountToUnbond := staked.SubAmount(math.OneInt()) // unbond once (not unstaking completely but still below min stake) - _, err := ts.TxDualstakingUnbond(provider1Acct.GetVaultAddr(), provider, ts.spec.Name, amountToUnbond) - require.NoError(t, err) - - stakeEntry := ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, staked.IsEqual(stakeEntry.Stake)) - - // advance epoch to digest the delegate - ts.AdvanceEpoch() - // provider should be unstaked -> getStakeEntry should panic - require.Panics(t, func() { ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) }) + _, err := ts.TxDualstakingUnbond(provider1Acct.GetVaultAddr(), provider, amountToUnbond) + require.Error(t, err) } func TestDualstakingBondStakeIsGreaterThanMinStakeCausesUnFreeze(t *testing.T) { @@ -584,7 +551,7 @@ func TestDualstakingBondStakeIsGreaterThanMinStakeCausesUnFreeze(t *testing.T) { // delegate once amount := sdk.NewCoin("ulava", sdk.NewInt(10000)) - _, err := ts.TxDualstakingDelegate(provider1Acct.GetVaultAddr(), provider1Addr, ts.spec.Name, amount) + _, err := ts.TxDualstakingDelegate(provider1Acct.GetVaultAddr(), provider1Addr, amount) require.NoError(t, err) // advance epoch to digest the delegate @@ -609,8 +576,8 @@ func TestDualstakingRedelegateFreezeOneUnFreezeOther(t *testing.T) { // redelegate once minSelfDelegation := ts.Keepers.Dualstaking.MinSelfDelegation(ts.Ctx) - amountToUnbond := stake.Sub(stake.Sub(minSelfDelegation.AddAmount(math.OneInt()))) - _, err := ts.TxDualstakingRedelegate(provider1Acct.GetVaultAddr(), provider1Addr, provider2Addr, ts.spec.Name, ts.spec.Name, stake.Sub(amountToUnbond)) + amountToUnbond := minSelfDelegation.AddAmount(math.OneInt()) + _, err := ts.TxDualstakingRedelegate(provider1Acct.GetVaultAddr(), provider1Addr, provider2Addr, stake.Sub(amountToUnbond)) require.NoError(t, err) // advance epoch to digest the delegate @@ -627,7 +594,7 @@ func TestDualstakingRedelegateFreezeOneUnFreezeOther(t *testing.T) { require.False(t, stakeEntry.IsFrozen()) // redelegate again - _, err = ts.TxDualstakingRedelegate(provider2Acct.GetVaultAddr(), provider2Addr, provider1Addr, ts.spec.Name, ts.spec.Name, stake.SubAmount(amountToUnbond.Amount)) + _, err = ts.TxDualstakingRedelegate(provider2Acct.GetVaultAddr(), provider2Addr, provider1Addr, stake.SubAmount(amountToUnbond.Amount)) require.NoError(t, err) // advance epoch to digest the delegate diff --git a/x/dualstaking/keeper/delegator_reward.go b/x/dualstaking/keeper/delegator_reward.go index 5decaf9a7e..e2ec897392 100644 --- a/x/dualstaking/keeper/delegator_reward.go +++ b/x/dualstaking/keeper/delegator_reward.go @@ -1,72 +1,53 @@ package keeper import ( - "fmt" "strconv" "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/utils" - "github.com/lavanet/lava/v3/utils/lavaslices" "github.com/lavanet/lava/v3/x/dualstaking/types" - epochstoragetypes "github.com/lavanet/lava/v3/x/epochstorage/types" spectypes "github.com/lavanet/lava/v3/x/spec/types" ) // SetDelegatorReward set a specific DelegatorReward in the store from its index func (k Keeper) SetDelegatorReward(ctx sdk.Context, delegatorReward types.DelegatorReward) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.DelegatorRewardKeyPrefix)) - index := types.DelegationKey(delegatorReward.Provider, delegatorReward.Delegator, delegatorReward.ChainId) - b := k.cdc.MustMarshal(&delegatorReward) - store.Set(types.DelegatorRewardKey( - index, - ), b) + err := k.rewards.Set(ctx, types.DelegationKey(delegatorReward.Provider, delegatorReward.Delegator), delegatorReward) + if err != nil { + panic(err) + } } // GetDelegatorReward returns a DelegatorReward from its index -func (k Keeper) GetDelegatorReward( - ctx sdk.Context, - index string, -) (val types.DelegatorReward, found bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.DelegatorRewardKeyPrefix)) - - b := store.Get(types.DelegatorRewardKey( - index, - )) - if b == nil { - return val, false - } - - k.cdc.MustUnmarshal(b, &val) - return val, true +func (k Keeper) GetDelegatorReward(ctx sdk.Context, provider, delegator string) (val types.DelegatorReward, found bool) { + val, err := k.rewards.Get(ctx, types.DelegationKey(provider, delegator)) + return val, err == nil } // RemoveDelegatorReward removes a DelegatorReward from the store func (k Keeper) RemoveDelegatorReward( ctx sdk.Context, - index string, + provider, delegator string, ) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.DelegatorRewardKeyPrefix)) - store.Delete(types.DelegatorRewardKey( - index, - )) + err := k.rewards.Remove(ctx, types.DelegationKey(provider, delegator)) + if err != nil { + panic(err) + } } // GetAllDelegatorReward returns all DelegatorReward func (k Keeper) GetAllDelegatorReward(ctx sdk.Context) (list []types.DelegatorReward) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.DelegatorRewardKeyPrefix)) - iterator := sdk.KVStorePrefixIterator(store, []byte{}) - - defer iterator.Close() + iter, err := k.rewards.Iterate(ctx, nil) + if err != nil { + panic(err) + } - for ; iterator.Valid(); iterator.Next() { - var val types.DelegatorReward - k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) + list, err = iter.Values() + if err != nil { + panic(err) } - return + return list } // The reward for servicing a consumer is divided between the provider and its delegators. @@ -83,18 +64,19 @@ func (k Keeper) GetAllDelegatorReward(ctx sdk.Context) (list []types.DelegatorRe // CalcRewards calculates the provider reward and the total reward for delegators // providerReward = totalReward * ((effectiveDelegations*commission + providerStake) / effectiveStake) // delegatorsReward = totalReward - providerReward -func (k Keeper) CalcRewards(ctx sdk.Context, stakeEntry epochstoragetypes.StakeEntry, totalReward sdk.Coins, delegations []types.Delegation) (providerReward sdk.Coins, delegatorsReward sdk.Coins) { +func (k Keeper) CalcRewards(ctx sdk.Context, totalReward sdk.Coins, totalDelegations math.Int, selfDelegation types.Delegation, delegations []types.Delegation, commission uint64) (providerReward sdk.Coins, delegatorsReward sdk.Coins) { zeroCoins := sdk.NewCoins() + totalDelegationsWithSelf := totalDelegations.Add(selfDelegation.Amount.Amount) // Sanity check - effectiveStake != 0 - if stakeEntry.DelegateTotal.IsZero() && stakeEntry.Stake.IsZero() { + if totalDelegationsWithSelf.IsZero() { return zeroCoins, zeroCoins } - providerReward = totalReward.MulInt(stakeEntry.Stake.Amount).QuoInt(stakeEntry.TotalStake()) - if !stakeEntry.DelegateTotal.IsZero() && stakeEntry.DelegateCommission != 0 { - rawDelegatorsReward := totalReward.MulInt(stakeEntry.DelegateTotal.Amount).QuoInt(stakeEntry.TotalStake()) - providerCommission := rawDelegatorsReward.MulInt(sdk.NewIntFromUint64(stakeEntry.DelegateCommission)).QuoInt(sdk.NewInt(100)) + providerReward = totalReward.MulInt(selfDelegation.Amount.Amount).QuoInt(totalDelegationsWithSelf) + if !totalDelegations.IsZero() && commission != 0 { + rawDelegatorsReward := totalReward.MulInt(totalDelegations).QuoInt(totalDelegationsWithSelf) + providerCommission := rawDelegatorsReward.MulInt(sdk.NewIntFromUint64(commission)).QuoInt(sdk.NewInt(100)) providerReward = providerReward.Add(providerCommission...) } @@ -137,9 +119,7 @@ func (k Keeper) ClaimRewards(ctx sdk.Context, delegator string, provider string) rewardCoins := sdk.NewCoins() for _, reward := range res.Rewards { rewardCoins = rewardCoins.Add(reward.Amount...) - - ind := types.DelegationKey(reward.Provider, delegator, reward.ChainId) - k.RemoveDelegatorReward(ctx, ind) + k.RemoveDelegatorReward(ctx, reward.Provider, delegator) } // not minting new coins because they're minted when the provider @@ -163,24 +143,15 @@ func (k Keeper) ClaimRewards(ctx sdk.Context, delegator string, provider string) func (k Keeper) RewardProvidersAndDelegators(ctx sdk.Context, provider string, chainID string, totalReward sdk.Coins, senderModule string, calcOnlyProvider bool, calcOnlyDelegators bool, calcOnlyContributor bool) (providerReward sdk.Coins, err error) { block := uint64(ctx.BlockHeight()) zeroCoins := sdk.NewCoins() - epoch, _, err := k.epochstorageKeeper.GetEpochStartForBlock(ctx, block) + + metadata, err := k.epochstorageKeeper.GetMetadata(ctx, provider) if err != nil { return zeroCoins, utils.LavaFormatError(types.ErrCalculatingProviderReward.Error(), err, utils.Attribute{Key: "block", Value: block}, ) } - stakeEntry, found := k.epochstorageKeeper.GetStakeEntry(ctx, epoch, chainID, provider) - if !found { - return zeroCoins, utils.LavaFormatWarning("RewardProvidersAndDelegators: cannot send rewards to provider and delegators", fmt.Errorf("provider stake entry not found, probably unstaked"), - utils.LogAttr("epoch", epoch), - utils.LogAttr("provider", provider), - utils.LogAttr("chain_id", chainID), - utils.LogAttr("sender_module", senderModule), - utils.LogAttr("reward", totalReward.String()), - ) - } - delegations, err := k.GetProviderDelegators(ctx, provider, epoch) + delegations, err := k.GetProviderDelegators(ctx, provider) if err != nil { return zeroCoins, utils.LavaFormatError("cannot get provider's delegators", err) } @@ -200,21 +171,27 @@ func (k Keeper) RewardProvidersAndDelegators(ctx sdk.Context, provider string, c } } - // delegators eligible for rewards are delegators that their delegation is at least a week old - relevantDelegations := lavaslices.Filter(delegations, - func(d types.Delegation) bool { - return d.ChainID == chainID && d.IsFirstWeekPassed(ctx.BlockTime().UTC().Unix()) && d.Delegator != stakeEntry.Vault - }) + relevantDelegations := []types.Delegation{} + totalDelegations := sdk.ZeroInt() + var selfdelegation types.Delegation + // fetch relevant delegations (those who are passed the first week of delegation), self delegation and sum the total delegations + for _, d := range delegations { + if d.Delegator == metadata.Vault { + selfdelegation = d + } else if d.IsFirstWeekPassed(ctx.BlockTime().UTC().Unix()) { + relevantDelegations = append(relevantDelegations, d) + totalDelegations = totalDelegations.Add(d.Amount.Amount) + } + } - // calculate the rewards for the providers and delegators (total reward - contributors reward) - providerReward, delegatorsReward := k.CalcRewards(ctx, stakeEntry, totalReward.Sub(contributorReward...), relevantDelegations) + providerReward, delegatorsReward := k.CalcRewards(ctx, totalReward.Sub(contributorReward...), totalDelegations, selfdelegation, relevantDelegations, metadata.DelegateCommission) - leftoverRewards := k.updateDelegatorsReward(ctx, stakeEntry.DelegateTotal.Amount, relevantDelegations, delegatorsReward, senderModule, calcOnlyDelegators) + leftoverRewards := k.updateDelegatorsReward(ctx, totalDelegations, relevantDelegations, delegatorsReward, senderModule, calcOnlyDelegators) fullProviderReward := providerReward.Add(leftoverRewards...) if !calcOnlyProvider { // reward provider's vault - k.rewardDelegator(ctx, types.Delegation{Provider: stakeEntry.Address, ChainID: chainID, Delegator: stakeEntry.Vault}, fullProviderReward, senderModule) + k.rewardDelegator(ctx, types.Delegation{Provider: metadata.Provider, Delegator: metadata.Vault}, fullProviderReward, senderModule) } return fullProviderReward, nil @@ -240,12 +217,10 @@ func (k Keeper) rewardDelegator(ctx sdk.Context, delegation types.Delegation, am return } - rewardMapKey := types.DelegationKey(delegation.Provider, delegation.Delegator, delegation.ChainID) - delegatorReward, found := k.GetDelegatorReward(ctx, rewardMapKey) + delegatorReward, found := k.GetDelegatorReward(ctx, delegation.Provider, delegation.Delegator) if !found { delegatorReward.Provider = delegation.Provider delegatorReward.Delegator = delegation.Delegator - delegatorReward.ChainId = delegation.ChainID delegatorReward.Amount = amount } else { delegatorReward.Amount = delegatorReward.Amount.Add(amount...) diff --git a/x/dualstaking/keeper/delegator_reward_test.go b/x/dualstaking/keeper/delegator_reward_test.go index ca684a3f60..f5d2a3237b 100644 --- a/x/dualstaking/keeper/delegator_reward_test.go +++ b/x/dualstaking/keeper/delegator_reward_test.go @@ -20,7 +20,6 @@ func createNDelegatorReward(keeper *keeper.Keeper, ctx sdk.Context, n int) []typ for i := range items { items[i].Provider = "p" + strconv.Itoa(i) items[i].Delegator = "d" + strconv.Itoa(i) - items[i].ChainId = "c" + strconv.Itoa(i) keeper.SetDelegatorReward(ctx, items[i]) } return items @@ -30,10 +29,8 @@ func TestDelegatorRewardGet(t *testing.T) { keeper, ctx := keepertest.DualstakingKeeper(t) items := createNDelegatorReward(keeper, ctx, 10) for _, item := range items { - index := types.DelegationKey(item.Provider, item.Delegator, item.ChainId) rst, found := keeper.GetDelegatorReward(ctx, - index, - ) + item.Provider, item.Delegator) require.True(t, found) require.Equal(t, nullify.Fill(&item), @@ -46,13 +43,10 @@ func TestDelegatorRewardRemove(t *testing.T) { keeper, ctx := keepertest.DualstakingKeeper(t) items := createNDelegatorReward(keeper, ctx, 10) for _, item := range items { - index := types.DelegationKey(item.Provider, item.Delegator, item.ChainId) keeper.RemoveDelegatorReward(ctx, - index, - ) + item.Provider, item.Delegator) _, found := keeper.GetDelegatorReward(ctx, - index, - ) + item.Provider, item.Delegator) require.False(t, found) } } diff --git a/x/dualstaking/keeper/grpc_query_delegator_providers.go b/x/dualstaking/keeper/grpc_query_delegator_providers.go index 172a6e6d65..f94530c7d2 100644 --- a/x/dualstaking/keeper/grpc_query_delegator_providers.go +++ b/x/dualstaking/keeper/grpc_query_delegator_providers.go @@ -2,10 +2,8 @@ package keeper import ( "context" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/lavanet/lava/v3/utils" "github.com/lavanet/lava/v3/x/dualstaking/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -18,30 +16,15 @@ func (k Keeper) DelegatorProviders(goCtx context.Context, req *types.QueryDelega ctx := sdk.UnwrapSDKContext(goCtx) - epoch := uint64(ctx.BlockHeight()) - if req.WithPending { - epoch = k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - } - - providers, err := k.GetDelegatorProviders(ctx, req.Delegator, epoch) + providers, err := k.GetDelegatorProviders(ctx, req.Delegator) if err != nil { return nil, err } var delegations []types.Delegation for _, provider := range providers { - indices := k.delegationFS.GetAllEntryIndicesWithPrefix(ctx, types.DelegationKey(provider, req.Delegator, "")) - for _, ind := range indices { - var delegation types.Delegation - found := k.delegationFS.FindEntry(ctx, ind, epoch, &delegation) - if !found { - utils.LavaFormatError("critical: provider found in delegatorFS but not in delegationFS", fmt.Errorf("provider delegation not found"), - utils.Attribute{Key: "delegator", Value: req.Delegator}, - utils.Attribute{Key: "provider", Value: provider}, - utils.Attribute{Key: "chainID", Value: delegation.ChainID}, - ) - continue - } + delegation, found := k.GetDelegation(ctx, provider, req.Delegator) + if found { delegations = append(delegations, delegation) } } diff --git a/x/dualstaking/keeper/grpc_query_delegator_providers_test.go b/x/dualstaking/keeper/grpc_query_delegator_providers_test.go index a8688e6eee..e546fa206c 100644 --- a/x/dualstaking/keeper/grpc_query_delegator_providers_test.go +++ b/x/dualstaking/keeper/grpc_query_delegator_providers_test.go @@ -17,49 +17,47 @@ func TestQueryWithUnbonding(t *testing.T) { _, delegator := ts.GetAccount(common.CONSUMER, 0) _, provider := ts.GetAccount(common.PROVIDER, 0) - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) // delegate and query - _, err := ts.TxDualstakingDelegate(delegator, provider, spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator, provider, amount) require.NoError(t, err) ts.AdvanceEpoch() - delegation := types.NewDelegation(delegator, provider, spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation := types.NewDelegation(delegator, provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation.Amount = amount - res, err := ts.QueryDualstakingDelegatorProviders(delegator, false) + res, err := ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) delegationRes := res.Delegations[0] require.True(t, delegation.Equal(&delegationRes)) // partially unbond and query unbondAmount := amount.Sub(sdk.NewCoin(ts.TokenDenom(), sdk.OneInt())) - _, err = ts.TxDualstakingUnbond(delegator, provider, spec.Index, unbondAmount) + _, err = ts.TxDualstakingUnbond(delegator, provider, unbondAmount) require.NoError(t, err) ts.AdvanceEpoch() bondedAmount := amount.Sub(unbondAmount) delegation.Amount = bondedAmount - res, err = ts.QueryDualstakingDelegatorProviders(delegator, false) + res, err = ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) delegationRes = res.Delegations[0] require.True(t, delegation.Equal(&delegationRes)) // unbond completely and query (should not get providers) - _, err = ts.TxDualstakingUnbond(delegator, provider, spec.Index, bondedAmount) + _, err = ts.TxDualstakingUnbond(delegator, provider, bondedAmount) require.NoError(t, err) ts.AdvanceEpoch() - res, err = ts.QueryDualstakingDelegatorProviders(delegator, false) + res, err = ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) require.Equal(t, 0, len(res.Delegations)) } -func TestQueryWithPendingDelegations(t *testing.T) { +func TestQueryDelegations(t *testing.T) { ts := newTester(t) ts.setupForDelegation(2, 1, 0, 0) // 2 delegators, 1 staked provider @@ -68,62 +66,45 @@ func TestQueryWithPendingDelegations(t *testing.T) { _, delegator2 := ts.GetAccount(common.CONSUMER, 1) _, provider := ts.GetAccount(common.PROVIDER, 0) - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) - delegation1 := types.NewDelegation(delegator1, provider, spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation1 := types.NewDelegation(delegator1, provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation1.Amount = amount // delegate without advancing an epoch - _, err := ts.TxDualstakingDelegate(delegator1, provider, spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator1, provider, amount) require.NoError(t, err) // query pending delegators - res, err := ts.QueryDualstakingDelegatorProviders(delegator1, true) + res, err := ts.QueryDualstakingDelegatorProviders(delegator1) require.NoError(t, err) require.Equal(t, 1, len(res.Delegations)) delegationRes := res.Delegations[0] require.True(t, delegationRes.Equal(&delegation1)) - // query current delegators - res, err = ts.QueryDualstakingDelegatorProviders(delegator1, false) - require.NoError(t, err) - require.Equal(t, 0, len(res.Delegations)) - // advance epoch, delegator1 should show in both flag values ts.AdvanceEpoch() - res, err = ts.QueryDualstakingDelegatorProviders(delegator1, true) - require.NoError(t, err) - require.Equal(t, 1, len(res.Delegations)) - delegationRes = res.Delegations[0] - require.True(t, delegationRes.Equal(&delegation1)) - - res, err = ts.QueryDualstakingDelegatorProviders(delegator1, false) + res, err = ts.QueryDualstakingDelegatorProviders(delegator1) require.NoError(t, err) require.Equal(t, 1, len(res.Delegations)) delegationRes = res.Delegations[0] require.True(t, delegationRes.Equal(&delegation1)) // delegate delegator2 and query again - delegation2 := types.NewDelegation(delegator2, provider, spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation2 := types.NewDelegation(delegator2, provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation2.Amount = amount - _, err = ts.TxDualstakingDelegate(delegator2, provider, spec.Index, amount) + _, err = ts.TxDualstakingDelegate(delegator2, provider, amount) require.NoError(t, err) // delegator2 should show when quering with showPending=true and not show when showPending=false - res, err = ts.QueryDualstakingDelegatorProviders(delegator2, true) + res, err = ts.QueryDualstakingDelegatorProviders(delegator2) require.NoError(t, err) require.Equal(t, 1, len(res.Delegations)) delegationRes = res.Delegations[0] require.True(t, delegationRes.Equal(&delegation2)) - - res, err = ts.QueryDualstakingDelegatorProviders(delegator2, false) - require.NoError(t, err) - require.Equal(t, 0, len(res.Delegations)) } func TestQueryProviderMultipleDelegators(t *testing.T) { @@ -140,7 +121,6 @@ func TestQueryProviderMultipleDelegators(t *testing.T) { delegators := []string{delegator1, delegator2, delegator3} - spec := ts.Spec("mock") spec1 := ts.Spec("mock1") err := ts.StakeProvider(providerAcc.GetVaultAddr(), provider, spec1, testStake) require.NoError(t, err) @@ -150,16 +130,10 @@ func TestQueryProviderMultipleDelegators(t *testing.T) { delegations := []types.Delegation{} for i := 0; i < len(delegators); i++ { - var chainID string - if i == 0 { - chainID = spec.Index - } else { - chainID = spec1.Index - } - _, err := ts.TxDualstakingDelegate(delegators[i], provider, chainID, amount) + _, err := ts.TxDualstakingDelegate(delegators[i], provider, amount) require.NoError(t, err) - delegation := types.NewDelegation(delegators[i], provider, chainID, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation := types.NewDelegation(delegators[i], provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation.Amount = amount delegations = append(delegations, delegation) } @@ -167,7 +141,7 @@ func TestQueryProviderMultipleDelegators(t *testing.T) { ts.AdvanceEpoch() for i := 0; i < len(delegations); i++ { - res, err := ts.QueryDualstakingDelegatorProviders(delegations[i].Delegator, false) + res, err := ts.QueryDualstakingDelegatorProviders(delegations[i].Delegator) require.NoError(t, err) require.Equal(t, 1, len(res.Delegations)) resDelegation := res.Delegations[0] @@ -187,29 +161,28 @@ func TestQueryDelegatorMultipleProviders(t *testing.T) { providers := []string{provider1, provider2, provider3} - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) - delegations := []types.Delegation{} + delegations := map[string]types.Delegation{} for i := 0; i < len(providers); i++ { - _, err := ts.TxDualstakingDelegate(delegator, providers[i], spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator, providers[i], amount) require.NoError(t, err) - delegation := types.NewDelegation(delegator, providers[i], spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation := types.NewDelegation(delegator, providers[i], ts.Ctx.BlockTime(), ts.TokenDenom()) delegation.Amount = amount - delegations = append(delegations, delegation) + delegations[providers[i]] = delegation } ts.AdvanceEpoch() - res, err := ts.QueryDualstakingDelegatorProviders(delegator, false) + res, err := ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) require.Equal(t, 3, len(res.Delegations)) for i := 0; i < len(delegations); i++ { resDelegation := res.Delegations[i] - require.True(t, resDelegation.Equal(&delegations[i])) + delegation := delegations[resDelegation.Provider] + require.True(t, resDelegation.Equal(&delegation)) } } @@ -222,16 +195,14 @@ func TestQueryDelegatorUnstakedProvider(t *testing.T) { _, unstakedProvider := ts.GetAccount(common.PROVIDER, 0) _, unstakingProvider := ts.GetAccount(common.PROVIDER, 1) - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) // shouldn't be able to delegate to unstaked provider - _, err := ts.TxDualstakingDelegate(delegator, unstakedProvider, spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator, unstakedProvider, amount) require.Error(t, err) // shouldn't be able to delegate to unstaking provider (even though it didn't get its funds back, it's still considered unstaked) - _, err = ts.TxDualstakingDelegate(delegator, unstakingProvider, spec.Index, amount) + _, err = ts.TxDualstakingDelegate(delegator, unstakingProvider, amount) require.Error(t, err) } diff --git a/x/dualstaking/keeper/grpc_query_delegator_rewards.go b/x/dualstaking/keeper/grpc_query_delegator_rewards.go index bea3ab4281..36dcd1a84b 100644 --- a/x/dualstaking/keeper/grpc_query_delegator_rewards.go +++ b/x/dualstaking/keeper/grpc_query_delegator_rewards.go @@ -23,14 +23,11 @@ func (k Keeper) DelegatorRewards(goCtx context.Context, req *types.QueryDelegato } for _, delegation := range resProviders.Delegations { - if (delegation.ChainID == req.ChainId || req.ChainId == "") && - (delegation.Provider == req.Provider || req.Provider == "") { - ind := types.DelegationKey(delegation.Provider, req.Delegator, delegation.ChainID) - delegatorReward, found := k.GetDelegatorReward(ctx, ind) + if delegation.Provider == req.Provider || req.Provider == "" { + delegatorReward, found := k.GetDelegatorReward(ctx, delegation.Provider, delegation.Delegator) if found { reward := types.DelegatorRewardInfo{ Provider: delegation.Provider, - ChainId: delegation.ChainID, Amount: delegatorReward.Amount, } rewards = append(rewards, reward) diff --git a/x/dualstaking/keeper/grpc_query_provider_delegators.go b/x/dualstaking/keeper/grpc_query_provider_delegators.go index 72085ad045..6d02347ac7 100644 --- a/x/dualstaking/keeper/grpc_query_provider_delegators.go +++ b/x/dualstaking/keeper/grpc_query_provider_delegators.go @@ -16,12 +16,7 @@ func (k Keeper) ProviderDelegators(goCtx context.Context, req *types.QueryProvid ctx := sdk.UnwrapSDKContext(goCtx) - epoch := uint64(ctx.BlockHeight()) - if req.WithPending { - epoch = k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - } - - delegations, err := k.GetProviderDelegators(ctx, req.Provider, epoch) + delegations, err := k.GetProviderDelegators(ctx, req.Provider) if err != nil { return nil, err } diff --git a/x/dualstaking/keeper/grpc_query_provider_delegators_test.go b/x/dualstaking/keeper/grpc_query_provider_delegators_test.go index 4ae641a48e..e60d13ef6f 100644 --- a/x/dualstaking/keeper/grpc_query_provider_delegators_test.go +++ b/x/dualstaking/keeper/grpc_query_provider_delegators_test.go @@ -17,20 +17,18 @@ func TestQueryProviderDelegatorsWithUnbonding(t *testing.T) { _, delegator := ts.GetAccount(common.CONSUMER, 0) _, provider := ts.GetAccount(common.PROVIDER, 0) - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) // delegate and query - _, err := ts.TxDualstakingDelegate(delegator, provider, spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator, provider, amount) require.NoError(t, err) ts.AdvanceEpoch() - delegation := types.NewDelegation(delegator, provider, spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation := types.NewDelegation(delegator, provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation.Amount = amount - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) var delegationRes types.Delegation @@ -43,14 +41,14 @@ func TestQueryProviderDelegatorsWithUnbonding(t *testing.T) { // partially unbond and query unbondAmount := amount.Sub(sdk.NewCoin(ts.TokenDenom(), sdk.OneInt())) - _, err = ts.TxDualstakingUnbond(delegator, provider, spec.Index, unbondAmount) + _, err = ts.TxDualstakingUnbond(delegator, provider, unbondAmount) require.NoError(t, err) ts.AdvanceEpoch() bondedAmount := amount.Sub(unbondAmount) delegation.Amount = bondedAmount - res, err = ts.QueryDualstakingProviderDelegators(provider, false) + res, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) for _, d := range res.Delegations { @@ -61,16 +59,16 @@ func TestQueryProviderDelegatorsWithUnbonding(t *testing.T) { require.True(t, delegation.Equal(&delegationRes)) // unbond completely and query (should not get providers) - _, err = ts.TxDualstakingUnbond(delegator, provider, spec.Index, bondedAmount) + _, err = ts.TxDualstakingUnbond(delegator, provider, bondedAmount) require.NoError(t, err) ts.AdvanceEpoch() - res, err = ts.QueryDualstakingProviderDelegators(provider, false) + res, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 1, len(res.Delegations)) } -func TestQueryProviderDelegatorsWithPendingDelegations(t *testing.T) { +func TestQueryProviderDelegators(t *testing.T) { ts := newTester(t) ts.setupForDelegation(2, 1, 0, 0) // 2 delegators, 1 staked provider @@ -79,20 +77,18 @@ func TestQueryProviderDelegatorsWithPendingDelegations(t *testing.T) { _, delegator2 := ts.GetAccount(common.CONSUMER, 1) _, provider := ts.GetAccount(common.PROVIDER, 0) - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) - delegation1 := types.NewDelegation(delegator1, provider, spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation1 := types.NewDelegation(delegator1, provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation1.Amount = amount // delegate without advancing an epoch - _, err := ts.TxDualstakingDelegate(delegator1, provider, spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator1, provider, amount) require.NoError(t, err) // query pending delegators - res, err := ts.QueryDualstakingProviderDelegators(provider, true) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) var delegationRes types.Delegation @@ -103,15 +99,7 @@ func TestQueryProviderDelegatorsWithPendingDelegations(t *testing.T) { } require.True(t, delegationRes.Equal(&delegation1)) - // query current delegators - res, err = ts.QueryDualstakingProviderDelegators(provider, false) - require.NoError(t, err) - require.Equal(t, 1, len(res.Delegations)) - - // advance epoch, delegator1 should show in both flag values - ts.AdvanceEpoch() - - res, err = ts.QueryDualstakingProviderDelegators(provider, true) + res, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) for _, d := range res.Delegations { @@ -121,7 +109,7 @@ func TestQueryProviderDelegatorsWithPendingDelegations(t *testing.T) { } require.True(t, delegationRes.Equal(&delegation1)) - res, err = ts.QueryDualstakingProviderDelegators(provider, false) + res, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) for _, d := range res.Delegations { @@ -132,13 +120,13 @@ func TestQueryProviderDelegatorsWithPendingDelegations(t *testing.T) { require.True(t, delegationRes.Equal(&delegation1)) // delegate delegator2 and query again - delegation2 := types.NewDelegation(delegator2, provider, spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation2 := types.NewDelegation(delegator2, provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation2.Amount = amount - _, err = ts.TxDualstakingDelegate(delegator2, provider, spec.Index, amount) + _, err = ts.TxDualstakingDelegate(delegator2, provider, amount) require.NoError(t, err) // delegator2 should show when quering with showPending=true and not show when showPending=false - res, err = ts.QueryDualstakingProviderDelegators(provider, true) + res, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 3, len(res.Delegations)) for _, d := range res.Delegations { @@ -148,16 +136,6 @@ func TestQueryProviderDelegatorsWithPendingDelegations(t *testing.T) { require.True(t, d.Equal(&delegation2)) } } - - res, err = ts.QueryDualstakingProviderDelegators(provider, false) - require.NoError(t, err) - require.Equal(t, 2, len(res.Delegations)) - for _, d := range res.Delegations { - if d.Delegator == delegation1.Delegator { - delegationRes = d - } - } - require.True(t, delegationRes.Equal(&delegation1)) } func TestQueryProviderDelegatorsProviderMultipleDelegators(t *testing.T) { @@ -174,7 +152,6 @@ func TestQueryProviderDelegatorsProviderMultipleDelegators(t *testing.T) { delegators := []string{delegator1, delegator2, delegator3} - spec := ts.Spec("mock") spec1 := ts.Spec("mock1") err := ts.StakeProvider(providerAcc.GetVaultAddr(), provider, spec1, testStake) require.NoError(t, err) @@ -184,22 +161,16 @@ func TestQueryProviderDelegatorsProviderMultipleDelegators(t *testing.T) { delegations := []types.Delegation{} for i := 0; i < len(delegators); i++ { - var chainID string - if i == 0 { - chainID = spec.Index - } else { - chainID = spec1.Index - } - _, err := ts.TxDualstakingDelegate(delegators[i], provider, chainID, amount) + _, err := ts.TxDualstakingDelegate(delegators[i], provider, amount) require.NoError(t, err) - delegation := types.NewDelegation(delegators[i], provider, chainID, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation := types.NewDelegation(delegators[i], provider, ts.Ctx.BlockTime(), ts.TokenDenom()) delegation.Amount = amount delegations = append(delegations, delegation) } ts.AdvanceEpoch() - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.Equal(t, 4, len(res.Delegations)) require.NoError(t, err) for _, d := range delegations { @@ -223,17 +194,15 @@ func TestQueryProviderDelegatorsDelegatorMultipleProviders(t *testing.T) { providers := []string{provider1, provider2, provider3} - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) delegations := []types.Delegation{} for i := 0; i < len(providers); i++ { - _, err := ts.TxDualstakingDelegate(delegator, providers[i], spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator, providers[i], amount) require.NoError(t, err) - delegation := types.NewDelegation(delegator, providers[i], spec.Index, ts.Ctx.BlockTime(), ts.TokenDenom()) + delegation := types.NewDelegation(delegator, providers[i], ts.Ctx.BlockTime(), ts.TokenDenom()) delegation.Amount = amount delegations = append(delegations, delegation) } @@ -241,7 +210,7 @@ func TestQueryProviderDelegatorsDelegatorMultipleProviders(t *testing.T) { ts.AdvanceEpoch() for i := 0; i < len(providers); i++ { - res, err := ts.QueryDualstakingProviderDelegators(providers[i], false) + res, err := ts.QueryDualstakingProviderDelegators(providers[i]) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) var delegationRes types.Delegation @@ -263,16 +232,14 @@ func TestQueryProviderDelegatorsDelegatorUnstakedProvider(t *testing.T) { _, unstakedProvider := ts.GetAccount(common.PROVIDER, 0) _, unstakingProvider := ts.GetAccount(common.PROVIDER, 1) - spec := ts.Spec("mock") - amountUint64 := uint64(100) amount := sdk.NewCoin(ts.TokenDenom(), sdk.NewIntFromUint64(amountUint64)) // shouldn't be able to delegate to unstaked provider - _, err := ts.TxDualstakingDelegate(delegator, unstakedProvider, spec.Index, amount) + _, err := ts.TxDualstakingDelegate(delegator, unstakedProvider, amount) require.Error(t, err) // shouldn't be able to delegate to unstaking provider (even though it didn't get its funds back, it's still considered unstaked) - _, err = ts.TxDualstakingDelegate(delegator, unstakingProvider, spec.Index, amount) + _, err = ts.TxDualstakingDelegate(delegator, unstakingProvider, amount) require.Error(t, err) } diff --git a/x/dualstaking/keeper/hooks_test.go b/x/dualstaking/keeper/hooks_test.go index 9a46c24953..f988230a56 100644 --- a/x/dualstaking/keeper/hooks_test.go +++ b/x/dualstaking/keeper/hooks_test.go @@ -28,7 +28,7 @@ func TestCreateValidator(t *testing.T) { amount := sdk.NewIntFromUint64(100) ts.TxCreateValidator(validator, amount) - res, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, true) + res, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, res.Delegations[0].Delegator, validator.Addr.String()) } @@ -43,7 +43,7 @@ func TestDelegateToValidator(t *testing.T) { amount := sdk.NewIntFromUint64(100) ts.TxCreateValidator(validator, amount) - res, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, true) + res, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, res.Delegations[0].Delegator, validator.Addr.String()) @@ -52,7 +52,7 @@ func TestDelegateToValidator(t *testing.T) { _, err = ts.TxDelegateValidator(delegator, validator, amount) require.NoError(t, err) - res, err = ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, true) + res, err = ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) require.True(t, res.Delegations[0].Delegator == validator.Addr.String() || res.Delegations[0].Delegator == delegator.Addr.String()) @@ -71,7 +71,7 @@ func TestReDelegateToValidator(t *testing.T) { ts.TxCreateValidator(validator1, amount) ts.TxCreateValidator(validator2, amount) - delegatorsRes, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, true) + delegatorsRes, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, 2, len(delegatorsRes.Delegations)) @@ -80,11 +80,11 @@ func TestReDelegateToValidator(t *testing.T) { _, err = ts.TxDelegateValidator(delegator, validator1, amount) require.NoError(t, err) - delegatorsRes, err = ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, true) + delegatorsRes, err = ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, 3, len(delegatorsRes.Delegations)) - providersRes, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String(), true) + providersRes, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String()) require.NoError(t, err) require.Equal(t, 1, len(providersRes.Delegations)) require.Equal(t, delegator.Addr.String(), providersRes.Delegations[0].Delegator) @@ -92,11 +92,11 @@ func TestReDelegateToValidator(t *testing.T) { _, err = ts.TxReDelegateValidator(delegator, validator1, validator2, amount) require.NoError(t, err) - delegatorsRes1, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, true) + delegatorsRes1, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, delegatorsRes, delegatorsRes1) - providersRes1, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String(), true) + providersRes1, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String()) require.NoError(t, err) require.Equal(t, providersRes, providersRes1) } @@ -128,7 +128,7 @@ func TestReDelegateToProvider(t *testing.T) { require.True(t, found) require.Equal(t, amount, entry.Stake.Amount) - providersRes, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String(), true) + providersRes, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String()) require.NoError(t, err) require.Equal(t, 1, len(providersRes.Delegations)) require.Equal(t, commontypes.EMPTY_PROVIDER, providersRes.Delegations[0].Provider) @@ -138,19 +138,12 @@ func TestReDelegateToProvider(t *testing.T) { _, err = ts.TxDualstakingRedelegate(delegator.Addr.String(), commontypes.EMPTY_PROVIDER, provider, - commontypes.EMPTY_PROVIDER_CHAINID, - entry.Chain, sdk.NewCoin(ts.TokenDenom(), amount)) require.NoError(t, err) - providersRes1, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String(), false) + providersRes1, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String()) require.NoError(t, err) - require.Equal(t, providersRes, providersRes1) - - providersRes1, err = ts.QueryDualstakingDelegatorProviders(delegator.Addr.String(), true) - require.NoError(t, err) - require.Equal(t, provider, providersRes1.Delegations[0].Provider) ts.AdvanceEpoch() @@ -159,6 +152,7 @@ func TestReDelegateToProvider(t *testing.T) { require.True(t, found) require.Equal(t, amount, entry.DelegateTotal.Amount) require.Equal(t, amount, entry.Stake.Amount) + require.Equal(t, provider, providersRes1.Delegations[0].Provider) } // TestUnbondUniformProviders checks that the uniform unbond of providers (that is triggered by a validator unbond) @@ -208,8 +202,6 @@ func TestUnbondUniformProviders(t *testing.T) { _, err = ts.TxDualstakingRedelegate(delegatorAcc.Addr.String(), commontypes.EMPTY_PROVIDER, provider, - commontypes.EMPTY_PROVIDER_CHAINID, - ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), redelegateAmts[i])) require.NoError(t, err) } @@ -218,7 +210,7 @@ func TestUnbondUniformProviders(t *testing.T) { _, err = ts.TxUnbondValidator(delegatorAcc, validator, sdk.NewInt(25*5)) require.NoError(t, err) - res, err := ts.QueryDualstakingDelegatorProviders(delegator, true) + res, err := ts.QueryDualstakingDelegatorProviders(delegator) require.Len(t, res.Delegations, 3) require.NoError(t, err) for _, d := range res.Delegations { @@ -254,7 +246,7 @@ func TestValidatorSlash(t *testing.T) { require.Equal(t, amount, val.Tokens) // sanity check: empty provider should have delegation of 1000000000 tokens - resQ, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, false) + resQ, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, 1, len(resQ.Delegations)) require.Equal(t, amount, resQ.Delegations[0].Amount.Amount) @@ -268,7 +260,7 @@ func TestValidatorSlash(t *testing.T) { // check: the only delegation should be validator delegated to empty provider // the delegation amount should be original_amount(=1000000000) - expectedTokensToBurn - res, err := ts.QueryDualstakingDelegatorProviders(valAcc.Addr.String(), true) + res, err := ts.QueryDualstakingDelegatorProviders(valAcc.Addr.String()) require.NoError(t, err) require.Equal(t, 1, len(res.Delegations)) // empty provider require.Equal(t, amount.Sub(expectedTokensToBurn), res.Delegations[0].Amount.Amount) @@ -322,7 +314,7 @@ func TestValidatorAndProvidersSlash(t *testing.T) { ts.AdvanceEpoch() // advance epoch to apply the empty provider delegation (that happens automatically when delegating to the validator) // sanity check: empty provider should have val_stake(=1000000000) + 250*consensusPowerTokens tokens in two delegations - resQ, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER, false) + resQ, err := ts.QueryDualstakingProviderDelegators(commontypes.EMPTY_PROVIDER) require.NoError(t, err) require.Equal(t, 2, len(resQ.Delegations)) require.Equal(t, stake.Add(consensusPowerTokens.MulRaw(250)), resQ.Delegations[0].Amount.Amount.Add(resQ.Delegations[1].Amount.Amount)) @@ -343,14 +335,12 @@ func TestValidatorAndProvidersSlash(t *testing.T) { _, err = ts.TxDualstakingRedelegate(delegatorAcc.Addr.String(), commontypes.EMPTY_PROVIDER, provider, - commontypes.EMPTY_PROVIDER_CHAINID, - ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), redelegateAmts[i])) require.NoError(t, err) ts.AdvanceEpoch() // verify delegation is applied (should be 2 delegations: self delegation + redelegate amount) - resQ, err = ts.QueryDualstakingProviderDelegators(provider, false) + resQ, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(resQ.Delegations)) require.Equal(t, redelegateAmts[i].Add(stake), resQ.Delegations[0].Amount.Amount.Add(resQ.Delegations[1].Amount.Amount)) @@ -361,7 +351,7 @@ func TestValidatorAndProvidersSlash(t *testing.T) { ts.AdvanceBlockUntilStale() // sanity check: redelegate from provider0 to provider1 and check delegations balance - _, err = ts.TxDualstakingRedelegate(delegator, providers[0], providers[1], ts.spec.Index, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), consensusPowerTokens.MulRaw(5))) + _, err = ts.TxDualstakingRedelegate(delegator, providers[0], providers[1], sdk.NewCoin(ts.TokenDenom(), consensusPowerTokens.MulRaw(5))) require.NoError(t, err) ts.AdvanceEpoch() // apply redelegation diff, _, err := ts.Keepers.Dualstaking.VerifyDelegatorBalance(ts.Ctx, delegatorAcc.Addr) @@ -369,7 +359,7 @@ func TestValidatorAndProvidersSlash(t *testing.T) { require.True(t, diff.IsZero()) // sanity check: unbond some of provider2's funds and check delegations balance - _, err = ts.TxDualstakingUnbond(delegator, providers[2], ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), consensusPowerTokens.MulRaw(5))) + _, err = ts.TxDualstakingUnbond(delegator, providers[2], sdk.NewCoin(ts.TokenDenom(), consensusPowerTokens.MulRaw(5))) require.NoError(t, err) ts.AdvanceEpoch() // apply unbond diff, _, err = ts.Keepers.Dualstaking.VerifyDelegatorBalance(ts.Ctx, delegatorAcc.Addr) @@ -378,7 +368,7 @@ func TestValidatorAndProvidersSlash(t *testing.T) { expectedValidatorTokens = expectedValidatorTokens.Sub(consensusPowerTokens.MulRaw(5)) // get the delegator's provider delegations before the slash - res, err := ts.QueryDualstakingDelegatorProviders(delegator, true) + res, err := ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) delegationsBeforeSlash := res.Delegations slices.SortFunc(delegationsBeforeSlash, func(i, j dualstakingtypes.Delegation) bool { @@ -396,13 +386,13 @@ func TestValidatorAndProvidersSlash(t *testing.T) { // both the validator and providers have a single delegation that was created by their // self delegation. Check that the new amount after slash is (1-fraction) * old_amount - res, err = ts.QueryDualstakingDelegatorProviders(valAcc.Addr.String(), true) + res, err = ts.QueryDualstakingDelegatorProviders(valAcc.Addr.String()) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, sdk.OneDec().Sub(fraction).MulInt(stake).RoundInt(), res.Delegations[0].Amount.Amount) for _, p := range providersAccs { - res, err = ts.QueryDualstakingDelegatorProviders(p.GetVaultAddr(), true) + res, err = ts.QueryDualstakingDelegatorProviders(p.GetVaultAddr()) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, sdk.OneDec().Sub(fraction).MulInt(stake).RoundInt(), res.Delegations[0].Amount.Amount) @@ -410,7 +400,7 @@ func TestValidatorAndProvidersSlash(t *testing.T) { // the total token to deduct from the delegator's provider delegations is: // total_providers_delegations * fraction = (245 * consensus_power_tokens) * fraction - res, err = ts.QueryDualstakingDelegatorProviders(delegator, true) + res, err = ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) require.Len(t, res.Delegations, 5) // 5 providers from redelegations totalDelegations := math.ZeroInt() @@ -495,7 +485,7 @@ func TestHooksRandomDelegations(t *testing.T) { delegatorAcc = prevDelegatorAcc delegator = prevDelegator } - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(int64(d)))) + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(int64(d)))) require.NoError(t, err) _, found := ts.Keepers.StakingKeeper.GetDelegation(ts.Ctx, delegatorAcc.Addr, sdk.ValAddress(validatorAcc.Addr)) @@ -533,7 +523,7 @@ func TestNotRoundedShares(t *testing.T) { require.NoError(t, err) ts.Keepers.StakingKeeper.SetDelegation(ts.Ctx, stakingtypes.NewDelegation(delegatorAcc.Addr, sdk.ValAddress(validatorAcc.Addr), shares)) - _, err = ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), delAmount)) + _, err = ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), delAmount)) require.NoError(t, err) } @@ -567,27 +557,11 @@ func TestUnbondValidatorButNotRemoveStakeEntry(t *testing.T) { require.NoError(t, err) } - providerAcct, provider := ts.GetAccount(common.PROVIDER, 0) + providerAcct, _ := ts.GetAccount(common.PROVIDER, 0) // provider completely unbond from validator, delegation is removed _, err = ts.TxUnbondValidator(*providerAcct.Vault, validator, sdk.NewInt(9999)) - require.NoError(t, err) - - // other delegator should not be able to delegate to the provider - _, err = ts.TxDualstakingRedelegate(delegatorAcc1.Addr.String(), - commontypes.EMPTY_PROVIDER, - provider, - commontypes.EMPTY_PROVIDER_CHAINID, - ts.spec.Index, - sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(9999))) require.Error(t, err) - - // checking that provider is not found - _, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) - require.False(t, found) - - _, err = ts.QueryDualstakingProviderDelegators(provider, true) - require.NoError(t, err) } // TestUndelegateProvider checks for a bug that when a provider unstakes, its delegations are not @@ -634,14 +608,12 @@ func TestUndelegateProvider(t *testing.T) { _, err = ts.TxDualstakingRedelegate(delegatorAcc1.Addr.String(), commontypes.EMPTY_PROVIDER, provider, - commontypes.EMPTY_PROVIDER_CHAINID, - ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(9999))) require.NoError(t, err) ts.AdvanceEpoch() - res2, err := ts.QueryDualstakingProviderDelegators(provider, true) + res2, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) fmt.Println("Delegation of Provider before provider is removed", res2) @@ -653,9 +625,9 @@ func TestUndelegateProvider(t *testing.T) { // delegation of the removed provider // the provider is removed but the delegation is still remained - res2, err = ts.QueryDualstakingProviderDelegators(provider, true) + res2, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) - fmt.Println("Delegation of Provider after provider is removed", res2) + require.Equal(t, int64(9999), res2.Delegations[0].Amount.Amount.Int64()) ts.AdvanceEpochUntilStale() @@ -663,30 +635,25 @@ func TestUndelegateProvider(t *testing.T) { err = ts.StakeProvider(providerAcct.GetVaultAddr(), providerAcct.Addr.String(), ts.spec, sdk.NewIntFromUint64(1000).Int64()) require.NoError(t, err) - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) + entry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) require.True(t, found) - fmt.Println("Stake entry of re-staked provider", stakeEntry.String()) + require.Equal(t, int64(9999), entry.DelegateTotal.Amount.Int64()) // delegator1 should be able to redelegate back to the empty provider _, err = ts.TxDualstakingRedelegate(delegatorAcc1.Addr.String(), provider, commontypes.EMPTY_PROVIDER, - ts.spec.Index, - commontypes.EMPTY_PROVIDER_CHAINID, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(1))) require.NoError(t, err) - stakeEntry, found = ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) + _, found = ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) require.True(t, found) - fmt.Println("Stake entry of re-staked provider after del1 9999 redelegation", stakeEntry.String()) // another one delegates to provider // delegator2 delegates 9998 to the provider _, err = ts.TxDualstakingRedelegate(delegatorAcc2.Addr.String(), commontypes.EMPTY_PROVIDER, provider, - commontypes.EMPTY_PROVIDER_CHAINID, - ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(9998))) require.NoError(t, err) @@ -696,16 +663,12 @@ func TestUndelegateProvider(t *testing.T) { _, err = ts.TxDualstakingRedelegate(delegatorAcc1.Addr.String(), provider, commontypes.EMPTY_PROVIDER, - ts.spec.Index, - commontypes.EMPTY_PROVIDER_CHAINID, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(9999))) require.Error(t, err) _, err = ts.TxDualstakingRedelegate(delegatorAcc1.Addr.String(), provider, commontypes.EMPTY_PROVIDER, - ts.spec.Index, - commontypes.EMPTY_PROVIDER_CHAINID, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(9998))) require.NoError(t, err) } diff --git a/x/dualstaking/keeper/keeper.go b/x/dualstaking/keeper/keeper.go index 4749bb3082..111b388935 100644 --- a/x/dualstaking/keeper/keeper.go +++ b/x/dualstaking/keeper/keeper.go @@ -2,16 +2,16 @@ package keeper import ( "fmt" - "strconv" + "cosmossdk.io/collections" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/libs/log" "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" - fixationtypes "github.com/lavanet/lava/v3/x/fixationstore/types" + collcompat "github.com/lavanet/lava/v3/utils/collcompat" "github.com/lavanet/lava/v3/x/dualstaking/types" ) @@ -28,8 +28,9 @@ type ( epochstorageKeeper types.EpochstorageKeeper specKeeper types.SpecKeeper - delegationFS fixationtypes.FixationStore // map proviers/chainID -> delegations - delegatorFS fixationtypes.FixationStore // map delegators -> providers + schema collections.Schema + delegations *collections.IndexedMap[collections.Pair[string, string], types.Delegation, types.DelegationIndexes] // key: [delegator, provider] + rewards collections.Map[collections.Pair[string, string], types.DelegatorReward] // key: [delegator, provider] } ) @@ -50,6 +51,8 @@ func NewKeeper( ps = ps.WithKeyTable(types.ParamKeyTable()) } + sb := collections.NewSchemaBuilder(collcompat.NewKVStoreService(storeKey)) + keeper := &Keeper{ cdc: cdc, storeKey: storeKey, @@ -61,50 +64,36 @@ func NewKeeper( accountKeeper: accountKeeper, epochstorageKeeper: epochstorageKeeper, specKeeper: specKeeper, - } - delegationFS := *fixationStoreKeeper.NewFixationStore(storeKey, types.DelegationPrefix) - delegatorFS := *fixationStoreKeeper.NewFixationStore(storeKey, types.DelegatorPrefix) + delegations: collections.NewIndexedMap(sb, types.DelegationsPrefix, "delegations", + collections.PairKeyCodec(collections.StringKey, collections.StringKey), + collcompat.ProtoValue[types.Delegation](cdc), + types.NewDelegationIndexes(sb)), - keeper.delegationFS = delegationFS - keeper.delegatorFS = delegatorFS + rewards: collections.NewMap(sb, types.RewardPrefix, "rewards", + collections.PairKeyCodec(collections.StringKey, collections.StringKey), + collcompat.ProtoValue[types.DelegatorReward](cdc)), + } + schema, err := sb.Build() + if err != nil { + panic(err) + } + keeper.schema = schema return keeper } -// ExportDelegations exports dualstaking delegations data (for genesis) -func (k Keeper) ExportDelegations(ctx sdk.Context) fixationtypes.GenesisState { - return k.delegationFS.Export(ctx) -} - -// ExportDelegators exports dualstaking delegators data (for genesis) -func (k Keeper) ExportDelegators(ctx sdk.Context) fixationtypes.GenesisState { - return k.delegatorFS.Export(ctx) -} - -// InitDelegations imports dualstaking delegations data (from genesis) -func (k Keeper) InitDelegations(ctx sdk.Context, data fixationtypes.GenesisState) { - k.delegationFS.Init(ctx, data) -} - -// InitDelegators imports dualstaking delegators data (from genesis) -func (k Keeper) InitDelegators(ctx sdk.Context, data fixationtypes.GenesisState) { - k.delegatorFS.Init(ctx, data) -} - func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } -func (k Keeper) ChangeDelegationTimestampForTesting(ctx sdk.Context, index string, block uint64, timestamp int64) error { - var d types.Delegation - entryBlock, _, _, found := k.delegationFS.FindEntryDetailed(ctx, index, block, &d) +func (k Keeper) ChangeDelegationTimestampForTesting(ctx sdk.Context, provider, delegator string, timestamp int64) error { + d, found := k.GetDelegation(ctx, provider, delegator) if !found { - return fmt.Errorf("cannot change delegation timestamp: delegation not found. index: %s, block: %s", index, strconv.FormatUint(block, 10)) + return fmt.Errorf("cannot change delegation timestamp: delegation not found. provider: %s, delegator: %s", provider, delegator) } d.Timestamp = timestamp - k.delegationFS.ModifyEntry(ctx, index, entryBlock, &d) - return nil + return k.SetDelegation(ctx, d) } func (k Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/dualstaking/keeper/migrations.go b/x/dualstaking/keeper/migrations.go index 3e8254a8d3..dcbfeb9604 100644 --- a/x/dualstaking/keeper/migrations.go +++ b/x/dualstaking/keeper/migrations.go @@ -5,9 +5,9 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" - dualstakingv4 "github.com/lavanet/lava/v3/x/dualstaking/migrations/v4" - dualstakingtypes "github.com/lavanet/lava/v3/x/dualstaking/types" - "github.com/lavanet/lava/v3/x/pairing/types" + "github.com/lavanet/lava/v3/x/dualstaking/types" + fixationtypes "github.com/lavanet/lava/v3/x/fixationstore/types" + timerstoretypes "github.com/lavanet/lava/v3/x/timerstore/types" ) type Migrator struct { @@ -18,36 +18,69 @@ func NewMigrator(keeper Keeper) Migrator { return Migrator{keeper: keeper} } -// MigrateVersion4To5 change the DelegatorReward object amount's field from sdk.Coin to sdk.Coins -func (m Migrator) MigrateVersion4To5(ctx sdk.Context) error { - delegatorRewards := m.GetAllDelegatorRewardV4(ctx) - for _, dr := range delegatorRewards { - delegatorReward := dualstakingtypes.DelegatorReward{ - Delegator: dr.Delegator, - Provider: dr.Provider, - ChainId: dr.ChainId, - Amount: sdk.NewCoins(dr.Amount), +func (m Migrator) MigrateVersion5To6(ctx sdk.Context) error { + nextEpoch := m.keeper.epochstorageKeeper.GetCurrentNextEpoch(ctx) + + // prefix for the delegations fixation store + const ( + DelegationPrefix = "delegation-fs" + DelegatorPrefix = "delegator-fs" + UnbondingPrefix = "unbonding-ts" + DelegatorRewardKeyPrefix = "DelegatorReward/value/" + ) + + // set delegations + ts := timerstoretypes.NewTimerStore(m.keeper.storeKey, m.keeper.cdc, DelegationPrefix) + delegationFS := fixationtypes.NewFixationStore(m.keeper.storeKey, m.keeper.cdc, DelegationPrefix, ts, nil) + incisec := delegationFS.GetAllEntryIndices(ctx) + for _, index := range incisec { + var oldDelegation types.Delegation + found := delegationFS.FindEntry(ctx, index, nextEpoch, &oldDelegation) + if found { + delegation, found := m.keeper.GetDelegation(ctx, oldDelegation.Provider, oldDelegation.Delegator) + if found { + delegation.Amount = delegation.Amount.Add(oldDelegation.Amount) + } else { + delegation = oldDelegation + } + m.keeper.SetDelegation(ctx, delegation) } - m.keeper.RemoveDelegatorReward(ctx, dualstakingtypes.DelegationKey(dr.Provider, dr.Delegator, dr.ChainId)) - m.keeper.SetDelegatorReward(ctx, delegatorReward) } - params := dualstakingtypes.DefaultParams() - m.keeper.SetParams(ctx, params) - return nil -} - -func (m Migrator) GetAllDelegatorRewardV4(ctx sdk.Context) (list []dualstakingv4.DelegatorRewardv4) { - store := prefix.NewStore(ctx.KVStore(m.keeper.storeKey), types.KeyPrefix(dualstakingtypes.DelegatorRewardKeyPrefix)) + // set rewards + store := prefix.NewStore(ctx.KVStore(m.keeper.storeKey), types.KeyPrefix(DelegatorRewardKeyPrefix)) iterator := sdk.KVStorePrefixIterator(store, []byte{}) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var val dualstakingv4.DelegatorRewardv4 + var val types.DelegatorReward m.keeper.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) + reward, found := m.keeper.GetDelegatorReward(ctx, val.Delegator, val.Delegator) + if found { + reward.Amount = reward.Amount.Add(val.Amount...) + } else { + reward = val + } + m.keeper.SetDelegatorReward(ctx, reward) } - return + // now delete the stores + deleteStore := func(prefixString string) { + store := prefix.NewStore(ctx.KVStore(m.keeper.storeKey), types.KeyPrefix(prefixString)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + store.Delete(iterator.Key()) + } + } + + deleteStore(DelegationPrefix) + deleteStore(DelegatorPrefix) + deleteStore(UnbondingPrefix) + deleteStore(DelegatorRewardKeyPrefix) + + return nil } diff --git a/x/dualstaking/keeper/msg_server_delegate.go b/x/dualstaking/keeper/msg_server_delegate.go index 0ce56b460a..eeeab8ab58 100644 --- a/x/dualstaking/keeper/msg_server_delegate.go +++ b/x/dualstaking/keeper/msg_server_delegate.go @@ -2,7 +2,6 @@ package keeper import ( "context" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -13,17 +12,11 @@ import ( func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - return &types.MsgDelegateResponse{}, k.Keeper.DelegateFull(ctx, msg.Creator, msg.Validator, msg.Provider, msg.ChainID, msg.Amount) + return &types.MsgDelegateResponse{}, k.Keeper.DelegateFull(ctx, msg.Creator, msg.Validator, msg.Provider, msg.Amount, false) } // DelegateFull uses staking module for to delegate with hooks -func (k Keeper) DelegateFull(ctx sdk.Context, delegator string, validator string, provider string, chainID string, amount sdk.Coin) error { - _, found := k.specKeeper.GetSpec(ctx, chainID) - if !found && chainID != commontypes.EMPTY_PROVIDER_CHAINID { - return utils.LavaFormatWarning("invalid chain ID", fmt.Errorf("chain ID not found"), - utils.LogAttr("chain_id", chainID)) - } - +func (k Keeper) DelegateFull(ctx sdk.Context, delegator string, validator string, provider string, amount sdk.Coin, stake bool) error { valAddr, valErr := sdk.ValAddressFromBech32(validator) if valErr != nil { return valErr @@ -47,9 +40,7 @@ func (k Keeper) DelegateFull(ctx sdk.Context, delegator string, validator string return err } - nextEpoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) - - delegation, found := k.GetDelegation(ctx, delegator, commontypes.EMPTY_PROVIDER, commontypes.EMPTY_PROVIDER_CHAINID, nextEpoch) + delegation, found := k.GetDelegation(ctx, commontypes.EMPTY_PROVIDER, delegator) amountBefore := sdk.ZeroInt() if found { amountBefore = delegation.Amount.Amount @@ -60,7 +51,7 @@ func (k Keeper) DelegateFull(ctx sdk.Context, delegator string, validator string return err } - delegation, _ = k.GetDelegation(ctx, delegator, commontypes.EMPTY_PROVIDER, commontypes.EMPTY_PROVIDER_CHAINID, nextEpoch) + delegation, _ = k.GetDelegation(ctx, commontypes.EMPTY_PROVIDER, delegator) amount.Amount = delegation.Amount.Amount.Sub(amountBefore) @@ -69,9 +60,8 @@ func (k Keeper) DelegateFull(ctx sdk.Context, delegator string, validator string delegator, commontypes.EMPTY_PROVIDER, provider, - commontypes.EMPTY_PROVIDER_CHAINID, - chainID, amount, + stake, ) if err == nil { @@ -79,7 +69,6 @@ func (k Keeper) DelegateFull(ctx sdk.Context, delegator string, validator string details := map[string]string{ "delegator": delegator, "provider": provider, - "chainID": chainID, "amount": amount.String(), } utils.LogLavaEvent(ctx, logger, types.DelegateEventName, details, "Delegate") diff --git a/x/dualstaking/keeper/msg_server_redelegate.go b/x/dualstaking/keeper/msg_server_redelegate.go index 4e3c112b17..2f11eaaa46 100644 --- a/x/dualstaking/keeper/msg_server_redelegate.go +++ b/x/dualstaking/keeper/msg_server_redelegate.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/utils" - commontypes "github.com/lavanet/lava/v3/utils/common/types" "github.com/lavanet/lava/v3/x/dualstaking/types" ) @@ -20,22 +19,13 @@ func (k msgServer) Redelegate(goCtx context.Context, msg *types.MsgRedelegate) ( return &types.MsgRedelegateResponse{}, err } - // allow non empty chainID calls to redelegate form empty provider - if msg.FromChainID == commontypes.EMPTY_PROVIDER_CHAINID_STAR { - msg.FromChainID = commontypes.EMPTY_PROVIDER_CHAINID - } - if msg.ToChainID == commontypes.EMPTY_PROVIDER_CHAINID_STAR { - msg.ToChainID = commontypes.EMPTY_PROVIDER_CHAINID - } - err := k.Keeper.Redelegate( ctx, msg.Creator, msg.FromProvider, msg.ToProvider, - msg.FromChainID, - msg.ToChainID, msg.Amount, + false, ) if err == nil { @@ -44,8 +34,6 @@ func (k msgServer) Redelegate(goCtx context.Context, msg *types.MsgRedelegate) ( "delegator": msg.Creator, "from_provider": msg.FromProvider, "to_provider": msg.ToProvider, - "from_chainID": msg.FromChainID, - "to_chainID": msg.ToChainID, "amount": msg.Amount.String(), } utils.LogLavaEvent(ctx, logger, types.RedelegateEventName, details, "Redelegate") diff --git a/x/dualstaking/keeper/msg_server_unbond.go b/x/dualstaking/keeper/msg_server_unbond.go index d195fbf80e..1d79bfe5b3 100644 --- a/x/dualstaking/keeper/msg_server_unbond.go +++ b/x/dualstaking/keeper/msg_server_unbond.go @@ -11,11 +11,11 @@ import ( func (k msgServer) Unbond(goCtx context.Context, msg *types.MsgUnbond) (*types.MsgUnbondResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - return &types.MsgUnbondResponse{}, k.Keeper.UnbondFull(ctx, msg.Creator, msg.Validator, msg.Provider, msg.ChainID, msg.Amount, false) + return &types.MsgUnbondResponse{}, k.Keeper.UnbondFull(ctx, msg.Creator, msg.Validator, msg.Provider, msg.Amount, false) } // UnbondFul uses staking module for to unbond with hooks -func (k Keeper) UnbondFull(ctx sdk.Context, delegator string, validator string, provider string, chainID string, amount sdk.Coin, unstake bool) error { +func (k Keeper) UnbondFull(ctx sdk.Context, delegator string, validator string, provider string, amount sdk.Coin, stake bool) error { // 1.redelegate from the provider to the empty provider // 2.calls staking module to unbond from the validator // 3.calls the hooks to than unbond from the empty provider @@ -45,9 +45,8 @@ func (k Keeper) UnbondFull(ctx sdk.Context, delegator string, validator string, delegator, provider, commontypes.EMPTY_PROVIDER, - chainID, - commontypes.EMPTY_PROVIDER_CHAINID, amount, + stake, ) if err != nil { return err @@ -61,7 +60,6 @@ func (k Keeper) UnbondFull(ctx sdk.Context, delegator string, validator string, details := map[string]string{ "delegator": delegator, "provider": provider, - "chainID": chainID, "amount": amount.String(), } utils.LogLavaEvent(ctx, logger, types.UnbondingEventName, details, "Unbond") diff --git a/x/dualstaking/module.go b/x/dualstaking/module.go index 977359096f..31f43c1546 100644 --- a/x/dualstaking/module.go +++ b/x/dualstaking/module.go @@ -118,8 +118,8 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { migrator := keeper.NewMigrator(am.keeper) - // register v4 -> v5 migration - if err := cfg.RegisterMigration(types.ModuleName, 4, migrator.MigrateVersion4To5); err != nil { + // register v5 -> v6 migration + if err := cfg.RegisterMigration(types.ModuleName, 5, migrator.MigrateVersion5To6); err != nil { // panic:ok: at start up, migration cannot proceed anyhow panic(fmt.Errorf("%s: failed to register migration to v5: %w", types.ModuleName, err)) } @@ -146,7 +146,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion is a sequence number for state-breaking change of the module. It should be incremented on each consensus-breaking change introduced by the module. To avoid wrong/empty versions, the initial version should be set to 1 -func (AppModule) ConsensusVersion() uint64 { return 5 } +func (AppModule) ConsensusVersion() uint64 { return 6 } // BeginBlock contains the logic that is automatically triggered at the beginning of each block func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/dualstaking/types/delegate.go b/x/dualstaking/types/delegate.go index 420ebc5f70..db934b9b51 100644 --- a/x/dualstaking/types/delegate.go +++ b/x/dualstaking/types/delegate.go @@ -3,16 +3,36 @@ package types import ( "time" + "cosmossdk.io/collections" + "cosmossdk.io/collections/indexes" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/utils" "github.com/lavanet/lava/v3/utils/lavaslices" ) -func NewDelegation(delegator, provider, chainID string, blockTime time.Time, tokenDenom string) Delegation { +var DelegationIndexPrefix = collections.NewPrefix(1) + +type DelegationIndexes struct { + ReverseIndex *indexes.ReversePair[string, string, Delegation] +} + +func (a DelegationIndexes) IndexesList() []collections.Index[collections.Pair[string, string], Delegation] { + return []collections.Index[collections.Pair[string, string], Delegation]{a.ReverseIndex} +} + +func NewDelegationIndexes(sb *collections.SchemaBuilder) DelegationIndexes { + return DelegationIndexes{ + ReverseIndex: indexes.NewReversePair[Delegation]( + sb, DelegationIndexPrefix, "delegation_by_provider_delegator", + collections.PairKeyCodec(collections.StringKey, collections.StringKey), + ), + } +} + +func NewDelegation(delegator, provider string, blockTime time.Time, tokenDenom string) Delegation { return Delegation{ Delegator: delegator, Provider: provider, - ChainID: chainID, Amount: sdk.NewCoin(tokenDenom, sdk.ZeroInt()), Timestamp: utils.NextMonth(blockTime).UTC().Unix(), } @@ -33,7 +53,6 @@ func (delegation *Delegation) IsZero() bool { func (delegation *Delegation) Equal(other *Delegation) bool { if delegation.Delegator != other.Delegator || delegation.Provider != other.Provider || - delegation.ChainID != other.ChainID || !delegation.Amount.IsEqual(other.Amount) { return false } diff --git a/x/dualstaking/types/delegate.pb.go b/x/dualstaking/types/delegate.pb.go index 3e04209a2b..34ec8b0c40 100644 --- a/x/dualstaking/types/delegate.pb.go +++ b/x/dualstaking/types/delegate.pb.go @@ -26,7 +26,6 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Delegation struct { Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"` - ChainID string `protobuf:"bytes,2,opt,name=chainID,proto3" json:"chainID,omitempty"` Delegator string `protobuf:"bytes,3,opt,name=delegator,proto3" json:"delegator,omitempty"` Amount types.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount"` Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` @@ -72,13 +71,6 @@ func (m *Delegation) GetProvider() string { return "" } -func (m *Delegation) GetChainID() string { - if m != nil { - return m.ChainID - } - return "" -} - func (m *Delegation) GetDelegator() string { if m != nil { return m.Delegator @@ -154,27 +146,26 @@ func init() { } var fileDescriptor_547eac7f30bf94d4 = []byte{ - // 306 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0xb1, 0x4e, 0xc3, 0x30, - 0x10, 0x86, 0x63, 0x5a, 0x0a, 0x31, 0x5b, 0xc4, 0x60, 0xaa, 0xca, 0x44, 0x5d, 0x28, 0x8b, 0xad, - 0xd2, 0x81, 0xbd, 0x74, 0x80, 0xb5, 0x23, 0x9b, 0x93, 0x5a, 0xa9, 0x45, 0xe3, 0x8b, 0x62, 0x37, - 0x82, 0xb7, 0xe0, 0x6d, 0x78, 0x85, 0x8e, 0x1d, 0x99, 0x10, 0x4a, 0x5e, 0x04, 0x39, 0x49, 0x53, - 0x3a, 0x9d, 0xef, 0xff, 0x7f, 0xf9, 0x3e, 0xdd, 0xe1, 0xbb, 0x8d, 0x28, 0x84, 0x96, 0x96, 0xbb, - 0xca, 0x57, 0x5b, 0xb1, 0x31, 0x56, 0xbc, 0x29, 0x9d, 0xf0, 0x95, 0xdc, 0xc8, 0x44, 0x58, 0xc9, - 0xb2, 0x1c, 0x2c, 0x04, 0xa4, 0x0d, 0x32, 0x57, 0xd9, 0xbf, 0xe0, 0xf0, 0x3a, 0x81, 0x04, 0xea, - 0x10, 0x77, 0xaf, 0x26, 0x3f, 0xa4, 0x31, 0x98, 0x14, 0x0c, 0x8f, 0x84, 0x91, 0xbc, 0x98, 0x46, - 0xd2, 0x8a, 0x29, 0x8f, 0x41, 0xe9, 0xc6, 0x1f, 0x7f, 0x21, 0x8c, 0x17, 0xcd, 0x08, 0x05, 0x3a, - 0x18, 0xe2, 0xcb, 0x2c, 0x87, 0x42, 0xad, 0x64, 0x4e, 0x50, 0x88, 0x26, 0xfe, 0xb2, 0xeb, 0x03, - 0x82, 0x2f, 0xe2, 0xb5, 0x50, 0xfa, 0x65, 0x41, 0xce, 0x6a, 0xeb, 0xd0, 0x06, 0x23, 0xec, 0xb7, - 0x98, 0x90, 0x93, 0x5e, 0xed, 0x1d, 0x85, 0xe0, 0x11, 0x0f, 0x44, 0x0a, 0x5b, 0x6d, 0x49, 0x3f, - 0x44, 0x93, 0xab, 0x87, 0x1b, 0xd6, 0x30, 0x31, 0xc7, 0xc4, 0x5a, 0x26, 0xf6, 0x04, 0x4a, 0xcf, - 0xfb, 0xbb, 0x9f, 0x5b, 0x6f, 0xd9, 0xc6, 0xdd, 0xb7, 0x56, 0xa5, 0xd2, 0x58, 0x91, 0x66, 0xe4, - 0x3c, 0x44, 0x93, 0xde, 0xf2, 0x28, 0x8c, 0xef, 0xb1, 0xbf, 0xe8, 0x66, 0x8c, 0xb0, 0x7f, 0xe0, - 0x34, 0x04, 0x85, 0x3d, 0x47, 0xd0, 0x09, 0xf3, 0xe7, 0x5d, 0x49, 0xd1, 0xbe, 0xa4, 0xe8, 0xb7, - 0xa4, 0xe8, 0xb3, 0xa2, 0xde, 0xbe, 0xa2, 0xde, 0x77, 0x45, 0xbd, 0x57, 0x96, 0x28, 0xbb, 0xde, - 0x46, 0x2c, 0x86, 0x94, 0x9f, 0x9c, 0xa0, 0x98, 0xf1, 0xf7, 0x93, 0x3b, 0xd8, 0x8f, 0x4c, 0x9a, - 0x68, 0x50, 0x6f, 0x6d, 0xf6, 0x17, 0x00, 0x00, 0xff, 0xff, 0x90, 0xb7, 0x12, 0x3c, 0xb0, 0x01, - 0x00, 0x00, + // 300 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0xb1, 0x4e, 0xf3, 0x30, + 0x14, 0x85, 0xe3, 0x3f, 0xfd, 0xab, 0xc6, 0x2c, 0x28, 0x62, 0x30, 0x55, 0x65, 0xa2, 0x2e, 0x94, + 0xc5, 0x56, 0xe9, 0xc0, 0x5e, 0x3a, 0x20, 0xc6, 0x8e, 0x6c, 0x4e, 0x6b, 0x05, 0x8b, 0xc6, 0x37, + 0x8a, 0x9d, 0x08, 0xde, 0x82, 0x77, 0xe0, 0x65, 0x3a, 0x76, 0x64, 0x42, 0x28, 0x79, 0x11, 0xe4, + 0x24, 0xa4, 0x74, 0xba, 0xf6, 0xb9, 0x47, 0xf7, 0x3b, 0x3a, 0xf8, 0x7a, 0x27, 0x4a, 0xa1, 0xa5, + 0xe5, 0x6e, 0xf2, 0x6d, 0x21, 0x76, 0xc6, 0x8a, 0x17, 0xa5, 0x13, 0xbe, 0x95, 0x3b, 0x99, 0x08, + 0x2b, 0x59, 0x96, 0x83, 0x85, 0x90, 0x74, 0x46, 0xe6, 0x26, 0xfb, 0x63, 0x1c, 0x5f, 0x24, 0x90, + 0x40, 0x63, 0xe2, 0xee, 0xd5, 0xfa, 0xc7, 0x74, 0x03, 0x26, 0x05, 0xc3, 0x63, 0x61, 0x24, 0x2f, + 0xe7, 0xb1, 0xb4, 0x62, 0xce, 0x37, 0xa0, 0x74, 0xbb, 0x9f, 0x7e, 0x20, 0x8c, 0x57, 0x2d, 0x42, + 0x81, 0x0e, 0xc7, 0x78, 0x94, 0xe5, 0x50, 0xaa, 0xad, 0xcc, 0x09, 0x8a, 0xd0, 0x2c, 0x58, 0xf7, + 0xff, 0x70, 0x82, 0x83, 0x2e, 0x0c, 0xe4, 0xc4, 0x6f, 0x96, 0x47, 0x21, 0xbc, 0xc3, 0x43, 0x91, + 0x42, 0xa1, 0x2d, 0x19, 0x44, 0x68, 0x76, 0x76, 0x7b, 0xc9, 0x5a, 0x32, 0x73, 0x64, 0xd6, 0x91, + 0xd9, 0x3d, 0x28, 0xbd, 0x1c, 0xec, 0xbf, 0xae, 0xbc, 0x75, 0x67, 0x77, 0x67, 0xad, 0x4a, 0xa5, + 0xb1, 0x22, 0xcd, 0xc8, 0xff, 0x08, 0xcd, 0xfc, 0xf5, 0x51, 0x78, 0x1c, 0x8c, 0xfe, 0x9d, 0xfb, + 0xd3, 0x1b, 0x1c, 0xac, 0x7a, 0xd2, 0x04, 0x07, 0xbf, 0x99, 0x0c, 0x41, 0x91, 0xef, 0x72, 0xf4, + 0xc2, 0xf2, 0x61, 0x5f, 0x51, 0x74, 0xa8, 0x28, 0xfa, 0xae, 0x28, 0x7a, 0xaf, 0xa9, 0x77, 0xa8, + 0xa9, 0xf7, 0x59, 0x53, 0xef, 0x89, 0x25, 0xca, 0x3e, 0x17, 0x31, 0xdb, 0x40, 0xca, 0x4f, 0xea, + 0x2e, 0x17, 0xfc, 0xf5, 0xa4, 0x73, 0xfb, 0x96, 0x49, 0x13, 0x0f, 0x9b, 0x86, 0x16, 0x3f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x2a, 0xdf, 0x39, 0x25, 0x9c, 0x01, 0x00, 0x00, } func (m *Delegation) Marshal() (dAtA []byte, err error) { @@ -219,13 +210,6 @@ func (m *Delegation) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x1a } - if len(m.ChainID) > 0 { - i -= len(m.ChainID) - copy(dAtA[i:], m.ChainID) - i = encodeVarintDelegate(dAtA, i, uint64(len(m.ChainID))) - i-- - dAtA[i] = 0x12 - } if len(m.Provider) > 0 { i -= len(m.Provider) copy(dAtA[i:], m.Provider) @@ -289,10 +273,6 @@ func (m *Delegation) Size() (n int) { if l > 0 { n += 1 + l + sovDelegate(uint64(l)) } - l = len(m.ChainID) - if l > 0 { - n += 1 + l + sovDelegate(uint64(l)) - } l = len(m.Delegator) if l > 0 { n += 1 + l + sovDelegate(uint64(l)) @@ -387,38 +367,6 @@ func (m *Delegation) Unmarshal(dAtA []byte) error { } m.Provider = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDelegate - } - 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 ErrInvalidLengthDelegate - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthDelegate - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainID = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Delegator", wireType) diff --git a/x/dualstaking/types/delegator_reward.pb.go b/x/dualstaking/types/delegator_reward.pb.go index 3f6469da51..d7e4c02c44 100644 --- a/x/dualstaking/types/delegator_reward.pb.go +++ b/x/dualstaking/types/delegator_reward.pb.go @@ -28,7 +28,6 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type DelegatorReward struct { Delegator string `protobuf:"bytes,1,opt,name=delegator,proto3" json:"delegator,omitempty"` Provider string `protobuf:"bytes,2,opt,name=provider,proto3" json:"provider,omitempty"` - ChainId string `protobuf:"bytes,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` } @@ -79,13 +78,6 @@ func (m *DelegatorReward) GetProvider() string { return "" } -func (m *DelegatorReward) GetChainId() string { - if m != nil { - return m.ChainId - } - return "" -} - func (m *DelegatorReward) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { if m != nil { return m.Amount @@ -102,26 +94,26 @@ func init() { } var fileDescriptor_c8b6da054bf40d1f = []byte{ - // 301 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x50, 0xbd, 0x4e, 0xf3, 0x30, - 0x14, 0x8d, 0xbf, 0x7e, 0x2a, 0xad, 0x19, 0x90, 0x22, 0x86, 0xb4, 0x42, 0x6e, 0xc5, 0xd4, 0x05, - 0x9b, 0xd2, 0x37, 0x28, 0x0c, 0xb0, 0x76, 0x64, 0xa9, 0x9c, 0xd8, 0x4a, 0xad, 0xb6, 0xbe, 0x95, - 0xed, 0x04, 0x78, 0x0b, 0x9e, 0x83, 0x27, 0xa9, 0xc4, 0xd2, 0x91, 0x09, 0x50, 0xf2, 0x22, 0x28, - 0x4e, 0x28, 0xed, 0x74, 0x73, 0x73, 0xee, 0xf9, 0xf1, 0xc1, 0x6c, 0xc5, 0x73, 0xae, 0xa5, 0xf3, - 0x93, 0x89, 0x8c, 0xaf, 0xac, 0xe3, 0x4b, 0xa5, 0x53, 0x26, 0xe4, 0x4a, 0xa6, 0xdc, 0x81, 0x99, - 0x1b, 0xf9, 0xc4, 0x8d, 0xa0, 0x1b, 0x03, 0x0e, 0xc2, 0xa8, 0x21, 0xd0, 0x6a, 0xd2, 0x03, 0x42, - 0xff, 0x3c, 0x85, 0x14, 0xfc, 0x11, 0xab, 0xbe, 0xea, 0xfb, 0x3e, 0x49, 0xc0, 0xae, 0xc1, 0xb2, - 0x98, 0x5b, 0xc9, 0xf2, 0x71, 0x2c, 0x1d, 0x1f, 0xb3, 0x04, 0x94, 0xae, 0xf1, 0xcb, 0x77, 0x84, - 0xcf, 0xee, 0x7e, 0xad, 0x66, 0xde, 0x29, 0xbc, 0xc0, 0xdd, 0xbd, 0x7b, 0x84, 0x86, 0x68, 0xd4, - 0x9d, 0xfd, 0xfd, 0x08, 0xfb, 0xb8, 0xb3, 0x31, 0x90, 0x2b, 0x21, 0x4d, 0xf4, 0xcf, 0x83, 0xfb, - 0x3d, 0xec, 0xe1, 0x4e, 0xb2, 0xe0, 0x4a, 0xcf, 0x95, 0x88, 0x5a, 0x1e, 0x3b, 0xf1, 0xfb, 0x83, - 0x08, 0x13, 0xdc, 0xe6, 0x6b, 0xc8, 0xb4, 0x8b, 0xfe, 0x0f, 0x5b, 0xa3, 0xd3, 0x9b, 0x1e, 0xad, - 0x93, 0xd1, 0x2a, 0x19, 0x6d, 0x92, 0xd1, 0x5b, 0x50, 0x7a, 0x7a, 0xbd, 0xfd, 0x1c, 0x04, 0x6f, - 0x5f, 0x83, 0x51, 0xaa, 0xdc, 0x22, 0x8b, 0x69, 0x02, 0x6b, 0xd6, 0x3c, 0xa3, 0x1e, 0x57, 0x56, - 0x2c, 0x99, 0x7b, 0xd9, 0x48, 0xeb, 0x09, 0x76, 0xd6, 0x48, 0x4f, 0xef, 0xb7, 0x05, 0x41, 0xbb, - 0x82, 0xa0, 0xef, 0x82, 0xa0, 0xd7, 0x92, 0x04, 0xbb, 0x92, 0x04, 0x1f, 0x25, 0x09, 0x1e, 0xe9, - 0x81, 0xd6, 0x51, 0xe7, 0xf9, 0x84, 0x3d, 0x1f, 0x15, 0xef, 0x75, 0xe3, 0xb6, 0xaf, 0x67, 0xf2, - 0x13, 0x00, 0x00, 0xff, 0xff, 0x46, 0xff, 0xf5, 0xaa, 0xa1, 0x01, 0x00, 0x00, + // 291 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0x31, 0x4e, 0xfb, 0x30, + 0x18, 0xc5, 0xe3, 0x7f, 0xa3, 0xaa, 0xcd, 0x7f, 0x00, 0x45, 0x0c, 0x21, 0x42, 0x6e, 0xc5, 0x94, + 0x05, 0x9b, 0xd2, 0x1b, 0x14, 0x06, 0xc4, 0x98, 0x91, 0x05, 0x39, 0x89, 0x15, 0xa2, 0x26, 0xfe, + 0x22, 0xdb, 0x09, 0x70, 0x0b, 0xce, 0xc1, 0x01, 0x38, 0x43, 0xc7, 0x8e, 0x4c, 0x80, 0x92, 0x8b, + 0xa0, 0x38, 0xa1, 0xb4, 0xd3, 0xb3, 0xfd, 0x7d, 0xef, 0xfd, 0xac, 0xe7, 0xd0, 0x9c, 0xd5, 0x4c, + 0x70, 0x6d, 0x94, 0x26, 0x15, 0xcb, 0x95, 0x66, 0xeb, 0x4c, 0xa4, 0x34, 0xe1, 0x39, 0x4f, 0x99, + 0x06, 0xf9, 0x20, 0xf9, 0x13, 0x93, 0x09, 0x29, 0x25, 0x68, 0x70, 0xbd, 0xc1, 0x40, 0x3a, 0x25, + 0x7b, 0x06, 0xff, 0x24, 0x85, 0x14, 0xcc, 0x12, 0xed, 0x4e, 0xfd, 0xbe, 0x8f, 0x63, 0x50, 0x05, + 0x28, 0x1a, 0x31, 0xc5, 0x69, 0xbd, 0x88, 0xb8, 0x66, 0x0b, 0x1a, 0x43, 0x26, 0xfa, 0xf9, 0xf9, + 0x3b, 0x72, 0x8e, 0x6e, 0x7e, 0x51, 0xa1, 0x21, 0xb9, 0x67, 0xce, 0x74, 0x47, 0xf7, 0xd0, 0x1c, + 0x05, 0xd3, 0xf0, 0xef, 0xc1, 0xf5, 0x9d, 0x49, 0x29, 0xa1, 0xce, 0x12, 0x2e, 0xbd, 0x7f, 0x66, + 0xb8, 0xbb, 0xbb, 0xb1, 0x33, 0x66, 0x05, 0x54, 0x42, 0x7b, 0xf6, 0x7c, 0x14, 0xfc, 0xbf, 0x3a, + 0x25, 0x3d, 0x9e, 0x74, 0x78, 0x32, 0xe0, 0xc9, 0x35, 0x64, 0x62, 0x75, 0xb9, 0xf9, 0x9c, 0x59, + 0x6f, 0x5f, 0xb3, 0x20, 0xcd, 0xf4, 0x63, 0x15, 0x91, 0x18, 0x0a, 0x3a, 0xfc, 0xb5, 0x97, 0x0b, + 0x95, 0xac, 0xa9, 0x7e, 0x29, 0xb9, 0x32, 0x06, 0x15, 0x0e, 0xd1, 0x77, 0xf6, 0x64, 0x74, 0x6c, + 0xaf, 0x6e, 0x37, 0x0d, 0x46, 0xdb, 0x06, 0xa3, 0xef, 0x06, 0xa3, 0xd7, 0x16, 0x5b, 0xdb, 0x16, + 0x5b, 0x1f, 0x2d, 0xb6, 0xee, 0xc9, 0x5e, 0xe2, 0x41, 0xbd, 0xf5, 0x92, 0x3e, 0x1f, 0x74, 0x6c, + 0xd2, 0xa3, 0xb1, 0x69, 0x62, 0xf9, 0x13, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x84, 0xf0, 0x2c, 0x8c, + 0x01, 0x00, 0x00, } func (m *DelegatorReward) Marshal() (dAtA []byte, err error) { @@ -158,13 +150,6 @@ func (m *DelegatorReward) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x22 } } - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintDelegatorReward(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0x1a - } if len(m.Provider) > 0 { i -= len(m.Provider) copy(dAtA[i:], m.Provider) @@ -207,10 +192,6 @@ func (m *DelegatorReward) Size() (n int) { if l > 0 { n += 1 + l + sovDelegatorReward(uint64(l)) } - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovDelegatorReward(uint64(l)) - } if len(m.Amount) > 0 { for _, e := range m.Amount { l = e.Size() @@ -319,38 +300,6 @@ func (m *DelegatorReward) Unmarshal(dAtA []byte) error { } m.Provider = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDelegatorReward - } - 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 ErrInvalidLengthDelegatorReward - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthDelegatorReward - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) diff --git a/x/dualstaking/types/expected_keepers.go b/x/dualstaking/types/expected_keepers.go index cd454a6c2f..e6e3851470 100644 --- a/x/dualstaking/types/expected_keepers.go +++ b/x/dualstaking/types/expected_keepers.go @@ -38,6 +38,8 @@ type EpochstorageKeeper interface { GetCurrentNextEpoch(ctx sdk.Context) (nextEpoch uint64) RemoveStakeEntryCurrent(ctx sdk.Context, chainID string, address string) GetStakeEntry(ctx sdk.Context, epoch uint64, chainID string, provider string) (val epochstoragetypes.StakeEntry, found bool) + GetMetadata(ctx sdk.Context, provider string) (epochstoragetypes.ProviderMetadata, error) + SetMetadata(ctx sdk.Context, metadata epochstoragetypes.ProviderMetadata) // Methods imported from epochstorage should be defined here } diff --git a/x/dualstaking/types/genesis.go b/x/dualstaking/types/genesis.go index aefa38b541..1dc916c630 100644 --- a/x/dualstaking/types/genesis.go +++ b/x/dualstaking/types/genesis.go @@ -2,8 +2,6 @@ package types import ( fmt "fmt" - - fixationstoretypes "github.com/lavanet/lava/v3/x/fixationstore/types" ) // DefaultIndex is the default global index @@ -15,8 +13,7 @@ func DefaultGenesis() *GenesisState { // this line is used by starport scaffolding # genesis/types/default Params: DefaultParams(), DelegatorRewardList: []DelegatorReward{}, - DelegationsFS: *fixationstoretypes.DefaultGenesis(), - DelegatorsFS: *fixationstoretypes.DefaultGenesis(), + Delegations: []Delegation{}, } } @@ -27,12 +24,23 @@ func (gs GenesisState) Validate() error { delegatorRewardIndexMap := make(map[string]struct{}) for _, elem := range gs.DelegatorRewardList { - index := DelegationKey(elem.Provider, elem.Delegator, elem.ChainId) + key := DelegationKey(elem.Provider, elem.Delegator) + index := key.K1() + key.K2() if _, ok := delegatorRewardIndexMap[index]; ok { return fmt.Errorf("duplicated index for delegatorReward") } delegatorRewardIndexMap[index] = struct{}{} } + + delegationIndexMap := make(map[string]struct{}) + for _, elem := range gs.Delegations { + key := DelegationKey(elem.Provider, elem.Delegator) + index := key.K1() + key.K2() + if _, ok := delegationIndexMap[index]; ok { + return fmt.Errorf("duplicated index for delegations") + } + delegationIndexMap[index] = struct{}{} + } // this line is used by starport scaffolding # genesis/types/validate return gs.Params.Validate() diff --git a/x/dualstaking/types/genesis.pb.go b/x/dualstaking/types/genesis.pb.go index 1c48861d97..672d9c0e41 100644 --- a/x/dualstaking/types/genesis.pb.go +++ b/x/dualstaking/types/genesis.pb.go @@ -7,8 +7,6 @@ import ( fmt "fmt" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" - types "github.com/lavanet/lava/v3/x/fixationstore/types" - _ "github.com/lavanet/lava/v3/x/timerstore/types" io "io" math "math" math_bits "math/bits" @@ -27,10 +25,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the dualstaking module's genesis state. type GenesisState struct { - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - DelegationsFS types.GenesisState `protobuf:"bytes,2,opt,name=delegationsFS,proto3" json:"delegationsFS"` - DelegatorsFS types.GenesisState `protobuf:"bytes,3,opt,name=delegatorsFS,proto3" json:"delegatorsFS"` - DelegatorRewardList []DelegatorReward `protobuf:"bytes,5,rep,name=delegator_reward_list,json=delegatorRewardList,proto3" json:"delegator_reward_list"` + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + DelegatorRewardList []DelegatorReward `protobuf:"bytes,5,rep,name=delegator_reward_list,json=delegatorRewardList,proto3" json:"delegator_reward_list"` + Delegations []Delegation `protobuf:"bytes,6,rep,name=Delegations,proto3" json:"Delegations"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -73,23 +70,16 @@ func (m *GenesisState) GetParams() Params { return Params{} } -func (m *GenesisState) GetDelegationsFS() types.GenesisState { - if m != nil { - return m.DelegationsFS - } - return types.GenesisState{} -} - -func (m *GenesisState) GetDelegatorsFS() types.GenesisState { +func (m *GenesisState) GetDelegatorRewardList() []DelegatorReward { if m != nil { - return m.DelegatorsFS + return m.DelegatorRewardList } - return types.GenesisState{} + return nil } -func (m *GenesisState) GetDelegatorRewardList() []DelegatorReward { +func (m *GenesisState) GetDelegations() []Delegation { if m != nil { - return m.DelegatorRewardList + return m.Delegations } return nil } @@ -103,28 +93,27 @@ func init() { } var fileDescriptor_d5bca863c53f218f = []byte{ - // 336 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0x4f, 0x4b, 0xc3, 0x30, - 0x18, 0xc6, 0xdb, 0xfd, 0x43, 0xba, 0x09, 0x52, 0x15, 0xca, 0x0e, 0x75, 0x28, 0xca, 0x76, 0x49, - 0x60, 0xbb, 0x7b, 0x18, 0xa2, 0x22, 0x1e, 0x64, 0xf3, 0xe4, 0x65, 0x64, 0x6b, 0x8c, 0xc1, 0xae, - 0x19, 0xc9, 0xbb, 0x39, 0xbf, 0x85, 0x1f, 0x6b, 0xc7, 0x1d, 0x3d, 0x89, 0xac, 0x5f, 0x44, 0x9a, - 0xc6, 0xb1, 0x08, 0xbd, 0x78, 0x4a, 0x5a, 0x7e, 0xcf, 0x2f, 0x79, 0xf2, 0x7a, 0x17, 0x31, 0x59, - 0x90, 0x84, 0x02, 0xce, 0x56, 0x1c, 0xcd, 0x49, 0xac, 0x80, 0xbc, 0xf2, 0x84, 0x61, 0x46, 0x13, - 0xaa, 0xb8, 0x42, 0x33, 0x29, 0x40, 0xf8, 0x81, 0xe1, 0x50, 0xb6, 0xa2, 0x1d, 0xae, 0x79, 0xc4, - 0x04, 0x13, 0x1a, 0xc2, 0xd9, 0x2e, 0xe7, 0x9b, 0xe7, 0x85, 0xde, 0x19, 0x91, 0x64, 0x6a, 0xb4, - 0xcd, 0x8e, 0x85, 0x3d, 0xf3, 0x25, 0x01, 0x2e, 0x12, 0x05, 0x42, 0xd2, 0xed, 0x97, 0x41, 0xcf, - 0x2c, 0x14, 0xf8, 0x94, 0xca, 0x9c, 0xd3, 0x5b, 0x03, 0xe1, 0xc2, 0x63, 0x23, 0x1a, 0x53, 0x46, - 0x40, 0xc8, 0x91, 0xa4, 0x6f, 0x44, 0x46, 0x79, 0xe0, 0x34, 0x2d, 0x79, 0x8d, 0x9b, 0xbc, 0xe9, - 0x10, 0x08, 0x50, 0xff, 0xd2, 0xab, 0xe5, 0x37, 0x0c, 0xdc, 0x96, 0xdb, 0xae, 0x77, 0x5b, 0xa8, - 0xa8, 0x39, 0x7a, 0xd0, 0x5c, 0xbf, 0xb2, 0xfa, 0x3a, 0x71, 0x06, 0x26, 0xe5, 0x3f, 0x7a, 0xfb, - 0xe6, 0xa8, 0xac, 0xc8, 0xf5, 0x30, 0x28, 0x69, 0x4d, 0xdb, 0xd6, 0x58, 0x4d, 0xd1, 0xee, 0x05, - 0x8c, 0xce, 0x96, 0xf8, 0x03, 0xaf, 0xb1, 0x2d, 0x90, 0x49, 0xcb, 0xff, 0x92, 0x5a, 0x0e, 0x7f, - 0xe2, 0x1d, 0xff, 0x7d, 0x94, 0x51, 0xcc, 0x15, 0x04, 0xd5, 0x56, 0xb9, 0x5d, 0xef, 0x76, 0x8a, - 0x8b, 0x5f, 0xfd, 0xc6, 0x06, 0x3a, 0x65, 0xec, 0x87, 0x91, 0xfd, 0xfb, 0x9e, 0x2b, 0xb8, 0xab, - 0xec, 0x55, 0x0e, 0xaa, 0xfd, 0xdb, 0xd5, 0x26, 0x74, 0xd7, 0x9b, 0xd0, 0xfd, 0xde, 0x84, 0xee, - 0x47, 0x1a, 0x3a, 0xeb, 0x34, 0x74, 0x3e, 0xd3, 0xd0, 0x79, 0x42, 0x8c, 0xc3, 0xcb, 0x7c, 0x8c, - 0x26, 0x62, 0x6a, 0xcf, 0x6e, 0xd1, 0xc3, 0x4b, 0x6b, 0x80, 0xf0, 0x3e, 0xa3, 0x6a, 0x5c, 0xd3, - 0x63, 0xeb, 0xfd, 0x04, 0x00, 0x00, 0xff, 0xff, 0x08, 0x1d, 0xa0, 0x30, 0xb8, 0x02, 0x00, 0x00, + // 308 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcb, 0x49, 0x2c, 0x4b, + 0xcc, 0x4b, 0x2d, 0xd1, 0x07, 0xd1, 0xfa, 0x29, 0xa5, 0x89, 0x39, 0xc5, 0x25, 0x89, 0xd9, 0x99, + 0x79, 0xe9, 0xfa, 0xe9, 0xa9, 0x79, 0xa9, 0xc5, 0x99, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, + 0x42, 0x12, 0x50, 0x75, 0x7a, 0x20, 0x5a, 0x0f, 0x49, 0x9d, 0x94, 0x48, 0x7a, 0x7e, 0x7a, 0x3e, + 0x58, 0x91, 0x3e, 0x88, 0x05, 0x51, 0x2f, 0xa5, 0x8a, 0xd3, 0xdc, 0x82, 0xc4, 0xa2, 0xc4, 0x5c, + 0xa8, 0xb1, 0x52, 0xfa, 0x38, 0x95, 0xa5, 0xa4, 0xe6, 0xa4, 0xa6, 0x27, 0x96, 0xe4, 0x17, 0xc5, + 0x17, 0xa5, 0x96, 0x27, 0x16, 0xa5, 0x40, 0x35, 0xa8, 0x13, 0xd2, 0x90, 0x0a, 0x51, 0xa8, 0x34, + 0x99, 0x89, 0x8b, 0xc7, 0x1d, 0xe2, 0x85, 0xe0, 0x92, 0xc4, 0x92, 0x54, 0x21, 0x3b, 0x2e, 0x36, + 0x88, 0xd5, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x0a, 0x7a, 0xb8, 0xbc, 0xa4, 0x17, 0x00, + 0x56, 0xe7, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x54, 0x97, 0x50, 0x32, 0x97, 0x28, 0xba, + 0x9b, 0xe2, 0x73, 0x32, 0x8b, 0x4b, 0x24, 0x58, 0x15, 0x98, 0x35, 0xb8, 0x8d, 0x34, 0x71, 0x1b, + 0xe7, 0x02, 0xd3, 0x16, 0x04, 0xd6, 0x05, 0x35, 0x57, 0x38, 0x05, 0x55, 0xd8, 0x27, 0xb3, 0xb8, + 0x44, 0xc8, 0x87, 0x8b, 0x1b, 0xaa, 0x3a, 0x33, 0x3f, 0xaf, 0x58, 0x82, 0x0d, 0x6c, 0xb4, 0x0a, + 0x41, 0xa3, 0x33, 0xf3, 0xf3, 0xa0, 0xa6, 0x22, 0x6b, 0xf7, 0x62, 0xe1, 0x60, 0x12, 0x60, 0xf6, + 0x62, 0xe1, 0x60, 0x16, 0x60, 0xf1, 0x62, 0xe1, 0x60, 0x11, 0x60, 0x75, 0xf2, 0x38, 0xf1, 0x48, + 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, + 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xbd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, + 0xe4, 0xfc, 0x5c, 0xd4, 0x48, 0x29, 0x33, 0xd6, 0xaf, 0x40, 0x09, 0xe8, 0x92, 0xca, 0x82, 0xd4, + 0xe2, 0x24, 0x36, 0x70, 0x30, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x19, 0x97, 0xa1, 0xc1, + 0x41, 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -147,6 +136,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Delegations) > 0 { + for iNdEx := len(m.Delegations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Delegations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } if len(m.DelegatorRewardList) > 0 { for iNdEx := len(m.DelegatorRewardList) - 1; iNdEx >= 0; iNdEx-- { { @@ -161,26 +164,6 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x2a } } - { - size, err := m.DelegatorsFS.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - { - size, err := m.DelegationsFS.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 { size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -213,16 +196,18 @@ func (m *GenesisState) Size() (n int) { _ = l l = m.Params.Size() n += 1 + l + sovGenesis(uint64(l)) - l = m.DelegationsFS.Size() - n += 1 + l + sovGenesis(uint64(l)) - l = m.DelegatorsFS.Size() - n += 1 + l + sovGenesis(uint64(l)) if len(m.DelegatorRewardList) > 0 { for _, e := range m.DelegatorRewardList { l = e.Size() n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.Delegations) > 0 { + for _, e := range m.Delegations { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -294,42 +279,9 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegationsFS", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.DelegationsFS.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatorsFS", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DelegatorRewardList", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -356,13 +308,14 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.DelegatorsFS.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.DelegatorRewardList = append(m.DelegatorRewardList, DelegatorReward{}) + if err := m.DelegatorRewardList[len(m.DelegatorRewardList)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 5: + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatorRewardList", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Delegations", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -389,8 +342,8 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.DelegatorRewardList = append(m.DelegatorRewardList, DelegatorReward{}) - if err := m.DelegatorRewardList[len(m.DelegatorRewardList)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Delegations = append(m.Delegations, Delegation{}) + if err := m.Delegations[len(m.Delegations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/dualstaking/types/genesis_test.go b/x/dualstaking/types/genesis_test.go index 48751c24af..aaa1b556a9 100644 --- a/x/dualstaking/types/genesis_test.go +++ b/x/dualstaking/types/genesis_test.go @@ -25,12 +25,10 @@ func TestGenesisState_Validate(t *testing.T) { { Provider: "p0", Delegator: "d0", - ChainId: "c0", }, { Provider: "p1", Delegator: "d1", - ChainId: "c1", }, }, // this line is used by starport scaffolding # types/genesis/validField @@ -44,12 +42,10 @@ func TestGenesisState_Validate(t *testing.T) { { Provider: "p0", Delegator: "d0", - ChainId: "c0", }, { Provider: "p0", Delegator: "d0", - ChainId: "c0", }, }, }, diff --git a/x/dualstaking/types/key_delegator_reward.go b/x/dualstaking/types/key_delegator_reward.go deleted file mode 100644 index 7bf7db8cb7..0000000000 --- a/x/dualstaking/types/key_delegator_reward.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -import "encoding/binary" - -var _ binary.ByteOrder - -const ( - // DelegatorRewardKeyPrefix is the prefix to retrieve all DelegatorReward - DelegatorRewardKeyPrefix = "DelegatorReward/value/" -) - -// DelegatorRewardKey returns the store key to retrieve a DelegatorReward from the index fields -func DelegatorRewardKey( - index string, -) []byte { - var key []byte - - indexBytes := []byte(index) - key = append(key, indexBytes...) - key = append(key, []byte("/")...) - - return key -} diff --git a/x/dualstaking/types/keys.go b/x/dualstaking/types/keys.go index b8aaa80a3e..73c73a8849 100644 --- a/x/dualstaking/types/keys.go +++ b/x/dualstaking/types/keys.go @@ -1,7 +1,7 @@ package types import ( - "strings" + "cosmossdk.io/collections" ) const ( @@ -17,15 +17,6 @@ const ( // MemStoreKey defines the in-memory store key MemStoreKey = "mem_dualstaking" - // prefix for the delegations fixation store - DelegationPrefix = "delegation-fs" - - // prefix for the delegators fixation store - DelegatorPrefix = "delegator-fs" - - // prefix for the unbonding timer store - UnbondingPrefix = "unbonding-ts" - // DisableDualstakingHooks prefix DisableDualstakingHookPrefix = "disable-dualstaking-hooks" @@ -37,24 +28,11 @@ func KeyPrefix(p string) []byte { return []byte(p) } -// DelegationKey returns the key/prefix for the Delegation entry in fixation store. -// Using " " (space) as spearator is safe because Bech32 forbids its use as part of -// the address (and is the only visible character that can be safely used). -// (reference https://en.bitcoin.it/wiki/BIP_0173#Specification) -func DelegationKey(provider, delegator, chainID string) string { - return provider + " " + delegator + " " + chainID -} - -func DelegationKeyDecode(prefix string) (provider, delegator, chainID string) { - split := strings.Split(prefix, " ") - return split[0], split[1], split[2] +func DelegationKey(provider, delegator string) collections.Pair[string, string] { + return collections.Join(provider, delegator) } -// DelegatorKey returns the key/prefix for the Delegator entry in fixation store. -func DelegatorKey(delegator string) string { - return delegator -} - -func DelegatorKeyDecode(prefix string) (delegator string) { - return prefix -} +var ( + DelegationsPrefix = collections.NewPrefix([]byte("Delegations/")) + RewardPrefix = collections.NewPrefix([]byte("Rewards/")) +) diff --git a/x/dualstaking/types/message_delegate_test.go b/x/dualstaking/types/message_delegate_test.go index c58d392d9d..5b8916fcc1 100644 --- a/x/dualstaking/types/message_delegate_test.go +++ b/x/dualstaking/types/message_delegate_test.go @@ -6,7 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/v3/testutil/sample" - commontypes "github.com/lavanet/lava/v3/utils/common/types" "github.com/stretchr/testify/require" ) @@ -26,7 +25,7 @@ func TestMsgDelegate_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: oneCoin, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, @@ -37,7 +36,7 @@ func TestMsgDelegate_ValidateBasic(t *testing.T) { Provider: "invalid_address", Amount: oneCoin, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, @@ -48,7 +47,7 @@ func TestMsgDelegate_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: oneCoin, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, }, { @@ -58,7 +57,7 @@ func TestMsgDelegate_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: sdk.Coin{Denom: "utest", Amount: sdk.NewInt(-1)}, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidCoins, }, @@ -69,7 +68,7 @@ func TestMsgDelegate_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: oneCoin, Validator: "invalid_validator", - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, diff --git a/x/dualstaking/types/message_redelegate_test.go b/x/dualstaking/types/message_redelegate_test.go index 164f97457d..d3c2e3e79f 100644 --- a/x/dualstaking/types/message_redelegate_test.go +++ b/x/dualstaking/types/message_redelegate_test.go @@ -6,7 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/v3/testutil/sample" - commontypes "github.com/lavanet/lava/v3/utils/common/types" "github.com/stretchr/testify/require" ) @@ -25,8 +24,8 @@ func TestMsgRedelegate_ValidateBasic(t *testing.T) { FromProvider: sample.AccAddress(), ToProvider: sample.AccAddress(), Amount: oneCoin, - FromChainID: commontypes.EMPTY_PROVIDER_CHAINID, - ToChainID: commontypes.EMPTY_PROVIDER_CHAINID, + FromChainID: "", + ToChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, { @@ -36,8 +35,8 @@ func TestMsgRedelegate_ValidateBasic(t *testing.T) { FromProvider: "invalid_address", ToProvider: sample.AccAddress(), Amount: oneCoin, - FromChainID: commontypes.EMPTY_PROVIDER_CHAINID, - ToChainID: commontypes.EMPTY_PROVIDER_CHAINID, + FromChainID: "", + ToChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, { @@ -47,8 +46,8 @@ func TestMsgRedelegate_ValidateBasic(t *testing.T) { FromProvider: sample.AccAddress(), ToProvider: sample.AccAddress(), Amount: oneCoin, - FromChainID: commontypes.EMPTY_PROVIDER_CHAINID, - ToChainID: commontypes.EMPTY_PROVIDER_CHAINID, + FromChainID: "", + ToChainID: "", }, }, { name: "invalid amount", @@ -57,8 +56,8 @@ func TestMsgRedelegate_ValidateBasic(t *testing.T) { FromProvider: sample.AccAddress(), ToProvider: sample.AccAddress(), Amount: sdk.Coin{Denom: "utest", Amount: sdk.NewInt(-1)}, - FromChainID: commontypes.EMPTY_PROVIDER_CHAINID, - ToChainID: commontypes.EMPTY_PROVIDER_CHAINID, + FromChainID: "", + ToChainID: "", }, err: legacyerrors.ErrInvalidCoins, }, diff --git a/x/dualstaking/types/message_unbond_test.go b/x/dualstaking/types/message_unbond_test.go index b18ba40cce..08bcf0dab0 100644 --- a/x/dualstaking/types/message_unbond_test.go +++ b/x/dualstaking/types/message_unbond_test.go @@ -6,7 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/v3/testutil/sample" - commontypes "github.com/lavanet/lava/v3/utils/common/types" "github.com/stretchr/testify/require" ) @@ -26,7 +25,7 @@ func TestMsgUnbond_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: oneCoin, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, @@ -37,7 +36,7 @@ func TestMsgUnbond_ValidateBasic(t *testing.T) { Provider: "invalid_address", Amount: oneCoin, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, @@ -48,7 +47,7 @@ func TestMsgUnbond_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: oneCoin, Validator: "invalid_validator", - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidAddress, }, @@ -59,7 +58,7 @@ func TestMsgUnbond_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: oneCoin, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, }, { @@ -69,7 +68,7 @@ func TestMsgUnbond_ValidateBasic(t *testing.T) { Provider: sample.AccAddress(), Amount: sdk.Coin{Denom: "utest", Amount: sdk.NewInt(-1)}, Validator: validator, - ChainID: commontypes.EMPTY_PROVIDER_CHAINID, + ChainID: "", }, err: legacyerrors.ErrInvalidCoins, }, diff --git a/x/dualstaking/types/query.pb.go b/x/dualstaking/types/query.pb.go index e572f9b124..ebdfedebcc 100644 --- a/x/dualstaking/types/query.pb.go +++ b/x/dualstaking/types/query.pb.go @@ -413,7 +413,6 @@ func (m *QueryDelegatorRewardsResponse) GetRewards() []DelegatorRewardInfo { type DelegatorRewardInfo struct { Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` } @@ -457,13 +456,6 @@ func (m *DelegatorRewardInfo) GetProvider() string { return "" } -func (m *DelegatorRewardInfo) GetChainId() string { - if m != nil { - return m.ChainId - } - return "" -} - func (m *DelegatorRewardInfo) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { if m != nil { return m.Amount @@ -488,53 +480,52 @@ func init() { } var fileDescriptor_8393eed0cfbc46b2 = []byte{ - // 722 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x95, 0x4f, 0x4f, 0x13, 0x4f, - 0x18, 0xc7, 0x3b, 0xe5, 0xf7, 0x2b, 0x30, 0xf5, 0x60, 0x06, 0x0e, 0xa5, 0xc1, 0xa5, 0x6e, 0x30, - 0x36, 0x46, 0x76, 0x04, 0x12, 0x01, 0x4d, 0xfc, 0x83, 0x1c, 0x24, 0x81, 0x88, 0x4d, 0xb8, 0x78, - 0x69, 0xa6, 0xdd, 0x71, 0x99, 0xd0, 0xce, 0x2c, 0x3b, 0xd3, 0x22, 0x21, 0x5c, 0x7c, 0x03, 0x9a, - 0xf8, 0x2e, 0xbc, 0xf9, 0x2e, 0x48, 0xf4, 0x40, 0xe2, 0xc5, 0x78, 0x40, 0x03, 0xbe, 0x10, 0xb3, - 0xb3, 0xb3, 0x75, 0x4b, 0x59, 0x5a, 0x48, 0xf4, 0xb4, 0xf4, 0x99, 0xe7, 0x79, 0xbe, 0xcf, 0x67, - 0x9e, 0x7c, 0x07, 0x38, 0xdd, 0x20, 0x6d, 0xc2, 0xa9, 0xc2, 0xe1, 0x17, 0xbb, 0x2d, 0xd2, 0x90, - 0x8a, 0x6c, 0x33, 0xee, 0xe1, 0x9d, 0x16, 0x0d, 0xf6, 0x1c, 0x3f, 0x10, 0x4a, 0xa0, 0x82, 0xc9, - 0x72, 0xc2, 0xaf, 0x93, 0xc8, 0x2a, 0x8e, 0x7b, 0xc2, 0x13, 0x3a, 0x09, 0x87, 0x7f, 0x45, 0xf9, - 0xc5, 0x49, 0x4f, 0x08, 0xaf, 0x41, 0x31, 0xf1, 0x19, 0x26, 0x9c, 0x0b, 0x45, 0x14, 0x13, 0x5c, - 0x9a, 0xd3, 0x3b, 0x75, 0x21, 0x9b, 0x42, 0xe2, 0x1a, 0x91, 0x34, 0x92, 0xc1, 0xed, 0xd9, 0x1a, - 0x55, 0x64, 0x16, 0xfb, 0xc4, 0x63, 0x5c, 0x27, 0x9b, 0xdc, 0x5b, 0xa9, 0xf3, 0xf9, 0x24, 0x20, - 0xcd, 0xb8, 0xe5, 0xed, 0xd4, 0x34, 0x97, 0x36, 0xa8, 0x47, 0x14, 0x35, 0x89, 0x56, 0x52, 0x3b, - 0x56, 0xad, 0x0b, 0x66, 0xf4, 0xec, 0x71, 0x88, 0x5e, 0x86, 0x13, 0x6d, 0xe8, 0xee, 0x15, 0xba, - 0xd3, 0xa2, 0x52, 0xd9, 0x9b, 0x70, 0xac, 0x2b, 0x2a, 0x7d, 0xc1, 0x25, 0x45, 0x8f, 0x60, 0x2e, - 0x9a, 0xa2, 0x00, 0x4a, 0xa0, 0x9c, 0x9f, 0x2b, 0x39, 0x69, 0xf7, 0xe4, 0x44, 0x95, 0xcb, 0xff, - 0x1d, 0x1e, 0x4f, 0x65, 0x2a, 0xa6, 0xca, 0x26, 0xd0, 0xd2, 0x6d, 0x57, 0xa2, 0x19, 0x45, 0xb0, - 0x11, 0x88, 0x36, 0x73, 0x69, 0x10, 0x0b, 0xa3, 0x49, 0x38, 0xea, 0xc6, 0x87, 0x5a, 0x64, 0xb4, - 0xf2, 0x27, 0x80, 0x6e, 0xc2, 0x6b, 0xbb, 0x4c, 0x6d, 0x55, 0x7d, 0xca, 0x5d, 0xc6, 0xbd, 0x42, - 0xb6, 0x04, 0xca, 0x23, 0x95, 0x7c, 0x18, 0xdb, 0x88, 0x42, 0xb6, 0x80, 0x53, 0xa9, 0x12, 0x86, - 0x62, 0x0d, 0xe6, 0x4d, 0xcb, 0x70, 0x47, 0x05, 0x50, 0x1a, 0x2a, 0xe7, 0xe7, 0xa6, 0xd3, 0x51, - 0x56, 0x3a, 0xc9, 0x06, 0x27, 0x59, 0x6e, 0x57, 0x0d, 0x53, 0xac, 0xd3, 0x11, 0xee, 0x30, 0x15, - 0xe1, 0x88, 0x6f, 0x0e, 0x0d, 0x52, 0xe7, 0xf7, 0x65, 0x88, 0xce, 0x13, 0xf8, 0x2b, 0x44, 0x12, - 0x4e, 0x76, 0x5f, 0x61, 0x85, 0xee, 0x92, 0xc0, 0x1d, 0x70, 0x47, 0x49, 0xda, 0xec, 0x19, 0xda, - 0x09, 0x38, 0x52, 0xdf, 0x22, 0x8c, 0x57, 0x99, 0x5b, 0x18, 0xd2, 0x67, 0xc3, 0xfa, 0xf7, 0xaa, - 0x6b, 0x73, 0x78, 0x23, 0x45, 0xd4, 0x30, 0xae, 0xc3, 0xe1, 0x20, 0x0a, 0x19, 0xbe, 0x99, 0xbe, - 0x7c, 0x71, 0x93, 0x55, 0xfe, 0x5a, 0x18, 0xd0, 0xb8, 0x87, 0xfd, 0x09, 0xc0, 0xb1, 0x73, 0xd2, - 0x2e, 0x5c, 0x56, 0x72, 0xfc, 0x6c, 0xd7, 0xf8, 0xa8, 0x0e, 0x73, 0xa4, 0x29, 0x5a, 0x5c, 0x15, - 0x86, 0xf4, 0x70, 0x13, 0x4e, 0xe4, 0x3b, 0x27, 0xf4, 0x9d, 0x63, 0x7c, 0xe7, 0x3c, 0x13, 0x8c, - 0x2f, 0xdf, 0x0b, 0x07, 0xf9, 0xf8, 0x63, 0xaa, 0xec, 0x31, 0xb5, 0xd5, 0xaa, 0x39, 0x75, 0xd1, - 0xc4, 0xc6, 0xa4, 0xd1, 0x67, 0x46, 0xba, 0xdb, 0x58, 0xed, 0xf9, 0x54, 0xea, 0x02, 0x59, 0x31, - 0xad, 0xe7, 0x8e, 0x87, 0xe1, 0xff, 0xfa, 0x92, 0xd0, 0x3b, 0x00, 0x73, 0x91, 0xc3, 0xd0, 0xdd, - 0xf4, 0x6b, 0xe8, 0x35, 0x76, 0x71, 0x66, 0xc0, 0xec, 0xe8, 0xd2, 0xed, 0xf2, 0xdb, 0xaf, 0xbf, - 0x3e, 0x64, 0x6d, 0x54, 0xc2, 0x7d, 0x9e, 0x25, 0xf4, 0x05, 0x40, 0xd4, 0xeb, 0x39, 0xb4, 0xd8, - 0x47, 0x2f, 0xf5, 0x25, 0x28, 0x2e, 0x5d, 0xa1, 0xd2, 0x4c, 0xfd, 0x54, 0x4f, 0xfd, 0x10, 0x2d, - 0xe1, 0x7e, 0xaf, 0xa4, 0x08, 0xaa, 0xf1, 0x76, 0x25, 0xde, 0xef, 0x04, 0x0f, 0xd0, 0x67, 0x00, - 0x51, 0xaf, 0xe1, 0xfa, 0xe2, 0xa4, 0x3e, 0x02, 0x7d, 0x71, 0xd2, 0xdd, 0x6d, 0x3f, 0xd1, 0x38, - 0x0f, 0xd0, 0xe2, 0x05, 0x4b, 0x30, 0xd5, 0xd5, 0x0e, 0x82, 0xc4, 0xfb, 0x71, 0xf0, 0x00, 0x7d, - 0x07, 0xf0, 0xfa, 0x59, 0x63, 0xa1, 0xfb, 0x83, 0x5e, 0x70, 0xb7, 0xfd, 0x8b, 0x0b, 0x97, 0xae, - 0x33, 0x1c, 0x9b, 0x9a, 0xe3, 0x05, 0x5a, 0x1f, 0x64, 0x2d, 0xc6, 0xa7, 0xc9, 0xa5, 0x24, 0x88, - 0xf0, 0x7e, 0x6c, 0xc4, 0x03, 0x74, 0x08, 0xe0, 0xf8, 0x59, 0xcd, 0x35, 0x26, 0xd5, 0xbf, 0x07, - 0x7c, 0xac, 0x01, 0x97, 0xd0, 0xc2, 0x15, 0x01, 0x97, 0x9f, 0x1f, 0x9e, 0x58, 0xe0, 0xe8, 0xc4, - 0x02, 0x3f, 0x4f, 0x2c, 0xf0, 0xfe, 0xd4, 0xca, 0x1c, 0x9d, 0x5a, 0x99, 0x6f, 0xa7, 0x56, 0xe6, - 0x95, 0x93, 0x78, 0x2c, 0xba, 0x9a, 0xb7, 0xe7, 0xf1, 0x9b, 0x2e, 0x05, 0xfd, 0x70, 0xd4, 0x72, - 0xfa, 0xbf, 0xfb, 0xfc, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0c, 0x54, 0x32, 0x8e, 0xef, 0x08, - 0x00, 0x00, + // 719 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x95, 0xcf, 0x4f, 0x13, 0x41, + 0x14, 0xc7, 0xbb, 0x2d, 0x96, 0x32, 0xf5, 0x40, 0x06, 0x0e, 0xa5, 0xc1, 0xa5, 0x6e, 0x30, 0x36, + 0x46, 0x76, 0x04, 0x12, 0x01, 0x4d, 0xfc, 0x81, 0x1c, 0xc4, 0x40, 0xc4, 0x26, 0x5c, 0xbc, 0x34, + 0xd3, 0xee, 0xb8, 0x4c, 0x68, 0x67, 0x96, 0x9d, 0x69, 0x91, 0x10, 0x2e, 0xfe, 0x03, 0x9a, 0x78, + 0xf5, 0x2f, 0xf0, 0x2f, 0x21, 0xd1, 0x03, 0x89, 0x17, 0xe3, 0x01, 0x0d, 0xf8, 0x87, 0x98, 0x9d, + 0x9d, 0xad, 0x5b, 0xca, 0xd2, 0x42, 0xa2, 0xa7, 0xa5, 0x6f, 0xde, 0x7b, 0xdf, 0xf7, 0x99, 0x97, + 0xef, 0x00, 0xa6, 0x1b, 0xb8, 0x8d, 0x19, 0x91, 0x28, 0xf8, 0x22, 0xa7, 0x85, 0x1b, 0x42, 0xe2, + 0x6d, 0xca, 0x5c, 0xb4, 0xd3, 0x22, 0xfe, 0x9e, 0xed, 0xf9, 0x5c, 0x72, 0x58, 0xd0, 0x59, 0x76, + 0xf0, 0xb5, 0x63, 0x59, 0xc5, 0x71, 0x97, 0xbb, 0x5c, 0x25, 0xa1, 0xe0, 0xaf, 0x30, 0xbf, 0x38, + 0xe9, 0x72, 0xee, 0x36, 0x08, 0xc2, 0x1e, 0x45, 0x98, 0x31, 0x2e, 0xb1, 0xa4, 0x9c, 0x09, 0x7d, + 0x7a, 0xa7, 0xce, 0x45, 0x93, 0x0b, 0x54, 0xc3, 0x82, 0x84, 0x32, 0xa8, 0x3d, 0x5b, 0x23, 0x12, + 0xcf, 0x22, 0x0f, 0xbb, 0x94, 0xa9, 0x64, 0x9d, 0x7b, 0x2b, 0x71, 0x3e, 0x0f, 0xfb, 0xb8, 0x19, + 0xb5, 0xbc, 0x9d, 0x98, 0xe6, 0x90, 0x06, 0x71, 0xb1, 0x24, 0x3a, 0xd1, 0x8c, 0x6b, 0x47, 0xaa, + 0x75, 0x4e, 0xb5, 0x9e, 0x35, 0x0e, 0xe0, 0xab, 0x60, 0xa2, 0x0d, 0xd5, 0xbd, 0x42, 0x76, 0x5a, + 0x44, 0x48, 0x6b, 0x13, 0x8c, 0x75, 0x45, 0x85, 0xc7, 0x99, 0x20, 0xf0, 0x11, 0xc8, 0x86, 0x53, + 0x14, 0x8c, 0x92, 0x51, 0xce, 0xcf, 0x95, 0xec, 0xa4, 0x7b, 0xb2, 0xc3, 0xca, 0xe5, 0xa1, 0xc3, + 0xe3, 0xa9, 0x54, 0x45, 0x57, 0x59, 0x18, 0x98, 0xaa, 0xed, 0x4a, 0x38, 0x23, 0xf7, 0x37, 0x7c, + 0xde, 0xa6, 0x0e, 0xf1, 0x23, 0x61, 0x38, 0x09, 0x46, 0x9c, 0xe8, 0x50, 0x89, 0x8c, 0x54, 0xfe, + 0x06, 0xe0, 0x4d, 0x70, 0x7d, 0x97, 0xca, 0xad, 0xaa, 0x47, 0x98, 0x43, 0x99, 0x5b, 0x48, 0x97, + 0x8c, 0x72, 0xae, 0x92, 0x0f, 0x62, 0x1b, 0x61, 0xc8, 0xe2, 0x60, 0x2a, 0x51, 0x42, 0x53, 0xac, + 0x81, 0xbc, 0x6e, 0x19, 0xec, 0xa8, 0x60, 0x94, 0x32, 0xe5, 0xfc, 0xdc, 0x74, 0x32, 0xca, 0x4a, + 0x27, 0x59, 0xe3, 0xc4, 0xcb, 0xad, 0xaa, 0x66, 0x8a, 0x74, 0x3a, 0xc2, 0x1d, 0xa6, 0x22, 0xc8, + 0x79, 0xfa, 0x50, 0x23, 0x75, 0x7e, 0x5f, 0x86, 0xe8, 0x3c, 0x81, 0x7f, 0x42, 0x24, 0xc0, 0x64, + 0xf7, 0x15, 0x56, 0xc8, 0x2e, 0xf6, 0x9d, 0x01, 0x77, 0x14, 0xa7, 0x4d, 0x9f, 0xa1, 0x9d, 0x00, + 0xb9, 0xfa, 0x16, 0xa6, 0xac, 0x4a, 0x9d, 0x42, 0x46, 0x9d, 0x0d, 0xab, 0xdf, 0xab, 0x8e, 0xc5, + 0xc0, 0x8d, 0x04, 0x51, 0xcd, 0xb8, 0x0e, 0x86, 0xfd, 0x30, 0xa4, 0xf9, 0x66, 0xfa, 0xf2, 0x45, + 0x4d, 0x56, 0xd9, 0x1b, 0xae, 0x41, 0xa3, 0x1e, 0xd6, 0x27, 0x03, 0x8c, 0x9d, 0x93, 0x76, 0xe1, + 0xb2, 0xea, 0x20, 0x8b, 0x9b, 0xbc, 0xc5, 0x64, 0x21, 0xa3, 0x26, 0x98, 0xb0, 0x43, 0x73, 0xd9, + 0x81, 0xb9, 0x6c, 0x6d, 0x2e, 0xfb, 0x19, 0xa7, 0x6c, 0xf9, 0x5e, 0xa0, 0xf6, 0xf9, 0xe7, 0x54, + 0xd9, 0xa5, 0x72, 0xab, 0x55, 0xb3, 0xeb, 0xbc, 0x89, 0xb4, 0x13, 0xc3, 0xcf, 0x8c, 0x70, 0xb6, + 0x91, 0xdc, 0xf3, 0x88, 0x50, 0x05, 0xa2, 0xa2, 0x5b, 0xbf, 0x18, 0xca, 0xa5, 0x47, 0x33, 0x73, + 0xc7, 0xc3, 0xe0, 0x9a, 0xba, 0x0f, 0xf8, 0xde, 0x00, 0xd9, 0xd0, 0x4c, 0xf0, 0x6e, 0x32, 0x71, + 0xaf, 0x87, 0x8b, 0x33, 0x03, 0x66, 0x87, 0xf7, 0x6b, 0x95, 0xdf, 0x7d, 0xfb, 0xfd, 0x31, 0x6d, + 0xc1, 0x12, 0xea, 0xf3, 0x02, 0xc1, 0xaf, 0x06, 0x80, 0xbd, 0xf6, 0x82, 0x8b, 0x7d, 0xf4, 0x12, + 0x4d, 0x5f, 0x5c, 0xba, 0x42, 0xa5, 0x9e, 0xfa, 0xa9, 0x9a, 0xfa, 0x21, 0x5c, 0x42, 0xfd, 0x1e, + 0x44, 0xee, 0x57, 0xa3, 0x45, 0x0a, 0xb4, 0xdf, 0x09, 0x1e, 0xc0, 0x2f, 0x06, 0x80, 0xbd, 0xde, + 0xea, 0x8b, 0x93, 0xe8, 0xf7, 0xbe, 0x38, 0xc9, 0x46, 0xb6, 0x9e, 0x28, 0x9c, 0x07, 0x70, 0xf1, + 0x82, 0x25, 0xe8, 0xea, 0x6a, 0x07, 0x41, 0xa0, 0xfd, 0x28, 0x78, 0x00, 0x7f, 0x18, 0x60, 0xf4, + 0xac, 0x87, 0xe0, 0xfd, 0x41, 0x2f, 0xb8, 0xdb, 0xe9, 0xc5, 0x85, 0x4b, 0xd7, 0x69, 0x8e, 0x4d, + 0xc5, 0xf1, 0x12, 0xae, 0x0f, 0xb2, 0x16, 0x6d, 0xc9, 0xf8, 0x52, 0x62, 0x44, 0x68, 0x3f, 0x7a, + 0x32, 0x0e, 0xe0, 0xa1, 0x01, 0xc6, 0xcf, 0x6a, 0xae, 0x51, 0x21, 0xff, 0x3f, 0xe0, 0x63, 0x05, + 0xb8, 0x04, 0x17, 0xae, 0x08, 0xb8, 0xfc, 0xfc, 0xf0, 0xc4, 0x34, 0x8e, 0x4e, 0x4c, 0xe3, 0xd7, + 0x89, 0x69, 0x7c, 0x38, 0x35, 0x53, 0x47, 0xa7, 0x66, 0xea, 0xfb, 0xa9, 0x99, 0x7a, 0x6d, 0xc7, + 0x9e, 0x8c, 0xae, 0xe6, 0xed, 0x79, 0xf4, 0xb6, 0x4b, 0x41, 0x3d, 0x1f, 0xb5, 0xac, 0xfa, 0x47, + 0x3e, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0x70, 0x47, 0xc0, 0x97, 0xda, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1096,13 +1087,6 @@ func (m *DelegatorRewardInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x1a } } - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0x12 - } if len(m.Provider) > 0 { i -= len(m.Provider) copy(dAtA[i:], m.Provider) @@ -1252,10 +1236,6 @@ func (m *DelegatorRewardInfo) Size() (n int) { if l > 0 { n += 1 + l + sovQuery(uint64(l)) } - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } if len(m.Amount) > 0 { for _, e := range m.Amount { l = e.Size() @@ -2067,38 +2047,6 @@ func (m *DelegatorRewardInfo) Unmarshal(dAtA []byte) error { } m.Provider = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", 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.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) diff --git a/x/epochstorage/README.md b/x/epochstorage/README.md index cab73a26ac..5a197c3c21 100644 --- a/x/epochstorage/README.md +++ b/x/epochstorage/README.md @@ -13,6 +13,7 @@ Note that the module will make sure that any changes will be applied only in the * [Epoch](#epoch) * [EpochDetails](#epochdetails) * [FixatedParams](#fixatedparams) + * [Metadata](#metadata) * [StakeEntry](#stakeentry) * [StakeEntry Storage](#stakeentry-storage) * [Parameters](#parameters) @@ -63,6 +64,21 @@ type FixatedParams struct { This is done in the [BeginBlock method of the module](keeper/fixated_params.go) +### Metadata + +The metadata struct includes all the data for a provider that is the same accross all chains +```go +type ProviderMetadata struct { + Provider string // provider address + Vault string // vault address + TotalDelegations types.Coin // total delegations by delegators + Chains []string // list of all chain ids the provider is staken on + DelegateCommission uint64 // provider commission from rewards + LastChange uint64 // date of the last commission change + Description types1.Description // string descriptions of the provider entity (moniker, identity, wesite...) +} +``` + ### StakeEntry The stake entry is a struct that contains all the information of a provider. @@ -146,6 +162,7 @@ The epochstorage module supports the following queries: | `show-fixated-params` | chainid | a specific fixated param | | `list-stake-storage` | chainid | list of all stake storages indices | | `show-stake-storage` | chainid | show a specific stake storage | +| `provider-metadata` | provider-address | shows the metadata of a specific provider, if left empty returns metadata for all providers | ## Transactions diff --git a/x/epochstorage/client/cli/query.go b/x/epochstorage/client/cli/query.go index decae416ca..1f0b91db88 100644 --- a/x/epochstorage/client/cli/query.go +++ b/x/epochstorage/client/cli/query.go @@ -30,6 +30,8 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdShowEpochDetails()) cmd.AddCommand(CmdListFixatedParams()) cmd.AddCommand(CmdShowFixatedParams()) + cmd.AddCommand(CmdProviderMetadata()) + // this line is used by starport scaffolding # 1 return cmd diff --git a/x/epochstorage/client/cli/query_provider_metadata.go b/x/epochstorage/client/cli/query_provider_metadata.go new file mode 100644 index 0000000000..cf2a7bb355 --- /dev/null +++ b/x/epochstorage/client/cli/query_provider_metadata.go @@ -0,0 +1,44 @@ +package cli + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/lavanet/lava/v3/x/epochstorage/types" + "github.com/spf13/cobra" +) + +func CmdProviderMetadata() *cobra.Command { + cmd := &cobra.Command{ + Use: "provider-metadata", + Short: "returns the metadata for the provider address, if empty returns the metadata of all providers", + Example: "lavad provider-metadata lava@12345", + Args: cobra.RangeArgs(0, 1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + provider := "" + if len(args) == 1 { + provider = args[0] + } + + res, err := queryClient.ProviderMetaData(context.Background(), &types.QueryProviderMetaDataRequest{Provider: provider}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddPaginationFlagsToCmd(cmd, cmd.Use) + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/epochstorage/keeper/grpc_query_provider_metadata.go b/x/epochstorage/keeper/grpc_query_provider_metadata.go new file mode 100644 index 0000000000..5587c2e2b9 --- /dev/null +++ b/x/epochstorage/keeper/grpc_query_provider_metadata.go @@ -0,0 +1,29 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/v3/x/epochstorage/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (k Keeper) ProviderMetaData(c context.Context, req *types.QueryProviderMetaDataRequest) (*types.QueryProviderMetaDataResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(c) + var err error + res := types.QueryProviderMetaDataResponse{} + if req.Provider == "" { + res.MetaData, err = k.GetAllMetadata(ctx) + } else { + var metadata types.ProviderMetadata + metadata, err = k.GetMetadata(ctx, req.Provider) + res.MetaData = append(res.MetaData, metadata) + } + + return &res, err +} diff --git a/x/epochstorage/keeper/keeper.go b/x/epochstorage/keeper/keeper.go index 999f0932e5..a289969d11 100644 --- a/x/epochstorage/keeper/keeper.go +++ b/x/epochstorage/keeper/keeper.go @@ -34,6 +34,7 @@ type ( stakeEntries *collections.IndexedMap[collections.Triple[uint64, string, collections.Pair[uint64, string]], types.StakeEntry, types.EpochChainIdProviderIndexes] stakeEntriesCurrent *collections.IndexedMap[collections.Pair[string, string], types.StakeEntry, types.ChainIdVaultIndexes] epochHashes collections.Map[uint64, []byte] + providersMetaData collections.Map[string, types.ProviderMetadata] } ) @@ -77,6 +78,8 @@ func NewKeeper( collcompat.ProtoValue[types.StakeEntry](cdc), types.NewChainIdVaultIndexes(sb)), epochHashes: collections.NewMap(sb, types.EpochHashesPrefix, "epoch_hashes", collections.Uint64Key, collections.BytesValue), + + providersMetaData: collections.NewMap(sb, types.ProviderMetaDataPrefix, "provider_metadata", collections.StringKey, collcompat.ProtoValue[types.ProviderMetadata](cdc)), } keeper.AddFixationRegistry(string(types.KeyEpochBlocks), func(ctx sdk.Context) any { return keeper.EpochBlocksRaw(ctx) }) diff --git a/x/epochstorage/keeper/provider_metadata.go b/x/epochstorage/keeper/provider_metadata.go new file mode 100644 index 0000000000..9c3db359b3 --- /dev/null +++ b/x/epochstorage/keeper/provider_metadata.go @@ -0,0 +1,35 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/v3/x/epochstorage/types" +) + +func (k Keeper) GetMetadata(ctx sdk.Context, provider string) (types.ProviderMetadata, error) { + return k.providersMetaData.Get(ctx, provider) +} + +func (k Keeper) SetMetadata(ctx sdk.Context, metadata types.ProviderMetadata) { + err := k.providersMetaData.Set(ctx, metadata.Provider, metadata) + if err != nil { + panic(err) + } +} + +func (k Keeper) RemoveMetadata(ctx sdk.Context, provider string) error { + return k.providersMetaData.Remove(ctx, provider) +} + +func (k Keeper) SetAllMetadata(ctx sdk.Context, metadata []types.ProviderMetadata) { + for _, md := range metadata { + k.SetMetadata(ctx, md) + } +} + +func (k Keeper) GetAllMetadata(ctx sdk.Context) ([]types.ProviderMetadata, error) { + iter, err := k.providersMetaData.Iterate(ctx, nil) + if err != nil { + panic(err) + } + return iter.Values() +} diff --git a/x/epochstorage/keeper/stake_entries.go b/x/epochstorage/keeper/stake_entries.go index de35d9d4d4..ad2abcec6e 100644 --- a/x/epochstorage/keeper/stake_entries.go +++ b/x/epochstorage/keeper/stake_entries.go @@ -8,6 +8,7 @@ import ( "cosmossdk.io/collections" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/utils" + "github.com/lavanet/lava/v3/utils/lavaslices" "github.com/lavanet/lava/v3/x/epochstorage/types" ) @@ -187,6 +188,23 @@ func (k Keeper) RemoveStakeEntryCurrent(ctx sdk.Context, chainID string, provide if err != nil { panic(fmt.Errorf("RemoveStakeEntryCurrent: Failed to remove entry with key %v, error: %w", key, err)) } + + metadata, err := k.GetMetadata(ctx, provider) + if err != nil { + panic(fmt.Errorf("RemoveStakeEntryCurrent: Failed to fetch provider metadata %v, error: %w", provider, err)) + } + var ok bool + metadata.Chains, ok = lavaslices.Remove(metadata.Chains, chainID) + if !ok { + panic(fmt.Errorf("RemoveStakeEntryCurrent: Failed to remove chain from provider metadata %v, error: %w", provider, err)) + } + if len(metadata.Chains) == 0 { + if k.RemoveMetadata(ctx, provider) != nil { + panic(fmt.Errorf("RemoveStakeEntryCurrent: Failed to remove provider metadata %v, error: %w", provider, err)) + } + } else { + k.SetMetadata(ctx, metadata) + } } // GetAllStakeEntriesCurrent gets all the current stake entries diff --git a/x/epochstorage/keeper/stake_entries_test.go b/x/epochstorage/keeper/stake_entries_test.go index 91d40c9420..0bdab37d08 100644 --- a/x/epochstorage/keeper/stake_entries_test.go +++ b/x/epochstorage/keeper/stake_entries_test.go @@ -99,6 +99,12 @@ func createNStakeEntriesCurrent(keeper *keeper.Keeper, ctx sdk.Context, n int) [ Chain: strconv.Itoa(i), } keeper.SetStakeEntryCurrent(ctx, items[i]) + metadata := types.ProviderMetadata{ + Provider: items[i].Address, + Vault: items[i].Vault, + Chains: []string{items[i].Chain}, + } + keeper.SetMetadata(ctx, metadata) } return items } diff --git a/x/epochstorage/types/provider_metadata.pb.go b/x/epochstorage/types/provider_metadata.pb.go new file mode 100644 index 0000000000..873bcdbcd8 --- /dev/null +++ b/x/epochstorage/types/provider_metadata.pb.go @@ -0,0 +1,618 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: lavanet/lava/epochstorage/provider_metadata.proto + +package types + +import ( + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + types1 "github.com/cosmos/cosmos-sdk/x/staking/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type ProviderMetadata struct { + Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"` + Vault string `protobuf:"bytes,2,opt,name=vault,proto3" json:"vault,omitempty"` + TotalDelegations types.Coin `protobuf:"bytes,3,opt,name=total_delegations,json=totalDelegations,proto3" json:"total_delegations"` + Chains []string `protobuf:"bytes,4,rep,name=chains,proto3" json:"chains,omitempty"` + DelegateCommission uint64 `protobuf:"varint,5,opt,name=delegate_commission,json=delegateCommission,proto3" json:"delegate_commission,omitempty"` + LastChange uint64 `protobuf:"varint,6,opt,name=last_change,json=lastChange,proto3" json:"last_change,omitempty"` + Description types1.Description `protobuf:"bytes,7,opt,name=description,proto3" json:"description"` +} + +func (m *ProviderMetadata) Reset() { *m = ProviderMetadata{} } +func (m *ProviderMetadata) String() string { return proto.CompactTextString(m) } +func (*ProviderMetadata) ProtoMessage() {} +func (*ProviderMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_eea88d8dbfad23fd, []int{0} +} +func (m *ProviderMetadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProviderMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProviderMetadata.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 *ProviderMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProviderMetadata.Merge(m, src) +} +func (m *ProviderMetadata) XXX_Size() int { + return m.Size() +} +func (m *ProviderMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_ProviderMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_ProviderMetadata proto.InternalMessageInfo + +func (m *ProviderMetadata) GetProvider() string { + if m != nil { + return m.Provider + } + return "" +} + +func (m *ProviderMetadata) GetVault() string { + if m != nil { + return m.Vault + } + return "" +} + +func (m *ProviderMetadata) GetTotalDelegations() types.Coin { + if m != nil { + return m.TotalDelegations + } + return types.Coin{} +} + +func (m *ProviderMetadata) GetChains() []string { + if m != nil { + return m.Chains + } + return nil +} + +func (m *ProviderMetadata) GetDelegateCommission() uint64 { + if m != nil { + return m.DelegateCommission + } + return 0 +} + +func (m *ProviderMetadata) GetLastChange() uint64 { + if m != nil { + return m.LastChange + } + return 0 +} + +func (m *ProviderMetadata) GetDescription() types1.Description { + if m != nil { + return m.Description + } + return types1.Description{} +} + +func init() { + proto.RegisterType((*ProviderMetadata)(nil), "lavanet.lava.epochstorage.ProviderMetadata") +} + +func init() { + proto.RegisterFile("lavanet/lava/epochstorage/provider_metadata.proto", fileDescriptor_eea88d8dbfad23fd) +} + +var fileDescriptor_eea88d8dbfad23fd = []byte{ + // 401 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0x31, 0x6e, 0xdb, 0x30, + 0x18, 0x85, 0xcd, 0xc4, 0x71, 0x6b, 0x7a, 0x49, 0xd8, 0xa0, 0x50, 0x3c, 0x28, 0x46, 0xdb, 0xc1, + 0xe8, 0x40, 0xc2, 0xcd, 0x0d, 0xec, 0x2c, 0x05, 0x5a, 0x20, 0xd0, 0xd8, 0xc5, 0xf8, 0x45, 0x11, + 0x12, 0x51, 0x89, 0xbf, 0x20, 0x32, 0x42, 0x7b, 0x8b, 0x1e, 0xa3, 0x63, 0x8f, 0x91, 0xa9, 0xc8, + 0xd8, 0xa9, 0x28, 0xec, 0xa1, 0xd7, 0x08, 0x44, 0x51, 0x4e, 0xb2, 0x88, 0x7a, 0xff, 0x7b, 0x8f, + 0xfa, 0x20, 0x92, 0xae, 0x4a, 0x68, 0xc1, 0x28, 0x27, 0xba, 0x55, 0xa8, 0x1a, 0x65, 0x61, 0x1d, + 0x36, 0x90, 0x2b, 0x51, 0x37, 0xd8, 0xea, 0x4c, 0x35, 0xdb, 0x4a, 0x39, 0xc8, 0xc0, 0x01, 0xaf, + 0x1b, 0x74, 0xc8, 0x2e, 0x42, 0x85, 0x77, 0x2b, 0x7f, 0x5a, 0x99, 0x9f, 0xe7, 0x98, 0xa3, 0x4f, + 0x89, 0xee, 0xad, 0x2f, 0xcc, 0x63, 0x89, 0xb6, 0x42, 0x2b, 0x52, 0xb0, 0x4a, 0xb4, 0xab, 0x54, + 0x39, 0x58, 0x09, 0x89, 0xda, 0x04, 0xff, 0x0c, 0x2a, 0x6d, 0x50, 0xf8, 0x67, 0x18, 0xbd, 0x0b, + 0x15, 0xeb, 0xe0, 0xab, 0x36, 0xf9, 0xa1, 0x15, 0x74, 0x9f, 0x7a, 0xf3, 0xfb, 0x88, 0x9e, 0xde, + 0x04, 0xca, 0xcf, 0x01, 0x92, 0xcd, 0xe9, 0xcb, 0x81, 0x3c, 0x22, 0x0b, 0xb2, 0x9c, 0x26, 0x07, + 0xcd, 0xce, 0xe9, 0x49, 0x0b, 0xb7, 0xa5, 0x8b, 0x8e, 0xbc, 0xd1, 0x0b, 0xf6, 0x89, 0x9e, 0x39, + 0x74, 0x50, 0x6e, 0x33, 0x55, 0xaa, 0x1c, 0x9c, 0x46, 0x63, 0xa3, 0xe3, 0x05, 0x59, 0xce, 0x3e, + 0x5c, 0xf0, 0x1e, 0x84, 0x77, 0xec, 0x3c, 0x50, 0xf0, 0x0d, 0x6a, 0xb3, 0x1e, 0xdf, 0xfd, 0xbd, + 0x1c, 0x25, 0xa7, 0xbe, 0x79, 0xfd, 0x58, 0x64, 0xaf, 0xe9, 0x44, 0x16, 0xa0, 0x8d, 0x8d, 0xc6, + 0x8b, 0xe3, 0xe5, 0x34, 0x09, 0x8a, 0x09, 0xfa, 0x2a, 0xec, 0xaf, 0xb6, 0x12, 0xab, 0x4a, 0x5b, + 0xab, 0xd1, 0x44, 0x27, 0x0b, 0xb2, 0x1c, 0x27, 0x6c, 0xb0, 0x36, 0x07, 0x87, 0x5d, 0xd2, 0x59, + 0x09, 0xd6, 0x6d, 0x65, 0x01, 0x26, 0x57, 0xd1, 0xc4, 0x07, 0x69, 0x37, 0xda, 0xf8, 0x09, 0xbb, + 0xa1, 0xb3, 0x4c, 0x59, 0xd9, 0xe8, 0xba, 0xfb, 0x72, 0xf4, 0xc2, 0x13, 0xbf, 0x1d, 0x88, 0x87, + 0x5f, 0x35, 0x40, 0x5f, 0x3f, 0x46, 0xd7, 0xd3, 0x8e, 0xfd, 0xe7, 0xff, 0x5f, 0xef, 0x49, 0xf2, + 0x74, 0x8b, 0xf5, 0xc7, 0xbb, 0x5d, 0x4c, 0xee, 0x77, 0x31, 0xf9, 0xb7, 0x8b, 0xc9, 0x8f, 0x7d, + 0x3c, 0xba, 0xdf, 0xc7, 0xa3, 0x3f, 0xfb, 0x78, 0xf4, 0x45, 0xe4, 0xda, 0x15, 0xb7, 0x29, 0x97, + 0x58, 0x89, 0x67, 0x57, 0xa6, 0xbd, 0x12, 0xdf, 0x9e, 0xdf, 0x1b, 0xf7, 0xbd, 0x56, 0x36, 0x9d, + 0xf8, 0x23, 0xba, 0x7a, 0x08, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x00, 0x30, 0x06, 0x61, 0x02, 0x00, + 0x00, +} + +func (m *ProviderMetadata) 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 *ProviderMetadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProviderMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Description.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProviderMetadata(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + if m.LastChange != 0 { + i = encodeVarintProviderMetadata(dAtA, i, uint64(m.LastChange)) + i-- + dAtA[i] = 0x30 + } + if m.DelegateCommission != 0 { + i = encodeVarintProviderMetadata(dAtA, i, uint64(m.DelegateCommission)) + i-- + dAtA[i] = 0x28 + } + if len(m.Chains) > 0 { + for iNdEx := len(m.Chains) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Chains[iNdEx]) + copy(dAtA[i:], m.Chains[iNdEx]) + i = encodeVarintProviderMetadata(dAtA, i, uint64(len(m.Chains[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.TotalDelegations.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProviderMetadata(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Vault) > 0 { + i -= len(m.Vault) + copy(dAtA[i:], m.Vault) + i = encodeVarintProviderMetadata(dAtA, i, uint64(len(m.Vault))) + i-- + dAtA[i] = 0x12 + } + if len(m.Provider) > 0 { + i -= len(m.Provider) + copy(dAtA[i:], m.Provider) + i = encodeVarintProviderMetadata(dAtA, i, uint64(len(m.Provider))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintProviderMetadata(dAtA []byte, offset int, v uint64) int { + offset -= sovProviderMetadata(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ProviderMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Provider) + if l > 0 { + n += 1 + l + sovProviderMetadata(uint64(l)) + } + l = len(m.Vault) + if l > 0 { + n += 1 + l + sovProviderMetadata(uint64(l)) + } + l = m.TotalDelegations.Size() + n += 1 + l + sovProviderMetadata(uint64(l)) + if len(m.Chains) > 0 { + for _, s := range m.Chains { + l = len(s) + n += 1 + l + sovProviderMetadata(uint64(l)) + } + } + if m.DelegateCommission != 0 { + n += 1 + sovProviderMetadata(uint64(m.DelegateCommission)) + } + if m.LastChange != 0 { + n += 1 + sovProviderMetadata(uint64(m.LastChange)) + } + l = m.Description.Size() + n += 1 + l + sovProviderMetadata(uint64(l)) + return n +} + +func sovProviderMetadata(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozProviderMetadata(x uint64) (n int) { + return sovProviderMetadata(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ProviderMetadata) 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 ErrIntOverflowProviderMetadata + } + 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: ProviderMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProviderMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Provider", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + 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 ErrInvalidLengthProviderMetadata + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProviderMetadata + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Provider = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vault", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + 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 ErrInvalidLengthProviderMetadata + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProviderMetadata + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Vault = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalDelegations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProviderMetadata + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProviderMetadata + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TotalDelegations.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Chains", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + 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 ErrInvalidLengthProviderMetadata + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProviderMetadata + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Chains = append(m.Chains, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DelegateCommission", wireType) + } + m.DelegateCommission = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DelegateCommission |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastChange", wireType) + } + m.LastChange = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastChange |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProviderMetadata + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProviderMetadata + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Description.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipProviderMetadata(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthProviderMetadata + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipProviderMetadata(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowProviderMetadata + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthProviderMetadata + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupProviderMetadata + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthProviderMetadata + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthProviderMetadata = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowProviderMetadata = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupProviderMetadata = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/epochstorage/types/query.pb.go b/x/epochstorage/types/query.pb.go index 64e754ca79..2247632086 100644 --- a/x/epochstorage/types/query.pb.go +++ b/x/epochstorage/types/query.pb.go @@ -562,6 +562,94 @@ func (m *QueryAllFixatedParamsResponse) GetPagination() *query.PageResponse { return nil } +type QueryProviderMetaDataRequest struct { + Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"` +} + +func (m *QueryProviderMetaDataRequest) Reset() { *m = QueryProviderMetaDataRequest{} } +func (m *QueryProviderMetaDataRequest) String() string { return proto.CompactTextString(m) } +func (*QueryProviderMetaDataRequest) ProtoMessage() {} +func (*QueryProviderMetaDataRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_60112e15fc266719, []int{12} +} +func (m *QueryProviderMetaDataRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProviderMetaDataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProviderMetaDataRequest.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 *QueryProviderMetaDataRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProviderMetaDataRequest.Merge(m, src) +} +func (m *QueryProviderMetaDataRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryProviderMetaDataRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProviderMetaDataRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProviderMetaDataRequest proto.InternalMessageInfo + +func (m *QueryProviderMetaDataRequest) GetProvider() string { + if m != nil { + return m.Provider + } + return "" +} + +type QueryProviderMetaDataResponse struct { + MetaData []ProviderMetadata `protobuf:"bytes,1,rep,name=MetaData,proto3" json:"MetaData"` +} + +func (m *QueryProviderMetaDataResponse) Reset() { *m = QueryProviderMetaDataResponse{} } +func (m *QueryProviderMetaDataResponse) String() string { return proto.CompactTextString(m) } +func (*QueryProviderMetaDataResponse) ProtoMessage() {} +func (*QueryProviderMetaDataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_60112e15fc266719, []int{13} +} +func (m *QueryProviderMetaDataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProviderMetaDataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProviderMetaDataResponse.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 *QueryProviderMetaDataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProviderMetaDataResponse.Merge(m, src) +} +func (m *QueryProviderMetaDataResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryProviderMetaDataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProviderMetaDataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProviderMetaDataResponse proto.InternalMessageInfo + +func (m *QueryProviderMetaDataResponse) GetMetaData() []ProviderMetadata { + if m != nil { + return m.MetaData + } + return nil +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "lavanet.lava.epochstorage.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "lavanet.lava.epochstorage.QueryParamsResponse") @@ -575,6 +663,8 @@ func init() { proto.RegisterType((*QueryGetFixatedParamsResponse)(nil), "lavanet.lava.epochstorage.QueryGetFixatedParamsResponse") proto.RegisterType((*QueryAllFixatedParamsRequest)(nil), "lavanet.lava.epochstorage.QueryAllFixatedParamsRequest") proto.RegisterType((*QueryAllFixatedParamsResponse)(nil), "lavanet.lava.epochstorage.QueryAllFixatedParamsResponse") + proto.RegisterType((*QueryProviderMetaDataRequest)(nil), "lavanet.lava.epochstorage.QueryProviderMetaDataRequest") + proto.RegisterType((*QueryProviderMetaDataResponse)(nil), "lavanet.lava.epochstorage.QueryProviderMetaDataResponse") } func init() { @@ -582,51 +672,58 @@ func init() { } var fileDescriptor_60112e15fc266719 = []byte{ - // 703 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x96, 0x41, 0x4f, 0xd4, 0x40, - 0x14, 0xc7, 0x77, 0x40, 0x88, 0x8e, 0x10, 0xcd, 0xc8, 0x41, 0x57, 0xa8, 0x52, 0x23, 0x02, 0x86, - 0x19, 0x96, 0x35, 0x8a, 0x27, 0x03, 0x51, 0x88, 0x37, 0x58, 0x8c, 0x07, 0x2f, 0x64, 0x76, 0x19, - 0x4a, 0x63, 0xe9, 0x94, 0xed, 0x2c, 0x81, 0x18, 0x2f, 0x7e, 0x02, 0xa3, 0x9f, 0xc4, 0xc4, 0x83, - 0x9a, 0xc8, 0x99, 0x23, 0x89, 0x17, 0x4f, 0xc6, 0x80, 0x1f, 0xc4, 0x74, 0x66, 0xd6, 0xce, 0x84, - 0x96, 0x16, 0xe1, 0xb4, 0xdb, 0xe9, 0x7b, 0xff, 0xf7, 0xfb, 0xcf, 0xbc, 0xbe, 0x16, 0xde, 0x0d, - 0xe8, 0x36, 0x0d, 0x99, 0x20, 0xc9, 0x2f, 0x61, 0x11, 0x6f, 0x6d, 0xc4, 0x82, 0xb7, 0xa9, 0xc7, - 0xc8, 0x56, 0x87, 0xb5, 0x77, 0x71, 0xd4, 0xe6, 0x82, 0xa3, 0x1b, 0x3a, 0x0c, 0x27, 0xbf, 0xd8, - 0x0c, 0xab, 0x0e, 0x7b, 0x9c, 0x7b, 0x01, 0x23, 0x34, 0xf2, 0x09, 0x0d, 0x43, 0x2e, 0xa8, 0xf0, - 0x79, 0x18, 0xab, 0xc4, 0xea, 0x64, 0x8b, 0xc7, 0x9b, 0x3c, 0x26, 0x4d, 0x1a, 0x6b, 0x45, 0xb2, - 0x5d, 0x6b, 0x32, 0x41, 0x6b, 0x24, 0xa2, 0x9e, 0x1f, 0xca, 0x60, 0x1d, 0x3b, 0x96, 0xcf, 0x12, - 0xd1, 0x36, 0xdd, 0xec, 0x6a, 0x4e, 0xe5, 0xc7, 0xc5, 0x82, 0xbe, 0x66, 0xab, 0xfa, 0xaa, 0x38, - 0x5c, 0x5e, 0xac, 0xae, 0x31, 0x41, 0xfd, 0xa0, 0xab, 0x8e, 0xf3, 0xc3, 0xd7, 0xfd, 0x1d, 0x2a, - 0xd8, 0xda, 0xaa, 0x45, 0xe3, 0x98, 0x0e, 0xbb, 0xde, 0x5a, 0xdc, 0xef, 0xba, 0x1a, 0xf2, 0xb8, - 0xc7, 0xe5, 0x5f, 0x92, 0xfc, 0x53, 0xab, 0xee, 0x10, 0x44, 0xcb, 0xc9, 0x6e, 0x2c, 0x49, 0xa9, - 0x06, 0xdb, 0xea, 0xb0, 0x58, 0xb8, 0x2f, 0xe1, 0x35, 0x6b, 0x35, 0x8e, 0x78, 0x18, 0x33, 0xf4, - 0x04, 0xf6, 0xab, 0x92, 0xd7, 0xc1, 0x6d, 0x30, 0x7e, 0x79, 0x66, 0x14, 0xe7, 0x1e, 0x07, 0x56, - 0xa9, 0xf3, 0x17, 0xf6, 0x7f, 0xdd, 0xaa, 0x34, 0x74, 0x9a, 0x5b, 0x87, 0x37, 0xa5, 0xee, 0x22, - 0x13, 0x2b, 0xc9, 0x0e, 0xad, 0xa8, 0x60, 0x5d, 0x16, 0x0d, 0xc1, 0x3e, 0x3f, 0x5c, 0x63, 0x3b, - 0x52, 0xfe, 0x52, 0x43, 0x5d, 0xb8, 0x5b, 0x70, 0x38, 0x3b, 0x49, 0x53, 0x2d, 0xc3, 0x81, 0xd8, - 0x58, 0xd7, 0x6c, 0xf7, 0x4e, 0x60, 0x33, 0x65, 0x34, 0xa1, 0x25, 0xe1, 0x32, 0xcd, 0x39, 0x17, - 0x04, 0x59, 0x9c, 0x0b, 0x10, 0xa6, 0x4d, 0xa3, 0xeb, 0x8d, 0x61, 0xb5, 0xff, 0x38, 0xd9, 0x7f, - 0xac, 0x7a, 0x56, 0x9f, 0x02, 0x5e, 0x4a, 0x73, 0x1b, 0x46, 0xa6, 0xfb, 0x0d, 0x68, 0x6b, 0xc7, - 0xea, 0xe4, 0x5a, 0xeb, 0x3d, 0xa3, 0x35, 0xb4, 0x68, 0xb1, 0xf7, 0xe8, 0xbd, 0x2a, 0x62, 0x57, - 0x3c, 0x16, 0xfc, 0x48, 0x7a, 0x96, 0xcf, 0x12, 0x82, 0xa7, 0xaa, 0x7b, 0xbb, 0x2d, 0x64, 0x9c, - 0x9a, 0x7d, 0x3b, 0xb5, 0x66, 0xae, 0x97, 0x38, 0x35, 0x33, 0xbc, 0x6b, 0xcd, 0x5c, 0x73, 0x1f, - 0xa4, 0x25, 0x17, 0xd4, 0x13, 0x62, 0x75, 0x75, 0x4e, 0x7b, 0x75, 0xe0, 0x48, 0x4e, 0x96, 0x26, - 0x7d, 0x01, 0x07, 0xd7, 0xcd, 0x1b, 0x1a, 0x75, 0xfc, 0x04, 0x54, 0x4b, 0x48, 0xb3, 0xda, 0x22, - 0xee, 0x7a, 0x7a, 0xf4, 0x99, 0xb0, 0xe7, 0xd5, 0x63, 0x7b, 0x40, 0xfb, 0x3b, 0x5e, 0x28, 0xdf, - 0x5f, 0xef, 0x99, 0xfd, 0x9d, 0x5b, 0x9f, 0xcd, 0xec, 0x5d, 0x84, 0x7d, 0xd2, 0x00, 0xfa, 0x00, - 0x60, 0xbf, 0x56, 0x9f, 0x3a, 0x01, 0xee, 0xf8, 0x3c, 0xab, 0xe2, 0xb2, 0xe1, 0xaa, 0xbe, 0x3b, - 0xf1, 0xee, 0xc7, 0x9f, 0x8f, 0x3d, 0x77, 0xd0, 0x28, 0x29, 0x7a, 0x15, 0xa0, 0xaf, 0x00, 0x0e, - 0x98, 0x0f, 0x1d, 0x7a, 0x58, 0x54, 0x2b, 0x7b, 0xf8, 0x55, 0x1f, 0x9d, 0x3a, 0x4f, 0xc3, 0xce, - 0x4a, 0xd8, 0x19, 0x34, 0x4d, 0x4a, 0xbe, 0x8f, 0xc8, 0x1b, 0xd9, 0xf9, 0x6f, 0xd1, 0x67, 0x00, - 0xaf, 0x98, 0x92, 0x73, 0x41, 0x50, 0x8c, 0x9f, 0x3d, 0x13, 0x8b, 0xf1, 0x73, 0x66, 0x9c, 0x3b, - 0x2d, 0xf1, 0x27, 0xd1, 0x78, 0x59, 0x7c, 0xf4, 0x09, 0xd8, 0xb3, 0xa3, 0xd4, 0x96, 0x67, 0xcc, - 0xa8, 0x52, 0x5b, 0x9e, 0x35, 0xbc, 0x4a, 0x31, 0x5b, 0xef, 0x74, 0xf4, 0x1d, 0xc0, 0x41, 0xeb, - 0xa9, 0x41, 0x65, 0x8a, 0x67, 0x4d, 0x86, 0xea, 0xec, 0xe9, 0x13, 0x35, 0xf6, 0x63, 0x89, 0x5d, - 0x47, 0x35, 0x52, 0xf6, 0xdb, 0xe2, 0x5f, 0xab, 0x7c, 0x01, 0xf0, 0xaa, 0x25, 0x9a, 0xf4, 0x4a, - 0x99, 0x33, 0xff, 0x3f, 0x0b, 0x79, 0xc3, 0xca, 0xad, 0x49, 0x0b, 0xf7, 0xd1, 0x44, 0x69, 0x0b, - 0xf3, 0xcf, 0xf7, 0x0f, 0x1d, 0x70, 0x70, 0xe8, 0x80, 0xdf, 0x87, 0x0e, 0x78, 0x7f, 0xe4, 0x54, - 0x0e, 0x8e, 0x9c, 0xca, 0xcf, 0x23, 0xa7, 0xf2, 0x8a, 0x78, 0xbe, 0xd8, 0xe8, 0x34, 0x71, 0x8b, - 0x6f, 0xda, 0x72, 0xdb, 0x75, 0xb2, 0x63, 0x6b, 0x8a, 0xdd, 0x88, 0xc5, 0xcd, 0x7e, 0xf9, 0xd1, - 0x54, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xdb, 0x27, 0x7e, 0x6a, 0xae, 0x0a, 0x00, 0x00, + // 807 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x96, 0xcd, 0x4f, 0x13, 0x4d, + 0x1c, 0xc7, 0x3b, 0xf0, 0x40, 0x78, 0xe6, 0x81, 0x3c, 0x64, 0x1e, 0x0e, 0x8f, 0x15, 0xaa, 0xac, + 0x11, 0x79, 0x09, 0x3b, 0x94, 0x1a, 0x01, 0x2f, 0x04, 0x82, 0x10, 0x0f, 0x24, 0x50, 0x8c, 0x07, + 0x2f, 0xcd, 0xb4, 0x1d, 0xca, 0xc6, 0x76, 0xa7, 0x74, 0xa7, 0x0d, 0x84, 0x70, 0xf1, 0xe2, 0xd5, + 0xe8, 0x5f, 0x62, 0xe2, 0x41, 0x4d, 0xf4, 0x68, 0x38, 0x92, 0x78, 0xf1, 0x64, 0x0c, 0xf8, 0x87, + 0x98, 0x9d, 0xfd, 0x2d, 0xdd, 0xb1, 0xbb, 0xdd, 0x45, 0x38, 0xb5, 0x3b, 0xfd, 0xbd, 0x7c, 0x7e, + 0x2f, 0xfb, 0xed, 0xe0, 0xbb, 0x55, 0xd6, 0x62, 0x36, 0x97, 0xd4, 0xfd, 0xa4, 0xbc, 0x2e, 0x4a, + 0x7b, 0x8e, 0x14, 0x0d, 0x56, 0xe1, 0x74, 0xbf, 0xc9, 0x1b, 0x87, 0x66, 0xbd, 0x21, 0xa4, 0x20, + 0x37, 0xc0, 0xcc, 0x74, 0x3f, 0xcd, 0xa0, 0x59, 0x7a, 0xb4, 0x22, 0x44, 0xa5, 0xca, 0x29, 0xab, + 0x5b, 0x94, 0xd9, 0xb6, 0x90, 0x4c, 0x5a, 0xc2, 0x76, 0x3c, 0xc7, 0xf4, 0x74, 0x49, 0x38, 0x35, + 0xe1, 0xd0, 0x22, 0x73, 0x20, 0x22, 0x6d, 0x65, 0x8b, 0x5c, 0xb2, 0x2c, 0xad, 0xb3, 0x8a, 0x65, + 0x2b, 0x63, 0xb0, 0x9d, 0x88, 0x66, 0xa9, 0xb3, 0x06, 0xab, 0xf9, 0x31, 0x67, 0xa3, 0xed, 0x1c, + 0xc9, 0x9e, 0xf3, 0x02, 0x3c, 0xc5, 0x9b, 0xab, 0x87, 0x42, 0x99, 0x4b, 0x66, 0x55, 0xfd, 0xe8, + 0x66, 0xb4, 0xf9, 0xae, 0x75, 0xc0, 0x24, 0x2f, 0x17, 0x34, 0x9a, 0x6c, 0x17, 0xea, 0x86, 0x68, + 0x59, 0x65, 0xde, 0x28, 0xd4, 0xb8, 0x64, 0x65, 0x26, 0x19, 0xb8, 0x64, 0x82, 0x4d, 0xf1, 0xdb, + 0x51, 0x12, 0x96, 0xdf, 0x88, 0x91, 0x8a, 0xa8, 0x08, 0xf5, 0x95, 0xba, 0xdf, 0xbc, 0x53, 0x63, + 0x04, 0x93, 0x6d, 0xb7, 0x81, 0x5b, 0x2a, 0x7b, 0x9e, 0xef, 0x37, 0xb9, 0x23, 0x8d, 0xa7, 0xf8, + 0x3f, 0xed, 0xd4, 0xa9, 0x0b, 0xdb, 0xe1, 0x64, 0x19, 0xf7, 0x7b, 0x94, 0xff, 0xa3, 0xdb, 0x68, + 0xf2, 0x9f, 0xf9, 0x71, 0x33, 0x72, 0x82, 0xa6, 0xe7, 0xba, 0xfa, 0xd7, 0xc9, 0xf7, 0x5b, 0xa9, + 0x3c, 0xb8, 0x19, 0x39, 0x7c, 0x53, 0xc5, 0xdd, 0xe0, 0x72, 0xc7, 0x6d, 0xea, 0x8e, 0x67, 0x0c, + 0x69, 0xc9, 0x08, 0xee, 0xb3, 0xec, 0x32, 0x3f, 0x50, 0xe1, 0xff, 0xce, 0x7b, 0x0f, 0xc6, 0x3e, + 0x1e, 0x0d, 0x77, 0x02, 0xaa, 0x6d, 0x3c, 0xe8, 0x04, 0xce, 0x81, 0xed, 0x5e, 0x17, 0xb6, 0x60, + 0x18, 0x20, 0xd4, 0x42, 0x18, 0x1c, 0x38, 0x57, 0xaa, 0xd5, 0x30, 0xce, 0x75, 0x8c, 0xdb, 0x7b, + 0x06, 0xf9, 0x26, 0x4c, 0xaf, 0xff, 0xa6, 0xdb, 0x7f, 0xd3, 0x5b, 0x73, 0x98, 0x82, 0xb9, 0xd5, + 0xf6, 0xcd, 0x07, 0x3c, 0x8d, 0x8f, 0x08, 0x4a, 0xeb, 0xc8, 0x13, 0x59, 0x5a, 0xef, 0x15, 0x4b, + 0x23, 0x1b, 0x1a, 0x7b, 0x0f, 0xf4, 0x2a, 0x8e, 0xdd, 0xe3, 0xd1, 0xe0, 0xc7, 0xda, 0xb3, 0x7c, + 0xe4, 0x12, 0xac, 0x79, 0x0b, 0xef, 0xaf, 0x50, 0x60, 0x6a, 0xfa, 0xcf, 0xed, 0xd2, 0x82, 0xe7, + 0x09, 0xa6, 0x16, 0x34, 0xf7, 0x4b, 0x0b, 0x9e, 0x19, 0xf7, 0xdb, 0x29, 0xd7, 0xbd, 0x97, 0x4a, + 0xdb, 0xea, 0x88, 0xf5, 0x6a, 0xe2, 0xb1, 0x08, 0x2f, 0x20, 0x7d, 0x82, 0x87, 0x76, 0x83, 0x3f, + 0x00, 0xea, 0x64, 0x17, 0x54, 0x2d, 0x10, 0xb0, 0xea, 0x41, 0x8c, 0xdd, 0xf6, 0xe8, 0x43, 0x61, + 0xaf, 0x6b, 0xc7, 0x3e, 0x23, 0xa8, 0xaf, 0x33, 0x51, 0x74, 0x7d, 0xbd, 0x57, 0xae, 0xef, 0xfa, + 0xf6, 0xec, 0x21, 0x34, 0x6a, 0x0b, 0x74, 0x6f, 0x93, 0x4b, 0xb6, 0xc6, 0x24, 0xf3, 0x1b, 0x95, + 0xc6, 0x03, 0xbe, 0x24, 0xc2, 0x60, 0x2f, 0x9e, 0x0d, 0x1b, 0x6a, 0xef, 0xf4, 0x85, 0xda, 0x37, + 0xf1, 0x80, 0x7f, 0x06, 0x65, 0xcf, 0x74, 0xd3, 0xb4, 0x40, 0x18, 0x57, 0x79, 0xa1, 0xf2, 0x8b, + 0x10, 0xf3, 0x2f, 0x31, 0xee, 0x53, 0x09, 0xc9, 0x6b, 0x84, 0xfb, 0xa1, 0x13, 0xb3, 0x5d, 0x22, + 0x76, 0x6a, 0x6f, 0xda, 0x4c, 0x6a, 0xee, 0x95, 0x60, 0x4c, 0xbd, 0xf8, 0xfa, 0xf3, 0x4d, 0xcf, + 0x1d, 0x32, 0x4e, 0xe3, 0xfe, 0xe9, 0xc8, 0x07, 0x84, 0x07, 0x83, 0x02, 0x41, 0x1e, 0xc4, 0xe5, + 0x0a, 0x17, 0xea, 0xf4, 0xc2, 0xa5, 0xfd, 0x00, 0x76, 0x51, 0xc1, 0xce, 0x93, 0x39, 0x9a, 0xf0, + 0xef, 0x96, 0x1e, 0xa9, 0xb7, 0xf4, 0x98, 0xbc, 0x43, 0xf8, 0xdf, 0x60, 0xc8, 0x95, 0x6a, 0x35, + 0x1e, 0x3f, 0x5c, 0xbf, 0xe3, 0xf1, 0x23, 0xf4, 0xd8, 0x98, 0x53, 0xf8, 0xd3, 0x64, 0x32, 0x29, + 0x3e, 0x79, 0x8b, 0x74, 0x9d, 0x4b, 0xd4, 0xf2, 0x10, 0x3d, 0x4d, 0xd4, 0xf2, 0x30, 0xa1, 0x4d, + 0xc4, 0xac, 0x5d, 0x59, 0xc8, 0x27, 0x84, 0x87, 0xb4, 0x37, 0x9c, 0x24, 0x49, 0x1e, 0xa6, 0x62, + 0xe9, 0xc5, 0xcb, 0x3b, 0x02, 0xf6, 0x92, 0xc2, 0xce, 0x91, 0x2c, 0x4d, 0x7a, 0x75, 0xba, 0x58, + 0x95, 0xf7, 0x08, 0x0f, 0x6b, 0x41, 0xdd, 0x5d, 0x49, 0x32, 0xf3, 0x3f, 0x2b, 0x21, 0x4a, 0x58, + 0x8d, 0xac, 0x2a, 0x61, 0x86, 0x4c, 0x25, 0x2e, 0x81, 0x7c, 0x41, 0x78, 0xf8, 0x77, 0xb1, 0x8a, + 0x47, 0x8f, 0x90, 0xc6, 0x78, 0xf4, 0x28, 0x5d, 0x34, 0x96, 0x15, 0xfa, 0x12, 0x59, 0xa0, 0x97, + 0xb8, 0x88, 0xd2, 0x23, 0xff, 0xe8, 0x78, 0xf5, 0xf1, 0xc9, 0x59, 0x06, 0x9d, 0x9e, 0x65, 0xd0, + 0x8f, 0xb3, 0x0c, 0x7a, 0x75, 0x9e, 0x49, 0x9d, 0x9e, 0x67, 0x52, 0xdf, 0xce, 0x33, 0xa9, 0x67, + 0xb4, 0x62, 0xc9, 0xbd, 0x66, 0xd1, 0x2c, 0x89, 0x9a, 0x1e, 0xbc, 0x95, 0xa3, 0x07, 0x7a, 0x06, + 0x79, 0x58, 0xe7, 0x4e, 0xb1, 0x5f, 0xdd, 0x54, 0x73, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xdb, + 0xdb, 0xbf, 0x35, 0x56, 0x0c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -653,6 +750,8 @@ type QueryClient interface { FixatedParams(ctx context.Context, in *QueryGetFixatedParamsRequest, opts ...grpc.CallOption) (*QueryGetFixatedParamsResponse, error) // Queries a list of FixatedParams items. FixatedParamsAll(ctx context.Context, in *QueryAllFixatedParamsRequest, opts ...grpc.CallOption) (*QueryAllFixatedParamsResponse, error) + // Queries provider metadata. + ProviderMetaData(ctx context.Context, in *QueryProviderMetaDataRequest, opts ...grpc.CallOption) (*QueryProviderMetaDataResponse, error) } type queryClient struct { @@ -717,6 +816,15 @@ func (c *queryClient) FixatedParamsAll(ctx context.Context, in *QueryAllFixatedP return out, nil } +func (c *queryClient) ProviderMetaData(ctx context.Context, in *QueryProviderMetaDataRequest, opts ...grpc.CallOption) (*QueryProviderMetaDataResponse, error) { + out := new(QueryProviderMetaDataResponse) + err := c.cc.Invoke(ctx, "/lavanet.lava.epochstorage.Query/ProviderMetaData", 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. @@ -731,6 +839,8 @@ type QueryServer interface { FixatedParams(context.Context, *QueryGetFixatedParamsRequest) (*QueryGetFixatedParamsResponse, error) // Queries a list of FixatedParams items. FixatedParamsAll(context.Context, *QueryAllFixatedParamsRequest) (*QueryAllFixatedParamsResponse, error) + // Queries provider metadata. + ProviderMetaData(context.Context, *QueryProviderMetaDataRequest) (*QueryProviderMetaDataResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -755,6 +865,9 @@ func (*UnimplementedQueryServer) FixatedParams(ctx context.Context, req *QueryGe func (*UnimplementedQueryServer) FixatedParamsAll(ctx context.Context, req *QueryAllFixatedParamsRequest) (*QueryAllFixatedParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method FixatedParamsAll not implemented") } +func (*UnimplementedQueryServer) ProviderMetaData(ctx context.Context, req *QueryProviderMetaDataRequest) (*QueryProviderMetaDataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProviderMetaData not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -868,6 +981,24 @@ func _Query_FixatedParamsAll_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Query_ProviderMetaData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryProviderMetaDataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ProviderMetaData(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/lavanet.lava.epochstorage.Query/ProviderMetaData", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ProviderMetaData(ctx, req.(*QueryProviderMetaDataRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "lavanet.lava.epochstorage.Query", HandlerType: (*QueryServer)(nil), @@ -896,6 +1027,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "FixatedParamsAll", Handler: _Query_FixatedParamsAll_Handler, }, + { + MethodName: "ProviderMetaData", + Handler: _Query_ProviderMetaData_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "lavanet/lava/epochstorage/query.proto", @@ -1307,6 +1442,73 @@ func (m *QueryAllFixatedParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *QueryProviderMetaDataRequest) 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 *QueryProviderMetaDataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProviderMetaDataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Provider) > 0 { + i -= len(m.Provider) + copy(dAtA[i:], m.Provider) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Provider))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryProviderMetaDataResponse) 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 *QueryProviderMetaDataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProviderMetaDataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MetaData) > 0 { + for iNdEx := len(m.MetaData) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MetaData[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 @@ -1470,6 +1672,34 @@ func (m *QueryAllFixatedParamsResponse) Size() (n int) { return n } +func (m *QueryProviderMetaDataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Provider) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryProviderMetaDataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.MetaData) > 0 { + for _, e := range m.MetaData { + 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 } @@ -2484,6 +2714,172 @@ func (m *QueryAllFixatedParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryProviderMetaDataRequest) 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: QueryProviderMetaDataRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProviderMetaDataRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Provider", 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.Provider = 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 *QueryProviderMetaDataResponse) 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: QueryProviderMetaDataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProviderMetaDataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MetaData", 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.MetaData = append(m.MetaData, ProviderMetadata{}) + if err := m.MetaData[len(m.MetaData)-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/epochstorage/types/query.pb.gw.go b/x/epochstorage/types/query.pb.gw.go index 66cc24ed93..29270cc94c 100644 --- a/x/epochstorage/types/query.pb.gw.go +++ b/x/epochstorage/types/query.pb.gw.go @@ -249,6 +249,60 @@ func local_request_Query_FixatedParamsAll_0(ctx context.Context, marshaler runti } +func request_Query_ProviderMetaData_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProviderMetaDataRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["provider"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "provider") + } + + protoReq.Provider, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "provider", err) + } + + msg, err := client.ProviderMetaData(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ProviderMetaData_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProviderMetaDataRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["provider"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "provider") + } + + protoReq.Provider, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "provider", err) + } + + msg, err := server.ProviderMetaData(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. @@ -393,6 +447,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_ProviderMetaData_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_ProviderMetaData_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_ProviderMetaData_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -554,6 +631,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_ProviderMetaData_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_ProviderMetaData_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_ProviderMetaData_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -569,6 +666,8 @@ var ( pattern_Query_FixatedParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"lavanet", "lava", "epochstorage", "fixated_params", "index"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_FixatedParamsAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"lavanet", "lava", "epochstorage", "fixated_params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_ProviderMetaData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"lavanet", "lava", "epochstorage", "provider_metadata", "provider"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -583,4 +682,6 @@ var ( forward_Query_FixatedParams_0 = runtime.ForwardResponseMessage forward_Query_FixatedParamsAll_0 = runtime.ForwardResponseMessage + + forward_Query_ProviderMetaData_0 = runtime.ForwardResponseMessage ) diff --git a/x/epochstorage/types/stake_entries.go b/x/epochstorage/types/stake_entries.go index a1a8c5cd81..3fb2470bc7 100644 --- a/x/epochstorage/types/stake_entries.go +++ b/x/epochstorage/types/stake_entries.go @@ -17,6 +17,7 @@ var ( EpochChainIdProviderIndexesPrefix = collections.NewPrefix([]byte("EpochChainIdProviderIndexes/")) ChainIdVaultIndexesPrefix = collections.NewPrefix([]byte("ChainIdVaultIndexes/")) EpochHashesPrefix = collections.NewPrefix([]byte("EpochHash/")) + ProviderMetaDataPrefix = collections.NewPrefix([]byte("ProviderMetaData/")) ) // EpochChainIdProviderIndexes defines a secondary unique index for the keeper's stakeEntries indexed map diff --git a/x/epochstorage/types/stake_entry.pb.go b/x/epochstorage/types/stake_entry.pb.go index a5753318b7..74eeb33f9b 100644 --- a/x/epochstorage/types/stake_entry.pb.go +++ b/x/epochstorage/types/stake_entry.pb.go @@ -36,7 +36,6 @@ type StakeEntry struct { Moniker string `protobuf:"bytes,8,opt,name=moniker,proto3" json:"moniker,omitempty"` DelegateTotal types.Coin `protobuf:"bytes,9,opt,name=delegate_total,json=delegateTotal,proto3" json:"delegate_total"` DelegateCommission uint64 `protobuf:"varint,11,opt,name=delegate_commission,json=delegateCommission,proto3" json:"delegate_commission,omitempty"` - LastChange uint64 `protobuf:"varint,12,opt,name=last_change,json=lastChange,proto3" json:"last_change,omitempty"` BlockReport *BlockReport `protobuf:"bytes,13,opt,name=block_report,json=blockReport,proto3" json:"block_report,omitempty"` Vault string `protobuf:"bytes,14,opt,name=vault,proto3" json:"vault,omitempty"` Description types1.Description `protobuf:"bytes,15,opt,name=description,proto3" json:"description"` @@ -140,13 +139,6 @@ func (m *StakeEntry) GetDelegateCommission() uint64 { return 0 } -func (m *StakeEntry) GetLastChange() uint64 { - if m != nil { - return m.LastChange - } - return 0 -} - func (m *StakeEntry) GetBlockReport() *BlockReport { if m != nil { return m.BlockReport @@ -247,45 +239,44 @@ func init() { } var fileDescriptor_df6302d6b53c056e = []byte{ - // 597 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xbd, 0x4e, 0xdd, 0x30, - 0x18, 0xbd, 0x81, 0x5c, 0xb8, 0xd7, 0x01, 0x0a, 0x86, 0xc1, 0x30, 0x84, 0x14, 0xaa, 0x2a, 0x6a, - 0xa5, 0x58, 0x80, 0xfa, 0x00, 0xbd, 0x14, 0x2a, 0x98, 0xaa, 0x94, 0xa9, 0x4b, 0xe4, 0x24, 0x56, - 0xae, 0x4b, 0x62, 0x47, 0xb1, 0xb9, 0x2a, 0x6f, 0xd1, 0xc7, 0xe8, 0xd8, 0xbd, 0x2f, 0xc0, 0xc8, - 0xd8, 0xa9, 0xaa, 0x60, 0xe8, 0x6b, 0x54, 0xb6, 0x93, 0xfb, 0x33, 0x50, 0x75, 0x49, 0x7c, 0xbe, - 0x73, 0xfc, 0xf9, 0x3b, 0x47, 0x36, 0x78, 0x5d, 0x92, 0x09, 0xe1, 0x54, 0x61, 0xfd, 0xc7, 0xb4, - 0x16, 0xd9, 0x58, 0x2a, 0xd1, 0x90, 0x82, 0x62, 0xa9, 0xc8, 0x35, 0x4d, 0x28, 0x57, 0xcd, 0x6d, - 0x54, 0x37, 0x42, 0x09, 0xb8, 0xdb, 0x8a, 0x23, 0xfd, 0x8f, 0xe6, 0xc5, 0x7b, 0xe1, 0xd3, 0x7d, - 0x28, 0xcf, 0x6b, 0xc1, 0xb8, 0xb2, 0x4d, 0xf6, 0x76, 0x0a, 0x51, 0x08, 0xb3, 0xc4, 0x7a, 0xd5, - 0x56, 0xfd, 0x4c, 0xc8, 0x4a, 0x48, 0x9c, 0x12, 0x49, 0xf1, 0xe4, 0x28, 0xa5, 0x8a, 0x1c, 0xe1, - 0x4c, 0x30, 0xde, 0xf2, 0x2f, 0x5a, 0x5e, 0x0f, 0xc5, 0x78, 0x31, 0x95, 0xb4, 0xb8, 0x55, 0x6d, - 0x91, 0x8a, 0x71, 0x81, 0xcd, 0xd7, 0x96, 0x0e, 0x7e, 0xf4, 0x01, 0xf8, 0xa8, 0x9d, 0x9c, 0x69, - 0x23, 0xf0, 0x0d, 0xe8, 0x1b, 0x5f, 0xc8, 0x09, 0x9c, 0xd0, 0x3b, 0xde, 0x8d, 0x6c, 0xdf, 0x48, - 0x9f, 0x1b, 0xb5, 0x4d, 0xa3, 0x53, 0xc1, 0xf8, 0xc8, 0xbd, 0xfb, 0xb5, 0xdf, 0x8b, 0xad, 0x1a, - 0x22, 0xb0, 0x4a, 0xf2, 0xbc, 0xa1, 0x52, 0xa2, 0xa5, 0xc0, 0x09, 0x87, 0x71, 0x07, 0x61, 0x04, - 0xb6, 0x6d, 0x50, 0xa4, 0xae, 0x4b, 0x46, 0xf3, 0x24, 0x2d, 0x45, 0x76, 0x8d, 0x96, 0x03, 0x27, - 0x74, 0xe3, 0x2d, 0x43, 0xbd, 0xb5, 0xcc, 0x48, 0x13, 0xf0, 0x3d, 0x18, 0x76, 0x81, 0x48, 0xe4, - 0x06, 0xcb, 0xa1, 0x77, 0x7c, 0x18, 0x3d, 0x99, 0x6b, 0x74, 0xd6, 0x6a, 0xdb, 0x71, 0x66, 0x7b, - 0x61, 0x00, 0xbc, 0x82, 0x8a, 0x52, 0x64, 0x44, 0x31, 0xc1, 0x51, 0x3f, 0x70, 0xc2, 0x7e, 0x3c, - 0x5f, 0x82, 0x3b, 0xa0, 0x9f, 0x8d, 0x09, 0xe3, 0x68, 0xc5, 0x8c, 0x6c, 0x81, 0xb6, 0x52, 0x09, - 0xce, 0xae, 0x69, 0x83, 0x06, 0xd6, 0x4a, 0x0b, 0xe1, 0x39, 0xd8, 0xc8, 0x69, 0x49, 0x0b, 0xa2, - 0x68, 0xa2, 0x84, 0x22, 0x25, 0x1a, 0xfe, 0x5f, 0x48, 0xeb, 0xdd, 0xb6, 0x2b, 0xbd, 0x0b, 0x62, - 0xb0, 0x3d, 0xed, 0x93, 0x89, 0xaa, 0x62, 0x52, 0xea, 0x09, 0x3d, 0x13, 0x09, 0xec, 0xa8, 0xd3, - 0x29, 0x03, 0xf7, 0x81, 0x57, 0x12, 0xa9, 0x92, 0x6c, 0x4c, 0x78, 0x41, 0xd1, 0x9a, 0x11, 0x02, - 0x5d, 0x3a, 0x35, 0x15, 0x78, 0x01, 0xd6, 0x4c, 0xac, 0x49, 0x43, 0x6b, 0xd1, 0x28, 0xb4, 0x6e, - 0xe6, 0x7a, 0xf9, 0x8f, 0xdc, 0x4c, 0xd8, 0xb1, 0x51, 0xc7, 0x5e, 0x3a, 0x03, 0x3a, 0x94, 0x09, - 0xb9, 0x29, 0x15, 0xda, 0xb0, 0xa1, 0x18, 0x00, 0x3f, 0x00, 0x2f, 0xa7, 0x32, 0x6b, 0x58, 0x6d, - 0xc2, 0x7c, 0x66, 0xfa, 0x1f, 0x76, 0xbe, 0xbb, 0x4b, 0xd6, 0x59, 0x7f, 0x37, 0x93, 0x8e, 0x86, - 0x3a, 0x81, 0x6f, 0x7f, 0xbe, 0xbf, 0x72, 0xe2, 0xf9, 0x16, 0xfa, 0x9c, 0xcf, 0x84, 0x95, 0x12, - 0x6d, 0x1a, 0x37, 0x16, 0xc0, 0x03, 0xb0, 0xae, 0x17, 0x09, 0xe5, 0x79, 0xa2, 0x58, 0x45, 0xd1, - 0x56, 0xe0, 0x84, 0xcb, 0xb1, 0xa7, 0x8b, 0x67, 0x3c, 0xbf, 0x62, 0x15, 0xbd, 0x74, 0x07, 0xab, - 0x9b, 0x83, 0x4b, 0x77, 0x00, 0x36, 0xbd, 0x83, 0x73, 0xe0, 0x8d, 0x16, 0x87, 0x37, 0x2e, 0xcd, - 0xed, 0x75, 0x63, 0x0b, 0xe0, 0x73, 0xb0, 0x56, 0x12, 0x45, 0xa5, 0x6a, 0xef, 0xde, 0x92, 0x21, - 0x3d, 0x5b, 0x33, 0xdb, 0x47, 0x17, 0x77, 0x0f, 0xbe, 0x73, 0xff, 0xe0, 0x3b, 0xbf, 0x1f, 0x7c, - 0xe7, 0xeb, 0xa3, 0xdf, 0xbb, 0x7f, 0xf4, 0x7b, 0x3f, 0x1f, 0xfd, 0xde, 0x27, 0x5c, 0x30, 0x35, - 0xbe, 0x49, 0xa3, 0x4c, 0x54, 0x78, 0xe1, 0x0d, 0x4f, 0x4e, 0xf0, 0x97, 0xc5, 0x87, 0xac, 0x6e, - 0x6b, 0x2a, 0xd3, 0x15, 0xf3, 0xae, 0x4e, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x28, 0x02, 0x10, - 0xfc, 0x3a, 0x04, 0x00, 0x00, + // 585 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xcd, 0x4e, 0xdc, 0x3c, + 0x14, 0x9d, 0x40, 0x06, 0x66, 0x1c, 0x86, 0x6f, 0x30, 0x2c, 0x0c, 0x8b, 0x7c, 0x29, 0x54, 0x55, + 0xd4, 0x4a, 0xb1, 0x00, 0xf5, 0x01, 0x3a, 0x14, 0x2a, 0x58, 0x55, 0x29, 0xab, 0x6e, 0x22, 0x27, + 0xb1, 0x82, 0x4b, 0x62, 0x47, 0xb1, 0x19, 0x95, 0xb7, 0xe8, 0x23, 0x74, 0xd9, 0x65, 0x1f, 0x83, + 0x25, 0xcb, 0xae, 0xaa, 0x0a, 0x16, 0x7d, 0x8d, 0xca, 0x76, 0x32, 0x3f, 0x0b, 0xaa, 0x6e, 0x12, + 0x9f, 0x7b, 0x8e, 0xaf, 0xef, 0x39, 0xb2, 0xc1, 0xab, 0x92, 0x4c, 0x09, 0xa7, 0x0a, 0xeb, 0x3f, + 0xa6, 0xb5, 0xc8, 0xae, 0xa4, 0x12, 0x0d, 0x29, 0x28, 0x96, 0x8a, 0x5c, 0xd3, 0x84, 0x72, 0xd5, + 0xdc, 0x46, 0x75, 0x23, 0x94, 0x80, 0xbb, 0xad, 0x38, 0xd2, 0xff, 0x68, 0x51, 0xbc, 0x17, 0x3e, + 0xdd, 0x87, 0xf2, 0xbc, 0x16, 0x8c, 0x2b, 0xdb, 0x64, 0x6f, 0xa7, 0x10, 0x85, 0x30, 0x4b, 0xac, + 0x57, 0x6d, 0xd5, 0xcf, 0x84, 0xac, 0x84, 0xc4, 0x29, 0x91, 0x14, 0x4f, 0x0f, 0x53, 0xaa, 0xc8, + 0x21, 0xce, 0x04, 0xe3, 0x2d, 0xff, 0xbc, 0xe5, 0xf5, 0x50, 0x8c, 0x17, 0x33, 0x49, 0x8b, 0x5b, + 0xd5, 0x16, 0xa9, 0x18, 0x17, 0xd8, 0x7c, 0x6d, 0x69, 0xff, 0x6b, 0x1f, 0x80, 0x0f, 0xda, 0xc9, + 0xa9, 0x36, 0x02, 0x5f, 0x83, 0xbe, 0xf1, 0x85, 0x9c, 0xc0, 0x09, 0xbd, 0xa3, 0xdd, 0xc8, 0xf6, + 0x8d, 0xf4, 0xb9, 0x51, 0xdb, 0x34, 0x3a, 0x11, 0x8c, 0x4f, 0xdc, 0xbb, 0x9f, 0xff, 0xf7, 0x62, + 0xab, 0x86, 0x08, 0xac, 0x93, 0x3c, 0x6f, 0xa8, 0x94, 0x68, 0x25, 0x70, 0xc2, 0x61, 0xdc, 0x41, + 0x18, 0x81, 0x6d, 0x1b, 0x14, 0xa9, 0xeb, 0x92, 0xd1, 0x3c, 0x49, 0x4b, 0x91, 0x5d, 0xa3, 0xd5, + 0xc0, 0x09, 0xdd, 0x78, 0xcb, 0x50, 0x6f, 0x2c, 0x33, 0xd1, 0x04, 0x7c, 0x07, 0x86, 0x5d, 0x20, + 0x12, 0xb9, 0xc1, 0x6a, 0xe8, 0x1d, 0x1d, 0x44, 0x4f, 0xe6, 0x1a, 0x9d, 0xb6, 0xda, 0x76, 0x9c, + 0xf9, 0x5e, 0x18, 0x00, 0xaf, 0xa0, 0xa2, 0x14, 0x19, 0x51, 0x4c, 0x70, 0xd4, 0x0f, 0x9c, 0xb0, + 0x1f, 0x2f, 0x96, 0xe0, 0x0e, 0xe8, 0x67, 0x57, 0x84, 0x71, 0xb4, 0x66, 0x46, 0xb6, 0x40, 0x5b, + 0xa9, 0x04, 0x67, 0xd7, 0xb4, 0x41, 0x03, 0x6b, 0xa5, 0x85, 0xf0, 0x0c, 0x6c, 0xe6, 0xb4, 0xa4, + 0x05, 0x51, 0x34, 0x51, 0x42, 0x91, 0x12, 0x0d, 0xff, 0x2d, 0xa4, 0x51, 0xb7, 0xed, 0x52, 0xef, + 0x82, 0x18, 0x6c, 0xcf, 0xfa, 0x64, 0xa2, 0xaa, 0x98, 0x94, 0x7a, 0x42, 0xcf, 0x44, 0x02, 0x3b, + 0xea, 0x64, 0xc6, 0xc0, 0x73, 0xb0, 0x61, 0x52, 0x4b, 0x1a, 0x5a, 0x8b, 0x46, 0xa1, 0x91, 0x39, + 0xf6, 0xc5, 0x5f, 0x62, 0x31, 0x59, 0xc6, 0x46, 0x1d, 0x7b, 0xe9, 0x1c, 0x68, 0xcf, 0x53, 0x72, + 0x53, 0x2a, 0xb4, 0x69, 0x3d, 0x1b, 0x00, 0xdf, 0x03, 0x2f, 0xa7, 0x32, 0x6b, 0x58, 0x6d, 0xb2, + 0xfa, 0xcf, 0xf4, 0x3f, 0xe8, 0x6c, 0x75, 0x77, 0xa8, 0x73, 0xf6, 0x76, 0x2e, 0x9d, 0x0c, 0xb5, + 0xc1, 0x6f, 0xbf, 0xbf, 0xbf, 0x74, 0xe2, 0xc5, 0x16, 0xfa, 0x9c, 0x4f, 0x84, 0x95, 0x12, 0x8d, + 0x8d, 0x2b, 0x0b, 0xe0, 0x3e, 0x18, 0xe9, 0x45, 0x42, 0x79, 0x9e, 0x28, 0x56, 0x51, 0xb4, 0x15, + 0x38, 0xe1, 0x6a, 0xec, 0xe9, 0xe2, 0x29, 0xcf, 0x2f, 0x59, 0x45, 0x2f, 0xdc, 0xc1, 0xfa, 0x78, + 0x70, 0xe1, 0x0e, 0xc0, 0xd8, 0xbb, 0x70, 0x07, 0x1b, 0xe3, 0xd1, 0xfe, 0x19, 0xf0, 0x26, 0xcb, + 0x16, 0x8c, 0x57, 0x73, 0x45, 0xdd, 0xd8, 0x02, 0xf8, 0x0c, 0x6c, 0x94, 0x44, 0x51, 0xa9, 0xda, + 0x0b, 0xb6, 0x62, 0x48, 0xcf, 0xd6, 0xcc, 0xf6, 0xc9, 0xf9, 0xdd, 0x83, 0xef, 0xdc, 0x3f, 0xf8, + 0xce, 0xaf, 0x07, 0xdf, 0xf9, 0xf2, 0xe8, 0xf7, 0xee, 0x1f, 0xfd, 0xde, 0x8f, 0x47, 0xbf, 0xf7, + 0x11, 0x17, 0x4c, 0x5d, 0xdd, 0xa4, 0x51, 0x26, 0x2a, 0xbc, 0xf4, 0x50, 0xa7, 0xc7, 0xf8, 0xf3, + 0xf2, 0x6b, 0x55, 0xb7, 0x35, 0x95, 0xe9, 0x9a, 0x79, 0x3c, 0xc7, 0x7f, 0x02, 0x00, 0x00, 0xff, + 0xff, 0xa6, 0xec, 0xe6, 0x19, 0x1f, 0x04, 0x00, 0x00, } func (m *StakeEntry) Marshal() (dAtA []byte, err error) { @@ -351,11 +342,6 @@ func (m *StakeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x6a } - if m.LastChange != 0 { - i = encodeVarintStakeEntry(dAtA, i, uint64(m.LastChange)) - i-- - dAtA[i] = 0x60 - } if m.DelegateCommission != 0 { i = encodeVarintStakeEntry(dAtA, i, uint64(m.DelegateCommission)) i-- @@ -510,9 +496,6 @@ func (m *StakeEntry) Size() (n int) { if m.DelegateCommission != 0 { n += 1 + sovStakeEntry(uint64(m.DelegateCommission)) } - if m.LastChange != 0 { - n += 1 + sovStakeEntry(uint64(m.LastChange)) - } if m.BlockReport != nil { l = m.BlockReport.Size() n += 1 + l + sovStakeEntry(uint64(l)) @@ -835,25 +818,6 @@ func (m *StakeEntry) Unmarshal(dAtA []byte) error { break } } - case 12: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field LastChange", wireType) - } - m.LastChange = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStakeEntry - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.LastChange |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } case 13: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field BlockReport", wireType) diff --git a/x/pairing/README.md b/x/pairing/README.md index 593aaad6b4..a89b0eda88 100644 --- a/x/pairing/README.md +++ b/x/pairing/README.md @@ -90,6 +90,16 @@ A consumer sends requests to a provider's endpoint to communicate with them. The Stake entries' storage is managed by the epochstorage module. For more details, see its README. +Providers `DelegateTotal` is the delegators delegations part for this chain and is calculated by as follows: `total_provider_delegations` * `stake` / `total_stake` + +when: + +`stake` is the providers stake on a specific chain + +`total_stake` is the total stake of the provider across all chains + +`total_provider_delegations` is the total delegations for the provider + #### Unstake A provider can unstake and retrieve their coins. When a provider unstakes, they are removed from the pairing list starting from the next epoch. After a specified number of blocks called `UnstakeHoldBlocks` (a parameter of the epochstorage module), the provider is eligible to receive their coins back. @@ -354,6 +364,7 @@ The pairing module supports the following transactions: | `stake-provider` | chain-id (string), amount (Coin), endpoints ([]Endpoint), geolocation (int32), validator (string, optional), --provider-moniker (string) --grant-provider-gas-fees-auth (bool)| stake a provider in a chain with multiple endpoints | | `unfreeze` | chain-ids ([]string) | unfreeze a provider in multiple chains | | `unstake-provider` | chain-ids ([]string), validator (string, optional) | unstake a provider from multiple chains | +| `move-provider-stake` | src-chain dst-chain amount (Coin)| move provider stake amount from one chain to another | Note, the `Coin` type is from Cosmos-SDK (`cosmos.base.v1beta1.Coin`). From the CLI, use `100ulava` to assign a `Coin` argument. The `Endpoint` type defines a provider endpoint. From the CLI, use "my-provider-grpc-addr.com:9090,1" for one endpoint (includes the endpoint's URL+port and the endpoint's geolocation). When it comes to staking-related transactions, the geolocation argument should encompass the geolocations of all the endpoints combined. diff --git a/x/pairing/client/cli/tx.go b/x/pairing/client/cli/tx.go index 4ee4bb6fd2..545f50eb2e 100644 --- a/x/pairing/client/cli/tx.go +++ b/x/pairing/client/cli/tx.go @@ -48,6 +48,8 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdUnfreeze()) cmd.AddCommand(CmdModifyProvider()) cmd.AddCommand(CmdSimulateRelayPayment()) + cmd.AddCommand(CmdMoveProviderStake()) + cmd.AddCommand(CmdDistributeProviderStake()) // this line is used by starport scaffolding # 1 @@ -134,12 +136,10 @@ func NewSubmitUnstakeProposalTxCmd() *cobra.Command { content.ProvidersInfo = []types.ProviderUnstakeInfo{{Provider: providerEntry.Address, ChainId: providerEntry.Chain}} content.DelegatorsSlashing = []types.DelegatorSlashing{} for _, delegator := range delegators.Delegations { - if delegator.ChainID == providerEntry.Chain { - content.DelegatorsSlashing = append(content.DelegatorsSlashing, types.DelegatorSlashing{ - Delegator: delegator.Delegator, - SlashingAmount: sdk.NewCoin(commontypes.TokenDenom, delegator.Amount.Amount.MulRaw(int64(slashfactor)).QuoRaw(100)), - }) - } + content.DelegatorsSlashing = append(content.DelegatorsSlashing, types.DelegatorSlashing{ + Delegator: delegator.Delegator, + SlashingAmount: sdk.NewCoin(commontypes.TokenDenom, delegator.Amount.Amount.MulRaw(int64(slashfactor)).QuoRaw(100)), + }) } } diff --git a/x/pairing/client/cli/tx_distribute_provider_stake.go b/x/pairing/client/cli/tx_distribute_provider_stake.go new file mode 100644 index 0000000000..344af3d3ec --- /dev/null +++ b/x/pairing/client/cli/tx_distribute_provider_stake.go @@ -0,0 +1,164 @@ +package cli + +import ( + "context" + "fmt" + "sort" + "strconv" + "strings" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + commontypes "github.com/lavanet/lava/v3/utils/common/types" + epochstoragetypes "github.com/lavanet/lava/v3/x/epochstorage/types" + "github.com/lavanet/lava/v3/x/pairing/types" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdDistributeProviderStake() *cobra.Command { + cmd := &cobra.Command{ + Use: "distribute-provider-stake chain,%,chain,%", + Short: "redistribute providers stake between all the chains it is staked on.", + Long: `sends batch of movestake tx to redistribute the total stake according to the users input, the total percentages must be exactly 100`, + Example: `lavad tx pairing distribute-provider-stake chain0,33,chain1,33,chain2,34"`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + provider := clientCtx.GetFromAddress().String() + + pairingQuerier := types.NewQueryClient(clientCtx) + ctx := context.Background() + response, err := pairingQuerier.Provider(ctx, &types.QueryProviderRequest{Address: provider}) + if err != nil { + return err + } + + msgs, err := CalculateDistbiruitions(provider, response.StakeEntries, args[0]) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +type data struct { + chain string + original math.Int + percent sdk.Dec + target math.Int + diff math.Int +} + +func CalculateDistbiruitions(provider string, entries []epochstoragetypes.StakeEntry, distributionsArg string) ([]sdk.Msg, error) { + splitedArgs := strings.Split(distributionsArg, ",") + if len(splitedArgs)%2 != 0 { + return nil, fmt.Errorf("args must: chain,percent,chain,percent") + } + + totalStake := sdk.NewCoin(commontypes.TokenDenom, sdk.ZeroInt()) + totalP := sdk.ZeroDec() + distributions := []data{} + for i := 0; i < len(splitedArgs); i += 2 { + p, err := sdk.NewDecFromStr(splitedArgs[i+1]) + if err != nil { + return nil, err + } + for _, e := range entries { + if splitedArgs[i] == e.Chain { + distributions = append(distributions, data{chain: e.Chain, original: e.Stake.Amount, percent: p}) + totalStake = totalStake.Add(e.Stake) + totalP = totalP.Add(p) + } + } + } + + if len(distributions) != len(entries) { + return nil, fmt.Errorf("must specify percentages for all chains the provider is staked on") + } + if !totalP.Equal(sdk.NewDec(100)) { + return nil, fmt.Errorf("total percentages must be 100") + } + + left := totalStake + excesses := []data{} + deficits := []data{} + for i := 0; i < len(distributions); i++ { + if i == len(distributions)-1 { + distributions[i].target = left.Amount + } else { + distributions[i].target = distributions[i].percent.MulInt(totalStake.Amount).QuoInt64(100).RoundInt() + } + left = left.SubAmount(distributions[i].target) + + if distributions[i].original.GT(distributions[i].target) { + distributions[i].diff = distributions[i].original.Sub(distributions[i].target) + excesses = append(excesses, distributions[i]) + } else if distributions[i].original.LT(distributions[i].target) { + distributions[i].diff = distributions[i].target.Sub(distributions[i].original) + deficits = append(deficits, distributions[i]) + } + } + + // Sort excesses and deficits by points, descending order + sort.Slice(excesses, func(i, j int) bool { + return excesses[i].diff.GT(excesses[j].diff) + }) + sort.Slice(deficits, func(i, j int) bool { + return deficits[i].diff.GT(deficits[j].diff) + }) + + // Match excesses and deficits + msgs := []sdk.Msg{} + excessIdx, deficitIdx := 0, 0 + for excessIdx < len(excesses) && deficitIdx < len(deficits) { + // Move the smaller of the excess or deficit + tokensToMove := excesses[excessIdx].diff + if excesses[excessIdx].diff.GT(deficits[deficitIdx].diff) { + tokensToMove = deficits[deficitIdx].diff + } + + msg := types.NewMsgMoveProviderStake(provider, excesses[excessIdx].chain, deficits[deficitIdx].chain, sdk.NewCoin(commontypes.TokenDenom, tokensToMove)) + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + msgs = append(msgs, msg) + excesses[excessIdx].diff = excesses[excessIdx].diff.Sub(tokensToMove) + deficits[deficitIdx].diff = deficits[deficitIdx].diff.Sub(tokensToMove) + + // If an excess or deficit is fully resolved, move to the next one + if excesses[excessIdx].diff.IsZero() { + excessIdx++ + } + if deficits[deficitIdx].diff.IsZero() { + deficitIdx++ + } + } + + for _, item := range deficits { + if !item.diff.IsZero() { + return nil, fmt.Errorf("failed to distribute provider stake") + } + } + + for _, item := range excesses { + if !item.diff.IsZero() { + return nil, fmt.Errorf("failed to distribute provider stake") + } + } + + return msgs, nil +} diff --git a/x/pairing/client/cli/tx_move_provider_stake.go b/x/pairing/client/cli/tx_move_provider_stake.go new file mode 100644 index 0000000000..98b6386d8f --- /dev/null +++ b/x/pairing/client/cli/tx_move_provider_stake.go @@ -0,0 +1,53 @@ +package cli + +import ( + "fmt" + "strconv" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/v3/x/pairing/types" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdMoveProviderStake() *cobra.Command { + cmd := &cobra.Command{ + Use: "move-provider-stake src-chain dst-chain amount", + Short: "moves providers stak from one chain to another", + Long: `moves a provider stake amount from source chain to destination chain that the provider is taked in`, + Example: `required flags: --from alice. + lavad tx pairing move-provider-stake chain0 chain1 100ulava"`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + srcChain := args[0] + dstChain := args[1] + amount, err := sdk.ParseCoinNormalized(args[2]) + if err != nil { + return fmt.Errorf("failed to parse amount: %w", err) + } + + msg := types.NewMsgMoveProviderStake( + clientCtx.GetFromAddress().String(), + srcChain, + dstChain, + amount, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/pairing/handler.go b/x/pairing/handler.go index 9f036f9c2b..a472ebb735 100644 --- a/x/pairing/handler.go +++ b/x/pairing/handler.go @@ -33,6 +33,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler { case *types.MsgUnfreezeProvider: res, err := msgServer.UnfreezeProvider(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgMoveProviderStake: + res, err := msgServer.MoveProviderStake(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) // this line is used by starport scaffolding # 1 default: errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) diff --git a/x/pairing/keeper/cu_tracker_test.go b/x/pairing/keeper/cu_tracker_test.go index cc5454d765..d8f96c501d 100644 --- a/x/pairing/keeper/cu_tracker_test.go +++ b/x/pairing/keeper/cu_tracker_test.go @@ -144,17 +144,17 @@ func TestTrackedCuWithDelegations(t *testing.T) { clientAcct, _ := ts.GetAccount(common.CONSUMER, 0) providerAcct, provider := ts.GetAccount(common.PROVIDER, 0) - // change the provider's delegation limit and commission - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) - require.True(t, found) - stakeEntry.DelegateCommission = 0 - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) + // change the provider's and commission + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err) + metadata.DelegateCommission = 0 + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) ts.AdvanceEpoch() // delegate testStake/2 (with commission=0) -> provider should get 66% of the reward _, delegator := ts.AddAccount(common.CONSUMER, 1, testBalance) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake/2))) + _, err = ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake/2))) require.NoError(t, err) ts.AdvanceEpoch() @@ -484,16 +484,16 @@ func TestProviderMonthlyPayoutQuery(t *testing.T) { require.NoError(t, err) ts.AdvanceEpoch() - // change the provider's delegation limit and commission - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) - require.True(t, found) - stakeEntry.DelegateCommission = 0 - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) + // change the provider's and commission + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err) + metadata.DelegateCommission = 10 + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) ts.AdvanceEpoch() // delegate testStake/2 (with commission=0) -> provider should get 66% of the reward _, delegator := ts.AddAccount(common.CONSUMER, 1, testBalance) - _, err = ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake/2))) + _, err = ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake/2))) require.NoError(t, err) ts.AdvanceEpoch() ts.AdvanceMonths(1).AdvanceEpoch() // advance first month of delegation so it'll apply @@ -515,12 +515,12 @@ func TestProviderMonthlyPayoutQuery(t *testing.T) { } ts.relayPaymentWithoutPay(relayPaymentMessage, true) - // check for expected balance: credit*100/200 (from spec1) + credit*(100/200)*(2/3) (from spec, considering delegations) - // for credit=100 (first month there was no use, so no credit was spent), expected monthly payout is 50+33 - expectedTotalPayout := uint64(83) + // check for expected balance: (credit*100/200 (from spec1) + credit*(100/200))*(4/5+1/5*commission(10%) (from spec, considering delegations) + // for credit=100 (first month there was no use, so no credit was spent), expected monthly payout is 90 + expectedTotalPayout := uint64(82) expectedPayouts := []types.SubscriptionPayout{ - {Subscription: clientAcc.Addr.String(), ChainId: ts.spec.Index, Amount: 33}, - {Subscription: clientAcc.Addr.String(), ChainId: spec1.Index, Amount: 50}, + {Subscription: clientAcc.Addr.String(), ChainId: ts.spec.Index, Amount: 41}, + {Subscription: clientAcc.Addr.String(), ChainId: spec1.Index, Amount: 41}, } res, err := ts.QueryPairingProviderMonthlyPayout(provider) require.NoError(t, err) @@ -603,16 +603,16 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { require.NoError(t, err) ts.AdvanceEpoch() - // change the provider's delegation limit and commission - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) - require.True(t, found) - stakeEntry.DelegateCommission = 0 - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) + // change the provider's and commission + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err) + metadata.DelegateCommission = 10 + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) ts.AdvanceEpoch() // delegate testStake/2 (with commission=0) -> provider should get 66% of the reward _, delegator := ts.AddAccount(common.CONSUMER, 1, testBalance) - _, err = ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake/2))) + _, err = ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake/2))) require.NoError(t, err) delegationTime := ts.BlockTime() ts.AdvanceEpoch() @@ -622,7 +622,7 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { // now since we want to check the expected reward, before it gets transferred). So, we need to artificially // change the delegations' timestamp to be a month forward fakeTimestamp := ts.BlockTime().AddDate(0, -2, 0) - err = ts.ChangeDelegationTimestamp(provider, delegator, ts.spec.Index, ts.BlockHeight(), ts.GetNextMonth(fakeTimestamp)) + err = ts.ChangeDelegationTimestamp(provider, delegator, ts.BlockHeight(), ts.GetNextMonth(fakeTimestamp)) require.NoError(t, err) // send two relay payments in spec and spec1 @@ -641,16 +641,13 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { } ts.relayPaymentWithoutPay(relayPaymentMessage, true) - // half the plan payment for spec1 is 25. Then it's divided between 2 contributors equally rounded down - expectedContributorPay := uint64(12) - - // for planPrice=100, and equal CU usage for both specs, the expected provider monthly payout is: - // spec (delegator is 33% of stake): planPrice * specUsedCu/totalUsedCu * providerStake/totalStake = 100*0.5*(2/3) = 33 - // spec1 (contributors with commission=50%): planPrice * specUsedCu/totalUsedCu - contributorsPart = 100*0.5 - 24 = 26 - expectedTotalPayout := uint64(59) + // check for expected balance: planPrice*(100/200 (from spec1) + planPrice*(100/200))*(4/5 + 1/5*0.1) (from spec, considering delegations) + // for planPrice=100, expected monthly payout is 50 (spec1 with contributor) + 33 (normal spec no contributor) + expectedContributorPay := uint64(12) // half the plan payment for spec1:25 then divided between contributors half half rounded down + expectedTotalPayout := uint64(85) - expectedContributorPay*2 expectedPayouts := []types.SubscriptionPayout{ - {Subscription: clientAcc.Addr.String(), ChainId: ts.spec.Index, Amount: 33}, - {Subscription: clientAcc.Addr.String(), ChainId: spec1.Index, Amount: 26}, + {Subscription: clientAcc.Addr.String(), ChainId: ts.spec.Index, Amount: 41}, + {Subscription: clientAcc.Addr.String(), ChainId: spec1.Index, Amount: 20}, // 50 - 26 for contributors (each contributor gets 12) } res, err := ts.QueryPairingProviderMonthlyPayout(provider) require.NoError(t, err) @@ -690,7 +687,7 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { // advance month + blocksToSave + 1 to trigger the monthly payment // (also restore delegation original timestamp) oldBalance := ts.GetBalance(providerAcct.Vault.Addr) - err = ts.ChangeDelegationTimestamp(provider, delegator, ts.spec.Index, ts.BlockHeight(), ts.GetNextMonth(delegationTime)) + err = ts.ChangeDelegationTimestamp(provider, delegator, ts.BlockHeight(), ts.GetNextMonth(delegationTime)) require.NoError(t, err) ts.AdvanceMonths(1) diff --git a/x/pairing/keeper/delegator_rewards_test.go b/x/pairing/keeper/delegator_rewards_test.go index a8049e9811..17baf1e5bb 100644 --- a/x/pairing/keeper/delegator_rewards_test.go +++ b/x/pairing/keeper/delegator_rewards_test.go @@ -6,7 +6,6 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/testutil/common" - "github.com/lavanet/lava/v3/utils/lavaslices" "github.com/lavanet/lava/v3/utils/sigs" dualstakingtypes "github.com/lavanet/lava/v3/x/dualstaking/types" "github.com/lavanet/lava/v3/x/pairing/types" @@ -72,25 +71,26 @@ func TestProviderDelegatorsRewards(t *testing.T) { if amount1.IsZero() { amount1.Amount = sdk.OneInt() } - _, err = ts.TxDualstakingDelegate(delegator1, provider, ts.spec.Index, amount1) + _, err = ts.TxDualstakingDelegate(delegator1, provider, amount1) require.NoError(t, err) amount2 := sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(tt.d2Amount*delegationAmount/100)) - _, err = ts.TxDualstakingDelegate(delegator2, provider, ts.spec.Index, amount2) + _, err = ts.TxDualstakingDelegate(delegator2, provider, amount2) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations // change delegation traits of stake entry and get the modified one - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) - require.True(t, found) - stakeEntry.DelegateCommission = tt.commission - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err) + metadata.DelegateCommission = tt.commission + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) + ts.AdvanceEpoch() - stakeEntry, found = ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) + stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) require.True(t, found) // check that there are two delegators - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 3, len(res.Delegations)) @@ -187,33 +187,41 @@ func TestProviderRewardWithCommission(t *testing.T) { ts.AdvanceEpoch() // to apply pairing delegationAmount1 := sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake)) - _, err = ts.TxDualstakingDelegate(delegator1, provider, ts.spec.Index, delegationAmount1) + _, err = ts.TxDualstakingDelegate(delegator1, provider, delegationAmount1) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) - require.True(t, found) - // ** provider's commission is 100% ** // + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err) + metadata.DelegateCommission = 100 + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) - stakeEntry.DelegateCommission = 100 - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) ts.AdvanceEpoch() - stakeEntry, found = ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) + stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) require.True(t, found) - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) // the expected reward for the provider with 100% commission is the total rewards (delegators get nothing) currentTimestamp := ts.Ctx.BlockTime().UTC().Unix() - relevantDelegations := lavaslices.Filter(res.Delegations, - func(d dualstakingtypes.Delegation) bool { - return d.ChainID == ts.spec.Index && d.IsFirstWeekPassed(currentTimestamp) - }) totalReward := sdk.NewCoins(sdk.NewCoin(ts.TokenDenom(), math.NewInt(int64(relayCuSum)))) - providerReward, _ := ts.Keepers.Dualstaking.CalcRewards(ts.Ctx, stakeEntry, totalReward, relevantDelegations) + + relevantDelegations := []dualstakingtypes.Delegation{} + totalDelegations := sdk.ZeroInt() + var selfdelegation dualstakingtypes.Delegation + for _, d := range res.Delegations { + if d.Delegator != stakeEntry.Vault { + selfdelegation = d + } else if d.IsFirstWeekPassed(currentTimestamp) { + relevantDelegations = append(relevantDelegations, d) + totalDelegations = totalDelegations.Add(d.Amount.Amount) + } + } + + providerReward, _ := ts.Keepers.Dualstaking.CalcRewards(ts.Ctx, totalReward, totalDelegations, selfdelegation, relevantDelegations, stakeEntry.DelegateCommission) require.True(t, totalReward.IsEqual(providerReward)) @@ -227,8 +235,11 @@ func TestProviderRewardWithCommission(t *testing.T) { require.Equal(t, 0, len(resRewards.Rewards)) // ** provider's commission is 0% ** // - stakeEntry.DelegateCommission = 0 - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) + metadata, err1 := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err1) + metadata.DelegateCommission = 0 + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) + ts.AdvanceEpoch() // the expected reward for the provider with 0% commission is half of the total rewards @@ -301,16 +312,16 @@ func TestQueryDelegatorRewards(t *testing.T) { ts.AdvanceEpoch() - makeProviderCommissionZero(ts, ts.spec.Index, provider1) - makeProviderCommissionZero(ts, spec1.Index, provider1) - makeProviderCommissionZero(ts, ts.spec.Index, provider2) + makeProviderCommissionZero(ts, provider1) + makeProviderCommissionZero(ts, provider1) + makeProviderCommissionZero(ts, provider2) delegationAmount := sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake)) - _, err = ts.TxDualstakingDelegate(delegator1, provider1, ts.spec.Index, delegationAmount) + _, err = ts.TxDualstakingDelegate(delegator1, provider1, delegationAmount) require.NoError(t, err) - _, err = ts.TxDualstakingDelegate(delegator1, provider1, spec1.Index, delegationAmount) + _, err = ts.TxDualstakingDelegate(delegator1, provider1, delegationAmount) require.NoError(t, err) - _, err = ts.TxDualstakingDelegate(delegator1, provider2, ts.spec.Index, delegationAmount) + _, err = ts.TxDualstakingDelegate(delegator1, provider2, delegationAmount) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations @@ -337,12 +348,11 @@ func TestQueryDelegatorRewards(t *testing.T) { chainID string expectedRewards int64 }{ - {"assigned provider+chainID", delegator1, provider1, ts.spec.Index, (planPrice * 100) / (200 * 2)}, + {"assigned provider+chainID", delegator1, provider1, ts.spec.Index, 2 * (planPrice * 100) / (200 * 2)}, {"assigned provider", delegator1, provider1, "", 2 * ((planPrice * 100) / (200 * 2))}, {"nothing assigned", delegator1, "", "", (2 * ((planPrice * 100) / (200 * 2))) + (planPrice*100)/(100*2)}, {"invalid delegator", delegator2, provider2, spec1.Index, 0}, {"invalid provider", delegator1, provider3, ts.spec.Index, 0}, - {"invalid chain ID", delegator1, provider2, spec1.Index, 0}, } for _, tt := range tests { @@ -410,11 +420,13 @@ func TestVaultProviderDelegatorRewardsQuery(t *testing.T) { } } -func makeProviderCommissionZero(ts *tester, chainID string, provider string) { - stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, chainID, provider) - require.True(ts.T, found) - stakeEntry.DelegateCommission = 0 - ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) +func makeProviderCommissionZero(ts *tester, provider string) { + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + if err != nil { + panic(err) + } + metadata.DelegateCommission = 0 + ts.Keepers.Epochstorage.SetMetadata(ts.Ctx, metadata) ts.AdvanceEpoch() } @@ -430,12 +442,12 @@ func TestDelegationTimestamp(t *testing.T) { // delegate and check the timestamp is equal to current time + month currentTimeAfterMonth := ts.GetNextMonth(ts.BlockTime()) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) // expect two because of provider self delegation + delegator for _, d := range res.Delegations { @@ -447,11 +459,11 @@ func TestDelegationTimestamp(t *testing.T) { // advance time and delegate again to verify that the timestamp hasn't changed ts.AdvanceMonths(1) expectedDelegation := sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(2*testStake)) - _, err = ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) + _, err = ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations - res, err = ts.QueryDualstakingProviderDelegators(provider, false) + res, err = ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) // expect two because of provider self delegation + delegator for _, d := range res.Delegations { @@ -481,11 +493,11 @@ func TestDelegationFirstMonthPairing(t *testing.T) { // delegate and check the delegation's timestamp is equal than nowPlusMonthTime nowPlusMonthTime := ts.GetNextMonth(ts.BlockTime()) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) // expect two because of provider self delegation + delegator for _, d := range res.Delegations { @@ -518,16 +530,16 @@ func TestDelegationFirstMonthReward(t *testing.T) { require.True(t, found) ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) ts.AdvanceEpoch() - makeProviderCommissionZero(ts, ts.spec.Index, provider) + makeProviderCommissionZero(ts, provider) // delegate and check the delegation's timestamp is equal to nowPlusMonthTime nowPlusMonthTime := ts.GetNextMonth(ts.BlockTime()) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) // expect two because of provider self delegation + delegator for _, d := range res.Delegations { @@ -572,17 +584,17 @@ func TestRedelegationFirstMonthReward(t *testing.T) { require.True(t, found) ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, stakeEntry) ts.AdvanceEpoch() - makeProviderCommissionZero(ts, ts.spec.Index, provider1) - makeProviderCommissionZero(ts, ts.spec.Index, provider) + makeProviderCommissionZero(ts, provider1) + makeProviderCommissionZero(ts, provider) // delegate and check the delegation's timestamp is equal to nowPlusMonthTime nowPlusMonthTime := ts.GetNextMonth(ts.BlockTime()) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) require.NoError(t, err) ts.AdvanceEpoch() // apply delegations - res, err := ts.QueryDualstakingProviderDelegators(provider, false) + res, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) require.Equal(t, 2, len(res.Delegations)) // expect two because of provider self delegation + delegator for _, d := range res.Delegations { @@ -594,7 +606,7 @@ func TestRedelegationFirstMonthReward(t *testing.T) { // advance a month a redelegate some of the funds to the second provider ts.AdvanceMonths(1) redelegateAmount := sdk.NewCoin(ts.TokenDenom(), res.Delegations[0].Amount.Amount.QuoRaw(2)) - _, err = ts.TxDualstakingRedelegate(delegator, provider, provider1, ts.spec.Index, ts.spec.Index, redelegateAmount) + _, err = ts.TxDualstakingRedelegate(delegator, provider, provider1, redelegateAmount) require.NoError(t, err) // to trigger the payment's code, we need to advance a month+blocksToSave. If we do that, @@ -620,3 +632,84 @@ func TestRedelegationFirstMonthReward(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, len(resRewards.Rewards)) } + +// TestDelegatorRewardProviderAddingChain checks that a delegator gets rewards even if the provider moves stake between chains +func TestDelegatorRewardProviderAddingChain(t *testing.T) { + ts := newTester(t) + ts.setupForPayments(1, 0, 2) // 1 providers, 1 client, 1 providersToPair + ts.AddAccount(common.CONSUMER, 1, testBalance) // add delegator1 + + providerAcc, provider := ts.GetAccount(common.PROVIDER, 0) + _, delegator := ts.GetAccount(common.CONSUMER, 1) + clientAcc, client := ts.AddAccount(common.CONSUMER, 0, testBalance) + makeProviderCommissionZero(ts, provider) + + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.TokenDenom(), sdk.NewInt(testStake))) + require.NoError(t, err) + ts.AdvanceEpoch() // apply delegations + + _, err = ts.TxSubscriptionBuy(client, client, ts.plan.Index, 1, true, false) + require.NoError(t, err) + + ts.AdvanceEpoch() // to apply pairing + + relayPaymentMessage := sendRelay(ts, provider, clientAcc, []string{ts.spec.Index}) + _, err = ts.TxPairingRelayPayment(relayPaymentMessage.Creator, relayPaymentMessage.Relays...) + require.Nil(ts.T, err) + + // advance month + blocksToSave + 1 to trigger the provider monthly payment + ts.AdvanceMonths(1) + ts.AdvanceEpoch() + ts.AdvanceBlocks(ts.BlocksToSave() + 1) + + // delegator should get half of the payment + res, err := ts.QueryDualstakingDelegatorRewards(delegator, provider, "") + require.Nil(ts.T, err) + require.Equal(ts.T, ts.plan.Price.Amount.QuoRaw(2), res.Rewards[0].Amount[0].Amount) + ts.TxDualstakingClaimRewards(delegator, "") + + // add additional spec + spec1 := common.CreateMockSpec() + spec1.Index = "mock1" + spec1.Name = "mock1" + ts.AddSpec(spec1.Index, spec1) + err = ts.StakeProvider(providerAcc.GetVaultAddr(), provider, spec1, testStake) + makeProviderCommissionZero(ts, provider) + require.NoError(t, err) + + ts.AdvanceEpoch() + + relayPaymentMessage = sendRelay(ts, provider, clientAcc, []string{ts.spec.Index, spec1.Index}) + _, err = ts.TxPairingRelayPayment(relayPaymentMessage.Creator, relayPaymentMessage.Relays...) + require.Nil(ts.T, err) + + // advance month + blocksToSave + 1 to trigger the provider monthly payment + ts.AdvanceMonths(1) + ts.AdvanceEpoch() + ts.AdvanceBlocks(ts.BlocksToSave() + 1) + + // delegator should get third of the payment + res, err = ts.QueryDualstakingDelegatorRewards(delegator, provider, "") + require.Nil(ts.T, err) + require.Equal(ts.T, ts.plan.Price.Amount.QuoRaw(3).AddRaw(1), res.Rewards[0].Amount[0].Amount) + ts.TxDualstakingClaimRewards(delegator, "") + + // move the stake between chains, should still get third + relayPaymentMessage = sendRelay(ts, provider, clientAcc, []string{ts.spec.Index, spec1.Index}) + _, err = ts.TxPairingRelayPayment(relayPaymentMessage.Creator, relayPaymentMessage.Relays...) + require.Nil(ts.T, err) + + err = ts.Keepers.Pairing.MoveProviderStake(ts.Ctx, provider, ts.spec.Index, spec1.Index, sdk.NewCoin(ts.BondDenom(), sdk.NewInt(testStake/10))) + require.Nil(ts.T, err) + + // advance month + blocksToSave + 1 to trigger the provider monthly payment + ts.AdvanceMonths(1) + ts.AdvanceEpoch() + ts.AdvanceBlocks(ts.BlocksToSave() + 1) + + // delegator should get half of the payment + res, err = ts.QueryDualstakingDelegatorRewards(delegator, provider, "") + require.Nil(ts.T, err) + require.Equal(ts.T, ts.plan.Price.Amount.QuoRaw(3).AddRaw(1), res.Rewards[0].Amount[0].Amount) + ts.TxDualstakingClaimRewards(delegator, "") +} diff --git a/x/pairing/keeper/grpc_query_provider.go b/x/pairing/keeper/grpc_query_provider.go index e23711c1f8..bd2970c82c 100644 --- a/x/pairing/keeper/grpc_query_provider.go +++ b/x/pairing/keeper/grpc_query_provider.go @@ -17,9 +17,14 @@ func (k Keeper) Provider(goCtx context.Context, req *types.QueryProviderRequest) ctx := sdk.UnwrapSDKContext(goCtx) + metadata, err := k.epochStorageKeeper.GetMetadata(ctx, req.Address) + if err != nil { + return &types.QueryProviderResponse{}, nil + } + chains := []string{req.ChainID} if req.ChainID == "" { - chains = k.specKeeper.GetAllChainIDs(ctx) + chains = metadata.Chains } stakeEntries := []epochstoragetypes.StakeEntry{} @@ -28,7 +33,10 @@ func (k Keeper) Provider(goCtx context.Context, req *types.QueryProviderRequest) if !found { continue } - stakeEntry.Moniker = stakeEntry.Description.Moniker + stakeEntry.Description = metadata.Description + stakeEntry.Moniker = metadata.Description.Moniker + stakeEntry.DelegateCommission = metadata.DelegateCommission + stakeEntry.Vault = metadata.Vault stakeEntries = append(stakeEntries, stakeEntry) } diff --git a/x/pairing/keeper/grpc_query_providers.go b/x/pairing/keeper/grpc_query_providers.go index 182748f4f7..632f007311 100644 --- a/x/pairing/keeper/grpc_query_providers.go +++ b/x/pairing/keeper/grpc_query_providers.go @@ -19,16 +19,24 @@ func (k Keeper) Providers(goCtx context.Context, req *types.QueryProvidersReques stakeEntries := k.epochStorageKeeper.GetAllStakeEntriesCurrentForChainId(ctx, req.ChainID) - if !req.ShowFrozen { - stakeEntriesNoFrozen := []epochstoragetypes.StakeEntry{} - for i := range stakeEntries { - stakeEntries[i].Moniker = stakeEntries[i].Description.Moniker - - // show providers with valid stakeAppliedBlock (frozen providers have stakeAppliedBlock = MaxUint64) - if stakeEntries[i].GetStakeAppliedBlock() <= uint64(ctx.BlockHeight()) { - stakeEntriesNoFrozen = append(stakeEntriesNoFrozen, stakeEntries[i]) - } + stakeEntriesNoFrozen := []epochstoragetypes.StakeEntry{} + for i := range stakeEntries { + metadata, err := k.epochStorageKeeper.GetMetadata(ctx, stakeEntries[i].Address) + if err != nil { + return nil, err + } + stakeEntries[i].DelegateCommission = metadata.DelegateCommission + stakeEntries[i].Description = metadata.Description + stakeEntries[i].Moniker = metadata.Description.Moniker + stakeEntries[i].Vault = metadata.Vault + + // show providers with valid stakeAppliedBlock (frozen providers have stakeAppliedBlock = MaxUint64) + if !req.ShowFrozen && stakeEntries[i].GetStakeAppliedBlock() <= uint64(ctx.BlockHeight()) { + stakeEntriesNoFrozen = append(stakeEntriesNoFrozen, stakeEntries[i]) } + } + + if !req.ShowFrozen { stakeEntries = stakeEntriesNoFrozen } diff --git a/x/pairing/keeper/helpers_test.go b/x/pairing/keeper/helpers_test.go index e1509bd73b..78ca6c0360 100644 --- a/x/pairing/keeper/helpers_test.go +++ b/x/pairing/keeper/helpers_test.go @@ -73,24 +73,30 @@ func (ts *tester) addValidators(count int) { // addProvider: with default endpoints, geolocation, moniker func (ts *tester) addProvider(count int) error { d := common.MockDescription() - return ts.addProviderExtra(count, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) // default: endpoints, geolocation, moniker + return ts.addProviderExtra(count, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, ts.spec) // default: endpoints, geolocation, moniker +} + +// addProvider: with default endpoints, geolocation, moniker +func (ts *tester) addProviderSpec(count int, spec string) error { + d := common.MockDescription() + return ts.addProviderExtra(count, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, ts.Spec(spec)) } // addProviderGelocation: with geolocation, and default endpoints, moniker func (ts *tester) addProviderGeolocation(count int, geolocation int32) error { d := common.MockDescription() - return ts.addProviderExtra(count, nil, geolocation, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + return ts.addProviderExtra(count, nil, geolocation, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, ts.spec) } // addProviderEndpoints: with endpoints, and default geolocation, moniker func (ts *tester) addProviderEndpoints(count int, endpoints []epochstoragetypes.Endpoint) error { d := common.MockDescription() - return ts.addProviderExtra(count, endpoints, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + return ts.addProviderExtra(count, endpoints, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, ts.spec) } // addProviderDescription: with description, and default endpoints, geolocation func (ts *tester) addProviderDescription(count int, moniker string, identity string, website string, securityContact string, descriptionDetails string) error { - return ts.addProviderExtra(count, nil, 0, moniker, identity, website, securityContact, descriptionDetails) + return ts.addProviderExtra(count, nil, 0, moniker, identity, website, securityContact, descriptionDetails, ts.spec) } // addProviderExtra: with mock endpoints, and preset geolocation, description details @@ -103,11 +109,12 @@ func (ts *tester) addProviderExtra( website string, securityContact string, descriptionDetails string, + spec spectypes.Spec, ) error { start := len(ts.Accounts(common.PROVIDER)) for i := 0; i < count; i++ { acc, addr := ts.AddAccount(common.PROVIDER, start+i, testBalance) - err := ts.StakeProviderExtra(acc.GetVaultAddr(), addr, ts.spec, testStake, endpoints, geoloc, moniker, identity, website, securityContact, descriptionDetails) + err := ts.StakeProviderExtra(acc.GetVaultAddr(), addr, spec, testStake, endpoints, geoloc, moniker, identity, website, securityContact, descriptionDetails) if err != nil { return err } diff --git a/x/pairing/keeper/migrations.go b/x/pairing/keeper/migrations.go index 00b21034ce..d5f047be44 100644 --- a/x/pairing/keeper/migrations.go +++ b/x/pairing/keeper/migrations.go @@ -4,7 +4,9 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/lavanet/lava/v3/utils" + types1 "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/lavanet/lava/v3/utils/lavaslices" + epochstoragetypes "github.com/lavanet/lava/v3/x/epochstorage/types" v2 "github.com/lavanet/lava/v3/x/pairing/migrations/v2" ) @@ -24,33 +26,83 @@ func (m Migrator) MigrateVersion2To3(ctx sdk.Context) error { return nil } -// MigrateVersion3To4 fix delegation total in the stake entries -func (m Migrator) MigrateVersion3To4(ctx sdk.Context) error { +func (m Migrator) MigrateVersion4To5(ctx sdk.Context) error { entries := m.keeper.epochStorageKeeper.GetAllStakeEntriesCurrent(ctx) - epoch := m.keeper.epochStorageKeeper.GetCurrentNextEpoch(ctx) - for _, e := range entries { - delegations, err := m.keeper.dualstakingKeeper.GetProviderDelegators(ctx, e.Address, epoch) + providerMap := map[string][]*epochstoragetypes.StakeEntry{} + + // map the providers + for i := range entries { + providerMap[entries[i].Address] = append(providerMap[entries[i].Address], &entries[i]) + } + + // iterate over each provider + for address, entries := range providerMap { + metadata := epochstoragetypes.ProviderMetadata{Provider: address} + + // find the biggest vault + var biggestVault *epochstoragetypes.StakeEntry + biggestEntry := entries[0] + for i := range entries { + e := entries[i] + if biggestEntry.Stake.Amount.LT(e.Stake.Amount) { + biggestEntry = e + } + if e.Vault != e.Address { + if biggestVault == nil { + biggestVault = e + } else if biggestVault.Stake.Amount.LT(e.Stake.Amount) { + biggestVault = e + } + } + } + + // if no vault was found the vault is the address + metadata.Description = biggestEntry.Description + metadata.DelegateCommission = biggestEntry.DelegateCommission + metadata.Provider = address + if biggestVault != nil { + metadata.Vault = biggestVault.Vault + } else { + metadata.Vault = address + } + + // get all delegations and sum + delegations, err := m.keeper.dualstakingKeeper.GetProviderDelegators(ctx, metadata.Provider) if err != nil { - utils.LavaFormatError("failed getting provider delegators at MigrateVersion3To4", err, utils.LogAttr("provider", e.Address)) - continue + return err } - delegateTotal := sdk.ZeroInt() + metadata.TotalDelegations = sdk.NewCoin(m.keeper.stakingKeeper.BondDenom(ctx), sdk.ZeroInt()) for _, d := range delegations { - if e.Address == d.Delegator || e.Vault == d.Delegator || d.ChainID != e.Chain { - continue + if d.Delegator != metadata.Vault { + metadata.TotalDelegations = metadata.TotalDelegations.Add(d.Amount) } - delegateTotal = delegateTotal.Add(d.Amount.Amount) } - if !e.DelegateTotal.Amount.Equal(delegateTotal) { - fmt.Println("fixing delegate total for", e.Address, e.Chain) - e.DelegateTotal.Amount = delegateTotal - if e.TotalStake().LT(m.keeper.specKeeper.GetMinStake(ctx, e.Chain).Amount) { - e.Freeze() + // fix entries with different vaults + // count self delegations + TotalSelfDelegation := sdk.ZeroInt() + for _, e := range entries { + if e.Vault != metadata.Vault { + fmt.Println(address) + biggestVault.Stake = biggestVault.Stake.SubAmount(sdk.NewInt(1)) + e.Stake.Amount = sdk.OneInt() + e.Vault = metadata.Vault + } else { + TotalSelfDelegation = TotalSelfDelegation.Add(e.Stake.Amount) } - m.keeper.epochStorageKeeper.SetStakeEntryCurrent(ctx, e) } + + // calculate delegate total and update the entry + for _, entry := range entries { + metadata.Chains = lavaslices.AddUnique(metadata.Chains, entry.Chain) + entry.DelegateTotal = sdk.NewCoin(m.keeper.stakingKeeper.BondDenom(ctx), metadata.TotalDelegations.Amount.Mul(entry.Stake.Amount).Quo(TotalSelfDelegation)) + entry.Description = types1.Description{} + m.keeper.epochStorageKeeper.SetStakeEntryCurrent(ctx, *entry) + } + + // set the metadata + m.keeper.epochStorageKeeper.SetMetadata(ctx, metadata) } return nil diff --git a/x/pairing/keeper/migrations_test.go b/x/pairing/keeper/migrations_test.go new file mode 100644 index 0000000000..a5b7a5ee07 --- /dev/null +++ b/x/pairing/keeper/migrations_test.go @@ -0,0 +1,64 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + "github.com/lavanet/lava/v3/testutil/common" + "github.com/lavanet/lava/v3/x/pairing/keeper" + "github.com/stretchr/testify/require" +) + +func TestMigration4To5(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 0, 3, 0) + + provider0, _ := ts.AddAccount(common.PROVIDER, 0, testBalance) + provider1, _ := ts.AddAccount(common.PROVIDER, 1, testBalance) + + // stake provider 0 + d := common.MockDescription() + err := ts.StakeProviderExtra(provider0.GetVaultAddr(), provider0.Addr.String(), ts.Spec(SpecName(0)), testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + // stake provider 1 + err = ts.StakeProviderExtra(provider1.Addr.String(), provider1.Addr.String(), ts.Spec(SpecName(1)), testStake, nil, 0, "mon2", d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + // mimic the state where one provider has vault and another dont + + entry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, SpecName(0), provider0.Addr.String()) + ts.Keepers.Epochstorage.RemoveStakeEntryCurrent(ts.Ctx, entry.Chain, entry.Address) + require.True(t, found) + + // provider 0 address is now provider1 with vault of provider 0 + entry.Address = provider1.Addr.String() + entry.DelegateCommission = 49 + entry.Description = d + ts.Keepers.Epochstorage.SetStakeEntryCurrent(ts.Ctx, entry) + + keeper.NewMigrator(ts.Keepers.Pairing).MigrateVersion4To5(ts.Ctx) + + // unbond from validator with provider1 + val, _ := ts.GetAccount(common.VALIDATOR, 0) + _, err = ts.TxUnbondValidator(provider1, val, math.NewInt(testStake)) + require.NoError(t, err) + + // check stake entries are correct + res, err := ts.QueryPairingProvider(provider1.Addr.String(), "") + require.NoError(t, err) + require.Len(t, res.StakeEntries, 2) + for _, entry := range res.StakeEntries { + require.Equal(t, entry.Address, provider1.Addr.String()) + require.Equal(t, entry.Vault, provider0.GetVaultAddr()) + } + + mds, err := ts.Keepers.Epochstorage.GetAllMetadata(ts.Ctx) + require.NoError(t, err) + require.Len(t, mds, 1) + require.Equal(t, provider1.Addr.String(), mds[0].Provider) + require.Equal(t, provider0.GetVaultAddr(), mds[0].Vault) + require.Equal(t, []string{SpecName(0), SpecName(1)}, mds[0].Chains) + require.Equal(t, uint64(49), mds[0].DelegateCommission) + require.Equal(t, d, mds[0].Description) +} diff --git a/x/pairing/keeper/msg_server_move_provider_stake.go b/x/pairing/keeper/msg_server_move_provider_stake.go new file mode 100644 index 0000000000..4eaa377492 --- /dev/null +++ b/x/pairing/keeper/msg_server_move_provider_stake.go @@ -0,0 +1,49 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/v3/utils" + "github.com/lavanet/lava/v3/x/pairing/types" +) + +func (k msgServer) MoveProviderStake(goCtx context.Context, msg *types.MsgMoveProviderStake) (*types.MsgMoveProviderStakeResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + err := k.Keeper.MoveProviderStake(ctx, msg.Creator, msg.SrcChain, msg.DstChain, msg.Amount) + return &types.MsgMoveProviderStakeResponse{}, err +} + +func (k Keeper) MoveProviderStake(ctx sdk.Context, creator, srcChain, dstChain string, amount sdk.Coin) error { + srcEntry, found := k.epochStorageKeeper.GetStakeEntryCurrent(ctx, srcChain, creator) + if !found { + return utils.LavaFormatError("provider is not staked in the source chain", nil, + utils.LogAttr("provider", creator), + utils.LogAttr("chain", srcChain), + ) + } + + dstEntry, found := k.epochStorageKeeper.GetStakeEntryCurrent(ctx, dstChain, creator) + if !found { + return utils.LavaFormatError("provider is not staked in the destination chain", nil, + utils.LogAttr("provider", creator), + utils.LogAttr("chain", srcChain), + ) + } + + srcEntry.Stake = srcEntry.Stake.Sub(amount) + dstEntry.Stake = dstEntry.Stake.Add(amount) + + minSelfDelegation := k.dualstakingKeeper.MinSelfDelegation(ctx) + if srcEntry.Stake.IsLT(minSelfDelegation) { + return utils.LavaFormatError("provider will be below min stake on source chain", nil, + utils.LogAttr("provider", creator), + utils.LogAttr("chain", srcChain), + ) + } + + k.epochStorageKeeper.SetStakeEntryCurrent(ctx, srcEntry) + k.epochStorageKeeper.SetStakeEntryCurrent(ctx, dstEntry) + return k.dualstakingKeeper.AfterDelegationModified(ctx, srcEntry.Vault, srcEntry.Address, sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), sdk.ZeroInt()), false, true) +} diff --git a/x/pairing/keeper/msg_server_stake_provider_test.go b/x/pairing/keeper/msg_server_stake_provider_test.go index 161c020c57..d3046d47cd 100644 --- a/x/pairing/keeper/msg_server_stake_provider_test.go +++ b/x/pairing/keeper/msg_server_stake_provider_test.go @@ -27,9 +27,9 @@ func TestModifyStakeProviderWithDescription(t *testing.T) { providerAcct, providerAddr := ts.GetAccount(common.PROVIDER, 0) // Get the stake entry and check the provider is staked - stakeEntry, foundProvider := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, providerAddr) - require.True(t, foundProvider) - require.True(t, stakeEntry.Description.Equal(common.MockDescription())) + stakeEntry, err := ts.QueryPairingProvider(providerAddr, ts.spec.Index) + require.NoError(t, err) + require.True(t, stakeEntry.StakeEntries[0].Description.Equal(common.MockDescription())) // modify description dNew := stakingtypes.NewDescription("bla", "blan", "bal", "lala", "asdasd") @@ -38,9 +38,9 @@ func TestModifyStakeProviderWithDescription(t *testing.T) { ts.AdvanceEpoch() // Get the stake entry and check the provider is staked - stakeEntry, foundProvider = ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, providerAddr) - require.True(t, foundProvider) - require.True(t, stakeEntry.Description.Equal(dNew)) + stakeEntry, err = ts.QueryPairingProvider(providerAddr, ts.spec.Index) + require.NoError(t, err) + require.True(t, stakeEntry.StakeEntries[0].Description.Equal(dNew)) } func TestCmdStakeProviderGeoConfigAndEnum(t *testing.T) { @@ -207,7 +207,7 @@ func TestCmdStakeProviderGeoConfigAndEnum(t *testing.T) { endpoints[i].ApiInterfaces = []string{"stub"} endpoints[i].Addons = []string{} } - _, err = ts.TxPairingStakeProvider(provider, acc.GetVaultAddr(), ts.spec.Index, ts.spec.MinStakeProvider, endpoints, geo, common.MockDescription()) + _, err = ts.TxPairingStakeProvider(provider, acc.GetVaultAddr(), ts.spec.Index, ts.spec.MinStakeProvider, endpoints, geo, common.MockDescription(), 100) require.NoError(t, err) } else { require.Error(t, err) @@ -657,7 +657,7 @@ func TestStakeEndpoints(t *testing.T) { for _, play := range playbook { t.Run(play.name, func(t *testing.T) { - _, err := ts.TxPairingStakeProvider(providerAddr, providerAcc.GetVaultAddr(), ts.spec.Index, amount, play.endpoints, play.geolocation, common.MockDescription()) + _, err := ts.TxPairingStakeProvider(providerAddr, providerAcc.GetVaultAddr(), ts.spec.Index, amount, play.endpoints, play.geolocation, common.MockDescription(), 100) if play.success { require.NoError(t, err) @@ -761,7 +761,7 @@ func TestUnfreezeWithDelegations(t *testing.T) { // add delegator and delegate to provider so its effective stake is MinStakeProvider+MinSelfDelegation+1 // provider should still be frozen _, consumer := ts.AddAccount(common.CONSUMER, 1, testBalance) - _, err = ts.TxDualstakingDelegate(consumer, provider, ts.spec.Index, ts.spec.MinStakeProvider) + _, err = ts.TxDualstakingDelegate(consumer, provider, ts.spec.MinStakeProvider) require.NoError(t, err) ts.AdvanceEpoch() // apply delegation stakeEntry, found = ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, provider) @@ -801,7 +801,7 @@ func TestCommisionChange(t *testing.T) { // add delegator and delegate to provider _, consumer := ts.AddAccount(common.CONSUMER, 1, testBalance) - _, err = ts.TxDualstakingDelegate(consumer, provider, ts.spec.Index, ts.spec.MinStakeProvider) + _, err = ts.TxDualstakingDelegate(consumer, provider, ts.spec.MinStakeProvider) require.NoError(t, err) ts.AdvanceEpoch() // apply delegation ts.AdvanceBlock(time.Hour * 25) // advance time to allow changes @@ -855,11 +855,12 @@ func TestVaultProviderNewStakeEntry(t *testing.T) { provider sdk.AccAddress spec spectypes.Spec valid bool + fail bool }{ - {"stake provider = vault", p1Acc.Addr, p1Acc.Addr, ts.spec, true}, - {"stake provider != vault", p2Acc.Vault.Addr, p2Acc.Addr, ts.spec, true}, - {"stake existing provider", p1Acc.Vault.Addr, p1Acc.Addr, ts.spec, false}, - {"stake existing provider different chain", p1Acc.Vault.Addr, p1Acc.Addr, spec1, true}, + {"stake provider = vault", p1Acc.Addr, p1Acc.Addr, ts.spec, true, false}, + {"stake provider != vault", p2Acc.Vault.Addr, p2Acc.Addr, ts.spec, true, false}, + {"stake existing provider", p1Acc.Vault.Addr, p1Acc.Addr, ts.spec, false, false}, + {"stake existing provider different chain", p1Acc.Vault.Addr, p1Acc.Addr, spec1, false, true}, } for _, tt := range tests { @@ -881,10 +882,14 @@ func TestVaultProviderNewStakeEntry(t *testing.T) { // stake entry _, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, tt.spec.Index, tt.provider.String()) + if tt.fail { + require.False(t, found) + return + } require.True(t, found) // should be found because provider is registered in a vaild stake entry // delegations - res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String(), false) + res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String()) require.NoError(t, err) require.Len(t, res.Delegations, 0) } else { @@ -905,7 +910,7 @@ func TestVaultProviderNewStakeEntry(t *testing.T) { require.Equal(t, int64(0), stakeEntry.DelegateTotal.Amount.Int64()) // delegations - res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String(), false) + res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String()) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, tt.provider.String(), res.Delegations[0].Provider) @@ -963,7 +968,7 @@ func TestVaultProviderExistingStakeEntry(t *testing.T) { require.True(t, found) // should be found because provider is registered in a vaild stake entry // delegations - res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String(), false) + res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String()) require.NoError(t, err) require.Len(t, res.Delegations, 0) } else { @@ -984,7 +989,7 @@ func TestVaultProviderExistingStakeEntry(t *testing.T) { require.Equal(t, int64(0), stakeEntry.DelegateTotal.Amount.Int64()) // delegations - res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String(), false) + res, err := ts.QueryDualstakingDelegatorProviders(tt.vault.String()) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, tt.provider.String(), res.Delegations[0].Provider) @@ -1008,11 +1013,13 @@ func TestVaultProviderModifyStakeEntry(t *testing.T) { provider := acc.Addr.String() vault := acc.GetVaultAddr() - valAcc, _ := ts.GetAccount(common.VALIDATOR, 0) stakeEntry, found := ts.Keepers.Epochstorage.GetStakeEntryCurrent(ts.Ctx, ts.spec.Index, acc.Addr.String()) require.True(t, found) + metadata, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider) + require.NoError(t, err) + // consts for stake entry changes const ( STAKE = iota + 1 @@ -1047,12 +1054,11 @@ func TestVaultProviderModifyStakeEntry(t *testing.T) { t.Run(tt.name, func(t *testing.T) { msg := types.MsgStakeProvider{ Creator: tt.creator, - Validator: sdk.ValAddress(valAcc.Addr).String(), ChainID: stakeEntry.Chain, Amount: stakeEntry.Stake, Geolocation: stakeEntry.Geolocation, Endpoints: stakeEntry.Endpoints, - DelegateCommission: stakeEntry.DelegateCommission, + DelegateCommission: metadata.DelegateCommission, Address: stakeEntry.Address, Description: stakeEntry.Description, } @@ -1126,7 +1132,7 @@ func TestDelegatorStakesAfterProviderUnstakes(t *testing.T) { // create delegator and delegate to provider _, delegator := ts.AddAccount(common.CONSUMER, 0, testBalance) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, common.NewCoin(ts.TokenDenom(), testBalance/4)) + _, err := ts.TxDualstakingDelegate(delegator, provider, common.NewCoin(ts.TokenDenom(), testBalance/4)) require.NoError(t, err) ts.AdvanceEpoch() @@ -1134,7 +1140,7 @@ func TestDelegatorStakesAfterProviderUnstakes(t *testing.T) { _, err = ts.TxPairingUnstakeProvider(vault, ts.spec.Index) require.NoError(t, err) - res, err := ts.QueryDualstakingDelegatorProviders(delegator, false) + res, err := ts.QueryDualstakingDelegatorProviders(delegator) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, delegator, res.Delegations[0].Delegator) @@ -1182,7 +1188,7 @@ func TestDelegatorAfterProviderUnstakeAndStake(t *testing.T) { // create apple apple and delegate to banana _, apple := ts.AddAccount(common.CONSUMER, 0, testBalance) - _, err = ts.TxDualstakingDelegate(apple, banana, ts.spec.Index, common.NewCoin(ts.TokenDenom(), testBalance/4)) + _, err = ts.TxDualstakingDelegate(apple, banana, common.NewCoin(ts.TokenDenom(), testBalance/4)) require.NoError(t, err) ts.AdvanceEpoch() @@ -1191,7 +1197,7 @@ func TestDelegatorAfterProviderUnstakeAndStake(t *testing.T) { require.NoError(t, err) ts.AdvanceEpoch() - res, err := ts.QueryDualstakingDelegatorProviders(apple, false) + res, err := ts.QueryDualstakingDelegatorProviders(apple) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, apple, res.Delegations[0].Delegator) @@ -1211,10 +1217,10 @@ func TestDelegatorAfterProviderUnstakeAndStake(t *testing.T) { require.True(t, found) require.NotZero(t, stakeEntry.DelegateTotal.Amount.Int64()) - _, err = ts.TxDualstakingUnbond(apple, banana, ts.spec.Index, common.NewCoin(ts.TokenDenom(), testBalance/4)) + _, err = ts.TxDualstakingUnbond(apple, banana, common.NewCoin(ts.TokenDenom(), testBalance/4)) require.NoError(t, err) ts.AdvanceEpoch() - res, err := ts.QueryDualstakingProviderDelegators(banana, false) + res, err := ts.QueryDualstakingProviderDelegators(banana) require.NoError(t, err) require.Len(t, res.Delegations, 1) require.Equal(t, banana, res.Delegations[0].Provider) @@ -1229,10 +1235,10 @@ func TestDelegatorAfterProviderUnstakeAndStake(t *testing.T) { require.True(t, found) require.Zero(t, stakeEntry.DelegateTotal.Amount.Int64()) - _, err = ts.TxDualstakingUnbond(apple, banana, ts.spec.Index, common.NewCoin(ts.TokenDenom(), testBalance/4)) + _, err = ts.TxDualstakingUnbond(apple, banana, common.NewCoin(ts.TokenDenom(), testBalance/4)) require.NoError(t, err) ts.AdvanceEpoch() - res, err := ts.QueryDualstakingProviderDelegators(banana, false) + res, err := ts.QueryDualstakingProviderDelegators(banana) require.NoError(t, err) require.Len(t, res.Delegations, 0) } diff --git a/x/pairing/keeper/msg_server_unstake_provider_test.go b/x/pairing/keeper/msg_server_unstake_provider_test.go index 296dfd4b5b..3bcff8ea12 100644 --- a/x/pairing/keeper/msg_server_unstake_provider_test.go +++ b/x/pairing/keeper/msg_server_unstake_provider_test.go @@ -10,32 +10,31 @@ import ( // TestVaultProviderUnstake tests that only the vault address can unstake. // Scenarios: // 1. unstake with vault -> should work -// 2. try with provider -> should fail +// 2. try with provider -> should work func TestVaultProviderUnstake(t *testing.T) { ts := newTester(t) - ts.setupForPayments(1, 0, 0) + ts.setupForPayments(2, 0, 0) - acc, _ := ts.GetAccount(common.PROVIDER, 0) - provider := acc.Addr.String() - vault := acc.GetVaultAddr() + acc1, _ := ts.GetAccount(common.PROVIDER, 0) + provider1 := acc1.Addr.String() + + acc2, _ := ts.GetAccount(common.PROVIDER, 1) + vault2 := acc2.GetVaultAddr() tests := []struct { name string creator string - valid bool }{ - {"provider unstakes", provider, false}, - {"vault unstakes", vault, true}, + {"provider unstakes", provider1}, + {"vault unstakes", vault2}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + prov := ts.Keepers.Epochstorage.GetAllStakeEntriesCurrentForChainId(ts.Ctx, ts.spec.Index) + _ = prov _, err := ts.TxPairingUnstakeProvider(tt.creator, ts.spec.Index) - if tt.valid { - require.NoError(t, err) - } else { - require.Error(t, err) - } + require.NoError(t, err) }) } } diff --git a/x/pairing/keeper/pairing_test.go b/x/pairing/keeper/pairing_test.go index f1e607aff0..55e1024b95 100644 --- a/x/pairing/keeper/pairing_test.go +++ b/x/pairing/keeper/pairing_test.go @@ -968,7 +968,7 @@ func TestPairingDistributionPerStake(t *testing.T) { // double the stake of the first provider p := allProviders.StakeEntry[0] - _, err = ts.TxDualstakingDelegate(p.Vault, p.Address, ts.spec.Index, p.Stake) + _, err = ts.TxDualstakingDelegate(p.Vault, p.Address, p.Stake) require.NoError(t, err) ts.AdvanceEpoch() diff --git a/x/pairing/keeper/single_provider_test.go b/x/pairing/keeper/single_provider_test.go new file mode 100644 index 0000000000..29c33cd6c9 --- /dev/null +++ b/x/pairing/keeper/single_provider_test.go @@ -0,0 +1,510 @@ +package keeper_test + +import ( + "strconv" + "testing" + + "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/v3/testutil/common" + "github.com/lavanet/lava/v3/x/pairing/client/cli" + pairingtypes "github.com/lavanet/lava/v3/x/pairing/types" + "github.com/stretchr/testify/require" +) + +func SpecName(num int) string { + return "spec" + strconv.Itoa(num) +} + +func SetupForSingleProviderTests(ts *tester, providers, specs, clientsCount int) { + for i := 0; i < providers; i++ { + ts.AddAccount(common.PROVIDER, i, 100*testBalance) + } + + for i := 0; i < specs; i++ { + spec := ts.spec + spec.Index = SpecName(i) + ts.AddSpec(spec.Index, spec) + for i := 0; i < providers; i++ { + acc, addr := ts.GetAccount(common.PROVIDER, i) + d := common.MockDescription() + err := ts.StakeProviderExtra(acc.GetVaultAddr(), addr, spec, testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + } + } + + ts.addClient(clientsCount) + ts.AdvanceEpoch() +} + +// * unstake to see the delegations distributions +// * unstake from the rest of the chains +// * stake to get all delegations back +func TestUnstakeStake(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 1, 5, 0) + + delegator, _ := ts.AddAccount("del", 1, 1000000000) + provider0, _ := ts.GetAccount(common.PROVIDER, 0) + + // delegate and check delegatetotal + _, err := ts.TxDualstakingDelegate(delegator.Addr.String(), provider0.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), 5000)) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(1000), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + ts.AdvanceEpoch() + + stakeEntries := ts.Keepers.Epochstorage.GetAllStakeEntriesForEpoch(ts.Ctx, ts.EpochStart()) + require.Len(t, stakeEntries, 5) + for _, entry := range stakeEntries { + require.Equal(t, int64(1000), entry.DelegateTotal.Amount.Int64()) + } + + // unstake spec0 provider + _, err = ts.TxPairingUnstakeProvider(provider0.GetVaultAddr(), SpecName(0)) + require.NoError(t, err) + + // check redistribution of delegation + for i := 1; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(1250), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + // unstake all + for i := 1; i < 5; i++ { + _, err = ts.TxPairingUnstakeProvider(provider0.GetVaultAddr(), SpecName(i)) + require.NoError(t, err) + } + + res, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String()) + require.NoError(t, err) + require.Len(t, res.Delegations, 1) + require.Equal(t, provider0.Addr.String(), res.Delegations[0].Provider) + require.Equal(t, int64(5000), res.Delegations[0].Amount.Amount.Int64()) + + // stake again and check we got the delegation back + d := common.MockDescription() + err = ts.StakeProviderExtra(provider0.GetVaultAddr(), provider0.Addr.String(), ts.Spec(SpecName(0)), testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + res1, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, int64(5000), res1.StakeEntries[0].DelegateTotal.Amount.Int64()) + + // stake again on spec1 and check delegations + err = ts.StakeProviderExtra(provider0.GetVaultAddr(), provider0.Addr.String(), ts.Spec(SpecName(1)), testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + res1, err = ts.QueryPairingProvider(provider0.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, int64(2500), res1.StakeEntries[0].DelegateTotal.Amount.Int64()) + + res1, err = ts.QueryPairingProvider(provider0.Addr.String(), SpecName(1)) + require.NoError(t, err) + require.Equal(t, int64(2500), res1.StakeEntries[0].DelegateTotal.Amount.Int64()) + + ts.AdvanceEpoch() + + stakeEntries = ts.Keepers.Epochstorage.GetAllStakeEntriesForEpoch(ts.Ctx, ts.EpochStart()) + require.Len(t, stakeEntries, 2) + for _, entry := range stakeEntries { + require.Equal(t, int64(2500), entry.DelegateTotal.Amount.Int64()) + } +} + +// * unstake to see the delegations distributions +// * unstake from the rest of the chains +// * stake to get all delegations back with a new vault +func TestUnstakeStakeNewVault(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 1, 5, 0) + + delegator, _ := ts.AddAccount("del", 1, 1000000000) + provider0, _ := ts.GetAccount(common.PROVIDER, 0) + provider1, _ := ts.AddAccount(common.PROVIDER, 1, 1000000000) + + // delegate and check delegatetotal + _, err := ts.TxDualstakingDelegate(delegator.Addr.String(), provider0.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), 5000)) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(1000), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + ts.AdvanceEpoch() + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(1000), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + // unstake all + for i := 0; i < 5; i++ { + _, err = ts.TxPairingUnstakeProvider(provider0.GetVaultAddr(), SpecName(i)) + require.NoError(t, err) + + md, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider0.Addr.String()) + if i == 4 { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Len(t, md.Chains, 4-i) + } + } + + res, err := ts.QueryDualstakingDelegatorProviders(delegator.Addr.String()) + require.NoError(t, err) + require.Len(t, res.Delegations, 1) + require.Equal(t, provider0.Addr.String(), res.Delegations[0].Provider) + require.Equal(t, int64(5000), res.Delegations[0].Amount.Amount.Int64()) + + // stake again and check we got the delegation back + d := common.MockDescription() + err = ts.StakeProviderExtra(provider1.GetVaultAddr(), provider0.Addr.String(), ts.Spec(SpecName(0)), testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + res1, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, int64(5000), res1.StakeEntries[0].DelegateTotal.Amount.Int64()) + + // stake again on spec1 and check delegations + err = ts.StakeProviderExtra(provider1.GetVaultAddr(), provider0.Addr.String(), ts.Spec(SpecName(1)), testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + res1, err = ts.QueryPairingProvider(provider0.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, int64(2500), res1.StakeEntries[0].DelegateTotal.Amount.Int64()) + + res1, err = ts.QueryPairingProvider(provider0.Addr.String(), SpecName(1)) + require.NoError(t, err) + require.Equal(t, int64(2500), res1.StakeEntries[0].DelegateTotal.Amount.Int64()) +} + +func TestDelegations(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 1, 5, 0) + + delegator, _ := ts.AddAccount("del", 1, 1000000000) + provider, _ := ts.GetAccount(common.PROVIDER, 0) + + // delegate amount that does not divide by 5 + _, err := ts.TxDualstakingDelegate(delegator.Addr.String(), provider.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), 4999)) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(999), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + // unbond 4 tokens, now amount divides by 5 + _, err = ts.TxDualstakingUnbond(delegator.Addr.String(), provider.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), 4)) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(999), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + // add stake to spec0 + d := common.MockDescription() + err = ts.StakeProviderExtra(provider.GetVaultAddr(), provider.Addr.String(), ts.Spec(SpecName(0)), 2*testStake, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + // check delegate total is twice than others in spec0 + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, int64(1665), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + + for i := 1; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(832), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + // unbond with vault, should be uniformali + _, err = ts.TxDualstakingUnbond(provider.GetVaultAddr(), provider.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), testStake)) + require.NoError(t, err) + + res, err = ts.QueryPairingProvider(provider.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, testStake+testStake*4/5, res.StakeEntries[0].Stake.Amount.Int64()) + require.Equal(t, 4995*res.StakeEntries[0].Stake.Amount.Int64()/(5*testStake), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + + for i := 1; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, testStake*4/5, res.StakeEntries[0].Stake.Amount.Int64()) + require.Equal(t, 4995*res.StakeEntries[0].Stake.Amount.Int64()/(5*testStake), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + // unbond all delegator + _, err = ts.TxDualstakingUnbond(delegator.Addr.String(), provider.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), 4995)) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(0), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } +} + +func TestUnstakeWithOperator(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 1, 5, 0) + + provider, _ := ts.GetAccount(common.PROVIDER, 0) + + // unstake one chain + _, err := ts.TxPairingUnstakeProvider(provider.Addr.String(), SpecName(0)) + require.NoError(t, err) + + // check the entries got the stake of spec0 + for i := 1; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, testStake*5/4, res.StakeEntries[0].Stake.Amount.Int64()) + } + + // unstake everything + for i := 1; i < 5; i++ { + _, err := ts.TxPairingUnstakeProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + } + + res, err := ts.QueryPairingProvider(provider.Addr.String(), "") + require.NoError(t, err) + require.Len(t, res.StakeEntries, 0) + + // stake again + d := common.MockDescription() + err = ts.StakeProviderExtra(provider.GetVaultAddr(), provider.Addr.String(), ts.Spec(SpecName(0)), 1, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details) + require.NoError(ts.T, err) + + // check we got all the self delegations + res, err = ts.QueryPairingProvider(provider.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, testStake*5+1, res.StakeEntries[0].Stake.Amount.Int64()) +} + +func TestChangeCommisionAndDescription(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 0, 5, 0) + provider, _ := ts.AddAccount(common.PROVIDER, 0, testBalance) + + d := common.MockDescription() + err := ts.StakeProviderFull(provider.GetVaultAddr(), provider.Addr.String(), ts.Spec(SpecName(0)), 100, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, 50) + require.NoError(ts.T, err) + + md, err := ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider.Addr.String()) + require.NoError(ts.T, err) + require.Equal(t, d, md.Description) + require.Equal(t, md.DelegateCommission, uint64(50)) + + d.Moniker = "test2" + err = ts.StakeProviderFull(provider.GetVaultAddr(), provider.Addr.String(), ts.Spec(SpecName(1)), 100, nil, 0, d.Moniker, d.Identity, d.Website, d.SecurityContact, d.Details, 49) + require.NoError(ts.T, err) + + md, err = ts.Keepers.Epochstorage.GetMetadata(ts.Ctx, provider.Addr.String()) + require.NoError(ts.T, err) + require.Equal(t, d, md.Description) + require.Equal(t, md.DelegateCommission, uint64(49)) + + res, err := ts.QueryPairingProviders(ts.Spec(SpecName(0)).Index, true) + require.NoError(ts.T, err) + require.Equal(t, d, res.StakeEntry[0].Description) + require.Equal(t, uint64(49), res.StakeEntry[0].DelegateCommission) + + res1, err := ts.QueryPairingProvider(provider.Addr.String(), "") + require.NoError(ts.T, err) + require.Equal(t, d, res1.StakeEntries[0].Description) + require.Equal(t, uint64(49), res1.StakeEntries[0].DelegateCommission) +} + +func TestMoveStake(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 1, 5, 0) + + delegator, _ := ts.AddAccount("del", 1, 1000000000) + provider0, _ := ts.GetAccount(common.PROVIDER, 0) + + // delegate and check delegatetotal + _, err := ts.TxDualstakingDelegate(delegator.Addr.String(), provider0.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), 5000)) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(1000), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } + + _, err = ts.TxPairingMoveStake(provider0.GetVaultAddr(), SpecName(1), SpecName(0), testStake/2) + require.NoError(t, err) + + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(0)) + require.NoError(t, err) + require.Equal(t, int64(1500), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + + res, err = ts.QueryPairingProvider(provider0.Addr.String(), SpecName(1)) + require.NoError(t, err) + require.Equal(t, int64(500), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + + for i := 2; i < 5; i++ { + res, err := ts.QueryPairingProvider(provider0.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(1000), res.StakeEntries[0].DelegateTotal.Amount.Int64()) + } +} + +func TestPairingWithDelegationDistributions(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 0, 2, 1) + + stake := int64(1000) + delegator, _ := ts.AddAccount("del", 1, stake*10000) + client, _ := ts.GetAccount(common.CONSUMER, 0) + spec := ts.Spec(SpecName(0)) + + // stake for spec0 + for i := 0; i < 100; i++ { + acc, addr := ts.AddAccount(common.PROVIDER, i, testBalance) + err := ts.StakeProvider(acc.GetVaultAddr(), addr, spec, stake) + require.NoError(ts.T, err) + } + provider, _ := ts.GetAccount(common.PROVIDER, 0) + + // delegate a lot of stake to the first provider + _, err := ts.TxDualstakingDelegate(delegator.Addr.String(), provider.Addr.String(), types.NewInt64Coin(ts.TokenDenom(), stake*10000)) + require.NoError(t, err) + + numOfPairing := 0 + for i := 0; i < 100; i++ { + ts.AdvanceEpoch() + + // make sure the provider is in the pairing list + res, err := ts.QueryPairingGetPairing(spec.Index, client.Addr.String()) + require.NoError(t, err) + found := false + for _, p := range res.Providers { + if p.Address == provider.Addr.String() { + found = true + break + } + } + if found { + numOfPairing++ + } + } + require.Greater(t, numOfPairing, 95) + + spec = ts.Spec(SpecName(1)) + // stake to spec1 + for i := 0; i < 100; i++ { + acc, addr := ts.GetAccount(common.PROVIDER, i) + err := ts.StakeProvider(acc.GetVaultAddr(), addr, spec, stake) + require.NoError(ts.T, err) + } + + // check that provider is in pairing in spec1 + numOfPairing = 0 + for i := 0; i < 100; i++ { + ts.AdvanceEpoch() + + // make sure the provider is in the pairing list + res, err := ts.QueryPairingGetPairing(spec.Index, client.Addr.String()) + require.NoError(t, err) + found := false + for _, p := range res.Providers { + if p.Address == provider.Addr.String() { + found = true + break + } + } + if found { + numOfPairing++ + } + } + require.Greater(t, numOfPairing, 95) +} + +func TestDistributionCli(t *testing.T) { + ts := newTester(t) + SetupForSingleProviderTests(ts, 1, 100, 0) + + provider, _ := ts.GetAccount(common.PROVIDER, 0) + + res, err := ts.QueryPairingProvider(provider.Addr.String(), "") + require.NoError(t, err) + + // distribute each provider 0.1% and last with 90.1% + distribution := "" + for i := 0; i < 99; i++ { + distribution = distribution + SpecName(i) + "," + "0.1" + "," + } + distribution = distribution + SpecName(99) + "," + "90.1" + + // get the msgs and run + msgs, err := cli.CalculateDistbiruitions(provider.Addr.String(), res.StakeEntries, distribution) + require.NoError(t, err) + for _, msgRaw := range msgs { + msg, ok := msgRaw.(*pairingtypes.MsgMoveProviderStake) + require.True(t, ok) + require.Equal(t, provider.Addr.String(), msg.Creator) + require.Equal(t, SpecName(99), msg.DstChain) + require.NotEqual(t, SpecName(99), msg.SrcChain) + require.Equal(t, int64(90000), msg.Amount.Amount.Int64()) + + _, err := ts.Servers.PairingServer.MoveProviderStake(ts.Ctx, msg) + require.NoError(t, err) + } + + // check the stake entries on chain + for i := 0; i < 99; i++ { + res, err = ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, int64(10000), res.StakeEntries[0].Stake.Amount.Int64()) + } + + res, err = ts.QueryPairingProvider(provider.Addr.String(), SpecName(99)) + require.NoError(t, err) + require.Equal(t, int64(9010000), res.StakeEntries[0].Stake.Amount.Int64()) + + // distribute back to 1% each + res, err = ts.QueryPairingProvider(provider.Addr.String(), "") + require.NoError(t, err) + + distribution = "" + for i := 0; i < 100; i++ { + distribution = distribution + SpecName(i) + "," + "1" + "," + } + distribution = distribution[:len(distribution)-1] + + msgs, err = cli.CalculateDistbiruitions(provider.Addr.String(), res.StakeEntries, distribution) + require.NoError(t, err) + for _, msgRaw := range msgs { + msg, ok := msgRaw.(*pairingtypes.MsgMoveProviderStake) + require.True(t, ok) + require.Equal(t, provider.Addr.String(), msg.Creator) + require.Equal(t, SpecName(99), msg.SrcChain) + require.NotEqual(t, SpecName(99), msg.DstChain) + require.Equal(t, int64(90000), msg.Amount.Amount.Int64()) + + _, err := ts.Servers.PairingServer.MoveProviderStake(ts.Ctx, msg) + require.NoError(t, err) + } + + for i := 0; i < 100; i++ { + res, err = ts.QueryPairingProvider(provider.Addr.String(), SpecName(i)) + require.NoError(t, err) + require.Equal(t, testStake, res.StakeEntries[0].Stake.Amount.Int64()) + } +} diff --git a/x/pairing/keeper/staking.go b/x/pairing/keeper/staking.go index 5f4d179e7c..a2e0850e03 100644 --- a/x/pairing/keeper/staking.go +++ b/x/pairing/keeper/staking.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/lavanet/lava/v3/utils" + "github.com/lavanet/lava/v3/utils/lavaslices" epochstoragetypes "github.com/lavanet/lava/v3/x/epochstorage/types" "github.com/lavanet/lava/v3/x/pairing/types" planstypes "github.com/lavanet/lava/v3/x/plans/types" @@ -23,6 +24,19 @@ func (k Keeper) StakeNewEntry(ctx sdk.Context, validator, creator, chainID strin logger := k.Logger(ctx) specChainID := chainID + metadata, err := k.epochStorageKeeper.GetMetadata(ctx, provider) + if err != nil { + // first provider with this address + metadata = epochstoragetypes.ProviderMetadata{ + Provider: provider, + Vault: creator, + Chains: []string{chainID}, + TotalDelegations: sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), sdk.ZeroInt()), + } + } else { + metadata.Chains = lavaslices.AddUnique(metadata.Chains, chainID) + } + spec, err := k.specKeeper.GetExpandedSpec(ctx, specChainID) if err != nil || !spec.Enabled { return utils.LavaFormatWarning("spec not found or not active", err, @@ -31,14 +45,6 @@ func (k Keeper) StakeNewEntry(ctx sdk.Context, validator, creator, chainID strin } // if we get here, the spec is active and supported - if amount.IsLT(k.dualstakingKeeper.MinSelfDelegation(ctx)) { // we count on this to also check the denom - return utils.LavaFormatWarning("insufficient stake amount", fmt.Errorf("stake amount smaller than MinSelfDelegation"), - utils.Attribute{Key: "spec", Value: specChainID}, - utils.Attribute{Key: "provider", Value: creator}, - utils.Attribute{Key: "stake", Value: amount}, - utils.Attribute{Key: "minSelfDelegation", Value: k.dualstakingKeeper.MinSelfDelegation(ctx).String()}, - ) - } senderAddr, err := sdk.AccAddressFromBech32(creator) if err != nil { return utils.LavaFormatWarning("invalid address", err, @@ -94,15 +100,14 @@ func (k Keeper) StakeNewEntry(ctx sdk.Context, validator, creator, chainID strin // verify that the provider only tries to change non-stake related traits of the stake entry // a provider can be the same as the vault, so we verify it's not the case if isProvider { - if delegationCommission != existingEntry.DelegateCommission || + if delegationCommission != metadata.DelegateCommission || !amount.Equal(existingEntry.Stake) { return utils.LavaFormatWarning("only vault address can change stake/delegation related properties of the stake entry", fmt.Errorf("invalid modification request for stake entry"), utils.LogAttr("creator", creator), utils.LogAttr("vault", existingEntry.Vault), utils.LogAttr("provider", provider), utils.LogAttr("description", description.String()), - utils.LogAttr("req_delegation_limit", delegationLimit), - utils.LogAttr("current_delegation_commission", existingEntry.DelegateCommission), + utils.LogAttr("current_delegation_commission", metadata.DelegateCommission), utils.LogAttr("req_delegation_commission", delegationCommission), utils.LogAttr("current_stake", existingEntry.Stake.String()), utils.LogAttr("req_stake", amount.String()), @@ -131,48 +136,52 @@ func (k Keeper) StakeNewEntry(ctx sdk.Context, validator, creator, chainID strin // if the provider has no delegations then we dont limit the changes if !existingEntry.DelegateTotal.IsZero() { // if there was a change in the last 24h than we dont allow changes - if ctx.BlockTime().UTC().Unix()-int64(existingEntry.LastChange) < int64(CHANGE_WINDOW.Seconds()) { - if delegationCommission != existingEntry.DelegateCommission { + if ctx.BlockTime().UTC().Unix()-int64(metadata.LastChange) < int64(CHANGE_WINDOW.Seconds()) { + if delegationCommission != metadata.DelegateCommission { return utils.LavaFormatWarning(fmt.Sprintf("stake entry commmision or delegate limit can only be changes once in %s", CHANGE_WINDOW), nil, - utils.LogAttr("last_change_time", existingEntry.LastChange)) + utils.LogAttr("last_change_time", metadata.LastChange)) } } // check that the change is not mode than MAX_CHANGE_RATE - if int64(delegationCommission)-int64(existingEntry.DelegateCommission) > MAX_CHANGE_RATE { + if int64(delegationCommission)-int64(metadata.DelegateCommission) > MAX_CHANGE_RATE { return utils.LavaFormatWarning("stake entry commission increase too high", fmt.Errorf("commission change cannot increase by more than %d at a time", MAX_CHANGE_RATE), - utils.LogAttr("original_commission", existingEntry.DelegateCommission), + utils.LogAttr("original_commission", metadata.DelegateCommission), utils.LogAttr("wanted_commission", delegationCommission), ) } } // we dont change stakeAppliedBlocks and chain once they are set, if they need to change, unstake first + beforeAmount := existingEntry.Stake + increase := amount.Amount.GT(existingEntry.Stake.Amount) + decrease := amount.Amount.LT(existingEntry.Stake.Amount) existingEntry.Geolocation = geolocation existingEntry.Endpoints = endpointsVerified - existingEntry.Description = description - existingEntry.DelegateCommission = delegationCommission - existingEntry.LastChange = uint64(ctx.BlockTime().UTC().Unix()) + metadata.Description = description + metadata.DelegateCommission = delegationCommission + metadata.LastChange = uint64(ctx.BlockTime().UTC().Unix()) + existingEntry.Stake = amount k.epochStorageKeeper.SetStakeEntryCurrent(ctx, existingEntry) - - if amount.Amount.GT(existingEntry.Stake.Amount) { + k.epochStorageKeeper.SetMetadata(ctx, metadata) + if increase { // delegate the difference - diffAmount := amount.Sub(existingEntry.Stake) - err = k.dualstakingKeeper.DelegateFull(ctx, existingEntry.Vault, validator, existingEntry.Address, chainID, diffAmount) + diffAmount := amount.Sub(beforeAmount) + err = k.dualstakingKeeper.DelegateFull(ctx, existingEntry.Vault, validator, existingEntry.Address, diffAmount, true) if err != nil { details = append(details, utils.Attribute{Key: "neededStake", Value: amount.Sub(existingEntry.Stake).String()}) - return utils.LavaFormatWarning("insufficient funds to pay for difference in stake", err, + return utils.LavaFormatWarning("failed to increase stake", err, details..., ) } - } else if amount.Amount.LT(existingEntry.Stake.Amount) { + } else if decrease { // unbond the difference - diffAmount := existingEntry.Stake.Sub(amount) - err = k.dualstakingKeeper.UnbondFull(ctx, existingEntry.Vault, validator, existingEntry.Address, chainID, diffAmount, false) + diffAmount := beforeAmount.Sub(amount) + err = k.dualstakingKeeper.UnbondFull(ctx, existingEntry.Vault, validator, existingEntry.Address, diffAmount, true) if err != nil { details = append(details, utils.Attribute{Key: "neededStake", Value: amount.Sub(existingEntry.Stake).String()}) - return utils.LavaFormatWarning("insufficient funds to pay for difference in stake", err, + return utils.LavaFormatWarning("failed to decrease stake", err, details..., ) } @@ -201,6 +210,13 @@ func (k Keeper) StakeNewEntry(ctx sdk.Context, validator, creator, chainID strin } } + if creator != metadata.Vault { + return utils.LavaFormatWarning("creator does not match the provider vault", err, + utils.Attribute{Key: "vault", Value: metadata.Vault}, + utils.Attribute{Key: "creator", Value: creator}, + ) + } + // entry isn't staked so add him details := []utils.Attribute{ {Key: "spec", Value: specChainID}, @@ -220,39 +236,49 @@ func (k Keeper) StakeNewEntry(ctx sdk.Context, validator, creator, chainID strin ) } - delegations, err := k.dualstakingKeeper.GetProviderDelegators(ctx, provider, nextEpoch) - if err != nil { - utils.LavaFormatWarning("cannot get provider's delegators", err, - utils.LogAttr("provider", provider), - utils.LogAttr("block", nextEpoch), - ) + stakeAmount := amount + // creating a new provider, fetch old delegation + if len(metadata.Chains) == 1 { + delegations, err := k.dualstakingKeeper.GetProviderDelegators(ctx, provider) + if err == nil { + for _, d := range delegations { + if d.Delegator == creator { + stakeAmount = stakeAmount.Add(d.Amount) + } else { + metadata.TotalDelegations = metadata.TotalDelegations.Add(d.Amount) + } + } + } } - for _, d := range delegations { - if (d.Delegator == creator && d.Provider == provider) || d.ChainID != chainID { - // ignore provider self delegation (delegator = vault, provider = provider) or delegations from other chains - continue - } - delegateTotal = delegateTotal.Add(d.Amount.Amount) + if stakeAmount.IsLT(k.dualstakingKeeper.MinSelfDelegation(ctx)) { // we count on this to also check the denom + return utils.LavaFormatWarning("insufficient stake amount", fmt.Errorf("stake amount smaller than MinSelfDelegation"), + utils.Attribute{Key: "spec", Value: specChainID}, + utils.Attribute{Key: "provider", Value: creator}, + utils.Attribute{Key: "stake", Value: amount}, + utils.Attribute{Key: "minSelfDelegation", Value: k.dualstakingKeeper.MinSelfDelegation(ctx).String()}, + ) } stakeEntry := epochstoragetypes.StakeEntry{ - Stake: sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), sdk.ZeroInt()), // we set this to 0 since the delegate will take care of this - Address: provider, - StakeAppliedBlock: stakeAppliedBlock, - Endpoints: endpointsVerified, - Geolocation: geolocation, - Chain: chainID, - Description: description, - DelegateTotal: sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), delegateTotal), - DelegateCommission: delegationCommission, - Vault: creator, // the stake-provider TX creator is always regarded as the vault address - LastChange: uint64(ctx.BlockTime().UTC().Unix()), + Stake: stakeAmount, + Address: provider, + StakeAppliedBlock: stakeAppliedBlock, + Endpoints: endpointsVerified, + Geolocation: geolocation, + Chain: chainID, + DelegateTotal: sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), delegateTotal), + Vault: creator, // the stake-provider TX creator is always regarded as the vault address } + metadata.DelegateCommission = delegationCommission + metadata.LastChange = uint64(ctx.BlockTime().UTC().Unix()) + metadata.Description = description + + k.epochStorageKeeper.SetMetadata(ctx, metadata) k.epochStorageKeeper.SetStakeEntryCurrent(ctx, stakeEntry) - err = k.dualstakingKeeper.DelegateFull(ctx, stakeEntry.Vault, validator, stakeEntry.Address, chainID, amount) + err = k.dualstakingKeeper.DelegateFull(ctx, stakeEntry.Vault, validator, stakeEntry.Address, amount, true) if err != nil { return utils.LavaFormatWarning("provider self delegation failed", err, details..., diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index abaf11842c..28f34f1370 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -429,7 +429,7 @@ func TestJailProviderForUnresponsiveness(t *testing.T) { // jail first time jailProvider() // try to unfreeze with increase of self delegation - _, err = ts.TxDualstakingDelegate(provider1, provider1, ts.spec.Index, common.NewCoin(ts.TokenDenom(), 1)) + _, err = ts.TxDualstakingDelegate(provider1, provider1, common.NewCoin(ts.TokenDenom(), 1)) require.Nil(t, err) _, err = ts.TxPairingUnfreezeProvider(provider1, ts.spec.Index) @@ -457,7 +457,7 @@ func TestJailProviderForUnresponsiveness(t *testing.T) { // jail third time jailProvider() // try to unfreeze with increase of self delegation - _, err = ts.TxDualstakingDelegate(provider1, provider1, ts.spec.Index, common.NewCoin(ts.TokenDenom(), 1)) + _, err = ts.TxDualstakingDelegate(provider1, provider1, common.NewCoin(ts.TokenDenom(), 1)) require.Nil(t, err) _, err = ts.TxPairingUnfreezeProvider(provider1, ts.spec.Index) diff --git a/x/pairing/keeper/unstaking.go b/x/pairing/keeper/unstaking.go index 87d64d5174..c86bb75a48 100644 --- a/x/pairing/keeper/unstaking.go +++ b/x/pairing/keeper/unstaking.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/v3/utils" + epochstoragetypes "github.com/lavanet/lava/v3/x/epochstorage/types" "github.com/lavanet/lava/v3/x/pairing/types" ) @@ -36,8 +37,8 @@ func (k Keeper) UnstakeEntry(ctx sdk.Context, validator, chainID, creator, unsta ) } - if creator != existingEntry.Vault { - return utils.LavaFormatWarning("can't unstake entry with provider address, only vault address is allowed to unstake", fmt.Errorf("provider unstake failed"), + if creator != existingEntry.Vault && creator != existingEntry.Address { + return utils.LavaFormatWarning("unstake can be don only by provider or vault", fmt.Errorf("provider unstake failed"), utils.LogAttr("creator", creator), utils.LogAttr("provider", existingEntry.Address), utils.LogAttr("vault", existingEntry.Vault), @@ -45,13 +46,46 @@ func (k Keeper) UnstakeEntry(ctx sdk.Context, validator, chainID, creator, unsta ) } - // the stake entry is removed inside UnbondFull - err := k.dualstakingKeeper.UnbondFull(ctx, existingEntry.Vault, validator, existingEntry.Address, existingEntry.GetChain(), existingEntry.Stake, true) - if err != nil { - return utils.LavaFormatWarning("can't unbond self delegation", err, - utils.Attribute{Key: "address", Value: existingEntry.Address}, - utils.Attribute{Key: "spec", Value: chainID}, - ) + amount := existingEntry.Stake + k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, existingEntry.Chain, existingEntry.Address) + + if existingEntry.Vault == creator { + // remove delegation + err := k.dualstakingKeeper.UnbondFull(ctx, existingEntry.Vault, validator, existingEntry.Address, amount, true) + if err != nil { + return utils.LavaFormatWarning("can't unbond self delegation", err, + utils.Attribute{Key: "address", Value: existingEntry.Address}, + utils.Attribute{Key: "spec", Value: chainID}, + ) + } + } else { + // provider is not vault so delegation stays. + // distribute stake between other chains + metadata, err := k.epochStorageKeeper.GetMetadata(ctx, existingEntry.Address) + if err == nil { + entries := []*epochstoragetypes.StakeEntry{} + for _, chain := range metadata.Chains { + entry, found := k.epochStorageKeeper.GetStakeEntryCurrent(ctx, chain, existingEntry.Address) + if found { + entries = append(entries, &entry) + } else { + utils.LavaFormatError("did not find stake entry that exists in metadata", nil, + utils.LogAttr("provider", existingEntry.Address), + utils.LogAttr("chain", chain), + ) + } + } + + total := amount.Amount + count := int64(len(entries)) + for _, entry := range entries { + part := total.QuoRaw(count) + entry.Stake = entry.Stake.AddAmount(part) + total = total.Sub(part) + count-- + k.epochStorageKeeper.SetStakeEntryCurrent(ctx, *entry) + } + } } details := map[string]string{ @@ -96,7 +130,7 @@ func (k Keeper) UnstakeEntryForce(ctx sdk.Context, chainID, provider, unstakeDes amount = totalAmount } totalAmount = totalAmount.Sub(amount) - err = k.dualstakingKeeper.UnbondFull(ctx, existingEntry.Vault, validator.OperatorAddress, existingEntry.Address, existingEntry.GetChain(), sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), amount), true) + err = k.dualstakingKeeper.UnbondFull(ctx, existingEntry.Vault, validator.OperatorAddress, existingEntry.Address, sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), amount), true) if err != nil { return utils.LavaFormatWarning("can't unbond self delegation", err, utils.LogAttr("provider", existingEntry.Address), diff --git a/x/pairing/keeper/unstaking_test.go b/x/pairing/keeper/unstaking_test.go index cff2bf2537..7e0b3ebb5c 100644 --- a/x/pairing/keeper/unstaking_test.go +++ b/x/pairing/keeper/unstaking_test.go @@ -24,7 +24,7 @@ func TestUnstakeAndSlashProposal(t *testing.T) { for i := 0; i < delegators; i++ { _, delegator := ts.GetAccount(common.CONSUMER, i) beforeSlashDelegation[delegator] = sdk.NewInt(1000 * int64(i+1)) - _, err := ts.TxDualstakingDelegate(delegator, provider, ts.spec.Index, sdk.NewCoin(ts.BondDenom(), beforeSlashDelegation[delegator])) + _, err := ts.TxDualstakingDelegate(delegator, provider, sdk.NewCoin(ts.BondDenom(), beforeSlashDelegation[delegator])) require.NoError(t, err) delegatorsSlashing = append(delegatorsSlashing, types.DelegatorSlashing{Delegator: delegator, SlashingAmount: sdk.NewCoin(ts.BondDenom(), sdk.NewInt(1000/3*int64(i+1)))}) } @@ -38,7 +38,7 @@ func TestUnstakeAndSlashProposal(t *testing.T) { ) require.NoError(t, err) - result, err := ts.QueryDualstakingProviderDelegators(provider, true) + result, err := ts.QueryDualstakingProviderDelegators(provider) require.NoError(t, err) for _, d := range result.Delegations { for _, s := range delegatorsSlashing { diff --git a/x/pairing/module.go b/x/pairing/module.go index 5f605c9eb7..8692ed8ade 100644 --- a/x/pairing/module.go +++ b/x/pairing/module.go @@ -133,9 +133,13 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 2, migrator.MigrateVersion2To3); err != nil { panic(fmt.Errorf("%s: failed to register migration to v3: %w", types.ModuleName, err)) } - // register v3 -> v4 migration - if err := cfg.RegisterMigration(types.ModuleName, 3, migrator.MigrateVersion3To4); err != nil { - panic(fmt.Errorf("%s: failed to register migration to v4: %w", types.ModuleName, err)) + // // register v3 -> v4 migration + // if err := cfg.RegisterMigration(types.ModuleName, 3, migrator.MigrateVersion3To4); err != nil { + // panic(fmt.Errorf("%s: failed to register migration to v4: %w", types.ModuleName, err)) + // } + // register v4 -> v5 migration + if err := cfg.RegisterMigration(types.ModuleName, 4, migrator.MigrateVersion4To5); err != nil { + panic(fmt.Errorf("%s: failed to register migration to v5: %w", types.ModuleName, err)) } } @@ -161,7 +165,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 4 } +func (AppModule) ConsensusVersion() uint64 { return 5 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/pairing/types/codec.go b/x/pairing/types/codec.go index abac0115f6..8c75476c0d 100644 --- a/x/pairing/types/codec.go +++ b/x/pairing/types/codec.go @@ -16,6 +16,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgRelayPayment{}, "pairing/RelayPayment", nil) cdc.RegisterConcrete(&MsgFreezeProvider{}, "pairing/Freeze", nil) cdc.RegisterConcrete(&MsgUnfreezeProvider{}, "pairing/Unfreeze", nil) + cdc.RegisterConcrete(&MsgMoveProviderStake{}, "pairing/MoveProviderStake", nil) // this line is used by starport scaffolding # 2 } @@ -35,6 +36,9 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgUnfreezeProvider{}, ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgMoveProviderStake{}, + ) // this line is used by starport scaffolding # 3 msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/pairing/types/expected_keepers.go b/x/pairing/types/expected_keepers.go index b9ba3bed29..815b33048e 100644 --- a/x/pairing/types/expected_keepers.go +++ b/x/pairing/types/expected_keepers.go @@ -53,6 +53,8 @@ type EpochstorageKeeper interface { GetAllStakeEntriesCurrent(ctx sdk.Context) []epochstoragetypes.StakeEntry RemoveStakeEntryCurrent(ctx sdk.Context, chainID string, provider string) GetEpochHash(ctx sdk.Context, epoch uint64) []byte + GetMetadata(ctx sdk.Context, provider string) (epochstoragetypes.ProviderMetadata, error) + SetMetadata(ctx sdk.Context, metadata epochstoragetypes.ProviderMetadata) } type AccountKeeper interface { @@ -103,10 +105,12 @@ type DowntimeKeeper interface { type DualstakingKeeper interface { RewardProvidersAndDelegators(ctx sdk.Context, providerAddr string, chainID string, totalReward sdk.Coins, senderModule string, calcOnlyProvider bool, calcOnlyDelegators bool, calcOnlyContributor bool) (providerReward sdk.Coins, err error) - DelegateFull(ctx sdk.Context, delegator string, validator string, provider string, chainID string, amount sdk.Coin) error - UnbondFull(ctx sdk.Context, delegator string, validator string, provider string, chainID string, amount sdk.Coin, unstake bool) error - GetProviderDelegators(ctx sdk.Context, provider string, epoch uint64) ([]dualstakingtypes.Delegation, error) + DelegateFull(ctx sdk.Context, delegator string, validator string, provider string, amount sdk.Coin, stake bool) error + UnbondFull(ctx sdk.Context, delegator string, validator string, provider string, amount sdk.Coin, stake bool) error + GetProviderDelegators(ctx sdk.Context, provider string) ([]dualstakingtypes.Delegation, error) MinSelfDelegation(ctx sdk.Context) sdk.Coin + GetDelegation(ctx sdk.Context, provider, delegator string) (dualstakingtypes.Delegation, bool) + AfterDelegationModified(ctx sdk.Context, delegator, provider string, amount sdk.Coin, increase, stake bool) (err error) } type FixationStoreKeeper interface { diff --git a/x/pairing/types/message_move_provider_stake.go b/x/pairing/types/message_move_provider_stake.go new file mode 100644 index 0000000000..442085c265 --- /dev/null +++ b/x/pairing/types/message_move_provider_stake.go @@ -0,0 +1,49 @@ +package types + +import ( + sdkerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgMoveProviderStake = "MoveProviderStake" + +var _ sdk.Msg = &MsgMoveProviderStake{} + +func NewMsgMoveProviderStake(creator string, srcChain, dstChain string, amount sdk.Coin) *MsgMoveProviderStake { + return &MsgMoveProviderStake{ + Creator: creator, + SrcChain: srcChain, + DstChain: dstChain, + Amount: amount, + } +} + +func (msg *MsgMoveProviderStake) Route() string { + return RouterKey +} + +func (msg *MsgMoveProviderStake) Type() string { + return TypeMsgMoveProviderStake +} + +func (msg *MsgMoveProviderStake) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + return []sdk.AccAddress{creator} +} + +func (msg *MsgMoveProviderStake) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgMoveProviderStake) 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/pairing/types/tx.pb.go b/x/pairing/types/tx.pb.go index 0033fa0454..59b17da6ba 100644 --- a/x/pairing/types/tx.pb.go +++ b/x/pairing/types/tx.pb.go @@ -628,6 +628,110 @@ func (m *MsgUnfreezeProviderResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUnfreezeProviderResponse proto.InternalMessageInfo +type MsgMoveProviderStake struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + SrcChain string `protobuf:"bytes,2,opt,name=src_chain,json=srcChain,proto3" json:"src_chain,omitempty"` + DstChain string `protobuf:"bytes,3,opt,name=dst_chain,json=dstChain,proto3" json:"dst_chain,omitempty"` + Amount types.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgMoveProviderStake) Reset() { *m = MsgMoveProviderStake{} } +func (m *MsgMoveProviderStake) String() string { return proto.CompactTextString(m) } +func (*MsgMoveProviderStake) ProtoMessage() {} +func (*MsgMoveProviderStake) Descriptor() ([]byte, []int) { + return fileDescriptor_07b85a84d2198a91, []int{11} +} +func (m *MsgMoveProviderStake) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMoveProviderStake) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMoveProviderStake.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 *MsgMoveProviderStake) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMoveProviderStake.Merge(m, src) +} +func (m *MsgMoveProviderStake) XXX_Size() int { + return m.Size() +} +func (m *MsgMoveProviderStake) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMoveProviderStake.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMoveProviderStake proto.InternalMessageInfo + +func (m *MsgMoveProviderStake) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgMoveProviderStake) GetSrcChain() string { + if m != nil { + return m.SrcChain + } + return "" +} + +func (m *MsgMoveProviderStake) GetDstChain() string { + if m != nil { + return m.DstChain + } + return "" +} + +func (m *MsgMoveProviderStake) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + +type MsgMoveProviderStakeResponse struct { +} + +func (m *MsgMoveProviderStakeResponse) Reset() { *m = MsgMoveProviderStakeResponse{} } +func (m *MsgMoveProviderStakeResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMoveProviderStakeResponse) ProtoMessage() {} +func (*MsgMoveProviderStakeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_07b85a84d2198a91, []int{12} +} +func (m *MsgMoveProviderStakeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMoveProviderStakeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMoveProviderStakeResponse.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 *MsgMoveProviderStakeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMoveProviderStakeResponse.Merge(m, src) +} +func (m *MsgMoveProviderStakeResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMoveProviderStakeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMoveProviderStakeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMoveProviderStakeResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgStakeProvider)(nil), "lavanet.lava.pairing.MsgStakeProvider") proto.RegisterType((*MsgStakeProviderResponse)(nil), "lavanet.lava.pairing.MsgStakeProviderResponse") @@ -640,68 +744,75 @@ func init() { proto.RegisterType((*MsgFreezeProviderResponse)(nil), "lavanet.lava.pairing.MsgFreezeProviderResponse") proto.RegisterType((*MsgUnfreezeProvider)(nil), "lavanet.lava.pairing.MsgUnfreezeProvider") proto.RegisterType((*MsgUnfreezeProviderResponse)(nil), "lavanet.lava.pairing.MsgUnfreezeProviderResponse") + proto.RegisterType((*MsgMoveProviderStake)(nil), "lavanet.lava.pairing.MsgMoveProviderStake") + proto.RegisterType((*MsgMoveProviderStakeResponse)(nil), "lavanet.lava.pairing.MsgMoveProviderStakeResponse") } func init() { proto.RegisterFile("lavanet/lava/pairing/tx.proto", fileDescriptor_07b85a84d2198a91) } var fileDescriptor_07b85a84d2198a91 = []byte{ - // 887 bytes of a gzipped FileDescriptorProto + // 969 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x41, 0x73, 0xdb, 0x44, - 0x14, 0x8e, 0x12, 0xc5, 0xb1, 0x9f, 0xdb, 0xc4, 0xd9, 0xa4, 0x44, 0x51, 0x53, 0x63, 0x54, 0x20, - 0x26, 0x03, 0x12, 0x49, 0x0f, 0xcc, 0xf8, 0xe8, 0x86, 0x32, 0xed, 0xd4, 0x43, 0x46, 0x19, 0x0e, - 0x70, 0xf1, 0xac, 0xa5, 0x45, 0x51, 0x63, 0x69, 0x35, 0xda, 0xad, 0xa7, 0xe1, 0xcc, 0x89, 0x0b, - 0xf0, 0x13, 0xb8, 0x71, 0xec, 0xcf, 0xe8, 0xb1, 0x47, 0x4e, 0x0c, 0x93, 0x1c, 0xfa, 0x37, 0x98, - 0x5d, 0xad, 0x64, 0x4b, 0x76, 0x3a, 0x9e, 0x81, 0x4b, 0xac, 0xb7, 0xef, 0x7b, 0xef, 0xfb, 0xf4, - 0xbd, 0xb7, 0x19, 0xc1, 0x83, 0x31, 0x9e, 0xe0, 0x98, 0x70, 0x47, 0xfc, 0x3a, 0x09, 0x0e, 0xd3, - 0x30, 0x0e, 0x1c, 0xfe, 0xca, 0x4e, 0x52, 0xca, 0x29, 0xda, 0x55, 0x69, 0x5b, 0xfc, 0xda, 0x2a, - 0x6d, 0xb6, 0x3d, 0xca, 0x22, 0xca, 0x9c, 0x11, 0x66, 0xc4, 0x99, 0x1c, 0x8f, 0x08, 0xc7, 0xc7, - 0x8e, 0x47, 0xc3, 0x38, 0xab, 0x32, 0x77, 0x03, 0x1a, 0x50, 0xf9, 0xe8, 0x88, 0x27, 0x75, 0xda, - 0x2d, 0x51, 0x91, 0x84, 0x7a, 0x17, 0x8c, 0xd3, 0x14, 0x07, 0xc4, 0x21, 0xb1, 0x9f, 0xd0, 0x30, - 0xe6, 0x0a, 0xd9, 0x59, 0x28, 0x2a, 0x25, 0x63, 0x7c, 0xa5, 0x10, 0x1f, 0x2b, 0x05, 0x8c, 0xe3, - 0x4b, 0x91, 0xcb, 0x45, 0xa8, 0x58, 0xa1, 0xb6, 0x71, 0x14, 0xc6, 0xd4, 0x91, 0x7f, 0xb3, 0x23, - 0xeb, 0x57, 0x1d, 0x5a, 0x03, 0x16, 0x9c, 0x73, 0x7c, 0x49, 0xce, 0x52, 0x3a, 0x09, 0x7d, 0x92, - 0x22, 0x03, 0x36, 0xbc, 0x94, 0x60, 0x4e, 0x53, 0x43, 0xeb, 0x68, 0xdd, 0x86, 0x9b, 0x87, 0x32, - 0x73, 0x81, 0xc3, 0xf8, 0xe9, 0xa9, 0xb1, 0xaa, 0x32, 0x59, 0x88, 0xbe, 0x82, 0x1a, 0x8e, 0xe8, - 0xcb, 0x98, 0x1b, 0x6b, 0x1d, 0xad, 0xdb, 0x3c, 0xd9, 0xb7, 0x33, 0x49, 0xb6, 0x30, 0xc5, 0x56, - 0x7a, 0xec, 0xc7, 0x34, 0x8c, 0xfb, 0xfa, 0x9b, 0xbf, 0x3f, 0x5c, 0x71, 0x15, 0x1c, 0x7d, 0x03, - 0x8d, 0xfc, 0x75, 0x99, 0xa1, 0x77, 0xd6, 0xba, 0xcd, 0x93, 0x87, 0x76, 0xc9, 0xe6, 0x59, 0x6b, - 0xec, 0xaf, 0x15, 0x56, 0x75, 0x99, 0xd6, 0xa2, 0x0e, 0x34, 0x03, 0x42, 0xc7, 0xd4, 0xc3, 0x3c, - 0xa4, 0xb1, 0xb1, 0xde, 0xd1, 0xba, 0xeb, 0xee, 0xec, 0x11, 0x7a, 0x02, 0x9b, 0x3e, 0x19, 0x93, - 0x00, 0x73, 0x32, 0x1c, 0x87, 0x51, 0xc8, 0x8d, 0x8d, 0xe5, 0xb4, 0xde, 0xcd, 0xcb, 0x9e, 0x8b, - 0x2a, 0xe4, 0xc0, 0x4e, 0xd1, 0xc7, 0xa3, 0x51, 0x14, 0x32, 0x26, 0x18, 0xeb, 0x1d, 0xad, 0xab, - 0xbb, 0x28, 0x4f, 0x3d, 0x2e, 0x32, 0xe8, 0x00, 0x1a, 0x13, 0x3c, 0x0e, 0x7d, 0x69, 0x69, 0x43, - 0x1a, 0x37, 0x3d, 0x10, 0xa6, 0x62, 0xdf, 0x4f, 0x09, 0x63, 0x06, 0x64, 0xa6, 0xaa, 0x10, 0x9d, - 0x41, 0xd3, 0x27, 0xcc, 0x4b, 0xc3, 0x44, 0xbe, 0x52, 0x53, 0xaa, 0x7d, 0x98, 0xab, 0xcd, 0x87, - 0x9b, 0x0b, 0x3e, 0x9d, 0x42, 0xfb, 0x0d, 0xa1, 0xfb, 0xcf, 0x77, 0xaf, 0x8f, 0x34, 0x77, 0xb6, - 0x45, 0xcf, 0xfc, 0xe5, 0xdd, 0xeb, 0xa3, 0x7b, 0xf9, 0x0a, 0x95, 0xc6, 0xfe, 0x4c, 0xaf, 0xd7, - 0x5a, 0x1b, 0x96, 0x09, 0x46, 0x75, 0x21, 0x5c, 0xc2, 0x12, 0x1a, 0x33, 0x62, 0xfd, 0xac, 0x01, - 0x1a, 0xb0, 0xe0, 0xbb, 0x98, 0xfd, 0xe7, 0x7d, 0x29, 0x59, 0xb2, 0x56, 0xb1, 0xa4, 0x77, 0x20, - 0x64, 0xee, 0xe5, 0x32, 0x2b, 0x7c, 0xd6, 0x01, 0x98, 0xf3, 0x2a, 0x0a, 0x91, 0xbf, 0xaf, 0xc2, - 0xd6, 0x80, 0x05, 0xae, 0xb8, 0x1e, 0x67, 0xf8, 0x2a, 0x22, 0x31, 0x7f, 0x8f, 0xc2, 0x1e, 0xd4, - 0xe4, 0x45, 0x62, 0xc6, 0xaa, 0xdc, 0x3d, 0xcb, 0x5e, 0x74, 0xc5, 0x6d, 0xd9, 0xed, 0x9c, 0xc8, - 0x71, 0xba, 0xaa, 0x02, 0x7d, 0x0e, 0xdb, 0x33, 0xde, 0x9e, 0x73, 0x81, 0x34, 0x74, 0xd9, 0x7f, - 0x3e, 0x81, 0xbe, 0x87, 0xdd, 0x31, 0xe6, 0x84, 0xf1, 0xe1, 0x68, 0x4c, 0xbd, 0xcb, 0x61, 0x4a, - 0x12, 0x9a, 0x72, 0x66, 0xac, 0x4b, 0xde, 0xc3, 0xc5, 0xbc, 0xcf, 0x65, 0x45, 0x5f, 0x14, 0xb8, - 0x12, 0xef, 0xa2, 0x71, 0xf5, 0x88, 0xf5, 0xf6, 0x85, 0x5d, 0xbb, 0xb9, 0x5d, 0xb3, 0x6f, 0xfe, - 0x4c, 0xaf, 0xaf, 0xb5, 0x74, 0xeb, 0x5b, 0xd8, 0x9e, 0xeb, 0x84, 0xf6, 0x60, 0x83, 0x25, 0xc4, - 0x1b, 0x86, 0xbe, 0x32, 0xa5, 0x26, 0xc2, 0xa7, 0x3e, 0xfa, 0x08, 0xee, 0xcc, 0x2a, 0x95, 0xa3, - 0xd3, 0xdd, 0xe6, 0x0c, 0xb1, 0xd5, 0x87, 0xbd, 0x8a, 0xc7, 0xb9, 0xff, 0xe8, 0x10, 0xb6, 0x52, - 0xf2, 0x82, 0x78, 0x9c, 0xf8, 0x43, 0x65, 0xad, 0x68, 0x5f, 0x77, 0x37, 0xf3, 0x63, 0x59, 0xc6, - 0xac, 0x09, 0x6c, 0x0f, 0x58, 0xf0, 0x24, 0x25, 0xe4, 0xa7, 0x65, 0x76, 0xc9, 0x84, 0x7a, 0xb6, - 0x3c, 0x7e, 0x36, 0xab, 0x86, 0x5b, 0xc4, 0xe8, 0x03, 0x31, 0x45, 0xcc, 0x68, 0xac, 0x56, 0x49, - 0x45, 0xbd, 0x1d, 0x61, 0xcc, 0x66, 0x6e, 0x4c, 0x46, 0x65, 0xdd, 0x87, 0xfd, 0x39, 0xde, 0x62, - 0x7b, 0x46, 0xb0, 0x23, 0x77, 0xeb, 0xc7, 0xff, 0x41, 0x56, 0xef, 0x9e, 0xa0, 0x6f, 0x4d, 0xd7, - 0x38, 0x6b, 0x6a, 0x3d, 0x80, 0xfb, 0x0b, 0x38, 0x72, 0x09, 0x27, 0x7f, 0xe8, 0xb0, 0x36, 0x60, - 0x01, 0x0a, 0xe0, 0x6e, 0xf9, 0xff, 0xf2, 0xa7, 0x8b, 0x77, 0xa4, 0x7a, 0x5d, 0x4d, 0x7b, 0x39, - 0x5c, 0x31, 0xb1, 0x08, 0xb6, 0xaa, 0x57, 0xba, 0x7b, 0x6b, 0x8b, 0x0a, 0xd2, 0xfc, 0x72, 0x59, - 0x64, 0x41, 0xe7, 0xc3, 0x9d, 0xd2, 0xe5, 0xfc, 0xe4, 0xd6, 0x0e, 0xb3, 0x30, 0xf3, 0x8b, 0xa5, - 0x60, 0x05, 0xcb, 0x0b, 0xd8, 0xac, 0xac, 0xd6, 0xe1, 0xad, 0x0d, 0xca, 0x40, 0xd3, 0x59, 0x12, - 0x58, 0x70, 0x25, 0xd0, 0x9a, 0xdb, 0x98, 0xcf, 0xde, 0xe3, 0x4b, 0x19, 0x6a, 0x1e, 0x2f, 0x0d, - 0xcd, 0x19, 0xfb, 0xa7, 0x6f, 0xae, 0xdb, 0xda, 0xdb, 0xeb, 0xb6, 0xf6, 0xcf, 0x75, 0x5b, 0xfb, - 0xed, 0xa6, 0xbd, 0xf2, 0xf6, 0xa6, 0xbd, 0xf2, 0xd7, 0x4d, 0x7b, 0xe5, 0x87, 0xa3, 0x20, 0xe4, - 0x17, 0x2f, 0x47, 0xb6, 0x47, 0x23, 0xa7, 0xf4, 0xdd, 0x30, 0x79, 0xe4, 0xbc, 0x9a, 0x7e, 0xd1, - 0x5c, 0x25, 0x84, 0x8d, 0x6a, 0xf2, 0x23, 0xe0, 0xd1, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x78, - 0x28, 0x40, 0xa1, 0xf6, 0x08, 0x00, 0x00, + 0x14, 0x8e, 0x12, 0xc5, 0xb1, 0x9f, 0xdb, 0xc4, 0xde, 0xb8, 0x44, 0x51, 0x52, 0x63, 0x54, 0x20, + 0x26, 0x03, 0x12, 0x49, 0x0f, 0xcc, 0xf8, 0xe8, 0x84, 0x32, 0xed, 0xd4, 0x43, 0x46, 0x19, 0x0e, + 0x70, 0xf1, 0xac, 0xa5, 0x45, 0x51, 0x63, 0x6b, 0x35, 0xda, 0xad, 0xa7, 0xe1, 0xcc, 0x89, 0x0b, + 0x70, 0xe1, 0x37, 0x70, 0xec, 0x7f, 0xe0, 0xd2, 0x63, 0x8f, 0x9c, 0x18, 0x26, 0x39, 0xf4, 0x6f, + 0x30, 0xbb, 0x5a, 0xc9, 0xb6, 0xec, 0x64, 0xcc, 0xc0, 0xc5, 0xd2, 0xee, 0xfb, 0xf6, 0x7d, 0xdf, + 0x7e, 0xfb, 0xde, 0x5a, 0xf0, 0x70, 0x88, 0xc7, 0x38, 0x22, 0xdc, 0x11, 0x4f, 0x27, 0xc6, 0x61, + 0x12, 0x46, 0x81, 0xc3, 0x5f, 0xd9, 0x71, 0x42, 0x39, 0x45, 0x0d, 0x15, 0xb6, 0xc5, 0xd3, 0x56, + 0x61, 0xb3, 0xe9, 0x51, 0x36, 0xa2, 0xcc, 0x19, 0x60, 0x46, 0x9c, 0xf1, 0xd1, 0x80, 0x70, 0x7c, + 0xe4, 0x78, 0x34, 0x8c, 0xd2, 0x55, 0x66, 0x23, 0xa0, 0x01, 0x95, 0xaf, 0x8e, 0x78, 0x53, 0xb3, + 0xed, 0x19, 0x2a, 0x12, 0x53, 0xef, 0x82, 0x71, 0x9a, 0xe0, 0x80, 0x38, 0x24, 0xf2, 0x63, 0x1a, + 0x46, 0x5c, 0x21, 0x5b, 0x0b, 0x45, 0x25, 0x64, 0x88, 0xaf, 0x14, 0xe2, 0x43, 0xa5, 0x80, 0x71, + 0x7c, 0x29, 0x62, 0x99, 0x08, 0x35, 0x56, 0xa8, 0x3a, 0x1e, 0x85, 0x11, 0x75, 0xe4, 0x6f, 0x3a, + 0x65, 0xfd, 0xac, 0x43, 0xad, 0xc7, 0x82, 0x73, 0x8e, 0x2f, 0xc9, 0x59, 0x42, 0xc7, 0xa1, 0x4f, + 0x12, 0x64, 0xc0, 0x86, 0x97, 0x10, 0xcc, 0x69, 0x62, 0x68, 0x2d, 0xad, 0x5d, 0x71, 0xb3, 0xa1, + 0x8c, 0x5c, 0xe0, 0x30, 0x7a, 0x7a, 0x6a, 0xac, 0xaa, 0x48, 0x3a, 0x44, 0x5f, 0x40, 0x09, 0x8f, + 0xe8, 0xcb, 0x88, 0x1b, 0x6b, 0x2d, 0xad, 0x5d, 0x3d, 0xde, 0xb5, 0x53, 0x49, 0xb6, 0x30, 0xc5, + 0x56, 0x7a, 0xec, 0x13, 0x1a, 0x46, 0x5d, 0xfd, 0xcd, 0x5f, 0xef, 0xaf, 0xb8, 0x0a, 0x8e, 0xbe, + 0x82, 0x4a, 0xb6, 0x5d, 0x66, 0xe8, 0xad, 0xb5, 0x76, 0xf5, 0xf8, 0x91, 0x3d, 0x63, 0xf3, 0xb4, + 0x35, 0xf6, 0x97, 0x0a, 0xab, 0xb2, 0x4c, 0xd6, 0xa2, 0x16, 0x54, 0x03, 0x42, 0x87, 0xd4, 0xc3, + 0x3c, 0xa4, 0x91, 0xb1, 0xde, 0xd2, 0xda, 0xeb, 0xee, 0xf4, 0x14, 0x7a, 0x02, 0x9b, 0x3e, 0x19, + 0x92, 0x00, 0x73, 0xd2, 0x1f, 0x86, 0xa3, 0x90, 0x1b, 0x1b, 0xcb, 0x69, 0xbd, 0x9f, 0x2d, 0x7b, + 0x2e, 0x56, 0x21, 0x07, 0xb6, 0xf3, 0x3c, 0x1e, 0x1d, 0x8d, 0x42, 0xc6, 0x04, 0x63, 0xb9, 0xa5, + 0xb5, 0x75, 0x17, 0x65, 0xa1, 0x93, 0x3c, 0x82, 0xf6, 0xa1, 0x32, 0xc6, 0xc3, 0xd0, 0x97, 0x96, + 0x56, 0xa4, 0x71, 0x93, 0x09, 0x61, 0x2a, 0xf6, 0xfd, 0x84, 0x30, 0x66, 0x40, 0x6a, 0xaa, 0x1a, + 0xa2, 0x33, 0xa8, 0xfa, 0x84, 0x79, 0x49, 0x18, 0xcb, 0x2d, 0x55, 0xa5, 0xda, 0x47, 0x99, 0xda, + 0xec, 0x70, 0x33, 0xc1, 0xa7, 0x13, 0x68, 0xb7, 0x22, 0x74, 0xff, 0xfe, 0xee, 0xf5, 0xa1, 0xe6, + 0x4e, 0xa7, 0xe8, 0x98, 0x3f, 0xbd, 0x7b, 0x7d, 0xf8, 0x20, 0x2b, 0xa1, 0x99, 0x63, 0x7f, 0xa6, + 0x97, 0x4b, 0xb5, 0x0d, 0xcb, 0x04, 0xa3, 0x58, 0x10, 0x2e, 0x61, 0x31, 0x8d, 0x18, 0xb1, 0x7e, + 0xd4, 0x00, 0xf5, 0x58, 0xf0, 0x4d, 0xc4, 0xfe, 0x73, 0xbd, 0xcc, 0x58, 0xb2, 0x56, 0xb0, 0xa4, + 0xb3, 0x2f, 0x64, 0xee, 0x64, 0x32, 0x0b, 0x7c, 0xd6, 0x3e, 0x98, 0xf3, 0x2a, 0x72, 0x91, 0xbf, + 0xae, 0xc2, 0x56, 0x8f, 0x05, 0xae, 0x68, 0x8f, 0x33, 0x7c, 0x35, 0x22, 0x11, 0xbf, 0x43, 0x61, + 0x07, 0x4a, 0xb2, 0x91, 0x98, 0xb1, 0x2a, 0x6b, 0xcf, 0xb2, 0x17, 0xb5, 0xb8, 0x2d, 0xb3, 0x9d, + 0x13, 0x79, 0x9c, 0xae, 0x5a, 0x81, 0x3e, 0x85, 0xfa, 0x94, 0xb7, 0xe7, 0x5c, 0x20, 0x0d, 0x5d, + 0xe6, 0x9f, 0x0f, 0xa0, 0x6f, 0xa1, 0x31, 0xc4, 0x9c, 0x30, 0xde, 0x1f, 0x0c, 0xa9, 0x77, 0xd9, + 0x4f, 0x48, 0x4c, 0x13, 0xce, 0x8c, 0x75, 0xc9, 0x7b, 0xb0, 0x98, 0xf7, 0xb9, 0x5c, 0xd1, 0x15, + 0x0b, 0x5c, 0x89, 0x77, 0xd1, 0xb0, 0x38, 0xc5, 0x3a, 0xbb, 0xc2, 0xae, 0x46, 0x66, 0xd7, 0xf4, + 0xce, 0x9f, 0xe9, 0xe5, 0xb5, 0x9a, 0x6e, 0x7d, 0x0d, 0xf5, 0xb9, 0x4c, 0x68, 0x07, 0x36, 0x58, + 0x4c, 0xbc, 0x7e, 0xe8, 0x2b, 0x53, 0x4a, 0x62, 0xf8, 0xd4, 0x47, 0x1f, 0xc0, 0xbd, 0x69, 0xa5, + 0xf2, 0xe8, 0x74, 0xb7, 0x3a, 0x45, 0x6c, 0x75, 0x61, 0xa7, 0xe0, 0x71, 0xe6, 0x3f, 0x3a, 0x80, + 0xad, 0x84, 0xbc, 0x20, 0x1e, 0x27, 0x7e, 0x5f, 0x59, 0x2b, 0xd2, 0x97, 0xdd, 0xcd, 0x6c, 0x5a, + 0x2e, 0x63, 0xd6, 0x18, 0xea, 0x3d, 0x16, 0x3c, 0x49, 0x08, 0xf9, 0x61, 0x99, 0x5a, 0x32, 0xa1, + 0x9c, 0x16, 0x8f, 0x9f, 0x9e, 0x55, 0xc5, 0xcd, 0xc7, 0xe8, 0x3d, 0x71, 0x8a, 0x98, 0xd1, 0x48, + 0x95, 0x92, 0x1a, 0x75, 0xb6, 0x85, 0x31, 0x9b, 0x99, 0x31, 0x29, 0x95, 0xb5, 0x07, 0xbb, 0x73, + 0xbc, 0x79, 0xf5, 0x0c, 0x60, 0x5b, 0xd6, 0xd6, 0xf7, 0xff, 0x83, 0xac, 0xce, 0x03, 0x41, 0x5f, + 0x9b, 0x94, 0x71, 0x9a, 0xd4, 0x7a, 0x08, 0x7b, 0x0b, 0x38, 0x72, 0x09, 0x7f, 0x68, 0xd0, 0xe8, + 0xb1, 0xa0, 0x47, 0xc7, 0x79, 0x4c, 0xb6, 0xe3, 0x1d, 0x22, 0xf6, 0xa0, 0xc2, 0x12, 0xaf, 0x2f, + 0x89, 0x55, 0xa7, 0x95, 0x59, 0xe2, 0x9d, 0x88, 0xb1, 0x08, 0xfa, 0x8c, 0xab, 0x60, 0xea, 0x4f, + 0xd9, 0x67, 0x3c, 0x0d, 0x4e, 0xee, 0x6d, 0xfd, 0x5f, 0xdd, 0xdb, 0x9d, 0xa6, 0xd8, 0xdb, 0x6e, + 0xb6, 0xb7, 0x39, 0xb1, 0x56, 0x13, 0xf6, 0x17, 0x6d, 0x22, 0xdb, 0xe5, 0xf1, 0x6f, 0xeb, 0xb0, + 0xd6, 0x63, 0x01, 0x0a, 0xe0, 0xfe, 0xec, 0xbf, 0xcf, 0xc7, 0x8b, 0x3b, 0xa1, 0x78, 0x29, 0x99, + 0xf6, 0x72, 0xb8, 0xbc, 0x2e, 0x47, 0xb0, 0x55, 0xbc, 0xb8, 0xda, 0xb7, 0xa6, 0x28, 0x20, 0xcd, + 0xcf, 0x97, 0x45, 0xe6, 0x74, 0x3e, 0xdc, 0x9b, 0xb9, 0x82, 0x3e, 0xba, 0x35, 0xc3, 0x34, 0xcc, + 0xfc, 0x6c, 0x29, 0x58, 0xce, 0xf2, 0x02, 0x36, 0x0b, 0x0d, 0x74, 0x70, 0x6b, 0x82, 0x59, 0xa0, + 0xe9, 0x2c, 0x09, 0xcc, 0xb9, 0x62, 0xa8, 0xcd, 0xf5, 0xc5, 0x27, 0x77, 0xf8, 0x32, 0x0b, 0x35, + 0x8f, 0x96, 0x86, 0xe6, 0x8c, 0x0c, 0xea, 0xf3, 0x5d, 0x70, 0x78, 0x6b, 0x9e, 0x39, 0xac, 0x79, + 0xbc, 0x3c, 0x36, 0x23, 0xed, 0x9e, 0xbe, 0xb9, 0x6e, 0x6a, 0x6f, 0xaf, 0x9b, 0xda, 0xdf, 0xd7, + 0x4d, 0xed, 0x97, 0x9b, 0xe6, 0xca, 0xdb, 0x9b, 0xe6, 0xca, 0x9f, 0x37, 0xcd, 0x95, 0xef, 0x0e, + 0x83, 0x90, 0x5f, 0xbc, 0x1c, 0xd8, 0x1e, 0x1d, 0x39, 0x33, 0x9f, 0x64, 0xe3, 0xc7, 0xce, 0xab, + 0xc9, 0xc7, 0xe2, 0x55, 0x4c, 0xd8, 0xa0, 0x24, 0xbf, 0xaf, 0x1e, 0xff, 0x13, 0x00, 0x00, 0xff, + 0xff, 0x5b, 0x67, 0x92, 0xf3, 0x51, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -721,6 +832,7 @@ type MsgClient interface { RelayPayment(ctx context.Context, in *MsgRelayPayment, opts ...grpc.CallOption) (*MsgRelayPaymentResponse, error) FreezeProvider(ctx context.Context, in *MsgFreezeProvider, opts ...grpc.CallOption) (*MsgFreezeProviderResponse, error) UnfreezeProvider(ctx context.Context, in *MsgUnfreezeProvider, opts ...grpc.CallOption) (*MsgUnfreezeProviderResponse, error) + MoveProviderStake(ctx context.Context, in *MsgMoveProviderStake, opts ...grpc.CallOption) (*MsgMoveProviderStakeResponse, error) } type msgClient struct { @@ -776,6 +888,15 @@ func (c *msgClient) UnfreezeProvider(ctx context.Context, in *MsgUnfreezeProvide return out, nil } +func (c *msgClient) MoveProviderStake(ctx context.Context, in *MsgMoveProviderStake, opts ...grpc.CallOption) (*MsgMoveProviderStakeResponse, error) { + out := new(MsgMoveProviderStakeResponse) + err := c.cc.Invoke(ctx, "/lavanet.lava.pairing.Msg/MoveProviderStake", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { StakeProvider(context.Context, *MsgStakeProvider) (*MsgStakeProviderResponse, error) @@ -783,6 +904,7 @@ type MsgServer interface { RelayPayment(context.Context, *MsgRelayPayment) (*MsgRelayPaymentResponse, error) FreezeProvider(context.Context, *MsgFreezeProvider) (*MsgFreezeProviderResponse, error) UnfreezeProvider(context.Context, *MsgUnfreezeProvider) (*MsgUnfreezeProviderResponse, error) + MoveProviderStake(context.Context, *MsgMoveProviderStake) (*MsgMoveProviderStakeResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -804,6 +926,9 @@ func (*UnimplementedMsgServer) FreezeProvider(ctx context.Context, req *MsgFreez func (*UnimplementedMsgServer) UnfreezeProvider(ctx context.Context, req *MsgUnfreezeProvider) (*MsgUnfreezeProviderResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UnfreezeProvider not implemented") } +func (*UnimplementedMsgServer) MoveProviderStake(ctx context.Context, req *MsgMoveProviderStake) (*MsgMoveProviderStakeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MoveProviderStake not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -899,6 +1024,24 @@ func _Msg_UnfreezeProvider_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _Msg_MoveProviderStake_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMoveProviderStake) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).MoveProviderStake(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/lavanet.lava.pairing.Msg/MoveProviderStake", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).MoveProviderStake(ctx, req.(*MsgMoveProviderStake)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "lavanet.lava.pairing.Msg", HandlerType: (*MsgServer)(nil), @@ -923,6 +1066,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "UnfreezeProvider", Handler: _Msg_UnfreezeProvider_Handler, }, + { + MethodName: "MoveProviderStake", + Handler: _Msg_MoveProviderStake_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "lavanet/lava/pairing/tx.proto", @@ -1387,6 +1534,83 @@ func (m *MsgUnfreezeProviderResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *MsgMoveProviderStake) 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 *MsgMoveProviderStake) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMoveProviderStake) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.DstChain) > 0 { + i -= len(m.DstChain) + copy(dAtA[i:], m.DstChain) + i = encodeVarintTx(dAtA, i, uint64(len(m.DstChain))) + i-- + dAtA[i] = 0x1a + } + if len(m.SrcChain) > 0 { + i -= len(m.SrcChain) + copy(dAtA[i:], m.SrcChain) + i = encodeVarintTx(dAtA, i, uint64(len(m.SrcChain))) + i-- + dAtA[i] = 0x12 + } + 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 *MsgMoveProviderStakeResponse) 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 *MsgMoveProviderStakeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMoveProviderStakeResponse) 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 @@ -1597,6 +1821,38 @@ func (m *MsgUnfreezeProviderResponse) Size() (n int) { return n } +func (m *MsgMoveProviderStake) 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)) + } + l = len(m.SrcChain) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.DstChain) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgMoveProviderStakeResponse) 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 } @@ -2911,6 +3167,235 @@ func (m *MsgUnfreezeProviderResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgMoveProviderStake) 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: MsgMoveProviderStake: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMoveProviderStake: 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 != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SrcChain", 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.SrcChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DstChain", 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.DstChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMoveProviderStakeResponse) 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: MsgMoveProviderStakeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMoveProviderStakeResponse: 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 diff --git a/x/rewards/keeper/providers_test.go b/x/rewards/keeper/providers_test.go index 5ed1c58d52..0e4c1e906e 100644 --- a/x/rewards/keeper/providers_test.go +++ b/x/rewards/keeper/providers_test.go @@ -271,10 +271,9 @@ func Test2SpecsZeroShares(t *testing.T) { res, err := ts.QueryDualstakingDelegatorRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), "") require.NoError(t, err) - require.Len(t, res.Rewards, 2) + require.Len(t, res.Rewards, 1) expectedReward, _, _ := ts.DeductParticipationFees(ts.plan.Price.Amount) - require.Equal(t, expectedReward, res.Rewards[0].Amount.AmountOf(ts.BondDenom())) - require.Equal(t, expectedReward, res.Rewards[1].Amount.AmountOf(ts.BondDenom())) + require.Equal(t, expectedReward.MulRaw(2), res.Rewards[0].Amount.AmountOf(ts.BondDenom())) _, err = ts.TxDualstakingClaimRewards(providerAcc.GetVaultAddr(), "") require.NoError(t, err) @@ -287,7 +286,6 @@ func Test2SpecsZeroShares(t *testing.T) { require.NoError(t, err) require.Len(t, res.Rewards, 1) require.Equal(t, distBalance.QuoRaw(int64(ts.Keepers.Rewards.MaxRewardBoost(ts.Ctx))), res.Rewards[0].Amount.AmountOf(ts.BondDenom())) - require.Equal(t, res.Rewards[0].ChainId, ts.specs[0].Index) _, err = ts.TxDualstakingClaimRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String()) require.NoError(t, err) } @@ -303,11 +301,12 @@ func Test2SpecsDoubleShares(t *testing.T) { spec2.Shares *= 2 ts.AddSpec(spec2.Index, spec2) - providerAcc, _ := ts.AddAccount(common.PROVIDER, 1, 2*testBalance) - err := ts.StakeProvider(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), ts.specs[0], testBalance) + providerAcc1, _ := ts.AddAccount(common.PROVIDER, 1, 2*testBalance) + err := ts.StakeProvider(providerAcc1.GetVaultAddr(), providerAcc1.Addr.String(), ts.specs[0], testBalance) require.NoError(t, err) - err = ts.StakeProvider(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), spec2, testBalance) + providerAcc2, _ := ts.AddAccount(common.PROVIDER, 2, 2*testBalance) + err = ts.StakeProvider(providerAcc2.GetVaultAddr(), providerAcc2.Addr.String(), spec2, testBalance) require.NoError(t, err) ts.AdvanceEpoch() @@ -316,7 +315,7 @@ func Test2SpecsDoubleShares(t *testing.T) { _, err = ts.TxSubscriptionBuy(consumerAcc.Addr.String(), consumerAcc.Addr.String(), ts.plan.Index, 1, false, false) require.NoError(t, err) - msg := ts.SendRelay(providerAcc.Addr.String(), consumerAcc, []string{ts.specs[0].Index}, ts.plan.Price.Amount.Uint64()) + msg := ts.SendRelay(providerAcc1.Addr.String(), consumerAcc, []string{ts.specs[0].Index}, ts.plan.Price.Amount.Uint64()) _, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...) require.NoError(t, err) @@ -324,7 +323,7 @@ func Test2SpecsDoubleShares(t *testing.T) { _, err = ts.TxSubscriptionBuy(consumerAcc2.Addr.String(), consumerAcc2.Addr.String(), ts.plan.Index, 1, false, false) require.NoError(t, err) - msg = ts.SendRelay(providerAcc.Addr.String(), consumerAcc2, []string{spec2.Index}, ts.plan.Price.Amount.Uint64()) + msg = ts.SendRelay(providerAcc2.Addr.String(), consumerAcc2, []string{spec2.Index}, ts.plan.Price.Amount.Uint64()) _, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...) require.NoError(t, err) @@ -333,25 +332,39 @@ func Test2SpecsDoubleShares(t *testing.T) { ts.AdvanceEpoch() ts.AdvanceBlocks(ts.BlocksToSave() + 1) - res, err := ts.QueryDualstakingDelegatorRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), "") + res, err := ts.QueryDualstakingDelegatorRewards(providerAcc1.GetVaultAddr(), providerAcc1.Addr.String(), "") require.NoError(t, err) - require.Len(t, res.Rewards, 2) + require.Len(t, res.Rewards, 1) expectedReward, _, _ := ts.DeductParticipationFees(ts.plan.Price.Amount) require.Equal(t, expectedReward, res.Rewards[0].Amount.AmountOf(ts.BondDenom())) - require.Equal(t, expectedReward, res.Rewards[1].Amount.AmountOf(ts.BondDenom())) - _, err = ts.TxDualstakingClaimRewards(providerAcc.GetVaultAddr(), "") + _, err = ts.TxDualstakingClaimRewards(providerAcc1.GetVaultAddr(), "") + require.NoError(t, err) + + res, err = ts.QueryDualstakingDelegatorRewards(providerAcc2.GetVaultAddr(), providerAcc2.Addr.String(), "") + require.NoError(t, err) + require.Len(t, res.Rewards, 1) + expectedReward, _, _ = ts.DeductParticipationFees(ts.plan.Price.Amount) + require.Equal(t, expectedReward, res.Rewards[0].Amount.AmountOf(ts.BondDenom())) + _, err = ts.TxDualstakingClaimRewards(providerAcc2.GetVaultAddr(), "") require.NoError(t, err) // now the provider should get all of the provider allocation ts.AdvanceMonths(1) ts.AdvanceEpoch() - res, err = ts.QueryDualstakingDelegatorRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), "") + res1, err := ts.QueryDualstakingDelegatorRewards(providerAcc1.GetVaultAddr(), providerAcc1.Addr.String(), "") require.NoError(t, err) - require.Len(t, res.Rewards, 2) - require.Equal(t, res.Rewards[0].Amount.AmountOf(ts.BondDenom()).QuoRaw(2), res.Rewards[1].Amount.AmountOf(ts.BondDenom())) - _, err = ts.TxDualstakingClaimRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String()) + require.Len(t, res1.Rewards, 1) + _, err = ts.TxDualstakingClaimRewards(providerAcc1.GetVaultAddr(), providerAcc1.Addr.String()) + require.NoError(t, err) + + res2, err := ts.QueryDualstakingDelegatorRewards(providerAcc2.GetVaultAddr(), providerAcc2.Addr.String(), "") require.NoError(t, err) + require.Len(t, res1.Rewards, 1) + _, err = ts.TxDualstakingClaimRewards(providerAcc2.GetVaultAddr(), providerAcc2.Addr.String()) + require.NoError(t, err) + + require.Equal(t, res1.Rewards[0].Amount.AmountOf(ts.BondDenom()), res2.Rewards[0].Amount.AmountOf(ts.BondDenom()).QuoRaw(2)) } // in this test we setup 3 providers, each with different cu used (-> 3 different rewards from the plan) (1,2,4) diff --git a/x/subscription/keeper/grpc_query_estimated_rewards.go b/x/subscription/keeper/grpc_query_estimated_rewards.go index 6c180b44ef..b8b6771858 100644 --- a/x/subscription/keeper/grpc_query_estimated_rewards.go +++ b/x/subscription/keeper/grpc_query_estimated_rewards.go @@ -45,7 +45,7 @@ func (k Keeper) EstimatedRewards(goCtx context.Context, req *types.QueryEstimate if req.AmountDelegator != "" { _, err := sdk.AccAddressFromBech32(req.AmountDelegator) if err == nil { - d, found := k.dualstakingKeeper.GetDelegation(ctx, req.AmountDelegator, req.Provider, req.ChainId, uint64(ctx.BlockHeight())) + d, found := k.dualstakingKeeper.GetDelegation(ctx, req.AmountDelegator, req.Provider) if !found { return nil, fmt.Errorf("could not find delegator") } diff --git a/x/subscription/types/expected_keepers.go b/x/subscription/types/expected_keepers.go index f459e5e1bc..a1c4b0525f 100644 --- a/x/subscription/types/expected_keepers.go +++ b/x/subscription/types/expected_keepers.go @@ -69,7 +69,7 @@ type TimerStoreKeeper interface { type DualStakingKeeper interface { RewardProvidersAndDelegators(ctx sdk.Context, providerAddr string, chainID string, totalReward sdk.Coins, senderModule string, calcOnlyProvider bool, calcOnlyDelegators bool, calcOnlyContributor bool) (providerReward sdk.Coins, err error) - GetDelegation(ctx sdk.Context, delegator, provider, chainID string, epoch uint64) (dualstakingtypes.Delegation, bool) + GetDelegation(ctx sdk.Context, delegator, provider string) (dualstakingtypes.Delegation, bool) } type RewardsKeeper interface {