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-231 unitests tests and fixes #336

Merged
Show file tree
Hide file tree
Changes from 7 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
14 changes: 14 additions & 0 deletions testutil/keeper/keepers_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"github.com/lavanet/lava/x/plans"
planskeeper "github.com/lavanet/lava/x/plans/keeper"
planstypes "github.com/lavanet/lava/x/plans/types"
projectskeeper "github.com/lavanet/lava/x/projects/keeper"
projectstypes "github.com/lavanet/lava/x/projects/types"
"github.com/lavanet/lava/x/spec"
speckeeper "github.com/lavanet/lava/x/spec/keeper"
spectypes "github.com/lavanet/lava/x/spec/types"
Expand All @@ -47,6 +49,7 @@ type Keepers struct {
Plans planskeeper.Keeper
Pairing pairingkeeper.Keeper
Conflict conflictkeeper.Keeper
Projects projectskeeper.Keeper
Yaroms marked this conversation as resolved.
Show resolved Hide resolved
BankKeeper mockBankKeeper
AccountKeeper mockAccountKeeper
ParamsKeeper paramskeeper.Keeper
Expand All @@ -58,6 +61,7 @@ type Servers struct {
SpecServer spectypes.MsgServer
PairingServer pairingtypes.MsgServer
ConflictServer conflicttypes.MsgServer
ProjectServer projectstypes.MsgServer
PlansServer planstypes.MsgServer
}

Expand Down Expand Up @@ -115,6 +119,11 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) {
stateStore.MountStoreWithDB(conflictStoreKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(conflictMemStoreKey, sdk.StoreTypeMemory, nil)

projectsStoreKey := sdk.NewKVStoreKey(projectstypes.StoreKey)
Yaroms marked this conversation as resolved.
Show resolved Hide resolved
projectsMemStoreKey := storetypes.NewMemoryStoreKey(projectstypes.MemStoreKey)
stateStore.MountStoreWithDB(projectsStoreKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(projectsMemStoreKey, sdk.StoreTypeMemory, nil)

require.NoError(t, stateStore.LoadLatestVersion())

paramsKeeper := paramskeeper.NewKeeper(cdc, pairingtypes.Amino, paramsStoreKey, tkey)
Expand All @@ -129,6 +138,8 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) {

specparamsSubspace, _ := paramsKeeper.GetSubspace(spectypes.ModuleName)

projectsparamsSubspace, _ := paramsKeeper.GetSubspace(projectstypes.ModuleName)

plansparamsSubspace, _ := paramsKeeper.GetSubspace(planstypes.ModuleName)

conflictparamsSubspace := paramstypes.NewSubspace(cdc,
Expand All @@ -142,6 +153,7 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) {
ks.AccountKeeper = mockAccountKeeper{}
ks.BankKeeper = mockBankKeeper{balance: make(map[string]sdk.Coins)}
ks.Spec = *speckeeper.NewKeeper(cdc, specStoreKey, specMemStoreKey, specparamsSubspace)
ks.Projects = *projectskeeper.NewKeeper(cdc, projectsStoreKey, projectsMemStoreKey, projectsparamsSubspace)
Yaroms marked this conversation as resolved.
Show resolved Hide resolved
ks.Epochstorage = *epochstoragekeeper.NewKeeper(cdc, epochStoreKey, epochMemStoreKey, epochparamsSubspace, &ks.BankKeeper, &ks.AccountKeeper, ks.Spec)
ks.Plans = *planskeeper.NewKeeper(cdc, plansStoreKey, plansMemStoreKey, plansparamsSubspace)
ks.Pairing = *pairingkeeper.NewKeeper(cdc, pairingStoreKey, pairingMemStoreKey, pairingparamsSubspace, &ks.BankKeeper, &ks.AccountKeeper, ks.Spec, &ks.Epochstorage)
Expand All @@ -156,6 +168,7 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) {
ks.Spec.SetParams(ctx, spectypes.DefaultParams())
ks.Epochstorage.SetParams(ctx, epochstoragetypes.DefaultParams())
ks.Conflict.SetParams(ctx, conflicttypes.DefaultParams())
ks.Projects.SetParams(ctx, projectstypes.DefaultParams())
ks.Plans.SetParams(ctx, planstypes.DefaultParams())

ks.Epochstorage.PushFixatedParams(ctx, 0, 0)
Expand All @@ -166,6 +179,7 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) {
ss.PlansServer = planskeeper.NewMsgServerImpl(ks.Plans)
ss.PairingServer = pairingkeeper.NewMsgServerImpl(ks.Pairing)
ss.ConflictServer = conflictkeeper.NewMsgServerImpl(ks.Conflict)
ss.ProjectServer = projectskeeper.NewMsgServerImpl(ks.Projects)

core.SetEnvironment(&core.Environment{BlockStore: &ks.BlockStore})

Expand Down
45 changes: 21 additions & 24 deletions x/projects/keeper/creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,47 @@ import (

// add a default project to a subscription, add the subscription key as
func (k Keeper) CreateDefaultProject(ctx sdk.Context, subscriptionAddress string) error {
project := types.DefaultProject(subscriptionAddress) // TODO add the CU per epoch here
var emptyProject types.Project

_, found := k.projectsFS.FindEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &emptyProject)
if found {
return utils.LavaError(ctx, ctx.Logger(), "CreateDefaultProject_already_exist", map[string]string{"subscription": subscriptionAddress}, "default project already exist for the current subscription")
}

project.Enabled = true
// add subscription key as developer key to the default project
projectID := types.ProtoString{String_: project.Index}
k.developerKeysFS.AppendEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &projectID)

return k.projectsFS.AppendEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &project)
return k.CreateProject(ctx, subscriptionAddress, types.DEFAULT_PROJECT_NAME, subscriptionAddress, true)
}

// add a new project to the subscription
func (k Keeper) CreateEmptyProject(ctx sdk.Context, subscriptionAddress string, projectName string, adminAddress string, enable bool) error {
project := types.CreateEmptyProject(subscriptionAddress, projectName)
func (k Keeper) CreateProject(ctx sdk.Context, subscriptionAddress string, projectName string, adminAddress string, enable bool) error {
project := types.CreateProject(subscriptionAddress, projectName)
var emptyProject types.Project

_, found := k.projectsFS.FindEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &emptyProject)
blockHeight := uint64(ctx.BlockHeight())
_, found := k.projectsFS.FindEntry(ctx, project.Index, blockHeight, &emptyProject)
// the project with the same name already exists if no error has returned
if found {
return utils.LavaError(ctx, ctx.Logger(), "CreateEmptyProject_already_exist", map[string]string{"subscription": subscriptionAddress}, "project already exist for the current subscription with the same name")
}

if subscriptionAddress != adminAddress {
project.ProjectKeys = append(project.ProjectKeys, types.ProjectKey{Key: adminAddress, Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_ADMIN}})
project.AppendKey(types.ProjectKey{Key: adminAddress, Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_ADMIN}})
}

err := k.RegisterDeveloperKey(ctx, adminAddress, project.Index, blockHeight)
if err != nil {
return err
}

project.Enabled = enable
return k.projectsFS.AppendEntry(ctx, project.Index, blockHeight, &project)
}

