From 1ad1f4414719c9137d1c9e04530e715f92ba4fe7 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Mon, 17 Jun 2024 12:39:24 +0300 Subject: [PATCH 01/14] add tx add spec --- app/app.go | 1 + proto/lavanet/lava/spec/spec.proto | 1 + proto/lavanet/lava/spec/tx.proto | 13 +- testutil/keeper/dualstaking.go | 2 +- testutil/keeper/keepers_init.go | 2 +- testutil/keeper/plan.go | 2 +- testutil/keeper/spec.go | 1 + x/spec/keeper/keeper.go | 5 + x/spec/keeper/msg_server_add_specs.go | 15 + x/spec/keeper/spec.go | 82 ++++ x/spec/module.go | 2 +- x/spec/proposal_handler.go | 71 +--- x/spec/types/message_add_specs.go | 56 +++ x/spec/types/spec.pb.go | 139 ++++--- x/spec/types/tx.pb.go | 526 +++++++++++++++++++++++++- 15 files changed, 787 insertions(+), 131 deletions(-) create mode 100644 x/spec/keeper/msg_server_add_specs.go create mode 100644 x/spec/types/message_add_specs.go diff --git a/app/app.go b/app/app.go index 0ab1202df8..6a07eeafca 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) 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/tx.proto b/proto/lavanet/lava/spec/tx.proto index 9bc577b5f3..11a4c60c1a 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 = 3 [(gogoproto.nullable) = false]; +} + +message MsgAddSpecsResponse { +} \ No newline at end of file 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..2cd17aa786 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) 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..f24a081126 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()) 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/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/spec.go b/x/spec/keeper/spec.go index 905d9d6ff2..45b41a2fb8 100644 --- a/x/spec/keeper/spec.go +++ b/x/spec/keeper/spec.go @@ -359,3 +359,85 @@ 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) + + if creator != k.authority { + 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) + } + } else { + if sdk.SliceContains(spec.Contributor, creator) { + spec.Contributor = append(spec.Contributor, creator) + } + } + } + + 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/module.go b/x/spec/module.go index 5244792d52..63291b8d9e 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) diff --git a/x/spec/proposal_handler.go b/x/spec/proposal_handler.go index 4f63b3fd0d..0ca17fef48 100644 --- a/x/spec/proposal_handler.go +++ b/x/spec/proposal_handler.go @@ -3,7 +3,6 @@ package spec import ( "fmt" "log" - "strings" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" @@ -78,7 +77,7 @@ 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) + return k.HandleSpecs(ctx, c.Specs, k.GetAuthority()) default: log.Println("unrecognized spec proposal content") @@ -86,71 +85,3 @@ func NewSpecProposalsHandler(k keeper.Keeper) v1beta1.Handler { } } } - -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/message_add_specs.go b/x/spec/types/message_add_specs.go new file mode 100644 index 0000000000..13d62d4fa7 --- /dev/null +++ b/x/spec/types/message_add_specs.go @@ -0,0 +1,56 @@ +package types + +import ( + "math" + + 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.ValidateSpec(math.MaxUint64) + if err != nil { + return err + } + } + return nil +} 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/tx.pb.go b/x/spec/types/tx.pb.go index c3c53b4dce..8c7caa4e89 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,3,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, 0xac, 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, 0x5f, 0xa1, 0xd3, 0x88, 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] = 0x1a + } + } + 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 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 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") +) From 15792415ddc231ffc262f32135e8a0f865e5fd69 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Mon, 17 Jun 2024 14:59:37 +0300 Subject: [PATCH 02/14] depredace the old proposal --- app/app.go | 2 - app/upgrades/upgrade_0_35_0.go | 2 +- .../lavanet/lava/spec/spec_add_proposal.proto | 18 - testutil/keeper/keepers_init.go | 9 +- testutil/keeper/spec.go | 2 +- x/spec/client/cli/tx.go | 12 +- x/spec/client/utils/utils.go | 14 +- x/spec/keeper/spec_test.go | 4 +- x/spec/proposal_handler.go | 16 - x/spec/types/addproposal.go | 73 --- x/spec/types/codec.go | 1 - x/spec/types/message_add_specs.go | 4 +- x/spec/types/proposal.go | 2 +- x/spec/types/spec_add_proposal.pb.go | 449 ------------------ 14 files changed, 20 insertions(+), 588 deletions(-) delete mode 100644 proto/lavanet/lava/spec/spec_add_proposal.proto delete mode 100644 x/spec/types/addproposal.go delete mode 100644 x/spec/types/spec_add_proposal.pb.go diff --git a/app/app.go b/app/app.go index 6a07eeafca..cd9cca6d1b 100644 --- a/app/app.go +++ b/app/app.go @@ -609,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_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/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 2cd17aa786..9e728630d2 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -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/spec.go b/testutil/keeper/spec.go index f24a081126..6a0ad50b05 100644 --- a/testutil/keeper/spec.go +++ b/testutil/keeper/spec.go @@ -80,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/spec/client/cli/tx.go b/x/spec/client/cli/tx.go index 344cdb44c1..cebc2679cb 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" @@ -89,10 +88,6 @@ $ %s tx gov spec-proposal spec-add <path/to/proposal.json> --from=<key_or_addres from := clientCtx.GetFromAddress() content := &proposal.Proposal - deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit) - if err != nil { - return err - } devTest, err := cmd.Flags().GetBool(devTestFlagName) if err == nil && devTest { @@ -115,14 +110,13 @@ $ %s tx gov spec-proposal spec-add <path/to/proposal.json> --from=<key_or_addres } } - contentAny, err := codectypes.NewAnyWithValue(content) + deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit) if err != nil { return err } - msgExecLegacy := govv1.NewMsgExecLegacyContent(contentAny, authtypes.NewModuleAddress(govtypes.ModuleName).String()) - - submitPropMsg, err := govv1.NewMsgSubmitProposal([]sdk.Msg{msgExecLegacy}, deposit, from.String(), proposal.Proposal.Description, proposal.Proposal.Title, "Add a new spec", isExpedited) + msgAddSpecs := types.NewMsgAddSpecs(authtypes.NewModuleAddress(govtypes.ModuleName).String(), content.Specs) + submitPropMsg, err := govv1.NewMsgSubmitProposal([]sdk.Msg{msgAddSpecs}, deposit, from.String(), proposal.Proposal.Description, proposal.Proposal.Title, "Add a new spec", isExpedited) if err != nil { return err } 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/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/proposal_handler.go b/x/spec/proposal_handler.go index 0ca17fef48..866f9760e0 100644 --- a/x/spec/proposal_handler.go +++ b/x/spec/proposal_handler.go @@ -2,7 +2,6 @@ package spec import ( "fmt" - "log" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" @@ -13,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" ) @@ -71,17 +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 k.HandleSpecs(ctx, c.Specs, k.GetAuthority()) - - default: - log.Println("unrecognized spec proposal content") - return sdkerrors.Wrapf(legacyerrors.ErrUnknownRequest, "unrecognized spec proposal content type: %T", c) - } - } -} 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 index 13d62d4fa7..769aa1ea62 100644 --- a/x/spec/types/message_add_specs.go +++ b/x/spec/types/message_add_specs.go @@ -1,8 +1,6 @@ package types import ( - "math" - sdkerrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -47,7 +45,7 @@ func (msg *MsgAddSpecs) ValidateBasic() error { } for _, v := range msg.Specs { - _, err := v.ValidateSpec(math.MaxUint64) + err := v.ValidateBasic() if err != nil { return err } 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_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") -) From 58829d269c8a229620ba2545a7248b4e55510b37 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Mon, 17 Jun 2024 15:14:13 +0300 Subject: [PATCH 03/14] add tx cli --- x/spec/client/cli/tx.go | 61 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/x/spec/client/cli/tx.go b/x/spec/client/cli/tx.go index cebc2679cb..5d70f8b362 100644 --- a/x/spec/client/cli/tx.go +++ b/x/spec/client/cli/tx.go @@ -17,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" @@ -42,7 +43,7 @@ func GetTxCmd() *cobra.Command { } // this line is used by starport scaffolding # 1 - + cmd.AddCommand(NewAddSpecsTxCmd()) return cmd } @@ -128,3 +129,61 @@ $ %s tx gov spec-proposal spec-add <path/to/proposal.json> --from=<key_or_addres cmd.Flags().Bool(expeditedFlagName, false, "set to true to make the spec proposal expedited") return cmd } + +// NewAddSpecsTxCmd returns a CLI command handler for creating +// a add spec transaction +func NewAddSpecsTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "spec-add [proposal-file,proposal-file,...]", + Args: cobra.ExactArgs(1), + Short: "Submit a spec add", + Long: strings.TrimSpace( + fmt.Sprintf(`send a transaction to add or modify existing user specs. +Example: +$ %s tx spec spec-add <path/to/proposal.json> --from=<key_or_address> +`, + 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 +} From 483cae8ae73e69e48ff973af762ac4189fcf4386 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Mon, 17 Jun 2024 15:15:43 +0300 Subject: [PATCH 04/14] set the user spec bool --- x/spec/keeper/spec.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/spec/keeper/spec.go b/x/spec/keeper/spec.go index 45b41a2fb8..ca8f6fcf93 100644 --- a/x/spec/keeper/spec.go +++ b/x/spec/keeper/spec.go @@ -388,6 +388,7 @@ func (k Keeper) HandleSpecs(ctx sdk.Context, specs []types.Spec, creator string) } } + spec.UserSpec = creator != k.authority spec.BlockLastUpdated = uint64(ctx.BlockHeight()) k.SetSpec(ctx, spec) From 5b718b08d75210530adbba361ddd5dc4c365cbcf Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Mon, 17 Jun 2024 15:32:58 +0300 Subject: [PATCH 05/14] added migrator --- x/spec/keeper/migrations.go | 8 ++++++++ x/spec/module.go | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/x/spec/keeper/migrations.go b/x/spec/keeper/migrations.go index 2f76988f05..97c55c9311 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,10 @@ func (m Migrator) Migrate3to4(ctx sdk.Context) error { return nil } + +func (m Migrator) Migrate4to5(ctx sdk.Context) error { + params := m.keeper.GetParams(ctx) + params.AllowlistedExpeditedMsgs = append(params.AllowlistedExpeditedMsgs, proto.MessageName(&types.MsgAddSpecs{})) + m.keeper.SetParams(ctx, params) + return nil +} diff --git a/x/spec/module.go b/x/spec/module.go index 63291b8d9e..61143299bb 100644 --- a/x/spec/module.go +++ b/x/spec/module.go @@ -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) { From 77796672b10b398a55d53f13a62c2c202f5a6578 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Mon, 17 Jun 2024 15:49:05 +0300 Subject: [PATCH 06/14] added spec restrictions --- x/conflict/keeper/msg_server_detection.go | 9 +++++++++ x/conflict/types/expected_keepers.go | 1 + x/pairing/keeper/msg_server_relay_payment.go | 6 +++--- x/pairing/types/expected_keepers.go | 2 +- x/subscription/keeper/cu_tracker.go | 6 +++++- 5 files changed, 19 insertions(+), 5 deletions(-) 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/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/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/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 From bc9ddd508bfc2731c4f4e46c5728a348f60610de Mon Sep 17 00:00:00 2001 From: Yaroms <yaroms@lavanet.xyz> Date: Tue, 18 Jun 2024 13:05:01 +0300 Subject: [PATCH 07/14] pr changes --- proto/lavanet/lava/spec/tx.proto | 2 +- x/spec/client/cli/tx.go | 6 +++--- x/spec/keeper/migrations.go | 7 +++++-- x/spec/keeper/spec.go | 2 +- x/spec/types/tx.pb.go | 10 +++++----- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/proto/lavanet/lava/spec/tx.proto b/proto/lavanet/lava/spec/tx.proto index 11a4c60c1a..715c17ab4a 100644 --- a/proto/lavanet/lava/spec/tx.proto +++ b/proto/lavanet/lava/spec/tx.proto @@ -17,7 +17,7 @@ service Msg { message MsgAddSpecs { string creator = 1; - repeated Spec specs = 3 [(gogoproto.nullable) = false]; + repeated Spec specs = 2 [(gogoproto.nullable) = false]; } message MsgAddSpecsResponse { diff --git a/x/spec/client/cli/tx.go b/x/spec/client/cli/tx.go index 5d70f8b362..518b69e667 100644 --- a/x/spec/client/cli/tx.go +++ b/x/spec/client/cli/tx.go @@ -43,7 +43,7 @@ func GetTxCmd() *cobra.Command { } // this line is used by starport scaffolding # 1 - cmd.AddCommand(NewAddSpecsTxCmd()) + cmd.AddCommand(CmdTxAddSpecs()) return cmd } @@ -130,9 +130,9 @@ $ %s tx gov spec-proposal spec-add <path/to/proposal.json> --from=<key_or_addres return cmd } -// NewAddSpecsTxCmd returns a CLI command handler for creating +// CmdTxAddSpecs returns a CLI command handler for creating // a add spec transaction -func NewAddSpecsTxCmd() *cobra.Command { +func CmdTxAddSpecs() *cobra.Command { cmd := &cobra.Command{ Use: "spec-add [proposal-file,proposal-file,...]", Args: cobra.ExactArgs(1), diff --git a/x/spec/keeper/migrations.go b/x/spec/keeper/migrations.go index 97c55c9311..4153a6f6e4 100644 --- a/x/spec/keeper/migrations.go +++ b/x/spec/keeper/migrations.go @@ -54,7 +54,10 @@ func (m Migrator) Migrate3to4(ctx sdk.Context) error { func (m Migrator) Migrate4to5(ctx sdk.Context) error { params := m.keeper.GetParams(ctx) - params.AllowlistedExpeditedMsgs = append(params.AllowlistedExpeditedMsgs, proto.MessageName(&types.MsgAddSpecs{})) - m.keeper.SetParams(ctx, params) + 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/spec.go b/x/spec/keeper/spec.go index ca8f6fcf93..89fbc26a82 100644 --- a/x/spec/keeper/spec.go +++ b/x/spec/keeper/spec.go @@ -382,7 +382,7 @@ func (k Keeper) HandleSpecs(ctx sdk.Context, specs []types.Spec, creator string) return utils.LavaFormatWarning("user cannot change spec which he is not a contributor at", nil) } } else { - if sdk.SliceContains(spec.Contributor, creator) { + if !sdk.SliceContains(spec.Contributor, creator) { spec.Contributor = append(spec.Contributor, creator) } } diff --git a/x/spec/types/tx.pb.go b/x/spec/types/tx.pb.go index 8c7caa4e89..14705a0b50 100644 --- a/x/spec/types/tx.pb.go +++ b/x/spec/types/tx.pb.go @@ -30,7 +30,7 @@ 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,3,rep,name=specs,proto3" json:"specs"` + Specs []Spec `protobuf:"bytes,2,rep,name=specs,proto3" json:"specs"` } func (m *MsgAddSpecs) Reset() { *m = MsgAddSpecs{} } @@ -131,7 +131,7 @@ var fileDescriptor_c6aee532b425dbb5 = []byte{ 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, 0xac, 0xc0, 0xac, + 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, @@ -139,7 +139,7 @@ var fileDescriptor_c6aee532b425dbb5 = []byte{ 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, 0x5f, 0xa1, 0xd3, 0x88, 0x7b, 0x01, 0x00, 0x00, + 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. @@ -253,7 +253,7 @@ func (m *MsgAddSpecs) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintTx(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x12 } } if len(m.Creator) > 0 { @@ -395,7 +395,7 @@ func (m *MsgAddSpecs) Unmarshal(dAtA []byte) error { } m.Creator = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Specs", wireType) } From dd85e145c7c89de686f2620e4b21968a6abc5c69 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Thu, 27 Jun 2024 12:53:58 +0300 Subject: [PATCH 08/14] add spec tests --- testutil/common/mock.go | 6 ++- x/spec/keeper/msg_server_add_specs_test.go | 46 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 x/spec/keeper/msg_server_add_specs_test.go 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/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..0b171967fa --- /dev/null +++ b/x/spec/keeper/msg_server_add_specs_test.go @@ -0,0 +1,46 @@ +package keeper_test + +import ( + "testing" + + "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 + + 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) + + // 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) +} From 01c19f6062410e76f4854f68f947544f998ecb40 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Thu, 27 Jun 2024 14:09:42 +0300 Subject: [PATCH 09/14] fix test --- x/pairing/keeper/msg_server_stake_provider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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()) From 2a428a2350ae490600dbc0ebac34717a0d127482 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Tue, 2 Jul 2024 14:48:29 +0300 Subject: [PATCH 10/14] add fixed fee for contributors --- x/spec/keeper/spec.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/x/spec/keeper/spec.go b/x/spec/keeper/spec.go index 89fbc26a82..ba7e7b408e 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" ) +var USER_SPEC_CONTRIBUTION = sdk.NewDecWithPrec(1, 10) + // 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)) @@ -374,21 +376,22 @@ func (k Keeper) HandleSpecs(ctx sdk.Context, specs []types.Spec, creator string) for _, spec := range specs { ogSpec, found := k.GetSpec(ctx, spec.Index) - if creator != k.authority { + 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) } - } else { - if !sdk.SliceContains(spec.Contributor, creator) { - spec.Contributor = append(spec.Contributor, creator) - } } + + if !sdk.SliceContains(spec.Contributor, creator) { + spec.Contributor = append(spec.Contributor, creator) + } + spec.ContributorPercentage = &USER_SPEC_CONTRIBUTION } - spec.UserSpec = creator != k.authority spec.BlockLastUpdated = uint64(ctx.BlockHeight()) k.SetSpec(ctx, spec) From 09c2d5f86713400ed6d61a49a684f07ecd5d039b Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Tue, 2 Jul 2024 14:59:55 +0300 Subject: [PATCH 11/14] fix --- x/spec/keeper/msg_server_add_specs_test.go | 12 ++++++++++++ x/spec/keeper/spec.go | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/x/spec/keeper/msg_server_add_specs_test.go b/x/spec/keeper/msg_server_add_specs_test.go index 0b171967fa..39e082ed8a 100644 --- a/x/spec/keeper/msg_server_add_specs_test.go +++ b/x/spec/keeper/msg_server_add_specs_test.go @@ -3,6 +3,8 @@ 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" @@ -13,6 +15,8 @@ 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) @@ -34,6 +38,10 @@ func TestSpecAddPermissions(t *testing.T) { _, 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) @@ -43,4 +51,8 @@ func TestSpecAddPermissions(t *testing.T) { 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 ba7e7b408e..164fba3f2f 100644 --- a/x/spec/keeper/spec.go +++ b/x/spec/keeper/spec.go @@ -15,7 +15,7 @@ import ( "github.com/lavanet/lava/x/spec/types" ) -var USER_SPEC_CONTRIBUTION = sdk.NewDecWithPrec(1, 10) +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) { @@ -389,7 +389,8 @@ func (k Keeper) HandleSpecs(ctx sdk.Context, specs []types.Spec, creator string) if !sdk.SliceContains(spec.Contributor, creator) { spec.Contributor = append(spec.Contributor, creator) } - spec.ContributorPercentage = &USER_SPEC_CONTRIBUTION + contributorPercentage := math.LegacyMustNewDecFromStr(USER_SPEC_CONTRIBUTION) + spec.ContributorPercentage = &contributorPercentage } spec.BlockLastUpdated = uint64(ctx.BlockHeight()) From ad77459ae5455cc585aef00dc77265e17e29e004 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Tue, 2 Jul 2024 15:15:25 +0300 Subject: [PATCH 12/14] add tests --- x/rewards/keeper/iprpc_test.go | 8 ++++- x/rewards/keeper/providers_test.go | 50 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) 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) +} From 0408d11ada58a1fdb8b0b15ce6902f6882d1568c Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Tue, 2 Jul 2024 15:24:46 +0300 Subject: [PATCH 13/14] add conflict test --- .../keeper/msg_server_detection_test.go | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) 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() From b6d7ac679b477d7cfd968bc9e014d5a1582fe562 Mon Sep 17 00:00:00 2001 From: Yarom Swisa <yarom@lavanet.xyz git config --global user.name Yarom> Date: Tue, 2 Jul 2024 16:28:46 +0300 Subject: [PATCH 14/14] add readme --- x/spec/README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) 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.