Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CNS-668: let users see pending policy changes #945

Merged
merged 4 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion proto/lavanet/lava/pairing/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ message QueryVerifyPairingResponse {

message QueryGetUniquePaymentStorageClientProviderRequest {
string index = 1;

}

message QueryGetUniquePaymentStorageClientProviderResponse {
Expand Down Expand Up @@ -228,6 +227,7 @@ message QueryEffectivePolicyRequest {

message QueryEffectivePolicyResponse {
lavanet.lava.plans.Policy policy = 1;
lavanet.lava.plans.Policy pending_policy = 2;
}

// this line is used by starport scaffolding # 3
Expand Down
2 changes: 2 additions & 0 deletions proto/lavanet/lava/projects/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ message QueryInfoRequest {

message QueryInfoResponse {
Project project = 1;
Project pending_project = 2;
}

message QueryDeveloperRequest {
Expand All @@ -51,6 +52,7 @@ message QueryDeveloperRequest {

message QueryDeveloperResponse {
Project project = 1;
Project pending_project = 2;
}

// this line is used by starport scaffolding # 3
9 changes: 9 additions & 0 deletions testutil/common/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,15 @@ func (ts *Tester) QueryPairingVerifyPairing(chainID, client, provider string, bl
return ts.Keepers.Pairing.VerifyPairing(ts.GoCtx, msg)
}

// QueryPairingEffectivePolicy implements 'q pairing effective-policy'
func (ts *Tester) QueryPairingEffectivePolicy(chainID, consumer string) (*pairingtypes.QueryEffectivePolicyResponse, error) {
msg := &pairingtypes.QueryEffectivePolicyRequest{
SpecID: chainID,
Consumer: consumer,
}
return ts.Keepers.Pairing.EffectivePolicy(ts.GoCtx, msg)
}

// QueryPairingVerifyPairing implements 'q dualstaking delegator-providers'
func (ts *Tester) QueryDualstakingDelegatorProviders(delegator string, withPending bool) (*dualstakingtypes.QueryDelegatorProvidersResponse, error) {
msg := &dualstakingtypes.QueryDelegatorProvidersRequest{
Expand Down
40 changes: 35 additions & 5 deletions x/pairing/keeper/grpc_query_effective_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lavanet/lava/x/pairing/types"
projectstypes "github.com/lavanet/lava/x/projects/types"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand All @@ -17,15 +18,44 @@ func (k Keeper) EffectivePolicy(goCtx context.Context, req *types.QueryEffective

ctx := sdk.UnwrapSDKContext(goCtx)

project, err := k.projectsKeeper.GetProjectForDeveloper(ctx, req.Consumer, uint64(ctx.BlockHeight()))
project, err := k.getProjectByDeveloperOrIndex(ctx, req.Consumer, uint64(ctx.BlockHeight()))
if err != nil {
return nil, err
}
strictestPolicy, _, err := k.GetProjectStrictestPolicy(ctx, project, req.SpecID)
if err != nil {
return nil, err
}

// try getting pending policy changes (applied in next epoch)
nextEpoch, err := k.epochStorageKeeper.GetNextEpoch(ctx, uint64(ctx.BlockHeight()))
if err != nil {
return nil, fmt.Errorf("cannot get pending project policy. errors: %s", err.Error())
}

pendingProject, err := k.getProjectByDeveloperOrIndex(ctx, req.Consumer, nextEpoch)
if err != nil {
return nil, err
}

if pendingProject.Equal(project) {
return &types.QueryEffectivePolicyResponse{Policy: strictestPolicy}, err
} else {
pendingPolicy, _, err := k.GetProjectStrictestPolicy(ctx, pendingProject, req.SpecID)
return &types.QueryEffectivePolicyResponse{Policy: strictestPolicy, PendingPolicy: pendingPolicy}, err
}
}

func (k Keeper) getProjectByDeveloperOrIndex(ctx sdk.Context, idOrDeveloper string, block uint64) (projectstypes.Project, error) {
project, err := k.projectsKeeper.GetProjectForDeveloper(ctx, idOrDeveloper, block)
if err != nil {
origErr := err
// support giving a project-id
project, err = k.projectsKeeper.GetProjectForBlock(ctx, req.Consumer, uint64(ctx.BlockHeight()))
project, err = k.projectsKeeper.GetProjectForBlock(ctx, idOrDeveloper, block)
if err != nil {
return nil, fmt.Errorf("failed getting project for key %s errors %s, %s", req.Consumer, origErr, err)
return projectstypes.Project{}, fmt.Errorf("failed getting project for key %s errors %s, %s", idOrDeveloper, origErr, err)
}
}
strictestPolicy, _, err := k.GetProjectStrictestPolicy(ctx, project, req.SpecID)
return &types.QueryEffectivePolicyResponse{Policy: strictestPolicy}, err

return project, nil
}
92 changes: 92 additions & 0 deletions x/pairing/keeper/grpc_query_effective_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package keeper_test

import (
"testing"

"github.com/lavanet/lava/testutil/common"
planstypes "github.com/lavanet/lava/x/plans/types"
"github.com/stretchr/testify/require"
)

// Test effective policy query
func TestEffectivePolicy(t *testing.T) {
ts := newTester(t)
ts.setupForPayments(1, 1, 0) // 1 client, 1 provider

_, clientAddr := ts.GetAccount(common.CONSUMER, 0)

project, err := ts.GetProjectDeveloperData(clientAddr, ts.BlockHeight())
require.Nil(t, err)

// the auto-created project from setupForPayments is subject to the mock plan policy
// the mock policy assumed in this test is (implemented by common.CreateMockPolicy()):
//
// plantypes.Policy{
// TotalCuLimit: 100000,
// EpochCuLimit: 10000,
// MaxProvidersToPair: 3,
// GeolocationProfile: 1,
// }
//
// when testing the effective policy, this will be the policy in mind

adminPolicy := planstypes.Policy{
TotalCuLimit: 99000,
EpochCuLimit: 10000,
MaxProvidersToPair: 3,
GeolocationProfile: 1,
}
_, err = ts.TxProjectSetPolicy(project.ProjectID, clientAddr, adminPolicy)
require.Nil(t, err)

subPolicy := planstypes.Policy{
TotalCuLimit: 100000,
EpochCuLimit: 9900,
MaxProvidersToPair: 2,
GeolocationProfile: planstypes.Geolocation_value["GL"],
}
_, err = ts.TxProjectSetSubscriptionPolicy(project.ProjectID, clientAddr, subPolicy)
require.Nil(t, err)

// the effective policy function calcaulates the effective chain policy within it
// if there is no chain policy in any of the policies, it makes one using this function
chainPolicy, allowed := planstypes.GetStrictestChainPolicyForSpec(ts.spec.Index, []*planstypes.Policy{&adminPolicy, &subPolicy, &ts.plan.PlanPolicy})
require.True(t, allowed)

expectedEffectivePolicy := planstypes.Policy{
ChainPolicies: []planstypes.ChainPolicy{chainPolicy},
TotalCuLimit: 99000,
EpochCuLimit: 9900,
MaxProvidersToPair: 2,
GeolocationProfile: 1,
}

// apply the policy changes
ts.AdvanceEpoch()

res, err := ts.QueryPairingEffectivePolicy(ts.spec.Index, clientAddr)
require.Nil(t, err)
require.True(t, expectedEffectivePolicy.Equal(res.Policy))
require.Nil(t, res.PendingPolicy) // there should be no pending policy

// set a new policy without applying it (no advanceEpoch)
_, err = ts.TxProjectSetPolicy(project.ProjectID, clientAddr, planstypes.Policy{
TotalCuLimit: 80000,
EpochCuLimit: 5000,
MaxProvidersToPair: 3,
GeolocationProfile: 1,
})
require.Nil(t, err)
res, err = ts.QueryPairingEffectivePolicy(ts.spec.Index, clientAddr)
require.Nil(t, err)
require.True(t, expectedEffectivePolicy.Equal(res.Policy)) // policy should still be the original one

// there should be a new pending policy
require.True(t, res.PendingPolicy.Equal(planstypes.Policy{
ChainPolicies: expectedEffectivePolicy.ChainPolicies,
TotalCuLimit: 80000,
EpochCuLimit: 5000,
MaxProvidersToPair: 2,
GeolocationProfile: 1,
}))
}
Loading