func (k Keeper) RegisterDeveloperKey(ctx sdk.Context, developerKey string, projectIndex string, blockHeight uint64) error {
var projectID types.ProtoString
_, found = k.developerKeysFS.FindEntry(ctx, adminAddress, uint64(ctx.BlockHeight()), &projectID)
_, found := k.developerKeysFS.FindEntry(ctx, developerKey, blockHeight, &projectID)
// a developer key with this address is not registered, add it to the developer keys list
if found {
projectID.String_ = project.Index
err := k.developerKeysFS.AppendEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &projectID)
if !found {
projectID.String_ = projectIndex
err := k.developerKeysFS.AppendEntry(ctx, developerKey, blockHeight, &projectID)
if err != nil {
return err
}
}

project.Enabled = enable
return k.projectsFS.AppendEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &project)
return nil
}

// snapshot project, create a snapshot of a project and reset the cu
Expand Down
36 changes: 2 additions & 34 deletions x/projects/keeper/msg_server_add_project_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,15 @@ import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lavanet/lava/utils"
"github.com/lavanet/lava/x/projects/types"
)

func (k msgServer) AddProjectKeys(goCtx context.Context, msg *types.MsgAddProjectKeys) (*types.MsgAddProjectKeysResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
projectID := msg.Project
adminKey := msg.Creator
projectKeys := msg.ProjectKeys

var project types.Project
err, found := k.projectsFS.FindEntry(ctx, projectID, uint64(ctx.BlockHeight()), &project)
if err != nil || !found {
return nil, utils.LavaError(ctx, ctx.Logger(), "AddProjectKeys_project_not_found", map[string]string{"project": projectID}, "project id not found")
}

// check if the admin key is valid
if !project.IsKeyType(adminKey, types.ProjectKey_ADMIN) || project.Subscription != adminKey {
return nil, utils.LavaError(ctx, ctx.Logger(), "AddProjectKeys_not_admin", map[string]string{"project": projectID}, "the requesting key is not admin key")
}

// check that those keys are unique for developers
for _, projectKey := range projectKeys {
if projectKey.IsKeyType(types.ProjectKey_DEVELOPER) {
// if the key is a developer key add it to the map of developer keys
var projectIDstring types.ProtoString
_, found := k.developerKeysFS.FindEntry(ctx, projectKey.Key, uint64(ctx.BlockHeight()), &projectIDstring)
if !found {
projectIDstring.String_ = project.Index
err = k.developerKeysFS.AppendEntry(ctx, project.Index, uint64(ctx.BlockHeight()), &projectIDstring)
if err != nil {
return nil, utils.LavaError(ctx, ctx.Logger(), "AddProjectKeys_used_key", map[string]string{"project": projectID, "developerKey": projectKey.Key, "err": err.Error()}, "the requesting key is not admin key")
}
}
}
}

err = k.projectsFS.AppendEntry(ctx, projectID, uint64(ctx.BlockHeight()), &project)
err := k.AddKeysToProject(ctx, msg.Project, msg.Creator, msg.ProjectKeys)
if err != nil {
return nil, err
}

return &types.MsgAddProjectKeysResponse{}, err
return &types.MsgAddProjectKeysResponse{}, nil
}
30 changes: 29 additions & 1 deletion x/projects/keeper/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/lavanet/lava/x/projects/types"
)

