diff --git a/app/app.go b/app/app.go index 0ab1202df8..cd9cca6d1b 100644 --- a/app/app.go +++ b/app/app.go @@ -480,6 +480,7 @@ func New( keys[specmoduletypes.MemStoreKey], app.GetSubspace(specmoduletypes.ModuleName), app.StakingKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) specModule := specmodule.NewAppModule(appCodec, app.SpecKeeper, app.AccountKeeper, app.BankKeeper) @@ -608,10 +609,8 @@ func New( govRouter.AddRoute(govtypes.RouterKey, v1beta1.ProposalHandler). // // user defined - AddRoute(specmoduletypes.ProposalsRouterKey, specmodule.NewSpecProposalsHandler(app.SpecKeeper)). // copied the code from param and changed the handler to enable functionality AddRoute(paramproposal.RouterKey, specmodule.NewParamChangeProposalHandler(app.ParamsKeeper)). - // user defined AddRoute(plansmoduletypes.ProposalsRouterKey, plansmodule.NewPlansProposalsHandler(app.PlansKeeper)). AddRoute(pairingmoduletypes.ProposalsRouterKey, pairingmodule.NewPairingProposalsHandler(app.PairingKeeper)). diff --git a/app/upgrades/upgrade_0_35_0.go b/app/upgrades/upgrade_0_35_0.go index f3805afbdc..3e2160c39b 100644 --- a/app/upgrades/upgrade_0_35_0.go +++ b/app/upgrades/upgrade_0_35_0.go @@ -24,7 +24,7 @@ func v_35_0( params := lk.SpecKeeper.GetParams(ctx) params.AllowlistedExpeditedMsgs = []string{ proto.MessageName(&protocoltypes.MsgSetVersion{}), - proto.MessageName(&spectypes.SpecAddProposal{}), + proto.MessageName(&spectypes.MsgAddSpecs{}), proto.MessageName(&ibctypes.ClientUpdateProposal{}), proto.MessageName(&ibctypes.UpgradeProposal{}), } diff --git a/proto/lavanet/lava/spec/spec.proto b/proto/lavanet/lava/spec/spec.proto index 5607691dd0..165696d6b6 100644 --- a/proto/lavanet/lava/spec/spec.proto +++ b/proto/lavanet/lava/spec/spec.proto @@ -38,4 +38,5 @@ message Spec { ]; uint64 shares = 19; string identity = 20; + bool user_spec = 21; } diff --git a/proto/lavanet/lava/spec/spec_add_proposal.proto b/proto/lavanet/lava/spec/spec_add_proposal.proto deleted file mode 100644 index 85fe3fb770..0000000000 --- a/proto/lavanet/lava/spec/spec_add_proposal.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; -package lavanet.lava.spec; - -option go_package = "github.com/lavanet/lava/x/spec/types"; -option (gogoproto.equal_all) = true; - -import "gogoproto/gogo.proto"; - -import "lavanet/lava/spec/spec.proto"; - -message SpecAddProposal { - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; - - string title = 1; - string description = 2; - repeated Spec specs = 3 [(gogoproto.nullable) = false]; -} diff --git a/proto/lavanet/lava/spec/tx.proto b/proto/lavanet/lava/spec/tx.proto index 9bc577b5f3..715c17ab4a 100644 --- a/proto/lavanet/lava/spec/tx.proto +++ b/proto/lavanet/lava/spec/tx.proto @@ -4,10 +4,21 @@ package lavanet.lava.spec; // this line is used by starport scaffolding # proto/tx/import option go_package = "github.com/lavanet/lava/x/spec/types"; +import "gogoproto/gogo.proto"; +import "lavanet/lava/spec/spec.proto"; // Msg defines the Msg service. service Msg { + rpc AddSpecs(MsgAddSpecs) returns (MsgAddSpecsResponse); // this line is used by starport scaffolding # proto/tx/rpc } -// this line is used by starport scaffolding # proto/tx/message \ No newline at end of file +// this line is used by starport scaffolding # proto/tx/message + +message MsgAddSpecs { + string creator = 1; + repeated Spec specs = 2 [(gogoproto.nullable) = false]; +} + +message MsgAddSpecsResponse { +} \ No newline at end of file diff --git a/testutil/common/mock.go b/testutil/common/mock.go index 57de685454..524bbdc72d 100644 --- a/testutil/common/mock.go +++ b/testutil/common/mock.go @@ -17,9 +17,11 @@ func CreateMockSpec() spectypes.Spec { spec.BlockDistanceForFinalizedData = 0 spec.DataReliabilityEnabled = true spec.MinStakeProvider = sdk.NewCoin(commonconsts.TestTokenDenom, sdk.NewInt(1000)) - spec.ApiCollections = []*spectypes.ApiCollection{{Enabled: true, CollectionData: spectypes.CollectionData{ApiInterface: "stub", Type: "GET"}, Apis: []*spectypes.Api{{Name: specName + "API", ComputeUnits: 100, Enabled: true}}}} - spec.BlockDistanceForFinalizedData = 0 + spec.ApiCollections = []*spectypes.ApiCollection{{Enabled: true, CollectionData: spectypes.CollectionData{ApiInterface: spectypes.APIInterfaceJsonRPC, Type: "GET"}, Apis: []*spectypes.Api{{Name: specName + "API", ComputeUnits: 100, Enabled: true}}}} + spec.BlocksInFinalizationProof = 10 spec.Shares = 1 + spec.AverageBlockTime = 10000 + spec.AllowedBlockLagForQosSync = 5 return spec } diff --git a/testutil/keeper/dualstaking.go b/testutil/keeper/dualstaking.go index 313ec888d1..cf7a2ec3e8 100644 --- a/testutil/keeper/dualstaking.go +++ b/testutil/keeper/dualstaking.go @@ -67,7 +67,7 @@ func DualstakingKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { nil, &mockAccountKeeper{}, epochstorageKeeper, - speckeeper.NewKeeper(cdc, nil, nil, paramsSubspaceSpec, nil), + speckeeper.NewKeeper(cdc, nil, nil, paramsSubspaceSpec, nil, ""), fixationkeeper.NewKeeper(cdc, tsKeeper, epochstorageKeeper.BlocksToSaveRaw), ) diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 984c93689e..9e728630d2 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -253,7 +253,7 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { init_balance() ks.StakingKeeper = *stakingkeeper.NewKeeper(cdc, stakingStoreKey, ks.AccountKeeper, ks.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String()) ks.Distribution = distributionkeeper.NewKeeper(cdc, distributionStoreKey, ks.AccountKeeper, ks.BankKeeper, ks.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String()) - ks.Spec = *speckeeper.NewKeeper(cdc, specStoreKey, specMemStoreKey, specparamsSubspace, ks.StakingKeeper) + ks.Spec = *speckeeper.NewKeeper(cdc, specStoreKey, specMemStoreKey, specparamsSubspace, ks.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String()) ks.Epochstorage = *epochstoragekeeper.NewKeeper(cdc, epochStoreKey, epochMemStoreKey, epochparamsSubspace, &ks.BankKeeper, &ks.AccountKeeper, ks.Spec, ks.StakingKeeper) ks.FixationStoreKeeper = fixationkeeper.NewKeeper(cdc, ks.TimerStoreKeeper, ks.Epochstorage.BlocksToSaveRaw) ks.Dualstaking = *dualstakingkeeper.NewKeeper(cdc, dualstakingStoreKey, dualstakingMemStoreKey, dualstakingparamsSubspace, &ks.BankKeeper, &ks.StakingKeeper, &ks.AccountKeeper, ks.Epochstorage, ks.Spec, ks.FixationStoreKeeper) @@ -383,14 +383,7 @@ func SimulatePlansDelProposal(ctx sdk.Context, plansKeeper planskeeper.Keeper, p } func SimulateSpecAddProposal(ctx sdk.Context, specKeeper speckeeper.Keeper, specsToPropose []spectypes.Spec) error { - proposal := spectypes.NewSpecAddProposal("mockProposal", "mockProposal specs add for testing", specsToPropose) - err := proposal.ValidateBasic() - if err != nil { - return err - } - proposalHandler := spec.NewSpecProposalsHandler(specKeeper) - err = proposalHandler(ctx, proposal) - return err + return specKeeper.HandleSpecs(ctx, specsToPropose, specKeeper.GetAuthority()) } func SimulateUnstakeProposal(ctx sdk.Context, pairingKeeper pairingkeeper.Keeper, providersInfo []pairingtypes.ProviderUnstakeInfo, delegatorsSlashing []pairingtypes.DelegatorSlashing) error { diff --git a/testutil/keeper/plan.go b/testutil/keeper/plan.go index d4714b2571..7d65e27080 100644 --- a/testutil/keeper/plan.go +++ b/testutil/keeper/plan.go @@ -63,7 +63,7 @@ func PlanKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { memStoreKey, paramsSubspace, epochstorageKeeper, - speckeeper.NewKeeper(cdc, nil, nil, paramsSubspaceSpec, nil), + speckeeper.NewKeeper(cdc, nil, nil, paramsSubspaceSpec, nil, ""), fixationkeeper.NewKeeper(cdc, timerstorekeeper.NewKeeper(cdc), epochstorageKeeper.BlocksToSaveRaw), nil, ) diff --git a/testutil/keeper/spec.go b/testutil/keeper/spec.go index 6a0acc7e67..6a0ad50b05 100644 --- a/testutil/keeper/spec.go +++ b/testutil/keeper/spec.go @@ -57,6 +57,7 @@ func specKeeper() (*keeper.Keeper, sdk.Context, error) { memStoreKey, paramsSubspace, nil, + "", ) ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) @@ -79,7 +80,7 @@ func GetASpec(specIndex, getToTopMostPath string, ctxArg *sdk.Context, keeper *k } proposalFile := "./cookbook/specs/ibc.json,./cookbook/specs/cosmoswasm.json,./cookbook/specs/tendermint.json,./cookbook/specs/cosmossdk.json,./cookbook/specs/cosmossdk_full.json,./cookbook/specs/ethereum.json,./cookbook/specs/cosmoshub.json,./cookbook/specs/lava.json,./cookbook/specs/osmosis.json,./cookbook/specs/fantom.json,./cookbook/specs/celo.json,./cookbook/specs/optimism.json,./cookbook/specs/arbitrum.json,./cookbook/specs/starknet.json,./cookbook/specs/aptos.json,./cookbook/specs/juno.json,./cookbook/specs/polygon.json,./cookbook/specs/evmos.json,./cookbook/specs/base.json,./cookbook/specs/canto.json,./cookbook/specs/sui.json,./cookbook/specs/solana.json,./cookbook/specs/bsc.json,./cookbook/specs/axelar.json,./cookbook/specs/avalanche.json,./cookbook/specs/fvm.json" for _, fileName := range strings.Split(proposalFile, ",") { - proposal := utils.SpecAddProposalJSON{} + proposal := utils.SpecAddProposalWithDepositJSON{} contents, err := os.ReadFile(getToTopMostPath + fileName) if err != nil { diff --git a/x/conflict/keeper/msg_server_detection.go b/x/conflict/keeper/msg_server_detection.go index b6b46e90af..e7df25b68e 100644 --- a/x/conflict/keeper/msg_server_detection.go +++ b/x/conflict/keeper/msg_server_detection.go @@ -26,6 +26,15 @@ func (k msgServer) Detection(goCtx context.Context, msg *types.MsgDetection) (*t utils.Attribute{Key: "client", Value: msg.Creator}, ) } + + spec, found := k.specKeeper.GetSpec(ctx, msg.ResponseConflict.ConflictRelayData0.Request.RelaySession.SpecId) + if !found || spec.UserSpec { + return nil, utils.LavaFormatWarning("Simulation: invalid spec for conflict (not found or user spec)", err, + utils.Attribute{Key: "found", Value: found}, + utils.Attribute{Key: "userSpec", Value: spec.UserSpec}, + ) + } + if msg.FinalizationConflict != nil && msg.ResponseConflict == nil && msg.SameProviderConflict == nil { err := k.Keeper.ValidateFinalizationConflict(ctx, msg.FinalizationConflict, clientAddr) if err != nil { diff --git a/x/conflict/keeper/msg_server_detection_test.go b/x/conflict/keeper/msg_server_detection_test.go index 740b153b47..ea8fc1e174 100644 --- a/x/conflict/keeper/msg_server_detection_test.go +++ b/x/conflict/keeper/msg_server_detection_test.go @@ -69,8 +69,14 @@ func TestDetection(t *testing.T) { ts := newTester(t) ts.setupForConflict(ProvidersCount) + userSpec := ts.spec + userSpec.Index = "USERSPEC" + userSpec.UserSpec = true + ts.AddSpec(userSpec.Index, userSpec) + tests := []struct { - name string + Name string + Spec spectypes.Spec Creator sigs.Account Provider0 sigs.Account Provider1 sigs.Account @@ -87,24 +93,25 @@ func TestDetection(t *testing.T) { ReplyData []byte Valid bool }{ - {"HappyFlow", ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 0, 100, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, - {"CuSumChange", ts.consumer, ts.providers[0], ts.providers[2], "", "", 0, "", []byte{}, 0, 0, 100, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, - {"RelayNumChange", ts.consumer, ts.providers[0], ts.providers[3], "", "", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, - {"SessionIDChange", ts.consumer, ts.providers[0], ts.providers[4], "", "", 0, "", []byte{}, 0, 0, 0, 1, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, - {"QoSNil", ts.consumer, ts.providers[2], ts.providers[3], "", "", 0, "", []byte{}, 0, 0, 0, 0, nil, []byte("DIFF"), true}, - {"BadCreator", ts.providers[4], ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"BadConnectionType", ts.consumer, ts.providers[0], ts.providers[1], "DIFF", "", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"BadURL", ts.consumer, ts.providers[0], ts.providers[1], "", "DIFF", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"BadBlockHeight", ts.consumer, ts.providers[0], ts.providers[1], "", "", 10, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"BadChainID", ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "DIFF", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"BadData", ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte("DIFF"), 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"BadRequestBlock", ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 10, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, - {"SameReplyData", ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 10, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte{}, false}, + {"HappyFlow", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 0, 100, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, + {"UserSpec", userSpec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 0, 100, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"CuSumChange", ts.spec, ts.consumer, ts.providers[0], ts.providers[2], "", "", 0, "", []byte{}, 0, 0, 100, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, + {"RelayNumChange", ts.spec, ts.consumer, ts.providers[0], ts.providers[3], "", "", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, + {"SessionIDChange", ts.spec, ts.consumer, ts.providers[0], ts.providers[4], "", "", 0, "", []byte{}, 0, 0, 0, 1, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), true}, + {"QoSNil", ts.spec, ts.consumer, ts.providers[2], ts.providers[3], "", "", 0, "", []byte{}, 0, 0, 0, 0, nil, []byte("DIFF"), true}, + {"BadCreator", ts.spec, ts.providers[4], ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"BadConnectionType", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "DIFF", "", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"BadURL", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "DIFF", 0, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"BadBlockHeight", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 10, "", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"BadChainID", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "DIFF", []byte{}, 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"BadData", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte("DIFF"), 0, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"BadRequestBlock", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 10, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte("DIFF"), false}, + {"SameReplyData", ts.spec, ts.consumer, ts.providers[0], ts.providers[1], "", "", 0, "", []byte{}, 10, 0, 0, 0, &types.QualityOfServiceReport{Latency: sdk.OneDec(), Availability: sdk.OneDec(), Sync: sdk.OneDec()}, []byte{}, false}, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - msg, _, reply, err := common.CreateMsgDetectionTest(ts.GoCtx, tt.Creator, tt.Provider0, tt.Provider1, ts.spec) + t.Run(tt.Name, func(t *testing.T) { + msg, _, reply, err := common.CreateMsgDetectionTest(ts.GoCtx, tt.Creator, tt.Provider0, tt.Provider1, tt.Spec) require.NoError(t, err) msg.Creator = tt.Creator.Addr.String() diff --git a/x/conflict/types/expected_keepers.go b/x/conflict/types/expected_keepers.go index da1d226f04..d5101c4575 100644 --- a/x/conflict/types/expected_keepers.go +++ b/x/conflict/types/expected_keepers.go @@ -36,6 +36,7 @@ type EpochstorageKeeper interface { type SpecKeeper interface { IsSpecFoundAndActive(ctx sdk.Context, chainID string) (foundAndActive, found bool, providersType spectypes.Spec_ProvidersTypes) IsFinalizedBlock(ctx sdk.Context, chainID string, requestedBlock, latestBlock int64) bool + GetSpec(ctx sdk.Context, index string) (val spectypes.Spec, found bool) } // AccountKeeper defines the expected account keeper used for simulations (noalias) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index c5138bbf01..bd2f83a1f0 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -277,7 +277,7 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen utils.LogLavaEvent(ctx, logger, types.RelayPaymentEventName, successDetails, "New Proof Of Work Was Accepted") cuAfterQos := rewardedCUDec.TruncateInt().Uint64() - err = k.chargeCuToSubscriptionAndCreditProvider(ctx, project, relay, cuAfterQos) + err = k.chargeCuToSubscriptionAndCreditProvider(ctx, project, relay, cuAfterQos, spec.UserSpec) if err != nil { return nil, utils.LavaFormatError("Failed charging CU to project and subscription", err) } @@ -393,7 +393,7 @@ func (k EpochCuCache) updateProvidersComplainerCU(ctx sdk.Context, unresponsiveP return nil } -func (k Keeper) chargeCuToSubscriptionAndCreditProvider(ctx sdk.Context, project projectstypes.Project, relay *types.RelaySession, cuAfterQos uint64) error { +func (k Keeper) chargeCuToSubscriptionAndCreditProvider(ctx sdk.Context, project projectstypes.Project, relay *types.RelaySession, cuAfterQos uint64, userSpec bool) error { epoch := uint64(relay.Epoch) err := k.projectsKeeper.ChargeComputeUnitsToProject(ctx, project, epoch, relay.CuSum) @@ -406,7 +406,7 @@ func (k Keeper) chargeCuToSubscriptionAndCreditProvider(ctx sdk.Context, project return fmt.Errorf("failed to add CU to the subscription") } - err = k.subscriptionKeeper.AddTrackedCu(ctx, sub.Consumer, relay.Provider, relay.SpecId, cuAfterQos, sub.Block) + err = k.subscriptionKeeper.AddTrackedCu(ctx, sub.Consumer, relay.Provider, relay.SpecId, cuAfterQos, sub.Block, userSpec) if err != nil { return err } diff --git a/x/pairing/keeper/msg_server_stake_provider_test.go b/x/pairing/keeper/msg_server_stake_provider_test.go index 5562e43c78..d8d65e5a29 100644 --- a/x/pairing/keeper/msg_server_stake_provider_test.go +++ b/x/pairing/keeper/msg_server_stake_provider_test.go @@ -204,7 +204,7 @@ func TestCmdStakeProviderGeoConfigAndEnum(t *testing.T) { require.NoError(t, err) // adjust endpoints to match the default API interfaces and addons generated with ts for i := 0; i < len(endpoints); i++ { - endpoints[i].ApiInterfaces = []string{"stub"} + endpoints[i].ApiInterfaces = []string{spectypes.APIInterfaceJsonRPC} endpoints[i].Addons = []string{} } _, err = ts.TxPairingStakeProvider(provider, acc.GetVaultAddr(), ts.spec.Index, ts.spec.MinStakeProvider, endpoints, geo, common.MockDescription()) diff --git a/x/pairing/types/expected_keepers.go b/x/pairing/types/expected_keepers.go index 562feb1b2b..1cafb4c724 100644 --- a/x/pairing/types/expected_keepers.go +++ b/x/pairing/types/expected_keepers.go @@ -91,7 +91,7 @@ type SubscriptionKeeper interface { GetAllSubTrackedCuIndices(ctx sdk.Context, sub string) []string GetTrackedCu(ctx sdk.Context, sub string, provider string, chainID string, block uint64) (cu uint64, found bool, key string) CalcTotalMonthlyReward(ctx sdk.Context, totalAmount math.Int, trackedCu uint64, totalCuUsedBySub uint64) math.Int - AddTrackedCu(ctx sdk.Context, sub string, provider string, chainID string, cu uint64, block uint64) error + AddTrackedCu(ctx sdk.Context, sub string, provider string, chainID string, cu uint64, block uint64, userSpec bool) error GetAllSubscriptionsIndices(ctx sdk.Context) []string AppendAdjustment(ctx sdk.Context, consumer string, provider string, totalConsumerUsage uint64, usageWithThisProvider uint64) CalculateParticipationFees(ctx sdk.Context, reward sdk.Coin) (sdk.Coins, sdk.Coins, error) diff --git a/x/rewards/keeper/iprpc_test.go b/x/rewards/keeper/iprpc_test.go index fd94755a6b..f3a23739c6 100644 --- a/x/rewards/keeper/iprpc_test.go +++ b/x/rewards/keeper/iprpc_test.go @@ -9,6 +9,7 @@ import ( "github.com/lavanet/lava/testutil/common" "github.com/lavanet/lava/utils/sigs" rewardstypes "github.com/lavanet/lava/x/rewards/types" + spectypes "github.com/lavanet/lava/x/spec/types" "github.com/stretchr/testify/require" ) @@ -630,7 +631,12 @@ func TestMultipleIprpcSpec(t *testing.T) { spec3 := common.CreateMockSpec() spec3.Index = mockSpec3 spec3.Name = mockSpec3 - ts.specs = append(ts.specs, ts.AddSpec(mockSpec3, spec3).Spec(mockSpec3)) + msgSpec := spectypes.MsgAddSpecs{} + msgSpec.Specs = append(msgSpec.Specs, spec3) + msgSpec.Creator = c1Acc.Addr.String() + ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msgSpec) + + ts.specs = append(ts.specs, spec3) err := ts.StakeProvider(p1Acc.GetVaultAddr(), p1, ts.specs[2], testStake) require.NoError(ts.T, err) err = ts.StakeProvider(p2Acc.GetVaultAddr(), p2, ts.specs[2], testStake) diff --git a/x/rewards/keeper/providers_test.go b/x/rewards/keeper/providers_test.go index 50a85b3bc5..9c959287c4 100644 --- a/x/rewards/keeper/providers_test.go +++ b/x/rewards/keeper/providers_test.go @@ -9,6 +9,7 @@ import ( "github.com/lavanet/lava/testutil/common" "github.com/lavanet/lava/utils/sigs" "github.com/lavanet/lava/x/rewards/types" + spectypes "github.com/lavanet/lava/x/spec/types" subscription "github.com/lavanet/lava/x/subscription/keeper" "github.com/stretchr/testify/require" ) @@ -742,3 +743,52 @@ func TestCommunityTaxOne(t *testing.T) { communityBalance := communityCoins.AmountOf(ts.TokenDenom()).TruncateInt() require.Equal(t, expectedReward, communityBalance) } + +// TestZeroBonusRewardsForUserSpec tests that rewards are not given to providers who serve user specs +func TestZeroBonusRewardsForUserSpec(t *testing.T) { + ts := newTester(t, true) + + providerAcc, _ := ts.AddAccount(common.PROVIDER, 1, testBalance) + + // add user spec + spec := ts.specs[0] + spec.Index = "USERSPEC" + msgSpec := spectypes.MsgAddSpecs{} + msgSpec.Specs = append(msgSpec.Specs, spec) + msgSpec.Creator = providerAcc.Addr.String() + ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msgSpec) + + err := ts.StakeProvider(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), spec, testBalance) + require.NoError(t, err) + + ts.AdvanceEpoch() + + consumerAcc, _ := ts.AddAccount(common.CONSUMER, 1, ts.plan.Price.Amount.Int64()) + _, err = ts.TxSubscriptionBuy(consumerAcc.Addr.String(), consumerAcc.Addr.String(), ts.plan.Index, 1, false, false) + require.NoError(t, err) + + baserewards := uint64(100) + // the rewards by the subscription will be limited by LIMIT_TOKEN_PER_CU + msg := ts.SendRelay(providerAcc.Addr.String(), consumerAcc, []string{spec.Index}, baserewards) + _, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...) + require.NoError(t, err) + + // first months there are no bonus rewards and no regular rewards + ts.AdvanceMonths(1) + ts.AdvanceEpoch() + ts.AdvanceBlocks(ts.BlocksToSave() + 1) + + res, err := ts.QueryDualstakingDelegatorRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), "") + require.NoError(t, err) + /// no subscription rewards for user specs + require.Len(t, res.Rewards, 0) + + // now the provider should get all of the provider allocation + ts.AdvanceMonths(1) + ts.AdvanceEpoch() + + res, err = ts.QueryDualstakingDelegatorRewards(providerAcc.GetVaultAddr(), providerAcc.Addr.String(), "") + require.NoError(t, err) + /// no boost rewards for user specs + require.Len(t, res.Rewards, 0) +} diff --git a/x/spec/README.md b/x/spec/README.md index 6f43a1f00d..6e3adcc8ac 100644 --- a/x/spec/README.md +++ b/x/spec/README.md @@ -12,6 +12,7 @@ This document focuses on the specs' technical aspects and does not include curre ## Contents * [Concepts](#concepts) * [Spec](#spec) + * [UserSpec](#userspec) * [ApiCollections](#apicollection) * [CollectionData](#collectiondata) * [Extension](#extension) @@ -54,7 +55,9 @@ type Spec struct { ReliabilityThreshold uint32 // this determines the probability of data reliability checks by the consumer DataReliabilityEnabled bool // enables/disables data reliability for the chain BlockDistanceForFinalizedData uint32 - BlocksInFinalizationProof uint32 + BlocksInFinalizationProof uint32 + identity string // url identity in keybase + user_spec bool // specifies if this spec was added with gov or by a user, set automatic by the chain } ``` `Coin` type is from Cosmos-SDK (`cosmos.base.v1beta1.Coin`). @@ -62,6 +65,17 @@ type Spec struct { A `Contributor` is a member of the Lava community who can earn token commissions by maintaining specs on Lava. +### UserSpec + +User spec is a spec that was added without a gov proposal, using the tx `AddSpecs`. +These specs are meant for testing and providers can stake and serve consumers. +With a gov proposal of the same spec, it can become an official spec on chain and the next limitations will be removed. +A user spec is limited in use as follows: + +* user specs cannot get boost and subscription rewards +* conflicts cannot be opened for user specs +* user specs contribuitions for contributors are fixed and cannot be changed + ### ApiCollection ApiCollection is a struct that defines an interface, such as REST, JSON, etc., along with all of its APIs and properties. diff --git a/x/spec/client/cli/tx.go b/x/spec/client/cli/tx.go index 344cdb44c1..518b69e667 100644 --- a/x/spec/client/cli/tx.go +++ b/x/spec/client/cli/tx.go @@ -5,7 +5,6 @@ import ( "strings" "time" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" @@ -18,6 +17,7 @@ import ( "github.com/lavanet/lava/x/spec/client/utils" "github.com/lavanet/lava/x/spec/types" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -43,7 +43,7 @@ func GetTxCmd() *cobra.Command { } // this line is used by starport scaffolding # 1 - + cmd.AddCommand(CmdTxAddSpecs()) return cmd } @@ -89,10 +89,6 @@ $ %s tx gov spec-proposal spec-add --from= --from= --from= --from= +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + proposal, err := utils.ParseSpecAddProposalJSON(clientCtx.LegacyAmino, args[0]) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + content := &proposal.Proposal + + devTest, err := cmd.Flags().GetBool(devTestFlagName) + if err == nil && devTest { + // modify the lava spec for dev tests + for idx, spec := range content.Specs { + if spec.Index == "LAV1" { + utilslib.LavaFormatInfo("modified lava spec time for dev tests") + content.Specs[idx].AverageBlockTime = (1 * time.Second).Milliseconds() + for collection := range content.Specs[idx].ApiCollections { + for verification := range content.Specs[idx].ApiCollections[collection].Verifications { + if content.Specs[idx].ApiCollections[collection].Verifications[verification].Name == "chain-id" { + content.Specs[idx].ApiCollections[collection].Verifications[verification].Values[0].ExpectedValue = "*" + } + if content.Specs[idx].ApiCollections[collection].Verifications[verification].Name == "pruning" { + content.Specs[idx].ApiCollections[collection].Verifications = append(content.Specs[idx].ApiCollections[collection].Verifications[:verification], content.Specs[idx].ApiCollections[collection].Verifications[verification+1:]...) + } + } + } + } + } + } + + msgAddSpecs := types.NewMsgAddSpecs(from.String(), content.Specs) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgAddSpecs) + }, + } + cmd.Flags().Bool(devTestFlagName, false, "set to true to modify the average block time for lava spec") + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/spec/client/utils/utils.go b/x/spec/client/utils/utils.go index d00d19c99a..94580a87c4 100755 --- a/x/spec/client/utils/utils.go +++ b/x/spec/client/utils/utils.go @@ -17,15 +17,21 @@ import ( type ( SpecAddProposalJSON struct { - Proposal types.SpecAddProposal `json:"proposal"` - Deposit string `json:"deposit" yaml:"deposit"` + Title string `json:"title"` + Description string `json:"description"` + Specs []types.Spec `json:"specs"` + } + + SpecAddProposalWithDepositJSON struct { + Proposal SpecAddProposalJSON `json:"proposal"` + Deposit string `json:"deposit" yaml:"deposit"` } ) // Parse spec add proposal JSON form file -func ParseSpecAddProposalJSON(cdc *codec.LegacyAmino, proposalFile string) (ret SpecAddProposalJSON, err error) { +func ParseSpecAddProposalJSON(cdc *codec.LegacyAmino, proposalFile string) (ret SpecAddProposalWithDepositJSON, err error) { for _, fileName := range strings.Split(proposalFile, ",") { - proposal := SpecAddProposalJSON{} + proposal := SpecAddProposalWithDepositJSON{} contents, err := os.ReadFile(fileName) if err != nil { diff --git a/x/spec/keeper/keeper.go b/x/spec/keeper/keeper.go index 45ac8abe7f..0f7486a6df 100644 --- a/x/spec/keeper/keeper.go +++ b/x/spec/keeper/keeper.go @@ -21,6 +21,7 @@ type ( paramstore paramtypes.Subspace stakingKeeper types.StakingKeeper + authority string } ) @@ -30,6 +31,7 @@ func NewKeeper( memKey storetypes.StoreKey, ps paramtypes.Subspace, stakingKeeper types.StakingKeeper, + authority string, ) *Keeper { // set KeyTable if it has not already been set if !ps.HasKeyTable() { @@ -42,6 +44,7 @@ func NewKeeper( memKey: memKey, paramstore: ps, stakingKeeper: stakingKeeper, + authority: authority, } } @@ -50,3 +53,5 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { } func (k Keeper) BeginBlock(ctx sdk.Context) {} + +func (k Keeper) GetAuthority() string { return k.authority } diff --git a/x/spec/keeper/migrations.go b/x/spec/keeper/migrations.go index 2f76988f05..4153a6f6e4 100644 --- a/x/spec/keeper/migrations.go +++ b/x/spec/keeper/migrations.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" "github.com/lavanet/lava/x/spec/types" typesv1 "github.com/lavanet/lava/x/spec/types/migrations/v1" ) @@ -50,3 +51,13 @@ func (m Migrator) Migrate3to4(ctx sdk.Context) error { return nil } + +func (m Migrator) Migrate4to5(ctx sdk.Context) error { + params := m.keeper.GetParams(ctx) + if !sdk.SliceContains(params.AllowlistedExpeditedMsgs, proto.MessageName(&types.MsgAddSpecs{})) { + params.AllowlistedExpeditedMsgs = append(params.AllowlistedExpeditedMsgs, proto.MessageName(&types.MsgAddSpecs{})) + m.keeper.SetParams(ctx, params) + } + + return nil +} diff --git a/x/spec/keeper/msg_server_add_specs.go b/x/spec/keeper/msg_server_add_specs.go new file mode 100644 index 0000000000..bc884fab38 --- /dev/null +++ b/x/spec/keeper/msg_server_add_specs.go @@ -0,0 +1,15 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/x/spec/types" +) + +func (k msgServer) AddSpecs(goCtx context.Context, msg *types.MsgAddSpecs) (*types.MsgAddSpecsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + err := k.HandleSpecs(ctx, msg.Specs, msg.Creator) + return &types.MsgAddSpecsResponse{}, err +} diff --git a/x/spec/keeper/msg_server_add_specs_test.go b/x/spec/keeper/msg_server_add_specs_test.go new file mode 100644 index 0000000000..39e082ed8a --- /dev/null +++ b/x/spec/keeper/msg_server_add_specs_test.go @@ -0,0 +1,58 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + "github.com/lavanet/lava/x/spec/keeper" + "github.com/lavanet/lava/x/spec/types" + "github.com/stretchr/testify/require" + + testcommon "github.com/lavanet/lava/testutil/common" +) + +func TestSpecAddPermissions(t *testing.T) { + ts := newTester(t) + spec := testcommon.CreateMockSpec() + spec.DataReliabilityEnabled = false + contributorPercentage := math.LegacyMustNewDecFromStr("0.5") + spec.ContributorPercentage = &contributorPercentage + + msg := types.MsgAddSpecs{} + msg.Specs = append(msg.Specs, spec) + + // adding spec from user 1 + User1, _ := ts.AddAccount("user", 0, 10000) + msg.Creator = User1.Addr.String() + _, err := ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msg) + require.NoError(t, err) + + // trying to add same spec from user 2 + User2, _ := ts.AddAccount("user", 1, 10000) + msg.Creator = User2.Addr.String() + _, err = ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msg) + require.Error(t, err) + + // adding spec from user 1 + msg.Creator = User1.Addr.String() + _, err = ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msg) + require.NoError(t, err) + + val, found := ts.Keepers.Spec.GetSpec(ts.Ctx, spec.Index) + require.True(t, found) + require.True(t, val.ContributorPercentage.Equal(math.LegacyMustNewDecFromStr(keeper.USER_SPEC_CONTRIBUTION))) + + // add the spec from gov + msg.Creator = ts.Keepers.Spec.GetAuthority() + _, err = ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msg) + require.NoError(t, err) + + // try to add again from user 1 + msg.Creator = User1.Addr.String() + _, err = ts.Servers.SpecServer.AddSpecs(ts.Ctx, &msg) + require.Error(t, err) + + val, found = ts.Keepers.Spec.GetSpec(ts.Ctx, spec.Index) + require.True(t, found) + require.False(t, val.ContributorPercentage.Equal(math.LegacyMustNewDecFromStr(keeper.USER_SPEC_CONTRIBUTION))) +} diff --git a/x/spec/keeper/spec.go b/x/spec/keeper/spec.go index 905d9d6ff2..164fba3f2f 100644 --- a/x/spec/keeper/spec.go +++ b/x/spec/keeper/spec.go @@ -15,6 +15,8 @@ import ( "github.com/lavanet/lava/x/spec/types" ) +const USER_SPEC_CONTRIBUTION = "0.1" + // SetSpec set a specific Spec in the store from its index func (k Keeper) SetSpec(ctx sdk.Context, spec types.Spec) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.SpecKeyPrefix)) @@ -359,3 +361,88 @@ func (k Keeper) GetMinStake(ctx sdk.Context, chainID string) sdk.Coin { return spec.MinStakeProvider } + +func (k Keeper) HandleSpecs(ctx sdk.Context, specs []types.Spec, creator string) error { + logger := k.Logger(ctx) + + type event struct { + name string + event string + details map[string]string + } + + var events []event + + for _, spec := range specs { + ogSpec, found := k.GetSpec(ctx, spec.Index) + + spec.UserSpec = creator != k.authority + if spec.UserSpec { + if found { + if !ogSpec.UserSpec { + return utils.LavaFormatWarning("user cannot change existing gov specs", nil) + } else if !sdk.SliceContains(ogSpec.Contributor, creator) { + return utils.LavaFormatWarning("user cannot change spec which he is not a contributor at", nil) + } + } + + if !sdk.SliceContains(spec.Contributor, creator) { + spec.Contributor = append(spec.Contributor, creator) + } + contributorPercentage := math.LegacyMustNewDecFromStr(USER_SPEC_CONTRIBUTION) + spec.ContributorPercentage = &contributorPercentage + } + + spec.BlockLastUpdated = uint64(ctx.BlockHeight()) + k.SetSpec(ctx, spec) + + details, err := k.ValidateSpec(ctx, spec) + if err != nil { + attrs := utils.StringMapToAttributes(details) + return utils.LavaFormatWarning("invalid spec", err, attrs...) + } + + name := types.SpecAddEventName + + if found { + name = types.SpecModifyEventName + } + + // collect the events first, and only log them after everything succeeded + events = append(events, event{ + name: name, + event: "Gov Proposal Accepted Spec", + details: details, + }) + + // TODO: add api types once its implemented to the event + } + + // re-validate all the specs, in case the modified spec is imported by + // other specs and the new version creates a conflict; also update the + // BlockLastUpdated of all specs that inherit from the modified spec. + for _, spec := range k.GetAllSpec(ctx) { + inherits, err := k.RefreshSpec(ctx, spec, specs) + if err != nil { + return utils.LavaFormatWarning("invalidated spec", err) + } + if len(inherits) > 0 { + details := map[string]string{ + "name": spec.Index, + "import": strings.Join(inherits, ","), + } + name := types.SpecRefreshEventName + events = append(events, event{ + name: name, + event: "Gov Proposal Refreshsed Spec", + details: details, + }) + } + } + + for _, e := range events { + utils.LogLavaEvent(ctx, logger, e.name, e.details, e.event) + } + + return nil +} diff --git a/x/spec/keeper/spec_test.go b/x/spec/keeper/spec_test.go index fb98cd866c..93a8869f2c 100644 --- a/x/spec/keeper/spec_test.go +++ b/x/spec/keeper/spec_test.go @@ -820,7 +820,7 @@ func TestCookbookSpecs(t *testing.T) { Specs = removeSetFromSet(baseSpecs, Specs) Specs = append(baseSpecs, Specs...) for _, fileName := range Specs { - proposal := utils.SpecAddProposalJSON{} + proposal := utils.SpecAddProposalWithDepositJSON{} contents, err := os.ReadFile(getToTopMostPath + fileName) require.NoError(t, err) @@ -1081,7 +1081,7 @@ func TestSpecParsing(t *testing.T) { } }` - var proposal utils.SpecAddProposalJSON + var proposal utils.SpecAddProposalWithDepositJSON err := json.Unmarshal([]byte(specJSON), &proposal) require.NoError(t, err) ts := newTester(t) diff --git a/x/spec/module.go b/x/spec/module.go index 5244792d52..61143299bb 100644 --- a/x/spec/module.go +++ b/x/spec/module.go @@ -126,7 +126,7 @@ func (am AppModule) Name() string { // module-specific GRPC queries. func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - types.RegisterMsgServer(cfg.MsgServer(), am.keeper) + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) migrator := keeper.NewMigrator(am.keeper) @@ -141,6 +141,12 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { // panic:ok: at start up, migration cannot proceed anyhow panic(fmt.Errorf("%s: failed to register migration to v4: %w", types.ModuleName, err)) } + + // register v4 -> v5 migration + if err := cfg.RegisterMigration(types.ModuleName, 4, migrator.Migrate4to5); 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)) + } } // RegisterInvariants registers the capability module's invariants. @@ -165,7 +171,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/spec/proposal_handler.go b/x/spec/proposal_handler.go index 4f63b3fd0d..866f9760e0 100644 --- a/x/spec/proposal_handler.go +++ b/x/spec/proposal_handler.go @@ -2,8 +2,6 @@ package spec import ( "fmt" - "log" - "strings" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" @@ -14,7 +12,6 @@ import ( paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" "github.com/lavanet/lava/utils" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" - "github.com/lavanet/lava/x/spec/keeper" "github.com/lavanet/lava/x/spec/types" ) @@ -72,85 +69,3 @@ func HandleParameterChangeProposal(ctx sdk.Context, k paramkeeper.Keeper, p *par return nil } - -// NewSpecProposalsHandler creates a new governance Handler for a Spec -func NewSpecProposalsHandler(k keeper.Keeper) v1beta1.Handler { - return func(ctx sdk.Context, content v1beta1.Content) error { - switch c := content.(type) { - case *types.SpecAddProposal: - return handleSpecProposal(ctx, k, c) - - default: - log.Println("unrecognized spec proposal content") - return sdkerrors.Wrapf(legacyerrors.ErrUnknownRequest, "unrecognized spec proposal content type: %T", c) - } - } -} - -func handleSpecProposal(ctx sdk.Context, k keeper.Keeper, p *types.SpecAddProposal) error { - logger := k.Logger(ctx) - - type event struct { - name string - event string - details map[string]string - } - - var events []event - - for _, spec := range p.Specs { - _, found := k.GetSpec(ctx, spec.Index) - - spec.BlockLastUpdated = uint64(ctx.BlockHeight()) - k.SetSpec(ctx, spec) - - details, err := k.ValidateSpec(ctx, spec) - if err != nil { - attrs := utils.StringMapToAttributes(details) - return utils.LavaFormatWarning("invalid spec", err, attrs...) - } - - name := types.SpecAddEventName - - if found { - name = types.SpecModifyEventName - } - - // collect the events first, and only log them after everything succeeded - events = append(events, event{ - name: name, - event: "Gov Proposal Accepted Spec", - details: details, - }) - - // TODO: add api types once its implemented to the event - } - - // re-validate all the specs, in case the modified spec is imported by - // other specs and the new version creates a conflict; also update the - // BlockLastUpdated of all specs that inherit from the modified spec. - for _, spec := range k.GetAllSpec(ctx) { - inherits, err := k.RefreshSpec(ctx, spec, p.Specs) - if err != nil { - return utils.LavaFormatWarning("invalidated spec", err) - } - if len(inherits) > 0 { - details := map[string]string{ - "name": spec.Index, - "import": strings.Join(inherits, ","), - } - name := types.SpecRefreshEventName - events = append(events, event{ - name: name, - event: "Gov Proposal Refreshsed Spec", - details: details, - }) - } - } - - for _, e := range events { - utils.LogLavaEvent(ctx, logger, e.name, e.details, e.event) - } - - return nil -} diff --git a/x/spec/types/addproposal.go b/x/spec/types/addproposal.go deleted file mode 100644 index c0da76c2be..0000000000 --- a/x/spec/types/addproposal.go +++ /dev/null @@ -1,73 +0,0 @@ -package types - -import ( - fmt "fmt" - "strings" - - "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - - sdkerrors "cosmossdk.io/errors" -) - -const ( - ProposalSpecAdd = "SpecAdd" -) - -var _ v1beta1.Content = &SpecAddProposal{} - -func init() { - v1beta1.RegisterProposalType(ProposalSpecAdd) -} - -func NewSpecAddProposal(title, description string, specs []Spec) *SpecAddProposal { - return &SpecAddProposal{title, description, specs} -} - -// GetTitle returns the title of a proposal. -func (pcp *SpecAddProposal) GetTitle() string { return pcp.Title } - -// GetDescription returns the description of a proposal. -func (pcp *SpecAddProposal) GetDescription() string { return pcp.Description } - -// ProposalRoute returns the routing key of a proposal. -func (pcp *SpecAddProposal) ProposalRoute() string { return ProposalsRouterKey } - -// ProposalType returns the type of a proposal. -func (pcp *SpecAddProposal) ProposalType() string { return ProposalSpecAdd } - -// ValidateBasic validates the proposal -func (pcp *SpecAddProposal) ValidateBasic() error { - err := v1beta1.ValidateAbstract(pcp) - if err != nil { - return err - } - - if len(pcp.Specs) == 0 { - return sdkerrors.Wrap(ErrEmptySpecs, "proposal specs cannot be empty") - } - for _, spec := range pcp.Specs { - err := checkSpecProposal(spec) - if err != nil { - return err - } - } - - return nil -} - -// String implements the Stringer interface. -func (pcp SpecAddProposal) String() string { - var b strings.Builder - - b.WriteString(fmt.Sprintf(`Spec Add Proposal: - Title: %s - Description: %s - Changes: - `, pcp.Title, pcp.Description)) - - for _, spec := range pcp.Specs { - b = stringSpec(spec, b) - } - - return b.String() -} diff --git a/x/spec/types/codec.go b/x/spec/types/codec.go index 899edc36f1..78c672e9fd 100644 --- a/x/spec/types/codec.go +++ b/x/spec/types/codec.go @@ -20,7 +20,6 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations( (*v1beta1.Content)(nil), - &SpecAddProposal{}, ) } diff --git a/x/spec/types/message_add_specs.go b/x/spec/types/message_add_specs.go new file mode 100644 index 0000000000..769aa1ea62 --- /dev/null +++ b/x/spec/types/message_add_specs.go @@ -0,0 +1,54 @@ +package types + +import ( + sdkerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgAddSpecs = "cover_ibc_iprpc_fund_cost" + +var _ sdk.Msg = &MsgAddSpecs{} + +func NewMsgAddSpecs(creator string, specs []Spec) *MsgAddSpecs { + return &MsgAddSpecs{ + Creator: creator, + Specs: specs, + } +} + +func (msg *MsgAddSpecs) Route() string { + return RouterKey +} + +func (msg *MsgAddSpecs) Type() string { + return TypeMsgAddSpecs +} + +func (msg *MsgAddSpecs) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + return []sdk.AccAddress{creator} +} + +func (msg *MsgAddSpecs) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgAddSpecs) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkerrors.Wrapf(legacyerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + + for _, v := range msg.Specs { + err := v.ValidateBasic() + if err != nil { + return err + } + } + return nil +} diff --git a/x/spec/types/proposal.go b/x/spec/types/proposal.go index e53410bb5d..a554f66c20 100644 --- a/x/spec/types/proposal.go +++ b/x/spec/types/proposal.go @@ -7,7 +7,7 @@ import ( sdkerrors "cosmossdk.io/errors" ) -func checkSpecProposal(spec Spec) error { +func (spec Spec) ValidateBasic() error { if len(strings.TrimSpace(spec.Name)) == 0 { return sdkerrors.Wrapf(ErrBlankSpecName, "spec name cannot be blank %v", spec) } diff --git a/x/spec/types/spec.pb.go b/x/spec/types/spec.pb.go index ab47f378b6..e83111b2a0 100644 --- a/x/spec/types/spec.pb.go +++ b/x/spec/types/spec.pb.go @@ -69,6 +69,7 @@ type Spec struct { ContributorPercentage *github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,18,opt,name=contributor_percentage,json=contributorPercentage,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"contributor_percentage,omitempty"` Shares uint64 `protobuf:"varint,19,opt,name=shares,proto3" json:"shares,omitempty"` Identity string `protobuf:"bytes,20,opt,name=identity,proto3" json:"identity,omitempty"` + UserSpec bool `protobuf:"varint,21,opt,name=user_spec,json=userSpec,proto3" json:"user_spec,omitempty"` } func (m *Spec) Reset() { *m = Spec{} } @@ -223,6 +224,13 @@ func (m *Spec) GetIdentity() string { return "" } +func (m *Spec) GetUserSpec() bool { + if m != nil { + return m.UserSpec + } + return false +} + func init() { proto.RegisterEnum("lavanet.lava.spec.Spec_ProvidersTypes", Spec_ProvidersTypes_name, Spec_ProvidersTypes_value) proto.RegisterType((*Spec)(nil), "lavanet.lava.spec.Spec") @@ -231,52 +239,53 @@ func init() { func init() { proto.RegisterFile("lavanet/lava/spec/spec.proto", fileDescriptor_789140b95c48dfce) } var fileDescriptor_789140b95c48dfce = []byte{ - // 715 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0xdf, 0x6e, 0xeb, 0x34, - 0x18, 0x6f, 0x68, 0x4e, 0xdb, 0xb9, 0x9c, 0x2e, 0xc7, 0xf4, 0x4c, 0xde, 0x74, 0xc8, 0xc2, 0x84, - 0xa6, 0x80, 0x20, 0xd1, 0xb6, 0x1b, 0xee, 0xd0, 0xba, 0x51, 0xb1, 0x09, 0xc4, 0xc8, 0xc6, 0x0d, - 0x37, 0x91, 0xe3, 0x78, 0xad, 0xb5, 0xc4, 0x0e, 0xb1, 0x57, 0x56, 0x9e, 0x82, 0xc7, 0xe0, 0x51, - 0x76, 0xb9, 0xcb, 0x89, 0x8b, 0x09, 0x75, 0x2f, 0x82, 0xec, 0x24, 0x23, 0xd5, 0xb8, 0xa9, 0xf3, - 0xf9, 0xf7, 0xe7, 0xb3, 0xdd, 0x9f, 0x0d, 0x3e, 0x64, 0x78, 0x81, 0x39, 0x55, 0xa1, 0x1e, 0x43, - 0x59, 0x50, 0x62, 0x7e, 0x82, 0xa2, 0x14, 0x4a, 0xc0, 0x77, 0x35, 0x1a, 0xe8, 0x31, 0xd0, 0xc0, - 0xce, 0x78, 0x26, 0x66, 0xc2, 0xa0, 0xa1, 0xfe, 0xaa, 0x88, 0x3b, 0xfb, 0xaf, 0x6d, 0x70, 0xc1, - 0x62, 0x22, 0xb2, 0x8c, 0x12, 0xc5, 0x04, 0xaf, 0x79, 0x2e, 0x11, 0x32, 0x17, 0x32, 0x4c, 0xb0, - 0xa4, 0xe1, 0xe2, 0x20, 0xa1, 0x0a, 0x1f, 0x84, 0x44, 0xb0, 0x1a, 0xdf, 0x7b, 0xec, 0x03, 0xfb, - 0xb2, 0xa0, 0x04, 0x8e, 0xc1, 0x1b, 0xc6, 0x53, 0x7a, 0x87, 0x2c, 0xcf, 0xf2, 0x37, 0xa2, 0xaa, - 0x80, 0x10, 0xd8, 0x1c, 0xe7, 0x14, 0x7d, 0x64, 0x26, 0xcd, 0x37, 0x44, 0xa0, 0x4f, 0x39, 0x4e, - 0x32, 0x9a, 0x22, 0xdb, 0xb3, 0xfc, 0x41, 0xd4, 0x94, 0xf0, 0x08, 0xbc, 0x2f, 0x69, 0xc6, 0x70, - 0xc2, 0x32, 0xa6, 0x96, 0xb1, 0x9a, 0x97, 0x54, 0xce, 0x45, 0x96, 0xa2, 0x37, 0x9e, 0xe5, 0xbf, - 0x8d, 0xc6, 0x2d, 0xf0, 0xaa, 0xc1, 0xe0, 0x37, 0x00, 0xa5, 0x58, 0xe1, 0xb8, 0xad, 0x6c, 0xfc, - 0x7b, 0xc6, 0x7f, 0x4b, 0xe3, 0xd1, 0x7f, 0xf0, 0x77, 0x75, 0xbb, 0xef, 0xc1, 0x67, 0x49, 0x26, - 0xc8, 0x4d, 0x9c, 0x32, 0xa9, 0x30, 0x27, 0x34, 0xbe, 0x16, 0x65, 0x7c, 0xcd, 0x38, 0xce, 0xd8, - 0x1f, 0x34, 0x8d, 0xb5, 0x0c, 0xf5, 0x4d, 0xeb, 0x4f, 0x0d, 0xf1, 0xb4, 0xe6, 0x4d, 0x45, 0x39, - 0x6d, 0x58, 0xa7, 0x58, 0x61, 0xf8, 0x2d, 0xf8, 0x60, 0x08, 0x32, 0x66, 0xbc, 0x31, 0xc0, 0xfa, - 0x14, 0xe3, 0xa2, 0x14, 0xe2, 0x1a, 0x0d, 0x8c, 0xc9, 0x76, 0xc5, 0x39, 0xe3, 0xd3, 0x16, 0xe3, - 0x42, 0x13, 0xe0, 0x57, 0x00, 0xe2, 0x05, 0x2d, 0xf1, 0x8c, 0xc6, 0xd5, 0x92, 0x14, 0xcb, 0x29, - 0xda, 0xf0, 0x2c, 0xbf, 0x1b, 0x39, 0x35, 0x32, 0xd1, 0xc0, 0x15, 0xcb, 0x29, 0x3c, 0x06, 0x2e, - 0xce, 0x32, 0xf1, 0x3b, 0x4d, 0x6b, 0x76, 0x86, 0x67, 0x66, 0xed, 0xbf, 0x09, 0x19, 0xcb, 0x25, - 0x27, 0x08, 0x18, 0xe5, 0x76, 0xcd, 0x32, 0xca, 0x1f, 0xf0, 0x6c, 0x2a, 0xca, 0x9f, 0x85, 0xbc, - 0x5c, 0x72, 0xa2, 0x1b, 0x36, 0x52, 0xa9, 0xe2, 0xdb, 0x22, 0xc5, 0x8a, 0xa6, 0x68, 0xe8, 0x59, - 0xbe, 0x1d, 0x39, 0x49, 0xc5, 0x97, 0xea, 0x97, 0x6a, 0x1e, 0xfe, 0x08, 0x60, 0xce, 0x78, 0x2c, - 0x15, 0xbe, 0xa1, 0x7a, 0x4b, 0x0b, 0x96, 0xd2, 0x12, 0x7d, 0xec, 0x59, 0xfe, 0xf0, 0x70, 0x3b, - 0xa8, 0x22, 0x12, 0xe8, 0x88, 0x04, 0x75, 0x44, 0x82, 0x13, 0xc1, 0xf8, 0xc4, 0xbe, 0x7f, 0xda, - 0xed, 0x44, 0x4e, 0xce, 0xf8, 0xa5, 0x56, 0x5e, 0xd4, 0x42, 0xf8, 0x13, 0xd8, 0x6c, 0x4c, 0x64, - 0xac, 0x96, 0x05, 0x95, 0x68, 0xe4, 0x59, 0xfe, 0xe8, 0x70, 0x3f, 0x78, 0x95, 0xdf, 0x40, 0xa7, - 0x2b, 0x68, 0xa4, 0xf2, 0x4a, 0xb3, 0xa3, 0x51, 0xb1, 0x56, 0xeb, 0x48, 0xb1, 0xbc, 0x10, 0xa5, - 0x92, 0x68, 0xd3, 0xeb, 0xfa, 0x1b, 0x51, 0x53, 0xc2, 0x33, 0xb0, 0xb9, 0x9e, 0x6b, 0x89, 0x1c, - 0xaf, 0xeb, 0x0f, 0x0f, 0xbd, 0xff, 0x69, 0x75, 0x5c, 0xb0, 0x93, 0x17, 0x62, 0x34, 0xc2, 0xed, - 0x52, 0x42, 0x0f, 0x0c, 0x89, 0xe0, 0xaa, 0x64, 0xc9, 0xad, 0x12, 0x25, 0x7a, 0x67, 0x1a, 0xb5, - 0xa7, 0x20, 0x06, 0x5b, 0xad, 0x32, 0x2e, 0x68, 0x49, 0x28, 0x57, 0x78, 0x46, 0x11, 0xd4, 0xf9, - 0x9f, 0x7c, 0xf9, 0xf7, 0xd3, 0xee, 0xfe, 0x8c, 0xa9, 0xf9, 0x6d, 0x12, 0x10, 0x91, 0x87, 0xf5, - 0xdd, 0xaa, 0x86, 0xaf, 0x65, 0x7a, 0x13, 0x9a, 0xc3, 0x08, 0x4e, 0x29, 0x89, 0xde, 0xb7, 0x9c, - 0x2e, 0x5e, 0x8c, 0xe0, 0x16, 0xe8, 0xc9, 0x39, 0x2e, 0xa9, 0x44, 0x9f, 0x98, 0xff, 0xaa, 0xae, - 0xe0, 0x0e, 0x18, 0xb0, 0x94, 0x72, 0xc5, 0xd4, 0x12, 0x8d, 0xcd, 0x65, 0x7b, 0xa9, 0xf7, 0xbe, - 0x00, 0xa3, 0xf5, 0xf3, 0x83, 0x43, 0xd0, 0x4f, 0x97, 0x1c, 0xe7, 0x8c, 0x38, 0x1d, 0x08, 0x40, - 0x4f, 0x2a, 0xac, 0x18, 0x71, 0xac, 0x73, 0x7b, 0xd0, 0x75, 0xec, 0x73, 0x7b, 0xf0, 0xd6, 0x19, - 0x4d, 0x26, 0x7f, 0xad, 0x5c, 0xeb, 0x7e, 0xe5, 0x5a, 0x0f, 0x2b, 0xd7, 0xfa, 0x67, 0xe5, 0x5a, - 0x7f, 0x3e, 0xbb, 0x9d, 0x87, 0x67, 0xb7, 0xf3, 0xf8, 0xec, 0x76, 0x7e, 0xfd, 0xbc, 0xb5, 0x8f, - 0xb5, 0xb7, 0xe4, 0xae, 0x7a, 0x4d, 0xcc, 0x4e, 0x92, 0x9e, 0x79, 0x25, 0x8e, 0xfe, 0x0d, 0x00, - 0x00, 0xff, 0xff, 0x7b, 0x69, 0x42, 0xa7, 0xb6, 0x04, 0x00, 0x00, + // 736 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0xcd, 0x92, 0xdb, 0x34, + 0x1c, 0x8f, 0x89, 0x9b, 0x0f, 0x85, 0x66, 0x5d, 0x91, 0xdd, 0xd1, 0x2e, 0xc5, 0x35, 0x1d, 0x66, + 0xc7, 0x30, 0x60, 0x4f, 0xb7, 0x17, 0x6e, 0x4c, 0xd3, 0x25, 0x43, 0x3b, 0x30, 0x2c, 0xde, 0xe5, + 0xc2, 0x45, 0x23, 0xcb, 0xda, 0x44, 0xb3, 0xb6, 0x64, 0x2c, 0x25, 0x34, 0x3c, 0x05, 0x8f, 0xc1, + 0xa3, 0xf4, 0xd8, 0x23, 0xc3, 0xa1, 0xc3, 0x64, 0x9f, 0x81, 0x3b, 0x23, 0xd9, 0x5e, 0x9c, 0x69, + 0x2f, 0x91, 0xff, 0xfa, 0x7d, 0xfc, 0x25, 0xe5, 0x27, 0x81, 0x87, 0x39, 0xd9, 0x10, 0xc1, 0x74, + 0x6c, 0xc6, 0x58, 0x95, 0x8c, 0xda, 0x9f, 0xa8, 0xac, 0xa4, 0x96, 0xf0, 0x41, 0x83, 0x46, 0x66, + 0x8c, 0x0c, 0x70, 0x32, 0x5b, 0xca, 0xa5, 0xb4, 0x68, 0x6c, 0xbe, 0x6a, 0xe2, 0xc9, 0xe9, 0xbb, + 0x36, 0xa4, 0xe4, 0x98, 0xca, 0x3c, 0x67, 0x54, 0x73, 0x29, 0x1a, 0x9e, 0x4f, 0xa5, 0x2a, 0xa4, + 0x8a, 0x53, 0xa2, 0x58, 0xbc, 0x79, 0x92, 0x32, 0x4d, 0x9e, 0xc4, 0x54, 0xf2, 0x06, 0x7f, 0xfc, + 0xef, 0x10, 0xb8, 0x97, 0x25, 0xa3, 0x70, 0x06, 0xee, 0x71, 0x91, 0xb1, 0x57, 0xc8, 0x09, 0x9c, + 0x70, 0x9c, 0xd4, 0x05, 0x84, 0xc0, 0x15, 0xa4, 0x60, 0xe8, 0x03, 0x3b, 0x69, 0xbf, 0x21, 0x02, + 0x43, 0x26, 0x48, 0x9a, 0xb3, 0x0c, 0xb9, 0x81, 0x13, 0x8e, 0x92, 0xb6, 0x84, 0x4f, 0xc1, 0x61, + 0xc5, 0x72, 0x4e, 0x52, 0x9e, 0x73, 0xbd, 0xc5, 0x7a, 0x55, 0x31, 0xb5, 0x92, 0x79, 0x86, 0xee, + 0x05, 0x4e, 0x78, 0x3f, 0x99, 0x75, 0xc0, 0xab, 0x16, 0x83, 0x5f, 0x03, 0x94, 0x11, 0x4d, 0x70, + 0x57, 0xd9, 0xfa, 0x0f, 0xac, 0xff, 0x91, 0xc1, 0x93, 0xff, 0xe1, 0x6f, 0x9b, 0x76, 0xdf, 0x81, + 0x4f, 0xd3, 0x5c, 0xd2, 0x1b, 0x9c, 0x71, 0xa5, 0x89, 0xa0, 0x0c, 0x5f, 0xcb, 0x0a, 0x5f, 0x73, + 0x41, 0x72, 0xfe, 0x3b, 0xcb, 0xb0, 0x91, 0xa1, 0xa1, 0x6d, 0xfd, 0x89, 0x25, 0x9e, 0x37, 0xbc, + 0x85, 0xac, 0x16, 0x2d, 0xeb, 0x9c, 0x68, 0x02, 0xbf, 0x01, 0x0f, 0x2d, 0x41, 0x61, 0x2e, 0x5a, + 0x03, 0x62, 0x4e, 0x11, 0x97, 0x95, 0x94, 0xd7, 0x68, 0x64, 0x4d, 0x8e, 0x6b, 0xce, 0x0b, 0xb1, + 0xe8, 0x30, 0x2e, 0x0c, 0x01, 0x7e, 0x09, 0x20, 0xd9, 0xb0, 0x8a, 0x2c, 0x19, 0xae, 0x97, 0xa4, + 0x79, 0xc1, 0xd0, 0x38, 0x70, 0xc2, 0x7e, 0xe2, 0x35, 0xc8, 0xdc, 0x00, 0x57, 0xbc, 0x60, 0xf0, + 0x19, 0xf0, 0x49, 0x9e, 0xcb, 0xdf, 0x58, 0xd6, 0xb0, 0x73, 0xb2, 0xb4, 0x6b, 0xff, 0x55, 0x2a, + 0xac, 0xb6, 0x82, 0x22, 0x60, 0x95, 0xc7, 0x0d, 0xcb, 0x2a, 0xbf, 0x27, 0xcb, 0x85, 0xac, 0x7e, + 0x92, 0xea, 0x72, 0x2b, 0xa8, 0x69, 0xd8, 0x4a, 0x95, 0xc6, 0xeb, 0x32, 0x23, 0x9a, 0x65, 0x68, + 0x12, 0x38, 0xa1, 0x9b, 0x78, 0x69, 0xcd, 0x57, 0xfa, 0xe7, 0x7a, 0x1e, 0xfe, 0x00, 0x60, 0xc1, + 0x05, 0x56, 0x9a, 0xdc, 0x30, 0xb3, 0xa5, 0x0d, 0xcf, 0x58, 0x85, 0x3e, 0x0c, 0x9c, 0x70, 0x72, + 0x76, 0x1c, 0xd5, 0x11, 0x89, 0x4c, 0x44, 0xa2, 0x26, 0x22, 0xd1, 0x73, 0xc9, 0xc5, 0xdc, 0x7d, + 0xfd, 0xf6, 0x51, 0x2f, 0xf1, 0x0a, 0x2e, 0x2e, 0x8d, 0xf2, 0xa2, 0x11, 0xc2, 0x1f, 0xc1, 0x41, + 0x6b, 0xa2, 0xb0, 0xde, 0x96, 0x4c, 0xa1, 0x69, 0xe0, 0x84, 0xd3, 0xb3, 0xd3, 0xe8, 0x9d, 0xfc, + 0x46, 0x26, 0x5d, 0x51, 0x2b, 0x55, 0x57, 0x86, 0x9d, 0x4c, 0xcb, 0xbd, 0xda, 0x44, 0x8a, 0x17, + 0xa5, 0xac, 0xb4, 0x42, 0x07, 0x41, 0x3f, 0x1c, 0x27, 0x6d, 0x09, 0x5f, 0x80, 0x83, 0xfd, 0x5c, + 0x2b, 0xe4, 0x05, 0xfd, 0x70, 0x72, 0x16, 0xbc, 0xa7, 0xd5, 0xb3, 0x92, 0x3f, 0xbf, 0x23, 0x26, + 0x53, 0xd2, 0x2d, 0x15, 0x0c, 0xc0, 0x84, 0x4a, 0xa1, 0x2b, 0x9e, 0xae, 0xb5, 0xac, 0xd0, 0x03, + 0xdb, 0xa8, 0x3b, 0x05, 0x09, 0x38, 0xea, 0x94, 0xb8, 0x64, 0x15, 0x65, 0x42, 0x93, 0x25, 0x43, + 0xd0, 0xe4, 0x7f, 0xfe, 0xc5, 0xdf, 0x6f, 0x1f, 0x9d, 0x2e, 0xb9, 0x5e, 0xad, 0xd3, 0x88, 0xca, + 0x22, 0x6e, 0xee, 0x56, 0x3d, 0x7c, 0xa5, 0xb2, 0x9b, 0xd8, 0x1e, 0x46, 0x74, 0xce, 0x68, 0x72, + 0xd8, 0x71, 0xba, 0xb8, 0x33, 0x82, 0x47, 0x60, 0xa0, 0x56, 0xa4, 0x62, 0x0a, 0x7d, 0x64, 0xff, + 0xab, 0xa6, 0x82, 0x27, 0x60, 0xc4, 0x33, 0x26, 0x34, 0xd7, 0x5b, 0x34, 0xb3, 0x97, 0xed, 0xae, + 0x86, 0x1f, 0x83, 0xf1, 0x5a, 0xb1, 0x0a, 0x9b, 0x3d, 0xa2, 0x43, 0x7b, 0x25, 0x46, 0x66, 0xc2, + 0x9c, 0xec, 0xe3, 0xcf, 0xc1, 0x74, 0xff, 0x70, 0xe1, 0x04, 0x0c, 0xb3, 0xad, 0x20, 0x05, 0xa7, + 0x5e, 0x0f, 0x02, 0x30, 0x50, 0x9a, 0x68, 0x4e, 0x3d, 0xe7, 0xa5, 0x3b, 0xea, 0x7b, 0xee, 0x4b, + 0x77, 0x74, 0xdf, 0x9b, 0xce, 0xe7, 0x7f, 0xee, 0x7c, 0xe7, 0xf5, 0xce, 0x77, 0xde, 0xec, 0x7c, + 0xe7, 0x9f, 0x9d, 0xef, 0xfc, 0x71, 0xeb, 0xf7, 0xde, 0xdc, 0xfa, 0xbd, 0xbf, 0x6e, 0xfd, 0xde, + 0x2f, 0x9f, 0x75, 0x36, 0xb9, 0xf7, 0xd0, 0xbc, 0xaa, 0x9f, 0x1a, 0xbb, 0xcd, 0x74, 0x60, 0x9f, + 0x90, 0xa7, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x49, 0xef, 0x2b, 0xaf, 0xd3, 0x04, 0x00, 0x00, } func (this *Spec) Equal(that interface{}) bool { @@ -371,6 +380,9 @@ func (this *Spec) Equal(that interface{}) bool { if this.Identity != that1.Identity { return false } + if this.UserSpec != that1.UserSpec { + return false + } return true } func (m *Spec) Marshal() (dAtA []byte, err error) { @@ -393,6 +405,18 @@ func (m *Spec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.UserSpec { + i-- + if m.UserSpec { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa8 + } if len(m.Identity) > 0 { i -= len(m.Identity) copy(dAtA[i:], m.Identity) @@ -624,6 +648,9 @@ func (m *Spec) Size() (n int) { if l > 0 { n += 2 + l + sovSpec(uint64(l)) } + if m.UserSpec { + n += 3 + } return n } @@ -1117,6 +1144,26 @@ func (m *Spec) Unmarshal(dAtA []byte) error { } m.Identity = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 21: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UserSpec", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.UserSpec = bool(v != 0) default: iNdEx = preIndex skippy, err := skipSpec(dAtA[iNdEx:]) diff --git a/x/spec/types/spec_add_proposal.pb.go b/x/spec/types/spec_add_proposal.pb.go deleted file mode 100644 index 58ef6a2188..0000000000 --- a/x/spec/types/spec_add_proposal.pb.go +++ /dev/null @@ -1,449 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: lavanet/lava/spec/spec_add_proposal.proto - -package types - -import ( - fmt "fmt" - _ "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 SpecAddProposal struct { - Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Specs []Spec `protobuf:"bytes,3,rep,name=specs,proto3" json:"specs"` -} - -func (m *SpecAddProposal) Reset() { *m = SpecAddProposal{} } -func (*SpecAddProposal) ProtoMessage() {} -func (*SpecAddProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_90ccba27a5c90c8a, []int{0} -} -func (m *SpecAddProposal) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *SpecAddProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_SpecAddProposal.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 *SpecAddProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_SpecAddProposal.Merge(m, src) -} -func (m *SpecAddProposal) XXX_Size() int { - return m.Size() -} -func (m *SpecAddProposal) XXX_DiscardUnknown() { - xxx_messageInfo_SpecAddProposal.DiscardUnknown(m) -} - -var xxx_messageInfo_SpecAddProposal proto.InternalMessageInfo - -func init() { - proto.RegisterType((*SpecAddProposal)(nil), "lavanet.lava.spec.SpecAddProposal") -} - -func init() { - proto.RegisterFile("lavanet/lava/spec/spec_add_proposal.proto", fileDescriptor_90ccba27a5c90c8a) -} - -var fileDescriptor_90ccba27a5c90c8a = []byte{ - // 245 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xcc, 0x49, 0x2c, 0x4b, - 0xcc, 0x4b, 0x2d, 0xd1, 0x07, 0xd1, 0xfa, 0xc5, 0x05, 0xa9, 0xc9, 0x60, 0x22, 0x3e, 0x31, 0x25, - 0x25, 0xbe, 0xa0, 0x28, 0xbf, 0x20, 0xbf, 0x38, 0x31, 0x47, 0xaf, 0xa0, 0x28, 0xbf, 0x24, 0x5f, - 0x48, 0x10, 0xaa, 0x54, 0x0f, 0x44, 0xeb, 0x81, 0x54, 0x49, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, - 0x65, 0xf5, 0x41, 0x2c, 0x88, 0x42, 0x29, 0x19, 0xec, 0x66, 0x42, 0x64, 0x95, 0x3a, 0x18, 0xb9, - 0xf8, 0x83, 0x0b, 0x52, 0x93, 0x1d, 0x53, 0x52, 0x02, 0xa0, 0x16, 0x08, 0x89, 0x70, 0xb1, 0x96, - 0x64, 0x96, 0xe4, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x38, 0x42, 0x0a, 0x5c, - 0xdc, 0x29, 0xa9, 0xc5, 0xc9, 0x45, 0x99, 0x05, 0x25, 0x99, 0xf9, 0x79, 0x12, 0x4c, 0x60, 0x39, - 0x64, 0x21, 0x21, 0x63, 0x2e, 0x56, 0x90, 0xc9, 0xc5, 0x12, 0xcc, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, - 0xe2, 0x7a, 0x18, 0x4e, 0xd4, 0x03, 0x59, 0xe5, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x44, - 0xad, 0x15, 0x47, 0xc7, 0x02, 0x79, 0x86, 0x19, 0x0b, 0xe4, 0x19, 0x9c, 0x9c, 0x56, 0x3c, 0x92, - 0x63, 0x3c, 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, 0x95, 0xf4, 0xcc, 0x92, - 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x14, 0x1f, 0x55, 0x40, 0xfc, 0x54, 0x52, 0x59, - 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0xf6, 0x95, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xab, 0xcf, 0x87, - 0x10, 0x49, 0x01, 0x00, 0x00, -} - -func (this *SpecAddProposal) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*SpecAddProposal) - if !ok { - that2, ok := that.(SpecAddProposal) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if this.Title != that1.Title { - return false - } - if this.Description != that1.Description { - return false - } - if len(this.Specs) != len(that1.Specs) { - return false - } - for i := range this.Specs { - if !this.Specs[i].Equal(&that1.Specs[i]) { - return false - } - } - return true -} -func (m *SpecAddProposal) 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 *SpecAddProposal) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *SpecAddProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Specs) > 0 { - for iNdEx := len(m.Specs) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Specs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSpecAddProposal(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if len(m.Description) > 0 { - i -= len(m.Description) - copy(dAtA[i:], m.Description) - i = encodeVarintSpecAddProposal(dAtA, i, uint64(len(m.Description))) - i-- - dAtA[i] = 0x12 - } - if len(m.Title) > 0 { - i -= len(m.Title) - copy(dAtA[i:], m.Title) - i = encodeVarintSpecAddProposal(dAtA, i, uint64(len(m.Title))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintSpecAddProposal(dAtA []byte, offset int, v uint64) int { - offset -= sovSpecAddProposal(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *SpecAddProposal) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Title) - if l > 0 { - n += 1 + l + sovSpecAddProposal(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovSpecAddProposal(uint64(l)) - } - if len(m.Specs) > 0 { - for _, e := range m.Specs { - l = e.Size() - n += 1 + l + sovSpecAddProposal(uint64(l)) - } - } - return n -} - -func sovSpecAddProposal(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozSpecAddProposal(x uint64) (n int) { - return sovSpecAddProposal(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *SpecAddProposal) 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 ErrIntOverflowSpecAddProposal - } - 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: SpecAddProposal: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: SpecAddProposal: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSpecAddProposal - } - 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 ErrInvalidLengthSpecAddProposal - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSpecAddProposal - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Title = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSpecAddProposal - } - 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 ErrInvalidLengthSpecAddProposal - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSpecAddProposal - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Description = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Specs", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSpecAddProposal - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSpecAddProposal - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSpecAddProposal - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Specs = append(m.Specs, Spec{}) - if err := m.Specs[len(m.Specs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSpecAddProposal(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSpecAddProposal - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipSpecAddProposal(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, ErrIntOverflowSpecAddProposal - } - 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, ErrIntOverflowSpecAddProposal - } - 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, ErrIntOverflowSpecAddProposal - } - 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, ErrInvalidLengthSpecAddProposal - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupSpecAddProposal - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthSpecAddProposal - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthSpecAddProposal = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowSpecAddProposal = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupSpecAddProposal = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/spec/types/tx.pb.go b/x/spec/types/tx.pb.go index c3c53b4dce..14705a0b50 100644 --- a/x/spec/types/tx.pb.go +++ b/x/spec/types/tx.pb.go @@ -6,10 +6,15 @@ package types import ( context "context" fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -23,18 +28,118 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +type MsgAddSpecs struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + Specs []Spec `protobuf:"bytes,2,rep,name=specs,proto3" json:"specs"` +} + +func (m *MsgAddSpecs) Reset() { *m = MsgAddSpecs{} } +func (m *MsgAddSpecs) String() string { return proto.CompactTextString(m) } +func (*MsgAddSpecs) ProtoMessage() {} +func (*MsgAddSpecs) Descriptor() ([]byte, []int) { + return fileDescriptor_c6aee532b425dbb5, []int{0} +} +func (m *MsgAddSpecs) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAddSpecs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAddSpecs.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 *MsgAddSpecs) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddSpecs.Merge(m, src) +} +func (m *MsgAddSpecs) XXX_Size() int { + return m.Size() +} +func (m *MsgAddSpecs) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddSpecs.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAddSpecs proto.InternalMessageInfo + +func (m *MsgAddSpecs) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgAddSpecs) GetSpecs() []Spec { + if m != nil { + return m.Specs + } + return nil +} + +type MsgAddSpecsResponse struct { +} + +func (m *MsgAddSpecsResponse) Reset() { *m = MsgAddSpecsResponse{} } +func (m *MsgAddSpecsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAddSpecsResponse) ProtoMessage() {} +func (*MsgAddSpecsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c6aee532b425dbb5, []int{1} +} +func (m *MsgAddSpecsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAddSpecsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAddSpecsResponse.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 *MsgAddSpecsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddSpecsResponse.Merge(m, src) +} +func (m *MsgAddSpecsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgAddSpecsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddSpecsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAddSpecsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgAddSpecs)(nil), "lavanet.lava.spec.MsgAddSpecs") + proto.RegisterType((*MsgAddSpecsResponse)(nil), "lavanet.lava.spec.MsgAddSpecsResponse") +} + func init() { proto.RegisterFile("lavanet/lava/spec/tx.proto", fileDescriptor_c6aee532b425dbb5) } var fileDescriptor_c6aee532b425dbb5 = []byte{ - // 121 bytes of a gzipped FileDescriptorProto + // 240 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x49, 0x2c, 0x4b, 0xcc, 0x4b, 0x2d, 0xd1, 0x07, 0xd1, 0xfa, 0xc5, 0x05, 0xa9, 0xc9, 0xfa, 0x25, 0x15, 0x7a, 0x05, - 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x82, 0x50, 0x39, 0x3d, 0x10, 0xad, 0x07, 0x92, 0x33, 0x62, 0xe5, - 0x62, 0xf6, 0x2d, 0x4e, 0x77, 0xb2, 0x3b, 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, 0x95, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x14, 0xa3, 0x2b, - 0xa0, 0x86, 0x57, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x2d, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, - 0xff, 0x5c, 0x25, 0x52, 0x32, 0x7e, 0x00, 0x00, 0x00, + 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x82, 0x50, 0x39, 0x3d, 0x10, 0xad, 0x07, 0x92, 0x93, 0x12, 0x49, + 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xea, 0x83, 0x58, 0x10, 0x85, 0x52, 0x32, 0x98, 0x86, 0x80, 0x08, + 0x88, 0xac, 0x52, 0x0c, 0x17, 0xb7, 0x6f, 0x71, 0xba, 0x63, 0x4a, 0x4a, 0x70, 0x41, 0x6a, 0x72, + 0xb1, 0x90, 0x04, 0x17, 0x7b, 0x72, 0x51, 0x6a, 0x62, 0x49, 0x7e, 0x91, 0x04, 0xa3, 0x02, 0xa3, + 0x06, 0x67, 0x10, 0x8c, 0x2b, 0x64, 0xcc, 0xc5, 0x0a, 0xd2, 0x56, 0x2c, 0xc1, 0xa4, 0xc0, 0xac, + 0xc1, 0x6d, 0x24, 0xae, 0x87, 0x61, 0xbf, 0x1e, 0xc8, 0x08, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, + 0x82, 0x20, 0x6a, 0x95, 0x44, 0xb9, 0x84, 0x91, 0x4c, 0x0f, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, + 0x4e, 0x35, 0x8a, 0xe4, 0x62, 0xf6, 0x2d, 0x4e, 0x17, 0x0a, 0xe2, 0xe2, 0x80, 0x5b, 0x2c, 0x87, + 0xc5, 0x3c, 0x24, 0xad, 0x52, 0x6a, 0xf8, 0xe5, 0x61, 0x46, 0x3b, 0xd9, 0x9d, 0x78, 0x24, 0xc7, + 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, + 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x4a, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, + 0x7e, 0xae, 0x3e, 0x4a, 0x90, 0x54, 0x40, 0x43, 0xb6, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, + 0x2c, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56, 0xa5, 0x50, 0x44, 0x7b, 0x01, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -49,6 +154,7 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type MsgClient interface { + AddSpecs(ctx context.Context, in *MsgAddSpecs, opts ...grpc.CallOption) (*MsgAddSpecsResponse, error) } type msgClient struct { @@ -59,22 +165,422 @@ func NewMsgClient(cc grpc1.ClientConn) MsgClient { return &msgClient{cc} } +func (c *msgClient) AddSpecs(ctx context.Context, in *MsgAddSpecs, opts ...grpc.CallOption) (*MsgAddSpecsResponse, error) { + out := new(MsgAddSpecsResponse) + err := c.cc.Invoke(ctx, "/lavanet.lava.spec.Msg/AddSpecs", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { + AddSpecs(context.Context, *MsgAddSpecs) (*MsgAddSpecsResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. type UnimplementedMsgServer struct { } +func (*UnimplementedMsgServer) AddSpecs(ctx context.Context, req *MsgAddSpecs) (*MsgAddSpecsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddSpecs not implemented") +} + func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) } +func _Msg_AddSpecs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAddSpecs) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).AddSpecs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/lavanet.lava.spec.Msg/AddSpecs", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).AddSpecs(ctx, req.(*MsgAddSpecs)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "lavanet.lava.spec.Msg", HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{}, - Streams: []grpc.StreamDesc{}, - Metadata: "lavanet/lava/spec/tx.proto", + Methods: []grpc.MethodDesc{ + { + MethodName: "AddSpecs", + Handler: _Msg_AddSpecs_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "lavanet/lava/spec/tx.proto", +} + +func (m *MsgAddSpecs) 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 *MsgAddSpecs) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAddSpecs) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Specs) > 0 { + for iNdEx := len(m.Specs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Specs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + 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 *MsgAddSpecsResponse) 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 *MsgAddSpecsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAddSpecsResponse) 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 + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgAddSpecs) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Specs) > 0 { + for _, e := range m.Specs { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgAddSpecsResponse) 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 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgAddSpecs) 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: MsgAddSpecs: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAddSpecs: 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 Specs", 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 + } + m.Specs = append(m.Specs, Spec{}) + if err := m.Specs[len(m.Specs)-1].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 *MsgAddSpecsResponse) 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: MsgAddSpecsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAddSpecsResponse: 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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/subscription/keeper/cu_tracker.go b/x/subscription/keeper/cu_tracker.go index 83d5b6db60..014246720c 100644 --- a/x/subscription/keeper/cu_tracker.go +++ b/x/subscription/keeper/cu_tracker.go @@ -30,9 +30,13 @@ func (k Keeper) GetTrackedCu(ctx sdk.Context, sub string, provider string, chain // AddTrackedCu adds CU to the CU counters in relevant trackedCu entry // Also, it counts the IPRPC CU if the subscription is IPRPC eligible -func (k Keeper) AddTrackedCu(ctx sdk.Context, sub string, provider string, chainID string, cuToAdd uint64, block uint64) error { +func (k Keeper) AddTrackedCu(ctx sdk.Context, sub string, provider string, chainID string, cuToAdd uint64, block uint64, userSpec bool) error { k.rewardsKeeper.AggregateCU(ctx, sub, provider, chainID, cuToAdd) + if userSpec { + return nil + } + cu, found, key := k.GetTrackedCu(ctx, sub, provider, chainID, block) // Note that the trackedCu entry usually has one version since we used