// add a default project to a subscription
func (k Keeper) GetProjectForBlock(ctx sdk.Context, projectID string, blockHeight uint64) (types.Project, error) {
var project types.Project

Expand Down Expand Up @@ -49,6 +48,35 @@ func (k Keeper) GetProjectForDeveloper(ctx sdk.Context, developerKey string, blo
return project, nil
}

func (k Keeper) AddKeysToProject(ctx sdk.Context, projectID string, adminKey string, projectKeys []types.ProjectKey) error {
var project types.Project
err, found := k.projectsFS.FindEntry(ctx, projectID, uint64(ctx.BlockHeight()), &project)
if err != nil || !found {
return utils.LavaError(ctx, ctx.Logger(), "AddProjectKeys_project_not_found", map[string]string{"project": projectID}, "project id not found")
}

// check if the admin key is valid
if !project.IsKeyType(adminKey, types.ProjectKey_ADMIN) && project.Subscription != adminKey {
return utils.LavaError(ctx, ctx.Logger(), "AddProjectKeys_not_admin", map[string]string{"project": projectID}, "the requesting key is not admin key")
}

// check that those keys are unique for developers
for _, projectKey := range projectKeys {
err = k.RegisterDeveloperKey(ctx, projectKey.Key, project.Index, uint64(ctx.BlockHeight()))
if err != nil {
return err
}

project.AppendKey(projectKey)
}

err = k.projectsFS.AppendEntry(ctx, projectID, uint64(ctx.BlockHeight()), &project)
Yaroms marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
Yaroms marked this conversation as resolved.
Show resolved Hide resolved
return err
}
return nil
}

func (k Keeper) ValidateDeveloperRequest(ctx sdk.Context, developerKey string, chainID string, apiName string, blockHeight uint64) (valid bool, policy types.Policy, err error) {
project, err := k.GetProjectForDeveloper(ctx, developerKey, blockHeight)
if err != nil {
Expand Down
131 changes: 131 additions & 0 deletions x/projects/keeper/project_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package keeper_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lavanet/lava/testutil/common"
testkeeper "github.com/lavanet/lava/testutil/keeper"
"github.com/lavanet/lava/x/projects/types"
"github.com/stretchr/testify/require"
)

func TestCreateDefaultProject(t *testing.T) {
_, keepers, ctx := testkeeper.InitAllKeepers(t)

subAccount := common.CreateNewAccount(ctx, *keepers, 10000)
err := keepers.Projects.CreateDefaultProject(sdk.UnwrapSDKContext(ctx), subAccount.Addr.String())
require.Nil(t, err)

// subscription key is a developer in the default project
response1, err := keepers.Projects.ShowDevelopersProject(ctx, &types.QueryShowDevelopersProjectRequest{Developer: subAccount.Addr.String()})
require.Nil(t, err)

testkeeper.AdvanceEpoch(ctx, keepers)

response2, err := keepers.Projects.ShowProject(ctx, &types.QueryShowProjectRequest{Project: response1.Project.Index})
require.Nil(t, err)

require.Equal(t, response2.Project, response1.Project)
}

func TestCreateProject(t *testing.T) {
_, keepers, ctx := testkeeper.InitAllKeepers(t)

projectName := "mockname"
subAccount := common.CreateNewAccount(ctx, *keepers, 10000)
adminAcc := common.CreateNewAccount(ctx, *keepers, 10000)
err := keepers.Projects.CreateProject(sdk.UnwrapSDKContext(ctx), subAccount.Addr.String(), projectName, adminAcc.Addr.String(), false)
require.Nil(t, err)

testkeeper.AdvanceEpoch(ctx, keepers)

// create another project with the same name, should fail as this is unique
err = keepers.Projects.CreateProject(sdk.UnwrapSDKContext(ctx), subAccount.Addr.String(), projectName, adminAcc.Addr.String(), false)
require.NotNil(t, err)

// subscription key is not a developer
response1, err := keepers.Projects.ShowDevelopersProject(ctx, &types.QueryShowDevelopersProjectRequest{Developer: subAccount.Addr.String()})
require.NotNil(t, err)

response1, err = keepers.Projects.ShowDevelopersProject(ctx, &types.QueryShowDevelopersProjectRequest{Developer: adminAcc.Addr.String()})
require.Nil(t, err)

response2, err := keepers.Projects.ShowProject(ctx, &types.QueryShowProjectRequest{Project: response1.Project.Index})
require.Nil(t, err)

require.Equal(t, response2.Project, response1.Project)

require.Equal(t, len(response2.Project.ProjectKeys), 1)
require.Equal(t, response2.Project.ProjectKeys[0].Key, adminAcc.Addr.String())
require.Equal(t, len(response2.Project.ProjectKeys[0].Types), 1)
require.Equal(t, response2.Project.ProjectKeys[0].Types[0], types.ProjectKey_ADMIN)
}

func TestAddKeys(t *testing.T) {
servers, keepers, ctx := testkeeper.InitAllKeepers(t)

projectName := "mockname"
subAccount := common.CreateNewAccount(ctx, *keepers, 10000)
adminAcc := common.CreateNewAccount(ctx, *keepers, 10000)
developerAcc := common.CreateNewAccount(ctx, *keepers, 10000)
err := keepers.Projects.CreateProject(sdk.UnwrapSDKContext(ctx), subAccount.Addr.String(), projectName, adminAcc.Addr.String(), false)
require.Nil(t, err)

testkeeper.AdvanceEpoch(ctx, keepers)

projectRes, err := keepers.Projects.ShowDevelopersProject(ctx, &types.QueryShowDevelopersProjectRequest{Developer: adminAcc.Addr.String()})
require.Nil(t, err)

project := projectRes.Project
pk := types.ProjectKey{Key: developerAcc.Addr.String(), Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_ADMIN}}
// try adding myself as admin, should fail
_, err = servers.ProjectServer.AddProjectKeys(ctx, &types.MsgAddProjectKeys{Creator: developerAcc.Addr.String(), Project: project.Index, ProjectKeys: []types.ProjectKey{pk}})
require.NotNil(t, err)

// admin key adding as developer
pk = types.ProjectKey{Key: developerAcc.Addr.String(), Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_DEVELOPER}}
_, err = servers.ProjectServer.AddProjectKeys(ctx, &types.MsgAddProjectKeys{Creator: adminAcc.Addr.String(), Project: project.Index, ProjectKeys: []types.ProjectKey{pk}})
require.Nil(t, err)

// developer tries to add admin
pk = types.ProjectKey{Key: developerAcc.Addr.String(), Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_ADMIN}}
_, err = servers.ProjectServer.AddProjectKeys(ctx, &types.MsgAddProjectKeys{Creator: developerAcc.Addr.String(), Project: project.Index, ProjectKeys: []types.ProjectKey{pk}})
require.NotNil(t, err)

// admin adding admin
pk = types.ProjectKey{Key: developerAcc.Addr.String(), Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_ADMIN}}
_, err = servers.ProjectServer.AddProjectKeys(ctx, &types.MsgAddProjectKeys{Creator: adminAcc.Addr.String(), Project: project.Index, ProjectKeys: []types.ProjectKey{pk}})
require.Nil(t, err)

// new admin adding another developer
developerAcc2 := common.CreateNewAccount(ctx, *keepers, 10000)
pk = types.ProjectKey{Key: developerAcc2.Addr.String(), Types: []types.ProjectKey_KEY_TYPE{types.ProjectKey_ADMIN}}
_, err = servers.ProjectServer.AddProjectKeys(ctx, &types.MsgAddProjectKeys{Creator: developerAcc.Addr.String(), Project: project.Index, ProjectKeys: []types.ProjectKey{pk}})
require.Nil(t, err)

// fetch project with new developer
projectRes, err = keepers.Projects.ShowDevelopersProject(ctx, &types.QueryShowDevelopersProjectRequest{Developer: developerAcc2.Addr.String()})
Yaroms marked this conversation as resolved.
Show resolved Hide resolved
require.Nil(t, err)
}

func TestAddAdminInTwoProjects(t *testing.T) {
_, keepers, ctx := testkeeper.InitAllKeepers(t)
// he should be a developer only in the first project
projectName1 := "mockname1"
projectName2 := "mockname2"

subAccount := common.CreateNewAccount(ctx, *keepers, 10000)
adminAcc := common.CreateNewAccount(ctx, *keepers, 10000)
err := keepers.Projects.CreateProject(sdk.UnwrapSDKContext(ctx), subAccount.Addr.String(), projectName1, adminAcc.Addr.String(), false)
require.Nil(t, err)

err = keepers.Projects.CreateProject(sdk.UnwrapSDKContext(ctx), subAccount.Addr.String(), projectName2, adminAcc.Addr.String(), false)
require.Nil(t, err)

testkeeper.AdvanceEpoch(ctx, keepers)

response, err := keepers.Projects.ShowDevelopersProject(ctx, &types.QueryShowDevelopersProjectRequest{Developer: adminAcc.Addr.String()})
require.Nil(t, err)
require.Equal(t, response.Project.Index, types.ProjectIndex(subAccount.Addr.String(), projectName1))
}
Loading